================
@@ -851,72 +850,61 @@ void CIRRecordLowering::lowerUnion(bool
nonVirtualBaseType) {
fieldType = getStorageType(field);
}
- // This maps a field to its index. For unions, the index is always 0.
fieldIdxMap[field->getCanonicalDecl()] = 0;
+ fieldTypes.push_back(fieldType);
+ }
- // 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 ought 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;
- }
- }
+ // 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.
+ // Unlike classic codegen, we don't really 'give up' on adding all the
fields,
+ // though this is a decision/implementation we might want to revisit. We
just
+ // fall back on the typical storage type calculation rather than this bizarre
+ // "choose the first thing", as that likely won't be compatible with later
+ // decisions.
+ for (const FieldDecl *field : recordDecl->fields()) {
- // Because our union isn't zero initializable, we won't be getting a better
- // storage type.
- if (!zeroInitializable)
- continue;
+ auto hasNamedMember = [](const FieldDecl *curField) -> bool {
+ const auto *rd = curField->getType()->getAsRecordDecl();
+ return rd && rd->findFirstNamedDataMember();
+ };
- // 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.
- //
- // The base-subobject type instead uses a single (possibly clipped) storage
- // type, mirroring classic CodeGen, so that it exposes the union's reusable
- // tail padding.
- if (!nonVirtualBaseType)
- fieldTypes.push_back(fieldType);
+ if ((field->getIdentifier() || hasNamedMember(field)) &&
+ !isZeroInitializable(field)) {
+ zeroInitializable = zeroInitializableAsBase = false;
+ }
}
- if (!storageType) {
+ // If we have no candidates for storage, we are JUST padding.
+ if (fieldTypes.empty()) {
appendPaddingBytes(layoutSize);
return;
}
+ mlir::Type storageType =
+ cir::UnionType::getUnionStorageType(dataLayout.layout, fieldTypes);
+
+ // If our storage size was bigger than our required size (can happen in the
+ // case of packed bitfields on Itanium) then just use an I8 array.
if (layoutSize < getSize(storageType))
storageType = getByteArrayType(layoutSize);
+ // The base-subobject record is built as a struct from fieldTypes, so add
+ // the storage type and any trailing padding as ordinary fields rather than
+ // routing padding through the union's single tail-padding slot.
if (nonVirtualBaseType) {
- // The base-subobject record is built as a struct from fieldTypes, so add
- // the storage type and any trailing padding as ordinary fields rather than
- // routing padding through the union's single tail-padding slot.
+ fieldTypes.clear();
----------------
andykaylor wrote:
I don't understand why we only want the storage type in this case.
https://github.com/llvm/llvm-project/pull/210709
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits