diff --git a/src/compiler.bbb b/src/compiler.bbb index 6154c9f..eb291fd 100644 --- a/src/compiler.bbb +++ b/src/compiler.bbb @@ -7054,7 +7054,8 @@ abi_system_v_classify_type = fn (type: &Type, options: AbiSystemVClassifyArgumen if (gt_16 or padding) { result[0] = .memory; - #trap(); + result = abi_system_v_classify_post_merge(byte_size, result); + return result; } >member_classes = abi_system_v_classify_type(member_type, { @@ -7391,6 +7392,42 @@ abi_system_v_get_indirect_result = fn (module: &Module, type: &Type, free_gpr: u } } +NaturalAlignIndirect = struct +{ + semantic_type: &Type, + padding_type: &Type, + not_by_value: u1, // by_value = true by default + realign: u1, +} + +abi_system_v_get_natural_align_indirect = fn (natural: NaturalAlignIndirect) AbiInformation +{ + >alignment = get_byte_alignment(natural.semantic_type); + + return abi_system_v_get_indirect({ + .semantic_type = natural.semantic_type, + .padding_type = natural.padding_type, + .alignment = alignment, + .not_by_value = natural.not_by_value, + .realign = natural.realign, + }); +} + +abi_system_v_get_indirect_return_result = fn (type: &Type) AbiInformation +{ + if (type_is_aggregate_type_for_abi(type)) + { + return abi_system_v_get_natural_align_indirect({ + .semantic_type = type, + zero, + }); + } + else + { + #trap(); + } +} + abi_system_v_classify_return_type = fn (module: &Module, semantic_return_type: &Type) AbiInformation { >classes = abi_system_v_classify_type(semantic_return_type, zero); @@ -7428,6 +7465,10 @@ abi_system_v_classify_return_type = fn (module: &Module, semantic_return_type: & } } }, + .memory => + { + return abi_system_v_get_indirect_return_result(semantic_return_type); + }, else => { #trap(); @@ -7648,11 +7689,16 @@ abi_system_v_classify_argument = fn (module: &Module, available_registers: &AbiR abi_argument_type_buffer[abi_start] = coerce_to_type; count = 1; } - } + }, .indirect => { - #trap(); - } + >indirect_type = get_pointer_type(module, argument_abi.semantic_type); + >abi_index = argument_abi.abi_start; + abi_argument_type_buffer[abi_index] = indirect_type; + resolve_type_in_place(module, indirect_type); + llvm_abi_argument_type_buffer[abi_index] = indirect_type.llvm.abi; + count = 1; + }, else => { unreachable; }, } @@ -10937,6 +10983,10 @@ emit_assignment = fn (module: &Module, left_llvm: &LLVMValue, left_type: &Type, emit_intrinsic_call(module, ."llvm.va_start", argument_types[..], argument_values[..]); }, + .aggregate_initialization => + { + #trap(); + }, else => { #trap(); @@ -11719,7 +11769,16 @@ emit = fn (module: &Module) void if (return_abi_kind == .indirect) { - #trap(); + assert(!function_type.abi.return_abi.flags.sret_after_this); + function_type.abi.available_registers.system_v.gpr -= 1; + >indirect_type = get_pointer_type(module, function_type.abi.return_abi.semantic_type); + resolve_type_in_place(module, indirect_type); + + >abi_index = abi_argument_type_count; + abi_argument_type_buffer[abi_index] = indirect_type; + llvm_abi_argument_type_buffer[abi_index] = indirect_type.llvm.abi; + + abi_argument_type_count += 1; } if (semantic_argument_types.length != 0) @@ -11741,10 +11800,11 @@ emit = fn (module: &Module) void abi_argument_type_count += abi.abi_count; } - >abi_argument_types = arena_allocate_slice[&Type](module.arena, #extend(abi_argument_type_count)); - memcpy(#pointer_cast(abi_argument_types.pointer), #pointer_cast(&abi_argument_type_buffer), #extend(#byte_size(&Type) * abi_argument_type_count)); - function_type.abi.abi_argument_types = abi_argument_types; } + + >abi_argument_types = arena_allocate_slice[&Type](module.arena, #extend(abi_argument_type_count)); + memcpy(#pointer_cast(abi_argument_types.pointer), #pointer_cast(&abi_argument_type_buffer), #extend(#byte_size(&Type) * abi_argument_type_count)); + function_type.abi.abi_argument_types = abi_argument_types; }, .win64 => { @@ -11960,23 +12020,34 @@ emit = fn (module: &Module) void switch (return_abi.flags.kind) { .ignore => {}, - .indirect => + .indirect => + { + >indirect_argument_index = function_type.abi.return_abi.flags.sret_after_this; + if (function_type.abi.return_abi.flags.sret_after_this) { -#trap(); - }, - .in_alloca => + #trap(); + } + + global.variable.storage.content.function.llvm.return_alloca = llvm_abi_arguments[indirect_argument_index]; + + if (!function_type.abi.return_abi.flags.indirect_by_value) { -#trap(); - }, - else => - { - >alloca = create_alloca(module, { - .type = return_abi.semantic_type, - .name = "return_value", - zero, - }); - function.content.function.llvm.return_alloca = alloca; - }, + #trap(); + } + }, + .in_alloca => + { + #trap(); + }, + else => + { + >alloca = create_alloca(module, { + .type = return_abi.semantic_type, + .name = "return_value", + zero, + }); + function.content.function.llvm.return_alloca = alloca; + }, } >arguments = function.content.function.arguments; @@ -12613,7 +12684,8 @@ compile_file = fn (arena: &Arena, compile_options: CompileFile) []u8 return output_executable_path; } -names: [_][]u8 = [ +names: [_][]u8 = +[ "minimal", "comments", "constant_add", @@ -12662,6 +12734,9 @@ names: [_][]u8 = [ "bits_zero", "comparison", "global_struct", + "if_no_else", + "if_no_else_void", + "indirect", ]; [export] main = fn [cc(c)] (argument_count: u32, argv: &&u8, envp: &&u8) s32