7

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.

1
  • the <35> and <10> refers to a type defined previously, which should be existing on your module, try dumping the module contents and paste it in your question Commented Jun 20, 2011 at 19:03

1 Answer 1

10

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.

Sign up to request clarification or add additional context in comments.

2 Comments

@Michael: Compile your C code to llvm asm. You will see how test_struct in function argument is changed to i64 and how it's letter called. You need to do the same.
Thank you so much, thats the info I needed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.