diff options
| author | Nate Begeman <natebegeman@mac.com> | 2008-04-20 06:29:50 +0000 | 
|---|---|---|
| committer | Nate Begeman <natebegeman@mac.com> | 2008-04-20 06:29:50 +0000 | 
| commit | 8e8d498d34744e90ef02d0ccd01576a95aab46c9 (patch) | |
| tree | 282d0d0702009eea7ee67bd35c7d6057089098b4 /clang/lib/CodeGen | |
| parent | 470ab00c76a0c9a8043c6b328947f6fb61cf95cc (diff) | |
| download | bcm5719-llvm-8e8d498d34744e90ef02d0ccd01576a95aab46c9.tar.gz bcm5719-llvm-8e8d498d34744e90ef02d0ccd01576a95aab46c9.zip  | |
Only generate code for static functions and global variables that are actually used.
Warn about unused static functions and variables.
This fixes PR1998.
llvm-svn: 49987
Diffstat (limited to 'clang/lib/CodeGen')
| -rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 73 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 4 | 
2 files changed, 72 insertions, 5 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index da38698ab61..51d0a89cea3 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/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<FastCallAttr>()) @@ -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<FunctionDecl>(D)) { +        if (FD->getBody()) +          CodeGenFunction(*this).GenerateCode(FD); +      } else { +        const VarDecl *VD = cast<VarDecl>(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<NamedDecl>(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<llvm::GlobalVariable>(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/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index d40e35e00ce..aa676d6fdc6 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -59,6 +59,8 @@ class CodeGenModule {    llvm::Function *MemCpyFn;    llvm::Function *MemSetFn;    llvm::DenseMap<const Decl*, llvm::Constant*> GlobalDeclMap; +  std::vector<const Decl*> StaticDecls; +      std::vector<llvm::Constant*> GlobalCtors;    std::vector<llvm::Constant*> 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);  | 

