Encoding tagged joins (amount types) in LLVM

I am trying to encode the labeled union (also known as the sum type) in LLVM, and this is not possible, while preserving the agnostic of the front-end compiler platform. Imagine I had this tagged union (expressed in Rust):

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

To encode this in LLVM, I need to know the size of the largest option. This, in turn, requires me to know the alignment and size of all fields. In other words, my interface should

  • track the size and alignment of all things
  • create a dummy structure (correctly complemented) to represent the largest type that can match any option (for example {[2 x i64]}, assuming the tag can match the same word as the field i32),
  • and finally, either use packed structures or tell LLVM which “data layout” I assumed, so my calculations correspond to LLVM

What is the best way to encode labeled joins in LLVM?

+4
source share
1 answer

It is clear that I do not think that there is a better way than what you described, except that I would not worry about using the built type on the announcement site, since in fact access to the union would be easiest done through bitcast anyway.

Here's a snippet of code from Clang getTypeExpansion () , showing it also does this - manually find the largest field:

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);
+1
source

Source: https://habr.com/ru/post/1658287/


All Articles