fix a crash that could occur when a variable declaration became a

function definition.

llvm-svn: 67446
This commit is contained in:
Chris Lattner 2009-03-21 09:25:43 +00:00
parent 149927c9f8
commit a85d68e5d8
3 changed files with 72 additions and 43 deletions

View File

@ -585,6 +585,45 @@ void CodeGenModule::EmitGlobalDefinition(const ValueDecl *D) {
}
}
/// GetAddrOfFunction - Return the address of the given function. If Ty is
/// non-null, then this function will use the specified type if it has to
/// create it (this occurs when we see a definition of the function).
llvm::Constant *CodeGenModule::GetAddrOfFunction(const FunctionDecl *D,
const llvm::Type *Ty) {
// If there was no specific requested type, just convert it now.
if (!Ty)
Ty = getTypes().ConvertType(D->getType());
// Lookup the entry, lazily creating it if necessary.
const char *MangledName = getMangledName(D);
llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName];
if (Entry) {
if (Entry->getType()->getElementType() == Ty)
return Entry;
// Make sure the result is of the correct type.
const llvm::Type *PTy = llvm::PointerType::getUnqual(Ty);
return llvm::ConstantExpr::getBitCast(Entry, PTy);
}
// This function doesn't have a complete type (for example, the return
// type is an incomplete struct). Use a fake type instead, and make
// sure not to try to set attributes.
bool ShouldSetAttributes = true;
if (!isa<llvm::FunctionType>(Ty)) {
Ty = llvm::FunctionType::get(llvm::Type::VoidTy,
std::vector<const llvm::Type*>(), false);
ShouldSetAttributes = false;
}
llvm::Function *F = llvm::Function::Create(cast<llvm::FunctionType>(Ty),
llvm::Function::ExternalLinkage,
MangledName, &getModule());
if (ShouldSetAttributes)
SetFunctionAttributes(D, F);
Entry = F;
return F;
}
/// GetAddrOfGlobalVar - Return the llvm::Constant for the address of the
/// given global variable. If Ty is non-null and if the global doesn't exist,
/// then it will be greated with the specified type instead of whatever the
@ -712,7 +751,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
// Make a new global with the correct type, this is now guaranteed to work.
GV = cast<llvm::GlobalVariable>(GetAddrOfGlobalVar(D, InitType));
GV->takeName(cast<llvm::GlobalValue>(Entry));
// Replace all uses of the old global with the new global
llvm::Constant *NewPtrForOldDecl =
llvm::ConstantExpr::getBitCast(GV, Entry->getType());
@ -784,38 +824,6 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
}
}
/// GetAddrOfFunction - Return the address of the given function. If Ty is
/// non-null, then this function will use the specified type if it has to
/// create it (this occurs when we see a definition of the function).
llvm::Function *CodeGenModule::GetAddrOfFunction(const FunctionDecl *D,
const llvm::Type *Ty) {
// Lookup the entry, lazily creating it if necessary.
const char *MangledName = getMangledName(D);
llvm::GlobalValue *&Entry = GlobalDeclMap[MangledName];
if (Entry)
return cast<llvm::Function>(Entry);
// If there was no specific requested type, just convert it now.
if (!Ty)
Ty = getTypes().ConvertType(D->getType());
// This function doesn't have a complete type (for example, the return
// type is an incomplete struct). Use a fake type instead, and make
// sure not to try to set attributes.
bool ShouldSetAttributes = true;
if (!isa<llvm::FunctionType>(Ty)) {
Ty = llvm::FunctionType::get(llvm::Type::VoidTy,
std::vector<const llvm::Type*>(), false);
ShouldSetAttributes = false;
}
llvm::Function *F = llvm::Function::Create(cast<llvm::FunctionType>(Ty),
llvm::Function::ExternalLinkage,
MangledName, &getModule());
if (ShouldSetAttributes)
SetFunctionAttributes(D, F);
Entry = F;
return F;
}
void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) {
const llvm::FunctionType *Ty =
@ -830,11 +838,19 @@ void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) {
std::vector<const llvm::Type*>(), false);
// Get or create the prototype for teh function.
llvm::Function *Fn = GetAddrOfFunction(D, Ty);
llvm::Constant *Entry = GetAddrOfFunction(D, Ty);
if (Fn->getType()->getElementType() != Ty) {
// Strip off a bitcast if we got one back.
if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Entry)) {
assert(CE->getOpcode() == llvm::Instruction::BitCast);
Entry = CE->getOperand(0);
}
if (cast<llvm::GlobalValue>(Entry)->getType()->getElementType() != Ty) {
// If the types mismatch then we have to rewrite the definition.
assert(Fn->isDeclaration() && "Shouldn't replace non-declaration");
assert(cast<llvm::GlobalValue>(Entry)->isDeclaration() &&
"Shouldn't replace non-declaration");
// 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
@ -845,21 +861,23 @@ void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) {
// (e.g. "int f(int x)"). Start by making a new function of the
// correct type, RAUW, then steal the name.
GlobalDeclMap.erase(getMangledName(D));
llvm::Function *NewFn = GetAddrOfFunction(D, Ty);
NewFn->takeName(Fn);
llvm::Function *NewFn = cast<llvm::Function>(GetAddrOfFunction(D, Ty));
NewFn->takeName(cast<llvm::GlobalValue>(Entry));
// Replace uses of F with the Function we will endow with a body.
llvm::Constant *NewPtrForOldDecl =
llvm::ConstantExpr::getBitCast(NewFn, Fn->getType());
Fn->replaceAllUsesWith(NewPtrForOldDecl);
llvm::ConstantExpr::getBitCast(NewFn, Entry->getType());
Entry->replaceAllUsesWith(NewPtrForOldDecl);
// Ok, delete the old function now, which is dead.
// FIXME: If it was attribute(used) the pointer will dangle from the
// LLVMUsed array!
Fn->eraseFromParent();
cast<llvm::GlobalValue>(Entry)->eraseFromParent();
Fn = NewFn;
Entry = NewFn;
}
llvm::Function *Fn = cast<llvm::Function>(Entry);
CodeGenFunction(*this).GenerateCode(D, Fn);

View File

@ -184,7 +184,7 @@ public:
/// GetAddrOfFunction - Return the address of the given function. If Ty is
/// non-null, then this function will use the specified type if it has to
/// create it.
llvm::Function *GetAddrOfFunction(const FunctionDecl *D,
llvm::Constant *GetAddrOfFunction(const FunctionDecl *D,
const llvm::Type *Ty = 0);
/// GetStringForStringLiteral - Return the appropriate bytes for a string

View File

@ -36,3 +36,14 @@ void test2() {
}
int foo4 __asm__("var") = 4;
// Variable becomes a function
extern int foo5 __asm__("var2");
void test3() {
foo5 = 1;
}
void foo6() __asm__("var2");
void foo6() {
}