[cfe-commits] r46745 - in /cfe/trunk: CodeGen/CodeGenModule.cpp CodeGen/CodeGenModule.h CodeGen/CodeGenTypes.cpp CodeGen/CodeGenTypes.h CodeGen/ModuleBuilder.cpp Driver/ASTConsumers.cpp include/clang/CodeGen/ModuleBuilder.h test/CodeGen/types.c

Chris Lattner sabre at nondot.org
Tue Feb 5 00:06:14 PST 2008


Author: lattner
Date: Tue Feb  5 02:06:13 2008
New Revision: 46745

URL: http://llvm.org/viewvc/llvm-project?rev=46745&view=rev
Log:
rewrite some of the type refinement code to eliminate dangling pointers
simplify the code and generally make it more robust.

Added:
    cfe/trunk/test/CodeGen/types.c
Modified:
    cfe/trunk/CodeGen/CodeGenModule.cpp
    cfe/trunk/CodeGen/CodeGenModule.h
    cfe/trunk/CodeGen/CodeGenTypes.cpp
    cfe/trunk/CodeGen/CodeGenTypes.h
    cfe/trunk/CodeGen/ModuleBuilder.cpp
    cfe/trunk/Driver/ASTConsumers.cpp
    cfe/trunk/include/clang/CodeGen/ModuleBuilder.h

Modified: cfe/trunk/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenModule.cpp?rev=46745&r1=46744&r2=46745&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/CodeGen/CodeGenModule.cpp Tue Feb  5 02:06:13 2008
@@ -261,6 +261,27 @@
     EmitGlobalVar(D);
 }
 
+void CodeGenModule::EmitType(const TypeDecl *D) {
+  if (isa<TypedefDecl>(D)) {
+    // TODO: Emit debug info.
+    return;
+  }
+  
+  assert(!isa<ObjCInterfaceDecl>(D) && "FIXME: ADD OBJC SUPPORT");
+  
+  // This must be a tag decl.
+  const TagDecl *TD = cast<TagDecl>(D);
+  
+  // Get the LLVM type for this TagDecl.  If it is non-opaque or if this decl
+  // is still a forward declaration, just return.
+  QualType NewTy = Context.getTagDeclType(const_cast<TagDecl *>(TD));
+  const llvm::Type *T = Types.ConvertType(NewTy);
+  if (isa<llvm::OpaqueType>(T) && TD->isDefinition())
+    // Make sure that this type is translated.
+    Types.ForceTypeCompilation(NewTy);
+}
+
+
 /// getBuiltinLibFunction
 llvm::Function *CodeGenModule::getBuiltinLibFunction(unsigned BuiltinID) {
   if (BuiltinID > BuiltinFunctions.size())

Modified: cfe/trunk/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenModule.h?rev=46745&r1=46744&r2=46745&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/CodeGen/CodeGenModule.h Tue Feb  5 02:06:13 2008
@@ -34,6 +34,7 @@
   class Stmt;
   class ValueDecl;
   class VarDecl;
+  class TypeDecl;
   class FileVarDecl;
   struct LangOptions;
   class Diagnostic;
@@ -87,6 +88,7 @@
   void EmitFunction(const FunctionDecl *FD);
   void EmitGlobalVar(const FileVarDecl *D);
   void EmitGlobalVarDeclarator(const FileVarDecl *D);
+  void EmitType(const TypeDecl *D);
   llvm::Constant *EmitGlobalInit(const Expr *E);
   llvm::Constant *EmitConstantExpr(const Expr *E);
     

Modified: cfe/trunk/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenTypes.cpp?rev=46745&r1=46744&r2=46745&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/CodeGen/CodeGenTypes.cpp Tue Feb  5 02:06:13 2008
@@ -91,29 +91,6 @@
   CGRecordLayouts.clear();
 }
 
-/// isOpaqueTypeDefinition - Return true if LT is a llvm::OpaqueType
-/// and T is tag definition. This helper routine does not check
-/// relationship between T and LT.
-static bool isOpaqueTypeDefinition(QualType T, const llvm::Type *LT) {
-  if (const PointerType* PTy = T->getAsPointerType()) {
-    return
-      isOpaqueTypeDefinition(PTy->getPointeeType(),
-                             cast<llvm::PointerType>(LT)->getElementType());
-  }
-  if (!isa<llvm::OpaqueType>(LT))
-    return false;
-
-  const clang::Type &Ty = *T.getCanonicalType();
-  if (Ty.getTypeClass() == Type::Tagged) {
-    const TagType &TT = cast<TagType>(Ty);
-    const TagDecl *TD = TT.getDecl();
-    if (TD->isDefinition())
-      return true;
-  }
-
-  return false;
-}
-
 /// ConvertType - Convert the specified type to its LLVM form.
 const llvm::Type *CodeGenTypes::ConvertType(QualType T) {
   // See if type is already cached.
@@ -121,7 +98,7 @@
     I = TypeHolderMap.find(T.getTypePtr());
   // If type is found in map and this is not a definition for a opaque
   // place holder type then use it. Otherwise convert type T.
-  if (I != TypeHolderMap.end() && !isOpaqueTypeDefinition(T, I->second.get()))
+  if (I != TypeHolderMap.end())
     return I->second.get();
 
   const llvm::Type *ResultType = ConvertNewType(T);
@@ -148,6 +125,31 @@
   
 }
 
+/// ForceTypeCompilation - When we find the definition for a type, we require
+/// it to be recompiled, to update the lazy understanding of what it is in our
+/// maps.
+void CodeGenTypes::ForceTypeCompilation(QualType T) {
+  const TagDecl *TD = cast<TagType>(T)->getDecl();
+
+  // Remember the opaque LLVM type for this tagdecl.
+  llvm::DenseMap<const TagDecl*, llvm::PATypeHolder>::iterator TDTI = 
+     TagDeclTypes.find(TD);
+  llvm::PATypeHolder OpaqueHolder = TDTI->second;
+  assert(isa<llvm::OpaqueType>(OpaqueHolder.get()) &&
+         "Forcing compilation of non-opaque type?");
+  
+  // Remove it from TagDeclTypes so that it will be regenerated.
+  TagDeclTypes.erase(TDTI);
+
+  const llvm::Type *NT = ConvertNewType(T);
+
+  // If getting the type didn't itself refine it, refine it to its actual type
+  // now.
+  if (llvm::OpaqueType *OT = dyn_cast<llvm::OpaqueType>(OpaqueHolder.get()))
+    OT->refineAbstractTypeTo(NT);
+}
+
+
 
 const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
   const clang::Type &Ty = *T.getCanonicalType();
@@ -268,7 +270,6 @@
   
   case Type::ASQual:
     return ConvertType(cast<ASQualType>(Ty).getBaseType());
-    break;
 
   case Type::ObjCInterface:
     assert(0 && "FIXME: add missing functionality here");
@@ -285,40 +286,36 @@
   case Type::Tagged:
     const TagType &TT = cast<TagType>(Ty);
     const TagDecl *TD = TT.getDecl();
-    llvm::Type *ResultType = TagDeclTypes[TD];
+    llvm::DenseMap<const TagDecl*, llvm::PATypeHolder>::iterator TDTI = 
+      TagDeclTypes.find(TD);
       
     // If corresponding llvm type is not a opaque struct type
     // then use it.
-    if (ResultType && !isOpaqueTypeDefinition(T, ResultType))
-      return ResultType;
+    if (TDTI != TagDeclTypes.end() &&   // Don't have a type?
+        // Have a type, but it was opaque before and now we have a definition.
+        (!isa<llvm::OpaqueType>(TDTI->second.get()) || !TD->isDefinition()))
+      return TDTI->second;
+        
+    llvm::Type *ResultType = 0;
     
     if (!TD->isDefinition()) {
-      ResultType = TagDeclTypes[TD] = llvm::OpaqueType::get();  
+      ResultType = llvm::OpaqueType::get();  
+      TagDeclTypes.insert(std::make_pair(TD, ResultType));
     } else if (TD->getKind() == Decl::Enum) {
+      // Don't bother storing enums in TagDeclTypes.
       return ConvertType(cast<EnumDecl>(TD)->getIntegerType());
     } else if (TD->getKind() == Decl::Struct) {
       const RecordDecl *RD = cast<const RecordDecl>(TD);
       
       // If this is nested record and this RecordDecl is already under
       // process then return associated OpaqueType for now.
-      llvm::DenseMap<const RecordDecl *, llvm::Type *>::iterator 
-        OpaqueI = RecordTypesToResolve.find(RD);
-      if (OpaqueI != RecordTypesToResolve.end())
-        return OpaqueI->second;
-
-      llvm::OpaqueType *OpaqueTy = NULL;
-      if (ResultType)
-        OpaqueTy = dyn_cast<llvm::OpaqueType>(ResultType);
-      if (!OpaqueTy) {
-        // Create new OpaqueType now for later use.
-        // FIXME: This creates a lot of opaque types, most of them are not 
-        // needed. Reevaluate this when performance analyis finds tons of 
-        // opaque types.
-        OpaqueTy = llvm::OpaqueType::get();
-        TypeHolderMap.insert(std::make_pair(T.getTypePtr(), 
-                                            llvm::PATypeHolder(OpaqueTy)));
+      if (TDTI == TagDeclTypes.end()) {
+        // Create new OpaqueType now for later use in case this is a recursive
+        // type.  This will later be refined to the actual type.
+        ResultType = llvm::OpaqueType::get();
+        TagDeclTypes.insert(std::make_pair(TD, ResultType));
+        TypeHolderMap.insert(std::make_pair(T.getTypePtr(), ResultType));
       }
-      RecordTypesToResolve[RD] = OpaqueTy;
 
       // Layout fields.
       RecordOrganizer RO(*this);
@@ -331,16 +328,19 @@
       // Get llvm::StructType.
       CGRecordLayout *RLI = new CGRecordLayout(RO.getLLVMType(), 
                                                RO.getPaddingFields());
-      ResultType = TagDeclTypes[TD] = RLI->getLLVMType();
+      ResultType = RLI->getLLVMType();
+      TagDeclTypes.insert(std::make_pair(TD, ResultType));
       CGRecordLayouts[TD] = RLI;
 
-      // Refine any OpaqueType associated with this RecordDecl.
-      OpaqueTy->refineAbstractTypeTo(ResultType);
-      OpaqueI = RecordTypesToResolve.find(RD);
-      assert (OpaqueI != RecordTypesToResolve.end() 
-              && "Expected RecordDecl in RecordTypesToResolve");
-      RecordTypesToResolve.erase(OpaqueI);
+      // Refining away Opaque could cause ResultType to become invalidated.
+      // Keep it in a happy little type holder to handle this.
+      llvm::PATypeHolder Holder(ResultType);
+      
+      // Refine the OpaqueType associated with this RecordDecl.
+      cast<llvm::OpaqueType>(TagDeclTypes.find(TD)->second.get())
+        ->refineAbstractTypeTo(ResultType);
 
+      ResultType = Holder.get();
     } else if (TD->getKind() == Decl::Union) {
       const RecordDecl *RD = cast<const RecordDecl>(TD);
       // Just use the largest element of the union, breaking ties with the
@@ -355,11 +355,13 @@
         // Get llvm::StructType.
         CGRecordLayout *RLI = new CGRecordLayout(RO.getLLVMType(),
                                                  RO.getPaddingFields());
-        ResultType = TagDeclTypes[TD] = RLI->getLLVMType();
+        ResultType = RLI->getLLVMType();
+        TagDeclTypes.insert(std::make_pair(TD, ResultType));
         CGRecordLayouts[TD] = RLI;
       } else {       
         std::vector<const llvm::Type*> Fields;
-        ResultType = TagDeclTypes[TD] = llvm::StructType::get(Fields);
+        ResultType = llvm::StructType::get(Fields);
+        TagDeclTypes.insert(std::make_pair(TD, ResultType));
       }
     } else {
       assert(0 && "FIXME: Implement tag decl kind!");

Modified: cfe/trunk/CodeGen/CodeGenTypes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenTypes.h?rev=46745&r1=46744&r2=46745&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CodeGenTypes.h (original)
+++ cfe/trunk/CodeGen/CodeGenTypes.h Tue Feb  5 02:06:13 2008
@@ -75,7 +75,7 @@
   llvm::Module& TheModule;
   const llvm::TargetData& TheTargetData;
   
-  llvm::DenseMap<const TagDecl*, llvm::Type*> TagDeclTypes;
+  llvm::DenseMap<const TagDecl*, llvm::PATypeHolder> TagDeclTypes;
 
   /// CGRecordLayouts - This maps llvm struct type with corresponding 
   /// record layout info. 
@@ -100,11 +100,6 @@
 private:
   llvm::DenseMap<const FieldDecl *, BitFieldInfo> BitFields;
 
-  /// RecordTypesToResolve - This keeps track of record types that are not 
-  /// yet incomplete. One llvm::OpaqueType is associated with each incomplete
-  /// record.
-  llvm::DenseMap<const RecordDecl *, llvm::Type *> RecordTypesToResolve;
-
   /// TypeHolderMap - This map keeps cache of llvm::Types (through PATypeHolder)
   /// and maps llvm::Types to corresponding clang::Type. llvm::PATypeHolder is
   /// used instead of llvm::Type because it allows us to bypass potential 
@@ -142,6 +137,12 @@
   /// that corresponds to the field FD.
   unsigned getLLVMFieldNo(const FieldDecl *FD);
     
+  
+  /// ForceTypeCompilation - When we find the definition for a type, we require
+  /// it to be recompiled, to update the lazy understanding of what it is in our
+  /// maps.
+  void ForceTypeCompilation(QualType T);
+  
 public:  // These are internal details of CGT that shouldn't be used externally.
   void DecodeArgumentTypes(const FunctionTypeProto &FTP, 
                            std::vector<const llvm::Type*> &ArgTys);

Modified: cfe/trunk/CodeGen/ModuleBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/ModuleBuilder.cpp?rev=46745&r1=46744&r2=46745&view=diff

==============================================================================
--- cfe/trunk/CodeGen/ModuleBuilder.cpp (original)
+++ cfe/trunk/CodeGen/ModuleBuilder.cpp Tue Feb  5 02:06:13 2008
@@ -50,6 +50,11 @@
   Builder->EmitGlobalVarDeclarator(D);
 }
 
+/// CodeGenTypeDecl - Compile a type.
+void clang::CodeGen::CodeGenTypeDecl(CodeGenModule *Builder, TypeDecl *D) {
+  Builder->EmitType(D);
+}
+
 
 /// PrintStats - Emit statistic information to stderr.
 ///

Modified: cfe/trunk/Driver/ASTConsumers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/ASTConsumers.cpp?rev=46745&r1=46744&r2=46745&view=diff

==============================================================================
--- cfe/trunk/Driver/ASTConsumers.cpp (original)
+++ cfe/trunk/Driver/ASTConsumers.cpp Tue Feb  5 02:06:13 2008
@@ -635,10 +635,7 @@
       } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
         CodeGen::CodeGenLinkageSpec(Builder, LSD);
       } else {
-        assert(isa<TypeDecl>(D) && "Only expected type decls here");
-        // don't codegen for now, eventually pass down for debug info.
-        //std::cerr << "Read top-level typedef decl: '"
-        //    << D->getName() << "'\n";
+        CodeGen::CodeGenTypeDecl(Builder, cast<TypeDecl>(D));
       }
     }
   };

Modified: cfe/trunk/include/clang/CodeGen/ModuleBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/CodeGen/ModuleBuilder.h?rev=46745&r1=46744&r2=46745&view=diff

==============================================================================
--- cfe/trunk/include/clang/CodeGen/ModuleBuilder.h (original)
+++ cfe/trunk/include/clang/CodeGen/ModuleBuilder.h Tue Feb  5 02:06:13 2008
@@ -24,6 +24,7 @@
   class FunctionDecl;
   class LinkageSpecDecl;
   class FileVarDecl;
+  class TypeDecl;
   struct LangOptions;
   class Diagnostic;
 
@@ -44,6 +45,9 @@
   /// CodeGenGlobalVar - Emit the specified global variable to LLVM.
   void CodeGenGlobalVar(CodeGenModule *Builder, FileVarDecl *D);
   
+  /// CodeGenTypeDecl - Compile a type.
+  void CodeGenTypeDecl(CodeGenModule *Builder, TypeDecl *D);
+
   /// PrintStats - Emit statistic information to stderr.
   ///
   void PrintStats(CodeGenModule *Builder);

Added: cfe/trunk/test/CodeGen/types.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/types.c?rev=46745&view=auto

==============================================================================
--- cfe/trunk/test/CodeGen/types.c (added)
+++ cfe/trunk/test/CodeGen/types.c Tue Feb  5 02:06:13 2008
@@ -0,0 +1,16 @@
+// RUN: clang -emit-llvm %s
+
+struct FileName {
+    struct FileName *next;
+} *fnhead;
+
+
+struct ieeeExternal {
+    struct ieeeExternal *next;
+} *exthead;
+
+
+void f()
+{
+    struct ieeeExternal *exttmp = exthead;
+}





More information about the cfe-commits mailing list