Commit 9017efee22

Andrew Kelley <superjoe30@gmail.com>
2018-09-08 00:47:57
C ABI: support medium size structs & unions for x86_64 params
See #1481
1 parent 85534a2
Changed files (3)
src
test
stage1
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;
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);
+}
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);
+}