diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp index aba85ae83..1347a1cdd 100644 --- a/src/llvm_abi.cpp +++ b/src/llvm_abi.cpp @@ -11,6 +11,8 @@ struct lbArgType { LLVMTypeRef pad_type; // Optional LLVMAttributeRef attribute; // Optional LLVMAttributeRef align_attribute; // Optional + i64 byval_alignment; + bool is_byval; }; @@ -18,14 +20,14 @@ i64 lb_sizeof(LLVMTypeRef type); i64 lb_alignof(LLVMTypeRef type); lbArgType lb_arg_type_direct(LLVMTypeRef type, LLVMTypeRef cast_type, LLVMTypeRef pad_type, LLVMAttributeRef attr) { - return lbArgType{lbArg_Direct, type, cast_type, pad_type, attr, nullptr}; + return lbArgType{lbArg_Direct, type, cast_type, pad_type, attr, nullptr, 0, false}; } lbArgType lb_arg_type_direct(LLVMTypeRef type) { return lb_arg_type_direct(type, nullptr, nullptr, nullptr); } lbArgType lb_arg_type_indirect(LLVMTypeRef type, LLVMAttributeRef attr) { - return lbArgType{lbArg_Indirect, type, nullptr, nullptr, attr, nullptr}; + return lbArgType{lbArg_Indirect, type, nullptr, nullptr, attr, nullptr, 0, false}; } lbArgType lb_arg_type_indirect_byval(LLVMContextRef c, LLVMTypeRef type) { @@ -34,11 +36,11 @@ lbArgType lb_arg_type_indirect_byval(LLVMContextRef c, LLVMTypeRef type) { LLVMAttributeRef byval_attr = lb_create_enum_attribute_with_type(c, "byval", type); LLVMAttributeRef align_attr = lb_create_enum_attribute(c, "align", alignment); - return lbArgType{lbArg_Indirect, type, nullptr, nullptr, byval_attr, align_attr}; + return lbArgType{lbArg_Indirect, type, nullptr, nullptr, byval_attr, align_attr, alignment, true}; } lbArgType lb_arg_type_ignore(LLVMTypeRef type) { - return lbArgType{lbArg_Ignore, type, nullptr, nullptr, nullptr, nullptr}; + return lbArgType{lbArg_Ignore, type, nullptr, nullptr, nullptr, nullptr, 0, false}; } struct lbFunctionType { @@ -458,11 +460,10 @@ namespace lbAbiAmd64SysV { Amd64TypeAttribute_StructRect, }; - Array compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count); lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined); void classify_with(LLVMTypeRef t, Array *cls, i64 ix, i64 off); void fixup(LLVMTypeRef t, Array *cls); - lbArgType amd64_type(LLVMContextRef c, LLVMTypeRef type, Amd64TypeAttributeKind attribute_kind); + lbArgType amd64_type(LLVMContextRef c, LLVMTypeRef type, Amd64TypeAttributeKind attribute_kind, ProcCallingConvention calling_convention); Array classify(LLVMTypeRef t); LLVMTypeRef llreg(LLVMContextRef c, Array const ®_classes); @@ -473,11 +474,11 @@ namespace lbAbiAmd64SysV { ft->args = array_make(heap_allocator(), arg_count); for (unsigned i = 0; i < arg_count; i++) { - ft->args[i] = amd64_type(c, arg_types[i], Amd64TypeAttribute_ByVal); + ft->args[i] = amd64_type(c, arg_types[i], Amd64TypeAttribute_ByVal, calling_convention); } if (return_is_defined) { - ft->ret = amd64_type(c, return_type, Amd64TypeAttribute_StructRect); + ft->ret = amd64_type(c, return_type, Amd64TypeAttribute_StructRect, calling_convention); } else { ft->ret = lb_arg_type_direct(LLVMVoidTypeInContext(c)); } @@ -514,7 +515,7 @@ namespace lbAbiAmd64SysV { return false; } - lbArgType amd64_type(LLVMContextRef c, LLVMTypeRef type, Amd64TypeAttributeKind attribute_kind) { + lbArgType amd64_type(LLVMContextRef c, LLVMTypeRef type, Amd64TypeAttributeKind attribute_kind, ProcCallingConvention calling_convention) { if (is_register(type)) { LLVMAttributeRef attribute = nullptr; if (type == LLVMInt1TypeInContext(c)) { @@ -527,7 +528,10 @@ namespace lbAbiAmd64SysV { if (is_mem_cls(cls, attribute_kind)) { LLVMAttributeRef attribute = nullptr; if (attribute_kind == Amd64TypeAttribute_ByVal) { - return lb_arg_type_indirect_byval(c, type); + if (!is_calling_convention_odin(calling_convention)) { + return lb_arg_type_indirect_byval(c, type); + } + attribute = nullptr; } else if (attribute_kind == Amd64TypeAttribute_StructRect) { attribute = lb_create_enum_attribute_with_type(c, "sret", type); } @@ -817,26 +821,6 @@ namespace lbAbiAmd64SysV { } } - Array compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count) { - auto args = array_make(heap_allocator(), arg_count); - - for (unsigned i = 0; i < arg_count; i++) { - LLVMTypeRef t = arg_types[i]; - LLVMTypeKind kind = LLVMGetTypeKind(t); - if (kind == LLVMStructTypeKind) { - i64 sz = lb_sizeof(t); - if (sz == 0) { - args[i] = lb_arg_type_ignore(t); - } else { - args[i] = lb_arg_type_indirect_byval(c, t); - } - } else { - args[i] = non_struct(c, t); - } - } - return args; - } - lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined) { if (!return_is_defined) { return lb_arg_type_direct(LLVMVoidTypeInContext(c)); diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 3b4e5f3f6..ab2c97557 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -3712,11 +3712,8 @@ void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) { value.type = nested_proc->type; array_add(&p->module->procedures_to_generate, nested_proc); - if (p != nullptr) { - array_add(&p->children, nested_proc); - } else { - string_map_set(&p->module->members, name, value); - } + array_add(&p->children, nested_proc); + string_map_set(&p->module->members, name, value); } } } @@ -8507,7 +8504,9 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array const &args, } else if (arg->kind == lbArg_Indirect) { lbValue ptr = {}; - if (is_calling_convention_odin(pt->Proc.calling_convention)) { + if (arg->is_byval) { + ptr = lb_copy_value_to_ptr(p, x, original_type, arg->byval_alignment); + } else if (is_calling_convention_odin(pt->Proc.calling_convention)) { // NOTE(bill): Odin parameters are immutable so the original value can be passed if possible // i.e. `T const &` in C++ ptr = lb_address_from_load_or_generate_local(p, x);