aboutsummaryrefslogtreecommitdiff
path: root/src/types.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/types.cpp')
-rw-r--r--src/types.cpp476
1 files changed, 351 insertions, 125 deletions
diff --git a/src/types.cpp b/src/types.cpp
index 233f903a3..74da7f6aa 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -1,5 +1,5 @@
-struct Scope;
struct Ast;
+struct Scope;
struct Entity;
enum BasicKind {
@@ -111,7 +111,7 @@ enum BasicFlag {
BasicFlag_Ordered = BasicFlag_Integer | BasicFlag_Float | BasicFlag_String | BasicFlag_Pointer | BasicFlag_Rune,
BasicFlag_OrderedNumeric = BasicFlag_Integer | BasicFlag_Float | BasicFlag_Rune,
BasicFlag_ConstantType = BasicFlag_Boolean | BasicFlag_Numeric | BasicFlag_String | BasicFlag_Pointer | BasicFlag_Rune,
- BasicFlag_SimpleCompare = BasicFlag_Boolean | BasicFlag_Numeric | BasicFlag_Pointer | BasicFlag_Rune,
+ BasicFlag_SimpleCompare = BasicFlag_Boolean | BasicFlag_Integer | BasicFlag_Pointer | BasicFlag_Rune,
};
struct BasicType {
@@ -161,10 +161,10 @@ struct TypeStruct {
struct TypeUnion {
Slice<Type *> variants;
-
+
Ast * node;
Scope * scope;
-
+
i64 variant_block_size;
i64 custom_align;
Type * polymorphic_params; // Type_Tuple
@@ -503,9 +503,9 @@ gb_global Type basic_types[] = {
{Type_Basic, {Basic_rawptr, BasicFlag_Pointer, -1, STR_LIT("rawptr")}},
{Type_Basic, {Basic_string, BasicFlag_String, -1, STR_LIT("string")}},
{Type_Basic, {Basic_cstring, BasicFlag_String, -1, STR_LIT("cstring")}},
- {Type_Basic, {Basic_any, 0, -1, STR_LIT("any")}},
+ {Type_Basic, {Basic_any, 0, 16, STR_LIT("any")}},
- {Type_Basic, {Basic_typeid, 0, -1, STR_LIT("typeid")}},
+ {Type_Basic, {Basic_typeid, 0, 8, STR_LIT("typeid")}},
// Endian
{Type_Basic, {Basic_i16le, BasicFlag_Integer | BasicFlag_EndianLittle, 2, STR_LIT("i16le")}},
@@ -729,10 +729,12 @@ gb_global Type *t_map_set_proc = nullptr;
gb_global Type *t_objc_object = nullptr;
gb_global Type *t_objc_selector = nullptr;
gb_global Type *t_objc_class = nullptr;
+gb_global Type *t_objc_ivar = nullptr;
gb_global Type *t_objc_id = nullptr;
gb_global Type *t_objc_SEL = nullptr;
gb_global Type *t_objc_Class = nullptr;
+gb_global Type *t_objc_Ivar = nullptr;
enum OdinAtomicMemoryOrder : i32 {
OdinAtomicMemoryOrder_relaxed = 0, // unordered
@@ -856,41 +858,29 @@ gb_internal void type_path_pop(TypePath *tp) {
#define FAILURE_SIZE 0
#define FAILURE_ALIGNMENT 0
-gb_internal bool type_ptr_set_exists(PtrSet<Type *> *s, Type *t);
-
-gb_internal bool type_ptr_set_update(PtrSet<Type *> *s, Type *t) {
- if (t == nullptr) {
- return true;
- }
- if (type_ptr_set_exists(s, t)) {
- return true;
+gb_internal Type *base_type(Type *t) {
+ for (;;) {
+ if (t == nullptr) {
+ break;
+ }
+ if (t->kind != Type_Named) {
+ break;
+ }
+ if (t == t->Named.base) {
+ return t_invalid;
+ }
+ t = t->Named.base;
}
- ptr_set_add(s, t);
- return false;
+ return t;
}
-gb_internal bool type_ptr_set_exists(PtrSet<Type *> *s, Type *t) {
- if (t == nullptr) {
- return true;
- }
-
- if (ptr_set_exists(s, t)) {
- return true;
- }
-
- // TODO(bill, 2019-10-05): This is very slow and it's probably a lot
- // faster to cache types correctly
- for (Type *f : *s) {
- if (are_types_identical(t, f)) {
- ptr_set_add(s, t);
- return true;
- }
+gb_internal Type *base_named_type(Type *t) {
+ if (t->kind != Type_Named) {
+ return t_invalid;
}
- return false;
-}
-
-gb_internal Type *base_type(Type *t) {
+ Type *prev_named = t;
+ t = t->Named.base;
for (;;) {
if (t == nullptr) {
break;
@@ -901,9 +891,10 @@ gb_internal Type *base_type(Type *t) {
if (t == t->Named.base) {
return t_invalid;
}
+ prev_named = t;
t = t->Named.base;
}
- return t;
+ return prev_named;
}
gb_internal Type *base_enum_type(Type *t) {
@@ -1212,6 +1203,7 @@ gb_internal Type *type_deref(Type *t, bool allow_multi_pointer) {
}
gb_internal bool is_type_named(Type *t) {
+ if (t == nullptr) { return false; }
if (t->kind == Type_Basic) {
return true;
}
@@ -1221,6 +1213,7 @@ gb_internal bool is_type_named(Type *t) {
gb_internal bool is_type_boolean(Type *t) {
// t = core_type(t);
t = base_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Boolean) != 0;
}
@@ -1229,6 +1222,7 @@ gb_internal bool is_type_boolean(Type *t) {
gb_internal bool is_type_integer(Type *t) {
// t = core_type(t);
t = base_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Integer) != 0;
}
@@ -1250,15 +1244,18 @@ gb_internal bool is_type_integer_like(Type *t) {
gb_internal bool is_type_unsigned(Type *t) {
t = base_type(t);
- // t = core_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Unsigned) != 0;
}
+ if (t->kind == Type_Enum) {
+ return (t->Enum.base_type->Basic.flags & BasicFlag_Unsigned) != 0;
+ }
return false;
}
gb_internal bool is_type_integer_128bit(Type *t) {
- // t = core_type(t);
t = base_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Integer) != 0 && t->Basic.size == 16;
}
@@ -1267,6 +1264,7 @@ gb_internal bool is_type_integer_128bit(Type *t) {
gb_internal bool is_type_rune(Type *t) {
// t = core_type(t);
t = base_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Rune) != 0;
}
@@ -1275,6 +1273,7 @@ gb_internal bool is_type_rune(Type *t) {
gb_internal bool is_type_numeric(Type *t) {
// t = core_type(t);
t = base_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Numeric) != 0;
} else if (t->kind == Type_Enum) {
@@ -1288,6 +1287,7 @@ gb_internal bool is_type_numeric(Type *t) {
}
gb_internal bool is_type_string(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_String) != 0;
}
@@ -1295,6 +1295,7 @@ gb_internal bool is_type_string(Type *t) {
}
gb_internal bool is_type_cstring(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_Basic) {
return t->Basic.kind == Basic_cstring;
}
@@ -1302,9 +1303,7 @@ gb_internal bool is_type_cstring(Type *t) {
}
gb_internal bool is_type_typed(Type *t) {
t = base_type(t);
- if (t == nullptr) {
- return false;
- }
+ if (t == nullptr) { return false; }
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Untyped) == 0;
}
@@ -1312,9 +1311,7 @@ gb_internal bool is_type_typed(Type *t) {
}
gb_internal bool is_type_untyped(Type *t) {
t = base_type(t);
- if (t == nullptr) {
- return false;
- }
+ if (t == nullptr) { return false; }
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Untyped) != 0;
}
@@ -1322,6 +1319,7 @@ gb_internal bool is_type_untyped(Type *t) {
}
gb_internal bool is_type_ordered(Type *t) {
t = core_type(t);
+ if (t == nullptr) { return false; }
switch (t->kind) {
case Type_Basic:
return (t->Basic.flags & BasicFlag_Ordered) != 0;
@@ -1334,6 +1332,7 @@ gb_internal bool is_type_ordered(Type *t) {
}
gb_internal bool is_type_ordered_numeric(Type *t) {
t = core_type(t);
+ if (t == nullptr) { return false; }
switch (t->kind) {
case Type_Basic:
return (t->Basic.flags & BasicFlag_OrderedNumeric) != 0;
@@ -1342,6 +1341,7 @@ gb_internal bool is_type_ordered_numeric(Type *t) {
}
gb_internal bool is_type_constant_type(Type *t) {
t = core_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_ConstantType) != 0;
}
@@ -1355,6 +1355,7 @@ gb_internal bool is_type_constant_type(Type *t) {
}
gb_internal bool is_type_float(Type *t) {
t = core_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Float) != 0;
}
@@ -1362,6 +1363,7 @@ gb_internal bool is_type_float(Type *t) {
}
gb_internal bool is_type_complex(Type *t) {
t = core_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Complex) != 0;
}
@@ -1369,6 +1371,7 @@ gb_internal bool is_type_complex(Type *t) {
}
gb_internal bool is_type_quaternion(Type *t) {
t = core_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Quaternion) != 0;
}
@@ -1376,6 +1379,7 @@ gb_internal bool is_type_quaternion(Type *t) {
}
gb_internal bool is_type_complex_or_quaternion(Type *t) {
t = core_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_Basic) {
return (t->Basic.flags & (BasicFlag_Complex|BasicFlag_Quaternion)) != 0;
}
@@ -1383,6 +1387,7 @@ gb_internal bool is_type_complex_or_quaternion(Type *t) {
}
gb_internal bool is_type_pointer(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Pointer) != 0;
}
@@ -1390,10 +1395,12 @@ gb_internal bool is_type_pointer(Type *t) {
}
gb_internal bool is_type_soa_pointer(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
return t->kind == Type_SoaPointer;
}
gb_internal bool is_type_multi_pointer(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
return t->kind == Type_MultiPointer;
}
gb_internal bool is_type_internally_pointer_like(Type *t) {
@@ -1402,6 +1409,7 @@ gb_internal bool is_type_internally_pointer_like(Type *t) {
gb_internal bool is_type_tuple(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
return t->kind == Type_Tuple;
}
gb_internal bool is_type_uintptr(Type *t) {
@@ -1424,21 +1432,24 @@ gb_internal bool is_type_u8(Type *t) {
}
gb_internal bool is_type_array(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
return t->kind == Type_Array;
}
gb_internal bool is_type_enumerated_array(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
return t->kind == Type_EnumeratedArray;
}
gb_internal bool is_type_matrix(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
return t->kind == Type_Matrix;
}
gb_internal i64 matrix_align_of(Type *t, struct TypePath *tp) {
t = base_type(t);
GB_ASSERT(t->kind == Type_Matrix);
-
+
Type *elem = t->Matrix.elem;
i64 row_count = gb_max(t->Matrix.row_count, 1);
i64 column_count = gb_max(t->Matrix.column_count, 1);
@@ -1450,15 +1461,15 @@ gb_internal i64 matrix_align_of(Type *t, struct TypePath *tp) {
i64 elem_align = type_align_of_internal(elem, tp);
if (pop) type_path_pop(tp);
-
+
i64 elem_size = type_size_of(elem);
-
+
// NOTE(bill, 2021-10-25): The alignment strategy here is to have zero padding
// It would be better for performance to pad each column so that each column
// could be maximally aligned but as a compromise, having no padding will be
// beneficial to third libraries that assume no padding
-
+
i64 total_expected_size = row_count*column_count*elem_size;
// i64 min_alignment = prev_pow2(elem_align * row_count);
i64 min_alignment = prev_pow2(total_expected_size);
@@ -1466,7 +1477,7 @@ gb_internal i64 matrix_align_of(Type *t, struct TypePath *tp) {
min_alignment >>= 1;
}
min_alignment = gb_max(min_alignment, elem_align);
-
+
i64 align = gb_min(min_alignment, build_context.max_simd_align);
return align;
}
@@ -1480,7 +1491,7 @@ gb_internal i64 matrix_type_stride_in_bytes(Type *t, struct TypePath *tp) {
} else if (t->Matrix.row_count == 0) {
return 0;
}
-
+
i64 elem_size;
if (tp != nullptr) {
elem_size = type_size_of_internal(t->Matrix.elem, tp);
@@ -1489,7 +1500,7 @@ gb_internal i64 matrix_type_stride_in_bytes(Type *t, struct TypePath *tp) {
}
i64 stride_in_bytes = 0;
-
+
// NOTE(bill, 2021-10-25): The alignment strategy here is to have zero padding
// It would be better for performance to pad each column/row so that each column/row
// could be maximally aligned but as a compromise, having no padding will be
@@ -1545,7 +1556,7 @@ gb_internal i64 matrix_row_major_index_to_offset(Type *t, i64 index) {
gb_internal i64 matrix_column_major_index_to_offset(Type *t, i64 index) {
t = base_type(t);
GB_ASSERT(t->kind == Type_Matrix);
-
+
i64 row_index = index%t->Matrix.row_count;
i64 column_index = index/t->Matrix.row_count;
return matrix_indices_to_offset(t, row_index, column_index);
@@ -1566,7 +1577,7 @@ gb_internal bool is_type_valid_for_matrix_elems(Type *t) {
return true;
} else if (is_type_complex(t)) {
return true;
- }
+ }
if (t->kind == Type_Generic) {
return true;
}
@@ -1575,22 +1586,27 @@ gb_internal bool is_type_valid_for_matrix_elems(Type *t) {
gb_internal bool is_type_dynamic_array(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
return t->kind == Type_DynamicArray;
}
gb_internal bool is_type_slice(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
return t->kind == Type_Slice;
}
gb_internal bool is_type_proc(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
return t->kind == Type_Proc;
}
gb_internal bool is_type_asm_proc(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
return t->kind == Type_Proc && t->Proc.calling_convention == ProcCC_InlineAsm;
}
gb_internal bool is_type_simd_vector(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
return t->kind == Type_SimdVector;
}
@@ -1630,11 +1646,13 @@ gb_internal Type *base_any_array_type(Type *t) {
gb_internal bool is_type_generic(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
return t->kind == Type_Generic;
}
gb_internal bool is_type_u8_slice(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_Slice) {
return is_type_u8(t->Slice.elem);
}
@@ -1642,6 +1660,7 @@ gb_internal bool is_type_u8_slice(Type *t) {
}
gb_internal bool is_type_u8_array(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_Array) {
return is_type_u8(t->Array.elem);
}
@@ -1649,6 +1668,7 @@ gb_internal bool is_type_u8_array(Type *t) {
}
gb_internal bool is_type_u8_ptr(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_Pointer) {
return is_type_u8(t->Slice.elem);
}
@@ -1656,6 +1676,7 @@ gb_internal bool is_type_u8_ptr(Type *t) {
}
gb_internal bool is_type_u8_multi_ptr(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_MultiPointer) {
return is_type_u8(t->Slice.elem);
}
@@ -1663,6 +1684,7 @@ gb_internal bool is_type_u8_multi_ptr(Type *t) {
}
gb_internal bool is_type_rune_array(Type *t) {
t = base_type(t);
+ if (t == nullptr) { return false; }
if (t->kind == Type_Array) {
return is_type_rune(t->Array.elem);
}
@@ -1801,6 +1823,27 @@ gb_internal bool is_type_union_maybe_pointer_original_alignment(Type *t) {
}
+enum TypeEndianKind {
+ TypeEndian_Platform,
+ TypeEndian_Little,
+ TypeEndian_Big,
+};
+
+gb_internal TypeEndianKind type_endian_kind_of(Type *t) {
+ t = core_type(t);
+ if (t->kind == Type_Basic) {
+ if (t->Basic.flags & BasicFlag_EndianLittle) {
+ return TypeEndian_Little;
+ }
+ if (t->Basic.flags & BasicFlag_EndianBig) {
+ return TypeEndian_Big;
+ }
+ } else if (t->kind == Type_BitSet) {
+ return type_endian_kind_of(bit_set_to_int(t));
+ }
+ return TypeEndian_Platform;
+}
+
gb_internal bool is_type_endian_big(Type *t) {
t = core_type(t);
@@ -1967,7 +2010,13 @@ gb_internal bool is_type_untyped_uninit(Type *t) {
}
gb_internal bool is_type_empty_union(Type *t) {
+ if (t == nullptr) {
+ return false;
+ }
t = base_type(t);
+ if (t == nullptr) {
+ return false;
+ }
return t->kind == Type_Union && t->Union.variants.count == 0;
}
@@ -2098,6 +2147,26 @@ gb_internal bool is_type_sliceable(Type *t) {
return false;
}
+gb_internal Entity *type_get_polymorphic_parent(Type *t, Type **params_) {
+ t = base_type(t);
+ if (t == nullptr) {
+ return nullptr;
+ }
+ Type *parent = nullptr;
+ if (t->kind == Type_Struct) {
+ parent = t->Struct.polymorphic_parent;
+ if (params_) *params_ = t->Struct.polymorphic_params;
+ } else if (t->kind == Type_Union) {
+ parent = t->Union.polymorphic_parent;
+ if (params_) *params_ = t->Union.polymorphic_params;
+ }
+ if (parent != nullptr) {
+ GB_ASSERT(parent->kind == Type_Named);
+
+ return parent->Named.type_name;
+ }
+ return nullptr;
+}
gb_internal bool is_type_polymorphic_record(Type *t) {
t = base_type(t);
@@ -2464,7 +2533,7 @@ gb_internal bool is_type_simple_compare(Type *t) {
case Type_Proc:
case Type_BitSet:
return true;
-
+
case Type_Matrix:
return is_type_simple_compare(t->Matrix.elem);
@@ -2636,7 +2705,7 @@ gb_internal bool are_types_identical(Type *x, Type *y) {
y = y->Named.base;
}
}
- if (x->kind != y->kind) {
+ if (x == nullptr || y == nullptr || x->kind != y->kind) {
return false;
}
@@ -2711,7 +2780,7 @@ gb_internal bool are_types_identical_internal(Type *x, Type *y, bool check_tuple
case Type_Array:
return (x->Array.count == y->Array.count) && are_types_identical(x->Array.elem, y->Array.elem);
-
+
case Type_Matrix:
return x->Matrix.row_count == y->Matrix.row_count &&
x->Matrix.column_count == y->Matrix.column_count &&
@@ -2736,7 +2805,37 @@ gb_internal bool are_types_identical_internal(Type *x, Type *y, bool check_tuple
case Type_Enum:
- return x == y; // NOTE(bill): All enums are unique
+ if (x == y) {
+ return true;
+ }
+ if (x->Enum.fields.count != y->Enum.fields.count) {
+ return false;
+ }
+ if (!are_types_identical(x->Enum.base_type, y->Enum.base_type)) {
+ return false;
+ }
+ if (x->Enum.min_value_index != y->Enum.min_value_index) {
+ return false;
+ }
+ if (x->Enum.max_value_index != y->Enum.max_value_index) {
+ return false;
+ }
+
+ for (isize i = 0; i < x->Enum.fields.count; i++) {
+ Entity *a = x->Enum.fields[i];
+ Entity *b = y->Enum.fields[i];
+ if (a->token.string != b->token.string) {
+ return false;
+ }
+ GB_ASSERT(a->kind == b->kind);
+ GB_ASSERT(a->kind == Entity_Constant);
+ bool same = compare_exact_values(Token_CmpEq, a->Constant.value, b->Constant.value);
+ if (!same) {
+ return false;
+ }
+ }
+
+ return true;
case Type_Union:
if (x->Union.variants.count == y->Union.variants.count &&
@@ -2794,7 +2893,9 @@ gb_internal bool are_types_identical_internal(Type *x, Type *y, bool check_tuple
return false;
}
}
- return are_types_identical(x->Struct.polymorphic_params, y->Struct.polymorphic_params);
+ // TODO(bill): Which is the correct logic here?
+ // return are_types_identical(x->Struct.polymorphic_params, y->Struct.polymorphic_params);
+ return true;
}
break;
@@ -2893,6 +2994,10 @@ gb_internal Type *default_type(Type *type) {
case Basic_UntypedString: return t_string;
case Basic_UntypedRune: return t_rune;
}
+ } else if (type->kind == Type_Generic) {
+ if (type->Generic.specialized) {
+ return default_type(type->Generic.specialized);
+ }
}
return type;
}
@@ -2991,11 +3096,15 @@ gb_internal i64 union_tag_size(Type *u) {
compiler_error("how many variants do you have?! %lld", cast(long long)u->Union.variants.count);
}
- for_array(i, u->Union.variants) {
- Type *variant_type = u->Union.variants[i];
- i64 align = type_align_of(variant_type);
- if (max_align < align) {
- max_align = align;
+ if (u->Union.custom_align > 0) {
+ max_align = gb_max(max_align, u->Union.custom_align);
+ } else {
+ for_array(i, u->Union.variants) {
+ Type *variant_type = u->Union.variants[i];
+ i64 align = type_align_of(variant_type);
+ if (max_align < align) {
+ max_align = align;
+ }
}
}
@@ -3288,6 +3397,15 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name
}
}
}
+
+ Type *objc_ivar_type = e->TypeName.objc_ivar;
+ if (objc_ivar_type != nullptr) {
+ sel = lookup_field_with_selection(objc_ivar_type, field_name, false, sel, allow_blank_ident);
+ if (sel.entity != nullptr) {
+ sel.pseudo_field = true;
+ return sel;
+ }
+ }
}
if (is_type_polymorphic(type)) {
@@ -3571,7 +3689,7 @@ gb_internal bool are_struct_fields_reordered(Type *type) {
return false;
}
GB_ASSERT(type->Struct.offsets != nullptr);
-
+
i64 prev_offset = 0;
for_array(i, type->Struct.fields) {
i64 offset = type->Struct.offsets[i];
@@ -3592,9 +3710,9 @@ gb_internal Slice<i32> struct_fields_index_by_increasing_offset(gbAllocator allo
return {};
}
GB_ASSERT(type->Struct.offsets != nullptr);
-
+
auto indices = slice_make<i32>(allocator, type->Struct.fields.count);
-
+
i64 prev_offset = 0;
bool is_ordered = true;
for_array(i, indices) {
@@ -3609,14 +3727,14 @@ gb_internal Slice<i32> struct_fields_index_by_increasing_offset(gbAllocator allo
isize n = indices.count;
for (isize i = 1; i < n; i++) {
isize j = i;
-
+
while (j > 0 && type->Struct.offsets[indices[j-1]] > type->Struct.offsets[indices[j]]) {
gb_swap(i32, indices[j-1], indices[j]);
j -= 1;
- }
+ }
}
}
-
+
return indices;
}
@@ -3664,8 +3782,8 @@ gb_internal i64 type_size_of(Type *t) {
switch (t->Basic.kind) {
case Basic_string: size = 2*build_context.int_size; break;
case Basic_cstring: size = build_context.ptr_size; break;
- case Basic_any: size = 2*build_context.ptr_size; break;
- case Basic_typeid: size = build_context.ptr_size; break;
+ case Basic_any: size = 16; break;
+ case Basic_typeid: size = 8; break;
case Basic_int: case Basic_uint:
size = build_context.int_size;
@@ -3727,8 +3845,8 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) {
switch (t->Basic.kind) {
case Basic_string: return build_context.int_size;
case Basic_cstring: return build_context.ptr_size;
- case Basic_any: return build_context.ptr_size;
- case Basic_typeid: return build_context.ptr_size;
+ case Basic_any: return 8;
+ case Basic_typeid: return 8;
case Basic_int: case Basic_uint:
return build_context.int_size;
@@ -3866,8 +3984,8 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) {
// IMPORTANT TODO(bill): Figure out the alignment of vector types
return gb_clamp(next_pow2(type_size_of_internal(t, path)), 1, build_context.max_simd_align*2);
}
-
- case Type_Matrix:
+
+ case Type_Matrix:
return matrix_align_of(t, path);
case Type_SoaPointer:
@@ -3978,8 +4096,8 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) {
switch (kind) {
case Basic_string: return 2*build_context.int_size;
case Basic_cstring: return build_context.ptr_size;
- case Basic_any: return 2*build_context.ptr_size;
- case Basic_typeid: return build_context.ptr_size;
+ case Basic_any: return 16;
+ case Basic_typeid: return 8;
case Basic_int: case Basic_uint:
return build_context.int_size;
@@ -4069,10 +4187,10 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) {
}
i64 max = 0;
- i64 field_size = 0;
for_array(i, t->Union.variants) {
Type *variant_type = t->Union.variants[i];
+
i64 size = type_size_of_internal(variant_type, path);
if (max < size) {
max = size;
@@ -4091,7 +4209,7 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) {
size = align_formula(max, tag_size);
// NOTE(bill): Calculate the padding between the common fields and the tag
t->Union.tag_size = cast(i16)tag_size;
- t->Union.variant_block_size = size - field_size;
+ t->Union.variant_block_size = size;
size += tag_size;
}
@@ -4154,7 +4272,7 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) {
Type *elem = t->SimdVector.elem;
return count * type_size_of_internal(elem, path);
}
-
+
case Type_Matrix: {
i64 stride_in_bytes = matrix_type_stride_in_bytes(t, path);
if (t->Matrix.is_row_major) {
@@ -4215,7 +4333,7 @@ gb_internal i64 type_offset_of(Type *t, i64 index, Type **field_type_) {
return 0; // data
case 1:
if (field_type_) *field_type_ = t_typeid;
- return build_context.ptr_size; // id
+ return 8; // id
}
}
break;
@@ -4286,8 +4404,8 @@ gb_internal i64 type_offset_of_from_selection(Type *type, Selection sel) {
}
} else if (t->Basic.kind == Basic_any) {
switch (index) {
- case 0: t = t_type_info_ptr; break;
- case 1: t = t_rawptr; break;
+ case 0: t = t_rawptr; break;
+ case 1: t = t_typeid; break;
}
}
break;
@@ -4503,7 +4621,84 @@ gb_internal Type *alloc_type_proc_from_types(Type **param_types, unsigned param_
// return type;
// }
-gb_internal gbString write_type_to_string(gbString str, Type *type, bool shorthand=false) {
+// Index a type that is internally a struct or array.
+gb_internal Type *type_internal_index(Type *t, isize index) {
+ Type *bt = base_type(t);
+ if (bt == nullptr) {
+ return nullptr;
+ }
+
+ switch (bt->kind) {
+ case Type_Basic:
+ {
+ switch (bt->Basic.kind) {
+ case Basic_complex32: return t_f16;
+ case Basic_complex64: return t_f32;
+ case Basic_complex128: return t_f64;
+ case Basic_quaternion64: return t_f16;
+ case Basic_quaternion128: return t_f32;
+ case Basic_quaternion256: return t_f64;
+ case Basic_string:
+ {
+ GB_ASSERT(index == 0 || index == 1);
+ return index == 0 ? t_u8_ptr : t_int;
+ }
+ case Basic_any:
+ {
+ GB_ASSERT(index == 0 || index == 1);
+ return index == 0 ? t_rawptr : t_typeid;
+ }
+ }
+ }
+ break;
+
+ case Type_Array: return bt->Array.elem;
+ case Type_EnumeratedArray: return bt->EnumeratedArray.elem;
+ case Type_SimdVector: return bt->SimdVector.elem;
+ case Type_Slice:
+ {
+ GB_ASSERT(index == 0 || index == 1);
+ return index == 0 ? t_rawptr : t_typeid;
+ }
+ case Type_DynamicArray:
+ {
+ switch (index) {
+ case 0: return t_rawptr;
+ case 1: return t_int;
+ case 2: return t_int;
+ case 3: return t_allocator;
+ default: GB_PANIC("invalid raw dynamic array index");
+ };
+ }
+ case Type_Struct:
+ return get_struct_field_type(bt, index);
+ case Type_Union:
+ if (index < bt->Union.variants.count) {
+ return bt->Union.variants[index];
+ }
+ return union_tag_type(bt);
+ case Type_Tuple:
+ return bt->Tuple.variables[index]->type;
+ case Type_Matrix:
+ return bt->Matrix.elem;
+ case Type_SoaPointer:
+ {
+ GB_ASSERT(index == 0 || index == 1);
+ return index == 0 ? t_rawptr : t_int;
+ }
+ case Type_Map:
+ return type_internal_index(bt->Map.debug_metadata_type, index);
+ case Type_BitField:
+ return type_internal_index(bt->BitField.backing_type, index);
+ case Type_Generic:
+ return type_internal_index(bt->Generic.specialized, index);
+ };
+
+ GB_PANIC("Unhandled type %s", type_to_string(bt));
+ return nullptr;
+};
+
+gb_internal gbString write_type_to_string(gbString str, Type *type, bool shorthand=false, bool allow_polymorphic=false) {
if (type == nullptr) {
return gb_string_appendc(str, "<no type>");
}
@@ -4528,24 +4723,24 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
str = gb_string_append_length(str, name.text, name.len);
if (type->Generic.specialized != nullptr) {
str = gb_string_append_rune(str, '/');
- str = write_type_to_string(str, type->Generic.specialized);
+ str = write_type_to_string(str, type->Generic.specialized, shorthand, allow_polymorphic);
}
}
break;
case Type_Pointer:
str = gb_string_append_rune(str, '^');
- str = write_type_to_string(str, type->Pointer.elem);
+ str = write_type_to_string(str, type->Pointer.elem, shorthand, allow_polymorphic);
break;
case Type_SoaPointer:
str = gb_string_appendc(str, "#soa ^");
- str = write_type_to_string(str, type->SoaPointer.elem);
+ str = write_type_to_string(str, type->SoaPointer.elem, shorthand, allow_polymorphic);
break;
case Type_MultiPointer:
str = gb_string_appendc(str, "[^]");
- str = write_type_to_string(str, type->Pointer.elem);
+ str = write_type_to_string(str, type->Pointer.elem, shorthand, allow_polymorphic);
break;
case Type_EnumeratedArray:
@@ -4553,31 +4748,31 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
str = gb_string_appendc(str, "#sparse");
}
str = gb_string_append_rune(str, '[');
- str = write_type_to_string(str, type->EnumeratedArray.index);
+ str = write_type_to_string(str, type->EnumeratedArray.index, shorthand, allow_polymorphic);
str = gb_string_append_rune(str, ']');
- str = write_type_to_string(str, type->EnumeratedArray.elem);
+ str = write_type_to_string(str, type->EnumeratedArray.elem, shorthand, allow_polymorphic);
break;
case Type_Array:
- str = gb_string_appendc(str, gb_bprintf("[%d]", cast(int)type->Array.count));
- str = write_type_to_string(str, type->Array.elem);
+ str = gb_string_appendc(str, gb_bprintf("[%lld]", cast(long long)type->Array.count));
+ str = write_type_to_string(str, type->Array.elem, shorthand, allow_polymorphic);
break;
case Type_Slice:
str = gb_string_appendc(str, "[]");
- str = write_type_to_string(str, type->Array.elem);
+ str = write_type_to_string(str, type->Array.elem, shorthand, allow_polymorphic);
break;
case Type_DynamicArray:
str = gb_string_appendc(str, "[dynamic]");
- str = write_type_to_string(str, type->DynamicArray.elem);
+ str = write_type_to_string(str, type->DynamicArray.elem, shorthand, allow_polymorphic);
break;
case Type_Enum:
str = gb_string_appendc(str, "enum");
if (type->Enum.base_type != nullptr) {
str = gb_string_appendc(str, " ");
- str = write_type_to_string(str, type->Enum.base_type);
+ str = write_type_to_string(str, type->Enum.base_type, shorthand, allow_polymorphic);
}
str = gb_string_appendc(str, " {");
for_array(i, type->Enum.fields) {
@@ -4594,6 +4789,13 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
case Type_Union:
str = gb_string_appendc(str, "union");
+
+ if (allow_polymorphic && type->Struct.polymorphic_params) {
+ str = gb_string_appendc(str, "(");
+ str = write_type_to_string(str, type->Struct.polymorphic_params, shorthand, allow_polymorphic);
+ str = gb_string_appendc(str, ")");
+ }
+
switch (type->Union.kind) {
case UnionType_no_nil: str = gb_string_appendc(str, " #no_nil"); break;
case UnionType_shared_nil: str = gb_string_appendc(str, " #shared_nil"); break;
@@ -4603,7 +4805,7 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
for_array(i, type->Union.variants) {
Type *t = type->Union.variants[i];
if (i > 0) str = gb_string_appendc(str, ", ");
- str = write_type_to_string(str, t);
+ str = write_type_to_string(str, t, shorthand, allow_polymorphic);
}
str = gb_string_append_rune(str, '}');
break;
@@ -4616,17 +4818,24 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
case StructSoa_Dynamic: str = gb_string_appendc(str, "#soa[dynamic]"); break;
default: GB_PANIC("Unknown StructSoaKind"); break;
}
- str = write_type_to_string(str, type->Struct.soa_elem);
+ str = write_type_to_string(str, type->Struct.soa_elem, shorthand, allow_polymorphic);
break;
}
str = gb_string_appendc(str, "struct");
+
+ if (allow_polymorphic && type->Struct.polymorphic_params) {
+ str = gb_string_appendc(str, "(");
+ str = write_type_to_string(str, type->Struct.polymorphic_params, shorthand, allow_polymorphic);
+ str = gb_string_appendc(str, ")");
+ }
+
if (type->Struct.is_packed) str = gb_string_appendc(str, " #packed");
if (type->Struct.is_raw_union) str = gb_string_appendc(str, " #raw_union");
if (type->Struct.is_no_copy) str = gb_string_appendc(str, " #no_copy");
if (type->Struct.custom_align != 0) str = gb_string_append_fmt(str, " #align %d", cast(int)type->Struct.custom_align);
- str = gb_string_appendc(str, " {");
+ str = gb_string_appendc(str, " {");
if (shorthand && type->Struct.fields.count > 16) {
str = gb_string_append_fmt(str, "%lld fields...", cast(long long)type->Struct.fields.count);
@@ -4639,7 +4848,7 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
}
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 = write_type_to_string(str, f->type, shorthand, allow_polymorphic);
}
}
str = gb_string_append_rune(str, '}');
@@ -4647,9 +4856,9 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
case Type_Map: {
str = gb_string_appendc(str, "map[");
- str = write_type_to_string(str, type->Map.key);
+ str = write_type_to_string(str, type->Map.key, shorthand, allow_polymorphic);
str = gb_string_append_rune(str, ']');
- str = write_type_to_string(str, type->Map.value);
+ str = write_type_to_string(str, type->Map.value, shorthand, allow_polymorphic);
} break;
case Type_Named:
@@ -4679,9 +4888,11 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
str = gb_string_append_length(str, name.text, name.len);
if (!is_type_untyped(var->type)) {
str = gb_string_appendc(str, ": ");
- str = write_type_to_string(str, var->type);
- str = gb_string_appendc(str, " = ");
- str = write_exact_value_to_string(str, var->Constant.value);
+ str = write_type_to_string(str, var->type, shorthand, allow_polymorphic);
+ if (var->Constant.value.kind) {
+ str = gb_string_appendc(str, " = ");
+ str = write_exact_value_to_string(str, var->Constant.value);
+ }
} else {
str = gb_string_appendc(str, " := ");
str = write_exact_value_to_string(str, var->Constant.value);
@@ -4697,20 +4908,31 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
Type *slice = base_type(var->type);
str = gb_string_appendc(str, "..");
GB_ASSERT(var->type->kind == Type_Slice);
- str = write_type_to_string(str, slice->Slice.elem);
+ str = write_type_to_string(str, slice->Slice.elem, shorthand, allow_polymorphic);
} else {
- str = write_type_to_string(str, var->type);
+ str = write_type_to_string(str, var->type, shorthand, allow_polymorphic);
}
} else {
GB_ASSERT(var->kind == Entity_TypeName);
if (var->type->kind == Type_Generic) {
- str = gb_string_appendc(str, "typeid/");
- str = write_type_to_string(str, var->type);
+ if (var->token.string.len != 0) {
+ String name = var->token.string;
+ str = gb_string_appendc(str, "$");
+ str = gb_string_append_length(str, name.text, name.len);
+ str = gb_string_appendc(str, ": typeid");
+ if (var->type->Generic.specialized) {
+ str = gb_string_appendc(str, "/");
+ str = write_type_to_string(str, var->type->Generic.specialized, shorthand, allow_polymorphic);
+ }
+ } else {
+ str = gb_string_appendc(str, "typeid/");
+ str = write_type_to_string(str, var->type, shorthand, allow_polymorphic);
+ }
} else {
str = gb_string_appendc(str, "$");
str = gb_string_append_length(str, name.text, name.len);
str = gb_string_appendc(str, "=");
- str = write_type_to_string(str, var->type);
+ str = write_type_to_string(str, var->type, shorthand, allow_polymorphic);
}
}
}
@@ -4732,10 +4954,10 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
}
break;
case ProcCC_CDecl:
- str = gb_string_appendc(str, " \"cdecl\" ");
+ str = gb_string_appendc(str, " \"c\" ");
break;
case ProcCC_StdCall:
- str = gb_string_appendc(str, " \"stdcall\" ");
+ str = gb_string_appendc(str, " \"std\" ");
break;
case ProcCC_FastCall:
str = gb_string_appendc(str, " \"fastcall\" ");
@@ -4756,7 +4978,7 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
}
str = gb_string_appendc(str, "(");
if (type->Proc.params) {
- str = write_type_to_string(str, type->Proc.params);
+ str = write_type_to_string(str, type->Proc.params, shorthand, allow_polymorphic);
}
str = gb_string_appendc(str, ")");
if (type->Proc.results) {
@@ -4764,7 +4986,7 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
if (type->Proc.results->Tuple.variables.count > 1) {
str = gb_string_appendc(str, "(");
}
- str = write_type_to_string(str, type->Proc.results);
+ str = write_type_to_string(str, type->Proc.results, shorthand, allow_polymorphic);
if (type->Proc.results->Tuple.variables.count > 1) {
str = gb_string_appendc(str, ")");
}
@@ -4773,8 +4995,10 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
case Type_BitSet:
str = gb_string_appendc(str, "bit_set[");
- if (is_type_enum(type->BitSet.elem)) {
- str = write_type_to_string(str, type->BitSet.elem);
+ if (type->BitSet.elem == nullptr) {
+ str = gb_string_appendc(str, "<unresolved>");
+ } else if (is_type_enum(type->BitSet.elem)) {
+ str = write_type_to_string(str, type->BitSet.elem, shorthand, allow_polymorphic);
} else {
str = gb_string_append_fmt(str, "%lld", type->BitSet.lower);
str = gb_string_append_fmt(str, "..=");
@@ -4782,27 +5006,27 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
}
if (type->BitSet.underlying != nullptr) {
str = gb_string_appendc(str, "; ");
- str = write_type_to_string(str, type->BitSet.underlying);
+ str = write_type_to_string(str, type->BitSet.underlying, shorthand, allow_polymorphic);
}
str = gb_string_appendc(str, "]");
break;
case Type_SimdVector:
str = gb_string_append_fmt(str, "#simd[%d]", cast(int)type->SimdVector.count);
- str = write_type_to_string(str, type->SimdVector.elem);
+ str = write_type_to_string(str, type->SimdVector.elem, shorthand, allow_polymorphic);
break;
-
+
case Type_Matrix:
if (type->Matrix.is_row_major) {
str = gb_string_appendc(str, "#row_major ");
}
str = gb_string_appendc(str, gb_bprintf("matrix[%d, %d]", cast(int)type->Matrix.row_count, cast(int)type->Matrix.column_count));
- str = write_type_to_string(str, type->Matrix.elem);
+ str = write_type_to_string(str, type->Matrix.elem, shorthand, allow_polymorphic);
break;
case Type_BitField:
str = gb_string_appendc(str, "bit_field ");
- str = write_type_to_string(str, type->BitField.backing_type);
+ str = write_type_to_string(str, type->BitField.backing_type, shorthand, allow_polymorphic);
str = gb_string_appendc(str, " {");
for (isize i = 0; i < type->BitField.fields.count; i++) {
Entity *f = type->BitField.fields[i];
@@ -4811,7 +5035,7 @@ gb_internal gbString write_type_to_string(gbString str, Type *type, bool shortha
}
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 = write_type_to_string(str, f->type, shorthand, allow_polymorphic);
str = gb_string_append_fmt(str, " | %u", type->BitField.bit_sizes[i]);
}
str = gb_string_appendc(str, " }");
@@ -4829,9 +5053,11 @@ gb_internal gbString type_to_string(Type *type, bool shorthand) {
return write_type_to_string(gb_string_make(heap_allocator(), ""), type, shorthand);
}
-gb_internal gbString type_to_string_shorthand(Type *type) {
- return type_to_string(type, true);
+gb_internal gbString type_to_string_polymorphic(Type *type) {
+ return write_type_to_string(gb_string_make(heap_allocator(), ""), type, false, true);
}
-
+gb_internal gbString type_to_string_shorthand(Type *type) {
+ return type_to_string(type, true);
+}