aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2019-10-10 21:39:46 +0100
committergingerBill <bill@gingerbill.org>2019-10-10 21:39:46 +0100
commit39b3c8c80fa65ce91174659c5155b5e51512e8c1 (patch)
tree401041f787eda46d10269e7fe7fdc31be48cc277 /src
parent31391519353ba65e032cf6681d056cc7401557e3 (diff)
Update System V ABI to for more Odin types
Diffstat (limited to 'src')
-rw-r--r--src/check_type.cpp248
1 files changed, 136 insertions, 112 deletions
diff --git a/src/check_type.cpp b/src/check_type.cpp
index 0d9722ad8..917682f33 100644
--- a/src/check_type.cpp
+++ b/src/check_type.cpp
@@ -1838,108 +1838,109 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_results) {
}
Array<Type *> systemv_distribute_struct_fields(Type *t) {
- t = base_type(t);
- GB_ASSERT_MSG(t->kind == Type_Struct, "%s", type_to_string(t));
- TypeStruct *ts = &t->Struct;
+ Type *bt = core_type(t);
- auto distributed = array_make<Type *>(heap_allocator(), 0, ts->fields.count);
- for_array(field_index, ts->fields) {
- Entity *f = ts->fields[field_index];
- Type *bt = core_type(f->type);
- switch (bt->kind) {
- case Type_Basic:
- switch (bt->Basic.kind){
- case Basic_complex64:
- array_add(&distributed, t_f32);
- array_add(&distributed, t_f32);
- break;
- case Basic_complex128:
- array_add(&distributed, t_f64);
- array_add(&distributed, t_f64);
- break;
- case Basic_quaternion128:
- array_add(&distributed, t_f32);
- array_add(&distributed, t_f32);
- array_add(&distributed, t_f32);
- array_add(&distributed, t_f32);
- break;
- case Basic_quaternion256:
- goto DEFAULT;
- case Basic_string:
- array_add(&distributed, t_u8_ptr);
- array_add(&distributed, t_int);
- break;
- case Basic_any:
- GB_ASSERT(type_size_of(t_uintptr) == type_size_of(t_typeid));
- array_add(&distributed, t_rawptr);
- array_add(&distributed, t_uintptr);
- break;
+ isize distributed_cap = 1;
+ if (bt->kind == Type_Struct) {
+ distributed_cap = bt->Struct.fields.count;
+ }
+ auto distributed = array_make<Type *>(heap_allocator(), 0, distributed_cap);
- case Basic_u128:
- case Basic_i128:
- if (build_context.ODIN_OS == "windows") {
- array_add(&distributed, alloc_type_simd_vector(2, t_u64));
- } else {
- array_add(&distributed, bt);
- }
- break;
- default:
- goto DEFAULT;
- }
+ switch (bt->kind) {
+ case Type_Basic:
+ switch (bt->Basic.kind){
+ case Basic_complex64:
+ array_add(&distributed, t_f32);
+ array_add(&distributed, t_f32);
+ break;
+ case Basic_complex128:
+ array_add(&distributed, t_f64);
+ array_add(&distributed, t_f64);
+ break;
+ case Basic_quaternion128:
+ array_add(&distributed, t_f32);
+ array_add(&distributed, t_f32);
+ array_add(&distributed, t_f32);
+ array_add(&distributed, t_f32);
+ break;
+ case Basic_quaternion256:
+ goto DEFAULT;
+ case Basic_string:
+ array_add(&distributed, t_u8_ptr);
+ array_add(&distributed, t_int);
+ break;
+ case Basic_any:
+ GB_ASSERT(type_size_of(t_uintptr) == type_size_of(t_typeid));
+ array_add(&distributed, t_rawptr);
+ array_add(&distributed, t_uintptr);
break;
- case Type_Struct:
- if (bt->Struct.is_raw_union) {
- goto DEFAULT;
+ case Basic_u128:
+ case Basic_i128:
+ if (build_context.ODIN_OS == "windows") {
+ array_add(&distributed, alloc_type_simd_vector(2, t_u64));
} else {
- // IMPORTANT TOOD(bill): handle #packed structs correctly
- // IMPORTANT TODO(bill): handle #align structs correctly
- auto nested = systemv_distribute_struct_fields(f->type);
- for_array(i, nested) {
- array_add(&distributed, nested[i]);
- }
- array_free(&nested);
+ array_add(&distributed, bt);
}
break;
- case Type_Array:
- for (i64 i = 0; i < bt->Array.count; i++) {
- array_add(&distributed, bt->Array.elem);
+ default:
+ goto DEFAULT;
+ }
+ break;
+
+ case Type_Struct:
+ if (bt->Struct.is_raw_union) {
+ goto DEFAULT;
+ } else {
+ // IMPORTANT TOOD(bill): handle #packed structs correctly
+ // IMPORTANT TODO(bill): handle #align structs correctly
+ for_array(field_index, bt->Struct.fields) {
+ Entity *f = bt->Struct.fields[field_index];
+ auto nested = systemv_distribute_struct_fields(f->type);
+ array_add_elems(&distributed, nested.data, nested.count);
+ array_free(&nested);
}
- break;
+ }
+ break;
- case Type_BitSet:
- array_add(&distributed, bit_set_to_int(bt));
- break;
+ case Type_Array:
+ for (i64 i = 0; i < bt->Array.count; i++) {
+ array_add(&distributed, bt->Array.elem);
+ }
+ break;
- case Type_Tuple:
- GB_PANIC("Invalid struct field type");
- break;
+ case Type_BitSet:
+ array_add(&distributed, bit_set_to_int(bt));
+ break;
- case Type_Slice:
- array_add(&distributed, t_rawptr);
- array_add(&distributed, t_int);
- break;
+ case Type_Tuple:
+ GB_PANIC("Invalid struct field type");
+ break;
- case Type_DynamicArray:
- case Type_Map:
- case Type_Union:
- case Type_BitField: // TODO(bill): Ignore?
- // NOTE(bill, 2019-10-10): Odin specific, don't worry about C calling convention yet
- goto DEFAULT;
+ case Type_Slice:
+ array_add(&distributed, t_rawptr);
+ array_add(&distributed, t_int);
+ break;
- case Type_Pointer:
- case Type_Proc:
- case Type_SimdVector: // TODO(bill): Is this correct logic?
- default:
- DEFAULT:;
- if (type_size_of(bt) > 0) {
- array_add(&distributed, bt);
- }
- break;
+ case Type_DynamicArray:
+ case Type_Map:
+ case Type_Union:
+ case Type_BitField: // TODO(bill): Ignore?
+ // NOTE(bill, 2019-10-10): Odin specific, don't worry about C calling convention yet
+ goto DEFAULT;
+
+ case Type_Pointer:
+ case Type_Proc:
+ case Type_SimdVector: // TODO(bill): Is this correct logic?
+ default:
+ DEFAULT:;
+ if (type_size_of(bt) > 0) {
+ array_add(&distributed, bt);
}
+ break;
}
return distributed;
@@ -2002,11 +2003,48 @@ Type *handle_single_distributed_type_parameter(Array<Type *> const &types, bool
}
Type *handle_struct_system_v_amd64_abi_type(Type *t) {
- GB_ASSERT(is_type_struct(t));
+ Type *original_type = t;
Type *bt = core_type(t);
+ t = base_type(t);
i64 size = type_size_of(bt);
- if (!bt->Struct.is_raw_union) {
+ switch (t->kind) {
+ case Type_Array:
+ case Type_Slice:
+ case Type_DynamicArray:
+ case Type_Struct:
+ break;
+
+ case Type_Basic:
+ switch (bt->Basic.kind) {
+ case Basic_string:
+ case Basic_any:
+ case Basic_complex64:
+ case Basic_complex128:
+ case Basic_quaternion128:
+ break;
+ }
+ return original_type;
+ case Type_Pointer:
+ case Type_Map:
+ case Type_Union:
+ case Type_Enum:
+ case Type_Proc:
+ case Type_BitField:
+ case Type_BitSet:
+ case Type_SimdVector:
+ return original_type;
+ }
+
+ bool is_packed = false;
+ if (is_type_struct(bt)) {
+ is_packed = bt->Struct.is_packed;
+ }
+
+ if (is_type_raw_union(bt)) {
+ // TODO(bill): Handle raw union correctly for
+ return t;
+ } else {
auto field_types = systemv_distribute_struct_fields(bt);
defer (array_free(&field_types));
@@ -2015,21 +2053,21 @@ Type *handle_struct_system_v_amd64_abi_type(Type *t) {
Type *final_type = nullptr;
if (field_types.count == 0) {
- // Do nothing
+ return t;
} else if (field_types.count == 1) {
final_type = field_types[0];
} else {
if (size <= 8) {
isize offset = 0;
- final_type = handle_single_distributed_type_parameter(field_types, bt->Struct.is_packed, &offset);
+ final_type = handle_single_distributed_type_parameter(field_types, is_packed, &offset);
} else {
isize offset = 0;
isize next_offset = 0;
Type *two_types[2] = {};
- two_types[0] = handle_single_distributed_type_parameter(field_types, bt->Struct.is_packed, &offset);
+ two_types[0] = handle_single_distributed_type_parameter(field_types, is_packed, &offset);
auto remaining = array_slice(field_types, offset, field_types.count);
- two_types[1] = handle_single_distributed_type_parameter(remaining, bt->Struct.is_packed, &next_offset);
+ two_types[1] = handle_single_distributed_type_parameter(remaining, is_packed, &next_offset);
GB_ASSERT(offset + next_offset == field_types.count);
auto variables = array_make<Entity *>(heap_allocator(), 2);
@@ -2040,8 +2078,6 @@ Type *handle_struct_system_v_amd64_abi_type(Type *t) {
}
}
return final_type;
- } else {
- return t;
}
}
@@ -2141,29 +2177,17 @@ Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type, ProcCall
case Type_Pointer: break;
case Type_Proc: break; // NOTE(bill): Just a pointer
- // Odin specific
- case Type_Slice:
- case Type_Array:
- case Type_DynamicArray:
- case Type_Map:
- case Type_Union:
- // Could be in C too
- case Type_Struct: {
- i64 align = type_align_of(original_type);
- i64 size = type_size_of(original_type);
+ default: {
+ i64 size = type_size_of(original_type);
if (size > 16) {
new_type = alloc_type_pointer(original_type);
} else if (build_context.ODIN_ARCH == "amd64") {
- if (is_type_struct(bt)) {
- // NOTE(bill): System V AMD64 ABI
- if (bt->Struct.is_raw_union) {
- // TODO(bill): Handle raw union correctly for
- break;
- }
-
- new_type = handle_struct_system_v_amd64_abi_type(bt);
- return new_type;
+ // NOTE(bill): System V AMD64 ABI
+ new_type = handle_struct_system_v_amd64_abi_type(bt);
+ if (are_types_identical(core_type(original_type), new_type)) {
+ new_type = original_type;
}
+ return new_type;
}
break;