*begins thinking of very _mean_ words to say to Eric if and when the compile-time regressions come* ;)
Chad On Feb 16, 2012, at 2:54 PM, Eric Christopher wrote: > Author: echristo > Date: Thu Feb 16 16:54:45 2012 > New Revision: 150752 > > URL: http://llvm.org/viewvc/llvm-project?rev=150752&view=rev > Log: > Reapply r150631: > > "Add a completed/incomplete type difference. This allows us to have > partial types for contexts and forward decls while allowing us to > complete types later on for debug purposes. > > This piggy-backs on the metadata replacement and rauw changes > for temporary nodes and takes advantage of the incremental > support I added in earlier. This allows us to, if we decide, > to limit adding methods and variables to structures in order > to limit the amount of debug information output into a .o file. > > The caching is a bit complicated though so any thoughts on > untangling that are welcome." > > with a fix: > > - Remove all RAUW during type construction by adding stub versions > of types that we later complete. > > and some TODOs: > > - Add an RAUW cache for forward declared types so that we can replace > them at the end of compilation. > - Remove the code that updates on completed types because we no > longer need to have that happen. We emit incomplete types on > purpose and only want to know when we want to complete them. > > Modified: > cfe/trunk/lib/CodeGen/CGDebugInfo.cpp > cfe/trunk/lib/CodeGen/CGDebugInfo.h > cfe/trunk/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp > > Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=150752&r1=150751&r2=150752&view=diff > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Thu Feb 16 16:54:45 2012 > @@ -524,11 +524,8 @@ > > if (const RecordDecl *RD = dyn_cast<RecordDecl>(Context)) { > if (!RD->isDependentType()) { > - llvm::DIDescriptor FDContext = > - createContextChain(cast<Decl>(RD->getDeclContext())); > - llvm::DIType Ty = createRecordFwdDecl(RD, FDContext); > - > - RegionMap[Context] = llvm::WeakVH(Ty); > + llvm::DIType Ty = > getOrCreateLimitedType(CGM.getContext().getTypeDeclType(RD), > + getOrCreateMainFile()); > return llvm::DIDescriptor(Ty); > } > } > @@ -557,7 +554,9 @@ > RecordDecl *RD = RTy->getDecl(); > llvm::DIDescriptor FDContext = > getContextDescriptor(cast<Decl>(RD->getDeclContext())); > - return createRecordFwdDecl(RD, FDContext); > + llvm::DIType RetTy = createRecordFwdDecl(RD, FDContext); > + TypeCache[PointeeTy.getAsOpaquePtr()] = RetTy; > + return RetTy; > } > return getOrCreateType(PointeeTy, Unit); > > @@ -654,10 +653,11 @@ > // declared. > unsigned Line = getLineNumber(Ty->getDecl()->getLocation()); > const TypedefNameDecl *TyDecl = Ty->getDecl(); > + > llvm::DIDescriptor TypedefContext = > getContextDescriptor(cast<Decl>(Ty->getDecl()->getDeclContext())); > - > - return > + > + return > DBuilder.createTypedef(Src, TyDecl->getName(), Unit, Line, > TypedefContext); > } > > @@ -1133,8 +1133,6 @@ > > // Get overall information about the record type for the debug info. > llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation()); > - unsigned Line = getLineNumber(RD->getLocation()); > - StringRef RDName = RD->getName(); > > // Records and classes and unions can all be recursive. To handle them, we > // first generate a debug descriptor for the struct as a forward > declaration. > @@ -1143,28 +1141,21 @@ > // may refer to the forward decl if the struct is recursive) and replace all > // uses of the forward declaration with the final definition. > > - llvm::DIDescriptor RDContext; > - if (CGM.getCodeGenOpts().LimitDebugInfo) > - RDContext = createContextChain(cast<Decl>(RD->getDeclContext())); > - else > - RDContext = getContextDescriptor(cast<Decl>(RD->getDeclContext())); > - > - // If this is just a forward declaration, construct an appropriately > - // marked node and just return it. > - if (!RD->getDefinition()) > - return createRecordFwdDecl(RD, RDContext); > - > - llvm::DIType FwdDecl = DBuilder.createTemporaryType(DefUnit); > + llvm::DIType FwdDecl = getOrCreateLimitedType(QualType(Ty, 0), DefUnit); > > + if (FwdDecl.isForwardDecl()) > + return FwdDecl; > + > llvm::MDNode *MN = FwdDecl; > llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN; > - // Otherwise, insert it into the TypeCache so that recursive uses will find > - // it. > - TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl; > + > // Push the struct on region stack. > LexicalBlockStack.push_back(FwdDeclNode); > RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl); > > + // Add this to the completed types cache since we're completing it. > + CompletedTypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl; > + > // Convert all the elements. > SmallVector<llvm::Value *, 16> EltTys; > > @@ -1196,50 +1187,20 @@ > if (RI != RegionMap.end()) > RegionMap.erase(RI); > > - uint64_t Size = CGM.getContext().getTypeSize(Ty); > - uint64_t Align = CGM.getContext().getTypeAlign(Ty); > llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys); > - llvm::MDNode *RealDecl = NULL; > - > + // FIXME: Magic numbers ahoy! These should be changed when we > + // get some enums in llvm/Analysis/DebugInfo.h to refer to > + // them. > if (RD->isUnion()) > - RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line, > - Size, Align, 0, Elements); > + MN->replaceOperandWith(10, Elements); > else if (CXXDecl) { > - RDName = getClassName(RD); > - // A class's primary base or the class itself contains the vtable. > - llvm::MDNode *ContainingType = NULL; > - const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); > - if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) { > - // Seek non virtual primary base root. > - while (1) { > - const ASTRecordLayout &BRL = > CGM.getContext().getASTRecordLayout(PBase); > - const CXXRecordDecl *PBT = BRL.getPrimaryBase(); > - if (PBT && !BRL.isPrimaryBaseVirtual()) > - PBase = PBT; > - else > - break; > - } > - ContainingType = > - getOrCreateType(QualType(PBase->getTypeForDecl(), 0), DefUnit); > - } > - else if (CXXDecl->isDynamicClass()) > - ContainingType = FwdDecl; > - > - // FIXME: This could be a struct type giving a default visibility > different > - // than C++ class type, but needs llvm metadata changes first. > - RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line, > - Size, Align, 0, 0, llvm::DIType(), > - Elements, ContainingType, > - TParamsArray); > + MN->replaceOperandWith(10, Elements); > + MN->replaceOperandWith(13, TParamsArray); > } else > - RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line, > - Size, Align, 0, Elements); > + MN->replaceOperandWith(10, Elements); > > - // Now that we have a real decl for the struct, replace anything using the > - // old decl with the new one. This will recursively update the debug info. > - llvm::DIType(FwdDeclNode).replaceAllUsesWith(RealDecl); > - RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl); > - return llvm::DIType(RealDecl); > + RegionMap[Ty->getDecl()] = llvm::WeakVH(MN); > + return llvm::DIType(MN); > } > > /// CreateType - get objective-c object type. > @@ -1274,22 +1235,28 @@ > } > ID = Def; > > - // To handle a recursive interface, we first generate a debug descriptor > - // for the struct as a forward declaration. Then (if it is a definition) > - // we go through and get debug info for all of its members. Finally, we > - // create a descriptor for the complete type (which may refer to the > - // forward decl if the struct is recursive) and replace all uses of the > - // forward declaration with the final definition. > - llvm::DIType FwdDecl = DBuilder.createTemporaryType(DefUnit); > + // Bit size, align and offset of the type. > + uint64_t Size = CGM.getContext().getTypeSize(Ty); > + uint64_t Align = CGM.getContext().getTypeAlign(Ty); > > - llvm::MDNode *MN = FwdDecl; > - llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN; > + unsigned Flags = 0; > + if (ID->getImplementation()) > + Flags |= llvm::DIDescriptor::FlagObjcClassComplete; > + > + llvm::DIType RealDecl = > + DBuilder.createStructType(Unit, ID->getName(), DefUnit, > + Line, Size, Align, Flags, > + llvm::DIArray(), RuntimeLang); > + > // Otherwise, insert it into the TypeCache so that recursive uses will find > // it. > - TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl; > + TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl; > // Push the struct on region stack. > + llvm::MDNode *MN = RealDecl; > + llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN; > + > LexicalBlockStack.push_back(FwdDeclNode); > - RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl); > + RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl); > > // Convert all the elements. > SmallVector<llvm::Value *, 16> EltTys; > @@ -1302,7 +1269,7 @@ > return llvm::DIType(); > > llvm::DIType InhTag = > - DBuilder.createInheritance(FwdDecl, SClassTy, 0, 0); > + DBuilder.createInheritance(RealDecl, SClassTy, 0, 0); > EltTys.push_back(InhTag); > } > > @@ -1381,31 +1348,9 @@ > } > > llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys); > - > + RealDecl->replaceOperandWith(10, Elements); > + > LexicalBlockStack.pop_back(); > - llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator RI = > - RegionMap.find(Ty->getDecl()); > - if (RI != RegionMap.end()) > - RegionMap.erase(RI); > - > - // Bit size, align and offset of the type. > - uint64_t Size = CGM.getContext().getTypeSize(Ty); > - uint64_t Align = CGM.getContext().getTypeAlign(Ty); > - > - unsigned Flags = 0; > - if (ID->getImplementation()) > - Flags |= llvm::DIDescriptor::FlagObjcClassComplete; > - > - llvm::DIType RealDecl = > - DBuilder.createStructType(Unit, ID->getName(), DefUnit, > - Line, Size, Align, Flags, > - Elements, RuntimeLang); > - > - // Now that we have a real decl for the struct, replace anything using the > - // old decl with the new one. This will recursively update the debug info. > - llvm::DIType(FwdDeclNode).replaceAllUsesWith(RealDecl); > - RegionMap[ID] = llvm::WeakVH(RealDecl); > - > return RealDecl; > } > > @@ -1637,6 +1582,26 @@ > return llvm::DIType(); > } > > +/// getCompletedTypeOrNull - Get the type from the cache or return null if it > +/// doesn't exist. > +llvm::DIType CGDebugInfo::getCompletedTypeOrNull(QualType Ty) { > + > + // Unwrap the type as needed for debug information. > + Ty = UnwrapTypeForDebugInfo(Ty); > + > + // Check for existing entry. > + llvm::DenseMap<void *, llvm::WeakVH>::iterator it = > + CompletedTypeCache.find(Ty.getAsOpaquePtr()); > + if (it != CompletedTypeCache.end()) { > + // Verify that the debug info still exists. > + if (&*it->second) > + return llvm::DIType(cast<llvm::MDNode>(it->second)); > + } > + > + return llvm::DIType(); > +} > + > + > /// getOrCreateType - Get the type from the cache or create a new > /// one if necessary. > llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) { > @@ -1646,14 +1611,18 @@ > // Unwrap the type as needed for debug information. > Ty = UnwrapTypeForDebugInfo(Ty); > > - llvm::DIType T = getTypeOrNull(Ty); > + llvm::DIType T = getCompletedTypeOrNull(Ty); > + > if (T.Verify()) return T; > > // Otherwise create the type. > llvm::DIType Res = CreateTypeNode(Ty, Unit); > - > + > // And update the type cache. > - TypeCache[Ty.getAsOpaquePtr()] = Res; > + TypeCache[Ty.getAsOpaquePtr()] = Res; > + > + if (!Res.isForwardDecl()) > + CompletedTypeCache[Ty.getAsOpaquePtr()] = Res; > return Res; > } > > @@ -1737,6 +1706,123 @@ > return llvm::DIType(); > } > > +/// getOrCreateLimitedType - Get the type from the cache or create a new > +/// limited type if necessary. > +llvm::DIType CGDebugInfo::getOrCreateLimitedType(QualType Ty, > + llvm::DIFile Unit) { > + if (Ty.isNull()) > + return llvm::DIType(); > + > + // Unwrap the type as needed for debug information. > + Ty = UnwrapTypeForDebugInfo(Ty); > + > + llvm::DIType T = getTypeOrNull(Ty); > + > + // We may have cached a forward decl when we could have created > + // a non-forward decl. Go ahead and create a non-forward decl > + // now. > + if (T.Verify() && !T.isForwardDecl()) return T; > + > + // Otherwise create the type. > + llvm::DIType Res = CreateLimitedTypeNode(Ty, Unit); > + > + // And update the type cache. > + TypeCache[Ty.getAsOpaquePtr()] = Res; > + return Res; > +} > + > +// TODO: Currently used for context chains when limiting debug info. > +llvm::DIType CGDebugInfo::CreateLimitedType(const RecordType *Ty) { > + RecordDecl *RD = Ty->getDecl(); > + > + // Get overall information about the record type for the debug info. > + llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation()); > + unsigned Line = getLineNumber(RD->getLocation()); > + StringRef RDName = RD->getName(); > + > + llvm::DIDescriptor RDContext; > + if (CGM.getCodeGenOpts().LimitDebugInfo) > + RDContext = createContextChain(cast<Decl>(RD->getDeclContext())); > + else > + RDContext = getContextDescriptor(cast<Decl>(RD->getDeclContext())); > + > + // If this is just a forward declaration, construct an appropriately > + // marked node and just return it. > + if (!RD->getDefinition()) { > + llvm::DIType RTy = createRecordFwdDecl(RD, RDContext); > + TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RTy; > + return RTy; > + } > + > + uint64_t Size = CGM.getContext().getTypeSize(Ty); > + uint64_t Align = CGM.getContext().getTypeAlign(Ty); > + const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD); > + llvm::MDNode *RealDecl = NULL; > + > + if (RD->isUnion()) > + RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line, > + Size, Align, 0, llvm::DIArray()); > + else if (CXXDecl) { > + RDName = getClassName(RD); > + > + // FIXME: This could be a struct type giving a default visibility > different > + // than C++ class type, but needs llvm metadata changes first. > + RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line, > + Size, Align, 0, 0, llvm::DIType(), > + llvm::DIArray(), NULL, > + llvm::DIArray()); > + } else > + RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line, > + Size, Align, 0, llvm::DIArray()); > + > + RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl); > + TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = llvm::DIType(RealDecl); > + > + if (CXXDecl) { > + // A class's primary base or the class itself contains the vtable. > + llvm::MDNode *ContainingType = NULL; > + const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); > + if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) { > + // Seek non virtual primary base root. > + while (1) { > + const ASTRecordLayout &BRL = CGM.getContext().getASTRecordLayout(PBase); > + const CXXRecordDecl *PBT = BRL.getPrimaryBase(); > + if (PBT && !BRL.isPrimaryBaseVirtual()) > + PBase = PBT; > + else > + break; > + } > + ContainingType = > + getOrCreateType(QualType(PBase->getTypeForDecl(), 0), DefUnit); > + } > + else if (CXXDecl->isDynamicClass()) > + ContainingType = RealDecl; > + > + RealDecl->replaceOperandWith(9, ContainingType); > + } > + return llvm::DIType(RealDecl); > +} > + > +/// CreateLimitedTypeNode - Create a new debug type node, but only forward > +/// declare composite types that haven't been processed yet. > +llvm::DIType CGDebugInfo::CreateLimitedTypeNode(QualType Ty,llvm::DIFile > Unit) { > + > + // Work out details of type. > + switch (Ty->getTypeClass()) { > +#define TYPE(Class, Base) > +#define ABSTRACT_TYPE(Class, Base) > +#define NON_CANONICAL_TYPE(Class, Base) > +#define DEPENDENT_TYPE(Class, Base) case Type::Class: > + #include "clang/AST/TypeNodes.def" > + llvm_unreachable("Dependent types cannot show up in debug information"); > + > + case Type::Record: > + return CreateLimitedType(cast<RecordType>(Ty)); > + default: > + return CreateTypeNode(Ty, Unit); > + } > +} > + > /// CreateMemberType - Create new member and increase Offset by FType's size. > llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType, > StringRef Name, > > Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=150752&r1=150751&r2=150752&view=diff > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGDebugInfo.h (original) > +++ cfe/trunk/lib/CodeGen/CGDebugInfo.h Thu Feb 16 16:54:45 2012 > @@ -53,6 +53,9 @@ > /// TypeCache - Cache of previously constructed Types. > llvm::DenseMap<void *, llvm::WeakVH> TypeCache; > > + /// CompleteTypeCache - Cache of previously constructed complete > RecordTypes. > + llvm::DenseMap<void *, llvm::WeakVH> CompletedTypeCache; > + > bool BlockLiteralGenericSet; > llvm::DIType BlockLiteralGeneric; > > @@ -84,6 +87,7 @@ > llvm::DIType CreateType(const BlockPointerType *Ty, llvm::DIFile F); > llvm::DIType CreateType(const FunctionType *Ty, llvm::DIFile F); > llvm::DIType CreateType(const RecordType *Ty); > + llvm::DIType CreateLimitedType(const RecordType *Ty); > llvm::DIType CreateType(const ObjCInterfaceType *Ty, llvm::DIFile F); > llvm::DIType CreateType(const ObjCObjectType *Ty, llvm::DIFile F); > llvm::DIType CreateType(const VectorType *Ty, llvm::DIFile F); > @@ -94,6 +98,7 @@ > llvm::DIType CreateType(const AtomicType *Ty, llvm::DIFile F); > llvm::DIType CreateEnumType(const EnumDecl *ED); > llvm::DIType getTypeOrNull(const QualType); > + llvm::DIType getCompletedTypeOrNull(const QualType); > llvm::DIType getOrCreateMethodType(const CXXMethodDecl *Method, > llvm::DIFile F); > llvm::DIType getOrCreateFunctionType(const Decl *D, QualType FnType, > @@ -257,9 +262,17 @@ > /// necessary. > llvm::DIType getOrCreateType(QualType Ty, llvm::DIFile F); > > + /// getOrCreateLimitedType - Get the type from the cache or create a new > + /// partial type if necessary. > + llvm::DIType getOrCreateLimitedType(QualType Ty, llvm::DIFile F); > + > /// CreateTypeNode - Create type metadata for a source language type. > llvm::DIType CreateTypeNode(QualType Ty, llvm::DIFile F); > > + /// CreateLimitedTypeNode - Create type metadata for a source language > + /// type, but only partial types for records. > + llvm::DIType CreateLimitedTypeNode(QualType Ty, llvm::DIFile F); > + > /// CreateMemberType - Create new member and increase Offset by FType's > size. > llvm::DIType CreateMemberType(llvm::DIFile Unit, QualType FType, > StringRef Name, uint64_t *Offset); > > Modified: cfe/trunk/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp?rev=150752&r1=150751&r2=150752&view=diff > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp (original) > +++ cfe/trunk/test/CodeGenCXX/debug-info-dup-fwd-decl.cpp Thu Feb 16 16:54:45 > 2012 > @@ -19,6 +19,6 @@ > > Test t; > > -// CHECK: metadata !"data", metadata !7, i32 13, i64 32, i64 32, i32 0, i32 0 > +// CHECK: metadata !"data", metadata !7, i32 14, i64 32, i64 32, i32 0, i32 0 > // CHECK: metadata !"", null, i32 0, i64 64, i64 64, i64 0, i32 0, metadata > !5} ; [ DW_TAG_pointer_type ] > // CHECK-NOT: metadata !"data", metadata !7, i32 13, i64 0, i64 0, i32 0, i32 > 4, > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
