Strings and Byte Buffers
How to work with strings, byte arrays, and buffer operations in SBBE IR.
SBBE has no string type. Strings are byte sequences in linear memory, managed entirely by the frontend. This guide shows common patterns for C-style null-terminated strings and length-prefixed strings.
C-style null-terminated strings
A C string is a pointer to a sequence of bytes ending with a zero byte. The frontend stores the string data in linear memory and passes the address around as a ptr.
String length (strlen)
func $strlen(ptr) -> i32 {
var $len i32
entry:
ldi 0
str $len
jmp check
check:
ldl 0 // current ptr position
ld $len
add.s i64 // ptr + len
ldm.u8 // load byte
eqz i32 // is it zero?
jmp.if done
jmp next
next:
ld $len
ldi 1
add.s i32
str $len
jmp check
done:
ld $len
ret
}
Comparing bytes
To compare two memory regions byte by byte:
func $memcmp(ptr, ptr, i32) -> i32 {
var $i i32
entry:
ldi 0
str $i
jmp check
check:
ld $i
ldl 2 // length
ge.u i32 // i >= length?
jmp.if equal
jmp compare
compare:
// Load byte from first buffer
ldl 0
ld $i
add.s i64
ldm.u8
// Load byte from second buffer
ldl 1
ld $i
add.s i64
ldm.u8
// Compare
sub.s i32 // a - b
dup
eqz i32
jmp.if advance
ret // return nonzero difference
advance:
drop // discard the zero difference
ld $i
ldi 1
add.s i32
str $i
jmp check
equal:
ldi 0
ret
}
Length-prefixed strings
Many languages (Pascal, Rust, Go) use a (pointer, length) pair instead of null termination. This is typically represented as a struct:
// StringView layout:
// offset 0: ptr data
// offset 8: i32 length
// Get the length of a string view
func $string_len(ptr) -> i32 {
entry:
ldl 0
ldi 8
add.s i64
ldm i32 // load length field
ret
}
// Get a byte at index i
func $string_at(ptr, i32) -> i32 {
entry:
ldl 0
ldm ptr // load data pointer
ldl 1 // index
add.s i64 // data + index
ldm.u8 // load byte
ret
}
Copying memory (memcpy)
A byte-by-byte copy loop. In practice, backends would recognize this pattern and emit optimized block copy instructions.
func $memcpy(ptr, ptr, i32) {
// params: dst=0, src=1, len=2
var $i i32
entry:
ldi 0
str $i
jmp check
check:
ld $i
ldl 2
ge.u i32
jmp.if done
jmp copy
copy:
// dst[i] = src[i]
ldl 0
ld $i
add.s i64 // dst + i
ldl 1
ld $i
add.s i64 // src + i
ldm.u8 // load byte from src
stm8 // store byte to dst
ld $i
ldi 1
add.s i32
str $i
jmp check
done:
ret
}
Key takeaways
- Strings are just pointers to byte sequences in linear memory
- The frontend decides the string representation (null-terminated, length-prefixed, etc.)
- Byte access uses
ldm.u8/stm8(narrow load/store) - The
ptrtype is used for addresses; integer arithmetic computes offsets