|
@@ -1162,9 +1162,6 @@ Type *determine_type_from_polymorphic(CheckerContext *ctx, Type *poly_type, Oper
|
|
|
}
|
|
|
|
|
|
if (is_polymorphic_type_assignable(ctx, poly_type, operand.type, false, modify_type)) {
|
|
|
- if (show_error) {
|
|
|
- set_procedure_abi_types(poly_type);
|
|
|
- }
|
|
|
return poly_type;
|
|
|
}
|
|
|
if (show_error) {
|
|
@@ -1767,623 +1764,8 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_results) {
|
|
|
return tuple;
|
|
|
}
|
|
|
|
|
|
-Array<Type *> systemv_distribute_struct_fields(Type *t) {
|
|
|
- Type *bt = core_type(t);
|
|
|
-
|
|
|
-
|
|
|
- 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);
|
|
|
-
|
|
|
- i64 sz = type_size_of(bt);
|
|
|
- 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 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;
|
|
|
- }
|
|
|
- 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;
|
|
|
-
|
|
|
- case Type_Array:
|
|
|
- for (i64 i = 0; i < bt->Array.count; i++) {
|
|
|
- array_add(&distributed, bt->Array.elem);
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- case Type_BitSet:
|
|
|
- array_add(&distributed, bit_set_to_int(bt));
|
|
|
- break;
|
|
|
-
|
|
|
- case Type_Tuple:
|
|
|
- GB_PANIC("Invalid struct field type");
|
|
|
- break;
|
|
|
-
|
|
|
- case Type_Slice:
|
|
|
- array_add(&distributed, t_rawptr);
|
|
|
- array_add(&distributed, t_int);
|
|
|
- break;
|
|
|
-
|
|
|
- case Type_Union:
|
|
|
- case Type_DynamicArray:
|
|
|
- case Type_Map:
|
|
|
- // 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 (sz > 0) {
|
|
|
- array_add(&distributed, bt);
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- return distributed;
|
|
|
-}
|
|
|
-
|
|
|
-Type *struct_type_from_systemv_distribute_struct_fields(Type *abi_type) {
|
|
|
- GB_ASSERT(is_type_tuple(abi_type));
|
|
|
- Type *final_type = alloc_type_struct();
|
|
|
- final_type->Struct.fields = abi_type->Tuple.variables;
|
|
|
- return final_type;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-Type *handle_single_distributed_type_parameter(Array<Type *> const &types, bool packed, isize *offset) {
|
|
|
- GB_ASSERT(types.count > 0);
|
|
|
-
|
|
|
- if (types.count == 1) {
|
|
|
- if (offset) *offset = 1;
|
|
|
-
|
|
|
- i64 sz = type_size_of(types[0]);
|
|
|
-
|
|
|
- if (is_type_float(types[0])) {
|
|
|
- return types[0];
|
|
|
- }
|
|
|
- switch (sz) {
|
|
|
- case 0:
|
|
|
- GB_PANIC("Zero sized type found!");
|
|
|
- case 1: return t_u8;
|
|
|
- case 2: return t_u16;
|
|
|
- case 4: return t_u32;
|
|
|
- case 8: return t_u64;
|
|
|
- default:
|
|
|
- return types[0];
|
|
|
- }
|
|
|
- } else if (types.count >= 2) {
|
|
|
- if (types[0] == t_f32 && types[1] == t_f32) {
|
|
|
- if (offset) *offset = 2;
|
|
|
- return alloc_type_simd_vector(2, t_f32);
|
|
|
- } else if (type_size_of(types[0]) == 8) {
|
|
|
- if (offset) *offset = 1;
|
|
|
- return types[0];
|
|
|
- }
|
|
|
-
|
|
|
- i64 total_size = 0;
|
|
|
- isize i = 0;
|
|
|
- if (packed) {
|
|
|
- for (; i < types.count && total_size < 8; i += 1) {
|
|
|
- Type *t = types[i];
|
|
|
- i64 s = type_size_of(t);
|
|
|
- total_size += s;
|
|
|
- }
|
|
|
- } else {
|
|
|
- for (; i < types.count && total_size < 8; i += 1) {
|
|
|
- Type *t = types[i];
|
|
|
- i64 s = gb_max(type_size_of(t), 0);
|
|
|
- i64 a = gb_max(type_align_of(t), 1);
|
|
|
- isize ts = align_formula(total_size, a);
|
|
|
- if (ts >= 8) {
|
|
|
- break;
|
|
|
- }
|
|
|
- total_size = ts + s;
|
|
|
- }
|
|
|
- }
|
|
|
- if (offset) *offset = i;
|
|
|
- switch (total_size) {
|
|
|
- case 1: return t_u8;
|
|
|
- case 2: return t_u16;
|
|
|
- case 4: return t_u32;
|
|
|
- case 8: return t_u64;
|
|
|
- }
|
|
|
- return t_u64;
|
|
|
- }
|
|
|
-
|
|
|
- return nullptr;
|
|
|
-}
|
|
|
-
|
|
|
-Type *handle_struct_system_v_amd64_abi_type(Type *t) {
|
|
|
- if (type_size_of(t) > 16) {
|
|
|
- return alloc_type_pointer(t);
|
|
|
- }
|
|
|
- Type *original_type = t;
|
|
|
- Type *bt = core_type(t);
|
|
|
- t = base_type(t);
|
|
|
- i64 size = type_size_of(bt);
|
|
|
-
|
|
|
- switch (t->kind) {
|
|
|
- case Type_Slice:
|
|
|
- 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;
|
|
|
- default:
|
|
|
- return original_type;
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- 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));
|
|
|
-
|
|
|
- GB_ASSERT(field_types.count <= 16);
|
|
|
-
|
|
|
- Type *final_type = nullptr;
|
|
|
-
|
|
|
- if (field_types.count == 0) {
|
|
|
- final_type = 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, 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, is_packed, &offset);
|
|
|
- auto remaining = array_slice(field_types, offset, field_types.count);
|
|
|
- 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);
|
|
|
- variables[0] = alloc_entity_param(nullptr, empty_token, two_types[0], false, false);
|
|
|
- variables[1] = alloc_entity_param(nullptr, empty_token, two_types[1], false, false);
|
|
|
- final_type = alloc_type_tuple();
|
|
|
- final_type->Tuple.variables = variables;
|
|
|
- if (t->kind == Type_Struct) {
|
|
|
- // NOTE(bill): Make this packed
|
|
|
- final_type->Tuple.is_packed = t->Struct.is_packed;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- GB_ASSERT(final_type != nullptr);
|
|
|
- i64 ftsz = type_size_of(final_type);
|
|
|
- i64 otsz = type_size_of(original_type);
|
|
|
- if (ftsz != otsz) {
|
|
|
- // TODO(bill): Handle this case which will be caused by #packed most likely
|
|
|
- switch (otsz) {
|
|
|
- case 1:
|
|
|
- case 2:
|
|
|
- case 4:
|
|
|
- case 8:
|
|
|
- GB_PANIC("Incorrectly handled case for handle_struct_system_v_amd64_abi_type, %s %lld vs %s %lld", type_to_string(final_type), ftsz, type_to_string(original_type), otsz);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return final_type;
|
|
|
- }
|
|
|
-}
|
|
|
|
|
|
-Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type, ProcCallingConvention cc) {
|
|
|
- Type *new_type = original_type;
|
|
|
|
|
|
- if (is_type_boolean(original_type)) {
|
|
|
- Type *t = core_type(base_type(new_type));
|
|
|
- if (t == t_bool) {
|
|
|
- return t_llvm_bool;
|
|
|
- }
|
|
|
- return new_type;
|
|
|
- }
|
|
|
-
|
|
|
- if (is_type_proc(original_type)) {
|
|
|
- // NOTE(bill): Force a cast to prevent a possible type cycle
|
|
|
- return t_rawptr;
|
|
|
- }
|
|
|
-
|
|
|
- if (is_calling_convention_none(cc)) {
|
|
|
- return new_type;
|
|
|
- }
|
|
|
-
|
|
|
- if (build_context.ODIN_ARCH == "386") {
|
|
|
- return new_type;
|
|
|
- }
|
|
|
-
|
|
|
- if (is_type_simd_vector(original_type)) {
|
|
|
- return new_type;
|
|
|
- }
|
|
|
- if (build_context.ODIN_ARCH == "amd64") {
|
|
|
- bool is_128 = is_type_integer_128bit(original_type);
|
|
|
- if (!is_128 && is_type_bit_set(original_type) && type_size_of(original_type) == 16) {
|
|
|
- // is_128 = true;
|
|
|
- }
|
|
|
- if (is_128) {
|
|
|
- if (build_context.ODIN_OS == "windows") {
|
|
|
- return alloc_type_simd_vector(2, t_u64);
|
|
|
- } else {
|
|
|
- return original_type;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (build_context.ODIN_OS == "windows") {
|
|
|
- // NOTE(bill): Changing the passing parameter value type is to match C's ABI
|
|
|
- // IMPORTANT TODO(bill): This only matches the ABI on MSVC at the moment
|
|
|
- // SEE: https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
|
|
|
-
|
|
|
-
|
|
|
- Type *bt = core_type(original_type);
|
|
|
- switch (bt->kind) {
|
|
|
- // Okay to pass by value (usually)
|
|
|
- // Especially the only Odin types
|
|
|
- case Type_Basic: {
|
|
|
- i64 sz = bt->Basic.size;
|
|
|
- // if (sz > 8 && build_context.word_size < 8) {
|
|
|
- if (sz > 8) {
|
|
|
- new_type = alloc_type_pointer(original_type);
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- case Type_Pointer:
|
|
|
- if (is_type_struct(bt->Pointer.elem)) {
|
|
|
- // Force to a raw pointer
|
|
|
- new_type = t_rawptr;
|
|
|
- }
|
|
|
- break;
|
|
|
- case Type_Proc:
|
|
|
- new_type = t_rawptr;
|
|
|
- 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);
|
|
|
-
|
|
|
- switch (8*size) {
|
|
|
- case 8: new_type = t_u8; break;
|
|
|
- case 16: new_type = t_u16; break;
|
|
|
- case 32: new_type = t_u32; break;
|
|
|
- case 64: new_type = t_u64; break;
|
|
|
- default:
|
|
|
- new_type = alloc_type_pointer(original_type);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- } else if (build_context.ODIN_OS == "linux" ||
|
|
|
- build_context.ODIN_OS == "darwin") {
|
|
|
- Type *bt = core_type(original_type);
|
|
|
- switch (bt->kind) {
|
|
|
- // Okay to pass by value (usually)
|
|
|
- // Especially the only Odin types
|
|
|
- case Type_Basic: {
|
|
|
- i64 sz = bt->Basic.size;
|
|
|
- // if (sz > 8 && build_context.word_size < 8) {
|
|
|
- if (sz > 8) {
|
|
|
- new_type = alloc_type_pointer(original_type);
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
- }
|
|
|
- case Type_Pointer: break;
|
|
|
- case Type_Proc: break; // NOTE(bill): Just a pointer
|
|
|
-
|
|
|
- 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") {
|
|
|
- // 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;
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- // IMPORTANT TODO(bill): figure out the ABI settings for Linux, OSX etc. for
|
|
|
- // their architectures
|
|
|
- }
|
|
|
-
|
|
|
- return new_type;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type, ProcCallingConvention cc) {
|
|
|
- Type *new_type = original_type;
|
|
|
- if (new_type == nullptr) {
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
- GB_ASSERT(is_type_tuple(original_type));
|
|
|
-
|
|
|
- Type *single_type = reduce_tuple_to_single_type(original_type);
|
|
|
-
|
|
|
- if (cc == ProcCC_InlineAsm) {
|
|
|
- return new_type;
|
|
|
- }
|
|
|
-
|
|
|
- if (is_type_proc(single_type)) {
|
|
|
- // NOTE(bill): Force a cast to prevent a possible type cycle
|
|
|
- return t_rawptr;
|
|
|
- }
|
|
|
-
|
|
|
- if (is_type_simd_vector(single_type)) {
|
|
|
- return new_type;
|
|
|
- }
|
|
|
-
|
|
|
- if (is_type_pointer(single_type)) {
|
|
|
- // NOTE(bill): Force a cast to prevent a possible type cycle
|
|
|
- return t_rawptr;
|
|
|
- }
|
|
|
-
|
|
|
- if (build_context.ODIN_OS == "windows") {
|
|
|
- if (build_context.ODIN_ARCH == "amd64") {
|
|
|
- if (is_type_integer_128bit(single_type)) {
|
|
|
- if (is_calling_convention_none(cc)) {
|
|
|
- return original_type;
|
|
|
- } else {
|
|
|
- return alloc_type_simd_vector(2, t_u64);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- Type *bt = core_type(reduce_tuple_to_single_type(original_type));
|
|
|
- // NOTE(bill): This is just reversed engineered from LLVM IR output
|
|
|
- switch (bt->kind) {
|
|
|
- // Okay to pass by value
|
|
|
- // Especially the only Odin types
|
|
|
- case Type_Pointer: break;
|
|
|
- case Type_Proc: break; // NOTE(bill): Just a pointer
|
|
|
- case Type_Basic: break;
|
|
|
-
|
|
|
-
|
|
|
- default: {
|
|
|
- i64 align = type_align_of(original_type);
|
|
|
- i64 size = type_size_of(original_type);
|
|
|
- switch (8*size) {
|
|
|
-#if 1
|
|
|
- case 8: new_type = t_u8; break;
|
|
|
- case 16: new_type = t_u16; break;
|
|
|
- case 32: new_type = t_u32; break;
|
|
|
- case 64: new_type = t_u64; break;
|
|
|
-#endif
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- } else if (build_context.ODIN_OS == "linux" || build_context.ODIN_OS == "darwin") {
|
|
|
- if (build_context.ODIN_ARCH == "amd64") {
|
|
|
-
|
|
|
- }
|
|
|
- } else {
|
|
|
- // IMPORTANT TODO(bill): figure out the ABI settings for Linux, OSX etc. for
|
|
|
- // their architectures
|
|
|
- }
|
|
|
-
|
|
|
- if (is_type_integer_128bit(single_type)) {
|
|
|
- if (build_context.word_size == 8) {
|
|
|
- return original_type;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if (new_type != original_type) {
|
|
|
- Type *tuple = alloc_type_tuple();
|
|
|
- auto variables = array_make<Entity *>(a, 0, 1);
|
|
|
- array_add(&variables, alloc_entity_param(original_type->Tuple.variables[0]->scope, empty_token, new_type, false, false));
|
|
|
- tuple->Tuple.variables = variables;
|
|
|
- new_type = tuple;
|
|
|
- }
|
|
|
-
|
|
|
- if (cc == ProcCC_None) {
|
|
|
- for_array(i, new_type->Tuple.variables) {
|
|
|
- Type **tp = &new_type->Tuple.variables[i]->type;
|
|
|
- Type *t = core_type(*tp);
|
|
|
- if (t == t_bool) {
|
|
|
- *tp = t_llvm_bool;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- new_type->cached_size = -1;
|
|
|
- new_type->cached_align = -1;
|
|
|
- return new_type;
|
|
|
-}
|
|
|
-
|
|
|
-bool abi_compat_return_by_pointer(gbAllocator a, ProcCallingConvention cc, Type *abi_return_type) {
|
|
|
- if (abi_return_type == nullptr) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- if (is_calling_convention_none(cc)) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- Type *single_type = reduce_tuple_to_single_type(abi_return_type);
|
|
|
-
|
|
|
- if (is_type_simd_vector(single_type)) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (build_context.word_size == 8) {
|
|
|
- if (is_type_integer_128bit(single_type)) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (build_context.ODIN_OS == "windows" || build_context.ODIN_OS == "linux" ) {
|
|
|
- i64 size = 8*type_size_of(abi_return_type);
|
|
|
- switch (size) {
|
|
|
- case 0:
|
|
|
- case 8:
|
|
|
- case 16:
|
|
|
- case 32:
|
|
|
- case 64:
|
|
|
- return false;
|
|
|
- default:
|
|
|
- return true;
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (is_type_integer_128bit(single_type)) {
|
|
|
- return build_context.word_size < 8;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-void set_procedure_abi_types(Type *type) {
|
|
|
- type = base_type(type);
|
|
|
- if (type->kind != Type_Proc) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (type->Proc.abi_types_set || type->flags & TypeFlag_InProcessOfCheckingABI) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- gbAllocator allocator = permanent_allocator();
|
|
|
-
|
|
|
- u32 flags = type->flags;
|
|
|
- type->flags |= TypeFlag_InProcessOfCheckingABI;
|
|
|
-
|
|
|
- type->Proc.abi_compat_params = array_make<Type *>(allocator, cast(isize)type->Proc.param_count);
|
|
|
- for (i32 i = 0; i < type->Proc.param_count; i++) {
|
|
|
- Entity *e = type->Proc.params->Tuple.variables[i];
|
|
|
- if (e->kind == Entity_Variable) {
|
|
|
- Type *original_type = e->type;
|
|
|
- Type *new_type = type_to_abi_compat_param_type(allocator, original_type, type->Proc.calling_convention);
|
|
|
- type->Proc.abi_compat_params[i] = new_type;
|
|
|
- switch (type->Proc.calling_convention) {
|
|
|
- case ProcCC_Odin:
|
|
|
- case ProcCC_Contextless:
|
|
|
- if (is_type_pointer(new_type) && !is_type_pointer(e->type) && !is_type_proc(e->type)) {
|
|
|
- e->flags |= EntityFlag_ImplicitReference;
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- if (build_context.ODIN_OS == "linux" ||
|
|
|
- build_context.ODIN_OS == "darwin") {
|
|
|
- if (is_type_pointer(new_type) & !is_type_pointer(e->type) && !is_type_proc(e->type)) {
|
|
|
- e->flags |= EntityFlag_ByVal;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- for (i32 i = 0; i < type->Proc.param_count; i++) {
|
|
|
- Entity *e = type->Proc.params->Tuple.variables[i];
|
|
|
- if (e->kind == Entity_Variable) {
|
|
|
- set_procedure_abi_types(e->type);
|
|
|
- }
|
|
|
- }
|
|
|
- for (i32 i = 0; i < type->Proc.result_count; i++) {
|
|
|
- Entity *e = type->Proc.results->Tuple.variables[i];
|
|
|
- if (e->kind == Entity_Variable) {
|
|
|
- set_procedure_abi_types(e->type);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // NOTE(bill): The types are the same
|
|
|
- type->Proc.abi_compat_result_type = type_to_abi_compat_result_type(allocator, type->Proc.results, type->Proc.calling_convention);
|
|
|
- type->Proc.return_by_pointer = abi_compat_return_by_pointer(allocator, type->Proc.calling_convention, type->Proc.abi_compat_result_type);
|
|
|
-
|
|
|
- type->Proc.abi_types_set = true;
|
|
|
- type->flags = flags;
|
|
|
-}
|
|
|
|
|
|
// NOTE(bill): 'operands' is for generating non generic procedure type
|
|
|
bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node, Array<Operand> *operands) {
|