123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779 |
- struct Scope;
- enum BasicKind {
- Basic_Invalid,
- Basic_bool,
- Basic_i8,
- Basic_i16,
- Basic_i32,
- Basic_i64,
- Basic_i128,
- Basic_u8,
- Basic_u16,
- Basic_u32,
- Basic_u64,
- Basic_u128,
- Basic_f32,
- Basic_f64,
- Basic_int,
- Basic_uint,
- Basic_rawptr,
- Basic_string,
- Basic_UntypedBool,
- Basic_UntypedInteger,
- Basic_UntypedFloat,
- Basic_UntypedPointer,
- Basic_UntypedString,
- Basic_UntypedRune,
- Basic_Count,
- Basic_byte = Basic_u8,
- Basic_rune = Basic_i32,
- };
- enum BasicFlag : u32 {
- BasicFlag_Boolean = GB_BIT(0),
- BasicFlag_Integer = GB_BIT(1),
- BasicFlag_Unsigned = GB_BIT(2),
- BasicFlag_Float = GB_BIT(3),
- BasicFlag_Pointer = GB_BIT(4),
- BasicFlag_String = GB_BIT(5),
- BasicFlag_Rune = GB_BIT(6),
- BasicFlag_Untyped = GB_BIT(7),
- BasicFlag_Numeric = BasicFlag_Integer | BasicFlag_Float,
- BasicFlag_Ordered = BasicFlag_Numeric | BasicFlag_String | BasicFlag_Pointer,
- BasicFlag_ConstantType = BasicFlag_Boolean | BasicFlag_Numeric | BasicFlag_Pointer | BasicFlag_String | BasicFlag_Rune,
- };
- struct BasicType {
- BasicKind kind;
- u32 flags;
- String name;
- };
- #define TYPE_KINDS \
- TYPE_KIND(Invalid), \
- TYPE_KIND(Basic), \
- TYPE_KIND(Array), \
- TYPE_KIND(Vector), \
- TYPE_KIND(Slice), \
- TYPE_KIND(Structure), \
- TYPE_KIND(Pointer), \
- TYPE_KIND(Named), \
- TYPE_KIND(Tuple), \
- TYPE_KIND(Proc), \
- TYPE_KIND(Count),
- enum TypeKind {
- #define TYPE_KIND(k) GB_JOIN2(Type_, k)
- TYPE_KINDS
- #undef TYPE_KIND
- };
- String const type_strings[] = {
- #define TYPE_KIND(k) {cast(u8 *)#k, gb_size_of(#k)-1}
- TYPE_KINDS
- #undef TYPE_KIND
- };
- enum TypeFlag {
- TypeFlag_thread_local = GB_BIT(0),
- TypeFlag_volatile = GB_BIT(1),
- };
- struct Type {
- u32 flags;
- TypeKind kind;
- union {
- BasicType basic;
- struct {
- Type *elem;
- i64 count;
- } array;
- struct {
- Type *elem;
- i64 count;
- } vector;
- struct {
- Type *elem;
- } slice;
- struct {
- // Theses are arrays
- Entity **fields; // Entity_Variable
- isize field_count; // == offset_count
- i64 * offsets;
- b32 are_offsets_set;
- b32 is_packed;
- } structure;
- struct { Type *elem; } pointer;
- struct {
- String name;
- Type * base;
- Entity *type_name; // Entity_TypeName
- } named;
- struct {
- Entity **variables; // Entity_Variable
- isize variable_count;
- } tuple;
- struct {
- Scope *scope;
- Type * params; // Type_Tuple
- Type * results; // Type_Tuple
- isize param_count;
- isize result_count;
- } proc;
- };
- };
- Type *get_base_type(Type *t) {
- while (t->kind == Type_Named) {
- t = t->named.base;
- }
- return t;
- }
- void set_base_type(Type *t, Type *base) {
- if (t && t->kind == Type_Named) {
- t->named.base = base;
- }
- }
- Type *alloc_type(gbAllocator a, TypeKind kind) {
- Type *t = gb_alloc_item(a, Type);
- t->kind = kind;
- return t;
- }
- Type *make_type_basic(gbAllocator a, BasicType basic) {
- Type *t = alloc_type(a, Type_Basic);
- t->basic = basic;
- return t;
- }
- Type *make_type_array(gbAllocator a, Type *elem, i64 count) {
- Type *t = alloc_type(a, Type_Array);
- t->array.elem = elem;
- t->array.count = count;
- return t;
- }
- Type *make_type_vector(gbAllocator a, Type *elem, i64 count) {
- Type *t = alloc_type(a, Type_Vector);
- t->vector.elem = elem;
- t->vector.count = count;
- return t;
- }
- Type *make_type_slice(gbAllocator a, Type *elem) {
- Type *t = alloc_type(a, Type_Slice);
- t->array.elem = elem;
- return t;
- }
- Type *make_type_structure(gbAllocator a) {
- Type *t = alloc_type(a, Type_Structure);
- return t;
- }
- Type *make_type_pointer(gbAllocator a, Type *elem) {
- Type *t = alloc_type(a, Type_Pointer);
- t->pointer.elem = elem;
- return t;
- }
- Type *make_type_named(gbAllocator a, String name, Type *base, Entity *type_name) {
- Type *t = alloc_type(a, Type_Named);
- t->named.name = name;
- t->named.base = base;
- t->named.type_name = type_name;
- return t;
- }
- Type *make_type_tuple(gbAllocator a) {
- Type *t = alloc_type(a, Type_Tuple);
- return t;
- }
- Type *make_type_proc(gbAllocator a, Scope *scope, Type *params, isize param_count, Type *results, isize result_count) {
- Type *t = alloc_type(a, Type_Proc);
- t->proc.scope = scope;
- t->proc.params = params;
- t->proc.param_count = param_count;
- t->proc.results = results;
- t->proc.result_count = result_count;
- return t;
- }
- Type *type_deref(Type *t) {
- if (t != NULL) {
- Type *bt = get_base_type(t);
- if (bt != NULL && bt->kind == Type_Pointer)
- return bt->pointer.elem;
- }
- return t;
- }
- #define STR_LIT(x) {cast(u8 *)(x), gb_size_of(x)-1}
- gb_global Type basic_types[] = {
- {0, Type_Basic, {Basic_Invalid, 0, STR_LIT("invalid type")}},
- {0, Type_Basic, {Basic_bool, BasicFlag_Boolean, STR_LIT("bool")}},
- {0, Type_Basic, {Basic_i8, BasicFlag_Integer, STR_LIT("i8")}},
- {0, Type_Basic, {Basic_i16, BasicFlag_Integer, STR_LIT("i16")}},
- {0, Type_Basic, {Basic_i32, BasicFlag_Integer, STR_LIT("i32")}},
- {0, Type_Basic, {Basic_i64, BasicFlag_Integer, STR_LIT("i64")}},
- {0, Type_Basic, {Basic_i128, BasicFlag_Integer, STR_LIT("i128")}},
- {0, Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u8")}},
- {0, Type_Basic, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u16")}},
- {0, Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u32")}},
- {0, Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u64")}},
- {0, Type_Basic, {Basic_u128, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u128")}},
- {0, Type_Basic, {Basic_f32, BasicFlag_Float, STR_LIT("f32")}},
- {0, Type_Basic, {Basic_f64, BasicFlag_Float, STR_LIT("f64")}},
- {0, Type_Basic, {Basic_int, BasicFlag_Integer, STR_LIT("int")}},
- {0, Type_Basic, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("uint")}},
- {0, Type_Basic, {Basic_rawptr, BasicFlag_Pointer, STR_LIT("rawptr")}},
- {0, Type_Basic, {Basic_string, BasicFlag_String, STR_LIT("string")}},
- {0, Type_Basic, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, STR_LIT("untyped bool")}},
- {0, Type_Basic, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped integer")}},
- {0, Type_Basic, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, STR_LIT("untyped float")}},
- {0, Type_Basic, {Basic_UntypedPointer, BasicFlag_Pointer | BasicFlag_Untyped, STR_LIT("untyped pointer")}},
- {0, Type_Basic, {Basic_UntypedString, BasicFlag_String | BasicFlag_Untyped, STR_LIT("untyped string")}},
- {0, Type_Basic, {Basic_UntypedRune, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped rune")}},
- };
- gb_global Type basic_type_aliases[] = {
- {0, Type_Basic, {Basic_byte, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("byte")}},
- {0, Type_Basic, {Basic_rune, BasicFlag_Integer, STR_LIT("rune")}},
- };
- gb_global Type *t_invalid = &basic_types[Basic_Invalid];
- gb_global Type *t_bool = &basic_types[Basic_bool];
- gb_global Type *t_i8 = &basic_types[Basic_i8];
- gb_global Type *t_i16 = &basic_types[Basic_i16];
- gb_global Type *t_i32 = &basic_types[Basic_i32];
- gb_global Type *t_i64 = &basic_types[Basic_i64];
- gb_global Type *t_i128 = &basic_types[Basic_i128];
- gb_global Type *t_u8 = &basic_types[Basic_u8];
- gb_global Type *t_u16 = &basic_types[Basic_u16];
- gb_global Type *t_u32 = &basic_types[Basic_u32];
- gb_global Type *t_u64 = &basic_types[Basic_u64];
- gb_global Type *t_u128 = &basic_types[Basic_u128];
- gb_global Type *t_f32 = &basic_types[Basic_f32];
- gb_global Type *t_f64 = &basic_types[Basic_f64];
- gb_global Type *t_int = &basic_types[Basic_int];
- gb_global Type *t_uint = &basic_types[Basic_uint];
- gb_global Type *t_rawptr = &basic_types[Basic_rawptr];
- gb_global Type *t_string = &basic_types[Basic_string];
- gb_global Type *t_untyped_bool = &basic_types[Basic_UntypedBool];
- gb_global Type *t_untyped_integer = &basic_types[Basic_UntypedInteger];
- gb_global Type *t_untyped_float = &basic_types[Basic_UntypedFloat];
- gb_global Type *t_untyped_pointer = &basic_types[Basic_UntypedPointer];
- gb_global Type *t_untyped_string = &basic_types[Basic_UntypedString];
- gb_global Type *t_untyped_rune = &basic_types[Basic_UntypedRune];
- gb_global Type *t_byte = &basic_type_aliases[Basic_byte];
- gb_global Type *t_rune = &basic_type_aliases[Basic_rune];
- b32 is_type_named(Type *t) {
- if (t->kind == Type_Basic)
- return true;
- return t->kind == Type_Named;
- }
- b32 is_type_boolean(Type *t) {
- t = get_base_type(t);
- if (t->kind == Type_Basic)
- return (t->basic.flags & BasicFlag_Boolean) != 0;
- return false;
- }
- b32 is_type_integer(Type *t) {
- t = get_base_type(t);
- if (t->kind == Type_Basic)
- return (t->basic.flags & BasicFlag_Integer) != 0;
- return false;
- }
- b32 is_type_unsigned(Type *t) {
- t = get_base_type(t);
- if (t->kind == Type_Basic)
- return (t->basic.flags & BasicFlag_Unsigned) != 0;
- return false;
- }
- b32 is_type_numeric(Type *t) {
- t = get_base_type(t);
- if (t->kind == Type_Basic)
- return (t->basic.flags & BasicFlag_Numeric) != 0;
- if (t->kind == Type_Vector)
- return is_type_numeric(t->vector.elem);
- return false;
- }
- b32 is_type_string(Type *t) {
- t = get_base_type(t);
- if (t->kind == Type_Basic)
- return (t->basic.flags & BasicFlag_String) != 0;
- return false;
- }
- b32 is_type_typed(Type *t) {
- t = get_base_type(t);
- if (t->kind == Type_Basic)
- return (t->basic.flags & BasicFlag_Untyped) == 0;
- return true;
- }
- b32 is_type_untyped(Type *t) {
- t = get_base_type(t);
- if (t->kind == Type_Basic)
- return (t->basic.flags & BasicFlag_Untyped) != 0;
- return false;
- }
- b32 is_type_ordered(Type *t) {
- t = get_base_type(t);
- if (t->kind == Type_Basic)
- return (t->basic.flags & BasicFlag_Ordered) != 0;
- if (t->kind == Type_Pointer)
- return true;
- return false;
- }
- b32 is_type_constant_type(Type *t) {
- t = get_base_type(t);
- if (t->kind == Type_Basic)
- return (t->basic.flags & BasicFlag_ConstantType) != 0;
- return false;
- }
- b32 is_type_float(Type *t) {
- t = get_base_type(t);
- if (t->kind == Type_Basic)
- return (t->basic.flags & BasicFlag_Float) != 0;
- return false;
- }
- b32 is_type_pointer(Type *t) {
- t = get_base_type(t);
- if (t->kind == Type_Basic)
- return (t->basic.flags & BasicFlag_Pointer) != 0;
- return t->kind == Type_Pointer;
- }
- b32 is_type_int_or_uint(Type *t) {
- if (t->kind == Type_Basic)
- return (t->basic.kind == Basic_int) || (t->basic.kind == Basic_uint);
- return false;
- }
- b32 is_type_rawptr(Type *t) {
- if (t->kind == Type_Basic)
- return t->basic.kind == Basic_rawptr;
- return false;
- }
- b32 is_type_u8(Type *t) {
- if (t->kind == Type_Basic)
- return t->basic.kind == Basic_u8;
- return false;
- }
- b32 is_type_slice(Type *t) {
- t = get_base_type(t);
- return t->kind == Type_Slice;
- }
- b32 is_type_u8_slice(Type *t) {
- t = get_base_type(t);
- if (t->kind == Type_Slice)
- return is_type_u8(t->slice.elem);
- return false;
- }
- b32 is_type_vector(Type *t) {
- return t->kind == Type_Vector;
- }
- b32 is_type_proc(Type *t) {
- t = get_base_type(t);
- return t->kind == Type_Proc;
- }
- Type *base_vector_type(Type *t) {
- if (is_type_vector(t)) {
- return t->vector.elem;
- }
- return t;
- }
- b32 is_type_comparable(Type *t) {
- t = get_base_type(t);
- switch (t->kind) {
- case Type_Basic:
- return true;
- case Type_Pointer:
- return true;
- case Type_Structure: {
- for (isize i = 0; i < t->structure.field_count; i++) {
- if (!is_type_comparable(t->structure.fields[i]->type))
- return false;
- }
- return true;
- } break;
- case Type_Array:
- return is_type_comparable(t->array.elem);
- case Type_Vector:
- return is_type_comparable(t->vector.elem);
- case Type_Proc:
- return true;
- }
- return false;
- }
- b32 are_types_identical(Type *x, Type *y) {
- if (x == y)
- return true;
- if ((x == NULL && y != NULL) ||
- (x != NULL && y == NULL)) {
- return false;
- }
- switch (x->kind) {
- case Type_Basic:
- if (y->kind == Type_Basic)
- return x->basic.kind == y->basic.kind;
- break;
- case Type_Array:
- if (y->kind == Type_Array)
- return (x->array.count == y->array.count) && are_types_identical(x->array.elem, y->array.elem);
- break;
- case Type_Vector:
- if (y->kind == Type_Vector)
- return (x->vector.count == y->vector.count) && are_types_identical(x->vector.elem, y->vector.elem);
- break;
- case Type_Slice:
- if (y->kind == Type_Slice)
- return are_types_identical(x->slice.elem, y->slice.elem);
- break;
- case Type_Structure:
- if (y->kind == Type_Structure) {
- if (x->structure.field_count == y->structure.field_count) {
- for (isize i = 0; i < x->structure.field_count; i++) {
- if (!are_types_identical(x->structure.fields[i]->type, y->structure.fields[i]->type)) {
- return false;
- }
- }
- return true;
- }
- }
- break;
- case Type_Pointer:
- if (y->kind == Type_Pointer)
- return are_types_identical(x->pointer.elem, y->pointer.elem);
- break;
- case Type_Named:
- if (y->kind == Type_Named)
- return x->named.base == y->named.base;
- break;
- case Type_Tuple:
- if (y->kind == Type_Tuple) {
- if (x->tuple.variable_count == y->tuple.variable_count) {
- for (isize i = 0; i < x->tuple.variable_count; i++) {
- if (!are_types_identical(x->tuple.variables[i]->type, y->tuple.variables[i]->type))
- return false;
- }
- return true;
- }
- }
- break;
- case Type_Proc:
- if (y->kind == Type_Proc) {
- return are_types_identical(x->proc.params, y->proc.params) &&
- are_types_identical(x->proc.results, y->proc.results);
- }
- break;
- }
- return false;
- }
- Type *default_type(Type *type) {
- if (type->kind == Type_Basic) {
- switch (type->basic.kind) {
- case Basic_UntypedBool: return &basic_types[Basic_bool];
- case Basic_UntypedInteger: return &basic_types[Basic_int];
- case Basic_UntypedFloat: return &basic_types[Basic_f64];
- case Basic_UntypedString: return &basic_types[Basic_string];
- case Basic_UntypedRune: return &basic_types[Basic_rune];
- case Basic_UntypedPointer: return &basic_types[Basic_rawptr];
- }
- }
- return type;
- }
- // NOTE(bill): Internal sizes of certain types
- // string: 2*word_size (ptr+len)
- // slice: 3*word_size (ptr+len+cap)
- // array: count*size_of(elem) aligned
- // NOTE(bill): Alignment of structures and other types are to be compatible with C
- struct BaseTypeSizes {
- i64 word_size;
- i64 max_align;
- };
- // TODO(bill): Change
- gb_global i64 basic_type_sizes[] = {
- 0, // Basic_Invalid
- 1, // Basic_bool
- 1, // Basic_i8
- 2, // Basic_i16
- 4, // Basic_i32
- 8, // Basic_i64
- 16, // Basic_i128
- 1, // Basic_u8
- 2, // Basic_u16
- 4, // Basic_u32
- 8, // Basic_u64
- 16, // Basic_u128
- 4, // Basic_f32
- 8, // Basic_f64
- };
- i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t);
- i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t);
- i64 type_offset_of(BaseTypeSizes s, gbAllocator allocator, Type *t, i64 index);
- i64 align_formula(i64 size, i64 align) {
- i64 result = size + align-1;
- return result - result%align;
- }
- i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
- t = get_base_type(t);
- switch (t->kind) {
- case Type_Array:
- return type_align_of(s, allocator, t->array.elem);
- case Type_Vector: {
- i64 size = type_size_of(s, allocator, t->vector.elem);
- size *= t->vector.count;
- size = next_pow2(size);
- // TODO(bill): Type_Vector type_align_of
- return gb_clamp(size, s.max_align, 4*s.max_align);
- } break;
- case Type_Structure: {
- if (!t->structure.is_packed) {
- i64 max = 1;
- for (isize i = 0; i < t->structure.field_count; i++) {
- i64 align = type_align_of(s, allocator, t->structure.fields[i]->type);
- if (max < align)
- max = align;
- }
- return max;
- }
- } break;
- }
- return gb_clamp(next_pow2(type_size_of(s, allocator, t)), 1, s.max_align);
- }
- i64 *type_set_offsets_of(BaseTypeSizes s, gbAllocator allocator, Entity **fields, isize field_count, b32 is_packed) {
- // TODO(bill): use arena allocation
- i64 *offsets = gb_alloc_array(allocator, i64, field_count);
- i64 curr_offset = 0;
- if (is_packed) {
- for (isize i = 0; i < field_count; i++) {
- offsets[i] = curr_offset;
- curr_offset += type_size_of(s, allocator, fields[i]->type);
- }
- } else {
- for (isize i = 0; i < field_count; i++) {
- i64 align = type_align_of(s, allocator, fields[i]->type);
- curr_offset = align_formula(curr_offset, align);
- offsets[i] = curr_offset;
- curr_offset += type_size_of(s, allocator, fields[i]->type);
- }
- }
- return offsets;
- }
- b32 type_set_offsets(BaseTypeSizes s, gbAllocator allocator, Type *t) {
- GB_ASSERT(t->kind == Type_Structure);
- if (!t->structure.are_offsets_set) {
- t->structure.offsets = type_set_offsets_of(s, allocator, t->structure.fields, t->structure.field_count, t->structure.is_packed);
- t->structure.are_offsets_set = true;
- return true;
- }
- return false;
- }
- i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
- t = get_base_type(t);
- switch (t->kind) {
- case Type_Basic: {
- GB_ASSERT(is_type_typed(t));
- BasicKind kind = t->basic.kind;
- if (kind < gb_count_of(basic_type_sizes)) {
- i64 size = basic_type_sizes[kind];
- if (size > 0)
- return size;
- }
- if (kind == Basic_string)
- return 2 * s.word_size;
- } break;
- case Type_Array: {
- i64 count = t->array.count;
- if (count == 0)
- return 0;
- i64 align = type_align_of(s, allocator, t->array.elem);
- i64 size = type_size_of(s, allocator, t->array.elem);
- i64 alignment = align_formula(size, align);
- return alignment*(count-1) + size;
- } break;
- case Type_Vector: {
- i64 count = t->vector.count;
- if (count == 0)
- return 0;
- // i64 align = type_align_of(s, allocator, t->vector.elem);
- i64 bit_size = 8*type_size_of(s, allocator, t->vector.elem);
- if (is_type_boolean(t->vector.elem)) {
- bit_size = 1; // NOTE(bill): LLVM can store booleans as 1 bit because a boolean _is_ an `i1`
- // Silly LLVM spec
- }
- i64 total_size_in_bits = bit_size * count;
- i64 total_size = (total_size_in_bits+7)/8;
- return total_size;
- // i64 alignment = align_formula(size, align);
- // return alignment*(count-1) + size;
- } break;
- case Type_Slice: // ptr + len + cap
- return 3 * s.word_size;
- case Type_Structure: {
- i64 count = t->structure.field_count;
- if (count == 0)
- return 0;
- type_set_offsets(s, allocator, t);
- return t->structure.offsets[count-1] + type_size_of(s, allocator, t->structure.fields[count-1]->type);
- } break;
- }
- // Catch all
- return s.word_size;
- }
- i64 type_offset_of(BaseTypeSizes s, gbAllocator allocator, Type *t, isize index) {
- if (t->kind == Type_Structure) {
- type_set_offsets(s, allocator, t);
- if (gb_is_between(index, 0, t->structure.field_count-1)) {
- return t->structure.offsets[index];
- }
- }
- return 0;
- }
- gbString write_type_to_string(gbString str, Type *type) {
- if (type == NULL) {
- return gb_string_appendc(str, "<no type>");
- }
- switch (type->kind) {
- case Type_Basic:
- str = gb_string_append_length(str, type->basic.name.text, type->basic.name.len);
- break;
- case Type_Array:
- str = gb_string_appendc(str, gb_bprintf("[%td]", type->array.count));
- str = write_type_to_string(str, type->array.elem);
- break;
- case Type_Vector:
- str = gb_string_appendc(str, gb_bprintf("{%td}", type->vector.count));
- str = write_type_to_string(str, type->vector.elem);
- break;
- case Type_Slice:
- str = gb_string_appendc(str, "[]");
- str = write_type_to_string(str, type->array.elem);
- break;
- case Type_Structure: {
- str = gb_string_appendc(str, "struct{");
- for (isize i = 0; i < type->structure.field_count; i++) {
- Entity *f = type->structure.fields[i];
- GB_ASSERT(f->kind == Entity_Variable);
- if (i > 0)
- str = gb_string_appendc(str, "; ");
- str = gb_string_append_length(str, f->token.string.text, f->token.string.len);
- str = gb_string_appendc(str, ": ");
- str = write_type_to_string(str, f->type);
- }
- str = gb_string_appendc(str, "}");
- } break;
- case Type_Pointer:
- str = gb_string_appendc(str, "^");
- str = write_type_to_string(str, type->pointer.elem);
- break;
- case Type_Named:
- if (type->named.type_name != NULL) {
- str = gb_string_append_length(str, type->named.name.text, type->named.name.len);
- } else {
- // NOTE(bill): Just in case
- str = gb_string_appendc(str, "<named type>");
- }
- break;
- case Type_Tuple:
- if (type->tuple.variable_count > 0) {
- for (isize i = 0; i < type->tuple.variable_count; i++) {
- Entity *var = type->tuple.variables[i];
- if (var != NULL) {
- GB_ASSERT(var->kind == Entity_Variable);
- if (i > 0)
- str = gb_string_appendc(str, ", ");
- str = write_type_to_string(str, var->type);
- }
- }
- }
- break;
- case Type_Proc:
- str = gb_string_appendc(str, "proc(");
- if (type->proc.params)
- str = write_type_to_string(str, type->proc.params);
- str = gb_string_appendc(str, ")");
- if (type->proc.results) {
- str = gb_string_appendc(str, " -> ");
- str = write_type_to_string(str, type->proc.results);
- }
- break;
- }
- return str;
- }
- gbString type_to_string(Type *type, gbAllocator a = gb_heap_allocator()) {
- gbString str = gb_string_make(a, "");
- return write_type_to_string(str, type);
- }
|