在LLVM中对标记的联合(总和类型)进行编码
我试图在LLVM中编码一个带标记的联合(也称为sum类型),但在保持编译器前端平台不可知的情况下,这似乎是不可能的。想象一下,我有一个带标签的工会(用锈表示): 要在LLVM中对其进行编码,我需要知道最大变体的大小。这反过来要求我知道所有字段的对齐方式和大小。换句话说,我的前端需要在LLVM中对标记的联合(总和类型)进行编码,llvm,llvm-ir,Llvm,Llvm Ir,我试图在LLVM中编码一个带标记的联合(也称为sum类型),但在保持编译器前端平台不可知的情况下,这似乎是不可能的。想象一下,我有一个带标签的工会(用锈表示): 要在LLVM中对其进行编码,我需要知道最大变体的大小。这反过来要求我知道所有字段的对齐方式和大小。换句话说,我的前端需要 跟踪所有事物的大小和对齐方式 创建一个虚拟结构(正确填充),以表示可以容纳任何变量的最大类型(例如,{[2 x i64]},假设标记可以容纳与i32字段相同的单词) 最后,要么使用压缩结构,要么告诉LLVM我假设的
- 跟踪所有事物的大小和对齐方式
- 创建一个虚拟结构(正确填充),以表示可以容纳任何变量的最大类型(例如,
,假设标记可以容纳与{[2 x i64]}
字段相同的单词)i32
- 最后,要么使用压缩结构,要么告诉LLVM我假设的是哪个“数据布局”,这样我的计算就与LLVM匹配了
目前在LLVM中编码带标签的联合体的最佳方法是什么?从概念上讲,我认为没有比您描述的更好的方法,只是我不想在声明站点使用构造的类型,因为实际上通过比特广播访问联合体是最容易的 下面是来自Clang的一段代码片段,显示它也执行此操作-手动查找最大字段:
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);
const FieldDecl*LargestFD=nullptr;
CharUnits UnionSize=CharUnits::Zero();
用于(常量自动*FD:RD->fields()){
//跳过零长度位字段。
如果(FD->isBitField()&&FD->getBitWidthValue(上下文)==0)
继续;
断言(!FD->isBitField()&&
“无法使用位字段成员展开结构。”);
CharUnits FieldSize=Context.getTypeSizeInChars(FD->getType());
如果(UnionSize
您是否知道计算Context.getTypeSizeInChars返回的值的代码在哪里(该函数仅检索已计算的值。计算类型的大小(例如strict),将对齐约束考虑在内,这是最棘手的部分之一。@tibbe我不知道所有计算都发生在哪里,您必须跟踪它。我确实相信起点总是在的子类中;请看。
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);