diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp | 946 |
1 files changed, 602 insertions, 344 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp index c7a9b40..7301d20 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGDebugInfo.cpp @@ -35,7 +35,6 @@ #include "llvm/Support/Dwarf.h" #include "llvm/Support/FileSystem.h" #include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetMachine.h" using namespace clang; using namespace clang::CodeGen; @@ -75,7 +74,7 @@ void CGDebugInfo::setLocation(SourceLocation Loc) { llvm::DILexicalBlockFile LBF = llvm::DILexicalBlockFile(LB); llvm::DIDescriptor D = DBuilder.createLexicalBlockFile(LBF.getScope(), - getOrCreateFile(CurLoc)); + getOrCreateFile(CurLoc)); llvm::MDNode *N = D; LexicalBlockStack.pop_back(); LexicalBlockStack.push_back(N); @@ -118,12 +117,25 @@ llvm::DIDescriptor CGDebugInfo::getContextDescriptor(const Decl *Context) { StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) { assert (FD && "Invalid FunctionDecl!"); IdentifierInfo *FII = FD->getIdentifier(); - if (FII) + FunctionTemplateSpecializationInfo *Info + = FD->getTemplateSpecializationInfo(); + if (!Info && FII) return FII->getName(); // Otherwise construct human readable name for debug info. std::string NS = FD->getNameAsString(); + // Add any template specialization args. + if (Info) { + const TemplateArgumentList *TArgs = Info->TemplateArguments; + const TemplateArgument *Args = TArgs->data(); + unsigned NumArgs = TArgs->size(); + PrintingPolicy Policy(CGM.getLangOpts()); + NS += TemplateSpecializationType::PrintTemplateArgumentList(Args, + NumArgs, + Policy); + } + // Copy this name on the side and use its reference. char *StrPtr = DebugInfoNames.Allocate<char>(NS.length()); memcpy(StrPtr, NS.data(), NS.length()); @@ -131,7 +143,7 @@ StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) { } StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) { - llvm::SmallString<256> MethodName; + SmallString<256> MethodName; llvm::raw_svector_ostream OS(MethodName); OS << (OMD->isInstanceMethod() ? '-' : '+') << '['; const DeclContext *DC = OMD->getDeclContext(); @@ -164,8 +176,8 @@ StringRef CGDebugInfo::getSelectorName(Selector S) { /// getClassName - Get class name including template argument list. StringRef -CGDebugInfo::getClassName(RecordDecl *RD) { - ClassTemplateSpecializationDecl *Spec +CGDebugInfo::getClassName(const RecordDecl *RD) { + const ClassTemplateSpecializationDecl *Spec = dyn_cast<ClassTemplateSpecializationDecl>(RD); if (!Spec) return RD->getName(); @@ -184,7 +196,7 @@ CGDebugInfo::getClassName(RecordDecl *RD) { NumArgs = TemplateArgs.size(); } Buffer = RD->getIdentifier()->getNameStart(); - PrintingPolicy Policy(CGM.getLangOptions()); + PrintingPolicy Policy(CGM.getLangOpts()); Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args, NumArgs, Policy); @@ -223,7 +235,6 @@ llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) { DIFileCache[fname] = F; return F; - } /// getOrCreateMainFile - Get the file info for main compile unit. @@ -234,7 +245,8 @@ llvm::DIFile CGDebugInfo::getOrCreateMainFile() { /// getLineNumber - Get line number for the location. If location is invalid /// then use current location. unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) { - assert((Loc.isValid() || CurLoc.isValid()) && "Invalid current location!"); + if (Loc.isInvalid() && CurLoc.isInvalid()) + return 0; SourceManager &SM = CGM.getContext().getSourceManager(); PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc); return PLoc.isValid()? PLoc.getLine() : 0; @@ -243,16 +255,20 @@ unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) { /// getColumnNumber - Get column number for the location. If location is /// invalid then use current location. unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc) { - assert((Loc.isValid() || CurLoc.isValid()) && "Invalid current location!"); + if (Loc.isInvalid() && CurLoc.isInvalid()) + return 0; SourceManager &SM = CGM.getContext().getSourceManager(); PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc); return PLoc.isValid()? PLoc.getColumn() : 0; } StringRef CGDebugInfo::getCurrentDirname() { + if (!CGM.getCodeGenOpts().DebugCompilationDir.empty()) + return CGM.getCodeGenOpts().DebugCompilationDir; + if (!CWDName.empty()) return CWDName; - llvm::SmallString<256> CWD; + SmallString<256> CWD; llvm::sys::fs::current_path(CWD); char *CompDirnamePtr = DebugInfoNames.Allocate<char>(CWD.size()); memcpy(CompDirnamePtr, CWD.data(), CWD.size()); @@ -285,7 +301,7 @@ void CGDebugInfo::CreateCompileUnit() { StringRef Filename(FilenamePtr, MainFileName.length()); unsigned LangTag; - const LangOptions &LO = CGM.getLangOptions(); + const LangOptions &LO = CGM.getLangOpts(); if (LO.CPlusPlus) { if (LO.ObjC1) LangTag = llvm::dwarf::DW_LANG_ObjC_plus_plus; @@ -321,35 +337,32 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) { unsigned Encoding = 0; const char *BTName = NULL; switch (BT->getKind()) { +#define BUILTIN_TYPE(Id, SingletonId) +#define PLACEHOLDER_TYPE(Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/AST/BuiltinTypes.def" case BuiltinType::Dependent: - llvm_unreachable("Unexpected builtin type Dependent"); - case BuiltinType::Overload: - llvm_unreachable("Unexpected builtin type Overload"); - case BuiltinType::BoundMember: - llvm_unreachable("Unexpected builtin type BoundMember"); - case BuiltinType::UnknownAny: - llvm_unreachable("Unexpected builtin type UnknownAny"); + llvm_unreachable("Unexpected builtin type"); case BuiltinType::NullPtr: return DBuilder. - createNullPtrType(BT->getName(CGM.getContext().getLangOptions())); + createNullPtrType(BT->getName(CGM.getContext().getLangOpts())); case BuiltinType::Void: return llvm::DIType(); case BuiltinType::ObjCClass: - return DBuilder.createStructType(TheCU, "objc_class", - getOrCreateMainFile(), 0, 0, 0, - llvm::DIDescriptor::FlagFwdDecl, - llvm::DIArray()); + return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, + "objc_class", getOrCreateMainFile(), + 0); case BuiltinType::ObjCId: { // typedef struct objc_class *Class; // typedef struct objc_object { // Class isa; // } *id; - llvm::DIType OCTy = - DBuilder.createStructType(TheCU, "objc_class", - getOrCreateMainFile(), 0, 0, 0, - llvm::DIDescriptor::FlagFwdDecl, - llvm::DIArray()); + // TODO: Cache these two types to avoid duplicates. + llvm::DIType OCTy = + DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, + "objc_class", getOrCreateMainFile(), + 0); unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); llvm::DIType ISATy = DBuilder.createPointerType(OCTy, Size); @@ -367,10 +380,10 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) { 0, 0, 0, 0, Elements); } case BuiltinType::ObjCSel: { - return DBuilder.createStructType(TheCU, "objc_selector", - getOrCreateMainFile(), 0, 0, 0, - llvm::DIDescriptor::FlagFwdDecl, - llvm::DIArray()); + return + DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, + "objc_selector", getOrCreateMainFile(), + 0); } case BuiltinType::UChar: case BuiltinType::Char_U: Encoding = llvm::dwarf::DW_ATE_unsigned_char; break; @@ -403,7 +416,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) { case BuiltinType::ULong: BTName = "long unsigned int"; break; case BuiltinType::ULongLong: BTName = "long long unsigned int"; break; default: - BTName = BT->getName(CGM.getContext().getLangOptions()); + BTName = BT->getName(CGM.getContext().getLangOpts()); break; } // Bit size, align and offset of the type. @@ -479,34 +492,82 @@ llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty, Ty->getPointeeType(), Unit); } +// Creates a forward declaration for a RecordDecl in the given context. +llvm::DIType CGDebugInfo::createRecordFwdDecl(const RecordDecl *RD, + llvm::DIDescriptor Ctx) { + llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation()); + unsigned Line = getLineNumber(RD->getLocation()); + StringRef RDName = RD->getName(); + + // Get the tag. + const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD); + unsigned Tag = 0; + if (CXXDecl) { + RDName = getClassName(RD); + Tag = llvm::dwarf::DW_TAG_class_type; + } + else if (RD->isStruct()) + Tag = llvm::dwarf::DW_TAG_structure_type; + else if (RD->isUnion()) + Tag = llvm::dwarf::DW_TAG_union_type; + else + llvm_unreachable("Unknown RecordDecl type!"); + + // Create the type. + return DBuilder.createForwardDecl(Tag, RDName, DefUnit, Line); +} + +// Walk up the context chain and create forward decls for record decls, +// and normal descriptors for namespaces. +llvm::DIDescriptor CGDebugInfo::createContextChain(const Decl *Context) { + if (!Context) + return TheCU; + + // See if we already have the parent. + llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator + I = RegionMap.find(Context); + if (I != RegionMap.end()) + return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(&*I->second)); + + // Check namespace. + if (const NamespaceDecl *NSDecl = dyn_cast<NamespaceDecl>(Context)) + return llvm::DIDescriptor(getOrCreateNameSpace(NSDecl)); + + if (const RecordDecl *RD = dyn_cast<RecordDecl>(Context)) { + if (!RD->isDependentType()) { + llvm::DIType Ty = getOrCreateLimitedType(CGM.getContext().getTypeDeclType(RD), + getOrCreateMainFile()); + return llvm::DIDescriptor(Ty); + } + } + return TheCU; +} + /// CreatePointeeType - Create Pointee type. If Pointee is a record /// then emit record's fwd if debug info size reduction is enabled. llvm::DIType CGDebugInfo::CreatePointeeType(QualType PointeeTy, llvm::DIFile Unit) { if (!CGM.getCodeGenOpts().LimitDebugInfo) return getOrCreateType(PointeeTy, Unit); - + + // Limit debug info for the pointee type. + + // If we have an existing type, use that, it's still smaller than creating + // a new type. + llvm::DIType Ty = getTypeOrNull(PointeeTy); + if (Ty.Verify()) return Ty; + + // Handle qualifiers. + if (PointeeTy.hasLocalQualifiers()) + return CreateQualifiedType(PointeeTy, Unit); + if (const RecordType *RTy = dyn_cast<RecordType>(PointeeTy)) { RecordDecl *RD = RTy->getDecl(); - llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation()); - unsigned Line = getLineNumber(RD->getLocation()); llvm::DIDescriptor FDContext = getContextDescriptor(cast<Decl>(RD->getDeclContext())); - - if (RD->isStruct()) - return DBuilder.createStructType(FDContext, RD->getName(), DefUnit, - Line, 0, 0, llvm::DIType::FlagFwdDecl, - llvm::DIArray()); - else if (RD->isUnion()) - return DBuilder.createUnionType(FDContext, RD->getName(), DefUnit, - Line, 0, 0, llvm::DIType::FlagFwdDecl, - llvm::DIArray()); - else { - assert(RD->isClass() && "Unknown RecordType!"); - return DBuilder.createClassType(FDContext, RD->getName(), DefUnit, - Line, 0, 0, 0, llvm::DIType::FlagFwdDecl, - llvm::DIType(), llvm::DIArray()); - } + llvm::DIType RetTy = createRecordFwdDecl(RD, FDContext); + TypeCache[QualType(RTy, 0).getAsOpaquePtr()] = RetTy; + return RetTy; } return getOrCreateType(PointeeTy, Unit); @@ -516,7 +577,6 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag, const Type *Ty, QualType PointeeTy, llvm::DIFile Unit) { - if (Tag == llvm::dwarf::DW_TAG_reference_type) return DBuilder.createReferenceType(CreatePointeeType(PointeeTy, Unit)); @@ -527,8 +587,8 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag, uint64_t Size = CGM.getContext().getTargetInfo().getPointerWidth(AS); uint64_t Align = CGM.getContext().getTypeAlign(Ty); - return - DBuilder.createPointerType(CreatePointeeType(PointeeTy, Unit), Size, Align); + return DBuilder.createPointerType(CreatePointeeType(PointeeTy, Unit), + Size, Align); } llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, @@ -594,8 +654,7 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, return BlockLiteralGeneric; } -llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, - llvm::DIFile Unit) { +llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, llvm::DIFile Unit) { // Typedefs are derived from some other type. If we have a typedef of a // typedef, make sure to emit the whole chain. llvm::DIType Src = getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit); @@ -605,11 +664,12 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, // declared. unsigned Line = getLineNumber(Ty->getDecl()->getLocation()); const TypedefNameDecl *TyDecl = Ty->getDecl(); - llvm::DIDescriptor TydefContext = + + llvm::DIDescriptor TypedefContext = getContextDescriptor(cast<Decl>(Ty->getDecl()->getDeclContext())); - - return - DBuilder.createTypedef(Src, TyDecl->getName(), Unit, Line, TydefContext); + + return + DBuilder.createTypedef(Src, TyDecl->getName(), Unit, Line, TypedefContext); } llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, @@ -634,6 +694,34 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, return DbgTy; } + +void CGDebugInfo:: +CollectRecordStaticVars(const RecordDecl *RD, llvm::DIType FwdDecl) { + + for (RecordDecl::decl_iterator I = RD->decls_begin(), E = RD->decls_end(); + I != E; ++I) + if (const VarDecl *V = dyn_cast<VarDecl>(*I)) { + if (V->getInit()) { + const APValue *Value = V->evaluateValue(); + if (Value && Value->isInt()) { + llvm::ConstantInt *CI + = llvm::ConstantInt::get(CGM.getLLVMContext(), Value->getInt()); + + // Create the descriptor for static variable. + llvm::DIFile VUnit = getOrCreateFile(V->getLocation()); + StringRef VName = V->getName(); + llvm::DIType VTy = getOrCreateType(V->getType(), VUnit); + // Do not use DIGlobalVariable for enums. + if (VTy.getTag() != llvm::dwarf::DW_TAG_enumeration_type) { + DBuilder.createStaticVariable(FwdDecl, VName, VName, VUnit, + getLineNumber(V->getLocation()), + VTy, true, CI); + } + } + } + } +} + llvm::DIType CGDebugInfo::createFieldType(StringRef name, QualType type, uint64_t sizeInBitsOverride, @@ -674,44 +762,75 @@ CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit, SmallVectorImpl<llvm::Value *> &elements, llvm::DIType RecordTy) { unsigned fieldNo = 0; - const FieldDecl *LastFD = 0; - bool IsMsStruct = record->hasAttr<MsStructAttr>(); - const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record); - for (RecordDecl::field_iterator I = record->field_begin(), - E = record->field_end(); - I != E; ++I, ++fieldNo) { - FieldDecl *field = *I; - if (IsMsStruct) { - // Zero-length bitfields following non-bitfield members are ignored - if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((field), LastFD)) { - --fieldNo; - continue; + const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(record); + + // For C++11 Lambdas a Fields will be the same as a Capture, but the Capture + // has the name and the location of the variable so we should iterate over + // both concurrently. + if (CXXDecl && CXXDecl->isLambda()) { + RecordDecl::field_iterator Field = CXXDecl->field_begin(); + unsigned fieldno = 0; + for (CXXRecordDecl::capture_const_iterator I = CXXDecl->captures_begin(), + E = CXXDecl->captures_end(); I != E; ++I, ++Field, ++fieldno) { + const LambdaExpr::Capture C = *I; + // TODO: Need to handle 'this' in some way by probably renaming the + // this of the lambda class and having a field member of 'this'. + if (C.capturesVariable()) { + VarDecl *V = C.getCapturedVar(); + llvm::DIFile VUnit = getOrCreateFile(C.getLocation()); + StringRef VName = V->getName(); + uint64_t SizeInBitsOverride = 0; + if (Field->isBitField()) { + SizeInBitsOverride = Field->getBitWidthValue(CGM.getContext()); + assert(SizeInBitsOverride && "found named 0-width bitfield"); + } + llvm::DIType fieldType + = createFieldType(VName, Field->getType(), SizeInBitsOverride, C.getLocation(), + Field->getAccess(), layout.getFieldOffset(fieldno), + VUnit, RecordTy); + elements.push_back(fieldType); } - LastFD = field; } + } else { + bool IsMsStruct = record->hasAttr<MsStructAttr>(); + const FieldDecl *LastFD = 0; + for (RecordDecl::field_iterator I = record->field_begin(), + E = record->field_end(); + I != E; ++I, ++fieldNo) { + FieldDecl *field = *I; + + if (IsMsStruct) { + // Zero-length bitfields following non-bitfield members are ignored + if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((field), LastFD)) { + --fieldNo; + continue; + } + LastFD = field; + } - StringRef name = field->getName(); - QualType type = field->getType(); + StringRef name = field->getName(); + QualType type = field->getType(); - // Ignore unnamed fields unless they're anonymous structs/unions. - if (name.empty() && !type->isRecordType()) { - LastFD = field; - continue; - } + // Ignore unnamed fields unless they're anonymous structs/unions. + if (name.empty() && !type->isRecordType()) { + LastFD = field; + continue; + } - uint64_t SizeInBitsOverride = 0; - if (field->isBitField()) { - SizeInBitsOverride = field->getBitWidthValue(CGM.getContext()); - assert(SizeInBitsOverride && "found named 0-width bitfield"); - } + uint64_t SizeInBitsOverride = 0; + if (field->isBitField()) { + SizeInBitsOverride = field->getBitWidthValue(CGM.getContext()); + assert(SizeInBitsOverride && "found named 0-width bitfield"); + } - llvm::DIType fieldType - = createFieldType(name, type, SizeInBitsOverride, - field->getLocation(), field->getAccess(), - layout.getFieldOffset(fieldNo), tunit, RecordTy); + llvm::DIType fieldType + = createFieldType(name, type, SizeInBitsOverride, + field->getLocation(), field->getAccess(), + layout.getFieldOffset(fieldNo), tunit, RecordTy); - elements.push_back(fieldType); + elements.push_back(fieldType); + } } } @@ -725,7 +844,7 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, = getOrCreateType(QualType(Method->getType()->getAs<FunctionProtoType>(), 0), Unit); - + // Add "this" pointer. llvm::DIArray Args = llvm::DICompositeType(FnTy).getTypeArray(); assert (Args.getNumElements() && "Invalid number of arguments!"); @@ -738,11 +857,29 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, if (!Method->isStatic()) { // "this" pointer is always first argument. QualType ThisPtr = Method->getThisType(CGM.getContext()); - llvm::DIType ThisPtrType = - DBuilder.createArtificialType(getOrCreateType(ThisPtr, Unit)); - - TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType; - Elts.push_back(ThisPtrType); + + const CXXRecordDecl *RD = Method->getParent(); + if (isa<ClassTemplateSpecializationDecl>(RD)) { + // Create pointer type directly in this case. + const PointerType *ThisPtrTy = cast<PointerType>(ThisPtr); + QualType PointeeTy = ThisPtrTy->getPointeeType(); + unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy); + uint64_t Size = CGM.getContext().getTargetInfo().getPointerWidth(AS); + uint64_t Align = CGM.getContext().getTypeAlign(ThisPtrTy); + llvm::DIType PointeeType = getOrCreateType(PointeeTy, Unit); + llvm::DIType ThisPtrType = DBuilder.createPointerType(PointeeType, Size, Align); + TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType; + // TODO: This and the artificial type below are misleading, the + // types aren't artificial the argument is, but the current + // metadata doesn't represent that. + ThisPtrType = DBuilder.createArtificialType(ThisPtrType); + Elts.push_back(ThisPtrType); + } else { + llvm::DIType ThisPtrType = getOrCreateType(ThisPtr, Unit); + TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType; + ThisPtrType = DBuilder.createArtificialType(ThisPtrType); + Elts.push_back(ThisPtrType); + } } // Copy rest of the arguments. @@ -757,14 +894,13 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, /// isFunctionLocalClass - Return true if CXXRecordDecl is defined /// inside a function. static bool isFunctionLocalClass(const CXXRecordDecl *RD) { - if (const CXXRecordDecl *NRD = - dyn_cast<CXXRecordDecl>(RD->getDeclContext())) + if (const CXXRecordDecl *NRD = dyn_cast<CXXRecordDecl>(RD->getDeclContext())) return isFunctionLocalClass(NRD); - else if (isa<FunctionDecl>(RD->getDeclContext())) + if (isa<FunctionDecl>(RD->getDeclContext())) return true; return false; - } + /// CreateCXXMemberFunction - A helper function to create a DISubprogram for /// a single member function GlobalDecl. llvm::DISubprogram @@ -823,35 +959,48 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method, } if (Method->hasPrototype()) Flags |= llvm::DIDescriptor::FlagPrototyped; - + + llvm::DIArray TParamsArray = CollectFunctionTemplateParams(Method, Unit); llvm::DISubprogram SP = DBuilder.createMethod(RecordTy, MethodName, MethodLinkageName, MethodDefUnit, MethodLine, MethodTy, /*isLocalToUnit=*/false, /* isDefinition=*/ false, Virtuality, VIndex, ContainingType, - Flags, CGM.getLangOptions().Optimize); + Flags, CGM.getLangOpts().Optimize, NULL, + TParamsArray); - SPCache[Method] = llvm::WeakVH(SP); + SPCache[Method->getCanonicalDecl()] = llvm::WeakVH(SP); return SP; } /// CollectCXXMemberFunctions - A helper function to collect debug info for -/// C++ member functions.This is used while creating debug info entry for +/// C++ member functions. This is used while creating debug info entry for /// a Record. void CGDebugInfo:: CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit, SmallVectorImpl<llvm::Value *> &EltTys, llvm::DIType RecordTy) { - for(CXXRecordDecl::method_iterator I = RD->method_begin(), - E = RD->method_end(); I != E; ++I) { - const CXXMethodDecl *Method = *I; - - if (Method->isImplicit() && !Method->isUsed()) + + // Since we want more than just the individual member decls if we + // have templated functions iterate over every declaration to gather + // the functions. + for(DeclContext::decl_iterator I = RD->decls_begin(), + E = RD->decls_end(); I != E; ++I) { + Decl *D = *I; + if (D->isImplicit() && !D->isUsed()) continue; - EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy)); + if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) + EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy)); + else if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D)) + for (FunctionTemplateDecl::spec_iterator SI = FTD->spec_begin(), + SE = FTD->spec_end(); SI != SE; ++SI) { + FunctionDecl *FD = *SI; + if (CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(FD)) + EltTys.push_back(CreateCXXMemberFunction(M, Unit, RecordTy)); + } } } @@ -862,7 +1011,7 @@ void CGDebugInfo:: CollectCXXFriends(const CXXRecordDecl *RD, llvm::DIFile Unit, SmallVectorImpl<llvm::Value *> &EltTys, llvm::DIType RecordTy) { - for (CXXRecordDecl::friend_iterator BI = RD->friend_begin(), + for (CXXRecordDecl::friend_iterator BI = RD->friend_begin(), BE = RD->friend_end(); BI != BE; ++BI) { if ((*BI)->isUnsupportedFriend()) continue; @@ -992,7 +1141,7 @@ llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) { /// getVTableName - Get vtable name for the given Class. StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) { - // Otherwise construct gdb compatible name name. + // Construct gdb compatible name name. std::string Name = "_vptr$" + RD->getNameAsString(); // Copy this name on the side and use its reference. @@ -1028,7 +1177,15 @@ CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit, /// getOrCreateRecordType - Emit record type's standalone debug info. llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy, SourceLocation Loc) { - llvm::DIType T = getOrCreateType(RTy, getOrCreateFile(Loc)); + llvm::DIType T = getOrCreateType(RTy, getOrCreateFile(Loc)); + return T; +} + +/// getOrCreateInterfaceType - Emit an objective c interface type standalone +/// debug info. +llvm::DIType CGDebugInfo::getOrCreateInterfaceType(QualType D, + SourceLocation Loc) { + llvm::DIType T = getOrCreateType(D, getOrCreateFile(Loc)); DBuilder.retainType(T); return T; } @@ -1036,11 +1193,9 @@ llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy, /// CreateType - get structure or union type. llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { RecordDecl *RD = Ty->getDecl(); - llvm::DIFile Unit = getOrCreateFile(RD->getLocation()); // Get overall information about the record type for the debug info. llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation()); - unsigned Line = getLineNumber(RD->getLocation()); // 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. @@ -1048,126 +1203,63 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { // 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::DIDescriptor FDContext = - 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 FwdDecl = - DBuilder.createStructType(FDContext, RD->getName(), - DefUnit, Line, 0, 0, - llvm::DIDescriptor::FlagFwdDecl, - llvm::DIArray()); + llvm::DIType FwdDecl = getOrCreateLimitedType(QualType(Ty, 0), DefUnit); - return FwdDecl; - } + if (FwdDecl.isForwardDecl()) + return FwdDecl; - llvm::DIType FwdDecl = DBuilder.createTemporaryType(DefUnit); + llvm::TrackingVH<llvm::MDNode> FwdDeclNode(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; + // Note: The split of CXXDecl information here is intentional, the + // gdb tests will depend on a certain ordering at printout. The debug + // information offsets are still correct if we merge them all together + // though. const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD); if (CXXDecl) { - CollectCXXBases(CXXDecl, Unit, EltTys, FwdDecl); - CollectVTableInfo(CXXDecl, Unit, EltTys); + CollectCXXBases(CXXDecl, DefUnit, EltTys, FwdDecl); + CollectVTableInfo(CXXDecl, DefUnit, EltTys); } - - // Collect static variables with initializers. - for (RecordDecl::decl_iterator I = RD->decls_begin(), E = RD->decls_end(); - I != E; ++I) - if (const VarDecl *V = dyn_cast<VarDecl>(*I)) { - if (const Expr *Init = V->getInit()) { - Expr::EvalResult Result; - if (Init->Evaluate(Result, CGM.getContext()) && Result.Val.isInt()) { - llvm::ConstantInt *CI - = llvm::ConstantInt::get(CGM.getLLVMContext(), Result.Val.getInt()); - - // Create the descriptor for static variable. - llvm::DIFile VUnit = getOrCreateFile(V->getLocation()); - StringRef VName = V->getName(); - llvm::DIType VTy = getOrCreateType(V->getType(), VUnit); - // Do not use DIGlobalVariable for enums. - if (VTy.getTag() != llvm::dwarf::DW_TAG_enumeration_type) { - DBuilder.createStaticVariable(FwdDecl, VName, VName, VUnit, - getLineNumber(V->getLocation()), - VTy, true, CI); - } - } - } - } - CollectRecordFields(RD, Unit, EltTys, FwdDecl); + // Collect static variables with initializers and other fields. + CollectRecordStaticVars(RD, FwdDecl); + CollectRecordFields(RD, DefUnit, EltTys, FwdDecl); llvm::DIArray TParamsArray; if (CXXDecl) { - CollectCXXMemberFunctions(CXXDecl, Unit, EltTys, FwdDecl); - CollectCXXFriends(CXXDecl, Unit, EltTys, FwdDecl); + CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl); + CollectCXXFriends(CXXDecl, DefUnit, EltTys, FwdDecl); if (const ClassTemplateSpecializationDecl *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD)) - TParamsArray = CollectCXXTemplateParams(TSpecial, Unit); + TParamsArray = CollectCXXTemplateParams(TSpecial, DefUnit); } LexicalBlockStack.pop_back(); - llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator RI = - RegionMap.find(Ty->getDecl()); - if (RI != RegionMap.end()) - RegionMap.erase(RI); + RegionMap.erase(Ty->getDecl()); - llvm::DIDescriptor RDContext = - getContextDescriptor(cast<Decl>(RD->getDeclContext())); - StringRef RDName = RD->getName(); - 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); + FwdDeclNode->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), Unit); - } - else if (CXXDecl->isDynamicClass()) - ContainingType = FwdDecl; - - RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line, - Size, Align, 0, 0, llvm::DIType(), - Elements, ContainingType, - TParamsArray); - } else - RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line, - Size, Align, 0, Elements); + FwdDeclNode->replaceOperandWith(10, Elements); + FwdDeclNode->replaceOperandWith(13, TParamsArray); + } else + FwdDeclNode->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[RD] = llvm::WeakVH(RealDecl); - return llvm::DIType(RealDecl); + RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDeclNode); + return llvm::DIType(FwdDeclNode); } /// CreateType - get objective-c object type. @@ -1191,30 +1283,38 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, // If this is just a forward declaration return a special forward-declaration // debug type since we won't be able to lay out the entire type. - if (ID->isForwardDecl()) { + ObjCInterfaceDecl *Def = ID->getDefinition(); + if (!Def) { llvm::DIType FwdDecl = - DBuilder.createStructType(Unit, ID->getName(), - DefUnit, Line, 0, 0, 0, - llvm::DIArray(), RuntimeLang); + DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, + ID->getName(), DefUnit, Line, + RuntimeLang); return FwdDecl; } - // 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); - - 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; + ID = Def; + + // 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, + llvm::DIArray(), RuntimeLang); + + // Otherwise, insert it into the CompletedTypeCache so that recursive uses + // will find it and we're emitting the complete type. + CompletedTypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl; // Push the struct on region stack. + llvm::TrackingVH<llvm::MDNode> FwdDeclNode(RealDecl); + 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; @@ -1227,12 +1327,31 @@ 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); } + for (ObjCContainerDecl::prop_iterator I = ID->prop_begin(), + E = ID->prop_end(); I != E; ++I) { + const ObjCPropertyDecl *PD = *I; + SourceLocation Loc = PD->getLocation(); + llvm::DIFile PUnit = getOrCreateFile(Loc); + unsigned PLine = getLineNumber(Loc); + ObjCMethodDecl *Getter = PD->getGetterMethodDecl(); + ObjCMethodDecl *Setter = PD->getSetterMethodDecl(); + llvm::MDNode *PropertyNode = + DBuilder.createObjCProperty(PD->getName(), + PUnit, PLine, + (Getter && Getter->isImplicit()) ? "" : + getSelectorName(PD->getGetterName()), + (Setter && Setter->isImplicit()) ? "" : + getSelectorName(PD->getSetterName()), + PD->getPropertyAttributes(), + getOrCreateType(PD->getType(), PUnit)); + EltTys.push_back(PropertyNode); + } + const ASTRecordLayout &RL = CGM.getContext().getASTObjCInterfaceLayout(ID); - ObjCImplementationDecl *ImpD = ID->getImplementation(); unsigned FieldNo = 0; for (ObjCIvarDecl *Field = ID->all_declared_ivar_begin(); Field; Field = Field->getNextIvar(), ++FieldNo) { @@ -1266,7 +1385,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, // the non-fragile abi and the debugger should ignore the value anyways. // Call it the FieldNo+1 due to how debuggers use the information, // e.g. negating the value when it needs a lookup in the dynamic table. - uint64_t FieldOffset = CGM.getLangOptions().ObjCNonFragileABI ? FieldNo+1 + uint64_t FieldOffset = CGM.getLangOpts().ObjCNonFragileABI ? FieldNo+1 : RL.getFieldOffset(FieldNo); unsigned Flags = 0; @@ -1275,69 +1394,43 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, else if (Field->getAccessControl() == ObjCIvarDecl::Private) Flags = llvm::DIDescriptor::FlagPrivate; - StringRef PropertyName; - StringRef PropertyGetter; - StringRef PropertySetter; - unsigned PropertyAttributes = 0; - ObjCPropertyDecl *PD = NULL; - if (ImpD) + llvm::MDNode *PropertyNode = NULL; + if (ObjCImplementationDecl *ImpD = ID->getImplementation()) { if (ObjCPropertyImplDecl *PImpD = - ImpD->FindPropertyImplIvarDecl(Field->getIdentifier())) - PD = PImpD->getPropertyDecl(); - if (PD) { - PropertyName = PD->getName(); - PropertyGetter = getSelectorName(PD->getGetterName()); - PropertySetter = getSelectorName(PD->getSetterName()); - PropertyAttributes = PD->getPropertyAttributes(); - } + ImpD->FindPropertyImplIvarDecl(Field->getIdentifier())) { + if (ObjCPropertyDecl *PD = PImpD->getPropertyDecl()) { + SourceLocation Loc = PD->getLocation(); + llvm::DIFile PUnit = getOrCreateFile(Loc); + unsigned PLine = getLineNumber(Loc); + ObjCMethodDecl *Getter = PD->getGetterMethodDecl(); + ObjCMethodDecl *Setter = PD->getSetterMethodDecl(); + PropertyNode = + DBuilder.createObjCProperty(PD->getName(), + PUnit, PLine, + (Getter && Getter->isImplicit()) ? "" : + getSelectorName(PD->getGetterName()), + (Setter && Setter->isImplicit()) ? "" : + getSelectorName(PD->getSetterName()), + PD->getPropertyAttributes(), + getOrCreateType(PD->getType(), PUnit)); + } + } + } FieldTy = DBuilder.createObjCIVar(FieldName, FieldDefUnit, FieldLine, FieldSize, FieldAlign, FieldOffset, Flags, FieldTy, - PropertyName, PropertyGetter, - PropertySetter, PropertyAttributes); + PropertyNode); EltTys.push_back(FieldTy); } llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys); - + FwdDeclNode->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; -} - -llvm::DIType CGDebugInfo::CreateType(const TagType *Ty) { - if (const RecordType *RT = dyn_cast<RecordType>(Ty)) - return CreateType(RT); - else if (const EnumType *ET = dyn_cast<EnumType>(Ty)) - return CreateEnumType(ET->getDecl()); - - return llvm::DIType(); + return llvm::DIType(FwdDeclNode); } -llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty, - llvm::DIFile Unit) { +llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty, llvm::DIFile Unit) { llvm::DIType ElementTy = getOrCreateType(Ty->getElementType(), Unit); int64_t NumElems = Ty->getNumElements(); int64_t LowerBound = 0; @@ -1545,20 +1638,14 @@ static QualType UnwrapTypeForDebugInfo(QualType T) { if (T == LastT) return T; } while (true); - - return T; } -/// getOrCreateType - Get the type from the cache or create a new -/// one if necessary. -llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, - llvm::DIFile Unit) { - if (Ty.isNull()) - return llvm::DIType(); +/// getType - Get the type from the cache or return null type if it doesn't exist. +llvm::DIType CGDebugInfo::getTypeOrNull(QualType Ty) { // Unwrap the type as needed for debug information. Ty = UnwrapTypeForDebugInfo(Ty); - + // Check for existing entry. llvm::DenseMap<void *, llvm::WeakVH>::iterator it = TypeCache.find(Ty.getAsOpaquePtr()); @@ -1568,17 +1655,59 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, return llvm::DIType(cast<llvm::MDNode>(it->second)); } + 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) { + if (Ty.isNull()) + return llvm::DIType(); + + // Unwrap the type as needed for debug information. + Ty = UnwrapTypeForDebugInfo(Ty); + + llvm::DIType T = getCompletedTypeOrNull(Ty); + + if (T.Verify()) return T; + // Otherwise create the type. llvm::DIType Res = CreateTypeNode(Ty, Unit); + llvm::DIType TC = getTypeOrNull(Ty); + if (TC.Verify() && TC.isForwardDecl()) + ReplaceMap.push_back(std::make_pair(Ty.getAsOpaquePtr(), TC)); + // And update the type cache. - TypeCache[Ty.getAsOpaquePtr()] = Res; + TypeCache[Ty.getAsOpaquePtr()] = Res; + + if (!Res.isForwardDecl()) + CompletedTypeCache[Ty.getAsOpaquePtr()] = Res; return Res; } /// CreateTypeNode - Create a new debug type node. -llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, - llvm::DIFile Unit) { +llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) { // Handle qualifiers, which recursively handles what they refer to. if (Ty.hasLocalQualifiers()) return CreateQualifiedType(Ty, Unit); @@ -1603,15 +1732,20 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, return CreateType(cast<ObjCObjectType>(Ty), Unit); case Type::ObjCInterface: return CreateType(cast<ObjCInterfaceType>(Ty), Unit); - case Type::Builtin: return CreateType(cast<BuiltinType>(Ty)); - case Type::Complex: return CreateType(cast<ComplexType>(Ty)); - case Type::Pointer: return CreateType(cast<PointerType>(Ty), Unit); + case Type::Builtin: + return CreateType(cast<BuiltinType>(Ty)); + case Type::Complex: + return CreateType(cast<ComplexType>(Ty)); + case Type::Pointer: + return CreateType(cast<PointerType>(Ty), Unit); case Type::BlockPointer: return CreateType(cast<BlockPointerType>(Ty), Unit); - case Type::Typedef: return CreateType(cast<TypedefType>(Ty), Unit); + case Type::Typedef: + return CreateType(cast<TypedefType>(Ty), Unit); case Type::Record: + return CreateType(cast<RecordType>(Ty)); case Type::Enum: - return CreateType(cast<TagType>(Ty)); + return CreateEnumType(cast<EnumType>(Ty)->getDecl()); case Type::FunctionProto: case Type::FunctionNoProto: return CreateType(cast<FunctionType>(Ty), Unit); @@ -1642,7 +1776,6 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, case Type::UnaryTransform: case Type::Auto: llvm_unreachable("type should have been unwrapped!"); - return llvm::DIType(); } assert(Diag && "Fall through without a diagnostic?"); @@ -1653,6 +1786,123 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, 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); + + if (T.Verify() && T.isForwardDecl()) + ReplaceMap.push_back(std::make_pair(Ty.getAsOpaquePtr(), T)); + + // 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()) + return createRecordFwdDecl(RD, RDContext); + + uint64_t Size = CGM.getContext().getTypeSize(Ty); + uint64_t Align = CGM.getContext().getTypeAlign(Ty); + const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD); + llvm::TrackingVH<llvm::MDNode> RealDecl; + + 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(), llvm::DIType(), + 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(12, 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, @@ -1677,7 +1927,7 @@ llvm::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) { getContextDescriptor(cast<Decl>(D->getDeclContext())); llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator - MI = SPCache.find(FD); + MI = SPCache.find(FD->getCanonicalDecl()); if (MI != SPCache.end()) { llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(&*MI->second)); if (SP.isSubprogram() && !llvm::DISubprogram(SP).isDefinition()) @@ -1688,7 +1938,7 @@ llvm::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) { E = FD->redecls_end(); I != E; ++I) { const FunctionDecl *NextFD = *I; llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator - MI = SPCache.find(NextFD); + MI = SPCache.find(NextFD->getCanonicalDecl()); if (MI != SPCache.end()) { llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(&*MI->second)); if (SP.isSubprogram() && !llvm::DISubprogram(SP).isDefinition()) @@ -1705,7 +1955,7 @@ llvm::DIType CGDebugInfo::getOrCreateFunctionType(const Decl * D, llvm::DIFile F) { if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) return getOrCreateMethodType(Method, F); - else if (const ObjCMethodDecl *OMethod = dyn_cast<ObjCMethodDecl>(D)) { + if (const ObjCMethodDecl *OMethod = dyn_cast<ObjCMethodDecl>(D)) { // Add "self" and "_cmd" SmallVector<llvm::Value *, 16> Elts; @@ -1726,8 +1976,7 @@ llvm::DIType CGDebugInfo::getOrCreateFunctionType(const Decl * D, return getOrCreateType(FnType, F); } -/// EmitFunctionStart - Constructs the debug code for entering a function - -/// "llvm.dbg.func.start.". +/// EmitFunctionStart - Constructs the debug code for entering a function. void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, llvm::Function *Fn, CGBuilderTy &Builder) { @@ -1738,15 +1987,17 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, FnBeginRegionCount.push_back(LexicalBlockStack.size()); const Decl *D = GD.getDecl(); + // Use the location of the declaration. + SourceLocation Loc = D->getLocation(); unsigned Flags = 0; - llvm::DIFile Unit = getOrCreateFile(CurLoc); + llvm::DIFile Unit = getOrCreateFile(Loc); llvm::DIDescriptor FDContext(Unit); llvm::DIArray TParamsArray; if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - // If there is a DISubprogram for this function available then use it. + // If there is a DISubprogram for this function available then use it. llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator - FI = SPCache.find(FD); + FI = SPCache.find(FD->getCanonicalDecl()); if (FI != SPCache.end()) { llvm::DIDescriptor SP(dyn_cast_or_null<llvm::MDNode>(&*FI->second)); if (SP.isSubprogram() && llvm::DISubprogram(SP).isDefinition()) { @@ -1758,12 +2009,13 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, } Name = getFunctionName(FD); // Use mangled name as linkage name for c/c++ functions. - if (!Fn->hasInternalLinkage()) + if (FD->hasPrototype()) { LinkageName = CGM.getMangledName(GD); + Flags |= llvm::DIDescriptor::FlagPrototyped; + } if (LinkageName == Name) LinkageName = StringRef(); - if (FD->hasPrototype()) - Flags |= llvm::DIDescriptor::FlagPrototyped; + if (const NamespaceDecl *NSDecl = dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext())) FDContext = getOrCreateNameSpace(NSDecl); @@ -1784,18 +2036,17 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, if (!Name.empty() && Name[0] == '\01') Name = Name.substr(1); - // It is expected that CurLoc is set before using EmitFunctionStart. - // Usually, CurLoc points to the left bracket location of compound - // statement representing function body. - unsigned LineNo = getLineNumber(CurLoc); + unsigned LineNo = getLineNumber(Loc); if (D->isImplicit()) Flags |= llvm::DIDescriptor::FlagArtificial; + llvm::DISubprogram SPDecl = getFunctionDeclaration(D); llvm::DISubprogram SP = DBuilder.createFunction(FDContext, Name, LinkageName, Unit, LineNo, getOrCreateFunctionType(D, FnType, Unit), Fn->hasInternalLinkage(), true/*definition*/, - Flags, CGM.getLangOptions().Optimize, Fn, + getLineNumber(CurLoc), + Flags, CGM.getLangOpts().Optimize, Fn, TParamsArray, SPDecl); // Push function on region stack. @@ -1835,11 +2086,11 @@ void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) { void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) { llvm::DIDescriptor D = DBuilder.createLexicalBlock(LexicalBlockStack.empty() ? - llvm::DIDescriptor() : - llvm::DIDescriptor(LexicalBlockStack.back()), - getOrCreateFile(CurLoc), - getLineNumber(CurLoc), - getColumnNumber(CurLoc)); + llvm::DIDescriptor() : + llvm::DIDescriptor(LexicalBlockStack.back()), + getOrCreateFile(CurLoc), + getLineNumber(CurLoc), + getColumnNumber(CurLoc)); llvm::MDNode *DN = D; LexicalBlockStack.push_back(DN); } @@ -1855,8 +2106,8 @@ void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder, SourceLocation Loc // Emit a line table change for the current location inside the new scope. Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(getLineNumber(Loc), - getColumnNumber(Loc), - LexicalBlockStack.back())); + getColumnNumber(Loc), + LexicalBlockStack.back())); } /// EmitLexicalBlockEnd - Constructs the debug code for exiting a declarative @@ -1997,7 +2248,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, if (VD->hasAttr<BlocksAttr>()) { CharUnits offset = CharUnits::fromQuantity(32); SmallVector<llvm::Value *, 9> addr; - llvm::Type *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext()); + llvm::Type *Int64Ty = CGM.Int64Ty; addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); // offset of __forwarding field offset = CGM.getContext().toCharUnitsFromBits( @@ -2017,7 +2268,6 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, addr, ArgNo); // Insert an llvm.dbg.declare into the current block. - // Insert an llvm.dbg.declare into the current block. llvm::Instruction *Call = DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock()); Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope)); @@ -2027,7 +2277,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, llvm::DIVariable D = DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope), Name, Unit, Line, Ty, - CGM.getLangOptions().Optimize, Flags, ArgNo); + CGM.getLangOpts().Optimize, Flags, ArgNo); // Insert an llvm.dbg.declare into the current block. llvm::Instruction *Call = @@ -2056,7 +2306,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, llvm::DIVariable D = DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope), FieldName, Unit, Line, FieldTy, - CGM.getLangOptions().Optimize, Flags, + CGM.getLangOpts().Optimize, Flags, ArgNo); // Insert an llvm.dbg.declare into the current block. @@ -2103,7 +2353,7 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable( ->getElementOffset(blockInfo.getCapture(VD).getIndex())); SmallVector<llvm::Value *, 9> addr; - llvm::Type *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext()); + llvm::Type *Int64Ty = CGM.Int64Ty; addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity())); if (isByRef) { @@ -2261,7 +2511,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, fields.push_back(fieldType); } - llvm::SmallString<36> typeName; + SmallString<36> typeName; llvm::raw_svector_ostream(typeName) << "__block_literal_" << CGM.getUniqueBlockCount(); @@ -2284,7 +2534,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, DBuilder.createLocalVariable(llvm::dwarf::DW_TAG_arg_variable, llvm::DIDescriptor(scope), name, tunit, line, type, - CGM.getLangOptions().Optimize, flags, + CGM.getLangOpts().Optimize, flags, cast<llvm::Argument>(addr)->getArgNo() + 1); // Insert an llvm.dbg.value into the current block. @@ -2297,7 +2547,6 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, /// EmitGlobalVariable - Emit information about a global variable. void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, const VarDecl *D) { - // Create global variable debug descriptor. llvm::DIFile Unit = getOrCreateFile(D->getLocation()); unsigned LineNo = getLineNumber(D->getLocation()); @@ -2314,7 +2563,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, QualType ET = CGM.getContext().getAsArrayType(T)->getElementType(); T = CGM.getContext().getConstantArrayType(ET, ConstVal, - ArrayType::Normal, 0); + ArrayType::Normal, 0); } StringRef DeclName = D->getName(); StringRef LinkageName; @@ -2395,16 +2644,25 @@ CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) { return NS; } -/// UpdateCompletedType - Update type cache because the type is now -/// translated. -void CGDebugInfo::UpdateCompletedType(const TagDecl *TD) { - QualType Ty = CGM.getContext().getTagDeclType(TD); - - // If the type exist in type cache then remove it from the cache. - // There is no need to prepare debug info for the completed type - // right now. It will be generated on demand lazily. - llvm::DenseMap<void *, llvm::WeakVH>::iterator it = - TypeCache.find(Ty.getAsOpaquePtr()); - if (it != TypeCache.end()) - TypeCache.erase(it); +void CGDebugInfo::finalize(void) { + for (std::vector<std::pair<void *, llvm::WeakVH> >::const_iterator VI + = ReplaceMap.begin(), VE = ReplaceMap.end(); VI != VE; ++VI) { + llvm::DIType Ty, RepTy; + // Verify that the debug info still exists. + if (&*VI->second) + Ty = llvm::DIType(cast<llvm::MDNode>(VI->second)); + + llvm::DenseMap<void *, llvm::WeakVH>::iterator it = + TypeCache.find(VI->first); + if (it != TypeCache.end()) { + // Verify that the debug info still exists. + if (&*it->second) + RepTy = llvm::DIType(cast<llvm::MDNode>(it->second)); + } + + if (Ty.Verify() && Ty.isForwardDecl() && RepTy.Verify()) { + Ty.replaceAllUsesWith(RepTy); + } + } + DBuilder.finalize(); } |