From f0acf7bd4c72370ecfc358d2d007b25d1b433cbc Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Thu, 19 Feb 2009 07:15:39 +0000 Subject: Don't emit K&R unprototyped function definitions as varargs. - clang/x86-64 - too many reg saves llvm-svn: 65032 --- clang/lib/CodeGen/CodeGenModule.cpp | 40 +++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 13 deletions(-) (limited to 'clang/lib/CodeGen/CodeGenModule.cpp') diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 17662ef340e4..ae472f01ce62 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -773,8 +773,10 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { } llvm::GlobalValue * -CodeGenModule::EmitForwardFunctionDefinition(const FunctionDecl *D) { - const llvm::Type *Ty = getTypes().ConvertType(D->getType()); +CodeGenModule::EmitForwardFunctionDefinition(const FunctionDecl *D, + const llvm::Type *Ty) { + if (!Ty) + Ty = getTypes().ConvertType(D->getType()); llvm::Function *F = llvm::Function::Create(cast(Ty), llvm::Function::ExternalLinkage, getMangledName(D), @@ -791,28 +793,40 @@ llvm::Constant *CodeGenModule::GetAddrOfFunction(const FunctionDecl *D) { // Lookup the entry, lazily creating it if necessary. llvm::GlobalValue *&Entry = GlobalDeclMap[getMangledName(D)]; if (!Entry) - Entry = EmitForwardFunctionDefinition(D); + Entry = EmitForwardFunctionDefinition(D, 0); return llvm::ConstantExpr::getBitCast(Entry, PTy); } void CodeGenModule::EmitGlobalFunctionDefinition(const FunctionDecl *D) { + const llvm::FunctionType *Ty = + cast(getTypes().ConvertType(D->getType())); + + // As a special case, make sure that definitions of K&R function + // "type foo()" aren't declared as varargs (which forces the backend + // to do unnecessary work). + if (Ty->isVarArg() && Ty->getNumParams() == 0 && Ty->isVarArg()) + Ty = llvm::FunctionType::get(Ty->getReturnType(), + std::vector(), + false); + llvm::GlobalValue *&Entry = GlobalDeclMap[getMangledName(D)]; if (!Entry) { - Entry = EmitForwardFunctionDefinition(D); + Entry = EmitForwardFunctionDefinition(D, Ty); } 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 - // Function* (which will be a definition). + // 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 Function* (which will be + // a definition). // - // 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::GlobalValue *NewFn = EmitForwardFunctionDefinition(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::GlobalValue *NewFn = EmitForwardFunctionDefinition(D, Ty); NewFn->takeName(Entry); // Replace uses of F with the Function we will endow with a body. -- cgit v1.2.3