Skip to content

Commit e522ed4

Browse files
committed
Track (previously deferred) emitted symbol; put back as deferred if unloaded.
`EmittedDeferredDecls` is a map from "global value emitted because a deferred definition was needed" to the entries of the DeferredDecls to be put back when the global value is unloaded. Fix the unloading of definitions of emitted deferred symbols, and the unloading of declarations from the DeferredDecls. forgetDecl() only needs to act on weak declarations with a definition (strong symbols are emitted, those without a definition cannot enter DeferredDecls).
1 parent 2f9604c commit e522ed4

File tree

3 files changed

+43
-18
lines changed

3 files changed

+43
-18
lines changed

interpreter/llvm/src/tools/clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1332,7 +1332,6 @@ void CodeGenModule::EmitDeferred() {
13321332

13331333
// Otherwise, emit the definition and move on to the next one.
13341334
EmitGlobalDefinition(D, GV);
1335-
EmittedDeferredDecls[GV->getName()] = D;
13361335

13371336
// If we found out that we need to emit more decls, do that recursively.
13381337
// This has the advantage that the decls are emitted in a DFS and related
@@ -1971,6 +1970,7 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
19711970
// DeferredDeclsToEmit list, and remove it from DeferredDecls (since we
19721971
// don't need it anymore).
19731972
addDeferredDeclToEmit(F, DDI->second);
1973+
EmittedDeferredDecls[F] = std::make_pair(DDI->first, DDI->second);
19741974
DeferredDecls.erase(DDI);
19751975

19761976
// Otherwise, there are cases we have to worry about where we're
@@ -2168,6 +2168,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
21682168
// Move the potentially referenced deferred decl to the DeferredDeclsToEmit
21692169
// list, and remove it from DeferredDecls (since we don't need it anymore).
21702170
addDeferredDeclToEmit(GV, DDI->second);
2171+
EmittedDeferredDecls[GV] = std::make_pair(DDI->first, DDI->second);
21712172
DeferredDecls.erase(DDI);
21722173
}
21732174

interpreter/llvm/src/tools/clang/lib/CodeGen/CodeGenModule.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
#include "llvm/IR/ValueHandle.h"
3737
#include "llvm/Transforms/Utils/SanitizerStats.h"
3838

39+
#include <unordered_map>
40+
3941
namespace llvm {
4042
class Module;
4143
class Constant;
@@ -321,7 +323,11 @@ class CodeGenModule : public CodeGenTypeCache {
321323
}
322324

323325
/// Enables unloading of emitted symbols that need to become deferred.
324-
llvm::StringMap<GlobalDecl> EmittedDeferredDecls;
326+
/// Key is the emitted definition, value is symbol name + Decl created
327+
/// while marking this deferred, i.e. the content of DeferredDecls.
328+
std::unordered_map<llvm::GlobalValue*,
329+
std::pair<llvm::StringRef, GlobalDecl>>
330+
EmittedDeferredDecls;
325331

326332

327333
/// List of alias we have emitted. Used to make sure that what they point to

interpreter/llvm/src/tools/clang/lib/CodeGen/ModuleBuilder.cpp

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -287,29 +287,47 @@ namespace clang {
287287
}
288288
}
289289

290-
if (GV->isWeakForLinker() && !GV->isDeclaration()) {
291-
auto IEmittedDeferredDecl
292-
= Builder->EmittedDeferredDecls.find(GV->getName());
293-
if (IEmittedDeferredDecl != Builder->EmittedDeferredDecls.end()) {
294-
Builder->DeferredDecls[GV->getName()] = IEmittedDeferredDecl->second;
295-
Builder->EmittedDeferredDecls.erase(IEmittedDeferredDecl);
290+
if (GV->isWeakForLinker()) {
291+
if (!GV->isDeclaration()) {
292+
// This is a definition. If if was emitted as deferred, move it
293+
// back into deferred state.
294+
auto IEmittedDeferredDecl
295+
= Builder->EmittedDeferredDecls.find(GV);
296+
if (IEmittedDeferredDecl != Builder->EmittedDeferredDecls.end()) {
297+
// Use the name of the original GV, not that of our definition
298+
// that's soon to be erased.
299+
Builder->DeferredDecls[IEmittedDeferredDecl->second.first]
300+
= IEmittedDeferredDecl->second.second;
301+
Builder->EmittedDeferredDecls.erase(IEmittedDeferredDecl);
302+
}
303+
} else {
304+
// might be an entry in the deferred decls, if so: remove!
305+
auto IDeferredDecl = Builder->DeferredDecls.find(GV->getName());
306+
if (IDeferredDecl != Builder->DeferredDecls.end()) {
307+
// yes, pointer comparison.
308+
if (IDeferredDecl->first.data() == GV->getName().data())
309+
Builder->DeferredDecls.erase(IDeferredDecl);
310+
}
296311
}
297312
}
298313
}
299314

300315
void forgetDecl(const GlobalDecl& GD) {
301-
StringRef MangledName = Builder->getMangledName(GD);
302-
auto IEmittedDeferredDecl
303-
= Builder->EmittedDeferredDecls.find(MangledName);
304-
if (IEmittedDeferredDecl != Builder->EmittedDeferredDecls.end()) {
305-
assert(IEmittedDeferredDecl->getValue() == GD
306-
&& "Removing wrong EmittedDeferredDecl");
307-
Builder->EmittedDeferredDecls.erase(IEmittedDeferredDecl);
316+
if (const auto VD = dyn_cast<VarDecl>(GD.getDecl())) {
317+
if (!VD->isWeak() || !VD->isThisDeclarationADefinition())
318+
return;
319+
} else if (const auto FD = dyn_cast<FunctionDecl>(GD.getDecl())) {
320+
if (!FD->isWeak() || !FD->isThisDeclarationADefinition())
321+
return;
308322
} else {
309-
auto IDeferredDecl = Builder->DeferredDecls.find(MangledName);
310-
if (IDeferredDecl != Builder->DeferredDecls.end()) {
323+
return;
324+
}
325+
// It's a weak, defined var or function decl.
326+
StringRef MangledName = Builder->getMangledName(GD);
327+
auto IDeferredDecl = Builder->DeferredDecls.find(MangledName);
328+
if (IDeferredDecl != Builder->DeferredDecls.end()) {
329+
if (IDeferredDecl->second == GD)
311330
Builder->DeferredDecls.erase(IDeferredDecl);
312-
}
313331
}
314332
}
315333

0 commit comments

Comments
 (0)