[clang] [CIR] Upstream support for record packing and padding (PR #136036)
Andy Kaylor via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 17 15:31:50 PDT 2025
================
@@ -225,17 +235,88 @@ void RecordType::complete(ArrayRef<Type> members, bool packed, bool padded) {
//===----------------------------------------------------------------------===//
llvm::TypeSize
-RecordType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
- ::mlir::DataLayoutEntryListRef params) const {
- assert(!cir::MissingFeatures::recordTypeLayoutInfo());
- return llvm::TypeSize::getFixed(8);
+RecordType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
+ mlir::DataLayoutEntryListRef params) const {
+ if (isUnion()) {
+ // TODO(CIR): Implement union layout.
+ return llvm::TypeSize::getFixed(8);
+ }
+
+ unsigned recordSize = computeStructSize(dataLayout);
+ return llvm::TypeSize::getFixed(recordSize * 8);
}
uint64_t
RecordType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
::mlir::DataLayoutEntryListRef params) const {
- assert(!cir::MissingFeatures::recordTypeLayoutInfo());
- return 4;
+ if (isUnion()) {
+ // TODO(CIR): Implement union layout.
+ return 8;
+ }
+
+ // Packed structures always have an ABI alignment of 1.
+ if (getPacked())
+ return 1;
+ return computeStructAlignment(dataLayout);
+}
+
+unsigned
+RecordType::computeStructSize(const mlir::DataLayout &dataLayout) const {
+ assert(isComplete() && "Cannot get layout of incomplete records");
+
+ // This is a similar algorithm to LLVM's StructLayout.
+ unsigned recordSize = 0;
+ uint64_t recordAlignment = 1;
+
+ // We can't use a range-based for loop here because we might be ignoring the
+ // last element.
+ for (mlir::Type ty : getMembers()) {
+ // This assumes that we're calculating size based on the ABI alignment, not
+ // the preferred alignment for each type.
+ const uint64_t tyAlign =
+ (getPacked() ? 1 : dataLayout.getTypeABIAlignment(ty));
+
+ // This should be aligned because the padding is inserted when we build
+ // the record.
+ assert(llvm::isAligned(llvm::Align(tyAlign), recordSize));
+
+ // Add padding to the struct size to align it to the abi alignment of the
+ // element type before than adding the size of the element.
+ recordSize = llvm::alignTo(recordSize, tyAlign);
+ recordSize += dataLayout.getTypeSize(ty);
+
+ // The alignment requirement of a struct is equal to the strictest alignment
+ // requirement of its elements.
+ recordAlignment = std::max(tyAlign, recordAlignment);
+ }
+
+ // Add padding to the end of the record so that it could be put in an array
+ // and all array elements would be aligned correctly.
+ assert(llvm::isAligned(llvm::Align(recordAlignment), recordSize));
+ // if (!llvm::isAligned(recordAlignment, recordSize))
----------------
andykaylor wrote:
This shouldn't be here.
https://github.com/llvm/llvm-project/pull/136036
More information about the cfe-commits
mailing list