diff options
Diffstat (limited to 'lib/CodeGen/AsmPrinter/CodeViewDebug.cpp')
-rw-r--r-- | lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 116 |
1 files changed, 44 insertions, 72 deletions
diff --git a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 932959c311fa..c6457f3626d1 100644 --- a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -98,7 +98,8 @@ using namespace llvm::codeview; namespace { class CVMCAdapter : public CodeViewRecordStreamer { public: - CVMCAdapter(MCStreamer &OS) : OS(&OS) {} + CVMCAdapter(MCStreamer &OS, TypeCollection &TypeTable) + : OS(&OS), TypeTable(TypeTable) {} void EmitBytes(StringRef Data) { OS->EmitBytes(Data); } @@ -110,8 +111,24 @@ public: void AddComment(const Twine &T) { OS->AddComment(T); } + void AddRawComment(const Twine &T) { OS->emitRawComment(T); } + + bool isVerboseAsm() { return OS->isVerboseAsm(); } + + std::string getTypeName(TypeIndex TI) { + std::string TypeName; + if (!TI.isNoneType()) { + if (TI.isSimple()) + TypeName = TypeIndex::simpleTypeName(TI); + else + TypeName = TypeTable.getTypeName(TI); + } + return TypeName; + } + private: MCStreamer *OS = nullptr; + TypeCollection &TypeTable; }; } // namespace @@ -617,13 +634,6 @@ emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S, OS.EmitBytes(NullTerminatedString); } -static StringRef getTypeLeafName(TypeLeafKind TypeKind) { - for (const EnumEntry<TypeLeafKind> &EE : getTypeLeafNames()) - if (EE.Value == TypeKind) - return EE.Name; - return ""; -} - void CodeViewDebug::emitTypeInformation() { if (TypeTable.empty()) return; @@ -632,30 +642,11 @@ void CodeViewDebug::emitTypeInformation() { OS.SwitchSection(Asm->getObjFileLowering().getCOFFDebugTypesSection()); emitCodeViewMagicVersion(); - SmallString<8> CommentPrefix; - if (OS.isVerboseAsm()) { - CommentPrefix += '\t'; - CommentPrefix += Asm->MAI->getCommentString(); - CommentPrefix += ' '; - } - TypeTableCollection Table(TypeTable.records()); - SmallString<512> CommentBlock; - raw_svector_ostream CommentOS(CommentBlock); - std::unique_ptr<ScopedPrinter> SP; - std::unique_ptr<TypeDumpVisitor> TDV; TypeVisitorCallbackPipeline Pipeline; - if (OS.isVerboseAsm()) { - // To construct block comment describing the type record for readability. - SP = llvm::make_unique<ScopedPrinter>(CommentOS); - SP->setPrefix(CommentPrefix); - TDV = llvm::make_unique<TypeDumpVisitor>(Table, SP.get(), false); - Pipeline.addCallbackToPipeline(*TDV); - } - // To emit type record using Codeview MCStreamer adapter - CVMCAdapter CVMCOS(OS); + CVMCAdapter CVMCOS(OS, Table); TypeRecordMapping typeMapping(CVMCOS); Pipeline.addCallbackToPipeline(typeMapping); @@ -664,17 +655,6 @@ void CodeViewDebug::emitTypeInformation() { // This will fail if the record data is invalid. CVType Record = Table.getType(*B); - CommentBlock.clear(); - - auto RecordLen = Record.length(); - auto RecordKind = Record.kind(); - if (OS.isVerboseAsm()) - CVMCOS.AddComment("Record length"); - CVMCOS.EmitIntValue(RecordLen - 2, 2); - if (OS.isVerboseAsm()) - CVMCOS.AddComment("Record kind: " + getTypeLeafName(RecordKind)); - CVMCOS.EmitIntValue(RecordKind, sizeof(RecordKind)); - Error E = codeview::visitTypeRecord(Record, *B, Pipeline); if (E) { @@ -682,13 +662,6 @@ void CodeViewDebug::emitTypeInformation() { llvm_unreachable("produced malformed type record"); } - if (OS.isVerboseAsm()) { - // emitRawComment will insert its own tab and comment string before - // the first line, so strip off our first one. It also prints its own - // newline. - OS.emitRawComment( - CommentOS.str().drop_front(CommentPrefix.size() - 1).rtrim()); - } B = Table.getNext(*B); } } @@ -1135,7 +1108,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, if (!BeginLabel->isDefined() || !EndLabel->isDefined()) continue; - DIType *DITy = std::get<2>(HeapAllocSite); + const DIType *DITy = std::get<2>(HeapAllocSite); MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE); OS.AddComment("Call site offset"); OS.EmitCOFFSecRel32(BeginLabel, /*Offset=*/0); @@ -1363,7 +1336,7 @@ void CodeViewDebug::beginFunctionImpl(const MachineFunction *MF) { const TargetRegisterInfo *TRI = TSI.getRegisterInfo(); const MachineFrameInfo &MFI = MF->getFrameInfo(); const Function &GV = MF->getFunction(); - auto Insertion = FnDebugInfo.insert({&GV, llvm::make_unique<FunctionInfo>()}); + auto Insertion = FnDebugInfo.insert({&GV, std::make_unique<FunctionInfo>()}); assert(Insertion.second && "function already has info"); CurFn = Insertion.first->second.get(); CurFn->FuncId = NextFuncId++; @@ -2633,17 +2606,6 @@ void CodeViewDebug::emitLocalVariableList(const FunctionInfo &FI, emitLocalVariable(FI, L); } -/// Only call this on endian-specific types like ulittle16_t and little32_t, or -/// structs composed of them. -template <typename T> -static void copyBytesForDefRange(SmallString<20> &BytePrefix, - SymbolKind SymKind, const T &DefRangeHeader) { - BytePrefix.resize(2 + sizeof(T)); - ulittle16_t SymKindLE = ulittle16_t(SymKind); - memcpy(&BytePrefix[0], &SymKindLE, 2); - memcpy(&BytePrefix[2], &DefRangeHeader, sizeof(T)); -} - void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI, const LocalVariable &Var) { // LocalSym record, see SymbolRecord.h for more info. @@ -2692,8 +2654,9 @@ void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI, (bool(Flags & LocalSymFlags::IsParameter) ? (EncFP == FI.EncodedParamFramePtrReg) : (EncFP == FI.EncodedLocalFramePtrReg))) { - little32_t FPOffset = little32_t(Offset); - copyBytesForDefRange(BytePrefix, S_DEFRANGE_FRAMEPOINTER_REL, FPOffset); + DefRangeFramePointerRelHeader DRHdr; + DRHdr.Offset = Offset; + OS.EmitCVDefRangeDirective(DefRange.Ranges, DRHdr); } else { uint16_t RegRelFlags = 0; if (DefRange.IsSubfield) { @@ -2701,28 +2664,27 @@ void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI, (DefRange.StructOffset << DefRangeRegisterRelSym::OffsetInParentShift); } - DefRangeRegisterRelSym::Header DRHdr; + DefRangeRegisterRelHeader DRHdr; DRHdr.Register = Reg; DRHdr.Flags = RegRelFlags; DRHdr.BasePointerOffset = Offset; - copyBytesForDefRange(BytePrefix, S_DEFRANGE_REGISTER_REL, DRHdr); + OS.EmitCVDefRangeDirective(DefRange.Ranges, DRHdr); } } else { assert(DefRange.DataOffset == 0 && "unexpected offset into register"); if (DefRange.IsSubfield) { - DefRangeSubfieldRegisterSym::Header DRHdr; + DefRangeSubfieldRegisterHeader DRHdr; DRHdr.Register = DefRange.CVRegister; DRHdr.MayHaveNoName = 0; DRHdr.OffsetInParent = DefRange.StructOffset; - copyBytesForDefRange(BytePrefix, S_DEFRANGE_SUBFIELD_REGISTER, DRHdr); + OS.EmitCVDefRangeDirective(DefRange.Ranges, DRHdr); } else { - DefRangeRegisterSym::Header DRHdr; + DefRangeRegisterHeader DRHdr; DRHdr.Register = DefRange.CVRegister; DRHdr.MayHaveNoName = 0; - copyBytesForDefRange(BytePrefix, S_DEFRANGE_REGISTER, DRHdr); + OS.EmitCVDefRangeDirective(DefRange.Ranges, DRHdr); } } - OS.EmitCVDefRangeDirective(DefRange.Ranges, BytePrefix); } } @@ -2896,6 +2858,14 @@ void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) { CurFn = nullptr; } +// Usable locations are valid with non-zero line numbers. A line number of zero +// corresponds to optimized code that doesn't have a distinct source location. +// In this case, we try to use the previous or next source location depending on +// the context. +static bool isUsableDebugLoc(DebugLoc DL) { + return DL && DL.getLine() != 0; +} + void CodeViewDebug::beginInstruction(const MachineInstr *MI) { DebugHandlerBase::beginInstruction(MI); @@ -2907,19 +2877,21 @@ void CodeViewDebug::beginInstruction(const MachineInstr *MI) { // If the first instruction of a new MBB has no location, find the first // instruction with a location and use that. DebugLoc DL = MI->getDebugLoc(); - if (!DL && MI->getParent() != PrevInstBB) { + if (!isUsableDebugLoc(DL) && MI->getParent() != PrevInstBB) { for (const auto &NextMI : *MI->getParent()) { if (NextMI.isDebugInstr()) continue; DL = NextMI.getDebugLoc(); - if (DL) + if (isUsableDebugLoc(DL)) break; } + // FIXME: Handle the case where the BB has no valid locations. This would + // probably require doing a real dataflow analysis. } PrevInstBB = MI->getParent(); // If we still don't have a debug location, don't record a location. - if (!DL) + if (!isUsableDebugLoc(DL)) return; maybeRecordLocation(DL, Asm->MF); @@ -3026,7 +2998,7 @@ void CodeViewDebug::collectGlobalVariableInfo() { auto Insertion = ScopeGlobals.insert( {Scope, std::unique_ptr<GlobalVariableList>()}); if (Insertion.second) - Insertion.first->second = llvm::make_unique<GlobalVariableList>(); + Insertion.first->second = std::make_unique<GlobalVariableList>(); VariableList = Insertion.first->second.get(); } else if (GV->hasComdat()) // Emit this global variable into a COMDAT section. |