From: Nate Begeman Date: Sun, 20 Apr 2008 06:29:50 +0000 (+0000) Subject: Only generate code for static functions and global variables that are actually used. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4c13b7a3973d2d263d9682d7b68fbfeb76334af5;p=clang Only generate code for static functions and global variables that are actually used. Warn about unused static functions and variables. This fixes PR1998. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49987 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index 8fdf716aea..4591210032 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -1036,4 +1036,10 @@ DIAG(ext_return_missing_expr, EXTENSION, DIAG(ext_return_has_expr, EXTENSION, "void function '%0' should not return a value") +//===----------------------------------------------------------------------===// +// Codegen +//===----------------------------------------------------------------------===// + +DIAG(warn_unused_static, WARNING, "static '%0' defined but not used") + #undef DIAG diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index da38698ab6..51d0a89cea 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -44,6 +44,7 @@ CodeGenModule::~CodeGenModule() { llvm::Function *ObjCInitFunction = Runtime->ModuleInitFunction(); if (ObjCInitFunction) AddGlobalCtor(ObjCInitFunction); + EmitStatics(); EmitGlobalCtors(); EmitAnnotations(); delete Runtime; @@ -167,8 +168,8 @@ llvm::Constant *CodeGenModule::GetAddrOfFunctionDecl(const FunctionDecl *D, // If it doesn't already exist, just create and return an entry. if (F == 0) { // FIXME: param attributes for sext/zext etc. - F = llvm::Function::Create(FTy, llvm::Function::ExternalLinkage, D->getName(), - &getModule()); + F = llvm::Function::Create(FTy, llvm::Function::ExternalLinkage, + D->getName(), &getModule()); // Set the appropriate calling convention for the Function. if (D->getAttr()) @@ -298,8 +299,58 @@ void CodeGenModule::EmitObjCMethod(const ObjCMethodDecl *OMD) { void CodeGenModule::EmitFunction(const FunctionDecl *FD) { // If this is not a prototype, emit the body. - if (FD->getBody()) + if (FD->getBody()) { + // If the function is a static, defer code generation until later so we can + // easily omit unused statics. + if (FD->getStorageClass() == FunctionDecl::Static) { + StaticDecls.push_back(FD); + return; + } CodeGenFunction(*this).GenerateCode(FD); + } +} + +void CodeGenModule::EmitStatics() { + // Emit code for each used static decl encountered. Since a previously unused + // static decl may become used during the generation of code for a static + // function, iterate until no changes are made. + bool Changed; + do { + Changed = false; + for (unsigned i = 0, e = StaticDecls.size(); i != e; ++i) { + // Check the map of used decls for our static. If not found, continue. + const Decl *D = StaticDecls[i]; + if (GlobalDeclMap[D] == 0) + continue; + + // If this is a function decl, generate code for the static function if it + // has a body. Otherwise, we must have a var decl for a static global + // variable. + if (const FunctionDecl *FD = dyn_cast(D)) { + if (FD->getBody()) + CodeGenFunction(*this).GenerateCode(FD); + } else { + const VarDecl *VD = cast(D); + EmitGlobalVarInit(VD); + } + // Erase the used decl from the list. + StaticDecls[i] = StaticDecls.back(); + StaticDecls.pop_back(); + --i; + --e; + + // Remember that we made a change. + Changed = true; + } + } while (Changed); + + // Warn about all statics that are still unused at end of code generation. + for (unsigned i = 0, e = StaticDecls.size(); i != e; ++i) { + const Decl *D = StaticDecls[i]; + std::string Msg = cast(D)->getName(); + getDiags().Report(Context.getFullLoc(D->getLocation()), + diag::warn_unused_static, &Msg, 1); + } } llvm::Constant *CodeGenModule::EmitGlobalInit(const Expr *Expr) { @@ -351,11 +402,22 @@ llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV, } void CodeGenModule::EmitGlobalVar(const VarDecl *D) { + // If the VarDecl is a static, defer code generation until later so we can + // easily omit unused statics. + if (D->getStorageClass() == VarDecl::Static) { + StaticDecls.push_back(D); + return; + } + // If this is just a forward declaration of the variable, don't emit it now, // allow it to be emitted lazily on its first use. if (D->getStorageClass() == VarDecl::Extern && D->getInit() == 0) return; + EmitGlobalVarInit(D); +} + +void CodeGenModule::EmitGlobalVarInit(const VarDecl *D) { // Get the global, forcing it to be a direct reference. llvm::GlobalVariable *GV = cast(GetAddrOfGlobalVar(D, true)); @@ -468,8 +530,9 @@ llvm::Function *CodeGenModule::getBuiltinLibFunction(unsigned BuiltinID) { } // FIXME: param attributes for sext/zext etc. - return FunctionSlot = llvm::Function::Create(Ty, llvm::Function::ExternalLinkage, - Name, &getModule()); + return FunctionSlot = + llvm::Function::Create(Ty, llvm::Function::ExternalLinkage, Name, + &getModule()); } llvm::Function *CodeGenModule::getIntrinsic(unsigned IID,const llvm::Type **Tys, diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index d40e35e00c..aa676d6fdc 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -59,6 +59,8 @@ class CodeGenModule { llvm::Function *MemCpyFn; llvm::Function *MemSetFn; llvm::DenseMap GlobalDeclMap; + std::vector StaticDecls; + std::vector GlobalCtors; std::vector Annotations; @@ -103,10 +105,12 @@ public: void EmitGlobalCtors(void); void AddAnnotation(llvm::Constant *C) { Annotations.push_back(C); } void EmitAnnotations(void); + void EmitStatics(void); void EmitObjCMethod(const ObjCMethodDecl *OMD); void EmitFunction(const FunctionDecl *FD); void EmitGlobalVar(const VarDecl *D); + void EmitGlobalVarInit(const VarDecl *D); void EmitGlobalVarDeclarator(const VarDecl *D); void UpdateCompletedType(const TagDecl *D); llvm::Constant *EmitGlobalInit(const Expr *E);