【问题标题】:Extracting a value from an union从联合中提取值
【发布时间】:2013-10-24 03:23:30
【问题描述】:

从联合数组中提取值的 LLVM 方法是什么? 不直接支持联合,这似乎使事情复杂化。

背景: 我正在调用 JIT 执行机器返回的函数 并传递1个参数,即数组的基地址 包含参数的联合。

数据结构是从 C 中设置的:

std::array<union{int,float*}> arguments(5);

intfloat*的出现序列被编码 在vector&lt;llvm::Type*&gt;:

i32
i32
float*
float*
float*

现在我正在尝试这个(这是jitted函数):

define void @main([8 x i8]* %arg_ptr) {
entrypoint:
   %0 = getelementptr [8 x i8]* %arg_ptr, i32 0
   %1 = getelementptr [8 x i8]* %arg_ptr, i32 1
   %2 = getelementptr [8 x i8]* %arg_ptr, i32 2
   %3 = getelementptr [8 x i8]* %arg_ptr, i32 3
   %4 = getelementptr [8 x i8]* %arg_ptr, i32 4
}

首先,函数的签名是否正确(假设 指针大小为 8 字节)?

如何从 %0 中存储的 [8 x i8] 中取出第一个 i32

我是否需要先将数组[8 x i8] 转换为指针i32*, 然后为其第一个元素创建另一个 GEP?

【问题讨论】:

    标签: llvm


    【解决方案1】:

    请注意,LLVM IR 并没有真正的联合。在实践中发生的事情是 Clang(它知道目标三元组,因此细节是特定于平台/ABI 的)将创建一个足够大的单个元素 struct 以包含您的联合并对其采取行动。下面是一些 C 代码:

    typedef union {
      double dnum;
      int inum;
      float* fptr;
    } my_union;
    
    int bar(my_union* mu) {
      return mu[4].inum;
    }
    

    使用 clang 将其转换为 LLVM IR(使用 x86-64 机器上的默认目标,我们得到此(优化代码,以减少混乱):

    %union.my_union = type { double }
    
    define i32 @bar(%union.my_union* nocapture readonly %mu) #0 {
    entry:
      %arrayidx = getelementptr inbounds %union.my_union* %mu, i64 4
      %inum = bitcast %union.my_union* %arrayidx to i32*
      %0 = load i32* %inum, align 4
      ret i32 %0
    }
    

    这里有几点需要注意,您的问题中包含一些子问题的答案:

    • 联合被 C 类型struct {double} 取代,因为它大到足以包含所有联合成员,并且它还提供正确的对齐约束。 LLVM 对联合一无所知。从这一点开始,它作用于结构聚合。
    • 对 LLVM 中的数组成员的访问是通过 GEP 完成的,该 GEP 获得两个数字索引。有关它为何以这种方式工作的深入解释,请参阅http://llvm.org/docs/GetElementPtr.html
    • 拥有成员后,您只需从中加载值。 Clang 知道成员在枚举中的布局方式,因此它直接从成员加载 i32*

    【讨论】:

    • 看看clang是做什么的好主意。所以它在 %arrayidx 之前做同样的事情,然后做一个比特广播。我也那么认为。唯一不明白的是align 4。我们在一个 8 字节的结构中,这自然是对齐到 8 字节的,对吧?为什么会在加载指令中加入4的对齐方式?
    • @wpunkt:请注意,load 作用于 i32*,因此严格来说不需要对齐 8。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-16
    • 2020-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-25
    相关资源
    最近更新 更多