From 9017efee220950b11070242415b6dc456d4442df Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 7 Sep 2018 18:47:57 -0400 Subject: [PATCH] C ABI: support medium size structs & unions for x86_64 params See #1481 --- src/codegen.cpp | 12 +++++++++--- test/stage1/c_abi/cfuncs.c | 18 ++++++++++++++++++ test/stage1/c_abi/main.zig | 22 ++++++++++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index a38cc869dd..4be08b03e7 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -354,8 +354,12 @@ static void addLLVMFnAttrInt(LLVMValueRef fn_val, const char *attr_name, uint64_ return addLLVMAttrInt(fn_val, -1, attr_name, attr_val); } -static void addLLVMArgAttr(LLVMValueRef arg_val, unsigned param_index, const char *attr_name) { - return addLLVMAttr(arg_val, param_index + 1, attr_name); +static void addLLVMArgAttr(LLVMValueRef fn_val, unsigned param_index, const char *attr_name) { + return addLLVMAttr(fn_val, param_index + 1, attr_name); +} + +static void addLLVMArgAttrInt(LLVMValueRef fn_val, unsigned param_index, const char *attr_name, uint64_t attr_val) { + return addLLVMAttrInt(fn_val, param_index + 1, attr_name, attr_val); } static bool is_symbol_available(CodeGen *g, Buf *name) { @@ -2096,6 +2100,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ switch (fn_walk->id) { case FnWalkIdAttrs: addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull"); + addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty)); fn_walk->data.attrs.gen_i += 1; break; case FnWalkIdCall: @@ -2132,6 +2137,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ switch (fn_walk->id) { case FnWalkIdAttrs: addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "byval"); + addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty)); addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull"); fn_walk->data.attrs.gen_i += 1; break; @@ -2159,7 +2165,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ break; } return true; - } else if (abi_class == X64CABIClass_INTEGER && ty_size <= 8) { + } else if (abi_class == X64CABIClass_INTEGER) { switch (fn_walk->id) { case FnWalkIdAttrs: fn_walk->data.attrs.gen_i += 1; diff --git a/test/stage1/c_abi/cfuncs.c b/test/stage1/c_abi/cfuncs.c index 393c3a4f5a..ff249d2a59 100644 --- a/test/stage1/c_abi/cfuncs.c +++ b/test/stage1/c_abi/cfuncs.c @@ -52,6 +52,13 @@ struct SmallStructInts { }; void zig_small_struct_ints(struct SmallStructInts); +struct SplitStructInts { + uint64_t a; + uint8_t b; + uint32_t c; +}; +void zig_split_struct_ints(struct SplitStructInts); + void run_c_tests(void) { zig_u8(0xff); zig_u16(0xfffe); @@ -83,6 +90,11 @@ void run_c_tests(void) { struct SmallStructInts s = {1, 2, 3, 4}; zig_small_struct_ints(s); } + + { + struct SplitStructInts s = {1234, 100, 1337}; + zig_split_struct_ints(s); + } } void c_u8(uint8_t x) { @@ -167,3 +179,9 @@ void c_small_struct_ints(struct SmallStructInts x) { assert_or_panic(x.c == 3); assert_or_panic(x.d == 4); } + +void c_split_struct_ints(struct SplitStructInts x) { + assert_or_panic(x.a == 1234); + assert_or_panic(x.b == 100); + assert_or_panic(x.c == 1337); +} diff --git a/test/stage1/c_abi/main.zig b/test/stage1/c_abi/main.zig index ef425ceb67..e1356f50ef 100644 --- a/test/stage1/c_abi/main.zig +++ b/test/stage1/c_abi/main.zig @@ -181,3 +181,25 @@ export fn zig_small_struct_ints(x: SmallStructInts) void { assertOrPanic(x.c == 3); assertOrPanic(x.d == 4); } + +const SplitStructInt = extern struct { + a: u64, + b: u8, + c: u32, +}; +extern fn c_split_struct_ints(SplitStructInt) void; + +test "C ABI split struct of ints" { + var s = SplitStructInt{ + .a = 1234, + .b = 100, + .c = 1337, + }; + c_split_struct_ints(s); +} + +export fn zig_split_struct_ints(x: SplitStructInt) void { + assertOrPanic(x.a == 1234); + assertOrPanic(x.b == 100); + assertOrPanic(x.c == 1337); +}