When we decide to output a deferred decl, remember the llvm GlobalValue.

We can reuse it to avoid a DenseMap+StringMap lookup to find if it was already
emitted or not.

This fixes a 2010 TODO.

llvm-svn: 196785
This commit is contained in:
Rafael Espindola
2013-12-09 14:59:08 +00:00
parent c3cde36ead
commit c0ff7448d7
3 changed files with 37 additions and 24 deletions

View File

@@ -233,6 +233,10 @@ void CodeGenModule::checkAliases() {
}
}
void CodeGenModule::clear() {
DeferredDeclsToEmit.clear();
}
void CodeGenModule::Release() {
EmitDeferred();
applyReplacements();
@@ -1002,22 +1006,19 @@ void CodeGenModule::EmitDeferred() {
// Stop if we're out of both deferred v-tables and deferred declarations.
if (DeferredDeclsToEmit.empty()) break;
GlobalDecl D = DeferredDeclsToEmit.back();
DeferredGlobal &G = DeferredDeclsToEmit.back();
GlobalDecl D = G.GD;
llvm::GlobalValue *GV = G.GV;
DeferredDeclsToEmit.pop_back();
assert(GV == GetGlobalValue(getMangledName(D)));
// Check to see if we've already emitted this. This is necessary
// for a couple of reasons: first, decls can end up in the
// deferred-decls queue multiple times, and second, decls can end
// up with definitions in unusual ways (e.g. by an extern inline
// function acquiring a strong function redefinition). Just
// ignore these cases.
//
// TODO: That said, looking this up multiple times is very wasteful.
StringRef Name = getMangledName(D);
llvm::GlobalValue *CGRef = GetGlobalValue(Name);
assert(CGRef && "Deferred decl wasn't referenced?");
if (!CGRef->isDeclaration())
if(!GV->isDeclaration())
continue;
// Otherwise, emit the definition and move on to the next one.
@@ -1226,8 +1227,8 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
// If the value has already been used, add it directly to the
// DeferredDeclsToEmit list.
StringRef MangledName = getMangledName(GD);
if (GetGlobalValue(MangledName))
DeferredDeclsToEmit.push_back(GD);
if (llvm::GlobalValue *GV = GetGlobalValue(MangledName))
addDeferredDeclToEmit(GV, GD);
else {
// Otherwise, remember that we saw a deferred decl with this name. The
// first use of the mangled name will cause it to move into
@@ -1428,7 +1429,7 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
if (D && isa<CXXDestructorDecl>(D) &&
getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(D),
GD.getDtorType()))
DeferredDeclsToEmit.push_back(GD);
addDeferredDeclToEmit(F, GD);
// This is the first use or definition of a mangled name. If there is a
// deferred decl with this name, remember that we need to emit it at the end
@@ -1438,7 +1439,7 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
// Move the potentially referenced deferred decl to the
// DeferredDeclsToEmit list, and remove it from DeferredDecls (since we
// don't need it anymore).
DeferredDeclsToEmit.push_back(DDI->second);
addDeferredDeclToEmit(F, DDI->second);
DeferredDecls.erase(DDI);
// Otherwise, if this is a sized deallocation function, emit a weak
@@ -1446,7 +1447,7 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
// for it at the end of the translation unit.
} else if (D && cast<FunctionDecl>(D)
->getCorrespondingUnsizedGlobalDeallocationFunction()) {
DeferredDeclsToEmit.push_back(GD);
addDeferredDeclToEmit(F, GD);
// Otherwise, there are cases we have to worry about where we're
// using a declaration for which we must emit a definition but where
@@ -1469,10 +1470,10 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
if (FD->isImplicit() && !ForVTable) {
assert(FD->isUsed() &&
"Sema didn't mark implicit function as used!");
DeferredDeclsToEmit.push_back(GD.getWithDecl(FD));
addDeferredDeclToEmit(F, GD.getWithDecl(FD));
break;
} else if (FD->doesThisDeclarationHaveABody()) {
DeferredDeclsToEmit.push_back(GD.getWithDecl(FD));
addDeferredDeclToEmit(F, GD.getWithDecl(FD));
break;
}
}
@@ -1574,6 +1575,13 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
return llvm::ConstantExpr::getBitCast(Entry, Ty);
}
unsigned AddrSpace = GetGlobalVarAddressSpace(D, Ty->getAddressSpace());
llvm::GlobalVariable *GV =
new llvm::GlobalVariable(getModule(), Ty->getElementType(), false,
llvm::GlobalValue::ExternalLinkage,
0, MangledName, 0,
llvm::GlobalVariable::NotThreadLocal, AddrSpace);
// This is the first use or definition of a mangled name. If there is a
// deferred decl with this name, remember that we need to emit it at the end
// of the file.
@@ -1581,17 +1589,10 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
if (DDI != DeferredDecls.end()) {
// Move the potentially referenced deferred decl to the DeferredDeclsToEmit
// list, and remove it from DeferredDecls (since we don't need it anymore).
DeferredDeclsToEmit.push_back(DDI->second);
addDeferredDeclToEmit(GV, DDI->second);
DeferredDecls.erase(DDI);
}
unsigned AddrSpace = GetGlobalVarAddressSpace(D, Ty->getAddressSpace());
llvm::GlobalVariable *GV =
new llvm::GlobalVariable(getModule(), Ty->getElementType(), false,
llvm::GlobalValue::ExternalLinkage,
0, MangledName, 0,
llvm::GlobalVariable::NotThreadLocal, AddrSpace);
// Handle things which are present even on external declarations.
if (D) {
// FIXME: This code is overly simple and should be merged with other global

View File

@@ -273,7 +273,15 @@ class CodeGenModule : public CodeGenTypeCache {
/// DeferredDeclsToEmit - This is a list of deferred decls which we have seen
/// that *are* actually referenced. These get code generated when the module
/// is done.
std::vector<GlobalDecl> DeferredDeclsToEmit;
struct DeferredGlobal {
DeferredGlobal(llvm::GlobalValue *GV, GlobalDecl GD) : GV(GV), GD(GD) {}
llvm::AssertingVH<llvm::GlobalValue> GV;
GlobalDecl GD;
};
std::vector<DeferredGlobal> DeferredDeclsToEmit;
void addDeferredDeclToEmit(llvm::GlobalValue *GV, GlobalDecl GD) {
DeferredDeclsToEmit.push_back(DeferredGlobal(GV, GD));
}
/// List of alias we have emitted. Used to make sure that what they point to
/// is defined once we get to the end of the of the translation unit.
@@ -433,6 +441,8 @@ public:
~CodeGenModule();
void clear();
/// Release - Finalize LLVM code generation.
void Release();

View File

@@ -117,6 +117,8 @@ namespace {
virtual void HandleTranslationUnit(ASTContext &Ctx) {
if (Diags.hasErrorOccurred()) {
if (Builder)
Builder->clear();
M.reset();
return;
}