I'm working on a scripting language, and as part of that I'm writing bridge code between my language and C using LLVM. I've been working on a wrapper for LLVM APIs in objective-c that has been working great up until this point.
typedef struct _test_struct {
int x;
int y;
} test_struct;
id testLLVMStructFuncCall(test_struct x) {
NSLog(@"%d %d",x.x,x.y);
return N(x.x + x.y);
}
-(void) testLLVMStructFuncCall {
CGKModule* myMod = [CGKModule moduleWithName:@"llvm_structfunccall_test"];
CGKType* testStructType = [CGKType structTypeWithElementTypes:[NSArray arrayWithObjects:[CGKType intTypeWith32Bits],[CGKType intTypeWith32Bits],nil]];
CGKFunction* lfunc = [CGKFunction functionWithName:@"testLLVMStructFuncCall" types:[NSArray arrayWithObjects:[CGKType idType],testStructType,nil] intoModule:myMod];
CGKFunction* rfunc = [CGKBuilder createStandaloneCallForFunction:lfunc withArguments:[NSArray
arrayWithObjects:
[CGKConstant getStructOfType:testStructType
withValues:[NSArray arrayWithObjects:[CGKConstant getIntConstant:N(10) bits:32],
[CGKConstant getIntConstant:N(25) bits:32],nil]],nil]
inModule:myMod];
[myMod dump];
id var = [[CGKRunner runnerForModule:myMod] runCGKFunction:rfunc];
assertThat(var,is(equalTo(N(35))));
}
The issue I have is seen in the following output from the test:
Test Case '-[SVFunctionTests testLLVMStructFuncCall]' started.
; ModuleID = 'llvm_structfunccall_test'
%0 = type { i32, i32 }
declare i64* @testLLVMStructFuncCall(%0)
define i64* @0() {
entry:
%0 = call i64* @testLLVMStructFuncCall(%0 { i32 10, i32 25 })
ret i64* %0
}
2011-06-20 21:25:54.821 otest-x86_64[3369:707] 10 0
/Users/mtindal/Projects/Silver/Tests/SVFunctionTests.m:576: error: -[SVFunctionTests testLLVMStructFuncCall] : Expected <35>, but was <10>
Test Case '-[SVFunctionTests testLLVMStructFuncCall]' failed (0.016 seconds).
The module dump shows that the structure argument is passed as expected, however, the C function only receives the x field set to 10, and y field is left empty. I'm completely clueless how this happening and what I can do to fix it. Thanks in advance for any help you can give me.
You're missing the Platform ABI. I assume you're on x86-64, then your struct (according to the ABI) should be passed in a single register as a whole. However you're passing {10, 25} as two separate 32-bit values. Given that 32-bit operations do implicit zero extension it's clear why you have 0 as the second value.
To be precise: the C code expects to receive 25 in the top 32 bits of the first argument register, but you're passing the value in the low 32 bits of the second argument register.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With