Skip to content

Commit 17d84f7

Browse files
committed
Invalidate struct layout cache
1 parent a9bb740 commit 17d84f7

File tree

2 files changed

+42
-24
lines changed

2 files changed

+42
-24
lines changed

llvm/lib/IR/DataLayout.cpp

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,29 @@ unsigned StructLayout::getElementContainingOffset(uint64_t FixedOffset) const {
117117
return SI - MemberOffsets.begin();
118118
}
119119

120+
namespace {
121+
122+
class StructLayoutMap {
123+
using LayoutInfoTy = DenseMap<StructType*, StructLayout*>;
124+
LayoutInfoTy LayoutInfo;
125+
126+
public:
127+
~StructLayoutMap() {
128+
// Remove any layouts.
129+
for (const auto &I : LayoutInfo) {
130+
StructLayout *Value = I.second;
131+
Value->~StructLayout();
132+
free(Value);
133+
}
134+
}
135+
136+
StructLayout *&operator[](StructType *STy) {
137+
return LayoutInfo[STy];
138+
}
139+
};
140+
141+
} // end anonymous namespace
142+
120143
//===----------------------------------------------------------------------===//
121144
// LayoutAlignElem, LayoutAlign support
122145
//===----------------------------------------------------------------------===//
@@ -214,7 +237,8 @@ DataLayout::DataLayout(StringRef LayoutString) {
214237
}
215238

216239
DataLayout &DataLayout::operator=(const DataLayout &Other) {
217-
// Copy everything except for LayoutMap, which will be recomputed on demand.
240+
delete static_cast<StructLayoutMap *>(LayoutMap);
241+
LayoutMap = nullptr;
218242
StringRepresentation = Other.StringRepresentation;
219243
BigEndian = Other.BigEndian;
220244
AllocaAddrSpace = Other.AllocaAddrSpace;
@@ -687,29 +711,6 @@ Align DataLayout::getIntegerAlignment(uint32_t BitWidth,
687711
return abi_or_pref ? I->ABIAlign : I->PrefAlign;
688712
}
689713

690-
namespace {
691-
692-
class StructLayoutMap {
693-
using LayoutInfoTy = DenseMap<StructType*, StructLayout*>;
694-
LayoutInfoTy LayoutInfo;
695-
696-
public:
697-
~StructLayoutMap() {
698-
// Remove any layouts.
699-
for (const auto &I : LayoutInfo) {
700-
StructLayout *Value = I.second;
701-
Value->~StructLayout();
702-
free(Value);
703-
}
704-
}
705-
706-
StructLayout *&operator[](StructType *STy) {
707-
return LayoutInfo[STy];
708-
}
709-
};
710-
711-
} // end anonymous namespace
712-
713714
DataLayout::~DataLayout() { delete static_cast<StructLayoutMap *>(LayoutMap); }
714715

715716
const StructLayout *DataLayout::getStructLayout(StructType *Ty) const {

llvm/unittests/IR/DataLayoutTest.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,23 @@ using namespace llvm;
1919

2020
namespace {
2121

22+
TEST(DataLayoutTest, CopyAssignmentInvalidatesStructLayout) {
23+
DataLayout DL1 = cantFail(DataLayout::parse("p:32:32"));
24+
DataLayout DL2 = cantFail(DataLayout::parse("p:64:64"));
25+
26+
LLVMContext Ctx;
27+
StructType *Ty = StructType::get(PointerType::getUnqual(Ctx));
28+
29+
// Initialize struct layout caches.
30+
EXPECT_EQ(DL1.getStructLayout(Ty)->getAlignment(), Align(4));
31+
EXPECT_EQ(DL2.getStructLayout(Ty)->getAlignment(), Align(8));
32+
33+
// The copy should invalidate DL1's cache.
34+
DL1 = DL2;
35+
EXPECT_EQ(DL1.getStructLayout(Ty)->getAlignment(), Align(8));
36+
EXPECT_EQ(DL2.getStructLayout(Ty)->getAlignment(), Align(8));
37+
}
38+
2239
TEST(DataLayoutTest, FunctionPtrAlign) {
2340
EXPECT_EQ(MaybeAlign(0), DataLayout("").getFunctionPtrAlign());
2441
EXPECT_EQ(MaybeAlign(1), DataLayout("Fi8").getFunctionPtrAlign());

0 commit comments

Comments
 (0)