为什么Clang强制结构参数为int [英] Why does Clang coerce struct parameters to ints

查看:220
本文介绍了为什么Clang强制结构参数为int的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在函数中使用struct参数时,clang将更改函数签名。代替使用struct类型,签名将是等大小的强制int。在我的编译器项目中,我使用llvm结构类型的方法签名(这似乎更合乎逻辑)。

When using struct parameters in a function, clang will change the function signature. Instead of using a struct type, the signature will be a coerced int of equal size. In my compiler project, I use the llvm struct type for the method signature (which seems more logical).

这不会是一个问题,当使用struct或coerced类型时,由LLVM生成的结果集合是不同的,而不是调用兼容。这导致我的编译器不能与带struct的C函数进行ABI兼容。

This wouldn't be a problem, except for the fact that resulting assembly produced by LLVM when using the struct or coerced types are different and not call compatible. This results in my compiler not being ABI compatible with C functions with structs.

为什么clang会这样做?这是C ABI中指定的内容吗?

下面是一个简单的C源文件示例:

Here's a simple example C source file:

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

来自Clang的LLVM-IR

Resulting LLVM-IR from Clang

%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
}

我预期的(以及我的编译器输出的结果):

What I would've expected (and what my compiler outputs):

%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
}


推荐答案

两个月前,llvmdev中有一个线程: [LLVMdev]结构参数被转换为其他类型由Jaymie Strecker。她遇到类似的问题:当具有struct参数或返回类型的函数使用 clang -O0 -emit-llvm 编译时,结果位码会根据类型的结构。,和clang将struct转换为指针,向量,传递为几个双精度,或合并为单个i64类型。 Anton Korobeynikov 回答:

Two month ago there was a thread in llvmdev: [LLVMdev] Struct parameters being converted to other types by Jaymie Strecker. She encountered similar problem: "When a function with a struct parameter or return type is compiled with clang -O0 -emit-llvm, the resulting bitcode varies greatly depending on the type of struct.", and clang turned struct into pointer, vector, passed it as several doubles, or merged into single i64 type. Anton Korobeynikov replied:



The struct is lowered to something which corresponds to C/C++ ABI on your platform for passing the struct in proper way.

结构体被降低到对应于平台上的C / C ++ ABI的某种东西。 ,clang根据您的操作系统,libs和本机编译器使用的方式进行结构传递。这样做是为了允许你构建模块,它将与本地库一起工作。我认为你的编译器项目使用错误的ABI。

So, clang does struct passing according to the way used by your OS, libs and native compiler. This is done to allow you build modules, which will work with local libraries. I think that your "compiler project" uses wrong ABI.

你可以修复你的编译器项目使用平台ABI(转换结构,或者你可以定义自己的ABI和调整铛来使用它。

You can fix your "compiler project" to use platform ABI (convert structs like it was done by clang), OR you can define your own ABI and tune clang to use it.

这篇关于为什么Clang强制结构参数为int的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆