diff options
-rw-r--r-- | CodeGen/CodeGenModule.cpp | 21 | ||||
-rw-r--r-- | CodeGen/CodeGenModule.h | 2 | ||||
-rw-r--r-- | CodeGen/CodeGenTypes.cpp | 112 | ||||
-rw-r--r-- | CodeGen/CodeGenTypes.h | 13 | ||||
-rw-r--r-- | CodeGen/ModuleBuilder.cpp | 5 | ||||
-rw-r--r-- | Driver/ASTConsumers.cpp | 5 | ||||
-rw-r--r-- | include/clang/CodeGen/ModuleBuilder.h | 4 | ||||
-rw-r--r-- | test/CodeGen/types.c | 16 |
8 files changed, 113 insertions, 65 deletions
diff --git a/CodeGen/CodeGenModule.cpp b/CodeGen/CodeGenModule.cpp index 9de5d3426f..eff26f91b1 100644 --- a/CodeGen/CodeGenModule.cpp +++ b/CodeGen/CodeGenModule.cpp @@ -261,6 +261,27 @@ void CodeGenModule::EmitGlobalVarDeclarator(const FileVarDecl *D) { 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()) diff --git a/CodeGen/CodeGenModule.h b/CodeGen/CodeGenModule.h index 87b9e9ce16..5135c1b598 100644 --- a/CodeGen/CodeGenModule.h +++ b/CodeGen/CodeGenModule.h @@ -34,6 +34,7 @@ namespace clang { class Stmt; class ValueDecl; class VarDecl; + class TypeDecl; class FileVarDecl; struct LangOptions; class Diagnostic; @@ -87,6 +88,7 @@ public: 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); diff --git a/CodeGen/CodeGenTypes.cpp b/CodeGen/CodeGenTypes.cpp index 97fc61d4ac..2e10cfc971 100644 --- a/CodeGen/CodeGenTypes.cpp +++ b/CodeGen/CodeGenTypes.cpp @@ -91,29 +91,6 @@ CodeGenTypes::~CodeGenTypes() { 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 @@ const llvm::Type *CodeGenTypes::ConvertType(QualType T) { 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 @@ const llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T) { } +/// 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 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { case Type::ASQual: return ConvertType(cast<ASQualType>(Ty).getBaseType()); - break; case Type::ObjCInterface: assert(0 && "FIXME: add missing functionality here"); @@ -285,40 +286,36 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { 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 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { // 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 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { // 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!"); diff --git a/CodeGen/CodeGenTypes.h b/CodeGen/CodeGenTypes.h index 0da71ca029..b60b9bab3a 100644 --- a/CodeGen/CodeGenTypes.h +++ b/CodeGen/CodeGenTypes.h @@ -75,7 +75,7 @@ class CodeGenTypes { 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 @@ public: 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 @@ public: /// 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); diff --git a/CodeGen/ModuleBuilder.cpp b/CodeGen/ModuleBuilder.cpp index fff5b3fbff..b626c45272 100644 --- a/CodeGen/ModuleBuilder.cpp +++ b/CodeGen/ModuleBuilder.cpp @@ -50,6 +50,11 @@ void clang::CodeGen::CodeGenGlobalVar(CodeGenModule *Builder, FileVarDecl *D) { Builder->EmitGlobalVarDeclarator(D); } +/// CodeGenTypeDecl - Compile a type. +void clang::CodeGen::CodeGenTypeDecl(CodeGenModule *Builder, TypeDecl *D) { + Builder->EmitType(D); +} + /// PrintStats - Emit statistic information to stderr. /// diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp index b96a905c95..904a22e59c 100644 --- a/Driver/ASTConsumers.cpp +++ b/Driver/ASTConsumers.cpp @@ -635,10 +635,7 @@ namespace { } 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)); } } }; diff --git a/include/clang/CodeGen/ModuleBuilder.h b/include/clang/CodeGen/ModuleBuilder.h index b27e3d35f5..ab08c4abc6 100644 --- a/include/clang/CodeGen/ModuleBuilder.h +++ b/include/clang/CodeGen/ModuleBuilder.h @@ -24,6 +24,7 @@ namespace clang { class FunctionDecl; class LinkageSpecDecl; class FileVarDecl; + class TypeDecl; struct LangOptions; class Diagnostic; @@ -44,6 +45,9 @@ namespace CodeGen { /// 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); diff --git a/test/CodeGen/types.c b/test/CodeGen/types.c new file mode 100644 index 0000000000..01286e8962 --- /dev/null +++ b/test/CodeGen/types.c @@ -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; +} |