diff options
author | Eric Christopher <echristo@apple.com> | 2012-02-16 22:54:45 +0000 |
---|---|---|
committer | Eric Christopher <echristo@apple.com> | 2012-02-16 22:54:45 +0000 |
commit | 9965deaad40b08203e4cfacf9253fbe494dce81f (patch) | |
tree | fdd1fc852f7c24efa753cb38f023178accf3cc5c /lib/CodeGen/CGDebugInfo.cpp | |
parent | 22cfaf512e4f66105fb1f8dd39e0a77787fbdf9b (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150752 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGDebugInfo.cpp')
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 292 |
1 files changed, 189 insertions, 103 deletions
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 34da5f4d99..1f733be1a7 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -524,11 +524,8 @@ llvm::DIDescriptor CGDebugInfo::createContextChain(const Decl *Context) { 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 @@ llvm::DIType CGDebugInfo::CreatePointeeType(QualType PointeeTy, 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 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, llvm::DIFile Unit) { // 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 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { // 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 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { // 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 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { 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 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, } 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 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, 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::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, } 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 @@ llvm::DIType CGDebugInfo::getTypeOrNull(QualType Ty) { 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 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) { // 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 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) { 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, |