[clang] [CIR] Upstream initial support for union type (PR #137501)
Andy Kaylor via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 28 10:53:13 PDT 2025
================
@@ -306,3 +320,71 @@ CIRGenTypes::computeRecordLayout(const RecordDecl *rd, cir::RecordType *ty) {
// TODO: implement verification
return rl;
}
+
+void CIRRecordLowering::lowerUnion() {
+ CharUnits layoutSize = astRecordLayout.getSize();
+ mlir::Type storageType = nullptr;
+ bool seenNamedMember = false;
+
+ // Iterate through the fields setting bitFieldInfo and the Fields array. Also
+ // locate the "most appropriate" storage type. The heuristic for finding the
+ // storage type isn't necessary, the first (non-0-length-bitfield) field's
+ // type would work fine and be simpler but would be different than what we've
+ // been doing and cause lit tests to change.
+ for (const FieldDecl *field : recordDecl->fields()) {
+ mlir::Type fieldType;
+ if (field->isBitField())
+ cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
+ "bitfields in lowerUnion");
+ else
+ fieldType = getStorageType(field);
+
+ fields[field->getCanonicalDecl()] = 0;
+
+ // Compute zero-initializable status.
+ // This union might not be zero initialized: it may contain a pointer to
+ // data member which might have some exotic initialization sequence.
+ // If this is the case, then we aught not to try and come up with a "better"
+ // type, it might not be very easy to come up with a Constant which
+ // correctly initializes it.
+ if (!seenNamedMember) {
+ seenNamedMember = field->getIdentifier();
+ if (!seenNamedMember)
+ if (const RecordDecl *fieldRD = field->getType()->getAsRecordDecl())
+ seenNamedMember = fieldRD->findFirstNamedDataMember();
+ if (seenNamedMember && !isZeroInitializable(field)) {
+ zeroInitializable = zeroInitializableAsBase = false;
+ storageType = fieldType;
+ }
+ }
+
+ // Because our union isn't zero initializable, we won't be getting a better
+ // storage type.
+ if (!zeroInitializable)
+ continue;
+
+ // Conditionally update our storage type if we've got a new "better" one.
+ if (!storageType || getAlignment(fieldType) > getAlignment(storageType) ||
+ (getAlignment(fieldType) == getAlignment(storageType) &&
+ getSize(fieldType) > getSize(storageType)))
+ storageType = fieldType;
+
+ // NOTE(cir): Track all union member's types, not just the largest one. It
+ // allows for proper type-checking and retain more info for analisys.
+ fieldTypes.push_back(fieldType);
+ }
+
+ if (!storageType)
+ cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
+ "No-storage Union NYI");
+
+ if (layoutSize < getSize(storageType))
+ storageType = getByteArrayType(layoutSize);
+
+ // NOTE(cir): Defer padding calculations to the lowering process.
----------------
andykaylor wrote:
I don't understand this comment. Isn't calculating padding exactly what we just did?
https://github.com/llvm/llvm-project/pull/137501
More information about the cfe-commits
mailing list