Jus*_*tin 9 compiler-construction struct abi llvm clang
在函数中使用struct参数时,clang将更改函数签名.签名将是一个相同大小的强制int,而不是使用结构类型.在我的编译器项目中,我使用llvm结构类型作为方法签名(这似乎更合乎逻辑).
这不会是一个问题,除了LLVM在使用struct或coerced类型时产生的汇编是不同的而不是调用兼容的事实.这导致我的编译器不与具有结构的C函数ABI兼容.
为什么clang这样做?这是C ABI中指定的内容吗?
这是一个简单的示例C源文件:
struct TwoInt { int a, b; };
struct EightChar { char a, b, c, d, e, f, g, h; };
void doTwoInt(struct TwoInt a) {}
void doEightChar(struct EightChar a) {}
int main()
{
struct TwoInt ti;
struct EightChar fc;
doTwoInt(ti);
doEightChar(fc);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
从Clang得到的LLVM-IR
%struct.TwoInt = type { i32, i32 }
%struct.EightChar = type { i8, i8, i8, i8, i8, i8, i8, i8 }
define void @doTwoInt(i64 %a.coerce) nounwind uwtable {
%a = alloca %struct.TwoInt, align 8
%1 = bitcast %struct.TwoInt* %a to i64*
store i64 %a.coerce, i64* %1, align 1
ret void
}
define void @doEightChar(i64 %a.coerce) nounwind uwtable {
%a = alloca %struct.EightChar, align 8
%1 = bitcast %struct.EightChar* %a to i64*
store i64 %a.coerce, i64* %1, align 1
ret void
}
define i32 @main() nounwind uwtable {
%1 = alloca i32, align 4
%ti = alloca %struct.TwoInt, align 4
%fc = alloca %struct.EightChar, align 1
store i32 0, i32* %1
%2 = bitcast %struct.TwoInt* %ti to i64*
%3 = load i64* %2, align 1
call void @doTwoInt(i64 %3)
%4 = bitcast %struct.EightChar* %fc to i64*
%5 = load i64* %4, align 1
call void @doEightChar(i64 %5)
ret i32 0
}
Run Code Online (Sandbox Code Playgroud)
我期望的是什么(以及我的编译器输出的内容):
%TwoInt = type { i32, i32 }
%EightChar = type { i8, i8, i8, i8, i8, i8, i8, i8 }
define void @doTwoInt(%TwoInt %a) {
%1 = alloca i32
%2 = alloca %TwoInt
store %TwoInt %a, %TwoInt* %2
ret void
}
define void @doEightChar(%EightChar %a) {
%1 = alloca i32
%2 = alloca %EightChar
store %EightChar %a, %EightChar* %2
ret void
}
define i32 @main() {
%1 = alloca i32
%ti = alloca %TwoInt
%fc = alloca %EightChar
%2 = load %TwoInt* %ti
call void @doTwoInt(%TwoInt %2)
%3 = load %EightChar* %fc
call void @doEightChar(%EightChar %3)
ret i32 0
}
Run Code Online (Sandbox Code Playgroud)
两个月前,有在llvmdev线程:[LLVMdev]"结构参数转换为其他类型的"通过Jaymie勒克,1月14日19点50分04秒CST 2013年,她遇到了类似的问题:" 当一个结构参数的函数或返回类型是用编译的clang -O0 -emit-llvm
,生成的bitcode根据struct的类型而变化很大. ",clang将struct转换为指针,vector,将其作为几个双精度传递,或者合并为单个i64类型.Anton Korobeynikov 于2013年1月15日00:41:43 回复:
结构被降低到与平台上的C/C++ ABI相对应的东西,以便以适当的方式传递结构.
因此,clang根据您的操作系统,库和本机编译器使用的方式进行struct传递.这样做是为了允许您构建模块,这些模块将与本地库一起使用.我认为你的编译器项目使用了错误的ABI.
您可以修改您的编译器项目以使用平台ABI(转换结构类似于它由clang完成),或者您可以定义自己的ABI并调整clang以使用它.
归档时间: |
|
查看次数: |
1751 次 |
最近记录: |