Structures
Structs currently is an something like type-definition with proper type checking and field accessors (auto-shift)
Defining an structure type
struct name
field type
...
end
For example defining an person struct
struct Person
age int
name *char[]
end
Accessing an structure field
var stepan Person // initialize variable of type Person
stepan.age // will push an pointer to an `age` field so you can write / read from it
Forward reference and self-reference
Forward reference of structures as children field is allowed:
struct X
id int
child X
end // 16 bytes
// This will define X as (8 byte int + 8 byte X (int))
Alignment on CPUs and packed layout
By default, all structures being aligned in memory according to max alignment of its own fields, e.g if biggest field type is int (8 bytes) then alignment for whole structure must be same amount of bytes
This can be overridden by specifying packed attribute for structure, which means do not apply any alignment, place all fields as-is linearly in memory
struct bad_layout
a char // 1 byte
b int // 8 byte
c char // 1 byte
end // Unpacked, 24 bytes
struct packed packed_layout
a char // 1 byte
b int // 8 byte
c char // 1 byte
end // Packed, 10 bytes
Packed (tight memory layout)
|-------------|
|a| b |c|| => 10 bytes
|-------------|
Aligned (thin memory layout)
|-------------------------------------------|
|a|...padding...| b |...padding...|c| => 24 bytes
|-------------------------------------------|
Padding is from both sides to properly align *int* (8 bytes) field access on CPU
Reordering
Reordering is a process when for performance reasons fields of structure being re-ordered to solve alignment issues (redundant padding on structure memory layout)
By default, structures does not apply reordering, this behavior can be overridden by specifying reorder attribute for structure.
struct bad_layout
a char // 1 byte
b int // 8 byte
c char // 1 byte
end // Unpacked, 24 bytes
struct reorder reordered_layout
a char // 1 byte
b int // 8 byte
c char // 1 byte
end // Unpacked, reordered 16 bytes
// Order was transformed into [b, a, c] (int, char, char) re-using padding from int to char
offset_of
offset_of pushes byte offset for specified field for given structure (concrete ones)
offset_of {STRUCTURE_TYPE} {FIELD_NAME}
It takes into account any alignment / reordering that is possible, and offset will be always same, as those whose will be used inside low-level machine code / ABI calls
struct Foo
// No special alignment, simple struct
a int
b int
end
offset_of Foo a // 0
offset_of Foo b // 8
align_of
align_of pushes alignment for specified type
align_of {TYPE}
It takes into account any alignment / reordering that is possible, and offset will be always same, as those whose will be used inside low-level machine code / ABI calls
struct Foo
// No special alignment, simple struct
a int
b int
end
align_of Foo // 8 (max is int, 8 bytes)
align_of int // 8
align_of char // 1
align_of int[32] // 8, alignment of int
Generic structure types
// Define generic struct with type param T
struct Generic{T}
field_a T
field_b T
field_c int
end
var x Generic{T = int} // Variable with concrete type