在LLVM中编码标记的联合(总和类型)

时间:2016-10-20 06:11:10

标签: llvm llvm-ir

我试图在LLVM中对标记的联合(也称为求和类型)进行编码,但在保持编译器前端平台不可知的情况下似乎不可能。想象一下,我有这个标记的联合(用Rust表示):

enum T {
    C1(i32, i64),
    C2(i64)
}

要在LLVM中对此进行编码,我需要知道最大变体的大小。这反过来要求我知道所有字段的对齐和大小。换句话说,我的前端需要

  • 跟踪所有事物的大小和对齐方式,
  • 创建一个虚拟结构(正确填充)以表示可以适合任何变体的最大类型(例如{[2 x i64]},假设标记可以与i32字段放在同一个单词中),
  • 最后要么使用打包的结构,要么告诉LLVM"数据布局"我假设,所以我的计算与LLVMs匹配

目前在LLVM中对标记联合进行编码的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

从概念上讲,我不认为这比你描述的更好,除了我不会在声明网站上使用构造的类型,因为实际访问联盟将是无论如何,通过一个bitcast最容易做到。

这是来自Clang getTypeExpansion()的代码片段,显示它也是这样做的 - 手动查找最大的字段:

const FieldDecl *LargestFD = nullptr;
CharUnits UnionSize = CharUnits::Zero();

for (const auto *FD : RD->fields()) {
  // Skip zero length bitfields.
  if (FD->isBitField() && FD->getBitWidthValue(Context) == 0)
    continue;
  assert(!FD->isBitField() &&
         "Cannot expand structure with bit-field members.");
  CharUnits FieldSize = Context.getTypeSizeInChars(FD->getType());
  if (UnionSize < FieldSize) {
    UnionSize = FieldSize;
    LargestFD = FD;
  }
}
if (LargestFD)
  Fields.push_back(LargestFD);