Next: Pinned Structs, Previous: Field Initializers, Up: Structs [Contents][Index]
In structs, each field is associated with an offset, which is relative to the beginning of the struct. This is the offset used when reading and writing the field from/to the IO space when mapping.
The offset is reset to zero bits at the beginning of the struct type, and it is increased by the size of the fields:
struct { /* Offset: 0#b */ uint<1> f1; /* Offset: 1#b */ sint<7> f2; /* Offset: 1#B */ int f3; /* Offset: 5#B */ Bar f4; /* Offset: 23#B */ }
It is possible to specify an alternative offset for a field using a field label.
Consider for example an entry in an ELF symbol table. Each entry has
a st_info
field which is 64-bits long, that in turn can be
interpreted as two fields st_bind
and st_type
.
The obvious solution is to encode st_info
as a sub-struct, like
this:
struct { elf32_word st_name; struct { uint<60> st_bind; uint<4> st_type; } st_info; }
However, that makes it inconvenient to access the value of
st_info
as an integral value, using the bit-concatenation
operator symbol.st_info.st_bind::symbol.st_info.st_type
. We
can use labels instead:
struct { elf32_word st_name; elf64_word st_info; uint<60> st_bind @ 4#B; uint<4> st_type @ 4#B + 60#b; }
The resulting struct has fields st_info
, st_bind
and
st_type
, with the last two overlapping the first.