2011-06-20 37 views
6

我正在研究一种脚本语言,并且我正在使用LLVM在我的语言和C之间编写桥代码。我一直在为Objective-C中的LLVM API进行包装工作,直到目前为止它一直在努力工作。以结构作为参数的LLVM和C函数

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

我已经在从所述测试输出下面看到的问题:

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). 

模块转储表明如预期的那样结构参数被传递,但是,C函数仅接收在x字段设置为10,并且y字段留空。我完全无知这是怎么发生的,以及我能做些什么来解决它。预先感谢您提供的任何帮助。

+0

<35>和<10>指的是以前定义的类型,它应该存在于你的模块中,尝试转储模块内容并将其粘贴到你的问题中 – lurscher

回答

9

您错过了平台ABI。我假设你在x86-64上,那么你的结构(根据ABI)应该作为一个整体在一个寄存器中传递。但是,您将{10,25}作为两个单独的32位值传递。鉴于32位操作做隐式零扩展,很明显你为什么有0作为第二个值。

准确而言:C代码希望在第一个参数寄存器的前32位中接收25,但是您将该值传递给第二个参数寄存器的低32位。

+1

@Michael:将你的C代码编译为llvm asm。你会看到函数参数中的'test_struct'如何被更改为i64以及它如何被调用。你需要这样做。 –

+0

非常感谢你,那是我需要的信息。 –