diff options
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 264 |
1 files changed, 145 insertions, 119 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 62ad356e7f8fa..3f053c7a38c77 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -101,27 +101,27 @@ public: CVMCAdapter(MCStreamer &OS, TypeCollection &TypeTable) : OS(&OS), TypeTable(TypeTable) {} - void EmitBytes(StringRef Data) { OS->EmitBytes(Data); } + void emitBytes(StringRef Data) override { OS->emitBytes(Data); } - void EmitIntValue(uint64_t Value, unsigned Size) { - OS->EmitIntValueInHex(Value, Size); + void emitIntValue(uint64_t Value, unsigned Size) override { + OS->emitIntValueInHex(Value, Size); } - void EmitBinaryData(StringRef Data) { OS->EmitBinaryData(Data); } + void emitBinaryData(StringRef Data) override { OS->emitBinaryData(Data); } - void AddComment(const Twine &T) { OS->AddComment(T); } + void AddComment(const Twine &T) override { OS->AddComment(T); } - void AddRawComment(const Twine &T) { OS->emitRawComment(T); } + void AddRawComment(const Twine &T) override { OS->emitRawComment(T); } - bool isVerboseAsm() { return OS->isVerboseAsm(); } + bool isVerboseAsm() override { return OS->isVerboseAsm(); } - std::string getTypeName(TypeIndex TI) { + std::string getTypeName(TypeIndex TI) override { std::string TypeName; if (!TI.isNoneType()) { if (TI.isSimple()) - TypeName = TypeIndex::simpleTypeName(TI); + TypeName = std::string(TypeIndex::simpleTypeName(TI)); else - TypeName = TypeTable.getTypeName(TI); + TypeName = std::string(TypeTable.getTypeName(TI)); } return TypeName; } @@ -183,7 +183,7 @@ StringRef CodeViewDebug::getFullFilepath(const DIFile *File) { if (Dir.startswith("/") || Filename.startswith("/")) { if (llvm::sys::path::is_absolute(Filename, llvm::sys::path::Style::posix)) return Filename; - Filepath = Dir; + Filepath = std::string(Dir); if (Dir.back() != '/') Filepath += '/'; Filepath += Filename; @@ -195,7 +195,7 @@ StringRef CodeViewDebug::getFullFilepath(const DIFile *File) { // that would increase the IR size and probably not needed for other users. // For now, just concatenate and canonicalize the path here. if (Filename.find(':') == 1) - Filepath = Filename; + Filepath = std::string(Filename); else Filepath = (Dir + "\\" + Filename).str(); @@ -250,8 +250,15 @@ unsigned CodeViewDebug::maybeRecordFile(const DIFile *F) { ChecksumAsBytes = ArrayRef<uint8_t>( reinterpret_cast<const uint8_t *>(CKMem), Checksum.size()); switch (F->getChecksum()->Kind) { - case DIFile::CSK_MD5: CSKind = FileChecksumKind::MD5; break; - case DIFile::CSK_SHA1: CSKind = FileChecksumKind::SHA1; break; + case DIFile::CSK_MD5: + CSKind = FileChecksumKind::MD5; + break; + case DIFile::CSK_SHA1: + CSKind = FileChecksumKind::SHA1; + break; + case DIFile::CSK_SHA256: + CSKind = FileChecksumKind::SHA256; + break; } } bool Success = OS.EmitCVFileDirective(NextId, FullPath, ChecksumAsBytes, @@ -303,12 +310,19 @@ static StringRef getPrettyScopeName(const DIScope *Scope) { return StringRef(); } -static const DISubprogram *getQualifiedNameComponents( +const DISubprogram *CodeViewDebug::collectParentScopeNames( const DIScope *Scope, SmallVectorImpl<StringRef> &QualifiedNameComponents) { const DISubprogram *ClosestSubprogram = nullptr; while (Scope != nullptr) { if (ClosestSubprogram == nullptr) ClosestSubprogram = dyn_cast<DISubprogram>(Scope); + + // If a type appears in a scope chain, make sure it gets emitted. The + // frontend will be responsible for deciding if this should be a forward + // declaration or a complete type. + if (const auto *Ty = dyn_cast<DICompositeType>(Scope)) + DeferredCompleteTypes.push_back(Ty); + StringRef ScopeName = getPrettyScopeName(Scope); if (!ScopeName.empty()) QualifiedNameComponents.push_back(ScopeName); @@ -317,24 +331,18 @@ static const DISubprogram *getQualifiedNameComponents( return ClosestSubprogram; } -static std::string getQualifiedName(ArrayRef<StringRef> QualifiedNameComponents, +static std::string formatNestedName(ArrayRef<StringRef> QualifiedNameComponents, StringRef TypeName) { std::string FullyQualifiedName; for (StringRef QualifiedNameComponent : llvm::reverse(QualifiedNameComponents)) { - FullyQualifiedName.append(QualifiedNameComponent); + FullyQualifiedName.append(std::string(QualifiedNameComponent)); FullyQualifiedName.append("::"); } - FullyQualifiedName.append(TypeName); + FullyQualifiedName.append(std::string(TypeName)); return FullyQualifiedName; } -static std::string getFullyQualifiedName(const DIScope *Scope, StringRef Name) { - SmallVector<StringRef, 5> QualifiedNameComponents; - getQualifiedNameComponents(Scope, QualifiedNameComponents); - return getQualifiedName(QualifiedNameComponents, Name); -} - struct CodeViewDebug::TypeLoweringScope { TypeLoweringScope(CodeViewDebug &CVD) : CVD(CVD) { ++CVD.TypeEmissionLevel; } ~TypeLoweringScope() { @@ -347,7 +355,18 @@ struct CodeViewDebug::TypeLoweringScope { CodeViewDebug &CVD; }; -static std::string getFullyQualifiedName(const DIScope *Ty) { +std::string CodeViewDebug::getFullyQualifiedName(const DIScope *Scope, + StringRef Name) { + // Ensure types in the scope chain are emitted as soon as possible. + // This can create otherwise a situation where S_UDTs are emitted while + // looping in emitDebugInfoForUDTs. + TypeLoweringScope S(*this); + SmallVector<StringRef, 5> QualifiedNameComponents; + collectParentScopeNames(Scope, QualifiedNameComponents); + return formatNestedName(QualifiedNameComponents, Name); +} + +std::string CodeViewDebug::getFullyQualifiedName(const DIScope *Ty) { const DIScope *Scope = Ty->getScope(); return getFullyQualifiedName(Scope, getPrettyScopeName(Ty)); } @@ -418,10 +437,11 @@ getFunctionOptions(const DISubroutineType *Ty, ReturnTy = TypeArray[0]; } - if (auto *ReturnDCTy = dyn_cast_or_null<DICompositeType>(ReturnTy)) { - if (isNonTrivial(ReturnDCTy)) + // Add CxxReturnUdt option to functions that return nontrivial record types + // or methods that return record types. + if (auto *ReturnDCTy = dyn_cast_or_null<DICompositeType>(ReturnTy)) + if (isNonTrivial(ReturnDCTy) || ClassTy) FO |= FunctionOptions::CxxReturnUdt; - } // DISubroutineType is unnamed. Use DISubprogram's i.e. SPName in comparison. if (ClassTy && isNonTrivial(ClassTy) && SPName == ClassTy->getName()) { @@ -543,15 +563,15 @@ void CodeViewDebug::maybeRecordLocation(const DebugLoc &DL, addLocIfNotPresent(CurFn->ChildSites, Loc); } - OS.EmitCVLocDirective(FuncId, FileId, DL.getLine(), DL.getCol(), + OS.emitCVLocDirective(FuncId, FileId, DL.getLine(), DL.getCol(), /*PrologueEnd=*/false, /*IsStmt=*/false, DL->getFilename(), SMLoc()); } void CodeViewDebug::emitCodeViewMagicVersion() { - OS.EmitValueToAlignment(4); + OS.emitValueToAlignment(4); OS.AddComment("Debug section magic"); - OS.EmitIntValue(COFF::DEBUG_SECTION_MAGIC, 4); + OS.emitInt32(COFF::DEBUG_SECTION_MAGIC); } void CodeViewDebug::endModule() { @@ -600,11 +620,11 @@ void CodeViewDebug::endModule() { // This subsection holds a file index to offset in string table table. OS.AddComment("File index to string table offset subsection"); - OS.EmitCVFileChecksumsDirective(); + OS.emitCVFileChecksumsDirective(); // This subsection holds the string table. OS.AddComment("String table"); - OS.EmitCVStringTableDirective(); + OS.emitCVStringTableDirective(); // Emit S_BUILDINFO, which points to LF_BUILDINFO. Put this in its own symbol // subsection in the generic .debug$S section at the end. There is no @@ -631,7 +651,7 @@ emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S, SmallString<32> NullTerminatedString( S.take_front(MaxRecordLength - MaxFixedRecordLength - 1)); NullTerminatedString.push_back('\0'); - OS.EmitBytes(NullTerminatedString); + OS.emitBytes(NullTerminatedString); } void CodeViewDebug::emitTypeInformation() { @@ -674,13 +694,13 @@ void CodeViewDebug::emitTypeGlobalHashes() { // hardcoded to version 0, SHA1. OS.SwitchSection(Asm->getObjFileLowering().getCOFFGlobalTypeHashesSection()); - OS.EmitValueToAlignment(4); + OS.emitValueToAlignment(4); OS.AddComment("Magic"); - OS.EmitIntValue(COFF::DEBUG_HASHES_SECTION_MAGIC, 4); + OS.emitInt32(COFF::DEBUG_HASHES_SECTION_MAGIC); OS.AddComment("Section Version"); - OS.EmitIntValue(0, 2); + OS.emitInt16(0); OS.AddComment("Hash Algorithm"); - OS.EmitIntValue(uint16_t(GlobalTypeHashAlg::SHA1_8), 2); + OS.emitInt16(uint16_t(GlobalTypeHashAlg::SHA1_8)); TypeIndex TI(TypeIndex::FirstNonSimpleIndex); for (const auto &GHR : TypeTable.hashes()) { @@ -696,7 +716,7 @@ void CodeViewDebug::emitTypeGlobalHashes() { assert(GHR.Hash.size() == 8); StringRef S(reinterpret_cast<const char *>(GHR.Hash.data()), GHR.Hash.size()); - OS.EmitBinaryData(S); + OS.emitBinaryData(S); } } @@ -775,16 +795,16 @@ void CodeViewDebug::emitCompilerInformation() { // TODO: Figure out which other flags need to be set. OS.AddComment("Flags and language"); - OS.EmitIntValue(Flags, 4); + OS.emitInt32(Flags); OS.AddComment("CPUType"); - OS.EmitIntValue(static_cast<uint64_t>(TheCPU), 2); + OS.emitInt16(static_cast<uint64_t>(TheCPU)); StringRef CompilerVersion = CU->getProducer(); Version FrontVer = parseVersion(CompilerVersion); OS.AddComment("Frontend version"); for (int N = 0; N < 4; ++N) - OS.EmitIntValue(FrontVer.Part[N], 2); + OS.emitInt16(FrontVer.Part[N]); // Some Microsoft tools, like Binscope, expect a backend version number of at // least 8.something, so we'll coerce the LLVM version into a form that @@ -797,7 +817,7 @@ void CodeViewDebug::emitCompilerInformation() { Version BackVer = {{ Major, 0, 0, 0 }}; OS.AddComment("Backend version"); for (int N = 0; N < 4; ++N) - OS.EmitIntValue(BackVer.Part[N], 2); + OS.emitInt16(BackVer.Part[N]); OS.AddComment("Null-terminated compiler version string"); emitNullTerminatedSymbolName(OS, CompilerVersion); @@ -841,7 +861,7 @@ void CodeViewDebug::emitBuildInfo() { MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols); MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO); OS.AddComment("LF_BUILDINFO index"); - OS.EmitIntValue(BuildInfoIndex.getIndex(), 4); + OS.emitInt32(BuildInfoIndex.getIndex()); endSymbolRecord(BIEnd); endCVSubsection(BISubsecEnd); } @@ -858,7 +878,7 @@ void CodeViewDebug::emitInlineeLinesSubsection() { // for instance, will display a warning that the breakpoints are not valid if // the pdb does not match the source. OS.AddComment("Inlinee lines signature"); - OS.EmitIntValue(unsigned(InlineeLinesSignature::Normal), 4); + OS.emitInt32(unsigned(InlineeLinesSignature::Normal)); for (const DISubprogram *SP : InlinedSubprograms) { assert(TypeIndices.count({SP, nullptr})); @@ -870,11 +890,11 @@ void CodeViewDebug::emitInlineeLinesSubsection() { SP->getFilename() + Twine(':') + Twine(SP->getLine())); OS.AddBlankLine(); OS.AddComment("Type index of inlined function"); - OS.EmitIntValue(InlineeIdx.getIndex(), 4); + OS.emitInt32(InlineeIdx.getIndex()); OS.AddComment("Offset into filechecksum table"); - OS.EmitCVFileChecksumOffsetDirective(FileId); + OS.emitCVFileChecksumOffsetDirective(FileId); OS.AddComment("Starting line number"); - OS.EmitIntValue(SP->getLine(), 4); + OS.emitInt32(SP->getLine()); } endCVSubsection(InlineEnd); @@ -890,16 +910,16 @@ void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI, MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE); OS.AddComment("PtrParent"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("PtrEnd"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("Inlinee type index"); - OS.EmitIntValue(InlineeIdx.getIndex(), 4); + OS.emitInt32(InlineeIdx.getIndex()); unsigned FileId = maybeRecordFile(Site.Inlinee->getFile()); unsigned StartLineNum = Site.Inlinee->getLine(); - OS.EmitCVInlineLinetableDirective(Site.SiteFuncId, FileId, StartLineNum, + OS.emitCVInlineLinetableDirective(Site.SiteFuncId, FileId, StartLineNum, FI.Begin, FI.End); endSymbolRecord(InlineEnd); @@ -943,7 +963,8 @@ void CodeViewDebug::switchToDebugSectionForSymbol(const MCSymbol *GVSym) { void CodeViewDebug::emitDebugInfoForThunk(const Function *GV, FunctionInfo &FI, const MCSymbol *Fn) { - std::string FuncName = GlobalValue::dropLLVMManglingEscape(GV->getName()); + std::string FuncName = + std::string(GlobalValue::dropLLVMManglingEscape(GV->getName())); const ThunkOrdinal ordinal = ThunkOrdinal::Standard; // Only supported kind. OS.AddComment("Symbol subsection for " + Twine(FuncName)); @@ -952,11 +973,11 @@ void CodeViewDebug::emitDebugInfoForThunk(const Function *GV, // Emit S_THUNK32 MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32); OS.AddComment("PtrParent"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("PtrEnd"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("PtrNext"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("Thunk section relative address"); OS.EmitCOFFSecRel32(Fn, /*Offset=*/0); OS.AddComment("Thunk section index"); @@ -964,7 +985,7 @@ void CodeViewDebug::emitDebugInfoForThunk(const Function *GV, OS.AddComment("Code size"); OS.emitAbsoluteSymbolDiff(FI.End, Fn, 2); OS.AddComment("Ordinal"); - OS.EmitIntValue(unsigned(ordinal), 1); + OS.emitInt8(unsigned(ordinal)); OS.AddComment("Function name"); emitNullTerminatedSymbolName(OS, FuncName); // Additional fields specific to the thunk ordinal would go here. @@ -1006,7 +1027,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, // If our DISubprogram name is empty, use the mangled name. if (FuncName.empty()) - FuncName = GlobalValue::dropLLVMManglingEscape(GV->getName()); + FuncName = std::string(GlobalValue::dropLLVMManglingEscape(GV->getName())); // Emit FPO data, but only on 32-bit x86. No other platforms use it. if (Triple(MMI->getModule()->getTargetTriple()).getArch() == Triple::x86) @@ -1022,27 +1043,27 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, // These fields are filled in by tools like CVPACK which run after the fact. OS.AddComment("PtrParent"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("PtrEnd"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("PtrNext"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); // This is the important bit that tells the debugger where the function // code is located and what's its size: OS.AddComment("Code size"); OS.emitAbsoluteSymbolDiff(FI.End, Fn, 4); OS.AddComment("Offset after prologue"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("Offset before epilogue"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("Function type index"); - OS.EmitIntValue(getFuncIdForSubprogram(GV->getSubprogram()).getIndex(), 4); + OS.emitInt32(getFuncIdForSubprogram(GV->getSubprogram()).getIndex()); OS.AddComment("Function section relative address"); OS.EmitCOFFSecRel32(Fn, /*Offset=*/0); OS.AddComment("Function section index"); OS.EmitCOFFSectionIndex(Fn); OS.AddComment("Flags"); - OS.EmitIntValue(0, 1); + OS.emitInt8(0); // Emit the function display name as a null-terminated string. OS.AddComment("Function name"); // Truncate the name so we won't overflow the record length field. @@ -1052,19 +1073,19 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC); // Subtract out the CSR size since MSVC excludes that and we include it. OS.AddComment("FrameSize"); - OS.EmitIntValue(FI.FrameSize - FI.CSRSize, 4); + OS.emitInt32(FI.FrameSize - FI.CSRSize); OS.AddComment("Padding"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("Offset of padding"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("Bytes of callee saved registers"); - OS.EmitIntValue(FI.CSRSize, 4); + OS.emitInt32(FI.CSRSize); OS.AddComment("Exception handler offset"); - OS.EmitIntValue(0, 4); + OS.emitInt32(0); OS.AddComment("Exception handler section"); - OS.EmitIntValue(0, 2); + OS.emitInt16(0); OS.AddComment("Flags (defines frame register)"); - OS.EmitIntValue(uint32_t(FI.FrameProcOpts), 4); + OS.emitInt32(uint32_t(FI.FrameProcOpts)); endSymbolRecord(FrameProcEnd); emitLocalVariableList(FI, FI.Locals); @@ -1088,13 +1109,13 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, OS.EmitCOFFSecRel32(Label, /*Offset=*/0); // FIXME: Make sure we don't overflow the max record size. OS.EmitCOFFSectionIndex(Label); - OS.EmitIntValue(Strs->getNumOperands(), 2); + OS.emitInt16(Strs->getNumOperands()); for (Metadata *MD : Strs->operands()) { // MDStrings are null terminated, so we can do EmitBytes and get the // nice .asciz directive. StringRef Str = cast<MDString>(MD)->getString(); assert(Str.data()[Str.size()] == '\0' && "non-nullterminated MDString"); - OS.EmitBytes(StringRef(Str.data(), Str.size() + 1)); + OS.emitBytes(StringRef(Str.data(), Str.size() + 1)); } endSymbolRecord(AnnotEnd); } @@ -1111,7 +1132,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, OS.AddComment("Call instruction length"); OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2); OS.AddComment("Type index"); - OS.EmitIntValue(getCompleteTypeIndex(DITy).getIndex(), 4); + OS.emitInt32(getCompleteTypeIndex(DITy).getIndex()); endSymbolRecord(HeapAllocEnd); } @@ -1124,7 +1145,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, endCVSubsection(SymbolsEnd); // We have an assembler directive that takes care of the whole line table. - OS.EmitCVLinetableDirective(FI.FuncId, Fn, FI.End); + OS.emitCVLinetableDirective(FI.FuncId, Fn, FI.End); } CodeViewDebug::LocalVarDefRange @@ -1173,7 +1194,7 @@ void CodeViewDebug::collectVariableInfoFromMFTable( } // Get the frame register used and the offset. - unsigned FrameReg = 0; + Register FrameReg; int FrameOffset = TFI->getFrameIndexReference(*Asm->MF, VI.Slot, FrameReg); uint16_t CVReg = TRI->getCodeViewRegNum(FrameReg); @@ -1468,12 +1489,12 @@ void CodeViewDebug::addToUDTs(const DIType *Ty) { if (!shouldEmitUdt(Ty)) return; - SmallVector<StringRef, 5> QualifiedNameComponents; + SmallVector<StringRef, 5> ParentScopeNames; const DISubprogram *ClosestSubprogram = - getQualifiedNameComponents(Ty->getScope(), QualifiedNameComponents); + collectParentScopeNames(Ty->getScope(), ParentScopeNames); std::string FullyQualifiedName = - getQualifiedName(QualifiedNameComponents, getPrettyScopeName(Ty)); + formatNestedName(ParentScopeNames, getPrettyScopeName(Ty)); if (ClosestSubprogram == nullptr) { GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty); @@ -1571,7 +1592,7 @@ TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) { assert(Element->getTag() == dwarf::DW_TAG_subrange_type); const DISubrange *Subrange = cast<DISubrange>(Element); - assert(Subrange->getLowerBound() == 0 && + assert(!Subrange->getRawLowerBound() && "codeview doesn't support subranges with lower bounds"); int64_t Count = -1; if (auto *CI = Subrange->getCount().dyn_cast<ConstantInt*>()) @@ -1767,11 +1788,12 @@ translatePtrToMemberRep(unsigned SizeInBytes, bool IsPMF, unsigned Flags) { TypeIndex CodeViewDebug::lowerTypeMemberPointer(const DIDerivedType *Ty, PointerOptions PO) { assert(Ty->getTag() == dwarf::DW_TAG_ptr_to_member_type); + bool IsPMF = isa<DISubroutineType>(Ty->getBaseType()); TypeIndex ClassTI = getTypeIndex(Ty->getClassType()); - TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType(), Ty->getClassType()); + TypeIndex PointeeTI = + getTypeIndex(Ty->getBaseType(), IsPMF ? Ty->getClassType() : nullptr); PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64 : PointerKind::Near32; - bool IsPMF = isa<DISubroutineType>(Ty->getBaseType()); PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction : PointerMode::PointerToDataMember; @@ -2063,7 +2085,7 @@ TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) { // order, which is what MSVC does. if (auto *Enumerator = dyn_cast_or_null<DIEnumerator>(Element)) { EnumeratorRecord ER(MemberAccess::Public, - APSInt::getUnsigned(Enumerator->getValue()), + APSInt(Enumerator->getValue(), true), Enumerator->getName()); ContinuationBuilder.writeMemberType(ER); EnumeratorCount++; @@ -2248,7 +2270,7 @@ TypeIndex CodeViewDebug::lowerCompleteTypeClass(const DICompositeType *Ty) { // MSVC appears to set this flag by searching any destructor or method with // FunctionOptions::Constructor among the emitted members. Clang AST has all - // the members, however special member functions are not yet emitted into + // the members, however special member functions are not yet emitted into // debug information. For now checking a class's non-triviality seems enough. // FIXME: not true for a nested unnamed struct. if (isNonTrivial(Ty)) @@ -2625,9 +2647,9 @@ void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI, TypeIndex TI = Var.UseReferenceType ? getTypeIndexForReferenceTo(Var.DIVar->getType()) : getCompleteTypeIndex(Var.DIVar->getType()); - OS.EmitIntValue(TI.getIndex(), 4); + OS.emitInt32(TI.getIndex()); OS.AddComment("Flags"); - OS.EmitIntValue(static_cast<uint16_t>(Flags), 2); + OS.emitInt16(static_cast<uint16_t>(Flags)); // Truncate the name so we won't overflow the record length field. emitNullTerminatedSymbolName(OS, Var.DIVar->getName()); endSymbolRecord(LocalEnd); @@ -2660,7 +2682,7 @@ void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI, : (EncFP == FI.EncodedLocalFramePtrReg))) { DefRangeFramePointerRelHeader DRHdr; DRHdr.Offset = Offset; - OS.EmitCVDefRangeDirective(DefRange.Ranges, DRHdr); + OS.emitCVDefRangeDirective(DefRange.Ranges, DRHdr); } else { uint16_t RegRelFlags = 0; if (DefRange.IsSubfield) { @@ -2672,7 +2694,7 @@ void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI, DRHdr.Register = Reg; DRHdr.Flags = RegRelFlags; DRHdr.BasePointerOffset = Offset; - OS.EmitCVDefRangeDirective(DefRange.Ranges, DRHdr); + OS.emitCVDefRangeDirective(DefRange.Ranges, DRHdr); } } else { assert(DefRange.DataOffset == 0 && "unexpected offset into register"); @@ -2681,12 +2703,12 @@ void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI, DRHdr.Register = DefRange.CVRegister; DRHdr.MayHaveNoName = 0; DRHdr.OffsetInParent = DefRange.StructOffset; - OS.EmitCVDefRangeDirective(DefRange.Ranges, DRHdr); + OS.emitCVDefRangeDirective(DefRange.Ranges, DRHdr); } else { DefRangeRegisterHeader DRHdr; DRHdr.Register = DefRange.CVRegister; DRHdr.MayHaveNoName = 0; - OS.EmitCVDefRangeDirective(DefRange.Ranges, DRHdr); + OS.emitCVDefRangeDirective(DefRange.Ranges, DRHdr); } } } @@ -2704,9 +2726,9 @@ void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block, const FunctionInfo& FI) { MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32); OS.AddComment("PtrParent"); - OS.EmitIntValue(0, 4); // PtrParent + OS.emitInt32(0); // PtrParent OS.AddComment("PtrEnd"); - OS.EmitIntValue(0, 4); // PtrEnd + OS.emitInt32(0); // PtrEnd OS.AddComment("Code size"); OS.emitAbsoluteSymbolDiff(Block.End, Block.Begin, 4); // Code Size OS.AddComment("Function section relative address"); @@ -2914,17 +2936,17 @@ void CodeViewDebug::beginInstruction(const MachineInstr *MI) { MCSymbol *CodeViewDebug::beginCVSubsection(DebugSubsectionKind Kind) { MCSymbol *BeginLabel = MMI->getContext().createTempSymbol(), *EndLabel = MMI->getContext().createTempSymbol(); - OS.EmitIntValue(unsigned(Kind), 4); + OS.emitInt32(unsigned(Kind)); OS.AddComment("Subsection size"); OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 4); - OS.EmitLabel(BeginLabel); + OS.emitLabel(BeginLabel); return EndLabel; } void CodeViewDebug::endCVSubsection(MCSymbol *EndLabel) { - OS.EmitLabel(EndLabel); + OS.emitLabel(EndLabel); // Every subsection must be aligned to a 4-byte boundary. - OS.EmitValueToAlignment(4); + OS.emitValueToAlignment(4); } static StringRef getSymbolName(SymbolKind SymKind) { @@ -2939,10 +2961,10 @@ MCSymbol *CodeViewDebug::beginSymbolRecord(SymbolKind SymKind) { *EndLabel = MMI->getContext().createTempSymbol(); OS.AddComment("Record length"); OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2); - OS.EmitLabel(BeginLabel); + OS.emitLabel(BeginLabel); if (OS.isVerboseAsm()) OS.AddComment("Record kind: " + getSymbolName(SymKind)); - OS.EmitIntValue(unsigned(SymKind), 2); + OS.emitInt16(unsigned(SymKind)); return EndLabel; } @@ -2951,27 +2973,31 @@ void CodeViewDebug::endSymbolRecord(MCSymbol *SymEnd) { // an extra copy of every symbol record in LLD. This increases object file // size by less than 1% in the clang build, and is compatible with the Visual // C++ linker. - OS.EmitValueToAlignment(4); - OS.EmitLabel(SymEnd); + OS.emitValueToAlignment(4); + OS.emitLabel(SymEnd); } void CodeViewDebug::emitEndSymbolRecord(SymbolKind EndKind) { OS.AddComment("Record length"); - OS.EmitIntValue(2, 2); + OS.emitInt16(2); if (OS.isVerboseAsm()) OS.AddComment("Record kind: " + getSymbolName(EndKind)); - OS.EmitIntValue(unsigned(EndKind), 2); // Record Kind + OS.emitInt16(uint16_t(EndKind)); // Record Kind } void CodeViewDebug::emitDebugInfoForUDTs( - ArrayRef<std::pair<std::string, const DIType *>> UDTs) { + const std::vector<std::pair<std::string, const DIType *>> &UDTs) { +#ifndef NDEBUG + size_t OriginalSize = UDTs.size(); +#endif for (const auto &UDT : UDTs) { const DIType *T = UDT.second; assert(shouldEmitUdt(T)); - MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT); OS.AddComment("Type"); - OS.EmitIntValue(getCompleteTypeIndex(T).getIndex(), 4); + OS.emitInt32(getCompleteTypeIndex(T).getIndex()); + assert(OriginalSize == UDTs.size() && + "getCompleteTypeIndex found new UDTs!"); emitNullTerminatedSymbolName(OS, UDT.first); endSymbolRecord(UDTRecordEnd); } @@ -3075,6 +3101,14 @@ void CodeViewDebug::emitGlobalVariableList(ArrayRef<CVGlobalVariable> Globals) { void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) { const DIGlobalVariable *DIGV = CVGV.DIGV; + + const DIScope *Scope = DIGV->getScope(); + // For static data members, get the scope from the declaration. + if (const auto *MemberDecl = dyn_cast_or_null<DIDerivedType>( + DIGV->getRawStaticDataMemberDeclaration())) + Scope = MemberDecl->getScope(); + std::string QualifiedName = getFullyQualifiedName(Scope, DIGV->getName()); + if (const GlobalVariable *GV = CVGV.GVInfo.dyn_cast<const GlobalVariable *>()) { // DataSym record, see SymbolRecord.h for more info. Thread local data @@ -3087,18 +3121,16 @@ void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) { : SymbolKind::S_GDATA32); MCSymbol *DataEnd = beginSymbolRecord(DataSym); OS.AddComment("Type"); - OS.EmitIntValue(getCompleteTypeIndex(DIGV->getType()).getIndex(), 4); + OS.emitInt32(getCompleteTypeIndex(DIGV->getType()).getIndex()); OS.AddComment("DataOffset"); OS.EmitCOFFSecRel32(GVSym, /*Offset=*/0); OS.AddComment("Segment"); OS.EmitCOFFSectionIndex(GVSym); OS.AddComment("Name"); const unsigned LengthOfDataRecord = 12; - emitNullTerminatedSymbolName(OS, DIGV->getName(), LengthOfDataRecord); + emitNullTerminatedSymbolName(OS, QualifiedName, LengthOfDataRecord); endSymbolRecord(DataEnd); } else { - // FIXME: Currently this only emits the global variables in the IR metadata. - // This should also emit enums and static data members. const DIExpression *DIE = CVGV.GVInfo.get<const DIExpression *>(); assert(DIE->isConstant() && "Global constant variables must contain a constant expression."); @@ -3106,7 +3138,7 @@ void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) { MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT); OS.AddComment("Type"); - OS.EmitIntValue(getTypeIndex(DIGV->getType()).getIndex(), 4); + OS.emitInt32(getTypeIndex(DIGV->getType()).getIndex()); OS.AddComment("Value"); // Encoded integers shouldn't need more than 10 bytes. @@ -3115,16 +3147,10 @@ void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) { CodeViewRecordIO IO(Writer); cantFail(IO.mapEncodedInteger(Val)); StringRef SRef((char *)data, Writer.getOffset()); - OS.EmitBinaryData(SRef); + OS.emitBinaryData(SRef); OS.AddComment("Name"); - const DIScope *Scope = DIGV->getScope(); - // For static data members, get the scope from the declaration. - if (const auto *MemberDecl = dyn_cast_or_null<DIDerivedType>( - DIGV->getRawStaticDataMemberDeclaration())) - Scope = MemberDecl->getScope(); - emitNullTerminatedSymbolName(OS, - getFullyQualifiedName(Scope, DIGV->getName())); + emitNullTerminatedSymbolName(OS, QualifiedName); endSymbolRecord(SConstantEnd); } } |