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

在LLVM中对标记的联合(总和类型)进行编码,llvm,llvm-ir,Llvm,Llvm Ir,我试图在LLVM中编码一个带标记的联合(也称为sum类型),但在保持编译器前端平台不可知的情况下,这似乎是不可能的。想象一下,我有一个带标签的工会(用锈表示): 要在LLVM中对其进行编码,我需要知道最大变体的大小。这反过来要求我知道所有字段的对齐方式和大小。换句话说,我的前端需要 跟踪所有事物的大小和对齐方式 创建一个虚拟结构(正确填充),以表示可以容纳任何变量的最大类型(例如,{[2 x i64]},假设标记可以容纳与i32字段相同的单词) 最后,要么使用压缩结构,要么告诉LLVM我假设的

我试图在LLVM中编码一个带标记的联合(也称为sum类型),但在保持编译器前端平台不可知的情况下,这似乎是不可能的。想象一下,我有一个带标签的工会(用锈表示):

要在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);