LLVM and C function with structure as argument

I am working on a scripting language, and as part of this I am writing bridge code between my language and C using LLVM. I am working on a shell for the LLVM API in objective-c, which works up to this point.

typedef struct _test_struct { int x; int y; } test_struct; id testLLVMStructFuncCall(test_struct x) { NSLog(@"%d %d",xx,xy); return N(xx + xy); } -(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 problem that I see is shown in the next test release:

 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 indicates that the structure argument is passed as expected, however, the C function receives only the field x set to 10, and the field y remains empty. I absolutely do not know how this happens and what I can do to fix it. Thanks in advance for any help you can give me.

+6
source share
1 answer

You are missing the ABI platform. I assume that you are on x86-64, then your structure (according to ABI) should be transferred in one register as a whole. However, you pass {10, 25} as two separate 32-bit values. Given that 32-bit operations have an implicit null extension, it’s clear why you have 0 as the second value.

To be precise: the C code expects to get 25 in the upper 32 bits of the register of the first argument, but you pass the value in the lower 32 bits of the second argument register.

+9
source

Source: https://habr.com/ru/post/890950/


All Articles