diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2011-02-20 13:06:31 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2011-02-20 13:06:31 +0000 |
commit | bca07a4524feb4edec581062d631a13116320a24 (patch) | |
tree | a9243275843fbeaa590afc07ee888e006b8d54ea /lib/CodeGen/CGDebugInfo.cpp | |
parent | 998bc5802ecdd65ce3b270f6c69a8ae8557f0a10 (diff) | |
download | src-bca07a4524feb4edec581062d631a13116320a24.tar.gz src-bca07a4524feb4edec581062d631a13116320a24.zip |
Notes
Diffstat (limited to 'lib/CodeGen/CGDebugInfo.cpp')
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 1006 |
1 files changed, 564 insertions, 442 deletions
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 406db886eeed..469b4605d7ca 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -14,6 +14,7 @@ #include "CGDebugInfo.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" +#include "CGBlocks.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" @@ -32,13 +33,14 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Dwarf.h" -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" +#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" using namespace clang; using namespace clang::CodeGen; CGDebugInfo::CGDebugInfo(CodeGenModule &CGM) - : CGM(CGM), DebugFactory(CGM.getModule()), + : CGM(CGM), DBuilder(CGM.getModule()), BlockLiteralGenericSet(false) { CreateCompileUnit(); } @@ -53,28 +55,27 @@ void CGDebugInfo::setLocation(SourceLocation Loc) { } /// getContextDescriptor - Get context info for the decl. -llvm::DIDescriptor CGDebugInfo::getContextDescriptor(const Decl *Context, - llvm::DIDescriptor &CompileUnit) { +llvm::DIDescriptor CGDebugInfo::getContextDescriptor(const Decl *Context) { if (!Context) - return CompileUnit; + return TheCU; 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)); + 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, CompileUnit)); + return llvm::DIDescriptor(getOrCreateNameSpace(NSDecl)); if (const RecordDecl *RDecl = dyn_cast<RecordDecl>(Context)) { if (!RDecl->isDependentType()) { - llvm::DIType Ty = getOrCreateType(CGM.getContext().getTypeDeclType(RDecl), - llvm::DIFile(CompileUnit)); + llvm::DIType Ty = getOrCreateType(CGM.getContext().getTypeDeclType(RDecl), + getOrCreateMainFile()); return llvm::DIDescriptor(Ty); } } - return CompileUnit; + return TheCU; } /// getFunctionName - Get function name for the given FunctionDecl. If the @@ -100,9 +101,14 @@ llvm::StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) { llvm::raw_svector_ostream OS(MethodName); OS << (OMD->isInstanceMethod() ? '-' : '+') << '['; const DeclContext *DC = OMD->getDeclContext(); - if (const ObjCImplementationDecl *OID = dyn_cast<const ObjCImplementationDecl>(DC)) { + if (const ObjCImplementationDecl *OID = + dyn_cast<const ObjCImplementationDecl>(DC)) { OS << OID->getName(); - } else if (const ObjCCategoryImplDecl *OCD = dyn_cast<const ObjCCategoryImplDecl>(DC)){ + } else if (const ObjCInterfaceDecl *OID = + dyn_cast<const ObjCInterfaceDecl>(DC)) { + OS << OID->getName(); + } else if (const ObjCCategoryImplDecl *OCD = + dyn_cast<const ObjCCategoryImplDecl>(DC)){ OS << ((NamedDecl *)OCD)->getIdentifier()->getNameStart() << '(' << OCD->getIdentifier()->getNameStart() << ')'; } @@ -131,8 +137,8 @@ CGDebugInfo::getClassName(RecordDecl *RD) { NumArgs = TST->getNumArgs(); } else { const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - Args = TemplateArgs.getFlatArgumentList(); - NumArgs = TemplateArgs.flat_size(); + Args = TemplateArgs.data(); + NumArgs = TemplateArgs.size(); } Buffer = RD->getIdentifier()->getNameStart(); PrintingPolicy Policy(CGM.getLangOptions()); @@ -144,18 +150,21 @@ CGDebugInfo::getClassName(RecordDecl *RD) { char *StrPtr = DebugInfoNames.Allocate<char>(Buffer.length()); memcpy(StrPtr, Buffer.data(), Buffer.length()); return llvm::StringRef(StrPtr, Buffer.length()); - } /// getOrCreateFile - Get the file debug info descriptor for the input location. llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) { if (!Loc.isValid()) // If Location is not valid then use main input file. - return DebugFactory.CreateFile(TheCU.getFilename(), TheCU.getDirectory(), - TheCU); + return DBuilder.CreateFile(TheCU.getFilename(), TheCU.getDirectory()); + SourceManager &SM = CGM.getContext().getSourceManager(); PresumedLoc PLoc = SM.getPresumedLoc(Loc); + if (PLoc.isInvalid() || llvm::StringRef(PLoc.getFilename()).empty()) + // If the location is not valid then use main input file. + return DBuilder.CreateFile(TheCU.getFilename(), TheCU.getDirectory()); + // Cache the results. const char *fname = PLoc.getFilename(); llvm::DenseMap<const char *, llvm::WeakVH>::iterator it = @@ -167,21 +176,25 @@ llvm::DIFile CGDebugInfo::getOrCreateFile(SourceLocation Loc) { return llvm::DIFile(cast<llvm::MDNode>(it->second)); } - llvm::DIFile F = DebugFactory.CreateFile(PLoc.getFilename(), - getCurrentDirname(), TheCU); + llvm::DIFile F = DBuilder.CreateFile(PLoc.getFilename(), getCurrentDirname()); DIFileCache[fname] = F; return F; } +/// getOrCreateMainFile - Get the file info for main compile unit. +llvm::DIFile CGDebugInfo::getOrCreateMainFile() { + return DBuilder.CreateFile(TheCU.getFilename(), TheCU.getDirectory()); +} + /// getLineNumber - Get line number for the location. If location is invalid /// then use current location. unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) { assert (CurLoc.isValid() && "Invalid current location!"); SourceManager &SM = CGM.getContext().getSourceManager(); PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc); - return PLoc.getLine(); + return PLoc.isValid()? PLoc.getLine() : 0; } /// getColumnNumber - Get column number for the location. If location is @@ -190,7 +203,7 @@ unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc) { assert (CurLoc.isValid() && "Invalid current location!"); SourceManager &SM = CGM.getContext().getSourceManager(); PresumedLoc PLoc = SM.getPresumedLoc(Loc.isValid() ? Loc : CurLoc); - return PLoc.getColumn(); + return PLoc.isValid()? PLoc.getColumn() : 0; } llvm::StringRef CGDebugInfo::getCurrentDirname() { @@ -251,16 +264,17 @@ void CGDebugInfo::CreateCompileUnit() { RuntimeVers = LO.ObjCNonFragileABI ? 2 : 1; // Create new compile unit. - TheCU = DebugFactory.CreateCompileUnit( + DBuilder.CreateCompileUnit( LangTag, Filename, getCurrentDirname(), - Producer, true, + Producer, LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers); + // FIXME - Eliminate TheCU. + TheCU = llvm::DICompileUnit(DBuilder.getCU()); } /// CreateType - Get the Basic type from the cache or create a new /// one if necessary. -llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT, - llvm::DIFile Unit) { +llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) { unsigned Encoding = 0; const char *BTName = NULL; switch (BT->getKind()) { @@ -268,10 +282,10 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT, case BuiltinType::Void: return llvm::DIType(); case BuiltinType::ObjCClass: - return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_structure_type, - Unit, "objc_class", Unit, 0, 0, 0, 0, - llvm::DIType::FlagFwdDecl, - llvm::DIType(), llvm::DIArray()); + return DBuilder.CreateStructType(TheCU, "objc_class", + getOrCreateMainFile(), 0, 0, 0, + llvm::DIDescriptor::FlagFwdDecl, + llvm::DIArray()); case BuiltinType::ObjCId: { // typedef struct objc_class *Class; // typedef struct objc_object { @@ -279,31 +293,31 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT, // } *id; llvm::DIType OCTy = - DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_structure_type, - Unit, "objc_class", Unit, 0, 0, 0, 0, - llvm::DIType::FlagFwdDecl, - llvm::DIType(), llvm::DIArray()); + DBuilder.CreateStructType(TheCU, "objc_class", + getOrCreateMainFile(), 0, 0, 0, + llvm::DIDescriptor::FlagFwdDecl, + llvm::DIArray()); unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); - llvm::DIType ISATy = - DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, - Unit, "", Unit, - 0, Size, 0, 0, 0, OCTy); - - llvm::SmallVector<llvm::DIDescriptor, 16> EltTys; + llvm::DIType ISATy = DBuilder.CreatePointerType(OCTy, Size); + llvm::SmallVector<llvm::Value *, 16> EltTys; llvm::DIType FieldTy = - DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - "isa", Unit, - 0,Size, 0, 0, 0, ISATy); + DBuilder.CreateMemberType("isa", getOrCreateMainFile(), + 0,Size, 0, 0, 0, ISATy); EltTys.push_back(FieldTy); llvm::DIArray Elements = - DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); + DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size()); - return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_structure_type, - Unit, "objc_object", Unit, 0, 0, 0, 0, - 0, - llvm::DIType(), Elements); + return DBuilder.CreateStructType(TheCU, "objc_object", + getOrCreateMainFile(), + 0, 0, 0, 0, Elements); + } + case BuiltinType::ObjCSel: { + return DBuilder.CreateStructType(TheCU, "objc_selector", + getOrCreateMainFile(), 0, 0, 0, + llvm::DIDescriptor::FlagFwdDecl, + llvm::DIArray()); } case BuiltinType::UChar: case BuiltinType::Char_U: Encoding = llvm::dwarf::DW_ATE_unsigned_char; break; @@ -335,17 +349,12 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT, // Bit size, align and offset of the type. uint64_t Size = CGM.getContext().getTypeSize(BT); uint64_t Align = CGM.getContext().getTypeAlign(BT); - uint64_t Offset = 0; - llvm::DIType DbgTy = - DebugFactory.CreateBasicType(Unit, BTName, - Unit, 0, Size, Align, - Offset, /*flags*/ 0, Encoding); + DBuilder.CreateBasicType(BTName, Size, Align, Encoding); return DbgTy; } -llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty, - llvm::DIFile Unit) { +llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty) { // Bit size, align and offset of the type. unsigned Encoding = llvm::dwarf::DW_ATE_complex_float; if (Ty->isComplexIntegerType()) @@ -353,12 +362,9 @@ llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty, uint64_t Size = CGM.getContext().getTypeSize(Ty); uint64_t Align = CGM.getContext().getTypeAlign(Ty); - uint64_t Offset = 0; - llvm::DIType DbgTy = - DebugFactory.CreateBasicType(Unit, "complex", - Unit, 0, Size, Align, - Offset, /*flags*/ 0, Encoding); + DBuilder.CreateBasicType("complex", Size, Align, Encoding); + return DbgTy; } @@ -389,13 +395,12 @@ llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) { return getOrCreateType(QualType(T, 0), Unit); } - llvm::DIType FromTy = getOrCreateType(Qc.apply(T), Unit); + llvm::DIType FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit); // No need to fill in the Name, Line, Size, Alignment, Offset in case of // CVR derived types. - llvm::DIType DbgTy = - DebugFactory.CreateDerivedType(Tag, Unit, "", Unit, - 0, 0, 0, 0, 0, FromTy); + llvm::DIType DbgTy = DBuilder.CreateQualifiedType(Tag, FromTy); + return DbgTy; } @@ -413,24 +418,56 @@ llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty, Ty->getPointeeType(), Unit); } +/// CreatePointeeType - Create PointTee 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); + + 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(dyn_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()); + } + } + return getOrCreateType(PointeeTy, Unit); + +} + llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag, const Type *Ty, QualType PointeeTy, llvm::DIFile Unit) { - llvm::DIType EltTy = getOrCreateType(PointeeTy, Unit); + if (Tag == llvm::dwarf::DW_TAG_reference_type) + return DBuilder.CreateReferenceType(CreatePointeeType(PointeeTy, Unit)); + // Bit size, align and offset of the type. - // Size is always the size of a pointer. We can't use getTypeSize here // because that does not return the correct value for references. uint64_t Size = CGM.getContext().Target.getPointerWidth(PointeeTy.getAddressSpace()); uint64_t Align = CGM.getContext().getTypeAlign(Ty); - return - DebugFactory.CreateDerivedType(Tag, Unit, "", Unit, - 0, Size, Align, 0, 0, EltTy); - + return + DBuilder.CreatePointerType(CreatePointeeType(PointeeTy, Unit), Size, Align); } llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, @@ -438,16 +475,11 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, if (BlockLiteralGenericSet) return BlockLiteralGeneric; - unsigned Tag = llvm::dwarf::DW_TAG_structure_type; - - llvm::SmallVector<llvm::DIDescriptor, 5> EltTys; - + llvm::SmallVector<llvm::Value *, 8> EltTys; llvm::DIType FieldTy; - QualType FType; uint64_t FieldSize, FieldOffset; unsigned FieldAlign; - llvm::DIArray Elements; llvm::DIType EltTy, DescTy; @@ -456,23 +488,20 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, EltTys.push_back(CreateMemberType(Unit, FType, "reserved", &FieldOffset)); EltTys.push_back(CreateMemberType(Unit, FType, "Size", &FieldOffset)); - Elements = DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); + Elements = DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size()); EltTys.clear(); - unsigned Flags = llvm::DIType::FlagAppleBlock; + unsigned Flags = llvm::DIDescriptor::FlagAppleBlock; unsigned LineNo = getLineNumber(CurLoc); - EltTy = DebugFactory.CreateCompositeType(Tag, Unit, "__block_descriptor", - Unit, LineNo, FieldOffset, 0, 0, - Flags, llvm::DIType(), Elements); + EltTy = DBuilder.CreateStructType(Unit, "__block_descriptor", + Unit, LineNo, FieldOffset, 0, + Flags, Elements); // Bit size, align and offset of the type. uint64_t Size = CGM.getContext().getTypeSize(Ty); - uint64_t Align = CGM.getContext().getTypeAlign(Ty); - DescTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, - Unit, "", Unit, - LineNo, Size, Align, 0, 0, EltTy); + DescTy = DBuilder.CreatePointerType(EltTy, Size); FieldOffset = 0; FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); @@ -487,24 +516,20 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, FieldTy = DescTy; FieldSize = CGM.getContext().getTypeSize(Ty); FieldAlign = CGM.getContext().getTypeAlign(Ty); - FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - "__descriptor", Unit, - LineNo, FieldSize, FieldAlign, - FieldOffset, 0, FieldTy); + FieldTy = DBuilder.CreateMemberType("__descriptor", Unit, + LineNo, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); FieldOffset += FieldSize; - Elements = DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); + Elements = DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size()); - EltTy = DebugFactory.CreateCompositeType(Tag, Unit, "__block_literal_generic", - Unit, LineNo, FieldOffset, 0, 0, - Flags, llvm::DIType(), Elements); + EltTy = DBuilder.CreateStructType(Unit, "__block_literal_generic", + Unit, LineNo, FieldOffset, 0, + Flags, Elements); BlockLiteralGenericSet = true; - BlockLiteralGeneric - = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit, - "", Unit, - LineNo, Size, Align, 0, 0, EltTy); + BlockLiteralGeneric = DBuilder.CreatePointerType(EltTy, Size); return BlockLiteralGeneric; } @@ -513,46 +538,36 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, // 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); - + if (!Src.Verify()) + return llvm::DIType(); // We don't set size information, but do specify where the typedef was // declared. unsigned Line = getLineNumber(Ty->getDecl()->getLocation()); - - llvm::DIDescriptor TyContext - = getContextDescriptor(dyn_cast<Decl>(Ty->getDecl()->getDeclContext()), - Unit); - llvm::DIType DbgTy = - DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_typedef, - TyContext, - Ty->getDecl()->getName(), Unit, - Line, 0, 0, 0, 0, Src); + llvm::DIType DbgTy = DBuilder.CreateTypedef(Src, Ty->getDecl()->getName(), + Unit, Line); return DbgTy; } llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, llvm::DIFile Unit) { - llvm::SmallVector<llvm::DIDescriptor, 16> EltTys; + llvm::SmallVector<llvm::Value *, 16> EltTys; // Add the result type at least. EltTys.push_back(getOrCreateType(Ty->getResultType(), Unit)); // Set up remainder of arguments if there is a prototype. // FIXME: IF NOT, HOW IS THIS REPRESENTED? llvm-gcc doesn't represent '...'! - if (const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(Ty)) { + if (isa<FunctionNoProtoType>(Ty)) + EltTys.push_back(DBuilder.CreateUnspecifiedParameter()); + else if (const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(Ty)) { for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i) EltTys.push_back(getOrCreateType(FTP->getArgType(i), Unit)); - } else { - // FIXME: Handle () case in C. llvm-gcc doesn't do it either. } llvm::DIArray EltTypeArray = - DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); + DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size()); - llvm::DIType DbgTy = - DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type, - Unit, "", Unit, - 0, 0, 0, 0, 0, - llvm::DIType(), EltTypeArray); + llvm::DIType DbgTy = DBuilder.CreateSubroutineType(Unit, EltTypeArray); return DbgTy; } @@ -560,7 +575,7 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, /// record fields. This is used while creating debug info entry for a Record. void CGDebugInfo:: CollectRecordFields(const RecordDecl *RD, llvm::DIFile Unit, - llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys) { + llvm::SmallVectorImpl<llvm::Value *> &EltTys) { unsigned FieldNo = 0; const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); for (RecordDecl::field_iterator I = RD->field_begin(), @@ -595,17 +610,13 @@ CollectRecordFields(const RecordDecl *RD, llvm::DIFile Unit, unsigned Flags = 0; AccessSpecifier Access = I->getAccess(); if (Access == clang::AS_private) - Flags |= llvm::DIType::FlagPrivate; + Flags |= llvm::DIDescriptor::FlagPrivate; else if (Access == clang::AS_protected) - Flags |= llvm::DIType::FlagProtected; - - // Create a DW_TAG_member node to remember the offset of this field in the - // struct. FIXME: This is an absolutely insane way to capture this - // information. When we gut debug info, this should be fixed. - FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - FieldName, FieldDefUnit, - FieldLine, FieldSize, FieldAlign, - FieldOffset, Flags, FieldTy); + Flags |= llvm::DIDescriptor::FlagProtected; + + FieldTy = DBuilder.CreateMemberType(FieldName, FieldDefUnit, + FieldLine, FieldSize, FieldAlign, + FieldOffset, Flags, FieldTy); EltTys.push_back(FieldTy); } } @@ -621,19 +632,12 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, 0), Unit); - unsigned BFlags=0; - AccessSpecifier Access = Method->getAccess(); - if (Access == clang::AS_private) - BFlags |= llvm::DIType::FlagPrivate; - else if (Access == clang::AS_protected) - BFlags |= llvm::DIType::FlagProtected; - // Add "this" pointer. llvm::DIArray Args = llvm::DICompositeType(FnTy).getTypeArray(); assert (Args.getNumElements() && "Invalid number of arguments!"); - llvm::SmallVector<llvm::DIDescriptor, 16> Elts; + llvm::SmallVector<llvm::Value *, 16> Elts; // First element is always return type. For 'void' functions it is NULL. Elts.push_back(Args.getElement(0)); @@ -645,7 +649,7 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, QualType ThisPtr = Context.getPointerType(Context.getTagDeclType(Method->getParent())); llvm::DIType ThisPtrType = - DebugFactory.CreateArtificialType(getOrCreateType(ThisPtr, Unit)); + DBuilder.CreateArtificialType(getOrCreateType(ThisPtr, Unit)); TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType; Elts.push_back(ThisPtrType); @@ -656,15 +660,22 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, Elts.push_back(Args.getElement(i)); llvm::DIArray EltTypeArray = - DebugFactory.GetOrCreateArray(Elts.data(), Elts.size()); + DBuilder.GetOrCreateArray(Elts.data(), Elts.size()); - return - DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type, - Unit, "", Unit, - 0, 0, 0, 0, 0, - llvm::DIType(), EltTypeArray); + return DBuilder.CreateSubroutineType(Unit, EltTypeArray); } +/// 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())) + return isFunctionLocalClass(NRD); + else 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 @@ -680,7 +691,7 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method, // Since a single ctor/dtor corresponds to multiple functions, it doesn't // make sense to give a single ctor/dtor a linkage name. llvm::StringRef MethodLinkageName; - if (!IsCtorOrDtor) + if (!IsCtorOrDtor && !isFunctionLocalClass(Method->getParent())) MethodLinkageName = CGM.getMangledName(Method); // Get the location for the method. @@ -705,15 +716,32 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method, ContainingType = RecordTy; } + unsigned Flags = 0; + if (Method->isImplicit()) + Flags |= llvm::DIDescriptor::FlagArtificial; + AccessSpecifier Access = Method->getAccess(); + if (Access == clang::AS_private) + Flags |= llvm::DIDescriptor::FlagPrivate; + else if (Access == clang::AS_protected) + Flags |= llvm::DIDescriptor::FlagProtected; + if (const CXXConstructorDecl *CXXC = dyn_cast<CXXConstructorDecl>(Method)) { + if (CXXC->isExplicit()) + Flags |= llvm::DIDescriptor::FlagExplicit; + } else if (const CXXConversionDecl *CXXC = + dyn_cast<CXXConversionDecl>(Method)) { + if (CXXC->isExplicit()) + Flags |= llvm::DIDescriptor::FlagExplicit; + } + if (Method->hasPrototype()) + Flags |= llvm::DIDescriptor::FlagPrototyped; + llvm::DISubprogram SP = - DebugFactory.CreateSubprogram(RecordTy , MethodName, MethodName, - MethodLinkageName, - MethodDefUnit, MethodLine, - MethodTy, /*isLocalToUnit=*/false, - /* isDefintion=*/ false, - Virtuality, VIndex, ContainingType, - Method->isImplicit(), - CGM.getLangOptions().Optimize); + DBuilder.CreateMethod(RecordTy , MethodName, MethodLinkageName, + MethodDefUnit, MethodLine, + MethodTy, /*isLocalToUnit=*/false, + /* isDefinition=*/ false, + Virtuality, VIndex, ContainingType, + Flags, CGM.getLangOptions().Optimize); // Don't cache ctors or dtors since we have to emit multiple functions for // a single ctor or dtor. @@ -728,7 +756,7 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method, /// a Record. void CGDebugInfo:: CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit, - llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys, + llvm::SmallVectorImpl<llvm::Value *> &EltTys, llvm::DIType RecordTy) { for(CXXRecordDecl::method_iterator I = RD->method_begin(), E = RD->method_end(); I != E; ++I) { @@ -746,26 +774,15 @@ CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit, /// a Record. void CGDebugInfo:: CollectCXXFriends(const CXXRecordDecl *RD, llvm::DIFile Unit, - llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys, + llvm::SmallVectorImpl<llvm::Value *> &EltTys, llvm::DIType RecordTy) { for (CXXRecordDecl::friend_iterator BI = RD->friend_begin(), BE = RD->friend_end(); BI != BE; ++BI) { - - TypeSourceInfo *TInfo = (*BI)->getFriendType(); - if(TInfo) - { - llvm::DIType Ty = getOrCreateType(TInfo->getType(), Unit); - - llvm::DIType DTy = - DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_friend, - RecordTy, llvm::StringRef(), - Unit, 0, 0, 0, - 0, 0, Ty); - - EltTys.push_back(DTy); - } - + if (TypeSourceInfo *TInfo = (*BI)->getFriendType()) + EltTys.push_back(DBuilder.CreateFriend(RecordTy, + getOrCreateType(TInfo->getType(), + Unit))); } } @@ -774,7 +791,7 @@ CollectCXXFriends(const CXXRecordDecl *RD, llvm::DIFile Unit, /// a Record. void CGDebugInfo:: CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit, - llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys, + llvm::SmallVectorImpl<llvm::Value *> &EltTys, llvm::DIType RecordTy) { const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); @@ -790,23 +807,20 @@ CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit, // virtual base offset offset is -ve. The code generator emits dwarf // expression where it expects +ve number. BaseOffset = 0 - CGM.getVTables().getVirtualBaseOffsetOffset(RD, Base); - BFlags = llvm::DIType::FlagVirtual; + BFlags = llvm::DIDescriptor::FlagVirtual; } else - BaseOffset = RL.getBaseClassOffset(Base); + BaseOffset = RL.getBaseClassOffsetInBits(Base); AccessSpecifier Access = BI->getAccessSpecifier(); if (Access == clang::AS_private) - BFlags |= llvm::DIType::FlagPrivate; + BFlags |= llvm::DIDescriptor::FlagPrivate; else if (Access == clang::AS_protected) - BFlags |= llvm::DIType::FlagProtected; + BFlags |= llvm::DIDescriptor::FlagProtected; - llvm::DIType DTy = - DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_inheritance, - RecordTy, llvm::StringRef(), - Unit, 0, 0, 0, - BaseOffset, BFlags, - getOrCreateType(BI->getType(), - Unit)); + llvm::DIType DTy = + DBuilder.CreateInheritance(RecordTy, + getOrCreateType(BI->getType(), Unit), + BaseOffset, BFlags); EltTys.push_back(DTy); } } @@ -819,23 +833,13 @@ llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) { ASTContext &Context = CGM.getContext(); /* Function type */ - llvm::DIDescriptor STy = getOrCreateType(Context.IntTy, Unit); - llvm::DIArray SElements = DebugFactory.GetOrCreateArray(&STy, 1); - llvm::DIType SubTy = - DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type, - Unit, "", Unit, - 0, 0, 0, 0, 0, llvm::DIType(), SElements); - + llvm::Value *STy = getOrCreateType(Context.IntTy, Unit); + llvm::DIArray SElements = DBuilder.GetOrCreateArray(&STy, 1); + llvm::DIType SubTy = DBuilder.CreateSubroutineType(Unit, SElements); unsigned Size = Context.getTypeSize(Context.VoidPtrTy); - llvm::DIType vtbl_ptr_type - = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, - Unit, "__vtbl_ptr_type", Unit, - 0, Size, 0, 0, 0, SubTy); - - VTablePtrType = - DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, - Unit, "", Unit, - 0, Size, 0, 0, 0, vtbl_ptr_type); + llvm::DIType vtbl_ptr_type = DBuilder.CreatePointerType(SubTy, Size, 0, + "__vtbl_ptr_type"); + VTablePtrType = DBuilder.CreatePointerType(vtbl_ptr_type, Size); return VTablePtrType; } @@ -855,7 +859,7 @@ llvm::StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) { /// debug info entry in EltTys vector. void CGDebugInfo:: CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit, - llvm::SmallVectorImpl<llvm::DIDescriptor> &EltTys) { + llvm::SmallVectorImpl<llvm::Value *> &EltTys) { const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); // If there is a primary base then it will hold vtable info. @@ -868,27 +872,24 @@ CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit, unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); llvm::DIType VPTR - = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - getVTableName(RD), Unit, - 0, Size, 0, 0, 0, - getOrCreateVTablePtrType(Unit)); + = DBuilder.CreateMemberType(getVTableName(RD), Unit, + 0, Size, 0, 0, 0, + getOrCreateVTablePtrType(Unit)); EltTys.push_back(VPTR); } +/// getOrCreateRecordType - Emit record type's standalone debug info. +llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy, + SourceLocation Loc) { + llvm::DIType T = getOrCreateType(RTy, getOrCreateFile(Loc)); + DBuilder.RetainType(T); + return T; +} + /// CreateType - get structure or union type. -llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, - llvm::DIFile Unit) { +llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) { RecordDecl *RD = Ty->getDecl(); - - unsigned Tag; - if (RD->isStruct()) - Tag = llvm::dwarf::DW_TAG_structure_type; - else if (RD->isUnion()) - Tag = llvm::dwarf::DW_TAG_union_type; - else { - assert(RD->isClass() && "Unknown RecordType!"); - Tag = llvm::dwarf::DW_TAG_class_type; - } + llvm::DIFile Unit = getOrCreateFile(RD->getLocation()); // Get overall information about the record type for the debug info. llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation()); @@ -901,21 +902,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 FDContext = - getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()), Unit); + getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext())); // If this is just a forward declaration, construct an appropriately // marked node and just return it. if (!RD->getDefinition()) { - llvm::DICompositeType FwdDecl = - DebugFactory.CreateCompositeType(Tag, FDContext, RD->getName(), - DefUnit, Line, 0, 0, 0, - llvm::DIType::FlagFwdDecl, - llvm::DIType(), llvm::DIArray()); + llvm::DIType FwdDecl = + DBuilder.CreateStructType(FDContext, RD->getName(), + DefUnit, Line, 0, 0, + llvm::DIDescriptor::FlagFwdDecl, + llvm::DIArray()); return FwdDecl; } - llvm::DIType FwdDecl = DebugFactory.CreateTemporaryType(); + llvm::DIType FwdDecl = DBuilder.CreateTemporaryType(DefUnit); llvm::MDNode *MN = FwdDecl; llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN; @@ -927,7 +928,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl); // Convert all the elements. - llvm::SmallVector<llvm::DIDescriptor, 16> EltTys; + llvm::SmallVector<llvm::Value *, 16> EltTys; const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD); if (CXXDecl) { @@ -951,36 +952,41 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, llvm::DIType VTy = getOrCreateType(V->getType(), VUnit); // Do not use DIGlobalVariable for enums. if (VTy.getTag() != llvm::dwarf::DW_TAG_enumeration_type) { - DebugFactory.CreateGlobalVariable(FwdDecl, VName, VName, VName, VUnit, - getLineNumber(V->getLocation()), - VTy, true, true, CI); + DBuilder.CreateStaticVariable(FwdDecl, VName, VName, VUnit, + getLineNumber(V->getLocation()), + VTy, true, CI); } } } } CollectRecordFields(RD, Unit, EltTys); - llvm::MDNode *ContainingType = NULL; + llvm::SmallVector<llvm::Value *, 16> TemplateParams; if (CXXDecl) { CollectCXXMemberFunctions(CXXDecl, Unit, EltTys, FwdDecl); CollectCXXFriends(CXXDecl, Unit, EltTys, FwdDecl); - - // A class's primary base or the class itself contains the vtable. - const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); - if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) - ContainingType = - getOrCreateType(QualType(PBase->getTypeForDecl(), 0), Unit); - else if (CXXDecl->isDynamicClass()) - ContainingType = FwdDecl; + if (ClassTemplateSpecializationDecl *TSpecial + = dyn_cast<ClassTemplateSpecializationDecl>(RD)) { + const TemplateArgumentList &TAL = TSpecial->getTemplateArgs(); + for (unsigned i = 0, e = TAL.size(); i != e; ++i) { + const TemplateArgument &TA = TAL[i]; + if (TA.getKind() == TemplateArgument::Type) { + llvm::DIType TTy = getOrCreateType(TA.getAsType(), Unit); + llvm::DITemplateTypeParameter TTP = + DBuilder.CreateTemplateTypeParameter(TheCU, TTy.getName(), TTy); + TemplateParams.push_back(TTP); + } else if (TA.getKind() == TemplateArgument::Integral) { + llvm::DIType TTy = getOrCreateType(TA.getIntegralType(), Unit); + // FIXME: Get parameter name, instead of parameter type name. + llvm::DITemplateValueParameter TVP = + DBuilder.CreateTemplateValueParameter(TheCU, TTy.getName(), TTy, + TA.getAsIntegral()->getZExtValue()); + TemplateParams.push_back(TVP); + } + } + } } - llvm::DIArray Elements = - DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); - - // Bit size, align and offset of the type. - uint64_t Size = CGM.getContext().getTypeSize(Ty); - uint64_t Align = CGM.getContext().getTypeAlign(Ty); - RegionStack.pop_back(); llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator RI = RegionMap.find(Ty->getDecl()); @@ -988,25 +994,54 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, RegionMap.erase(RI); llvm::DIDescriptor RDContext = - getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext()), Unit); - + getContextDescriptor(dyn_cast<Decl>(RD->getDeclContext())); llvm::StringRef RDName = RD->getName(); - // If this is a class, include the template arguments also. - if (Tag == llvm::dwarf::DW_TAG_class_type) + uint64_t Size = CGM.getContext().getTypeSize(Ty); + uint64_t Align = CGM.getContext().getTypeAlign(Ty); + llvm::DIArray Elements = + DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size()); + llvm::MDNode *RealDecl = NULL; + + if (RD->isStruct()) + RealDecl = DBuilder.CreateStructType(RDContext, RDName, DefUnit, Line, + Size, Align, 0, Elements); + else if (RD->isUnion()) + RealDecl = DBuilder.CreateUnionType(RDContext, RDName, DefUnit, Line, + Size, Align, 0, Elements); + else { + assert(RD->isClass() && "Unknown RecordType!"); RDName = getClassName(RD); - - llvm::DICompositeType RealDecl = - DebugFactory.CreateCompositeType(Tag, RDContext, - RDName, - DefUnit, Line, Size, Align, 0, 0, - llvm::DIType(), Elements, - 0, ContainingType); + // 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; + llvm::DIArray TParamsArray = + DBuilder.GetOrCreateArray(TemplateParams.data(), TemplateParams.size()); + RealDecl = DBuilder.CreateClassType(RDContext, RDName, DefUnit, Line, + Size, Align, 0, 0, llvm::DIType(), + Elements, ContainingType, + TParamsArray); + } // 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 RealDecl; + return llvm::DIType(RealDecl); } /// CreateType - get objective-c object type. @@ -1020,7 +1055,8 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCObjectType *Ty, llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, llvm::DIFile Unit) { ObjCInterfaceDecl *ID = Ty->getDecl(); - unsigned Tag = llvm::dwarf::DW_TAG_structure_type; + if (!ID) + return llvm::DIType(); // Get overall information about the record type for the debug info. llvm::DIFile DefUnit = getOrCreateFile(ID->getLocation()); @@ -1030,11 +1066,10 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, // If this is just a forward declaration, return a special forward-declaration // debug type. if (ID->isForwardDecl()) { - llvm::DICompositeType FwdDecl = - DebugFactory.CreateCompositeType(Tag, Unit, ID->getName(), - DefUnit, Line, 0, 0, 0, 0, - llvm::DIType(), llvm::DIArray(), - RuntimeLang); + llvm::DIType FwdDecl = + DBuilder.CreateStructType(Unit, ID->getName(), + DefUnit, Line, 0, 0, 0, + llvm::DIArray(), RuntimeLang); return FwdDecl; } @@ -1044,7 +1079,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *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::DIType FwdDecl = DebugFactory.CreateTemporaryType(); + llvm::DIType FwdDecl = DBuilder.CreateTemporaryType(DefUnit); llvm::MDNode *MN = FwdDecl; llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN; @@ -1056,27 +1091,29 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl); // Convert all the elements. - llvm::SmallVector<llvm::DIDescriptor, 16> EltTys; + llvm::SmallVector<llvm::Value *, 16> EltTys; ObjCInterfaceDecl *SClass = ID->getSuperClass(); if (SClass) { llvm::DIType SClassTy = getOrCreateType(CGM.getContext().getObjCInterfaceType(SClass), Unit); + if (!SClassTy.isValid()) + return llvm::DIType(); + llvm::DIType InhTag = - DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_inheritance, - Unit, "", Unit, 0, 0, 0, - 0 /* offset */, 0, SClassTy); + DBuilder.CreateInheritance(FwdDecl, SClassTy, 0, 0); EltTys.push_back(InhTag); } const ASTRecordLayout &RL = CGM.getContext().getASTObjCInterfaceLayout(ID); unsigned FieldNo = 0; - for (ObjCInterfaceDecl::ivar_iterator I = ID->ivar_begin(), - E = ID->ivar_end(); I != E; ++I, ++FieldNo) { - ObjCIvarDecl *Field = *I; + for (ObjCIvarDecl *Field = ID->all_declared_ivar_begin(); Field; + Field = Field->getNextIvar(), ++FieldNo) { llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit); - + if (!FieldTy.isValid()) + return llvm::DIType(); + llvm::StringRef FieldName = Field->getName(); // Ignore unnamed fields. @@ -1105,22 +1142,18 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, unsigned Flags = 0; if (Field->getAccessControl() == ObjCIvarDecl::Protected) - Flags = llvm::DIType::FlagProtected; + Flags = llvm::DIDescriptor::FlagProtected; else if (Field->getAccessControl() == ObjCIvarDecl::Private) - Flags = llvm::DIType::FlagPrivate; - - // Create a DW_TAG_member node to remember the offset of this field in the - // struct. FIXME: This is an absolutely insane way to capture this - // information. When we gut debug info, this should be fixed. - FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - FieldName, FieldDefUnit, - FieldLine, FieldSize, FieldAlign, - FieldOffset, Flags, FieldTy); + Flags = llvm::DIDescriptor::FlagPrivate; + + FieldTy = DBuilder.CreateMemberType(FieldName, FieldDefUnit, + FieldLine, FieldSize, FieldAlign, + FieldOffset, Flags, FieldTy); EltTys.push_back(FieldTy); } llvm::DIArray Elements = - DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); + DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size()); RegionStack.pop_back(); llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator RI = @@ -1132,10 +1165,10 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, uint64_t Size = CGM.getContext().getTypeSize(Ty); uint64_t Align = CGM.getContext().getTypeAlign(Ty); - llvm::DICompositeType RealDecl = - DebugFactory.CreateCompositeType(Tag, Unit, ID->getName(), DefUnit, - Line, Size, Align, 0, 0, llvm::DIType(), - Elements, RuntimeLang); + llvm::DIType RealDecl = + DBuilder.CreateStructType(Unit, ID->getName(), DefUnit, + Line, Size, Align, 0, + 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. @@ -1145,18 +1178,11 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty, return RealDecl; } -llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty, - llvm::DIFile Unit) { - return CreateEnumType(Ty->getDecl(), Unit); - -} - -llvm::DIType CGDebugInfo::CreateType(const TagType *Ty, - llvm::DIFile Unit) { +llvm::DIType CGDebugInfo::CreateType(const TagType *Ty) { if (const RecordType *RT = dyn_cast<RecordType>(Ty)) - return CreateType(RT, Unit); + return CreateType(RT); else if (const EnumType *ET = dyn_cast<EnumType>(Ty)) - return CreateType(ET, Unit); + return CreateEnumType(ET->getDecl()); return llvm::DIType(); } @@ -1168,17 +1194,14 @@ llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty, if (NumElems > 0) --NumElems; - llvm::DIDescriptor Subscript = DebugFactory.GetOrCreateSubrange(0, NumElems); - llvm::DIArray SubscriptArray = DebugFactory.GetOrCreateArray(&Subscript, 1); + llvm::Value *Subscript = DBuilder.GetOrCreateSubrange(0, NumElems); + llvm::DIArray SubscriptArray = DBuilder.GetOrCreateArray(&Subscript, 1); uint64_t Size = CGM.getContext().getTypeSize(Ty); uint64_t Align = CGM.getContext().getTypeAlign(Ty); return - DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_vector_type, - Unit, "", Unit, - 0, Size, Align, 0, 0, - ElementTy, SubscriptArray); + DBuilder.CreateVectorType(Size, Align, ElementTy, SubscriptArray); } llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty, @@ -1204,27 +1227,28 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty, // Add the dimensions of the array. FIXME: This loses CV qualifiers from // interior arrays, do we care? Why aren't nested arrays represented the // obvious/recursive way? - llvm::SmallVector<llvm::DIDescriptor, 8> Subscripts; + llvm::SmallVector<llvm::Value *, 8> Subscripts; QualType EltTy(Ty, 0); - while ((Ty = dyn_cast<ArrayType>(EltTy))) { - uint64_t Upper = 0; - if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty)) - if (CAT->getSize().getZExtValue()) - Upper = CAT->getSize().getZExtValue() - 1; - // FIXME: Verify this is right for VLAs. - Subscripts.push_back(DebugFactory.GetOrCreateSubrange(0, Upper)); + if (Ty->isIncompleteArrayType()) EltTy = Ty->getElementType(); + else { + while ((Ty = dyn_cast<ArrayType>(EltTy))) { + uint64_t Upper = 0; + if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty)) + if (CAT->getSize().getZExtValue()) + Upper = CAT->getSize().getZExtValue() - 1; + // FIXME: Verify this is right for VLAs. + Subscripts.push_back(DBuilder.GetOrCreateSubrange(0, Upper)); + EltTy = Ty->getElementType(); + } } llvm::DIArray SubscriptArray = - DebugFactory.GetOrCreateArray(Subscripts.data(), Subscripts.size()); + DBuilder.GetOrCreateArray(Subscripts.data(), Subscripts.size()); llvm::DIType DbgTy = - DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_array_type, - Unit, "", Unit, - 0, Size, Align, 0, 0, - getOrCreateType(EltTy, Unit), - SubscriptArray); + DBuilder.CreateArrayType(Size, Align, getOrCreateType(EltTy, Unit), + SubscriptArray); return DbgTy; } @@ -1234,6 +1258,12 @@ llvm::DIType CGDebugInfo::CreateType(const LValueReferenceType *Ty, Ty, Ty->getPointeeType(), Unit); } +llvm::DIType CGDebugInfo::CreateType(const RValueReferenceType *Ty, + llvm::DIFile Unit) { + return CreatePointerLikeType(llvm::dwarf::DW_TAG_rvalue_reference_type, + Ty, Ty->getPointeeType(), Unit); +} + llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty, llvm::DIFile U) { QualType PointerDiffTy = CGM.getContext().getPointerDiffType(); @@ -1249,47 +1279,46 @@ llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty, std::pair<uint64_t, unsigned> Info = CGM.getContext().getTypeInfo(Ty); uint64_t FieldOffset = 0; - llvm::DIDescriptor ElementTypes[2]; + llvm::Value *ElementTypes[2]; // FIXME: This should probably be a function type instead. ElementTypes[0] = - DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, U, - "ptr", U, 0, - Info.first, Info.second, FieldOffset, 0, - PointerDiffDITy); + DBuilder.CreateMemberType("ptr", U, 0, + Info.first, Info.second, FieldOffset, 0, + PointerDiffDITy); FieldOffset += Info.first; ElementTypes[1] = - DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, U, - "ptr", U, 0, - Info.first, Info.second, FieldOffset, 0, - PointerDiffDITy); + DBuilder.CreateMemberType("ptr", U, 0, + Info.first, Info.second, FieldOffset, 0, + PointerDiffDITy); llvm::DIArray Elements = - DebugFactory.GetOrCreateArray(&ElementTypes[0], - llvm::array_lengthof(ElementTypes)); + DBuilder.GetOrCreateArray(&ElementTypes[0], + llvm::array_lengthof(ElementTypes)); - return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_structure_type, - U, llvm::StringRef("test"), - U, 0, FieldOffset, - 0, 0, 0, llvm::DIType(), Elements); + return DBuilder.CreateStructType(U, llvm::StringRef("test"), + U, 0, FieldOffset, + 0, 0, Elements); } /// CreateEnumType - get enumeration type. -llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED, llvm::DIFile Unit){ - llvm::SmallVector<llvm::DIDescriptor, 32> Enumerators; +llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) { + llvm::DIFile Unit = getOrCreateFile(ED->getLocation()); + llvm::SmallVector<llvm::Value *, 16> Enumerators; // Create DIEnumerator elements for each enumerator. for (EnumDecl::enumerator_iterator Enum = ED->enumerator_begin(), EnumEnd = ED->enumerator_end(); Enum != EnumEnd; ++Enum) { - Enumerators.push_back(DebugFactory.CreateEnumerator(Enum->getName(), - Enum->getInitVal().getZExtValue())); + Enumerators.push_back( + DBuilder.CreateEnumerator(Enum->getName(), + Enum->getInitVal().getZExtValue())); } // Return a CompositeType for the enum itself. llvm::DIArray EltArray = - DebugFactory.GetOrCreateArray(Enumerators.data(), Enumerators.size()); + DBuilder.GetOrCreateArray(Enumerators.data(), Enumerators.size()); llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation()); unsigned Line = getLineNumber(ED->getLocation()); @@ -1299,11 +1328,11 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED, llvm::DIFile Unit){ Size = CGM.getContext().getTypeSize(ED->getTypeForDecl()); Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl()); } + llvm::DIDescriptor EnumContext = + getContextDescriptor(dyn_cast<Decl>(ED->getDeclContext())); llvm::DIType DbgTy = - DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type, - Unit, ED->getName(), DefUnit, Line, - Size, Align, 0, 0, - llvm::DIType(), EltArray); + DBuilder.CreateEnumerationType(EnumContext, ED->getName(), DefUnit, Line, + Size, Align, EltArray); return DbgTy; } @@ -1316,20 +1345,23 @@ static QualType UnwrapTypeForDebugInfo(QualType T) { case Type::TemplateSpecialization: T = cast<TemplateSpecializationType>(T)->desugar(); break; - case Type::TypeOfExpr: { - TypeOfExprType *Ty = cast<TypeOfExprType>(T); - T = Ty->getUnderlyingExpr()->getType(); + case Type::TypeOfExpr: + T = cast<TypeOfExprType>(T)->getUnderlyingExpr()->getType(); break; - } case Type::TypeOf: T = cast<TypeOfType>(T)->getUnderlyingType(); break; case Type::Decltype: T = cast<DecltypeType>(T)->getUnderlyingType(); break; + case Type::Attributed: + T = cast<AttributedType>(T)->getEquivalentType(); case Type::Elaborated: T = cast<ElaboratedType>(T)->getNamedType(); break; + case Type::Paren: + T = cast<ParenType>(T)->getInnerType(); + break; case Type::SubstTemplateTypeParm: T = cast<SubstTemplateTypeParmType>(T)->getReplacementType(); break; @@ -1400,15 +1432,15 @@ 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), Unit); - case Type::Complex: return CreateType(cast<ComplexType>(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::Record: case Type::Enum: - return CreateType(cast<TagType>(Ty), Unit); + return CreateType(cast<TagType>(Ty)); case Type::FunctionProto: case Type::FunctionNoProto: return CreateType(cast<FunctionType>(Ty), Unit); @@ -1419,29 +1451,29 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, case Type::LValueReference: return CreateType(cast<LValueReferenceType>(Ty), Unit); + case Type::RValueReference: + return CreateType(cast<RValueReferenceType>(Ty), Unit); case Type::MemberPointer: return CreateType(cast<MemberPointerType>(Ty), Unit); + case Type::Attributed: case Type::TemplateSpecialization: case Type::Elaborated: + case Type::Paren: case Type::SubstTemplateTypeParm: case Type::TypeOfExpr: case Type::TypeOf: case Type::Decltype: + case Type::Auto: llvm_unreachable("type should have been unwrapped!"); - return llvm::DIType(); - - case Type::RValueReference: - // FIXME: Implement! - Diag = "rvalue references"; - break; + return llvm::DIType(); } assert(Diag && "Fall through without a diagnostic?"); unsigned DiagID = CGM.getDiags().getCustomDiagID(Diagnostic::Error, "debug information for %0 is not yet supported"); - CGM.getDiags().Report(FullSourceLoc(), DiagID) + CGM.getDiags().Report(DiagID) << Diag; return llvm::DIType(); } @@ -1453,10 +1485,9 @@ llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType, llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); uint64_t FieldSize = CGM.getContext().getTypeSize(FType); unsigned FieldAlign = CGM.getContext().getTypeAlign(FType); - llvm::DIType Ty = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, - Unit, Name, Unit, 0, - FieldSize, FieldAlign, - *Offset, 0, FieldTy); + llvm::DIType Ty = DBuilder.CreateMemberType(Name, Unit, 0, + FieldSize, FieldAlign, + *Offset, 0, FieldTy); *Offset += FieldSize; return Ty; } @@ -1473,12 +1504,15 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, FnBeginRegionCount.push_back(RegionStack.size()); const Decl *D = GD.getDecl(); + unsigned Flags = 0; + llvm::DIFile Unit = getOrCreateFile(CurLoc); + llvm::DIDescriptor FDContext(Unit); if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { // If there is a DISubprogram for this function available then use it. llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator FI = SPCache.find(FD); if (FI != SPCache.end()) { - llvm::DIDescriptor SP(dyn_cast_or_null<llvm::MDNode>(FI->second)); + llvm::DIDescriptor SP(dyn_cast_or_null<llvm::MDNode>(&*FI->second)); if (SP.isSubprogram() && llvm::DISubprogram(SP).isDefinition()) { llvm::MDNode *SPN = SP; RegionStack.push_back(SPN); @@ -1489,13 +1523,20 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, Name = getFunctionName(FD); // Use mangled name as linkage name for c/c++ functions. LinkageName = CGM.getMangledName(GD); + if (LinkageName == Name) + LinkageName = llvm::StringRef(); + if (FD->hasPrototype()) + Flags |= llvm::DIDescriptor::FlagPrototyped; + if (const NamespaceDecl *NSDecl = + dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext())) + FDContext = getOrCreateNameSpace(NSDecl); } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) { Name = getObjCMethodName(OMD); - LinkageName = Name; + Flags |= llvm::DIDescriptor::FlagPrototyped; } else { - // Use llvm function name as linkage name. + // Use llvm function name. Name = Fn->getName(); - LinkageName = Name; + Flags |= llvm::DIDescriptor::FlagPrototyped; } if (!Name.empty() && Name[0] == '\01') Name = Name.substr(1); @@ -1503,16 +1544,14 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType, // It is expected that CurLoc is set before using EmitFunctionStart. // Usually, CurLoc points to the left bracket location of compound // statement representing function body. - llvm::DIFile Unit = getOrCreateFile(CurLoc); unsigned LineNo = getLineNumber(CurLoc); - + if (D->isImplicit()) + Flags |= llvm::DIDescriptor::FlagArtificial; llvm::DISubprogram SP = - DebugFactory.CreateSubprogram(Unit, Name, Name, LinkageName, Unit, LineNo, - getOrCreateType(FnType, Unit), - Fn->hasInternalLinkage(), true/*definition*/, - 0, 0, llvm::DIType(), - D->isImplicit(), - CGM.getLangOptions().Optimize, Fn); + DBuilder.CreateFunction(FDContext, Name, LinkageName, Unit, + LineNo, getOrCreateType(FnType, Unit), + Fn->hasInternalLinkage(), true/*definition*/, + Flags, CGM.getLangOptions().Optimize, Fn); // Push function on region stack. llvm::MDNode *SPN = SP; @@ -1556,7 +1595,8 @@ void CGDebugInfo::UpdateLineDirectiveRegion(CGBuilderTy &Builder) { PresumedLoc PCLoc = SM.getPresumedLoc(CurLoc); PresumedLoc PPLoc = SM.getPresumedLoc(PrevLoc); - if (!strcmp(PPLoc.getFilename(), PCLoc.getFilename())) + if (PCLoc.isInvalid() || PPLoc.isInvalid() || + !strcmp(PPLoc.getFilename(), PCLoc.getFilename())) return; // If #line directive stack is empty then we are entering a new scope. @@ -1570,9 +1610,10 @@ void CGDebugInfo::UpdateLineDirectiveRegion(CGBuilderTy &Builder) { && "error handling #line regions!"); bool SeenThisFile = false; + // Chek if current file is already seen earlier. for(std::vector<const char *>::iterator I = LineDirectiveFiles.begin(), E = LineDirectiveFiles.end(); I != E; ++I) - if (!strcmp(PPLoc.getFilename(), *I)) { + if (!strcmp(PCLoc.getFilename(), *I)) { SeenThisFile = true; break; } @@ -1599,12 +1640,12 @@ void CGDebugInfo::UpdateLineDirectiveRegion(CGBuilderTy &Builder) { /// region - "llvm.dbg.region.start.". void CGDebugInfo::EmitRegionStart(CGBuilderTy &Builder) { llvm::DIDescriptor D = - DebugFactory.CreateLexicalBlock(RegionStack.empty() ? - llvm::DIDescriptor() : - llvm::DIDescriptor(RegionStack.back()), - getOrCreateFile(CurLoc), - getLineNumber(CurLoc), - getColumnNumber(CurLoc)); + DBuilder.CreateLexicalBlock(RegionStack.empty() ? + llvm::DIDescriptor() : + llvm::DIDescriptor(RegionStack.back()), + getOrCreateFile(CurLoc), + getLineNumber(CurLoc), + getColumnNumber(CurLoc)); llvm::MDNode *DN = D; RegionStack.push_back(DN); } @@ -1637,8 +1678,7 @@ void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) { llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, uint64_t *XOffset) { - llvm::SmallVector<llvm::DIDescriptor, 5> EltTys; - + llvm::SmallVector<llvm::Value *, 5> EltTys; QualType FType; uint64_t FieldSize, FieldOffset; unsigned FieldAlign; @@ -1654,7 +1694,7 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset)); EltTys.push_back(CreateMemberType(Unit, FType, "__size", &FieldOffset)); - bool HasCopyAndDispose = CGM.BlockRequiresCopying(Type); + bool HasCopyAndDispose = CGM.getContext().BlockRequiresCopying(Type); if (HasCopyAndDispose) { FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); EltTys.push_back(CreateMemberType(Unit, FType, "__copy_helper", @@ -1685,24 +1725,21 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD, FieldAlign = Align.getQuantity()*8; *XOffset = FieldOffset; - FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit, - VD->getName(), Unit, - 0, FieldSize, FieldAlign, - FieldOffset, 0, FieldTy); + FieldTy = DBuilder.CreateMemberType(VD->getName(), Unit, + 0, FieldSize, FieldAlign, + FieldOffset, 0, FieldTy); EltTys.push_back(FieldTy); FieldOffset += FieldSize; llvm::DIArray Elements = - DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); + DBuilder.GetOrCreateArray(EltTys.data(), EltTys.size()); - unsigned Flags = llvm::DIType::FlagBlockByrefStruct; - - return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_structure_type, - Unit, "", Unit, - 0, FieldOffset, 0, 0, Flags, - llvm::DIType(), Elements); + unsigned Flags = llvm::DIDescriptor::FlagBlockByrefStruct; + return DBuilder.CreateStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags, + Elements); } + /// EmitDeclare - Emit local variable declaration debug info. void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, llvm::Value *Storage, CGBuilderTy &Builder) { @@ -1721,37 +1758,119 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, if (!Ty) return; + if (llvm::Argument *Arg = dyn_cast<llvm::Argument>(Storage)) { + // If Storage is an aggregate returned as 'sret' then let debugger know + // about this. + if (Arg->hasStructRetAttr()) + Ty = DBuilder.CreateReferenceType(Ty); + else if (CXXRecordDecl *Record = VD->getType()->getAsCXXRecordDecl()) { + // If an aggregate variable has non trivial destructor or non trivial copy + // constructor than it is pass indirectly. Let debug info know about this + // by using reference of the aggregate type as a argument type. + if (!Record->hasTrivialCopyConstructor() || !Record->hasTrivialDestructor()) + Ty = DBuilder.CreateReferenceType(Ty); + } + } + // Get location information. unsigned Line = getLineNumber(VD->getLocation()); unsigned Column = getColumnNumber(VD->getLocation()); - - // Create the descriptor for the variable. - llvm::DIVariable D = - DebugFactory.CreateVariable(Tag, llvm::DIDescriptor(RegionStack.back()), - VD->getName(), - Unit, Line, Ty, CGM.getLangOptions().Optimize); - // Insert an llvm.dbg.declare into the current block. - llvm::Instruction *Call = - DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock()); - + unsigned Flags = 0; + if (VD->isImplicit()) + Flags |= llvm::DIDescriptor::FlagArtificial; llvm::MDNode *Scope = RegionStack.back(); - Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope)); + + llvm::StringRef Name = VD->getName(); + if (!Name.empty()) { + if (VD->hasAttr<BlocksAttr>()) { + CharUnits offset = CharUnits::fromQuantity(32); + llvm::SmallVector<llvm::Value *, 9> addr; + const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext()); + addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); + // offset of __forwarding field + offset = + CharUnits::fromQuantity(CGM.getContext().Target.getPointerWidth(0)/8); + addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity())); + addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref)); + addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); + // offset of x field + offset = CharUnits::fromQuantity(XOffset/8); + addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity())); + + // Create the descriptor for the variable. + llvm::DIVariable D = + DBuilder.CreateComplexVariable(Tag, + llvm::DIDescriptor(RegionStack.back()), + VD->getName(), Unit, Line, Ty, + addr.data(), addr.size()); + + // 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)); + return; + } + // Create the descriptor for the variable. + llvm::DIVariable D = + DBuilder.CreateLocalVariable(Tag, llvm::DIDescriptor(Scope), + Name, Unit, Line, Ty, + CGM.getLangOptions().Optimize, Flags); + + // 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)); + return; + } + + // If VD is an anonymous union then Storage represents value for + // all union fields. + if (const RecordType *RT = dyn_cast<RecordType>(VD->getType())) + if (const RecordDecl *RD = dyn_cast<RecordDecl>(RT->getDecl())) + if (RD->isUnion()) { + for (RecordDecl::field_iterator I = RD->field_begin(), + E = RD->field_end(); + I != E; ++I) { + FieldDecl *Field = *I; + llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit); + llvm::StringRef FieldName = Field->getName(); + + // Ignore unnamed fields. Do not ignore unnamed records. + if (FieldName.empty() && !isa<RecordType>(Field->getType())) + continue; + + // Use VarDecl's Tag, Scope and Line number. + llvm::DIVariable D = + DBuilder.CreateLocalVariable(Tag, llvm::DIDescriptor(Scope), + FieldName, Unit, Line, FieldTy, + CGM.getLangOptions().Optimize, Flags); + + // 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)); + } + } } /// EmitDeclare - Emit local variable declaration debug info. -void CGDebugInfo::EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag, +void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, llvm::Value *Storage, CGBuilderTy &Builder, - CodeGenFunction *CGF) { - const ValueDecl *VD = BDRE->getDecl(); + const CGBlockInfo &blockInfo) { assert(!RegionStack.empty() && "Region stack mismatch, stack empty!"); if (Builder.GetInsertBlock() == 0) return; + bool isByRef = VD->hasAttr<BlocksAttr>(); + uint64_t XOffset = 0; llvm::DIFile Unit = getOrCreateFile(VD->getLocation()); llvm::DIType Ty; - if (VD->hasAttr<BlocksAttr>()) + if (isByRef) Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset); else Ty = getOrCreateType(VD->getType(), Unit); @@ -1760,20 +1879,25 @@ void CGDebugInfo::EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag, unsigned Line = getLineNumber(VD->getLocation()); unsigned Column = getColumnNumber(VD->getLocation()); - CharUnits offset = CGF->BlockDecls[VD]; + const llvm::TargetData &target = CGM.getTargetData(); + + CharUnits offset = CharUnits::fromQuantity( + target.getStructLayout(blockInfo.StructureType) + ->getElementOffset(blockInfo.getCapture(VD).getIndex())); + llvm::SmallVector<llvm::Value *, 9> addr; const llvm::Type *Int64Ty = llvm::Type::getInt64Ty(CGM.getLLVMContext()); - addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIFactory::OpDeref)); - addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIFactory::OpPlus)); + addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref)); + addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity())); - if (BDRE->isByRef()) { - addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIFactory::OpDeref)); - addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIFactory::OpPlus)); + if (isByRef) { + addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref)); + addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); // offset of __forwarding field - offset = CharUnits::fromQuantity(CGF->LLVMPointerWidth/8); + offset = CharUnits::fromQuantity(target.getPointerSize()/8); addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity())); - addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIFactory::OpDeref)); - addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIFactory::OpPlus)); + addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref)); + addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); // offset of x field offset = CharUnits::fromQuantity(XOffset/8); addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity())); @@ -1781,13 +1905,12 @@ void CGDebugInfo::EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag, // Create the descriptor for the variable. llvm::DIVariable D = - DebugFactory.CreateComplexVariable(Tag, - llvm::DIDescriptor(RegionStack.back()), - VD->getName(), Unit, Line, Ty, - addr); + DBuilder.CreateComplexVariable(Tag, llvm::DIDescriptor(RegionStack.back()), + VD->getName(), Unit, Line, Ty, + addr.data(), addr.size()); // Insert an llvm.dbg.declare into the current block. llvm::Instruction *Call = - DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock()); + DBuilder.InsertDeclare(Storage, D, Builder.GetInsertBlock()); llvm::MDNode *Scope = RegionStack.back(); Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope)); @@ -1800,9 +1923,10 @@ void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, } void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable( - const BlockDeclRefExpr *BDRE, llvm::Value *Storage, CGBuilderTy &Builder, - CodeGenFunction *CGF) { - EmitDeclare(BDRE, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder, CGF); + const VarDecl *variable, llvm::Value *Storage, CGBuilderTy &Builder, + const CGBlockInfo &blockInfo) { + EmitDeclare(variable, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder, + blockInfo); } /// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument @@ -1836,14 +1960,16 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, } llvm::StringRef DeclName = D->getName(); llvm::StringRef LinkageName; - if (D->getDeclContext() && !isa<FunctionDecl>(D->getDeclContext())) + if (D->getDeclContext() && !isa<FunctionDecl>(D->getDeclContext()) + && !isa<ObjCMethodDecl>(D->getDeclContext())) LinkageName = Var->getName(); + if (LinkageName == DeclName) + LinkageName = llvm::StringRef(); llvm::DIDescriptor DContext = - getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()), Unit); - DebugFactory.CreateGlobalVariable(DContext, DeclName, DeclName, LinkageName, - Unit, LineNo, getOrCreateType(T, Unit), - Var->hasInternalLinkage(), - true/*definition*/, Var); + getContextDescriptor(dyn_cast<Decl>(D->getDeclContext())); + DBuilder.CreateStaticVariable(DContext, DeclName, LinkageName, + Unit, LineNo, getOrCreateType(T, Unit), + Var->hasInternalLinkage(), Var); } /// EmitGlobalVariable - Emit information about an objective-c interface. @@ -1868,49 +1994,45 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, ArrayType::Normal, 0); } - DebugFactory.CreateGlobalVariable(Unit, Name, Name, Name, Unit, LineNo, - getOrCreateType(T, Unit), - Var->hasInternalLinkage(), - true/*definition*/, Var); + DBuilder.CreateGlobalVariable(Name, Unit, LineNo, + getOrCreateType(T, Unit), + Var->hasInternalLinkage(), Var); } /// EmitGlobalVariable - Emit global variable's debug info. void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, - llvm::ConstantInt *Init, - CGBuilderTy &Builder) { + llvm::Constant *Init) { // Create the descriptor for the variable. llvm::DIFile Unit = getOrCreateFile(VD->getLocation()); llvm::StringRef Name = VD->getName(); llvm::DIType Ty = getOrCreateType(VD->getType(), Unit); if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(VD)) { if (const EnumDecl *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) - Ty = CreateEnumType(ED, Unit); + Ty = CreateEnumType(ED); } // Do not use DIGlobalVariable for enums. if (Ty.getTag() == llvm::dwarf::DW_TAG_enumeration_type) return; - DebugFactory.CreateGlobalVariable(Unit, Name, Name, Name, Unit, - getLineNumber(VD->getLocation()), - Ty, true, true, Init); + DBuilder.CreateStaticVariable(Unit, Name, Name, Unit, + getLineNumber(VD->getLocation()), + Ty, true, Init); } /// getOrCreateNamesSpace - Return namespace descriptor for the given /// namespace decl. llvm::DINameSpace -CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl, - llvm::DIDescriptor Unit) { +CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) { llvm::DenseMap<const NamespaceDecl *, llvm::WeakVH>::iterator I = NameSpaceCache.find(NSDecl); if (I != NameSpaceCache.end()) return llvm::DINameSpace(cast<llvm::MDNode>(I->second)); unsigned LineNo = getLineNumber(NSDecl->getLocation()); - + llvm::DIFile FileD = getOrCreateFile(NSDecl->getLocation()); llvm::DIDescriptor Context = - getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()), Unit); + getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext())); llvm::DINameSpace NS = - DebugFactory.CreateNameSpace(Context, NSDecl->getName(), - llvm::DIFile(Unit), LineNo); + DBuilder.CreateNameSpace(Context, NSDecl->getName(), FileD, LineNo); NameSpaceCache[NSDecl] = llvm::WeakVH(NS); return NS; } |