Update System V ABI to for more Odin types

This commit is contained in:
gingerBill
2019-10-10 21:39:46 +01:00
parent 3139151935
commit 39b3c8c80f
+59 -35
View File
@@ -1838,15 +1838,16 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_results) {
} }
Array<Type *> systemv_distribute_struct_fields(Type *t) { Array<Type *> systemv_distribute_struct_fields(Type *t) {
t = base_type(t); Type *bt = core_type(t);
GB_ASSERT_MSG(t->kind == Type_Struct, "%s", type_to_string(t));
TypeStruct *ts = &t->Struct;
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);
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) { switch (bt->kind) {
case Type_Basic: case Type_Basic:
switch (bt->Basic.kind){ switch (bt->Basic.kind){
@@ -1896,12 +1897,13 @@ Array<Type *> systemv_distribute_struct_fields(Type *t) {
} else { } else {
// IMPORTANT TOOD(bill): handle #packed structs correctly // IMPORTANT TOOD(bill): handle #packed structs correctly
// IMPORTANT TODO(bill): handle #align 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); auto nested = systemv_distribute_struct_fields(f->type);
for_array(i, nested) { array_add_elems(&distributed, nested.data, nested.count);
array_add(&distributed, nested[i]);
}
array_free(&nested); array_free(&nested);
} }
}
break; break;
case Type_Array: case Type_Array:
@@ -1940,7 +1942,6 @@ Array<Type *> systemv_distribute_struct_fields(Type *t) {
} }
break; break;
} }
}
return distributed; 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) { 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); Type *bt = core_type(t);
t = base_type(t);
i64 size = type_size_of(bt); 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); auto field_types = systemv_distribute_struct_fields(bt);
defer (array_free(&field_types)); defer (array_free(&field_types));
@@ -2015,21 +2053,21 @@ Type *handle_struct_system_v_amd64_abi_type(Type *t) {
Type *final_type = nullptr; Type *final_type = nullptr;
if (field_types.count == 0) { if (field_types.count == 0) {
// Do nothing return t;
} else if (field_types.count == 1) { } else if (field_types.count == 1) {
final_type = field_types[0]; final_type = field_types[0];
} else { } else {
if (size <= 8) { if (size <= 8) {
isize offset = 0; 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 { } else {
isize offset = 0; isize offset = 0;
isize next_offset = 0; isize next_offset = 0;
Type *two_types[2] = {}; 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); 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); GB_ASSERT(offset + next_offset == field_types.count);
auto variables = array_make<Entity *>(heap_allocator(), 2); 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; 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_Pointer: break;
case Type_Proc: break; // NOTE(bill): Just a pointer case Type_Proc: break; // NOTE(bill): Just a pointer
// Odin specific default: {
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); i64 size = type_size_of(original_type);
if (size > 16) { if (size > 16) {
new_type = alloc_type_pointer(original_type); new_type = alloc_type_pointer(original_type);
} else if (build_context.ODIN_ARCH == "amd64") { } else if (build_context.ODIN_ARCH == "amd64") {
if (is_type_struct(bt)) {
// NOTE(bill): System V AMD64 ABI // 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); new_type = handle_struct_system_v_amd64_abi_type(bt);
return new_type; if (are_types_identical(core_type(original_type), new_type)) {
new_type = original_type;
} }
return new_type;
} }
break; break;