diff options
Diffstat (limited to 'lib/CodeGen/CGDebugInfo.cpp')
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 593 |
1 files changed, 404 insertions, 189 deletions
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 0607a5157a6f..12a68036b09c 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -13,9 +13,9 @@ #include "CGDebugInfo.h" #include "CGBlocks.h" -#include "CGRecordLayout.h" #include "CGCXXABI.h" #include "CGObjCRuntime.h" +#include "CGRecordLayout.h" #include "CodeGenFunction.h" #include "CodeGenModule.h" #include "clang/AST/ASTContext.h" @@ -31,6 +31,7 @@ #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/ModuleMap.h" #include "clang/Lex/PreprocessorOptions.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/Constants.h" @@ -40,10 +41,24 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MD5.h" #include "llvm/Support/Path.h" using namespace clang; using namespace clang::CodeGen; +static uint32_t getTypeAlignIfRequired(const Type *Ty, const ASTContext &Ctx) { + auto TI = Ctx.getTypeInfo(Ty); + return TI.AlignIsRequired ? TI.Align : 0; +} + +static uint32_t getTypeAlignIfRequired(QualType Ty, const ASTContext &Ctx) { + return getTypeAlignIfRequired(Ty.getTypePtr(), Ctx); +} + +static uint32_t getDeclAlignIfRequired(const Decl *D, const ASTContext &Ctx) { + return D->hasAttr<AlignedAttr>() ? D->getMaxAlignment() : 0; +} + CGDebugInfo::CGDebugInfo(CodeGenModule &CGM) : CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()), DebugTypeExtRefs(CGM.getCodeGenOpts().DebugTypeExtRefs), @@ -306,11 +321,36 @@ StringRef CGDebugInfo::getClassName(const RecordDecl *RD) { return StringRef(); } +llvm::DIFile::ChecksumKind +CGDebugInfo::computeChecksum(FileID FID, SmallString<32> &Checksum) const { + Checksum.clear(); + + if (!CGM.getCodeGenOpts().EmitCodeView) + return llvm::DIFile::CSK_None; + + SourceManager &SM = CGM.getContext().getSourceManager(); + bool Invalid; + llvm::MemoryBuffer *MemBuffer = SM.getBuffer(FID, &Invalid); + if (Invalid) + return llvm::DIFile::CSK_None; + + llvm::MD5 Hash; + llvm::MD5::MD5Result Result; + + Hash.update(MemBuffer->getBuffer()); + Hash.final(Result); + + Hash.stringifyResult(Result, Checksum); + return llvm::DIFile::CSK_MD5; +} + llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) { if (!Loc.isValid()) // If Location is not valid then use main input file. return DBuilder.createFile(remapDIPath(TheCU->getFilename()), - remapDIPath(TheCU->getDirectory())); + remapDIPath(TheCU->getDirectory()), + TheCU->getFile()->getChecksumKind(), + TheCU->getFile()->getChecksum()); SourceManager &SM = CGM.getContext().getSourceManager(); PresumedLoc PLoc = SM.getPresumedLoc(Loc); @@ -318,7 +358,9 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) { if (PLoc.isInvalid() || StringRef(PLoc.getFilename()).empty()) // If the location is not valid then use main input file. return DBuilder.createFile(remapDIPath(TheCU->getFilename()), - remapDIPath(TheCU->getDirectory())); + remapDIPath(TheCU->getDirectory()), + TheCU->getFile()->getChecksumKind(), + TheCU->getFile()->getChecksum()); // Cache the results. const char *fname = PLoc.getFilename(); @@ -330,8 +372,13 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) { return cast<llvm::DIFile>(V); } + SmallString<32> Checksum; + llvm::DIFile::ChecksumKind CSKind = + computeChecksum(SM.getFileID(Loc), Checksum); + llvm::DIFile *F = DBuilder.createFile(remapDIPath(PLoc.getFilename()), - remapDIPath(getCurrentDirname())); + remapDIPath(getCurrentDirname()), + CSKind, Checksum); DIFileCache[fname].reset(F); return F; @@ -339,7 +386,9 @@ llvm::DIFile *CGDebugInfo::getOrCreateFile(SourceLocation Loc) { llvm::DIFile *CGDebugInfo::getOrCreateMainFile() { return DBuilder.createFile(remapDIPath(TheCU->getFilename()), - remapDIPath(TheCU->getDirectory())); + remapDIPath(TheCU->getDirectory()), + TheCU->getFile()->getChecksumKind(), + TheCU->getFile()->getChecksum()); } std::string CGDebugInfo::remapDIPath(StringRef Path) const { @@ -382,6 +431,8 @@ StringRef CGDebugInfo::getCurrentDirname() { } void CGDebugInfo::CreateCompileUnit() { + SmallString<32> Checksum; + llvm::DIFile::ChecksumKind CSKind = llvm::DIFile::CSK_None; // Should we be asking the SourceManager for the main file name, instead of // accepting it as an argument? This just causes the main file name to @@ -408,6 +459,7 @@ void CGDebugInfo::CreateCompileUnit() { llvm::sys::path::append(MainFileDirSS, MainFileName); MainFileName = MainFileDirSS.str(); } + CSKind = computeChecksum(SM.getMainFileID(), Checksum); } llvm::dwarf::SourceLanguage LangTag; @@ -452,9 +504,12 @@ void CGDebugInfo::CreateCompileUnit() { // Create new compile unit. // FIXME - Eliminate TheCU. TheCU = DBuilder.createCompileUnit( - LangTag, remapDIPath(MainFileName), remapDIPath(getCurrentDirname()), + LangTag, DBuilder.createFile(remapDIPath(MainFileName), + remapDIPath(getCurrentDirname()), CSKind, + Checksum), Producer, LO.Optimize, CGM.getCodeGenOpts().DwarfDebugFlags, RuntimeVers, - CGM.getCodeGenOpts().SplitDwarfFile, EmissionKind, 0 /* DWOid */); + CGM.getCodeGenOpts().SplitDwarfFile, EmissionKind, 0 /* DWOid */, + CGM.getCodeGenOpts().SplitDwarfInlining); } llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) { @@ -494,14 +549,14 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) { auto *ISATy = DBuilder.createPointerType(ClassTy, Size); - ObjTy = - DBuilder.createStructType(TheCU, "objc_object", getOrCreateMainFile(), - 0, 0, 0, 0, nullptr, llvm::DINodeArray()); + ObjTy = DBuilder.createStructType( + TheCU, "objc_object", getOrCreateMainFile(), 0, 0, 0, + llvm::DINode::FlagZero, nullptr, llvm::DINodeArray()); DBuilder.replaceArrays( - ObjTy, - DBuilder.getOrCreateArray(&*DBuilder.createMemberType( - ObjTy, "isa", getOrCreateMainFile(), 0, Size, 0, 0, 0, ISATy))); + ObjTy, DBuilder.getOrCreateArray(&*DBuilder.createMemberType( + ObjTy, "isa", getOrCreateMainFile(), 0, Size, 0, 0, + llvm::DINode::FlagZero, ISATy))); return ObjTy; } case BuiltinType::ObjCSel: { @@ -518,9 +573,8 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) { SingletonId); #include "clang/Basic/OpenCLImageTypes.def" case BuiltinType::OCLSampler: - return DBuilder.createBasicType( - "opencl_sampler_t", CGM.getContext().getTypeSize(BT), - CGM.getContext().getTypeAlign(BT), llvm::dwarf::DW_ATE_unsigned); + return getOrCreateStructPtrType("opencl_sampler_t", + OCLSamplerDITy); case BuiltinType::OCLEvent: return getOrCreateStructPtrType("opencl_event_t", OCLEventDITy); case BuiltinType::OCLClkEvent: @@ -594,21 +648,19 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) { BTName = BT->getName(CGM.getLangOpts()); break; } - // Bit size, align and offset of the type. + // Bit size and offset of the type. uint64_t Size = CGM.getContext().getTypeSize(BT); - uint64_t Align = CGM.getContext().getTypeAlign(BT); - return DBuilder.createBasicType(BTName, Size, Align, Encoding); + return DBuilder.createBasicType(BTName, Size, Encoding); } llvm::DIType *CGDebugInfo::CreateType(const ComplexType *Ty) { - // Bit size, align and offset of the type. + // Bit size and offset of the type. llvm::dwarf::TypeKind Encoding = llvm::dwarf::DW_ATE_complex_float; if (Ty->isComplexIntegerType()) Encoding = llvm::dwarf::DW_ATE_lo_user; uint64_t Size = CGM.getContext().getTypeSize(Ty); - uint64_t Align = CGM.getContext().getTypeAlign(Ty); - return DBuilder.createBasicType("complex", Size, Align, Encoding); + return DBuilder.createBasicType("complex", Size, Encoding); } llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty, @@ -721,13 +773,7 @@ CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty, StringRef RDName = getClassName(RD); uint64_t Size = 0; - uint64_t Align = 0; - - const RecordDecl *D = RD->getDefinition(); - if (D && D->isCompleteDefinition()) { - Size = CGM.getContext().getTypeSize(Ty); - Align = CGM.getContext().getTypeAlign(Ty); - } + uint32_t Align = 0; // Create the type. SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU); @@ -749,7 +795,7 @@ llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag, // because that does not return the correct value for references. unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy); uint64_t Size = CGM.getTarget().getPointerWidth(AS); - uint64_t Align = CGM.getContext().getTypeAlign(Ty); + auto Align = getTypeAlignIfRequired(Ty, CGM.getContext()); if (Tag == llvm::dwarf::DW_TAG_reference_type || Tag == llvm::dwarf::DW_TAG_rvalue_reference_type) @@ -776,7 +822,7 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty, SmallVector<llvm::Metadata *, 8> EltTys; QualType FType; uint64_t FieldSize, FieldOffset; - unsigned FieldAlign; + uint32_t FieldAlign; llvm::DINodeArray Elements; FieldOffset = 0; @@ -787,7 +833,7 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty, Elements = DBuilder.getOrCreateArray(EltTys); EltTys.clear(); - unsigned Flags = llvm::DINode::FlagAppleBlock; + llvm::DINode::DIFlags Flags = llvm::DINode::FlagAppleBlock; unsigned LineNo = 0; auto *EltTy = @@ -811,9 +857,9 @@ llvm::DIType *CGDebugInfo::CreateType(const BlockPointerType *Ty, FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy); FieldSize = CGM.getContext().getTypeSize(Ty); FieldAlign = CGM.getContext().getTypeAlign(Ty); - EltTys.push_back(DBuilder.createMemberType(Unit, "__descriptor", nullptr, LineNo, - FieldSize, FieldAlign, FieldOffset, - 0, DescTy)); + EltTys.push_back(DBuilder.createMemberType( + Unit, "__descriptor", nullptr, LineNo, FieldSize, FieldAlign, FieldOffset, + llvm::DINode::FlagZero, DescTy)); FieldOffset += FieldSize; Elements = DBuilder.getOrCreateArray(EltTys); @@ -893,6 +939,7 @@ static unsigned getDwarfCC(CallingConv CC) { case CC_Swift: case CC_PreserveMost: case CC_PreserveAll: + case CC_X86RegCall: return 0; } return 0; @@ -917,14 +964,15 @@ llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty, } llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys); - return DBuilder.createSubroutineType(EltTypeArray, 0, + return DBuilder.createSubroutineType(EltTypeArray, llvm::DINode::FlagZero, getDwarfCC(Ty->getCallConv())); } /// Convert an AccessSpecifier into the corresponding DINode flag. /// As an optimization, return 0 if the access specifier equals the /// default for the containing type. -static unsigned getAccessFlag(AccessSpecifier Access, const RecordDecl *RD) { +static llvm::DINode::DIFlags getAccessFlag(AccessSpecifier Access, + const RecordDecl *RD) { AccessSpecifier Default = clang::AS_none; if (RD && RD->isClass()) Default = clang::AS_private; @@ -932,7 +980,7 @@ static unsigned getAccessFlag(AccessSpecifier Access, const RecordDecl *RD) { Default = clang::AS_public; if (Access == Default) - return 0; + return llvm::DINode::FlagZero; switch (Access) { case clang::AS_private: @@ -942,7 +990,7 @@ static unsigned getAccessFlag(AccessSpecifier Access, const RecordDecl *RD) { case clang::AS_public: return llvm::DINode::FlagPublic; case clang::AS_none: - return 0; + return llvm::DINode::FlagZero; } llvm_unreachable("unexpected access enumerator"); } @@ -964,21 +1012,20 @@ llvm::DIType *CGDebugInfo::createBitFieldType(const FieldDecl *BitFieldDecl, CGM.getTypes().getCGRecordLayout(RD).getBitFieldInfo(BitFieldDecl); uint64_t SizeInBits = BitFieldInfo.Size; assert(SizeInBits > 0 && "found named 0-width bitfield"); - unsigned AlignInBits = CGM.getContext().getTypeAlign(Ty); uint64_t StorageOffsetInBits = CGM.getContext().toBits(BitFieldInfo.StorageOffset); uint64_t OffsetInBits = StorageOffsetInBits + BitFieldInfo.Offset; - unsigned Flags = getAccessFlag(BitFieldDecl->getAccess(), RD); + llvm::DINode::DIFlags Flags = getAccessFlag(BitFieldDecl->getAccess(), RD); return DBuilder.createBitFieldMemberType( - RecordTy, Name, File, Line, SizeInBits, AlignInBits, OffsetInBits, - StorageOffsetInBits, Flags, DebugType); + RecordTy, Name, File, Line, SizeInBits, OffsetInBits, StorageOffsetInBits, + Flags, DebugType); } llvm::DIType * CGDebugInfo::createFieldType(StringRef name, QualType type, SourceLocation loc, AccessSpecifier AS, uint64_t offsetInBits, - llvm::DIFile *tunit, llvm::DIScope *scope, - const RecordDecl *RD) { + uint32_t AlignInBits, llvm::DIFile *tunit, + llvm::DIScope *scope, const RecordDecl *RD) { llvm::DIType *debugType = getOrCreateType(type, tunit); // Get the location for the field. @@ -986,16 +1033,17 @@ CGDebugInfo::createFieldType(StringRef name, QualType type, SourceLocation loc, unsigned line = getLineNumber(loc); uint64_t SizeInBits = 0; - unsigned AlignInBits = 0; + auto Align = AlignInBits; if (!type->isIncompleteArrayType()) { TypeInfo TI = CGM.getContext().getTypeInfo(type); SizeInBits = TI.Width; - AlignInBits = TI.Align; + if (!Align) + Align = getTypeAlignIfRequired(type, CGM.getContext()); } - unsigned flags = getAccessFlag(AS, RD); + llvm::DINode::DIFlags flags = getAccessFlag(AS, RD); return DBuilder.createMemberType(scope, name, file, line, SizeInBits, - AlignInBits, offsetInBits, flags, debugType); + Align, offsetInBits, flags, debugType); } void CGDebugInfo::CollectRecordLambdaFields( @@ -1017,9 +1065,10 @@ void CGDebugInfo::CollectRecordLambdaFields( VarDecl *V = C.getCapturedVar(); StringRef VName = V->getName(); llvm::DIFile *VUnit = getOrCreateFile(Loc); + auto Align = getDeclAlignIfRequired(V, CGM.getContext()); llvm::DIType *FieldType = createFieldType( VName, Field->getType(), Loc, Field->getAccess(), - layout.getFieldOffset(fieldno), VUnit, RecordTy, CXXDecl); + layout.getFieldOffset(fieldno), Align, VUnit, RecordTy, CXXDecl); elements.push_back(FieldType); } else if (C.capturesThis()) { // TODO: Need to handle 'this' in some way by probably renaming the @@ -1060,9 +1109,10 @@ CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy, } } - unsigned Flags = getAccessFlag(Var->getAccess(), RD); + llvm::DINode::DIFlags Flags = getAccessFlag(Var->getAccess(), RD); + auto Align = getDeclAlignIfRequired(Var, CGM.getContext()); llvm::DIDerivedType *GV = DBuilder.createStaticMemberType( - RecordTy, VName, VUnit, LineNumber, VTy, Flags, C); + RecordTy, VName, VUnit, LineNumber, VTy, Flags, C, Align); StaticDataMemberCache[Var->getCanonicalDecl()].reset(GV); return GV; } @@ -1082,14 +1132,26 @@ void CGDebugInfo::CollectRecordNormalField( if (field->isBitField()) { FieldType = createBitFieldType(field, RecordTy, RD); } else { + auto Align = getDeclAlignIfRequired(field, CGM.getContext()); FieldType = createFieldType(name, type, field->getLocation(), field->getAccess(), - OffsetInBits, tunit, RecordTy, RD); + OffsetInBits, Align, tunit, RecordTy, RD); } elements.push_back(FieldType); } +void CGDebugInfo::CollectRecordNestedRecord( + const RecordDecl *RD, SmallVectorImpl<llvm::Metadata *> &elements) { + QualType Ty = CGM.getContext().getTypeDeclType(RD); + // Injected class names are not considered nested records. + if (isa<InjectedClassNameType>(Ty)) + return; + SourceLocation Loc = RD->getLocation(); + llvm::DIType *nestedType = getOrCreateType(Ty, getOrCreateFile(Loc)); + elements.push_back(nestedType); +} + void CGDebugInfo::CollectRecordFields( const RecordDecl *record, llvm::DIFile *tunit, SmallVectorImpl<llvm::Metadata *> &elements, @@ -1101,6 +1163,10 @@ void CGDebugInfo::CollectRecordFields( else { const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record); + // Debug info for nested records is included in the member list only for + // CodeView. + bool IncludeNestedRecords = CGM.getCodeGenOpts().EmitCodeView; + // Field number for non-static fields. unsigned fieldNo = 0; @@ -1126,7 +1192,10 @@ void CGDebugInfo::CollectRecordFields( // Bump field number for next field. ++fieldNo; - } + } else if (const auto *nestedRec = dyn_cast<CXXRecordDecl>(I)) + if (IncludeNestedRecords && !nestedRec->isImplicit() && + nestedRec->getDeclContext() == record) + CollectRecordNestedRecord(nestedRec, elements); } } @@ -1162,7 +1231,7 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateInstanceMethodType( QualType PointeeTy = ThisPtrTy->getPointeeType(); unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy); uint64_t Size = CGM.getTarget().getPointerWidth(AS); - uint64_t Align = CGM.getContext().getTypeAlign(ThisPtrTy); + auto Align = getTypeAlignIfRequired(ThisPtrTy, CGM.getContext()); llvm::DIType *PointeeType = getOrCreateType(PointeeTy, Unit); llvm::DIType *ThisPtrType = DBuilder.createPointerType(PointeeType, Size, Align); @@ -1185,7 +1254,7 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateInstanceMethodType( llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); - unsigned Flags = 0; + llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; if (Func->getExtProtoInfo().RefQualifier == RQ_LValue) Flags |= llvm::DINode::FlagLValueReference; if (Func->getExtProtoInfo().RefQualifier == RQ_RValue) @@ -1236,7 +1305,7 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction( llvm::DIType *ContainingType = nullptr; unsigned Virtuality = 0; unsigned VIndex = 0; - unsigned Flags = 0; + llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; int ThisAdjustment = 0; if (Method->isVirtual()) { @@ -1347,13 +1416,33 @@ void CGDebugInfo::CollectCXXMemberFunctions( void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile *Unit, SmallVectorImpl<llvm::Metadata *> &EltTys, llvm::DIType *RecordTy) { - const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); - for (const auto &BI : RD->bases()) { - unsigned BFlags = 0; - uint64_t BaseOffset; + llvm::DenseSet<CanonicalDeclPtr<const CXXRecordDecl>> SeenTypes; + CollectCXXBasesAux(RD, Unit, EltTys, RecordTy, RD->bases(), SeenTypes, + llvm::DINode::FlagZero); + + // If we are generating CodeView debug info, we also need to emit records for + // indirect virtual base classes. + if (CGM.getCodeGenOpts().EmitCodeView) { + CollectCXXBasesAux(RD, Unit, EltTys, RecordTy, RD->vbases(), SeenTypes, + llvm::DINode::FlagIndirectVirtualBase); + } +} +void CGDebugInfo::CollectCXXBasesAux( + const CXXRecordDecl *RD, llvm::DIFile *Unit, + SmallVectorImpl<llvm::Metadata *> &EltTys, llvm::DIType *RecordTy, + const CXXRecordDecl::base_class_const_range &Bases, + llvm::DenseSet<CanonicalDeclPtr<const CXXRecordDecl>> &SeenTypes, + llvm::DINode::DIFlags StartingFlags) { + const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); + for (const auto &BI : Bases) { const auto *Base = cast<CXXRecordDecl>(BI.getType()->getAs<RecordType>()->getDecl()); + if (!SeenTypes.insert(Base).second) + continue; + auto *BaseTy = getOrCreateType(BI.getType(), Unit); + llvm::DINode::DIFlags BFlags = StartingFlags; + uint64_t BaseOffset; if (BI.isVirtual()) { if (CGM.getTarget().getCXXABI().isItaniumFamily()) { @@ -1368,15 +1457,15 @@ void CGDebugInfo::CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile *Unit, BaseOffset = 4 * CGM.getMicrosoftVTableContext().getVBTableIndex(RD, Base); } - BFlags = llvm::DINode::FlagVirtual; + BFlags |= llvm::DINode::FlagVirtual; } else BaseOffset = CGM.getContext().toBits(RL.getBaseClassOffset(Base)); // FIXME: Inconsistent units for BaseOffset. It is in bytes when // BI->isVirtual() and bits when not. BFlags |= getAccessFlag(BI.getAccessSpecifier(), RD); - llvm::DIType *DTy = DBuilder.createInheritance( - RecordTy, getOrCreateType(BI.getType(), Unit), BaseOffset, BFlags); + llvm::DIType *DTy = + DBuilder.createInheritance(RecordTy, BaseTy, BaseOffset, BFlags); EltTys.push_back(DTy); } } @@ -1531,22 +1620,56 @@ StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) { } void CGDebugInfo::CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile *Unit, - SmallVectorImpl<llvm::Metadata *> &EltTys) { + SmallVectorImpl<llvm::Metadata *> &EltTys, + llvm::DICompositeType *RecordTy) { + // If this class is not dynamic then there is not any vtable info to collect. + if (!RD->isDynamicClass()) + return; + + // Don't emit any vtable shape or vptr info if this class doesn't have an + // extendable vfptr. This can happen if the class doesn't have virtual + // methods, or in the MS ABI if those virtual methods only come from virtually + // inherited bases. const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); + if (!RL.hasExtendableVFPtr()) + return; - // If there is a primary base then it will hold vtable info. + // CodeView needs to know how large the vtable of every dynamic class is, so + // emit a special named pointer type into the element list. The vptr type + // points to this type as well. + llvm::DIType *VPtrTy = nullptr; + bool NeedVTableShape = CGM.getCodeGenOpts().EmitCodeView && + CGM.getTarget().getCXXABI().isMicrosoft(); + if (NeedVTableShape) { + uint64_t PtrWidth = + CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); + const VTableLayout &VFTLayout = + CGM.getMicrosoftVTableContext().getVFTableLayout(RD, CharUnits::Zero()); + unsigned VSlotCount = + VFTLayout.vtable_components().size() - CGM.getLangOpts().RTTIData; + unsigned VTableWidth = PtrWidth * VSlotCount; + + // Create a very wide void* type and insert it directly in the element list. + llvm::DIType *VTableType = + DBuilder.createPointerType(nullptr, VTableWidth, 0, "__vtbl_ptr_type"); + EltTys.push_back(VTableType); + + // The vptr is a pointer to this special vtable type. + VPtrTy = DBuilder.createPointerType(VTableType, PtrWidth); + } + + // If there is a primary base then the artificial vptr member lives there. if (RL.getPrimaryBase()) return; - // If this class is not dynamic then there is not any vtable info to collect. - if (!RD->isDynamicClass()) - return; + if (!VPtrTy) + VPtrTy = getOrCreateVTablePtrType(Unit); unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy); - llvm::DIType *VPTR = DBuilder.createMemberType( + llvm::DIType *VPtrMember = DBuilder.createMemberType( Unit, getVTableName(RD), Unit, 0, Size, 0, 0, - llvm::DINode::FlagArtificial, getOrCreateVTablePtrType(Unit)); - EltTys.push_back(VPTR); + llvm::DINode::FlagArtificial, VPtrTy); + EltTys.push_back(VPtrMember); } llvm::DIType *CGDebugInfo::getOrCreateRecordType(QualType RTy, @@ -1591,23 +1714,6 @@ void CGDebugInfo::completeType(const RecordDecl *RD) { completeRequiredType(RD); } -void CGDebugInfo::completeRequiredType(const RecordDecl *RD) { - if (DebugKind <= codegenoptions::DebugLineTablesOnly) - return; - - if (const auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD)) - if (CXXDecl->isDynamicClass()) - return; - - if (DebugTypeExtRefs && RD->isFromASTFile()) - return; - - QualType Ty = CGM.getContext().getRecordType(RD); - llvm::DIType *T = getTypeOrNull(Ty); - if (T && T->isForwardDecl()) - completeClassData(RD); -} - void CGDebugInfo::completeClassData(const RecordDecl *RD) { if (DebugKind <= codegenoptions::DebugLineTablesOnly) return; @@ -1633,21 +1739,37 @@ static bool hasExplicitMemberDefinition(CXXRecordDecl::method_iterator I, /// Does a type definition exist in an imported clang module? static bool isDefinedInClangModule(const RecordDecl *RD) { + // Only definitions that where imported from an AST file come from a module. if (!RD || !RD->isFromASTFile()) return false; + // Anonymous entities cannot be addressed. Treat them as not from module. if (!RD->isExternallyVisible() && RD->getName().empty()) return false; if (auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD)) { - assert(CXXDecl->isCompleteDefinition() && "incomplete record definition"); - if (CXXDecl->getTemplateSpecializationKind() != TSK_Undeclared) - // Make sure the instantiation is actually in a module. - if (CXXDecl->field_begin() != CXXDecl->field_end()) - return CXXDecl->field_begin()->isFromASTFile(); + if (!CXXDecl->isCompleteDefinition()) + return false; + auto TemplateKind = CXXDecl->getTemplateSpecializationKind(); + if (TemplateKind != TSK_Undeclared) { + // This is a template, check the origin of the first member. + if (CXXDecl->field_begin() == CXXDecl->field_end()) + return TemplateKind == TSK_ExplicitInstantiationDeclaration; + if (!CXXDecl->field_begin()->isFromASTFile()) + return false; + } } - return true; } +/// Return true if the class or any of its methods are marked dllimport. +static bool isClassOrMethodDLLImport(const CXXRecordDecl *RD) { + if (RD->hasAttr<DLLImportAttr>()) + return true; + for (const CXXMethodDecl *MD : RD->methods()) + if (MD->hasAttr<DLLImportAttr>()) + return true; + return false; +} + static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind, bool DebugTypeExtRefs, const RecordDecl *RD, const LangOptions &LangOpts) { @@ -1668,7 +1790,14 @@ static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind, if (!CXXDecl) return false; - if (CXXDecl->hasDefinition() && CXXDecl->isDynamicClass()) + // Only emit complete debug info for a dynamic class when its vtable is + // emitted. However, Microsoft debuggers don't resolve type information + // across DLL boundaries, so skip this optimization if the class or any of its + // methods are marked dllimport. This isn't a complete solution, since objects + // without any dllimport methods can be used in one DLL and constructed in + // another, but it is the current behavior of LimitedDebugInfo. + if (CXXDecl->hasDefinition() && CXXDecl->isDynamicClass() && + !isClassOrMethodDLLImport(CXXDecl)) return true; TemplateSpecializationKind Spec = TSK_Undeclared; @@ -1683,6 +1812,16 @@ static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind, return false; } +void CGDebugInfo::completeRequiredType(const RecordDecl *RD) { + if (shouldOmitDefinition(DebugKind, DebugTypeExtRefs, RD, CGM.getLangOpts())) + return; + + QualType Ty = CGM.getContext().getRecordType(RD); + llvm::DIType *T = getTypeOrNull(Ty); + if (T && T->isForwardDecl()) + completeClassData(RD); +} + llvm::DIType *CGDebugInfo::CreateType(const RecordType *Ty) { RecordDecl *RD = Ty->getDecl(); llvm::DIType *T = cast_or_null<llvm::DIType>(getTypeOrNull(QualType(Ty, 0))); @@ -1732,7 +1871,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { const auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD); if (CXXDecl) { CollectCXXBases(CXXDecl, DefUnit, EltTys, FwdDecl); - CollectVTableInfo(CXXDecl, DefUnit, EltTys); + CollectVTableInfo(CXXDecl, DefUnit, EltTys, FwdDecl); } // Collect data fields (including static variables and any initializers). @@ -1760,6 +1899,18 @@ llvm::DIType *CGDebugInfo::CreateType(const ObjCObjectType *Ty, return getOrCreateType(Ty->getBaseType(), Unit); } +llvm::DIType *CGDebugInfo::CreateType(const ObjCTypeParamType *Ty, + llvm::DIFile *Unit) { + // Ignore protocols. + SourceLocation Loc = Ty->getDecl()->getLocation(); + + // Use Typedefs to represent ObjCTypeParamType. + return DBuilder.createTypedef( + getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit), + Ty->getDecl()->getName(), getOrCreateFile(Loc), getLineNumber(Loc), + getDeclContextDescriptor(Ty->getDecl())); +} + /// \return true if Getter has the default name for the property PD. static bool hasDefaultGetterName(const ObjCPropertyDecl *PD, const ObjCMethodDecl *Getter) { @@ -1860,10 +2011,11 @@ CGDebugInfo::getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod, // but LLVM detects skeleton CUs by looking for a non-zero DWO id. uint64_t Signature = Mod.getSignature() ? Mod.getSignature() : ~1ULL; llvm::DIBuilder DIB(CGM.getModule()); - DIB.createCompileUnit(TheCU->getSourceLanguage(), Mod.getModuleName(), - Mod.getPath(), TheCU->getProducer(), true, - StringRef(), 0, Mod.getASTFile(), - llvm::DICompileUnit::FullDebug, Signature); + DIB.createCompileUnit(TheCU->getSourceLanguage(), + DIB.createFile(Mod.getModuleName(), Mod.getPath()), + TheCU->getProducer(), true, StringRef(), 0, + Mod.getASTFile(), llvm::DICompileUnit::FullDebug, + Signature); DIB.finalize(); } llvm::DIModule *Parent = @@ -1887,9 +2039,9 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty, // Bit size, align and offset of the type. uint64_t Size = CGM.getContext().getTypeSize(Ty); - uint64_t Align = CGM.getContext().getTypeAlign(Ty); + auto Align = getTypeAlignIfRequired(Ty, CGM.getContext()); - unsigned Flags = 0; + llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; if (ID->getImplementation()) Flags |= llvm::DINode::FlagObjcClassComplete; @@ -1915,7 +2067,8 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty, if (!SClassTy) return nullptr; - llvm::DIType *InhTag = DBuilder.createInheritance(RealDecl, SClassTy, 0, 0); + llvm::DIType *InhTag = DBuilder.createInheritance(RealDecl, SClassTy, 0, + llvm::DINode::FlagZero); EltTys.push_back(InhTag); } @@ -1970,7 +2123,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty, unsigned FieldLine = getLineNumber(Field->getLocation()); QualType FType = Field->getType(); uint64_t FieldSize = 0; - unsigned FieldAlign = 0; + uint32_t FieldAlign = 0; if (!FType->isIncompleteArrayType()) { @@ -1978,7 +2131,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty, FieldSize = Field->isBitField() ? Field->getBitWidthValue(CGM.getContext()) : CGM.getContext().getTypeSize(FType); - FieldAlign = CGM.getContext().getTypeAlign(FType); + FieldAlign = getTypeAlignIfRequired(FType, CGM.getContext()); } uint64_t FieldOffset; @@ -1997,7 +2150,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const ObjCInterfaceType *Ty, FieldOffset = RL.getFieldOffset(FieldNo); } - unsigned Flags = 0; + llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; if (Field->getAccessControl() == ObjCIvarDecl::Protected) Flags = llvm::DINode::FlagProtected; else if (Field->getAccessControl() == ObjCIvarDecl::Private) @@ -2052,33 +2205,33 @@ llvm::DIType *CGDebugInfo::CreateType(const VectorType *Ty, llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscript); uint64_t Size = CGM.getContext().getTypeSize(Ty); - uint64_t Align = CGM.getContext().getTypeAlign(Ty); + auto Align = getTypeAlignIfRequired(Ty, CGM.getContext()); return DBuilder.createVectorType(Size, Align, ElementTy, SubscriptArray); } llvm::DIType *CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile *Unit) { uint64_t Size; - uint64_t Align; + uint32_t Align; // FIXME: make getTypeAlign() aware of VLAs and incomplete array types if (const auto *VAT = dyn_cast<VariableArrayType>(Ty)) { Size = 0; - Align = - CGM.getContext().getTypeAlign(CGM.getContext().getBaseElementType(VAT)); + Align = getTypeAlignIfRequired(CGM.getContext().getBaseElementType(VAT), + CGM.getContext()); } else if (Ty->isIncompleteArrayType()) { Size = 0; if (Ty->getElementType()->isIncompleteType()) Align = 0; else - Align = CGM.getContext().getTypeAlign(Ty->getElementType()); + Align = getTypeAlignIfRequired(Ty->getElementType(), CGM.getContext()); } else if (Ty->isIncompleteType()) { Size = 0; Align = 0; } else { // Size and align of the whole array, not the element type. Size = CGM.getContext().getTypeSize(Ty); - Align = CGM.getContext().getTypeAlign(Ty); + Align = getTypeAlignIfRequired(Ty, CGM.getContext()); } // Add the dimensions of the array. FIXME: This loses CV qualifiers from @@ -2097,6 +2250,13 @@ llvm::DIType *CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile *Unit) { int64_t Count = -1; // Count == -1 is an unbounded array. if (const auto *CAT = dyn_cast<ConstantArrayType>(Ty)) Count = CAT->getSize().getZExtValue(); + else if (const auto *VAT = dyn_cast<VariableArrayType>(Ty)) { + if (Expr *Size = VAT->getSizeExpr()) { + llvm::APSInt V; + if (Size->EvaluateAsInt(V, CGM.getContext())) + Count = V.getExtValue(); + } + } // FIXME: Verify this is right for VLAs. Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count)); @@ -2123,7 +2283,7 @@ llvm::DIType *CGDebugInfo::CreateType(const RValueReferenceType *Ty, llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty, llvm::DIFile *U) { - unsigned Flags = 0; + llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; uint64_t Size = 0; if (!Ty->isIncompleteType()) { @@ -2163,9 +2323,8 @@ llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty, } llvm::DIType *CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile *U) { - // Ignore the atomic wrapping - // FIXME: What is the correct representation? - return getOrCreateType(Ty->getValueType(), U); + auto *FromTy = getOrCreateType(Ty->getValueType(), U); + return DBuilder.createQualifiedType(llvm::dwarf::DW_TAG_atomic_type, FromTy); } llvm::DIType* CGDebugInfo::CreateType(const PipeType *Ty, @@ -2177,10 +2336,10 @@ llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) { const EnumDecl *ED = Ty->getDecl(); uint64_t Size = 0; - uint64_t Align = 0; + uint32_t Align = 0; if (!ED->getTypeForDecl()->isIncompleteType()) { Size = CGM.getContext().getTypeSize(ED->getTypeForDecl()); - Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl()); + Align = getDeclAlignIfRequired(ED, CGM.getContext()); } SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU); @@ -2220,10 +2379,10 @@ llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) { llvm::DIType *CGDebugInfo::CreateTypeDefinition(const EnumType *Ty) { const EnumDecl *ED = Ty->getDecl(); uint64_t Size = 0; - uint64_t Align = 0; + uint32_t Align = 0; if (!ED->getTypeForDecl()->isIncompleteType()) { Size = CGM.getContext().getTypeSize(ED->getTypeForDecl()); - Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl()); + Align = getDeclAlignIfRequired(ED, CGM.getContext()); } SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU); @@ -2292,12 +2451,18 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) { case Type::SubstTemplateTypeParm: T = cast<SubstTemplateTypeParmType>(T)->getReplacementType(); break; - case Type::Auto: + case Type::Auto: { QualType DT = cast<AutoType>(T)->getDeducedType(); assert(!DT.isNull() && "Undeduced types shouldn't reach here."); T = DT; break; } + case Type::Adjusted: + case Type::Decayed: + // Decayed and adjusted types use the adjusted type in LLVM and DWARF. + T = cast<AdjustedType>(T)->getAdjustedType(); + break; + } assert(T != LastT && "Type unwrapping failed to unwrap!"); (void)LastT; @@ -2406,6 +2571,8 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { return CreateType(cast<ObjCObjectPointerType>(Ty), Unit); case Type::ObjCObject: return CreateType(cast<ObjCObjectType>(Ty), Unit); + case Type::ObjCTypeParam: + return CreateType(cast<ObjCTypeParamType>(Ty), Unit); case Type::ObjCInterface: return CreateType(cast<ObjCInterfaceType>(Ty), Unit); case Type::Builtin: @@ -2414,11 +2581,6 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { return CreateType(cast<ComplexType>(Ty)); case Type::Pointer: return CreateType(cast<PointerType>(Ty), Unit); - case Type::Adjusted: - case Type::Decayed: - // Decayed and adjusted types use the adjusted type in LLVM and DWARF. - return CreateType( - cast<PointerType>(cast<AdjustedType>(Ty)->getAdjustedType()), Unit); case Type::BlockPointer: return CreateType(cast<BlockPointerType>(Ty), Unit); case Type::Typedef: @@ -2454,6 +2616,8 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { case Type::Auto: case Type::Attributed: + case Type::Adjusted: + case Type::Decayed: case Type::Elaborated: case Type::Paren: case Type::SubstTemplateTypeParm: @@ -2518,13 +2682,13 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { return getOrCreateRecordFwdDecl(Ty, RDContext); uint64_t Size = CGM.getContext().getTypeSize(Ty); - uint64_t Align = CGM.getContext().getTypeAlign(Ty); + auto Align = getDeclAlignIfRequired(D, CGM.getContext()); SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU); llvm::DICompositeType *RealDecl = DBuilder.createReplaceableCompositeType( - getTagForRecord(RD), RDName, RDContext, DefUnit, Line, 0, Size, Align, 0, - FullName); + getTagForRecord(RD), RDName, RDContext, DefUnit, Line, 0, Size, Align, + llvm::DINode::FlagZero, FullName); // Elements of composite types usually have back to the type, creating // uniquing cycles. Distinct nodes are more efficient. @@ -2587,9 +2751,10 @@ llvm::DIType *CGDebugInfo::CreateMemberType(llvm::DIFile *Unit, QualType FType, StringRef Name, uint64_t *Offset) { llvm::DIType *FieldTy = CGDebugInfo::getOrCreateType(FType, Unit); uint64_t FieldSize = CGM.getContext().getTypeSize(FType); - unsigned FieldAlign = CGM.getContext().getTypeAlign(FType); - llvm::DIType *Ty = DBuilder.createMemberType(Unit, Name, Unit, 0, FieldSize, - FieldAlign, *Offset, 0, FieldTy); + auto FieldAlign = getTypeAlignIfRequired(FType, CGM.getContext()); + llvm::DIType *Ty = + DBuilder.createMemberType(Unit, Name, Unit, 0, FieldSize, FieldAlign, + *Offset, llvm::DINode::FlagZero, FieldTy); *Offset += FieldSize; return Ty; } @@ -2599,7 +2764,7 @@ void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit, StringRef &LinkageName, llvm::DIScope *&FDContext, llvm::DINodeArray &TParamsArray, - unsigned &Flags) { + llvm::DINode::DIFlags &Flags) { const auto *FD = cast<FunctionDecl>(GD.getDecl()); Name = getFunctionName(FD); // Use mangled name as linkage name for C/C++ functions. @@ -2624,6 +2789,9 @@ void CGDebugInfo::collectFunctionDeclProps(GlobalDecl GD, llvm::DIFile *Unit, llvm::DIScope *Mod = getParentModuleOrNull(RDecl); FDContext = getContextDescriptor(RDecl, Mod ? Mod : TheCU); } + // Check if it is a noreturn-marked function + if (FD->isNoReturn()) + Flags |= llvm::DINode::FlagNoReturn; // Collect template parameters. TParamsArray = CollectFunctionTemplateParams(FD, Unit); } @@ -2680,7 +2848,7 @@ llvm::DISubprogram * CGDebugInfo::getFunctionForwardDeclaration(const FunctionDecl *FD) { llvm::DINodeArray TParamsArray; StringRef Name, LinkageName; - unsigned Flags = 0; + llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; SourceLocation Loc = FD->getLocation(); llvm::DIFile *Unit = getOrCreateFile(Loc); llvm::DIScope *DContext = Unit; @@ -2717,9 +2885,10 @@ CGDebugInfo::getGlobalVariableForwardDeclaration(const VarDecl *VD) { unsigned Line = getLineNumber(Loc); collectVarDeclProps(VD, Unit, Line, T, Name, LinkageName, DContext); + auto Align = getDeclAlignIfRequired(VD, CGM.getContext()); auto *GV = DBuilder.createTempGlobalVariableFwdDecl( DContext, Name, LinkageName, Unit, Line, getOrCreateType(T, Unit), - !VD->isExternallyVisible(), nullptr, nullptr); + !VD->isExternallyVisible(), nullptr, Align); FwdDeclReplaceMap.emplace_back( std::piecewise_construct, std::make_tuple(cast<VarDecl>(VD->getCanonicalDecl())), @@ -2737,8 +2906,12 @@ llvm::DINode *CGDebugInfo::getDeclarationOrDefinition(const Decl *D) { getOrCreateFile(TD->getLocation())); auto I = DeclCache.find(D->getCanonicalDecl()); - if (I != DeclCache.end()) - return dyn_cast_or_null<llvm::DINode>(I->second); + if (I != DeclCache.end()) { + auto N = I->second; + if (auto *GVE = dyn_cast_or_null<llvm::DIGlobalVariableExpression>(N)) + return GVE->getVariable(); + return dyn_cast_or_null<llvm::DINode>(N); + } // No definition for now. Emit a forward definition that might be // merged with a potential upcoming definition. @@ -2834,7 +3007,8 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D, Elts.push_back(DBuilder.createUnspecifiedParameter()); llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); - return DBuilder.createSubroutineType(EltTypeArray, 0, getDwarfCC(CC)); + return DBuilder.createSubroutineType(EltTypeArray, llvm::DINode::FlagZero, + getDwarfCC(CC)); } // Handle variadic function types; they need an additional @@ -2848,7 +3022,8 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D, EltTys.push_back(getOrCreateType(ParamType, F)); EltTys.push_back(DBuilder.createUnspecifiedParameter()); llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys); - return DBuilder.createSubroutineType(EltTypeArray, 0, getDwarfCC(CC)); + return DBuilder.createSubroutineType(EltTypeArray, llvm::DINode::FlagZero, + getDwarfCC(CC)); } return cast<llvm::DISubroutineType>(getOrCreateType(FnType, F)); @@ -2866,7 +3041,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc, const Decl *D = GD.getDecl(); bool HasDecl = (D != nullptr); - unsigned Flags = 0; + llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; llvm::DIFile *Unit = getOrCreateFile(Loc); llvm::DIScope *FDContext = Unit; llvm::DINodeArray TParamsArray; @@ -2899,9 +3074,8 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, SourceLocation Loc, if (!HasDecl || D->isImplicit()) { Flags |= llvm::DINode::FlagArtificial; - // Artificial functions without a location should not silently reuse CurLoc. - if (Loc.isInvalid()) - CurLoc = SourceLocation(); + // Artificial functions should not silently reuse CurLoc. + CurLoc = SourceLocation(); } unsigned LineNo = getLineNumber(Loc); unsigned ScopeLine = getLineNumber(ScopeLoc); @@ -2939,7 +3113,7 @@ void CGDebugInfo::EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, if (!D) return; - unsigned Flags = 0; + llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; llvm::DIFile *Unit = getOrCreateFile(Loc); llvm::DIScope *FDContext = getDeclContextDescriptor(D); llvm::DINodeArray TParamsArray; @@ -3042,7 +3216,7 @@ llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD, SmallVector<llvm::Metadata *, 5> EltTys; QualType FType; uint64_t FieldSize, FieldOffset; - unsigned FieldAlign; + uint32_t FieldAlign; llvm::DIFile *Unit = getOrCreateFile(VD->getLocation()); QualType Type = VD->getType(); @@ -3096,13 +3270,14 @@ llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD, *XOffset = FieldOffset; FieldTy = DBuilder.createMemberType(Unit, VD->getName(), Unit, 0, FieldSize, - FieldAlign, FieldOffset, 0, FieldTy); + FieldAlign, FieldOffset, + llvm::DINode::FlagZero, FieldTy); EltTys.push_back(FieldTy); FieldOffset += FieldSize; llvm::DINodeArray Elements = DBuilder.getOrCreateArray(EltTys); - unsigned Flags = llvm::DINode::FlagBlockByrefStruct; + llvm::DINode::DIFlags Flags = llvm::DINode::FlagBlockByrefStruct; return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags, nullptr, Elements); @@ -3142,9 +3317,12 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage, Column = getColumnNumber(VD->getLocation()); } SmallVector<int64_t, 9> Expr; - unsigned Flags = 0; + llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; if (VD->isImplicit()) Flags |= llvm::DINode::FlagArtificial; + + auto Align = getDeclAlignIfRequired(VD, CGM.getContext()); + // If this is the first argument and it is implicit then // give it an object pointer flag. // FIXME: There has to be a better way to do this, but for static @@ -3179,7 +3357,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage, ? DBuilder.createParameterVariable(Scope, VD->getName(), *ArgNo, Unit, Line, Ty) : DBuilder.createAutoVariable(Scope, VD->getName(), Unit, - Line, Ty); + Line, Ty, Align); // Insert an llvm.dbg.declare into the current block. DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr), @@ -3209,9 +3387,10 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage, continue; // Use VarDecl's Tag, Scope and Line number. + auto FieldAlign = getDeclAlignIfRequired(Field, CGM.getContext()); auto *D = DBuilder.createAutoVariable( Scope, FieldName, Unit, Line, FieldTy, CGM.getLangOpts().Optimize, - Flags | llvm::DINode::FlagArtificial); + Flags | llvm::DINode::FlagArtificial, FieldAlign); // Insert an llvm.dbg.declare into the current block. DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr), @@ -3222,13 +3401,13 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage, } // Create the descriptor for the variable. - auto *D = - ArgNo - ? DBuilder.createParameterVariable(Scope, Name, *ArgNo, Unit, Line, - Ty, CGM.getLangOpts().Optimize, - Flags) - : DBuilder.createAutoVariable(Scope, Name, Unit, Line, Ty, - CGM.getLangOpts().Optimize, Flags); + auto *D = ArgNo + ? DBuilder.createParameterVariable( + Scope, Name, *ArgNo, Unit, Line, Ty, + CGM.getLangOpts().Optimize, Flags) + : DBuilder.createAutoVariable(Scope, Name, Unit, Line, Ty, + CGM.getLangOpts().Optimize, Flags, + Align); // Insert an llvm.dbg.declare into the current block. DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr), @@ -3307,9 +3486,10 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable( } // Create the descriptor for the variable. + auto Align = getDeclAlignIfRequired(VD, CGM.getContext()); auto *D = DBuilder.createAutoVariable( cast<llvm::DILocalScope>(LexicalBlockStack.back()), VD->getName(), Unit, - Line, Ty); + Line, Ty, false, llvm::DINode::FlagZero, Align); // Insert an llvm.dbg.declare into the current block. auto DL = llvm::DebugLoc::get(Line, Column, LexicalBlockStack.back()); @@ -3438,17 +3618,19 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, llvm::DIType *fieldType; if (capture->isByRef()) { TypeInfo PtrInfo = C.getTypeInfo(C.VoidPtrTy); + auto Align = PtrInfo.AlignIsRequired ? PtrInfo.Align : 0; // FIXME: this creates a second copy of this type! uint64_t xoffset; fieldType = EmitTypeForVarWithBlocksAttr(variable, &xoffset); fieldType = DBuilder.createPointerType(fieldType, PtrInfo.Width); - fieldType = - DBuilder.createMemberType(tunit, name, tunit, line, PtrInfo.Width, - PtrInfo.Align, offsetInBits, 0, fieldType); + fieldType = DBuilder.createMemberType(tunit, name, tunit, line, + PtrInfo.Width, Align, offsetInBits, + llvm::DINode::FlagZero, fieldType); } else { + auto Align = getDeclAlignIfRequired(variable, CGM.getContext()); fieldType = createFieldType(name, variable->getType(), loc, AS_public, - offsetInBits, tunit, tunit); + offsetInBits, Align, tunit, tunit); } fields.push_back(fieldType); } @@ -3459,14 +3641,14 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, llvm::DINodeArray fieldsArray = DBuilder.getOrCreateArray(fields); - llvm::DIType *type = DBuilder.createStructType( - tunit, typeName.str(), tunit, line, - CGM.getContext().toBits(block.BlockSize), - CGM.getContext().toBits(block.BlockAlign), 0, nullptr, fieldsArray); + llvm::DIType *type = + DBuilder.createStructType(tunit, typeName.str(), tunit, line, + CGM.getContext().toBits(block.BlockSize), 0, + llvm::DINode::FlagZero, nullptr, fieldsArray); type = DBuilder.createPointerType(type, CGM.PointerWidthInBits); // Get overall information about the block. - unsigned flags = llvm::DINode::FlagArtificial; + llvm::DINode::DIFlags flags = llvm::DINode::FlagArtificial; auto *scope = cast<llvm::DILocalScope>(LexicalBlockStack.back()); // Create the descriptor for the parameter. @@ -3505,10 +3687,10 @@ CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) { return CreateRecordStaticField(D, Ctxt, cast<RecordDecl>(DC)); } -llvm::DIGlobalVariable *CGDebugInfo::CollectAnonRecordDecls( +llvm::DIGlobalVariableExpression *CGDebugInfo::CollectAnonRecordDecls( const RecordDecl *RD, llvm::DIFile *Unit, unsigned LineNo, StringRef LinkageName, llvm::GlobalVariable *Var, llvm::DIScope *DContext) { - llvm::DIGlobalVariable *GV = nullptr; + llvm::DIGlobalVariableExpression *GVE = nullptr; for (const auto *Field : RD->fields()) { llvm::DIType *FieldTy = getOrCreateType(Field->getType(), Unit); @@ -3517,16 +3699,17 @@ llvm::DIGlobalVariable *CGDebugInfo::CollectAnonRecordDecls( // Ignore unnamed fields, but recurse into anonymous records. if (FieldName.empty()) { if (const auto *RT = dyn_cast<RecordType>(Field->getType())) - GV = CollectAnonRecordDecls(RT->getDecl(), Unit, LineNo, LinkageName, + GVE = CollectAnonRecordDecls(RT->getDecl(), Unit, LineNo, LinkageName, Var, DContext); continue; } // Use VarDecl's Tag, Scope and Line number. - GV = DBuilder.createGlobalVariable(DContext, FieldName, LinkageName, Unit, - LineNo, FieldTy, - Var->hasLocalLinkage(), Var, nullptr); + GVE = DBuilder.createGlobalVariableExpression( + DContext, FieldName, LinkageName, Unit, LineNo, FieldTy, + Var->hasLocalLinkage()); + Var->addDebugInfo(GVE); } - return GV; + return GVE; } void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, @@ -3534,6 +3717,14 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, assert(DebugKind >= codegenoptions::LimitedDebugInfo); if (D->hasAttr<NoDebugAttr>()) return; + + // If we already created a DIGlobalVariable for this declaration, just attach + // it to the llvm::GlobalVariable. + auto Cached = DeclCache.find(D->getCanonicalDecl()); + if (Cached != DeclCache.end()) + return Var->addDebugInfo( + cast<llvm::DIGlobalVariableExpression>(Cached->second)); + // Create global variable debug descriptor. llvm::DIFile *Unit = nullptr; llvm::DIScope *DContext = nullptr; @@ -3544,7 +3735,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, // Attempt to store one global variable for the declaration - even if we // emit a lot of fields. - llvm::DIGlobalVariable *GV = nullptr; + llvm::DIGlobalVariableExpression *GVE = nullptr; // If this is an anonymous union then we'll want to emit a global // variable for each member of the anonymous union so that it's possible @@ -3553,21 +3744,23 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var, const RecordDecl *RD = T->castAs<RecordType>()->getDecl(); assert(RD->isAnonymousStructOrUnion() && "unnamed non-anonymous struct or union?"); - GV = CollectAnonRecordDecls(RD, Unit, LineNo, LinkageName, Var, DContext); + GVE = CollectAnonRecordDecls(RD, Unit, LineNo, LinkageName, Var, DContext); } else { - GV = DBuilder.createGlobalVariable( + auto Align = getDeclAlignIfRequired(D, CGM.getContext()); + GVE = DBuilder.createGlobalVariableExpression( DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit), - Var->hasLocalLinkage(), Var, - getOrCreateStaticDataMemberDeclarationOrNull(D)); + Var->hasLocalLinkage(), /*Expr=*/nullptr, + getOrCreateStaticDataMemberDeclarationOrNull(D), Align); + Var->addDebugInfo(GVE); } - DeclCache[D->getCanonicalDecl()].reset(GV); + DeclCache[D->getCanonicalDecl()].reset(GVE); } -void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, - llvm::Constant *Init) { +void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, const APValue &Init) { assert(DebugKind >= codegenoptions::LimitedDebugInfo); if (VD->hasAttr<NoDebugAttr>()) return; + auto Align = getDeclAlignIfRequired(VD, CGM.getContext()); // Create the descriptor for the variable. llvm::DIFile *Unit = getOrCreateFile(VD->getLocation()); StringRef Name = VD->getName(); @@ -3604,9 +3797,20 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD, auto &GV = DeclCache[VD]; if (GV) return; - GV.reset(DBuilder.createGlobalVariable( + llvm::DIExpression *InitExpr = nullptr; + if (CGM.getContext().getTypeSize(VD->getType()) <= 64) { + // FIXME: Add a representation for integer constants wider than 64 bits. + if (Init.isInt()) + InitExpr = + DBuilder.createConstantValueExpression(Init.getInt().getExtValue()); + else if (Init.isFloat()) + InitExpr = DBuilder.createConstantValueExpression( + Init.getFloat().bitcastToAPInt().getZExtValue()); + } + GV.reset(DBuilder.createGlobalVariableExpression( DContext, Name, StringRef(), Unit, getLineNumber(VD->getLocation()), Ty, - true, Init, getOrCreateStaticDataMemberDeclarationOrNull(VarD))); + true, InitExpr, getOrCreateStaticDataMemberDeclarationOrNull(VarD), + Align)); } llvm::DIScope *CGDebugInfo::getCurrentContextDescriptor(const Decl *D) { @@ -3620,8 +3824,8 @@ void CGDebugInfo::EmitUsingDirective(const UsingDirectiveDecl &UD) { if (CGM.getCodeGenOpts().getDebugInfo() < codegenoptions::LimitedDebugInfo) return; const NamespaceDecl *NSDecl = UD.getNominatedNamespace(); - if (!NSDecl->isAnonymousNamespace() || - CGM.getCodeGenOpts().DebugExplicitImport) { + if (!NSDecl->isAnonymousNamespace() || + CGM.getCodeGenOpts().DebugExplicitImport) { DBuilder.createImportedModule( getCurrentContextDescriptor(cast<Decl>(UD.getDeclContext())), getOrCreateNameSpace(NSDecl), @@ -3700,8 +3904,8 @@ CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) { unsigned LineNo = getLineNumber(NSDecl->getLocation()); llvm::DIFile *FileD = getOrCreateFile(NSDecl->getLocation()); llvm::DIScope *Context = getDeclContextDescriptor(NSDecl); - llvm::DINamespace *NS = - DBuilder.createNameSpace(Context, NSDecl->getName(), FileD, LineNo); + llvm::DINamespace *NS = DBuilder.createNameSpace( + Context, NSDecl->getName(), FileD, LineNo, NSDecl->isInline()); NameSpaceCache[NSDecl].reset(NS); return NS; } @@ -3750,6 +3954,8 @@ void CGDebugInfo::finalize() { else Repl = it->second; + if (auto *GVE = dyn_cast_or_null<llvm::DIGlobalVariableExpression>(Repl)) + Repl = GVE->getVariable(); DBuilder.replaceTemporary(std::move(FwdDecl), cast<llvm::MDNode>(Repl)); } @@ -3770,3 +3976,12 @@ void CGDebugInfo::EmitExplicitCastType(QualType Ty) { // Don't ignore in case of explicit cast where it is referenced indirectly. DBuilder.retainType(DieTy); } + +llvm::DebugLoc CGDebugInfo::SourceLocToDebugLoc(SourceLocation Loc) { + if (LexicalBlockStack.empty()) + return llvm::DebugLoc(); + + llvm::MDNode *Scope = LexicalBlockStack.back(); + return llvm::DebugLoc::get( + getLineNumber(Loc), getColumnNumber(Loc), Scope); +} |