diff options
author | Chris Lattner <sabre@nondot.org> | 2009-03-21 09:25:43 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-03-21 09:25:43 +0000 |
commit | 0558e79840bfdbbd38c6e2b4f6765bf0158e85f4 (patch) | |
tree | 27e7ea0bea57cae00a0147643ec0fe7a8b70d346 /lib/CodeGen/CodeGenModule.cpp | |
parent | 570585c91dee98d7ba8ccf1198c03208ba17966b (diff) |
fix a crash that could occur when a variable declaration became a
function definition.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67446 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CodeGenModule.cpp')
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 102 |
1 files changed, 60 insertions, 42 deletions
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 39863dc498..109344b9c6 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -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); |