llvm.org GIT mirror llvm / cf8b959
BitcodeReader: Fix some BlockAddress forward reference corner cases `BlockAddress`es are interesting in that they can reference basic blocks from *outside* the block's function. Since basic blocks are not global values, this presents particular challenges for lazy parsing. One corner case was found in PR11677 and fixed in r147425. In that case, a global variable references a block address. It's necessary to load the relevant function to resolve the forward reference before doing anything with the module. By inspection, I found (and have fixed here) two other cases: - An instruction from one function references a block address from another function, and only the first function is lazily loaded. I fixed this the same way as PR11677: by eagerly loading the referenced function. - A function whose block address is taken is dematerialized, leaving invalid references to it. I fixed this by refusing to dematerialize functions whose block addresses are taken (if you have to load it, you can't unload it). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@214559 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan P. N. Exon Smith 5 years ago
4 changed file(s) with 136 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
159159 InvalidMultipleBlocks, // We found multiple blocks of a kind that should
160160 // have only one
161161 NeverResolvedValueFoundInFunction,
162 NeverResolvedFunctionFromBlockAddress,
162163 InvalidValue // Invalid version, inst number, attr number, etc
163164 };
164165 inline std::error_code make_error_code(BitcodeError E) {
3030 SWITCH_INST_MAGIC = 0x4B5 // May 2012 => 1205 => Hex
3131 };
3232
33 void BitcodeReader::materializeForwardReferencedFunctions() {
33 std::error_code BitcodeReader::materializeForwardReferencedFunctions() {
34 if (WillMaterializeAllForwardRefs)
35 return std::error_code();
36
37 // Prevent recursion.
38 WillMaterializeAllForwardRefs = true;
39
3440 while (!BlockAddrFwdRefs.empty()) {
3541 Function *F = BlockAddrFwdRefs.begin()->first;
36 F->Materialize();
37 }
42 assert(F && "Expected valid function");
43 // Check for a function that isn't materializable to prevent an infinite
44 // loop. When parsing a blockaddress stored in a global variable, there
45 // isn't a trivial way to check if a function will have a body without a
46 // linear search through FunctionsWithBodies, so just check it here.
47 if (!F->isMaterializable())
48 return Error(BitcodeError::NeverResolvedFunctionFromBlockAddress);
49
50 // Try to materialize F.
51 if (std::error_code EC = Materialize(F))
52 return EC;
53 }
54
55 // Reset state.
56 WillMaterializeAllForwardRefs = false;
57 return std::error_code();
3858 }
3959
4060 void BitcodeReader::FreeState() {
15861606 if (!Fn)
15871607 return Error(BitcodeError::InvalidRecord);
15881608
1609 // Don't let Fn get dematerialized.
1610 BlockAddressesTaken.insert(Fn);
1611
15891612 // If the function is already parsed we can insert the block address right
15901613 // away.
15911614 if (!Fn->empty()) {
32733296 }
32743297 }
32753298
3276 return std::error_code();
3299 // Bring in any functions that this function forward-referenced via
3300 // blockaddresses.
3301 return materializeForwardReferencedFunctions();
32773302 }
32783303
32793304 bool BitcodeReader::isDematerializable(const GlobalValue *GV) const {
32803305 const Function *F = dyn_cast(GV);
32813306 if (!F || F->isDeclaration())
32823307 return false;
3308
3309 // Dematerializing F would leave dangling references that wouldn't be
3310 // reconnected on re-materialization.
3311 if (BlockAddressesTaken.count(F))
3312 return false;
3313
32833314 return DeferredFunctionInfo.count(const_cast(F));
32843315 }
32853316
32983329 std::error_code BitcodeReader::MaterializeModule(Module *M) {
32993330 assert(M == TheModule &&
33003331 "Can only Materialize the Module this BitcodeReader is attached to.");
3332
3333 // Promise to materialize all forward references.
3334 WillMaterializeAllForwardRefs = true;
3335
33013336 // Iterate over the module, deserializing any functions that are still on
33023337 // disk.
33033338 for (Module::iterator F = TheModule->begin(), E = TheModule->end();
33123347 // of the bits in the module have been read.
33133348 if (NextUnreadBit)
33143349 ParseModule(true);
3350
3351 // Check that all block address forward references got resolved (as we
3352 // promised above).
3353 if (!BlockAddrFwdRefs.empty())
3354 return Error(BitcodeError::NeverResolvedFunctionFromBlockAddress);
33153355
33163356 // Upgrade any intrinsic calls that slipped through (should not happen!) and
33173357 // delete the old functions to clean up. We can't do this unless the entire
34303470 return "Invalid multiple blocks";
34313471 case BitcodeError::NeverResolvedValueFoundInFunction:
34323472 return "Never resolved value found in function";
3473 case BitcodeError::NeverResolvedFunctionFromBlockAddress:
3474 return "Never resolved function from blockaddress";
34333475 case BitcodeError::InvalidValue:
34343476 return "Invalid value";
34353477 }
34543496 Module *M = new Module(Buffer->getBufferIdentifier(), Context);
34553497 BitcodeReader *R = new BitcodeReader(Buffer, Context);
34563498 M->setMaterializer(R);
3457 if (std::error_code EC = R->ParseBitcodeInto(M)) {
3499
3500 auto cleanupOnError = [&](std::error_code EC) {
34583501 R->releaseBuffer(); // Never take ownership on error.
34593502 delete M; // Also deletes R.
34603503 return EC;
3461 }
3462
3463 R->materializeForwardReferencedFunctions();
3504 };
3505
3506 if (std::error_code EC = R->ParseBitcodeInto(M))
3507 return cleanupOnError(EC);
3508
3509 if (std::error_code EC = R->materializeForwardReferencedFunctions())
3510 return cleanupOnError(EC);
34643511
34653512 return M;
34663513 }
192192 /// not need this flag.
193193 bool UseRelativeIDs;
194194
195 /// True if all functions will be materialized, negating the need to process
196 /// (e.g.) blockaddress forward references.
197 bool WillMaterializeAllForwardRefs;
198
199 /// Functions that have block addresses taken. This is usually empty.
200 SmallPtrSet BlockAddressesTaken;
201
195202 public:
196203 std::error_code Error(BitcodeError E) { return make_error_code(E); }
197204
198205 explicit BitcodeReader(MemoryBuffer *buffer, LLVMContext &C)
199206 : Context(C), TheModule(nullptr), Buffer(buffer), LazyStreamer(nullptr),
200207 NextUnreadBit(0), SeenValueSymbolTable(false), ValueList(C),
201 MDValueList(C), SeenFirstFunctionBody(false), UseRelativeIDs(false) {}
208 MDValueList(C), SeenFirstFunctionBody(false), UseRelativeIDs(false),
209 WillMaterializeAllForwardRefs(false) {}
202210 explicit BitcodeReader(DataStreamer *streamer, LLVMContext &C)
203211 : Context(C), TheModule(nullptr), Buffer(nullptr), LazyStreamer(streamer),
204212 NextUnreadBit(0), SeenValueSymbolTable(false), ValueList(C),
205 MDValueList(C), SeenFirstFunctionBody(false), UseRelativeIDs(false) {}
213 MDValueList(C), SeenFirstFunctionBody(false), UseRelativeIDs(false),
214 WillMaterializeAllForwardRefs(false) {}
206215 ~BitcodeReader() { FreeState(); }
207216
208 void materializeForwardReferencedFunctions();
217 std::error_code materializeForwardReferencedFunctions();
209218
210219 void FreeState();
211220
6969 " unreachable\n"
7070 "}\n");
7171 EXPECT_FALSE(verifyModule(*M, &dbgs()));
72
73 // Try (and fail) to dematerialize @func.
74 M->getFunction("func")->Dematerialize();
75 EXPECT_FALSE(M->getFunction("func")->empty());
76 }
77
78 TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) {
79 SmallString<1024> Mem;
80
81 LLVMContext Context;
82 std::unique_ptr M = getLazyModuleFromAssembly(
83 Context, Mem, "define i8* @before() {\n"
84 " ret i8* blockaddress(@func, %bb)\n"
85 "}\n"
86 "define void @other() {\n"
87 " unreachable\n"
88 "}\n"
89 "define void @func() {\n"
90 " unreachable\n"
91 "bb:\n"
92 " unreachable\n"
93 "}\n");
94 EXPECT_TRUE(M->getFunction("before")->empty());
95 EXPECT_TRUE(M->getFunction("func")->empty());
96 EXPECT_FALSE(verifyModule(*M, &dbgs()));
97
98 // Materialize @before, pulling in @func.
99 EXPECT_FALSE(M->getFunction("before")->Materialize());
100 EXPECT_FALSE(M->getFunction("func")->empty());
101 EXPECT_TRUE(M->getFunction("other")->empty());
102 EXPECT_FALSE(verifyModule(*M, &dbgs()));
103
104 // Try (and fail) to dematerialize @func.
105 M->getFunction("func")->Dematerialize();
106 EXPECT_FALSE(M->getFunction("func")->empty());
107 EXPECT_FALSE(verifyModule(*M, &dbgs()));
108 }
109
110 TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionAfter) {
111 SmallString<1024> Mem;
112
113 LLVMContext Context;
114 std::unique_ptr M = getLazyModuleFromAssembly(
115 Context, Mem, "define void @func() {\n"
116 " unreachable\n"
117 "bb:\n"
118 " unreachable\n"
119 "}\n"
120 "define void @other() {\n"
121 " unreachable\n"
122 "}\n"
123 "define i8* @after() {\n"
124 " ret i8* blockaddress(@func, %bb)\n"
125 "}\n");
126 EXPECT_TRUE(M->getFunction("after")->empty());
127 EXPECT_TRUE(M->getFunction("func")->empty());
128 EXPECT_FALSE(verifyModule(*M, &dbgs()));
129
130 // Materialize @after, pulling in @func.
131 EXPECT_FALSE(M->getFunction("after")->Materialize());
132 EXPECT_FALSE(M->getFunction("func")->empty());
133 EXPECT_TRUE(M->getFunction("other")->empty());
134 EXPECT_FALSE(verifyModule(*M, &dbgs()));
135
136 // Try (and fail) to dematerialize @func.
137 M->getFunction("func")->Dematerialize();
138 EXPECT_FALSE(M->getFunction("func")->empty());
139 EXPECT_FALSE(verifyModule(*M, &dbgs()));
72140 }
73141
74142 } // end namespace