Llvm 从并集中提取值

Llvm 从并集中提取值,llvm,Llvm,LLVM从联合数组中提取值的方法是什么? 工会没有得到直接支持,这似乎使事情复杂化了 背景: 我正在调用JIT执行机器返回的函数 并将1个参数传递给它,即数组的基址 包含参数的联合 数据结构由C设置,如: std::array<union{int,float*}> arguments(5); 现在我正在尝试这个(这是jitted函数): 首先,函数的签名是否正确(假设 指针大小是8字节吗 如何从存储在%0中的[8 x i8]中获取第一个i32 是否需要先将数组[8 x i8]强制转

LLVM从联合数组中提取值的方法是什么? 工会没有得到直接支持,这似乎使事情复杂化了

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

数据结构由C设置,如:

std::array<union{int,float*}> arguments(5);
现在我正在尝试这个(这是jitted函数):

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

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

是否需要先将数组
[8 x i8]
强制转换为指针
i32*

然后为其第一个元素创建另一个GEP?

请注意,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被C类型
    struct{double}
    替换,因为它足够大,可以包含所有union成员,并且它还提供了正确的对齐约束。LLVM对union一无所知。从这一点开始,它作用于结构聚合
  • 对LLVM中数组成员的访问是通过一个GEP完成的,该GEP获得两个数字索引
  • 拥有成员后,只需从中加载值。Clang知道成员在枚举中的布局,因此它直接从成员加载
    i32*

看看clang是做什么的好主意。所以它对%arrayidx做同样的事情,然后进行比特广播。这就是我所想的。唯一不明白的是
align 4
。我们是在一个8字节的结构中,这自然被绑定到8字节,对吗?它为什么要在加载指令中添加4的对齐方式?@wpunk:注意
load
作用于
i32*
,因此严格来说,不需要对齐8。
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
}
typedef union {
  double dnum;
  int inum;
  float* fptr;
} my_union;

int bar(my_union* mu) {
  return mu[4].inum;
}
%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
}