Skip to content

Commit 751a3da

Browse files
committed
[clang-repl] Keep the first llvm::Module empty to avoid invalid memory access.
Clang's CodeGen is designed to work with a single llvm::Module. In many cases for convenience various CodeGen parts have a reference to the llvm::Module (TheModule or Module) which does not change when a new module is pushed. However, the execution engine wants to take ownership of the module which does not map well to CodeGen's design. To work this around we clone the module and pass it down. With some effort it is possible to teach CodeGen to ask the CodeGenModule for its current module and that would have an overall positive impact on CodeGen improving the encapsulation of various parts but that's not resilient to future regression. This patch takes a more conservative approach and keeps the first llvm::Module empty intentionally and does not pass it to the Jit. That's also not bullet proof because we have to guarantee that CodeGen does not write on the blueprint. However, we have inserted some assertions to catch accidental additions to that canary module. This change will fixes a long-standing invalid memory access reported by valgrind when we enable the TBAA optimization passes. It also unblock progress on #84758.
1 parent a810502 commit 751a3da

File tree

2 files changed

+25
-5
lines changed

2 files changed

+25
-5
lines changed

clang/lib/Interpreter/IncrementalParser.cpp

+20-5
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,10 @@ IncrementalParser::IncrementalParser(Interpreter &Interp,
209209
if (Err)
210210
return;
211211
CI->ExecuteAction(*Act);
212+
213+
if (getCodeGen())
214+
CachedInCodeGenModule = std::move(GenModule());
215+
212216
std::unique_ptr<ASTConsumer> IncrConsumer =
213217
std::make_unique<IncrementalASTConsumer>(Interp, CI->takeASTConsumer());
214218
CI->setASTConsumer(std::move(IncrConsumer));
@@ -224,11 +228,8 @@ IncrementalParser::IncrementalParser(Interpreter &Interp,
224228
return; // PTU.takeError();
225229
}
226230

227-
if (CodeGenerator *CG = getCodeGen()) {
228-
std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
229-
CG->StartModule("incr_module_" + std::to_string(PTUs.size()),
230-
M->getContext());
231-
PTU->TheModule = std::move(M);
231+
if (getCodeGen()) {
232+
PTU->TheModule = std::move(GenModule());
232233
assert(PTU->TheModule && "Failed to create initial PTU");
233234
}
234235
}
@@ -364,6 +365,20 @@ IncrementalParser::Parse(llvm::StringRef input) {
364365
std::unique_ptr<llvm::Module> IncrementalParser::GenModule() {
365366
static unsigned ID = 0;
366367
if (CodeGenerator *CG = getCodeGen()) {
368+
// Clang's CodeGen is designed to work with a single llvm::Module. In many
369+
// cases for convenience various CodeGen parts have a reference to the
370+
// llvm::Module (TheModule or Module) which does not change when a new
371+
// module is pushed. However, the execution engine wants to take ownership
372+
// of the module which does not map well to CodeGen's design. To work this
373+
// around we created an empty module to make CodeGen happy. We should make
374+
// sure it always stays empty.
375+
assert((!CachedInCodeGenModule ||
376+
(CachedInCodeGenModule->empty() &&
377+
CachedInCodeGenModule->global_empty() &&
378+
CachedInCodeGenModule->alias_empty() &&
379+
CachedInCodeGenModule->ifunc_empty() &&
380+
CachedInCodeGenModule->named_metadata_empty())) &&
381+
"CodeGen wrote to a readonly module");
367382
std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
368383
CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext());
369384
return M;

clang/lib/Interpreter/IncrementalParser.h

+5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <memory>
2525
namespace llvm {
2626
class LLVMContext;
27+
class Module;
2728
} // namespace llvm
2829

2930
namespace clang {
@@ -57,6 +58,10 @@ class IncrementalParser {
5758
/// of code.
5859
std::list<PartialTranslationUnit> PTUs;
5960

61+
/// When CodeGen is created the first llvm::Module gets cached in many places
62+
/// and we must keep it alive.
63+
std::unique_ptr<llvm::Module> CachedInCodeGenModule;
64+
6065
IncrementalParser();
6166

6267
public:

0 commit comments

Comments
 (0)