mirror of
https://github.com/intel/llvm.git
synced 2026-02-05 04:46:27 +08:00
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:
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -117,6 +117,8 @@ namespace {
|
||||
|
||||
virtual void HandleTranslationUnit(ASTContext &Ctx) {
|
||||
if (Diags.hasErrorOccurred()) {
|
||||
if (Builder)
|
||||
Builder->clear();
|
||||
M.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user