Skip to content

Commit 960c0b0

Browse files
[CIR] Add support for DumpRecordLayouts (#1667)
This PR adds support for the `-fdump-record-layouts` flag. It enables printing both the `CIRGenRecordLayout` and the `ASTRecordLayout`, similar to what is done in CodeGen.
1 parent 481118d commit 960c0b0

File tree

3 files changed

+110
-2
lines changed

3 files changed

+110
-2
lines changed

clang/lib/CIR/CodeGen/CIRGenRecordLayout.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ struct CIRGenBitFieldInfo {
107107
StorageSize(StorageSize), StorageOffset(StorageOffset) {}
108108

109109
void print(llvm::raw_ostream &OS) const;
110-
void dump() const;
110+
LLVM_DUMP_METHOD void dump() const;
111111

112112
/// Given a bit-field decl, build an appropriate helper object for
113113
/// accessing that field (which is expected to have the given offset and
@@ -201,6 +201,8 @@ class CIRGenRecordLayout {
201201
assert(it != BitFields.end() && "Unable to find bitfield info");
202202
return it->second;
203203
}
204+
void print(raw_ostream &os) const;
205+
LLVM_DUMP_METHOD void dump() const;
204206
};
205207

206208
} // namespace clang::CIRGen

clang/lib/CIR/CodeGen/CIRRecordLayoutBuilder.cpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -760,13 +760,55 @@ CIRGenTypes::computeRecordLayout(const RecordDecl *D, cir::RecordType *Ty) {
760760

761761
// Dump the layout, if requested.
762762
if (getContext().getLangOpts().DumpRecordLayouts) {
763-
llvm_unreachable("NYI");
763+
llvm::outs() << "\n*** Dumping CIRgen Record Layout\n";
764+
llvm::outs() << "Record: ";
765+
D->dump(llvm::outs());
766+
llvm::outs() << "\nLayout: ";
767+
RL->print(llvm::outs());
764768
}
765769

766770
// TODO: implement verification
767771
return RL;
768772
}
769773

774+
void CIRGenRecordLayout::print(raw_ostream &os) const {
775+
os << "<CIRecordLayout\n";
776+
os << " CIR Type:" << CompleteObjectType << "\n";
777+
if (BaseSubobjectType)
778+
os << " NonVirtualBaseCIRType:" << BaseSubobjectType << "\n";
779+
os << " IsZeroInitializable:" << IsZeroInitializable << "\n";
780+
os << " BitFields:[\n";
781+
std::vector<std::pair<unsigned, const CIRGenBitFieldInfo *>> bitInfo;
782+
for (auto &[decl, info] : BitFields) {
783+
const RecordDecl *rd = decl->getParent();
784+
unsigned index = 0;
785+
for (RecordDecl::field_iterator it = rd->field_begin(); *it != decl; ++it)
786+
++index;
787+
bitInfo.push_back(std::make_pair(index, &info));
788+
}
789+
llvm::array_pod_sort(bitInfo.begin(), bitInfo.end());
790+
for (auto &info : bitInfo) {
791+
os.indent(4);
792+
info.second->print(os);
793+
os << "\n";
794+
}
795+
os << " ]>\n";
796+
}
797+
798+
void CIRGenRecordLayout::dump() const { print(llvm::errs()); }
799+
800+
void CIRGenBitFieldInfo::print(raw_ostream &os) const {
801+
os << "<CIRBitFieldInfo" << " name:" << Name << " offset:" << Offset
802+
<< " size:" << Size << " isSigned:" << IsSigned
803+
<< " storageSize:" << StorageSize
804+
<< " storageOffset:" << StorageOffset.getQuantity()
805+
<< " volatileOffset:" << VolatileOffset
806+
<< " volatileStorageSize:" << VolatileStorageSize
807+
<< " volatileStorageOffset:" << VolatileStorageOffset.getQuantity() << ">";
808+
}
809+
810+
void CIRGenBitFieldInfo::dump() const { print(llvm::errs()); }
811+
770812
CIRGenBitFieldInfo CIRGenBitFieldInfo::MakeInfo(CIRGenTypes &Types,
771813
const FieldDecl *FD,
772814
uint64_t Offset, uint64_t Size,
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -fdump-record-layouts %s -o - | FileCheck %s
2+
3+
struct SimpleStruct {
4+
int a;
5+
float b;
6+
} simple;
7+
// CHECK: Layout: <CIRecordLayout
8+
// CHECK: CIR Type:!cir.record<struct "SimpleStruct" {!cir.int<s, 32>, !cir.float} #cir.record.decl.ast>
9+
// CHECK: NonVirtualBaseCIRType:!cir.record<struct "SimpleStruct" {!cir.int<s, 32>, !cir.float} #cir.record.decl.ast>
10+
// CHECK: IsZeroInitializable:1
11+
// CHECK: BitFields:[
12+
// CHECK: ]>
13+
14+
struct Empty {
15+
} empty;
16+
17+
// CHECK: Layout: <CIRecordLayout
18+
// CHECK: CIR Type:!cir.record<struct "Empty" padded {!cir.int<u, 8>} #cir.record.decl.ast>
19+
// CHECK: NonVirtualBaseCIRType:!cir.record<struct "Empty" padded {!cir.int<u, 8>} #cir.record.decl.ast>
20+
// CHECK: IsZeroInitializable:1
21+
// CHECK: BitFields:[
22+
// CHECK: ]>
23+
24+
struct BitfieldsInOrder {
25+
char a;
26+
unsigned bit: 8;
27+
unsigned should : 20;
28+
unsigned have: 3;
29+
unsigned order: 1;
30+
} bitfield_order;
31+
32+
// CHECK: Layout: <CIRecordLayout
33+
// CHECK: CIR Type:!cir.record<struct "BitfieldsInOrder" padded {!cir.int<s, 8>, !cir.int<u, 8>, !cir.array<!cir.int<u, 8> x 2>, !cir.array<!cir.int<u, 8> x 3>, !cir.int<u, 8>} #cir.record.decl.ast>
34+
// CHECK: NonVirtualBaseCIRType:!cir.record<struct "BitfieldsInOrder" padded {!cir.int<s, 8>, !cir.int<u, 8>, !cir.array<!cir.int<u, 8> x 2>, !cir.array<!cir.int<u, 8> x 3>, !cir.int<u, 8>} #cir.record.decl.ast>
35+
// CHECK: IsZeroInitializable:1
36+
// CHECK: BitFields:[
37+
// CHECK-NEXT: <CIRBitFieldInfo name:bit offset:0 size:8 isSigned:0 storageSize:8 storageOffset:1 volatileOffset:0 volatileStorageSize:0 volatileStorageOffset:0>
38+
// CHECK-NEXT: <CIRBitFieldInfo name:should offset:0 size:20 isSigned:0 storageSize:24 storageOffset:4 volatileOffset:0 volatileStorageSize:0 volatileStorageOffset:0>
39+
// CHECK-NEXT: <CIRBitFieldInfo name:have offset:20 size:3 isSigned:0 storageSize:24 storageOffset:4 volatileOffset:0 volatileStorageSize:0 volatileStorageOffset:0>
40+
// CHECK-NEXT: <CIRBitFieldInfo name:order offset:23 size:1 isSigned:0 storageSize:24 storageOffset:4 volatileOffset:0 volatileStorageSize:0 volatileStorageOffset:0>
41+
// CHECK:]>
42+
43+
struct Inner {
44+
int x;
45+
} in;
46+
47+
//CHECK: Layout: <CIRecordLayout
48+
//CHECK: CIR Type:!cir.record<struct "Inner" {!cir.int<s, 32>} #cir.record.decl.ast>
49+
//CHECK: NonVirtualBaseCIRType:!cir.record<struct "Inner" {!cir.int<s, 32>} #cir.record.decl.ast>
50+
//CHECK: IsZeroInitializable:1
51+
//CHECK: BitFields:[
52+
//CHECK: ]>
53+
54+
struct Outer {
55+
Inner i;
56+
int y = 6;
57+
} ou;
58+
59+
//CHECK: Layout: <CIRecordLayout
60+
//CHECK: CIR Type:!cir.record<struct "Outer" {!cir.record<struct "Inner" {!cir.int<s, 32>} #cir.record.decl.ast>, !cir.int<s, 32>} #cir.record.decl.ast>
61+
//CHECK: NonVirtualBaseCIRType:!cir.record<struct "Outer" {!cir.record<struct "Inner" {!cir.int<s, 32>} #cir.record.decl.ast>, !cir.int<s, 32>} #cir.record.decl.ast>
62+
//CHECK: IsZeroInitializable:1
63+
//CHECK: BitFields:[
64+
//CHECK: ]>

0 commit comments

Comments
 (0)