Skip to content

Commit ae3e0ad

Browse files
committed
[CIR] Extend StructLayoutAttr to support querying offset for members
Testcase not added because we are not using the printers and parsers, but upcoming atomic work will exercise the path and testcases.
1 parent 2062ac6 commit ae3e0ad

File tree

4 files changed

+36
-11
lines changed

4 files changed

+36
-11
lines changed

clang/include/clang/CIR/Dialect/IR/CIRAttrs.td

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -521,28 +521,31 @@ def VTableAttr : CIR_Attr<"VTable", "vtable", [TypedAttrInterface]> {
521521
def StructLayoutAttr : CIR_Attr<"StructLayout", "struct_layout"> {
522522
let summary = "ABI specific information about a struct layout";
523523
let description = [{
524+
Holds layout information often queried by !cir.struct users
525+
during lowering passes and optimizations.
524526
}];
525527

526528
let parameters = (ins "unsigned":$size,
527529
"unsigned":$alignment,
528530
"bool":$padded,
529-
"mlir::Type":$largest_member);
531+
"mlir::Type":$largest_member,
532+
"mlir::ArrayAttr":$offsets);
530533

531534
let builders = [
532535
AttrBuilderWithInferredContext<(ins "unsigned":$size,
533536
"unsigned":$alignment,
534537
"bool":$padded,
535-
"mlir::Type":$largest_member
536-
), [{
538+
"mlir::Type":$largest_member,
539+
"mlir::ArrayAttr":$offsets), [{
537540
return $_get(largest_member.getContext(), size, alignment, padded,
538-
largest_member);
541+
largest_member, offsets);
539542
}]>,
540543
];
541544

542545
let genVerifyDecl = 1;
543546
let assemblyFormat = [{
544547
`<`
545-
struct($size, $alignment, $padded, $largest_member)
548+
struct($size, $alignment, $padded, $largest_member, $offsets)
546549
`>`
547550
}];
548551
}

clang/include/clang/CIR/Dialect/IR/CIRTypes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ class StructType
172172
// instead.
173173
mutable mlir::Attribute layoutInfo;
174174
bool isPadded(const DataLayout &dataLayout) const;
175+
uint64_t getElementOffset(const DataLayout &dataLayout, unsigned idx) const;
176+
175177
void computeSizeAndAlignment(const DataLayout &dataLayout) const;
176178
};
177179

clang/lib/CIR/Dialect/IR/CIRAttrs.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,13 @@ LogicalResult ConstStructAttr::verify(
167167

168168
LogicalResult StructLayoutAttr::verify(
169169
::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError, unsigned size,
170-
unsigned alignment, bool padded, mlir::Type largest_member) {
170+
unsigned alignment, bool padded, mlir::Type largest_member,
171+
mlir::ArrayAttr offsets) {
172+
if (not std::all_of(offsets.begin(), offsets.end(), [](mlir::Attribute attr) {
173+
return attr.isa<mlir::IntegerAttr>();
174+
})) {
175+
return emitError() << "all index values must be integers";
176+
}
171177
return success();
172178
}
173179

clang/lib/CIR/Dialect/IR/CIRTypes.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,16 @@ bool StructType::isPadded(const ::mlir::DataLayout &dataLayout) const {
498498
return layoutInfo.cast<mlir::cir::StructLayoutAttr>().getPadded();
499499
}
500500

501+
uint64_t StructType::getElementOffset(const ::mlir::DataLayout &dataLayout,
502+
unsigned idx) const {
503+
assert(idx < getMembers().size() && "access not valid");
504+
if (!layoutInfo)
505+
computeSizeAndAlignment(dataLayout);
506+
auto offsets = layoutInfo.cast<mlir::cir::StructLayoutAttr>().getOffsets();
507+
auto intAttr = offsets[idx].cast<mlir::IntegerAttr>();
508+
return intAttr.getInt();
509+
}
510+
501511
void StructType::computeSizeAndAlignment(
502512
const ::mlir::DataLayout &dataLayout) const {
503513
assert(isComplete() && "Cannot get layout of incomplete structs");
@@ -513,8 +523,10 @@ void StructType::computeSizeAndAlignment(
513523
auto members = getMembers();
514524
mlir::Type largestMember;
515525
unsigned largestMemberSize = 0;
526+
SmallVector<mlir::Attribute, 4> memberOffsets;
516527

517528
// Loop over each of the elements, placing them in memory.
529+
memberOffsets.reserve(numElements);
518530
for (unsigned i = 0, e = numElements; i != e; ++i) {
519531
auto ty = members[i];
520532

@@ -544,8 +556,9 @@ void StructType::computeSizeAndAlignment(
544556
// Keep track of maximum alignment constraint.
545557
structAlignment = std::max(tyAlign, structAlignment);
546558

547-
// FIXME: track struct size up to each element.
548-
// getMemberOffsets()[i] = structSize;
559+
// Struct size up to each element is the element offset.
560+
memberOffsets.push_back(mlir::IntegerAttr::get(
561+
mlir::IntegerType::get(getContext(), 32), structSize));
549562

550563
// Consume space for this data item
551564
structSize += dataLayout.getTypeSize(ty);
@@ -564,9 +577,10 @@ void StructType::computeSizeAndAlignment(
564577
}
565578
}
566579

567-
layoutInfo = mlir::cir::StructLayoutAttr::get(getContext(), structSize,
568-
structAlignment.value(),
569-
isPadded, largestMember);
580+
auto offsets = mlir::ArrayAttr::get(getContext(), memberOffsets);
581+
layoutInfo = mlir::cir::StructLayoutAttr::get(
582+
getContext(), structSize, structAlignment.value(), isPadded,
583+
largestMember, offsets);
570584
}
571585

572586
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)