我正在尝试在LLVM中编码标记联合(也称为求和类型),并且在保持编译器前端平台不可知的情况下似乎不可能.想象一下,我有这个标记的联合(用Rust表示):
enum T {
C1(i32, i64),
C2(i64)
}
要在LLVM中对此进行编码,我需要知道最大变体的大小.这反过来要求我知道所有字段的对齐和大小.换句话说,我的前端需要
>跟踪所有事物的大小和对齐方式,
>创建一个虚拟结构(正确填充)来表示可以适合任何变体的最大类型(例如{[2 x i64]},假设标记可以与i32字段放在同一个单词中),
>最后要么使用打包的结构,要么告诉LLVM我假设的“数据布局”,所以我的计算与LLVM匹配
目前在LLVM中对标记联合进行编码的最佳方法是什么?
最佳答案 从概念上讲,我认为没有比你描述的更好的方法,除了我不打算在声明网站上使用构造的类型,因为无论如何实际访问联盟最容易通过一个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);