From a85d68e5d8adbe917c36d27e517071ec3838d46b Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 21 Mar 2009 09:25:43 +0000 Subject: [PATCH] fix a crash that could occur when a variable declaration became a function definition. llvm-svn: 67446 --- clang/lib/CodeGen/CodeGenModule.cpp | 102 ++++++++++++++++------------ clang/lib/CodeGen/CodeGenModule.h | 2 +- clang/test/CodeGen/mangle.c | 11 +++ 3 files changed, 72 insertions(+), 43 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 39863dc49882..109344b9c63d 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/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(Ty)) { + Ty = llvm::FunctionType::get(llvm::Type::VoidTy, + std::vector(), false); + ShouldSetAttributes = false; + } + llvm::Function *F = llvm::Function::Create(cast(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(GetAddrOfGlobalVar(D, InitType)); - + GV->takeName(cast(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(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(Ty)) { - Ty = llvm::FunctionType::get(llvm::Type::VoidTy, - std::vector(), false); - ShouldSetAttributes = false; - } - llvm::Function *F = llvm::Function::Create(cast(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(), 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(Entry)) { + assert(CE->getOpcode() == llvm::Instruction::BitCast); + Entry = CE->getOperand(0); + } + + + if (cast(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(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(GetAddrOfFunction(D, Ty)); + NewFn->takeName(cast(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(Entry)->eraseFromParent(); - Fn = NewFn; + Entry = NewFn; } + + llvm::Function *Fn = cast(Entry); CodeGenFunction(*this).GenerateCode(D, Fn); diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 60031ab648a7..47456804d3a6 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -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 diff --git a/clang/test/CodeGen/mangle.c b/clang/test/CodeGen/mangle.c index bcb1400dd580..89e0e8a79a88 100644 --- a/clang/test/CodeGen/mangle.c +++ b/clang/test/CodeGen/mangle.c @@ -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() { +}