C ABI: support medium size structs & unions for x86_64 params

See #1481
This commit is contained in:
Andrew Kelley 2018-09-07 18:47:57 -04:00
parent 85534a26c6
commit 9017efee22
No known key found for this signature in database
GPG Key ID: 4E7CD66038A4D47C
3 changed files with 49 additions and 3 deletions

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}