Change CodeGen of global decls to key off of the name (instead of

having multiple bindings from all the possible decls which
  conceptually map to the same global).

 - This eliminates CodeGen depending on the LLVM module for name
   lookup.

 - This also eliminates the need for ReplaceMapValuesWith (hurrah).

 - This handles lookups for FunctionDecls correctly in the presence of
   aliases, this was previously broken.

 - WIP: Can still clean up & unify variable and function emission.

llvm-svn: 54382
This commit is contained in:
Daniel Dunbar 2008-08-05 23:31:02 +00:00
parent de565e3bc9
commit 829e988899
3 changed files with 57 additions and 97 deletions

View File

@ -426,7 +426,7 @@ void CodeGenModule::EmitStatics() {
/// EmitAnnotateAttr - Generate the llvm::ConstantStruct which contains the
/// annotation information for a given GlobalValue. The annotation struct is
/// {i8 *, i8 *, i8 *, i32}. The first field is a constant expression, the
/// GlobalValue being annotated. The second filed is thee constant string
/// GlobalValue being annotated. The second field is the constant string
/// created from the AnnotateAttr's annotation. The third field is a constant
/// string containing the name of the translation unit. The fourth field is
/// the line number in the file of the annotated value declaration.
@ -467,16 +467,6 @@ llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV,
return llvm::ConstantStruct::get(Fields, 4, false);
}
/// ReplaceMapValuesWith - This is a really slow and bad function that
/// searches for any entries in GlobalDeclMap that point to OldVal, changing
/// them to point to NewVal. This is badbadbad, FIXME!
void CodeGenModule::ReplaceMapValuesWith(llvm::GlobalValue *OldVal,
llvm::GlobalValue *NewVal) {
for (llvm::DenseMap<const Decl*, llvm::GlobalValue*>::iterator
I = GlobalDeclMap.begin(), E = GlobalDeclMap.end(); I != E; ++I)
if (I->second == OldVal) I->second = NewVal;
}
void CodeGenModule::EmitGlobal(const ValueDecl *Global) {
bool isDef, isStatic;
@ -526,26 +516,14 @@ void CodeGenModule::EmitGlobalDefinition(const ValueDecl *D) {
const llvm::Type *Ty = getTypes().ConvertTypeForMem(ASTTy);
const llvm::Type *PTy = llvm::PointerType::get(Ty, ASTTy.getAddressSpace());
// See if it is already in the map.
llvm::GlobalValue *&Entry = GlobalDeclMap[D];
// If not look for an existing global (if this decl shadows another
// one) or lazily create a forward declaration.
if (!Entry) {
// Check to see if the global already exists.
llvm::GlobalVariable *GV = getModule().getGlobalVariable(D->getName(), true);
// Create it if not.
if (!GV)
GV = new llvm::GlobalVariable(Ty, false,
llvm::GlobalValue::ExternalLinkage,
0, D->getName(), &getModule(), 0,
ASTTy.getAddressSpace());
// Cache the entry.
Entry = GV;
}
// Lookup the entry, lazily creating it if necessary.
llvm::GlobalValue *&Entry = GlobalDeclMap[D->getName()];
if (!Entry)
Entry = new llvm::GlobalVariable(Ty, false,
llvm::GlobalValue::ExternalLinkage,
0, D->getName(), &getModule(), 0,
ASTTy.getAddressSpace());
// Make sure the result is of the correct type.
return llvm::ConstantExpr::getBitCast(Entry, PTy);
}
@ -573,15 +551,16 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
}
const llvm::Type* InitType = Init->getType();
llvm::GlobalVariable *GV = getModule().getGlobalVariable(D->getName(), true);
llvm::GlobalValue *&Entry = GlobalDeclMap[D->getName()];
llvm::GlobalVariable *GV = cast_or_null<llvm::GlobalVariable>(Entry);
if (!GV) {
GV = new llvm::GlobalVariable(InitType, false,
llvm::GlobalValue::ExternalLinkage,
0, D->getName(), &getModule(), 0,
ASTTy.getAddressSpace());
} else if (GV->getType()->getElementType() != InitType ||
GV->getType()->getAddressSpace() != ASTTy.getAddressSpace()) {
} else if (GV->getType() !=
llvm::PointerType::get(InitType, ASTTy.getAddressSpace())) {
// We have a definition after a prototype with the wrong type.
// We must make a new GlobalVariable* and update everything that used OldGV
// (a declaration or tentative definition) with the new GlobalVariable*
@ -611,16 +590,12 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
llvm::Constant *NewPtrForOldDecl =
llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
OldGV->replaceAllUsesWith(NewPtrForOldDecl);
// Make sure we don't keep around any stale references to globals
// FIXME: This is really slow; we need a better way to walk all
// the decls with the same name
ReplaceMapValuesWith(OldGV, GV);
// Erase the old global, since it is no longer used.
OldGV->eraseFromParent();
}
GlobalDeclMap[D] = GV;
Entry = GV;
if (const AnnotateAttr *AA = D->getAttr<AnnotateAttr>()) {
SourceManager &SM = Context.getSourceManager();
@ -714,45 +689,23 @@ llvm::Constant *CodeGenModule::GetAddrOfFunction(const FunctionDecl *D) {
QualType ASTTy = D->getType();
const llvm::Type *Ty = getTypes().ConvertTypeForMem(ASTTy);
const llvm::Type *PTy = llvm::PointerType::get(Ty, ASTTy.getAddressSpace());
// See if it is already in the map.
llvm::GlobalValue *&Entry = GlobalDeclMap[D];
// If not look for an existing global (if this decl shadows another
// one) or lazily create a forward declaration.
if (!Entry) {
// Check to see if the global already exists.
llvm::GlobalValue *GV = getModule().getFunction(D->getName());
// Create it if not.
if (!GV)
GV = EmitForwardFunctionDefinition(D);
// Cache the entry.
Entry = GV;
}
// Lookup the entry, lazily creating it if necessary.
llvm::GlobalValue *&Entry = GlobalDeclMap[D->getName()];
if (!Entry)
Entry = EmitForwardFunctionDefinition(D);
return llvm::ConstantExpr::getBitCast(Entry, PTy);
}
void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) {
llvm::GlobalValue *&Entry = GlobalDeclMap[D];
const llvm::Type *Ty = getTypes().ConvertType(D->getType());
const llvm::FunctionType *FTy = cast<llvm::FunctionType>(Ty);
// Check to see if the function already exists.
llvm::Function *F = getModule().getFunction(D->getName());
// If it doesn't already exist, just create and return an entry.
if (F == 0) {
llvm::GlobalValue *&Entry = GlobalDeclMap[D->getName()];
if (!Entry) {
Entry = EmitForwardFunctionDefinition(D);
} else {
// If the pointer type matches, just return it.
llvm::Type *PFTy = llvm::PointerType::getUnqual(Ty);
if (PFTy == F->getType()) {
Entry = F;
} else {
// If the types mismatch then we have to rewrite the definition.
const llvm::Type *Ty = getTypes().ConvertType(D->getType());
if (Entry->getType() != llvm::PointerType::getUnqual(Ty)) {
// Otherwise, we have a definition after a prototype with the wrong type.
// F is the Function* for the one with the wrong type, we must make a new
// Function* and update everything that used F (a declaration) with the new
@ -761,27 +714,25 @@ void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) {
// This happens if there is a prototype for a function (e.g. "int f()") and
// then a definition of a different type (e.g. "int f(int x)"). Start by
// making a new function of the correct type, RAUW, then steal the name.
llvm::Function *NewFn = llvm::Function::Create(FTy,
llvm::Function::ExternalLinkage,
"", &getModule());
NewFn->takeName(F);
llvm::GlobalValue *NewFn = EmitForwardFunctionDefinition(D);
NewFn->takeName(Entry);
// Replace uses of F with the Function we will endow with a body.
llvm::Constant *NewPtrForOldDecl =
llvm::ConstantExpr::getBitCast(NewFn, F->getType());
F->replaceAllUsesWith(NewPtrForOldDecl);
// FIXME: Update the globaldeclmap for the previous decl of this name. We
// really want a way to walk all of these, but we don't have it yet. This
// is incredibly slow!
ReplaceMapValuesWith(F, NewFn);
llvm::ConstantExpr::getBitCast(NewFn, Entry->getType());
Entry->replaceAllUsesWith(NewPtrForOldDecl);
// Ok, delete the old function now, which is dead.
assert(F->isDeclaration() && "Shouldn't replace non-declaration");
F->eraseFromParent();
// FIXME: Add GlobalValue->eraseFromParent().
assert(Entry->isDeclaration() && "Shouldn't replace non-declaration");
if (llvm::Function *F = dyn_cast<llvm::Function>(Entry)) {
F->eraseFromParent();
} else if (llvm::GlobalAlias *GA = dyn_cast<llvm::GlobalAlias>(Entry)) {
GA->eraseFromParent();
} else {
assert(0 && "Invalid global variable type.");
}
SetFunctionAttributes(D, NewFn, FTy);
// Return the new function which has the right type.
Entry = NewFn;
}
}

View File

@ -69,11 +69,13 @@ class CodeGenModule {
llvm::Function *MemMoveFn;
llvm::Function *MemSetFn;
/// GlobalDeclMap - Mapping of decls to global variables we have
/// GlobalDeclMap - Mapping of decl names global variables we have
/// already emitted. Note that the entries in this map are the
/// actual global and therefore may not be of the same type as the
/// decl, they should be bitcasted on retrieval.
llvm::DenseMap<const Decl*, llvm::GlobalValue*> GlobalDeclMap;
/// actual globals and therefore may not be of the same type as the
/// decl, they should be bitcasted on retrieval. Also note that the
/// globals are keyed on their source name, not the global name
/// (which may change with attributes such as asm-labels).
llvm::StringMap<llvm::GlobalValue*> GlobalDeclMap;
/// List of static global for which code generation is delayed. When
/// the translation unit has been fully processed we will lazily
@ -172,11 +174,6 @@ public:
VisibilityAttr::VisibilityTypes);
private:
/// ReplaceMapValuesWith - This is a really slow and bad function that
/// searches for any entries in GlobalDeclMap that point to OldVal, changing
/// them to point to NewVal. This is badbadbad, FIXME!
void ReplaceMapValuesWith(llvm::GlobalValue *OldVal, llvm::GlobalValue *NewVal);
void SetFunctionAttributes(const FunctionDecl *FD,
llvm::Function *F,
const llvm::FunctionType *FTy);

View File

@ -0,0 +1,12 @@
// RUN: clang -emit-llvm -o - %s | grep -e "^@f" | count 1
int x() {}
int f() __attribute__((weak, alias("x")));
/* Test that we link to the alias correctly instead of making a new
forward definition. */
int f();
int h() {
return f();
}