[cfe-commits] r109546 - in /cfe/trunk: include/clang/CodeGen/BackendUtil.h lib/CodeGen/CodeGenModule.cpp lib/Frontend/PCHWriterDecl.cpp test/PCH/cxx-required-decls.cpp test/PCH/cxx-required-decls.h tools/libclang/Makefile

Argyrios Kyrtzidis akyrtzi at gmail.com
Tue Jul 27 15:01:17 PDT 2010


Author: akirtzidis
Date: Tue Jul 27 17:01:17 2010
New Revision: 109546

URL: http://llvm.org/viewvc/llvm-project?rev=109546&view=rev
Log:
Merge PCHWriterDecl.cpp's isRequiredDecl and CodeGenModule::MayDeferGeneration into a new function,
DeclIsRequiredFunctionOrFileScopedVar.

This function is part of the public CodeGen interface since it's essentially a CodeGen predicate that is also
needed by the PCH mechanism to determine whether a decl needs to be deserialized during PCH loading for codegen purposes.
This fixes current (and avoids future) codegen-from-PCH bugs.

Modified:
    cfe/trunk/include/clang/CodeGen/BackendUtil.h
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
    cfe/trunk/test/PCH/cxx-required-decls.cpp
    cfe/trunk/test/PCH/cxx-required-decls.h
    cfe/trunk/tools/libclang/Makefile

Modified: cfe/trunk/include/clang/CodeGen/BackendUtil.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/CodeGen/BackendUtil.h?rev=109546&r1=109545&r2=109546&view=diff
==============================================================================
--- cfe/trunk/include/clang/CodeGen/BackendUtil.h (original)
+++ cfe/trunk/include/clang/CodeGen/BackendUtil.h Tue Jul 27 17:01:17 2010
@@ -19,6 +19,7 @@
   class Diagnostic;
   class CodeGenOptions;
   class TargetOptions;
+  class Decl;
   
   enum BackendAction {
     Backend_EmitAssembly,  ///< Emit native assembly files
@@ -32,6 +33,14 @@
   void EmitBackendOutput(Diagnostic &Diags, const CodeGenOptions &CGOpts,
                          const TargetOptions &TOpts, llvm::Module *M,
                          BackendAction Action, llvm::raw_ostream *OS);
+
+  /// \brief Determines if the decl can be CodeGen'ed or deserialized from PCH
+  /// lazily, only when used; this is only relevant for function or file scoped
+  /// var definitions.
+  ///
+  /// \returns true if the function/var must be CodeGen'ed/deserialized even if
+  /// it is not used.
+  bool DeclIsRequiredFunctionOrFileScopedVar(const Decl *D);
 }
 
 #endif

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=109546&r1=109545&r2=109546&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Jul 27 17:01:17 2010
@@ -18,6 +18,7 @@
 #include "CGObjCRuntime.h"
 #include "Mangle.h"
 #include "TargetInfo.h"
+#include "clang/CodeGen/BackendUtil.h"
 #include "clang/Frontend/CodeGenOptions.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/CharUnits.h"
@@ -323,12 +324,11 @@
 }
 
 static CodeGenModule::GVALinkage
-GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD,
-                      const LangOptions &Features) {
+GetLinkageForFunction(const FunctionDecl *FD, const LangOptions &Features) {
   CodeGenModule::GVALinkage External = CodeGenModule::GVA_StrongExternal;
 
   Linkage L = FD->getLinkage();
-  if (L == ExternalLinkage && Context.getLangOptions().CPlusPlus &&
+  if (L == ExternalLinkage && Features.CPlusPlus &&
       FD->getType()->getLinkage() == UniqueExternalLinkage)
     L = UniqueExternalLinkage;
   
@@ -383,7 +383,7 @@
 
 llvm::GlobalValue::LinkageTypes
 CodeGenModule::getFunctionLinkage(const FunctionDecl *D) {
-  GVALinkage Linkage = GetLinkageForFunction(getContext(), D, Features);
+  GVALinkage Linkage = GetLinkageForFunction(D, Features);
 
   if (Linkage == GVA_Internal)
     return llvm::Function::InternalLinkage;
@@ -642,7 +642,7 @@
 }
 
 static CodeGenModule::GVALinkage
-GetLinkageForVariable(ASTContext &Context, const VarDecl *VD) {
+GetLinkageForVariable(const VarDecl *VD, const LangOptions &Features) {
   // If this is a static data member, compute the kind of template
   // specialization. Otherwise, this variable is not part of a
   // template.
@@ -651,7 +651,7 @@
     TSK = VD->getTemplateSpecializationKind();
 
   Linkage L = VD->getLinkage();
-  if (L == ExternalLinkage && Context.getLangOptions().CPlusPlus &&
+  if (L == ExternalLinkage && Features.CPlusPlus &&
       VD->getType()->getLinkage() == UniqueExternalLinkage)
     L = UniqueExternalLinkage;
 
@@ -682,61 +682,83 @@
   return CodeGenModule::GVA_StrongExternal;
 }
 
-bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
-  // Never defer when EmitAllDecls is specified or the decl has
-  // attribute used.
-  if (Features.EmitAllDecls || Global->hasAttr<UsedAttr>())
+bool clang::DeclIsRequiredFunctionOrFileScopedVar(const Decl *D) {
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    if (!VD->isFileVarDecl())
+      return false;
+  } else if (!isa<FunctionDecl>(D))
     return false;
 
-  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) {
-    // Constructors and destructors should never be deferred.
-    if (FD->hasAttr<ConstructorAttr>() ||
-        FD->hasAttr<DestructorAttr>())
+  // Aliases and used decls are required.
+  if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>())
+    return true;
+
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    // Forward declarations aren't required.
+    if (!FD->isThisDeclarationADefinition())
       return false;
 
-    // The key function for a class must never be deferred.
-    if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Global)) {
+    // Constructors and destructors are required.
+    if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
+      return true;
+    
+    ASTContext &Ctx = FD->getASTContext();
+
+    // The key function for a class is required.
+    if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
       const CXXRecordDecl *RD = MD->getParent();
       if (MD->isOutOfLine() && RD->isDynamicClass()) {
-        const CXXMethodDecl *KeyFunction = getContext().getKeyFunction(RD);
-        if (KeyFunction && 
-            KeyFunction->getCanonicalDecl() == MD->getCanonicalDecl())
-          return false;
+        const CXXMethodDecl *KeyFunc = Ctx.getKeyFunction(RD);
+        if (KeyFunc && KeyFunc->getCanonicalDecl() == MD->getCanonicalDecl())
+          return true;
       }
     }
 
-    GVALinkage Linkage = GetLinkageForFunction(getContext(), FD, Features);
+    CodeGenModule::GVALinkage Linkage
+        = GetLinkageForFunction(FD, Ctx.getLangOptions());
 
     // static, static inline, always_inline, and extern inline functions can
     // always be deferred.  Normal inline functions can be deferred in C99/C++.
     // Implicit template instantiations can also be deferred in C++.
-    if (Linkage == GVA_Internal || Linkage == GVA_C99Inline ||
-        Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation)
-      return true;
-    return false;
+    if (Linkage == CodeGenModule::GVA_Internal  ||
+        Linkage == CodeGenModule::GVA_C99Inline ||
+        Linkage == CodeGenModule::GVA_CXXInline ||
+        Linkage == CodeGenModule::GVA_TemplateInstantiation)
+      return false;
+    return true;
   }
 
-  const VarDecl *VD = cast<VarDecl>(Global);
-  assert(VD->isFileVarDecl() && "Invalid decl");
+  const VarDecl *VD = cast<VarDecl>(D);
+  assert(VD->isFileVarDecl() && "Expected file scoped var");
+
+  // Structs that have non-trivial constructors or destructors are required.
 
-  // We never want to defer structs that have non-trivial constructors or 
-  // destructors.
-  
   // FIXME: Handle references.
   if (const RecordType *RT = VD->getType()->getAs<RecordType>()) {
     if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
       if (!RD->hasTrivialConstructor() || !RD->hasTrivialDestructor())
-        return false;
+        return true;
     }
   }
-      
-  GVALinkage L = GetLinkageForVariable(getContext(), VD);
-  if (L == GVA_Internal || L == GVA_TemplateInstantiation) {
-    if (!(VD->getInit() && VD->getInit()->HasSideEffects(Context)))
-      return true;
+
+  ASTContext &Ctx = VD->getASTContext();
+
+  CodeGenModule::GVALinkage L = GetLinkageForVariable(VD, Ctx.getLangOptions());
+  if (L == CodeGenModule::GVA_Internal ||
+      L == CodeGenModule::GVA_TemplateInstantiation) {
+    if (!(VD->getInit() && VD->getInit()->HasSideEffects(Ctx)))
+      return false;
   }
 
-  return false;
+  return true;
+}
+
+bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) {
+  // Never defer when EmitAllDecls is specified.
+  if (Features.EmitAllDecls)
+    return false;
+
+  return !DeclIsRequiredFunctionOrFileScopedVar(Global);
 }
 
 llvm::Constant *CodeGenModule::GetWeakRefReference(const ValueDecl *VD) {
@@ -1271,7 +1293,7 @@
   GV->setAlignment(getContext().getDeclAlign(D).getQuantity());
 
   // Set the llvm linkage type as appropriate.
-  GVALinkage Linkage = GetLinkageForVariable(getContext(), D);
+  GVALinkage Linkage = GetLinkageForVariable(D, Features);
   if (Linkage == GVA_Internal)
     GV->setLinkage(llvm::Function::InternalLinkage);
   else if (D->hasAttr<DLLImportAttr>())

Modified: cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriterDecl.cpp?rev=109546&r1=109545&r2=109546&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriterDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriterDecl.cpp Tue Jul 27 17:01:17 2010
@@ -16,6 +16,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
+#include "clang/CodeGen/BackendUtil.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Bitcode/BitstreamWriter.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -1078,63 +1079,12 @@
 /// clients to use a separate API call to "realize" the decl. This should be
 /// relatively painless since they would presumably only do it for top-level
 /// decls.
-//
-// FIXME: This predicate is essentially IRgen's predicate to determine whether a
-// declaration can be deferred. Merge them somehow.
 static bool isRequiredDecl(const Decl *D, ASTContext &Context) {
   // File scoped assembly must be seen.
   if (isa<FileScopeAsmDecl>(D))
     return true;
 
-  // Otherwise if this isn't a function or a file scoped variable it doesn't
-  // need to be seen.
-  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
-    if (!VD->isFileVarDecl())
-      return false;
-  } else if (!isa<FunctionDecl>(D))
-    return false;
-
-  // Aliases and used decls must be seen.
-  if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>())
-    return true;
-
-  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
-    // Forward declarations don't need to be seen.
-    if (!FD->isThisDeclarationADefinition())
-      return false;
-
-    // Constructors and destructors must be seen.
-    if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
-      return true;
-
-    // Otherwise, this is required unless it is static.
-    //
-    // FIXME: Inlines.
-    return FD->getStorageClass() != FunctionDecl::Static;
-  } else {
-    const VarDecl *VD = cast<VarDecl>(D);
-
-    // Structs that have non-trivial constructors or destructors must be seen.
-    if (const RecordType *RT = VD->getType()->getAs<RecordType>()) {
-      if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
-        if (!RD->hasTrivialConstructor() || !RD->hasTrivialDestructor())
-          return true;
-      }
-    }
-
-    // In C++, this doesn't need to be seen if it is marked "extern".
-    if (Context.getLangOptions().CPlusPlus && !VD->getInit() &&
-        (VD->getStorageClass() == VarDecl::Extern ||
-         VD->isExternC()))
-      return false;
-
-    // In C, this doesn't need to be seen unless it is a definition.
-    if (!Context.getLangOptions().CPlusPlus && !VD->getInit())
-      return false;
-
-    // Otherwise, this is required unless it is static.
-    return VD->getStorageClass() != VarDecl::Static;
-  }
+  return DeclIsRequiredFunctionOrFileScopedVar(D);
 }
 
 void PCHWriter::WriteDecl(ASTContext &Context, Decl *D) {

Modified: cfe/trunk/test/PCH/cxx-required-decls.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-required-decls.cpp?rev=109546&r1=109545&r2=109546&view=diff
==============================================================================
--- cfe/trunk/test/PCH/cxx-required-decls.cpp (original)
+++ cfe/trunk/test/PCH/cxx-required-decls.cpp Tue Jul 27 17:01:17 2010
@@ -6,3 +6,4 @@
 // RUN: %clang_cc1 -include-pch %t %s -emit-llvm -o - | FileCheck %s
 
 // CHECK: @_ZL5globS = internal global %struct.S zeroinitializer
+// CHECK: @_ZL3bar = internal global i32 0, align 4

Modified: cfe/trunk/test/PCH/cxx-required-decls.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-required-decls.h?rev=109546&r1=109545&r2=109546&view=diff
==============================================================================
--- cfe/trunk/test/PCH/cxx-required-decls.h (original)
+++ cfe/trunk/test/PCH/cxx-required-decls.h Tue Jul 27 17:01:17 2010
@@ -5,3 +5,6 @@
 };
 
 static S globS;
+
+extern int ext_foo;
+static int bar = ++ext_foo;

Modified: cfe/trunk/tools/libclang/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/Makefile?rev=109546&r1=109545&r2=109546&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/Makefile (original)
+++ cfe/trunk/tools/libclang/Makefile Tue Jul 27 17:01:17 2010
@@ -17,7 +17,7 @@
 
 LINK_COMPONENTS := bitreader mc core
 USEDLIBS = clangFrontend.a clangDriver.a clangSema.a \
-	   clangAnalysis.a clangAST.a clangParse.a clangLex.a clangBasic.a
+	   clangAnalysis.a clangAST.a clangCodeGen.a clangParse.a clangLex.a clangBasic.a
 
 include $(CLANG_LEVEL)/Makefile
 





More information about the cfe-commits mailing list