diff options
Diffstat (limited to 'contrib/llvm/lib/CodeGen/AsmPrinter')
36 files changed, 2223 insertions, 1315 deletions
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp index 20b0b8d3feab..95875ccb8a0b 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp @@ -23,6 +23,7 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include <algorithm> #include <cstddef> #include <cstdint> @@ -553,19 +554,31 @@ void llvm::emitDWARF5AccelTable( AsmPrinter *Asm, AccelTable<DWARF5AccelTableData> &Contents, const DwarfDebug &DD, ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs) { std::vector<MCSymbol *> CompUnits; + SmallVector<unsigned, 1> CUIndex(CUs.size()); + int Count = 0; for (const auto &CU : enumerate(CUs)) { + if (CU.value()->getCUNode()->getNameTableKind() == + DICompileUnit::DebugNameTableKind::None) + continue; + CUIndex[CU.index()] = Count++; assert(CU.index() == CU.value()->getUniqueID()); const DwarfCompileUnit *MainCU = DD.useSplitDwarf() ? CU.value()->getSkeleton() : CU.value().get(); CompUnits.push_back(MainCU->getLabelBegin()); } + if (CompUnits.empty()) + return; + + Asm->OutStreamer->SwitchSection( + Asm->getObjFileLowering().getDwarfDebugNamesSection()); + Contents.finalize(Asm, "names"); Dwarf5AccelTableWriter<DWARF5AccelTableData>( Asm, Contents, CompUnits, - [&DD](const DWARF5AccelTableData &Entry) { + [&](const DWARF5AccelTableData &Entry) { const DIE *CUDie = Entry.getDie().getUnitDie(); - return DD.lookupCU(CUDie)->getUniqueID(); + return CUIndex[DD.lookupCU(CUDie)->getUniqueID()]; }) .emit(); } diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp index c8305ad9c547..042243b79259 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp @@ -27,29 +27,35 @@ unsigned AddressPool::getIndex(const MCSymbol *Sym, bool TLS) { void AddressPool::emitHeader(AsmPrinter &Asm, MCSection *Section) { static const uint8_t AddrSize = Asm.getDataLayout().getPointerSize(); - Asm.OutStreamer->SwitchSection(Section); - uint64_t Length = sizeof(uint16_t) // version + sizeof(uint8_t) // address_size + sizeof(uint8_t) // segment_selector_size + AddrSize * Pool.size(); // entries + Asm.OutStreamer->AddComment("Length of contribution"); Asm.emitInt32(Length); // TODO: Support DWARF64 format. + Asm.OutStreamer->AddComment("DWARF version number"); Asm.emitInt16(Asm.getDwarfVersion()); + Asm.OutStreamer->AddComment("Address size"); Asm.emitInt8(AddrSize); + Asm.OutStreamer->AddComment("Segment selector size"); Asm.emitInt8(0); // TODO: Support non-zero segment_selector_size. } // Emit addresses into the section given. void AddressPool::emit(AsmPrinter &Asm, MCSection *AddrSection) { - if (Asm.getDwarfVersion() >= 5) - emitHeader(Asm, AddrSection); - - if (Pool.empty()) + if (isEmpty()) return; // Start the dwarf addr section. Asm.OutStreamer->SwitchSection(AddrSection); + if (Asm.getDwarfVersion() >= 5) + emitHeader(Asm, AddrSection); + + // Define the symbol that marks the start of the contribution. + // It is referenced via DW_AT_addr_base. + Asm.OutStreamer->EmitLabel(AddressTableBaseSym); + // Order the address pool entries by ID SmallVector<const MCExpr *, 64> Entries(Pool.size()); diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.h b/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.h index d5008fab5563..2209c7eb50ed 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.h @@ -51,8 +51,14 @@ public: void resetUsedFlag() { HasBeenUsed = false; } + MCSymbol *getLabel() { return AddressTableBaseSym; } + void setLabel(MCSymbol *Sym) { AddressTableBaseSym = Sym; } + private: void emitHeader(AsmPrinter &Asm, MCSection *Section); + + /// Symbol designates the start of the contribution to the address table. + MCSymbol *AddressTableBaseSym = nullptr; }; } // end namespace llvm diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 9bbc77b3056b..7070451e3330 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -12,10 +12,10 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/AsmPrinter.h" -#include "AsmPrinterHandler.h" #include "CodeViewDebug.h" #include "DwarfDebug.h" #include "DwarfException.h" +#include "WasmException.h" #include "WinCFGuard.h" #include "WinException.h" #include "llvm/ADT/APFloat.h" @@ -32,8 +32,10 @@ #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" +#include "llvm/BinaryFormat/COFF.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/BinaryFormat/ELF.h" +#include "llvm/CodeGen/AsmPrinterHandler.h" #include "llvm/CodeGen/GCMetadata.h" #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/GCStrategy.h" @@ -52,6 +54,7 @@ #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" +#include "llvm/CodeGen/StackMaps.h" #include "llvm/CodeGen/TargetFrameLowering.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetLowering.h" @@ -260,7 +263,7 @@ bool AsmPrinter::doInitialization(Module &M) { // use the directive, where it would need the same conditionalization // anyway. const Triple &Target = TM.getTargetTriple(); - OutStreamer->EmitVersionForTarget(Target); + OutStreamer->EmitVersionForTarget(Target, M.getSDKVersion()); // Allow the target to emit any magic that it wants at the start of the file. EmitStartOfAsmFile(M); @@ -355,7 +358,7 @@ bool AsmPrinter::doInitialization(Module &M) { } break; case ExceptionHandling::Wasm: - // TODO to prevent warning + ES = new WasmException(this); break; } if (ES) @@ -363,7 +366,7 @@ bool AsmPrinter::doInitialization(Module &M) { DWARFGroupName, DWARFGroupDescription)); if (mdconst::extract_or_null<ConstantInt>( - MMI->getModule()->getModuleFlag("cfguard"))) + MMI->getModule()->getModuleFlag("cfguardtable"))) Handlers.push_back(HandlerInfo(new WinCFGuard(this), CFGuardName, CFGuardDescription, DWARFGroupName, DWARFGroupDescription)); @@ -627,8 +630,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { /// /// \p Value - The value to emit. /// \p Size - The size of the integer (in bytes) to emit. -void AsmPrinter::EmitDebugThreadLocal(const MCExpr *Value, - unsigned Size) const { +void AsmPrinter::EmitDebugValue(const MCExpr *Value, unsigned Size) const { OutStreamer->EmitValue(Value, Size); } @@ -749,18 +751,30 @@ static bool emitComments(const MachineInstr &MI, raw_ostream &CommentOS, const MachineFrameInfo &MFI = MF->getFrameInfo(); bool Commented = false; + auto getSize = + [&MFI](const SmallVectorImpl<const MachineMemOperand *> &Accesses) { + unsigned Size = 0; + for (auto A : Accesses) + if (MFI.isSpillSlotObjectIndex( + cast<FixedStackPseudoSourceValue>(A->getPseudoValue()) + ->getFrameIndex())) + Size += A->getSize(); + return Size; + }; + // We assume a single instruction only has a spill or reload, not // both. const MachineMemOperand *MMO; + SmallVector<const MachineMemOperand *, 2> Accesses; if (TII->isLoadFromStackSlotPostFE(MI, FI)) { if (MFI.isSpillSlotObjectIndex(FI)) { MMO = *MI.memoperands_begin(); CommentOS << MMO->getSize() << "-byte Reload"; Commented = true; } - } else if (TII->hasLoadFromStackSlot(MI, MMO, FI)) { - if (MFI.isSpillSlotObjectIndex(FI)) { - CommentOS << MMO->getSize() << "-byte Folded Reload"; + } else if (TII->hasLoadFromStackSlot(MI, Accesses)) { + if (auto Size = getSize(Accesses)) { + CommentOS << Size << "-byte Folded Reload"; Commented = true; } } else if (TII->isStoreToStackSlotPostFE(MI, FI)) { @@ -769,9 +783,9 @@ static bool emitComments(const MachineInstr &MI, raw_ostream &CommentOS, CommentOS << MMO->getSize() << "-byte Spill"; Commented = true; } - } else if (TII->hasStoreToStackSlot(MI, MMO, FI)) { - if (MFI.isSpillSlotObjectIndex(FI)) { - CommentOS << MMO->getSize() << "-byte Folded Spill"; + } else if (TII->hasStoreToStackSlot(MI, Accesses)) { + if (auto Size = getSize(Accesses)) { + CommentOS << Size << "-byte Folded Spill"; Commented = true; } } @@ -1066,6 +1080,10 @@ void AsmPrinter::EmitFunctionBody() { ++NumInstsInFunction; } + // If there is a pre-instruction symbol, emit a label for it here. + if (MCSymbol *S = MI.getPreInstrSymbol()) + OutStreamer->EmitLabel(S); + if (ShouldPrintDebugScopes) { for (const HandlerInfo &HI : Handlers) { NamedRegionTimer T(HI.TimerName, HI.TimerDescription, @@ -1117,6 +1135,10 @@ void AsmPrinter::EmitFunctionBody() { break; } + // If there is a post-instruction symbol, emit a label for it here. + if (MCSymbol *S = MI.getPostInstrSymbol()) + OutStreamer->EmitLabel(S); + if (ShouldPrintDebugScopes) { for (const HandlerInfo &HI : Handlers) { NamedRegionTimer T(HI.TimerName, HI.TimerDescription, @@ -1394,6 +1416,33 @@ bool AsmPrinter::doFinalization(Module &M) { } } + if (TM.getTargetTriple().isOSBinFormatCOFF()) { + MachineModuleInfoCOFF &MMICOFF = + MMI->getObjFileInfo<MachineModuleInfoCOFF>(); + + // Output stubs for external and common global variables. + MachineModuleInfoCOFF::SymbolListTy Stubs = MMICOFF.GetGVStubList(); + if (!Stubs.empty()) { + const DataLayout &DL = M.getDataLayout(); + + for (const auto &Stub : Stubs) { + SmallString<256> SectionName = StringRef(".rdata$"); + SectionName += Stub.first->getName(); + OutStreamer->SwitchSection(OutContext.getCOFFSection( + SectionName, + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_LNK_COMDAT, + SectionKind::getReadOnly(), Stub.first->getName(), + COFF::IMAGE_COMDAT_SELECT_ANY)); + EmitAlignment(Log2_32(DL.getPointerSize())); + OutStreamer->EmitSymbolAttribute(Stub.first, MCSA_Global); + OutStreamer->EmitLabel(Stub.first); + OutStreamer->EmitSymbolValue(Stub.second.getPointer(), + DL.getPointerSize()); + } + } + } + // Finalize debug and EH information. for (const HandlerInfo &HI : Handlers) { NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName, @@ -1450,6 +1499,9 @@ bool AsmPrinter::doFinalization(Module &M) { // Emit llvm.ident metadata in an '.ident' directive. EmitModuleIdents(M); + // Emit bytes for llvm.commandline metadata. + EmitModuleCommandLines(M); + // Emit __morestack address if needed for indirect calls. if (MMI->usesMorestackAddr()) { unsigned Align = 1; @@ -1534,7 +1586,8 @@ bool AsmPrinter::doFinalization(Module &M) { // Emit address-significance attributes for all globals. OutStreamer->EmitAddrsig(); for (const GlobalValue &GV : M.global_values()) - if (!GV.isThreadLocal() && !GV.getName().startswith("llvm.") && + if (!GV.use_empty() && !GV.isThreadLocal() && + !GV.hasDLLImportStorageClass() && !GV.getName().startswith("llvm.") && !GV.hasAtLeastLocalUnnamedAddr()) OutStreamer->EmitAddrsigSym(getSymbol(&GV)); } @@ -1958,6 +2011,29 @@ void AsmPrinter::EmitModuleIdents(Module &M) { } } +void AsmPrinter::EmitModuleCommandLines(Module &M) { + MCSection *CommandLine = getObjFileLowering().getSectionForCommandLines(); + if (!CommandLine) + return; + + const NamedMDNode *NMD = M.getNamedMetadata("llvm.commandline"); + if (!NMD || !NMD->getNumOperands()) + return; + + OutStreamer->PushSection(); + OutStreamer->SwitchSection(CommandLine); + OutStreamer->EmitZeros(1); + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + const MDNode *N = NMD->getOperand(i); + assert(N->getNumOperands() == 1 && + "llvm.commandline metadata entry can have only one operand"); + const MDString *S = cast<MDString>(N->getOperand(0)); + OutStreamer->EmitBytes(S->getString()); + OutStreamer->EmitZeros(1); + } + OutStreamer->PopSection(); +} + //===--------------------------------------------------------------------===// // Emission and print routines // @@ -2927,11 +3003,6 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy &S) { if (!S.usesMetadata()) return nullptr; - assert(!S.useStatepoints() && "statepoints do not currently support custom" - " stackmap formats, please see the documentation for a description of" - " the default format. If you really need a custom serialized format," - " please file a bug"); - gcp_map_type &GCMap = getGCMap(GCMetadataPrinters); gcp_map_type::iterator GCPI = GCMap.find(&S); if (GCPI != GCMap.end()) @@ -2952,6 +3023,27 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy &S) { report_fatal_error("no GCMetadataPrinter registered for GC: " + Twine(Name)); } +void AsmPrinter::emitStackMaps(StackMaps &SM) { + GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>(); + assert(MI && "AsmPrinter didn't require GCModuleInfo?"); + bool NeedsDefault = false; + if (MI->begin() == MI->end()) + // No GC strategy, use the default format. + NeedsDefault = true; + else + for (auto &I : *MI) { + if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*I)) + if (MP->emitStackMaps(SM, *this)) + continue; + // The strategy doesn't have printer or doesn't emit custom stack maps. + // Use the default format. + NeedsDefault = true; + } + + if (NeedsDefault) + SM.serializeToStackMapSection(); +} + /// Pin vtable to this file. AsmPrinterHandler::~AsmPrinterHandler() = default; diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp index 605588470670..afce3ad3133b 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -212,6 +212,9 @@ void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const { case MCCFIInstruction::OpWindowSave: OutStreamer->EmitCFIWindowSave(); break; + case MCCFIInstruction::OpNegateRAState: + OutStreamer->EmitCFINegateRAState(); + break; case MCCFIInstruction::OpSameValue: OutStreamer->EmitCFISameValue(Inst.getRegister()); break; diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h deleted file mode 100644 index f5ac95a20b10..000000000000 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h +++ /dev/null @@ -1,74 +0,0 @@ -//===-- lib/CodeGen/AsmPrinter/AsmPrinterHandler.h -------------*- C++ -*--===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains a generic interface for AsmPrinter handlers, -// like debug and EH info emitters. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_ASMPRINTERHANDLER_H -#define LLVM_LIB_CODEGEN_ASMPRINTER_ASMPRINTERHANDLER_H - -#include "llvm/Support/DataTypes.h" - -namespace llvm { - -class AsmPrinter; -class MachineBasicBlock; -class MachineFunction; -class MachineInstr; -class MCSymbol; - -typedef MCSymbol *ExceptionSymbolProvider(AsmPrinter *Asm); - -/// Collects and handles AsmPrinter objects required to build debug -/// or EH information. -class AsmPrinterHandler { -public: - virtual ~AsmPrinterHandler(); - - /// For symbols that have a size designated (e.g. common symbols), - /// this tracks that size. - virtual void setSymbolSize(const MCSymbol *Sym, uint64_t Size) = 0; - - /// Emit all sections that should come after the content. - virtual void endModule() = 0; - - /// Gather pre-function debug information. - /// Every beginFunction(MF) call should be followed by an endFunction(MF) - /// call. - virtual void beginFunction(const MachineFunction *MF) = 0; - - // Emit any of function marker (like .cfi_endproc). This is called - // before endFunction and cannot switch sections. - virtual void markFunctionEnd(); - - /// Gather post-function debug information. - /// Please note that some AsmPrinter implementations may not call - /// beginFunction at all. - virtual void endFunction(const MachineFunction *MF) = 0; - - virtual void beginFragment(const MachineBasicBlock *MBB, - ExceptionSymbolProvider ESP) {} - virtual void endFragment() {} - - /// Emit target-specific EH funclet machinery. - virtual void beginFunclet(const MachineBasicBlock &MBB, - MCSymbol *Sym = nullptr) {} - virtual void endFunclet() {} - - /// Process beginning of an instruction. - virtual void beginInstruction(const MachineInstr *MI) = 0; - - /// Process end of an instruction. - virtual void endInstruction() = 0; -}; -} // End of namespace llvm - -#endif diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index 4159eb19423a..62103e3107c0 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -71,6 +71,42 @@ static void srcMgrDiagHandler(const SMDiagnostic &Diag, void *diagInfo) { DiagInfo->DiagHandler(Diag, DiagInfo->DiagContext, LocCookie); } +unsigned AsmPrinter::addInlineAsmDiagBuffer(StringRef AsmStr, + const MDNode *LocMDNode) const { + if (!DiagInfo) { + DiagInfo = make_unique<SrcMgrDiagInfo>(); + + MCContext &Context = MMI->getContext(); + Context.setInlineSourceManager(&DiagInfo->SrcMgr); + + LLVMContext &LLVMCtx = MMI->getModule()->getContext(); + if (LLVMCtx.getInlineAsmDiagnosticHandler()) { + DiagInfo->DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler(); + DiagInfo->DiagContext = LLVMCtx.getInlineAsmDiagnosticContext(); + DiagInfo->SrcMgr.setDiagHandler(srcMgrDiagHandler, DiagInfo.get()); + } + } + + SourceMgr &SrcMgr = DiagInfo->SrcMgr; + + std::unique_ptr<MemoryBuffer> Buffer; + // The inline asm source manager will outlive AsmStr, so make a copy of the + // string for SourceMgr to own. + Buffer = MemoryBuffer::getMemBufferCopy(AsmStr, "<inline asm>"); + + // Tell SrcMgr about this buffer, it takes ownership of the buffer. + unsigned BufNum = SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); + + // Store LocMDNode in DiagInfo, using BufNum as an identifier. + if (LocMDNode) { + DiagInfo->LocInfos.resize(BufNum); + DiagInfo->LocInfos[BufNum - 1] = LocMDNode; + } + + return BufNum; +} + + /// EmitInlineAsm - Emit a blob of inline asm to the output streamer. void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, const MCTargetOptions &MCOptions, @@ -98,39 +134,11 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, return; } - if (!DiagInfo) { - DiagInfo = make_unique<SrcMgrDiagInfo>(); + unsigned BufNum = addInlineAsmDiagBuffer(Str, LocMDNode); + DiagInfo->SrcMgr.setIncludeDirs(MCOptions.IASSearchPaths); - MCContext &Context = MMI->getContext(); - Context.setInlineSourceManager(&DiagInfo->SrcMgr); - - LLVMContext &LLVMCtx = MMI->getModule()->getContext(); - if (LLVMCtx.getInlineAsmDiagnosticHandler()) { - DiagInfo->DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler(); - DiagInfo->DiagContext = LLVMCtx.getInlineAsmDiagnosticContext(); - DiagInfo->SrcMgr.setDiagHandler(srcMgrDiagHandler, DiagInfo.get()); - } - } - - SourceMgr &SrcMgr = DiagInfo->SrcMgr; - SrcMgr.setIncludeDirs(MCOptions.IASSearchPaths); - - std::unique_ptr<MemoryBuffer> Buffer; - // The inline asm source manager will outlive Str, so make a copy of the - // string for SourceMgr to own. - Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>"); - - // Tell SrcMgr about this buffer, it takes ownership of the buffer. - unsigned BufNum = SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); - - // Store LocMDNode in DiagInfo, using BufNum as an identifier. - if (LocMDNode) { - DiagInfo->LocInfos.resize(BufNum); - DiagInfo->LocInfos[BufNum-1] = LocMDNode; - } - - std::unique_ptr<MCAsmParser> Parser( - createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI, BufNum)); + std::unique_ptr<MCAsmParser> Parser(createMCAsmParser( + DiagInfo->SrcMgr, OutContext, *OutStreamer, *MAI, BufNum)); // Do not use assembler-level information for parsing inline assembly. OutStreamer->setUseAssemblerInfoForParsing(false); @@ -148,9 +156,10 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, Parser->setAssemblerDialect(Dialect); Parser->setTargetParser(*TAP.get()); Parser->setEnablePrintSchedInfo(EnablePrintSchedInfo); + // Enable lexing Masm binary and hex integer literals in intel inline + // assembly. if (Dialect == InlineAsm::AD_Intel) - // We need this flag to be able to parse numbers like "0bH" - Parser->setParsingInlineAsm(true); + Parser->getLexer().setLexMasmIntegers(true); if (MF) { const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); TAP->SetFrameRegister(TRI->getFrameRegister(*MF)); @@ -519,6 +528,44 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { MCOptions.SanitizeAddress = MF->getFunction().hasFnAttribute(Attribute::SanitizeAddress); + // Emit warnings if we use reserved registers on the clobber list, as + // that might give surprising results. + std::vector<std::string> RestrRegs; + // Start with the first operand descriptor, and iterate over them. + for (unsigned I = InlineAsm::MIOp_FirstOperand, NumOps = MI->getNumOperands(); + I < NumOps; ++I) { + const MachineOperand &MO = MI->getOperand(I); + if (MO.isImm()) { + unsigned Flags = MO.getImm(); + const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); + if (InlineAsm::getKind(Flags) == InlineAsm::Kind_Clobber && + !TRI->isAsmClobberable(*MF, MI->getOperand(I + 1).getReg())) { + RestrRegs.push_back(TRI->getName(MI->getOperand(I + 1).getReg())); + } + // Skip to one before the next operand descriptor, if it exists. + I += InlineAsm::getNumOperandRegisters(Flags); + } + } + + if (!RestrRegs.empty()) { + unsigned BufNum = addInlineAsmDiagBuffer(OS.str(), LocMD); + auto &SrcMgr = DiagInfo->SrcMgr; + SMLoc Loc = SMLoc::getFromPointer( + SrcMgr.getMemoryBuffer(BufNum)->getBuffer().begin()); + + std::string Msg = "inline asm clobber list contains reserved registers: "; + for (auto I = RestrRegs.begin(), E = RestrRegs.end(); I != E; I++) { + if(I != RestrRegs.begin()) + Msg += ", "; + Msg += *I; + } + std::string Note = "Reserved registers on the clobber list may not be " + "preserved across the asm statement, and clobbering them may " + "lead to undefined behaviour."; + SrcMgr.PrintMessage(Loc, SourceMgr::DK_Warning, Msg); + SrcMgr.PrintMessage(Loc, SourceMgr::DK_Note, Note); + } + EmitInlineAsm(OS.str(), getSubtargetInfo(), MCOptions, LocMD, MI->getInlineAsmDialect()); diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 8c5c5478d01a..8cabad4ad312 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -31,6 +31,7 @@ #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/LexicalScopes.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineModuleInfo.h" @@ -43,6 +44,7 @@ #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h" #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/EnumTables.h" #include "llvm/DebugInfo/CodeView/Line.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" @@ -72,6 +74,7 @@ #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/Path.h" #include "llvm/Support/SMLoc.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Target/TargetLoweringObjectFile.h" @@ -90,8 +93,20 @@ using namespace llvm; using namespace llvm::codeview; -static cl::opt<bool> EmitDebugGlobalHashes("emit-codeview-ghash-section", - cl::ReallyHidden, cl::init(false)); +static CPUType mapArchToCVCPUType(Triple::ArchType Type) { + switch (Type) { + case Triple::ArchType::x86: + return CPUType::Pentium3; + case Triple::ArchType::x86_64: + return CPUType::X64; + case Triple::ArchType::thumb: + return CPUType::Thumb; + case Triple::ArchType::aarch64: + return CPUType::ARM64; + default: + report_fatal_error("target architecture doesn't map to a CodeView CPUType"); + } +} CodeViewDebug::CodeViewDebug(AsmPrinter *AP) : DebugHandlerBase(AP), OS(*Asm->OutStreamer), TypeTable(Allocator) { @@ -100,11 +115,21 @@ CodeViewDebug::CodeViewDebug(AsmPrinter *AP) if (!MMI->getModule()->getNamedMetadata("llvm.dbg.cu") || !AP->getObjFileLowering().getCOFFDebugSymbolsSection()) { Asm = nullptr; + MMI->setDebugInfoAvailability(false); return; } - // Tell MMI that we have debug info. MMI->setDebugInfoAvailability(true); + + TheCPU = + mapArchToCVCPUType(Triple(MMI->getModule()->getTargetTriple()).getArch()); + + collectGlobalVariableInfo(); + + // Check if we should emit type record hashes. + ConstantInt *GH = mdconst::extract_or_null<ConstantInt>( + MMI->getModule()->getModuleFlag("CodeViewGHash")); + EmitDebugGlobalHashes = GH && !GH->isZero(); } StringRef CodeViewDebug::getFullFilepath(const DIFile *File) { @@ -116,7 +141,9 @@ StringRef CodeViewDebug::getFullFilepath(const DIFile *File) { // If this is a Unix-style path, just use it as is. Don't try to canonicalize // it textually because one of the path components could be a symlink. - if (!Dir.empty() && Dir[0] == '/') { + if (Dir.startswith("/") || Filename.startswith("/")) { + if (llvm::sys::path::is_absolute(Filename, llvm::sys::path::Style::posix)) + return Filename; Filepath = Dir; if (Dir.back() != '/') Filepath += '/'; @@ -337,6 +364,36 @@ TypeIndex CodeViewDebug::getFuncIdForSubprogram(const DISubprogram *SP) { return recordTypeIndexForDINode(SP, TI); } +static bool isTrivial(const DICompositeType *DCTy) { + return ((DCTy->getFlags() & DINode::FlagTrivial) == DINode::FlagTrivial); +} + +static FunctionOptions +getFunctionOptions(const DISubroutineType *Ty, + const DICompositeType *ClassTy = nullptr, + StringRef SPName = StringRef("")) { + FunctionOptions FO = FunctionOptions::None; + const DIType *ReturnTy = nullptr; + if (auto TypeArray = Ty->getTypeArray()) { + if (TypeArray.size()) + ReturnTy = TypeArray[0].resolve(); + } + + if (auto *ReturnDCTy = dyn_cast_or_null<DICompositeType>(ReturnTy)) { + if (!isTrivial(ReturnDCTy)) + FO |= FunctionOptions::CxxReturnUdt; + } + + // DISubroutineType is unnamed. Use DISubprogram's i.e. SPName in comparison. + if (ClassTy && !isTrivial(ClassTy) && SPName == ClassTy->getName()) { + FO |= FunctionOptions::Constructor; + + // TODO: put the FunctionOptions::ConstructorWithVirtualBases flag. + + } + return FO; +} + TypeIndex CodeViewDebug::getMemberFunctionType(const DISubprogram *SP, const DICompositeType *Class) { // Always use the method declaration as the key for the function type. The @@ -356,8 +413,10 @@ TypeIndex CodeViewDebug::getMemberFunctionType(const DISubprogram *SP, // member function type. TypeLoweringScope S(*this); const bool IsStaticMethod = (SP->getFlags() & DINode::FlagStaticMember) != 0; + + FunctionOptions FO = getFunctionOptions(SP->getType(), Class, SP->getName()); TypeIndex TI = lowerTypeMemberFunction( - SP->getType(), Class, SP->getThisAdjustment(), IsStaticMethod); + SP->getType(), Class, SP->getThisAdjustment(), IsStaticMethod, FO); return recordTypeIndexForDINode(SP, TI, Class); } @@ -508,6 +567,11 @@ void CodeViewDebug::endModule() { OS.AddComment("String table"); 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 + // particular reason for this ordering other than to match MSVC. + emitBuildInfo(); + // Emit type information and hashes last, so that any types we translate while // emitting function info are included. emitTypeInformation(); @@ -669,30 +733,8 @@ static Version parseVersion(StringRef Name) { return V; } -static CPUType mapArchToCVCPUType(Triple::ArchType Type) { - switch (Type) { - case Triple::ArchType::x86: - return CPUType::Pentium3; - case Triple::ArchType::x86_64: - return CPUType::X64; - case Triple::ArchType::thumb: - return CPUType::Thumb; - case Triple::ArchType::aarch64: - return CPUType::ARM64; - default: - report_fatal_error("target architecture doesn't map to a CodeView CPUType"); - } -} - void CodeViewDebug::emitCompilerInformation() { - MCContext &Context = MMI->getContext(); - MCSymbol *CompilerBegin = Context.createTempSymbol(), - *CompilerEnd = Context.createTempSymbol(); - OS.AddComment("Record length"); - OS.emitAbsoluteSymbolDiff(CompilerEnd, CompilerBegin, 2); - OS.EmitLabel(CompilerBegin); - OS.AddComment("Record kind: S_COMPILE3"); - OS.EmitIntValue(SymbolKind::S_COMPILE3, 2); + MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_COMPILE3); uint32_t Flags = 0; NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu"); @@ -707,9 +749,7 @@ void CodeViewDebug::emitCompilerInformation() { OS.EmitIntValue(Flags, 4); OS.AddComment("CPUType"); - CPUType CPU = - mapArchToCVCPUType(Triple(MMI->getModule()->getTargetTriple()).getArch()); - OS.EmitIntValue(static_cast<uint64_t>(CPU), 2); + OS.EmitIntValue(static_cast<uint64_t>(TheCPU), 2); StringRef CompilerVersion = CU->getProducer(); Version FrontVer = parseVersion(CompilerVersion); @@ -733,7 +773,48 @@ void CodeViewDebug::emitCompilerInformation() { OS.AddComment("Null-terminated compiler version string"); emitNullTerminatedSymbolName(OS, CompilerVersion); - OS.EmitLabel(CompilerEnd); + endSymbolRecord(CompilerEnd); +} + +static TypeIndex getStringIdTypeIdx(GlobalTypeTableBuilder &TypeTable, + StringRef S) { + StringIdRecord SIR(TypeIndex(0x0), S); + return TypeTable.writeLeafType(SIR); +} + +void CodeViewDebug::emitBuildInfo() { + // First, make LF_BUILDINFO. It's a sequence of strings with various bits of + // build info. The known prefix is: + // - Absolute path of current directory + // - Compiler path + // - Main source file path, relative to CWD or absolute + // - Type server PDB file + // - Canonical compiler command line + // If frontend and backend compilation are separated (think llc or LTO), it's + // not clear if the compiler path should refer to the executable for the + // frontend or the backend. Leave it blank for now. + TypeIndex BuildInfoArgs[BuildInfoRecord::MaxArgs] = {}; + NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu"); + const MDNode *Node = *CUs->operands().begin(); // FIXME: Multiple CUs. + const auto *CU = cast<DICompileUnit>(Node); + const DIFile *MainSourceFile = CU->getFile(); + BuildInfoArgs[BuildInfoRecord::CurrentDirectory] = + getStringIdTypeIdx(TypeTable, MainSourceFile->getDirectory()); + BuildInfoArgs[BuildInfoRecord::SourceFile] = + getStringIdTypeIdx(TypeTable, MainSourceFile->getFilename()); + // FIXME: Path to compiler and command line. PDB is intentionally blank unless + // we implement /Zi type servers. + BuildInfoRecord BIR(BuildInfoArgs); + TypeIndex BuildInfoIndex = TypeTable.writeLeafType(BIR); + + // Make a new .debug$S subsection for the S_BUILDINFO record, which points + // from the module symbols into the type stream. + MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols); + MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO); + OS.AddComment("LF_BUILDINFO index"); + OS.EmitIntValue(BuildInfoIndex.getIndex(), 4); + endSymbolRecord(BIEnd); + endCVSubsection(BISubsecEnd); } void CodeViewDebug::emitInlineeLinesSubsection() { @@ -773,18 +854,11 @@ void CodeViewDebug::emitInlineeLinesSubsection() { void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI, const DILocation *InlinedAt, const InlineSite &Site) { - MCSymbol *InlineBegin = MMI->getContext().createTempSymbol(), - *InlineEnd = MMI->getContext().createTempSymbol(); - assert(TypeIndices.count({Site.Inlinee, nullptr})); TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee, nullptr}]; // SymbolRecord - OS.AddComment("Record length"); - OS.emitAbsoluteSymbolDiff(InlineEnd, InlineBegin, 2); // RecordLength - OS.EmitLabel(InlineBegin); - OS.AddComment("Record kind: S_INLINESITE"); - OS.EmitIntValue(SymbolKind::S_INLINESITE, 2); // RecordKind + MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE); OS.AddComment("PtrParent"); OS.EmitIntValue(0, 4); @@ -799,9 +873,9 @@ void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI, OS.EmitCVInlineLinetableDirective(Site.SiteFuncId, FileId, StartLineNum, FI.Begin, FI.End); - OS.EmitLabel(InlineEnd); + endSymbolRecord(InlineEnd); - emitLocalVariableList(Site.InlinedLocals); + emitLocalVariableList(FI, Site.InlinedLocals); // Recurse on child inlined call sites before closing the scope. for (const DILocation *ChildSite : Site.ChildSites) { @@ -812,10 +886,7 @@ void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI, } // Close the scope. - OS.AddComment("Record length"); - OS.EmitIntValue(2, 2); // RecordLength - OS.AddComment("Record kind: S_INLINESITE_END"); - OS.EmitIntValue(SymbolKind::S_INLINESITE_END, 2); // RecordKind + emitEndSymbolRecord(SymbolKind::S_INLINESITE_END); } void CodeViewDebug::switchToDebugSectionForSymbol(const MCSymbol *GVSym) { @@ -850,13 +921,7 @@ void CodeViewDebug::emitDebugInfoForThunk(const Function *GV, MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols); // Emit S_THUNK32 - MCSymbol *ThunkRecordBegin = MMI->getContext().createTempSymbol(), - *ThunkRecordEnd = MMI->getContext().createTempSymbol(); - OS.AddComment("Record length"); - OS.emitAbsoluteSymbolDiff(ThunkRecordEnd, ThunkRecordBegin, 2); - OS.EmitLabel(ThunkRecordBegin); - OS.AddComment("Record kind: S_THUNK32"); - OS.EmitIntValue(unsigned(SymbolKind::S_THUNK32), 2); + MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32); OS.AddComment("PtrParent"); OS.EmitIntValue(0, 4); OS.AddComment("PtrEnd"); @@ -874,17 +939,13 @@ void CodeViewDebug::emitDebugInfoForThunk(const Function *GV, OS.AddComment("Function name"); emitNullTerminatedSymbolName(OS, FuncName); // Additional fields specific to the thunk ordinal would go here. - OS.EmitLabel(ThunkRecordEnd); + endSymbolRecord(ThunkRecordEnd); // Local variables/inlined routines are purposely omitted here. The point of // marking this as a thunk is so Visual Studio will NOT stop in this routine. // Emit S_PROC_ID_END - const unsigned RecordLengthForSymbolEnd = 2; - OS.AddComment("Record length"); - OS.EmitIntValue(RecordLengthForSymbolEnd, 2); - OS.AddComment("Record kind: S_PROC_ID_END"); - OS.EmitIntValue(unsigned(SymbolKind::S_PROC_ID_END), 2); + emitEndSymbolRecord(SymbolKind::S_PROC_ID_END); endCVSubsection(SymbolsEnd); } @@ -927,19 +988,9 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, OS.AddComment("Symbol subsection for " + Twine(FuncName)); MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols); { - MCSymbol *ProcRecordBegin = MMI->getContext().createTempSymbol(), - *ProcRecordEnd = MMI->getContext().createTempSymbol(); - OS.AddComment("Record length"); - OS.emitAbsoluteSymbolDiff(ProcRecordEnd, ProcRecordBegin, 2); - OS.EmitLabel(ProcRecordBegin); - - if (GV->hasLocalLinkage()) { - OS.AddComment("Record kind: S_LPROC32_ID"); - OS.EmitIntValue(unsigned(SymbolKind::S_LPROC32_ID), 2); - } else { - OS.AddComment("Record kind: S_GPROC32_ID"); - OS.EmitIntValue(unsigned(SymbolKind::S_GPROC32_ID), 2); - } + SymbolKind ProcKind = GV->hasLocalLinkage() ? SymbolKind::S_LPROC32_ID + : SymbolKind::S_GPROC32_ID; + MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind); // These fields are filled in by tools like CVPACK which run after the fact. OS.AddComment("PtrParent"); @@ -968,9 +1019,28 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, OS.AddComment("Function name"); // Truncate the name so we won't overflow the record length field. emitNullTerminatedSymbolName(OS, FuncName); - OS.EmitLabel(ProcRecordEnd); + endSymbolRecord(ProcRecordEnd); - emitLocalVariableList(FI.Locals); + 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.AddComment("Padding"); + OS.EmitIntValue(0, 4); + OS.AddComment("Offset of padding"); + OS.EmitIntValue(0, 4); + OS.AddComment("Bytes of callee saved registers"); + OS.EmitIntValue(FI.CSRSize, 4); + OS.AddComment("Exception handler offset"); + OS.EmitIntValue(0, 4); + OS.AddComment("Exception handler section"); + OS.EmitIntValue(0, 2); + OS.AddComment("Flags (defines frame register)"); + OS.EmitIntValue(uint32_t(FI.FrameProcOpts), 4); + endSymbolRecord(FrameProcEnd); + + emitLocalVariableList(FI, FI.Locals); + emitGlobalVariableList(FI.Globals); emitLexicalBlockList(FI.ChildBlocks, FI); // Emit inlined call site information. Only emit functions inlined directly @@ -986,13 +1056,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, for (auto Annot : FI.Annotations) { MCSymbol *Label = Annot.first; MDTuple *Strs = cast<MDTuple>(Annot.second); - MCSymbol *AnnotBegin = MMI->getContext().createTempSymbol(), - *AnnotEnd = MMI->getContext().createTempSymbol(); - OS.AddComment("Record length"); - OS.emitAbsoluteSymbolDiff(AnnotEnd, AnnotBegin, 2); - OS.EmitLabel(AnnotBegin); - OS.AddComment("Record kind: S_ANNOTATION"); - OS.EmitIntValue(SymbolKind::S_ANNOTATION, 2); + MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION); OS.EmitCOFFSecRel32(Label, /*Offset=*/0); // FIXME: Make sure we don't overflow the max record size. OS.EmitCOFFSectionIndex(Label); @@ -1004,17 +1068,14 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV, assert(Str.data()[Str.size()] == '\0' && "non-nullterminated MDString"); OS.EmitBytes(StringRef(Str.data(), Str.size() + 1)); } - OS.EmitLabel(AnnotEnd); + endSymbolRecord(AnnotEnd); } if (SP != nullptr) emitDebugInfoForUDTs(LocalUDTs); // We're done with this function. - OS.AddComment("Record length"); - OS.EmitIntValue(0x0002, 2); - OS.AddComment("Record kind: S_PROC_ID_END"); - OS.EmitIntValue(unsigned(SymbolKind::S_PROC_ID_END), 2); + emitEndSymbolRecord(SymbolKind::S_PROC_ID_END); } endCVSubsection(SymbolsEnd); @@ -1034,21 +1095,8 @@ CodeViewDebug::createDefRangeMem(uint16_t CVRegister, int Offset) { return DR; } -CodeViewDebug::LocalVarDefRange -CodeViewDebug::createDefRangeGeneral(uint16_t CVRegister, bool InMemory, - int Offset, bool IsSubfield, - uint16_t StructOffset) { - LocalVarDefRange DR; - DR.InMemory = InMemory; - DR.DataOffset = Offset; - DR.IsSubfield = IsSubfield; - DR.StructOffset = StructOffset; - DR.CVRegister = CVRegister; - return DR; -} - void CodeViewDebug::collectVariableInfoFromMFTable( - DenseSet<InlinedVariable> &Processed) { + DenseSet<InlinedEntity> &Processed) { const MachineFunction &MF = *Asm->MF; const TargetSubtargetInfo &TSI = MF.getSubtarget(); const TargetFrameLowering *TFI = TSI.getFrameLowering(); @@ -1060,7 +1108,7 @@ void CodeViewDebug::collectVariableInfoFromMFTable( assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) && "Expected inlined-at fields to agree"); - Processed.insert(InlinedVariable(VI.Var, VI.Loc->getInlinedAt())); + Processed.insert(InlinedEntity(VI.Var, VI.Loc->getInlinedAt())); LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc); // If variable scope is not found then skip this variable. @@ -1196,15 +1244,15 @@ void CodeViewDebug::calculateRanges( } void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) { - DenseSet<InlinedVariable> Processed; + DenseSet<InlinedEntity> Processed; // Grab the variable info that was squirreled away in the MMI side-table. collectVariableInfoFromMFTable(Processed); for (const auto &I : DbgValues) { - InlinedVariable IV = I.first; + InlinedEntity IV = I.first; if (Processed.count(IV)) continue; - const DILocalVariable *DIVar = IV.first; + const DILocalVariable *DIVar = cast<DILocalVariable>(IV.first); const DILocation *InlinedAt = IV.second; // Instruction ranges, specifying where IV is accessible. @@ -1228,6 +1276,9 @@ void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) { } void CodeViewDebug::beginFunctionImpl(const MachineFunction *MF) { + const TargetSubtargetInfo &TSI = MF->getSubtarget(); + const TargetRegisterInfo *TRI = TSI.getRegisterInfo(); + const MachineFrameInfo &MFI = MF->getFrameInfo(); const Function &GV = MF->getFunction(); auto Insertion = FnDebugInfo.insert({&GV, llvm::make_unique<FunctionInfo>()}); assert(Insertion.second && "function already has info"); @@ -1235,6 +1286,66 @@ void CodeViewDebug::beginFunctionImpl(const MachineFunction *MF) { CurFn->FuncId = NextFuncId++; CurFn->Begin = Asm->getFunctionBegin(); + // The S_FRAMEPROC record reports the stack size, and how many bytes of + // callee-saved registers were used. For targets that don't use a PUSH + // instruction (AArch64), this will be zero. + CurFn->CSRSize = MFI.getCVBytesOfCalleeSavedRegisters(); + CurFn->FrameSize = MFI.getStackSize(); + CurFn->OffsetAdjustment = MFI.getOffsetAdjustment(); + CurFn->HasStackRealignment = TRI->needsStackRealignment(*MF); + + // For this function S_FRAMEPROC record, figure out which codeview register + // will be the frame pointer. + CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::None; // None. + CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::None; // None. + if (CurFn->FrameSize > 0) { + if (!TSI.getFrameLowering()->hasFP(*MF)) { + CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr; + CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::StackPtr; + } else { + // If there is an FP, parameters are always relative to it. + CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::FramePtr; + if (CurFn->HasStackRealignment) { + // If the stack needs realignment, locals are relative to SP or VFRAME. + CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr; + } else { + // Otherwise, locals are relative to EBP, and we probably have VLAs or + // other stack adjustments. + CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::FramePtr; + } + } + } + + // Compute other frame procedure options. + FrameProcedureOptions FPO = FrameProcedureOptions::None; + if (MFI.hasVarSizedObjects()) + FPO |= FrameProcedureOptions::HasAlloca; + if (MF->exposesReturnsTwice()) + FPO |= FrameProcedureOptions::HasSetJmp; + // FIXME: Set HasLongJmp if we ever track that info. + if (MF->hasInlineAsm()) + FPO |= FrameProcedureOptions::HasInlineAssembly; + if (GV.hasPersonalityFn()) { + if (isAsynchronousEHPersonality( + classifyEHPersonality(GV.getPersonalityFn()))) + FPO |= FrameProcedureOptions::HasStructuredExceptionHandling; + else + FPO |= FrameProcedureOptions::HasExceptionHandling; + } + if (GV.hasFnAttribute(Attribute::InlineHint)) + FPO |= FrameProcedureOptions::MarkedInline; + if (GV.hasFnAttribute(Attribute::Naked)) + FPO |= FrameProcedureOptions::Naked; + if (MFI.hasStackProtectorIndex()) + FPO |= FrameProcedureOptions::SecurityChecks; + FPO |= FrameProcedureOptions(uint32_t(CurFn->EncodedLocalFramePtrReg) << 14U); + FPO |= FrameProcedureOptions(uint32_t(CurFn->EncodedParamFramePtrReg) << 16U); + if (Asm->TM.getOptLevel() != CodeGenOpt::None && !GV.optForSize() && + !GV.hasFnAttribute(Attribute::OptimizeNone)) + FPO |= FrameProcedureOptions::OptimizedForSpeed; + // FIXME: Set GuardCfg when it is implemented. + CurFn->FrameProcOpts = FPO; + OS.EmitCVFuncIdDirective(CurFn->FuncId); // Find the end of the function prolog. First known non-DBG_VALUE and @@ -1358,6 +1469,8 @@ TypeIndex CodeViewDebug::lowerType(const DIType *Ty, const DIType *ClassTy) { case dwarf::DW_TAG_union_type: return lowerTypeUnion(cast<DICompositeType>(Ty)); case dwarf::DW_TAG_unspecified_type: + if (Ty->getName() == "decltype(nullptr)") + return TypeIndex::NullptrT(); return TypeIndex::None(); default: // Use the null type index. @@ -1552,6 +1665,9 @@ TypeIndex CodeViewDebug::lowerTypePointer(const DIDerivedType *Ty, break; } + if (Ty->isObjectPointer()) + PO |= PointerOptions::Const; + PointerRecord PR(PointeeTI, PK, PM, PO, Ty->getSizeInBits() / 8); return TypeTable.writeLeafType(PR); } @@ -1702,49 +1818,54 @@ TypeIndex CodeViewDebug::lowerTypeFunction(const DISubroutineType *Ty) { CallingConvention CC = dwarfCCToCodeView(Ty->getCC()); - ProcedureRecord Procedure(ReturnTypeIndex, CC, FunctionOptions::None, - ArgTypeIndices.size(), ArgListIndex); + FunctionOptions FO = getFunctionOptions(Ty); + ProcedureRecord Procedure(ReturnTypeIndex, CC, FO, ArgTypeIndices.size(), + ArgListIndex); return TypeTable.writeLeafType(Procedure); } TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty, const DIType *ClassTy, int ThisAdjustment, - bool IsStaticMethod) { + bool IsStaticMethod, + FunctionOptions FO) { // Lower the containing class type. TypeIndex ClassType = getTypeIndex(ClassTy); - SmallVector<TypeIndex, 8> ReturnAndArgTypeIndices; - for (DITypeRef ArgTypeRef : Ty->getTypeArray()) - ReturnAndArgTypeIndices.push_back(getTypeIndex(ArgTypeRef)); + DITypeRefArray ReturnAndArgs = Ty->getTypeArray(); - // MSVC uses type none for variadic argument. - if (ReturnAndArgTypeIndices.size() > 1 && - ReturnAndArgTypeIndices.back() == TypeIndex::Void()) { - ReturnAndArgTypeIndices.back() = TypeIndex::None(); - } - TypeIndex ReturnTypeIndex = TypeIndex::Void(); - ArrayRef<TypeIndex> ArgTypeIndices = None; - if (!ReturnAndArgTypeIndices.empty()) { - auto ReturnAndArgTypesRef = makeArrayRef(ReturnAndArgTypeIndices); - ReturnTypeIndex = ReturnAndArgTypesRef.front(); - ArgTypeIndices = ReturnAndArgTypesRef.drop_front(); - } + unsigned Index = 0; + SmallVector<TypeIndex, 8> ArgTypeIndices; + TypeIndex ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]); + + // If the first argument is a pointer type and this isn't a static method, + // treat it as the special 'this' parameter, which is encoded separately from + // the arguments. TypeIndex ThisTypeIndex; - if (!IsStaticMethod && !ArgTypeIndices.empty()) { - ThisTypeIndex = ArgTypeIndices.front(); - ArgTypeIndices = ArgTypeIndices.drop_front(); + if (!IsStaticMethod && ReturnAndArgs.size() > Index) { + if (const DIDerivedType *PtrTy = + dyn_cast_or_null<DIDerivedType>(ReturnAndArgs[Index].resolve())) { + if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) { + ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty); + Index++; + } + } } + while (Index < ReturnAndArgs.size()) + ArgTypeIndices.push_back(getTypeIndex(ReturnAndArgs[Index++])); + + // MSVC uses type none for variadic argument. + if (!ArgTypeIndices.empty() && ArgTypeIndices.back() == TypeIndex::Void()) + ArgTypeIndices.back() = TypeIndex::None(); + ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices); TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec); CallingConvention CC = dwarfCCToCodeView(Ty->getCC()); - // TODO: Need to use the correct values for FunctionOptions. - MemberFunctionRecord MFR(ReturnTypeIndex, ClassType, ThisTypeIndex, CC, - FunctionOptions::None, ArgTypeIndices.size(), - ArgListIndex, ThisAdjustment); + MemberFunctionRecord MFR(ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FO, + ArgTypeIndices.size(), ArgListIndex, ThisAdjustment); return TypeTable.writeLeafType(MFR); } @@ -1825,12 +1946,20 @@ static ClassOptions getCommonClassOptions(const DICompositeType *Ty) { if (ImmediateScope && isa<DICompositeType>(ImmediateScope)) CO |= ClassOptions::Nested; - // Put the Scoped flag on function-local types. - for (const DIScope *Scope = ImmediateScope; Scope != nullptr; - Scope = Scope->getScope().resolve()) { - if (isa<DISubprogram>(Scope)) { + // Put the Scoped flag on function-local types. MSVC puts this flag for enum + // type only when it has an immediate function scope. Clang never puts enums + // inside DILexicalBlock scopes. Enum types, as generated by clang, are + // always in function, class, or file scopes. + if (Ty->getTag() == dwarf::DW_TAG_enumeration_type) { + if (ImmediateScope && isa<DISubprogram>(ImmediateScope)) CO |= ClassOptions::Scoped; - break; + } else { + for (const DIScope *Scope = ImmediateScope; Scope != nullptr; + Scope = Scope->getScope().resolve()) { + if (isa<DISubprogram>(Scope)) { + CO |= ClassOptions::Scoped; + break; + } } } @@ -1930,6 +2059,7 @@ void CodeViewDebug::clear() { GlobalUDTs.clear(); TypeIndices.clear(); CompleteTypeIndices.clear(); + ScopeGlobals.clear(); } void CodeViewDebug::collectMemberInfo(ClassInfo &Info, @@ -2275,6 +2405,32 @@ TypeIndex CodeViewDebug::getTypeIndex(DITypeRef TypeRef, DITypeRef ClassTyRef) { return recordTypeIndexForDINode(Ty, TI, ClassTy); } +codeview::TypeIndex +CodeViewDebug::getTypeIndexForThisPtr(const DIDerivedType *PtrTy, + const DISubroutineType *SubroutineTy) { + assert(PtrTy->getTag() == dwarf::DW_TAG_pointer_type && + "this type must be a pointer type"); + + PointerOptions Options = PointerOptions::None; + if (SubroutineTy->getFlags() & DINode::DIFlags::FlagLValueReference) + Options = PointerOptions::LValueRefThisPointer; + else if (SubroutineTy->getFlags() & DINode::DIFlags::FlagRValueReference) + Options = PointerOptions::RValueRefThisPointer; + + // Check if we've already translated this type. If there is no ref qualifier + // on the function then we look up this pointer type with no associated class + // so that the TypeIndex for the this pointer can be shared with the type + // index for other pointers to this class type. If there is a ref qualifier + // then we lookup the pointer using the subroutine as the parent type. + auto I = TypeIndices.find({PtrTy, SubroutineTy}); + if (I != TypeIndices.end()) + return I->second; + + TypeLoweringScope S(*this); + TypeIndex TI = lowerTypePointer(PtrTy, Options); + return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy); +} + TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(DITypeRef TypeRef) { DIType *Ty = TypeRef.resolve(); PointerRecord PR(getTypeIndex(Ty), @@ -2292,6 +2448,14 @@ TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) { if (!Ty) return TypeIndex::Void(); + // Look through typedefs when getting the complete type index. Call + // getTypeIndex on the typdef to ensure that any UDTs are accumulated and are + // emitted only once. + if (Ty->getTag() == dwarf::DW_TAG_typedef) + (void)getTypeIndex(Ty); + while (Ty->getTag() == dwarf::DW_TAG_typedef) + Ty = cast<DIDerivedType>(Ty)->getBaseType().resolve(); + // If this is a non-record type, the complete type index is the same as the // normal type index. Just call getTypeIndex. switch (Ty->getTag()) { @@ -2360,35 +2524,40 @@ void CodeViewDebug::emitDeferredCompleteTypes() { } } -void CodeViewDebug::emitLocalVariableList(ArrayRef<LocalVariable> Locals) { +void CodeViewDebug::emitLocalVariableList(const FunctionInfo &FI, + ArrayRef<LocalVariable> Locals) { // Get the sorted list of parameters and emit them first. SmallVector<const LocalVariable *, 6> Params; for (const LocalVariable &L : Locals) if (L.DIVar->isParameter()) Params.push_back(&L); - llvm::sort(Params.begin(), Params.end(), - [](const LocalVariable *L, const LocalVariable *R) { - return L->DIVar->getArg() < R->DIVar->getArg(); - }); + llvm::sort(Params, [](const LocalVariable *L, const LocalVariable *R) { + return L->DIVar->getArg() < R->DIVar->getArg(); + }); for (const LocalVariable *L : Params) - emitLocalVariable(*L); + emitLocalVariable(FI, *L); // Next emit all non-parameters in the order that we found them. for (const LocalVariable &L : Locals) if (!L.DIVar->isParameter()) - emitLocalVariable(L); + emitLocalVariable(FI, L); } -void CodeViewDebug::emitLocalVariable(const LocalVariable &Var) { - // LocalSym record, see SymbolRecord.h for more info. - MCSymbol *LocalBegin = MMI->getContext().createTempSymbol(), - *LocalEnd = MMI->getContext().createTempSymbol(); - OS.AddComment("Record length"); - OS.emitAbsoluteSymbolDiff(LocalEnd, LocalBegin, 2); - OS.EmitLabel(LocalBegin); +/// 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)); +} - OS.AddComment("Record kind: S_LOCAL"); - OS.EmitIntValue(unsigned(SymbolKind::S_LOCAL), 2); +void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI, + const LocalVariable &Var) { + // LocalSym record, see SymbolRecord.h for more info. + MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL); LocalSymFlags Flags = LocalSymFlags::None; if (Var.DIVar->isParameter()) @@ -2405,7 +2574,7 @@ void CodeViewDebug::emitLocalVariable(const LocalVariable &Var) { OS.EmitIntValue(static_cast<uint16_t>(Flags), 2); // Truncate the name so we won't overflow the record length field. emitNullTerminatedSymbolName(OS, Var.DIVar->getName()); - OS.EmitLabel(LocalEnd); + endSymbolRecord(LocalEnd); // Calculate the on disk prefix of the appropriate def range record. The // records and on disk formats are described in SymbolRecords.h. BytePrefix @@ -2414,45 +2583,53 @@ void CodeViewDebug::emitLocalVariable(const LocalVariable &Var) { for (const LocalVarDefRange &DefRange : Var.DefRanges) { BytePrefix.clear(); if (DefRange.InMemory) { - uint16_t RegRelFlags = 0; - if (DefRange.IsSubfield) { - RegRelFlags = DefRangeRegisterRelSym::IsSubfieldFlag | - (DefRange.StructOffset - << DefRangeRegisterRelSym::OffsetInParentShift); + int Offset = DefRange.DataOffset; + unsigned Reg = DefRange.CVRegister; + + // 32-bit x86 call sequences often use PUSH instructions, which disrupt + // ESP-relative offsets. Use the virtual frame pointer, VFRAME or $T0, + // instead. In frames without stack realignment, $T0 will be the CFA. + if (RegisterId(Reg) == RegisterId::ESP) { + Reg = unsigned(RegisterId::VFRAME); + Offset += FI.OffsetAdjustment; + } + + // If we can use the chosen frame pointer for the frame and this isn't a + // sliced aggregate, use the smaller S_DEFRANGE_FRAMEPOINTER_REL record. + // Otherwise, use S_DEFRANGE_REGISTER_REL. + EncodedFramePtrReg EncFP = encodeFramePtrReg(RegisterId(Reg), TheCPU); + if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None && + (bool(Flags & LocalSymFlags::IsParameter) + ? (EncFP == FI.EncodedParamFramePtrReg) + : (EncFP == FI.EncodedLocalFramePtrReg))) { + little32_t FPOffset = little32_t(Offset); + copyBytesForDefRange(BytePrefix, S_DEFRANGE_FRAMEPOINTER_REL, FPOffset); + } else { + uint16_t RegRelFlags = 0; + if (DefRange.IsSubfield) { + RegRelFlags = DefRangeRegisterRelSym::IsSubfieldFlag | + (DefRange.StructOffset + << DefRangeRegisterRelSym::OffsetInParentShift); + } + DefRangeRegisterRelSym::Header DRHdr; + DRHdr.Register = Reg; + DRHdr.Flags = RegRelFlags; + DRHdr.BasePointerOffset = Offset; + copyBytesForDefRange(BytePrefix, S_DEFRANGE_REGISTER_REL, DRHdr); } - DefRangeRegisterRelSym Sym(S_DEFRANGE_REGISTER_REL); - Sym.Hdr.Register = DefRange.CVRegister; - Sym.Hdr.Flags = RegRelFlags; - Sym.Hdr.BasePointerOffset = DefRange.DataOffset; - ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_REGISTER_REL); - BytePrefix += - StringRef(reinterpret_cast<const char *>(&SymKind), sizeof(SymKind)); - BytePrefix += - StringRef(reinterpret_cast<const char *>(&Sym.Hdr), sizeof(Sym.Hdr)); } else { assert(DefRange.DataOffset == 0 && "unexpected offset into register"); if (DefRange.IsSubfield) { - // Unclear what matters here. - DefRangeSubfieldRegisterSym Sym(S_DEFRANGE_SUBFIELD_REGISTER); - Sym.Hdr.Register = DefRange.CVRegister; - Sym.Hdr.MayHaveNoName = 0; - Sym.Hdr.OffsetInParent = DefRange.StructOffset; - - ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_SUBFIELD_REGISTER); - BytePrefix += StringRef(reinterpret_cast<const char *>(&SymKind), - sizeof(SymKind)); - BytePrefix += StringRef(reinterpret_cast<const char *>(&Sym.Hdr), - sizeof(Sym.Hdr)); + DefRangeSubfieldRegisterSym::Header DRHdr; + DRHdr.Register = DefRange.CVRegister; + DRHdr.MayHaveNoName = 0; + DRHdr.OffsetInParent = DefRange.StructOffset; + copyBytesForDefRange(BytePrefix, S_DEFRANGE_SUBFIELD_REGISTER, DRHdr); } else { - // Unclear what matters here. - DefRangeRegisterSym Sym(S_DEFRANGE_REGISTER); - Sym.Hdr.Register = DefRange.CVRegister; - Sym.Hdr.MayHaveNoName = 0; - ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_REGISTER); - BytePrefix += StringRef(reinterpret_cast<const char *>(&SymKind), - sizeof(SymKind)); - BytePrefix += StringRef(reinterpret_cast<const char *>(&Sym.Hdr), - sizeof(Sym.Hdr)); + DefRangeRegisterSym::Header DRHdr; + DRHdr.Register = DefRange.CVRegister; + DRHdr.MayHaveNoName = 0; + copyBytesForDefRange(BytePrefix, S_DEFRANGE_REGISTER, DRHdr); } } OS.EmitCVDefRangeDirective(DefRange.Ranges, BytePrefix); @@ -2469,15 +2646,7 @@ void CodeViewDebug::emitLexicalBlockList(ArrayRef<LexicalBlock *> Blocks, /// lexical block scope. void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block, const FunctionInfo& FI) { - MCSymbol *RecordBegin = MMI->getContext().createTempSymbol(), - *RecordEnd = MMI->getContext().createTempSymbol(); - - // Lexical block symbol record. - OS.AddComment("Record length"); - OS.emitAbsoluteSymbolDiff(RecordEnd, RecordBegin, 2); // Record Length - OS.EmitLabel(RecordBegin); - OS.AddComment("Record kind: S_BLOCK32"); - OS.EmitIntValue(SymbolKind::S_BLOCK32, 2); // Record Kind + MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32); OS.AddComment("PtrParent"); OS.EmitIntValue(0, 4); // PtrParent OS.AddComment("PtrEnd"); @@ -2490,19 +2659,17 @@ void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block, OS.EmitCOFFSectionIndex(FI.Begin); // Func Symbol OS.AddComment("Lexical block name"); emitNullTerminatedSymbolName(OS, Block.Name); // Name - OS.EmitLabel(RecordEnd); + endSymbolRecord(RecordEnd); // Emit variables local to this lexical block. - emitLocalVariableList(Block.Locals); + emitLocalVariableList(FI, Block.Locals); + emitGlobalVariableList(Block.Globals); // Emit lexical blocks contained within this block. emitLexicalBlockList(Block.Children, FI); // Close the lexical block scope. - OS.AddComment("Record length"); - OS.EmitIntValue(2, 2); // Record Length - OS.AddComment("Record kind: S_END"); - OS.EmitIntValue(SymbolKind::S_END, 2); // Record Kind + emitEndSymbolRecord(SymbolKind::S_END); } /// Convenience routine for collecting lexical block information for a list @@ -2510,9 +2677,10 @@ void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block, void CodeViewDebug::collectLexicalBlockInfo( SmallVectorImpl<LexicalScope *> &Scopes, SmallVectorImpl<LexicalBlock *> &Blocks, - SmallVectorImpl<LocalVariable> &Locals) { + SmallVectorImpl<LocalVariable> &Locals, + SmallVectorImpl<CVGlobalVariable> &Globals) { for (LexicalScope *Scope : Scopes) - collectLexicalBlockInfo(*Scope, Blocks, Locals); + collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals); } /// Populate the lexical blocks and local variable lists of the parent with @@ -2520,45 +2688,58 @@ void CodeViewDebug::collectLexicalBlockInfo( void CodeViewDebug::collectLexicalBlockInfo( LexicalScope &Scope, SmallVectorImpl<LexicalBlock *> &ParentBlocks, - SmallVectorImpl<LocalVariable> &ParentLocals) { + SmallVectorImpl<LocalVariable> &ParentLocals, + SmallVectorImpl<CVGlobalVariable> &ParentGlobals) { if (Scope.isAbstractScope()) return; - auto LocalsIter = ScopeVariables.find(&Scope); - if (LocalsIter == ScopeVariables.end()) { - // This scope does not contain variables and can be eliminated. - collectLexicalBlockInfo(Scope.getChildren(), ParentBlocks, ParentLocals); - return; - } - SmallVectorImpl<LocalVariable> &Locals = LocalsIter->second; - + // Gather information about the lexical scope including local variables, + // global variables, and address ranges. + bool IgnoreScope = false; + auto LI = ScopeVariables.find(&Scope); + SmallVectorImpl<LocalVariable> *Locals = + LI != ScopeVariables.end() ? &LI->second : nullptr; + auto GI = ScopeGlobals.find(Scope.getScopeNode()); + SmallVectorImpl<CVGlobalVariable> *Globals = + GI != ScopeGlobals.end() ? GI->second.get() : nullptr; const DILexicalBlock *DILB = dyn_cast<DILexicalBlock>(Scope.getScopeNode()); - if (!DILB) { - // This scope is not a lexical block and can be eliminated, but keep any - // local variables it contains. - ParentLocals.append(Locals.begin(), Locals.end()); - collectLexicalBlockInfo(Scope.getChildren(), ParentBlocks, ParentLocals); - return; - } - const SmallVectorImpl<InsnRange> &Ranges = Scope.getRanges(); - if (Ranges.size() != 1 || !getLabelAfterInsn(Ranges.front().second)) { - // This lexical block scope has too many address ranges to represent in the - // current CodeView format or does not have a valid address range. - // Eliminate this lexical scope and promote any locals it contains to the - // parent scope. - // - // For lexical scopes with multiple address ranges you may be tempted to - // construct a single range covering every instruction where the block is - // live and everything in between. Unfortunately, Visual Studio only - // displays variables from the first matching lexical block scope. If the - // first lexical block contains exception handling code or cold code which - // is moved to the bottom of the routine creating a single range covering - // nearly the entire routine, then it will hide all other lexical blocks - // and the variables they contain. - // - ParentLocals.append(Locals.begin(), Locals.end()); - collectLexicalBlockInfo(Scope.getChildren(), ParentBlocks, ParentLocals); + + // Ignore lexical scopes which do not contain variables. + if (!Locals && !Globals) + IgnoreScope = true; + + // Ignore lexical scopes which are not lexical blocks. + if (!DILB) + IgnoreScope = true; + + // Ignore scopes which have too many address ranges to represent in the + // current CodeView format or do not have a valid address range. + // + // For lexical scopes with multiple address ranges you may be tempted to + // construct a single range covering every instruction where the block is + // live and everything in between. Unfortunately, Visual Studio only + // displays variables from the first matching lexical block scope. If the + // first lexical block contains exception handling code or cold code which + // is moved to the bottom of the routine creating a single range covering + // nearly the entire routine, then it will hide all other lexical blocks + // and the variables they contain. + if (Ranges.size() != 1 || !getLabelAfterInsn(Ranges.front().second)) + IgnoreScope = true; + + if (IgnoreScope) { + // This scope can be safely ignored and eliminating it will reduce the + // size of the debug information. Be sure to collect any variable and scope + // information from the this scope or any of its children and collapse them + // into the parent scope. + if (Locals) + ParentLocals.append(Locals->begin(), Locals->end()); + if (Globals) + ParentGlobals.append(Globals->begin(), Globals->end()); + collectLexicalBlockInfo(Scope.getChildren(), + ParentBlocks, + ParentLocals, + ParentGlobals); return; } @@ -2569,8 +2750,8 @@ void CodeViewDebug::collectLexicalBlockInfo( if (!BlockInsertion.second) return; - // Create a lexical block containing the local variables and collect the - // the lexical block information for the children. + // Create a lexical block containing the variables and collect the the + // lexical block information for the children. const InsnRange &Range = Ranges.front(); assert(Range.first && Range.second); LexicalBlock &Block = BlockInsertion.first->second; @@ -2579,9 +2760,15 @@ void CodeViewDebug::collectLexicalBlockInfo( assert(Block.Begin && "missing label for scope begin"); assert(Block.End && "missing label for scope end"); Block.Name = DILB->getName(); - Block.Locals = std::move(Locals); + if (Locals) + Block.Locals = std::move(*Locals); + if (Globals) + Block.Globals = std::move(*Globals); ParentBlocks.push_back(&Block); - collectLexicalBlockInfo(Scope.getChildren(), Block.Children, Block.Locals); + collectLexicalBlockInfo(Scope.getChildren(), + Block.Children, + Block.Locals, + Block.Globals); } void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) { @@ -2593,7 +2780,10 @@ void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) { // Build the lexical block structure to emit for this routine. if (LexicalScope *CFS = LScopes.getCurrentFunctionScope()) - collectLexicalBlockInfo(*CFS, CurFn->ChildBlocks, CurFn->Locals); + collectLexicalBlockInfo(*CFS, + CurFn->ChildBlocks, + CurFn->Locals, + CurFn->Globals); // Clear the scope and variable information from the map which will not be // valid after we have finished processing this routine. This also prepares @@ -2660,30 +2850,57 @@ void CodeViewDebug::endCVSubsection(MCSymbol *EndLabel) { OS.EmitValueToAlignment(4); } +static StringRef getSymbolName(SymbolKind SymKind) { + for (const EnumEntry<SymbolKind> &EE : getSymbolTypeNames()) + if (EE.Value == SymKind) + return EE.Name; + return ""; +} + +MCSymbol *CodeViewDebug::beginSymbolRecord(SymbolKind SymKind) { + MCSymbol *BeginLabel = MMI->getContext().createTempSymbol(), + *EndLabel = MMI->getContext().createTempSymbol(); + OS.AddComment("Record length"); + OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2); + OS.EmitLabel(BeginLabel); + if (OS.isVerboseAsm()) + OS.AddComment("Record kind: " + getSymbolName(SymKind)); + OS.EmitIntValue(unsigned(SymKind), 2); + return EndLabel; +} + +void CodeViewDebug::endSymbolRecord(MCSymbol *SymEnd) { + // MSVC does not pad out symbol records to four bytes, but LLVM does to avoid + // 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); +} + +void CodeViewDebug::emitEndSymbolRecord(SymbolKind EndKind) { + OS.AddComment("Record length"); + OS.EmitIntValue(2, 2); + if (OS.isVerboseAsm()) + OS.AddComment("Record kind: " + getSymbolName(EndKind)); + OS.EmitIntValue(unsigned(EndKind), 2); // Record Kind +} + void CodeViewDebug::emitDebugInfoForUDTs( ArrayRef<std::pair<std::string, const DIType *>> UDTs) { for (const auto &UDT : UDTs) { const DIType *T = UDT.second; assert(shouldEmitUdt(T)); - MCSymbol *UDTRecordBegin = MMI->getContext().createTempSymbol(), - *UDTRecordEnd = MMI->getContext().createTempSymbol(); - OS.AddComment("Record length"); - OS.emitAbsoluteSymbolDiff(UDTRecordEnd, UDTRecordBegin, 2); - OS.EmitLabel(UDTRecordBegin); - - OS.AddComment("Record kind: S_UDT"); - OS.EmitIntValue(unsigned(SymbolKind::S_UDT), 2); - + MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT); OS.AddComment("Type"); OS.EmitIntValue(getCompleteTypeIndex(T).getIndex(), 4); - emitNullTerminatedSymbolName(OS, UDT.first); - OS.EmitLabel(UDTRecordEnd); + endSymbolRecord(UDTRecordEnd); } } -void CodeViewDebug::emitDebugInfoForGlobals() { +void CodeViewDebug::collectGlobalVariableInfo() { DenseMap<const DIGlobalVariableExpression *, const GlobalVariable *> GlobalMap; for (const GlobalVariable &GV : MMI->getModule()->globals()) { @@ -2696,42 +2913,56 @@ void CodeViewDebug::emitDebugInfoForGlobals() { NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu"); for (const MDNode *Node : CUs->operands()) { const auto *CU = cast<DICompileUnit>(Node); - - // First, emit all globals that are not in a comdat in a single symbol - // substream. MSVC doesn't like it if the substream is empty, so only open - // it if we have at least one global to emit. - switchToDebugSectionForSymbol(nullptr); - MCSymbol *EndLabel = nullptr; for (const auto *GVE : CU->getGlobalVariables()) { - if (const auto *GV = GlobalMap.lookup(GVE)) - if (!GV->hasComdat() && !GV->isDeclarationForLinker()) { - if (!EndLabel) { - OS.AddComment("Symbol subsection for globals"); - EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols); - } - // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions. - emitDebugInfoForGlobal(GVE->getVariable(), GV, Asm->getSymbol(GV)); - } + const auto *GV = GlobalMap.lookup(GVE); + if (!GV || GV->isDeclarationForLinker()) + continue; + const DIGlobalVariable *DIGV = GVE->getVariable(); + DIScope *Scope = DIGV->getScope(); + SmallVector<CVGlobalVariable, 1> *VariableList; + if (Scope && isa<DILocalScope>(Scope)) { + // Locate a global variable list for this scope, creating one if + // necessary. + auto Insertion = ScopeGlobals.insert( + {Scope, std::unique_ptr<GlobalVariableList>()}); + if (Insertion.second) + Insertion.first->second = llvm::make_unique<GlobalVariableList>(); + VariableList = Insertion.first->second.get(); + } else if (GV->hasComdat()) + // Emit this global variable into a COMDAT section. + VariableList = &ComdatVariables; + else + // Emit this globla variable in a single global symbol section. + VariableList = &GlobalVariables; + CVGlobalVariable CVGV = {DIGV, GV}; + VariableList->emplace_back(std::move(CVGV)); } - if (EndLabel) - endCVSubsection(EndLabel); + } +} - // Second, emit each global that is in a comdat into its own .debug$S - // section along with its own symbol substream. - for (const auto *GVE : CU->getGlobalVariables()) { - if (const auto *GV = GlobalMap.lookup(GVE)) { - if (GV->hasComdat()) { - MCSymbol *GVSym = Asm->getSymbol(GV); - OS.AddComment("Symbol subsection for " + - Twine(GlobalValue::dropLLVMManglingEscape(GV->getName()))); - switchToDebugSectionForSymbol(GVSym); - EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols); - // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions. - emitDebugInfoForGlobal(GVE->getVariable(), GV, GVSym); - endCVSubsection(EndLabel); - } - } - } +void CodeViewDebug::emitDebugInfoForGlobals() { + // First, emit all globals that are not in a comdat in a single symbol + // substream. MSVC doesn't like it if the substream is empty, so only open + // it if we have at least one global to emit. + switchToDebugSectionForSymbol(nullptr); + if (!GlobalVariables.empty()) { + OS.AddComment("Symbol subsection for globals"); + MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols); + emitGlobalVariableList(GlobalVariables); + endCVSubsection(EndLabel); + } + + // Second, emit each global that is in a comdat into its own .debug$S + // section along with its own symbol substream. + for (const CVGlobalVariable &CVGV : ComdatVariables) { + MCSymbol *GVSym = Asm->getSymbol(CVGV.GV); + OS.AddComment("Symbol subsection for " + + Twine(GlobalValue::dropLLVMManglingEscape(CVGV.GV->getName()))); + switchToDebugSectionForSymbol(GVSym); + MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols); + // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions. + emitDebugInfoForGlobal(CVGV.DIGV, CVGV.GV, GVSym); + endCVSubsection(EndLabel); } } @@ -2747,34 +2978,26 @@ void CodeViewDebug::emitDebugInfoForRetainedTypes() { } } +// Emit each global variable in the specified array. +void CodeViewDebug::emitGlobalVariableList(ArrayRef<CVGlobalVariable> Globals) { + for (const CVGlobalVariable &CVGV : Globals) { + MCSymbol *GVSym = Asm->getSymbol(CVGV.GV); + // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions. + emitDebugInfoForGlobal(CVGV.DIGV, CVGV.GV, GVSym); + } +} + void CodeViewDebug::emitDebugInfoForGlobal(const DIGlobalVariable *DIGV, const GlobalVariable *GV, MCSymbol *GVSym) { - // DataSym record, see SymbolRecord.h for more info. - // FIXME: Thread local data, etc - MCSymbol *DataBegin = MMI->getContext().createTempSymbol(), - *DataEnd = MMI->getContext().createTempSymbol(); - const unsigned FixedLengthOfThisRecord = 12; - OS.AddComment("Record length"); - OS.emitAbsoluteSymbolDiff(DataEnd, DataBegin, 2); - OS.EmitLabel(DataBegin); - if (DIGV->isLocalToUnit()) { - if (GV->isThreadLocal()) { - OS.AddComment("Record kind: S_LTHREAD32"); - OS.EmitIntValue(unsigned(SymbolKind::S_LTHREAD32), 2); - } else { - OS.AddComment("Record kind: S_LDATA32"); - OS.EmitIntValue(unsigned(SymbolKind::S_LDATA32), 2); - } - } else { - if (GV->isThreadLocal()) { - OS.AddComment("Record kind: S_GTHREAD32"); - OS.EmitIntValue(unsigned(SymbolKind::S_GTHREAD32), 2); - } else { - OS.AddComment("Record kind: S_GDATA32"); - OS.EmitIntValue(unsigned(SymbolKind::S_GDATA32), 2); - } - } + // DataSym record, see SymbolRecord.h for more info. Thread local data + // happens to have the same format as global data. + SymbolKind DataSym = GV->isThreadLocal() + ? (DIGV->isLocalToUnit() ? SymbolKind::S_LTHREAD32 + : SymbolKind::S_GTHREAD32) + : (DIGV->isLocalToUnit() ? SymbolKind::S_LDATA32 + : SymbolKind::S_GDATA32); + MCSymbol *DataEnd = beginSymbolRecord(DataSym); OS.AddComment("Type"); OS.EmitIntValue(getCompleteTypeIndex(DIGV->getType()).getIndex(), 4); OS.AddComment("DataOffset"); @@ -2782,6 +3005,7 @@ void CodeViewDebug::emitDebugInfoForGlobal(const DIGlobalVariable *DIGV, OS.AddComment("Segment"); OS.EmitCOFFSectionIndex(GVSym); OS.AddComment("Name"); - emitNullTerminatedSymbolName(OS, DIGV->getName(), FixedLengthOfThisRecord); - OS.EmitLabel(DataEnd); + const unsigned LengthOfDataRecord = 12; + emitNullTerminatedSymbolName(OS, DIGV->getName(), LengthOfDataRecord); + endSymbolRecord(DataEnd); } diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h index 6a0da5f993d0..21557ed1be35 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -14,14 +14,14 @@ #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H #define LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H -#include "DbgValueHistoryCalculator.h" -#include "DebugHandlerBase.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/DbgEntityHistoryCalculator.h" +#include "llvm/CodeGen/DebugHandlerBase.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" @@ -54,6 +54,12 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { BumpPtrAllocator Allocator; codeview::GlobalTypeTableBuilder TypeTable; + /// Whether to emit type record hashes into .debug$H. + bool EmitDebugGlobalHashes = false; + + /// The codeview CPU type used by the translation unit. + codeview::CPUType TheCPU; + /// Represents the most general definition range. struct LocalVarDefRange { /// Indicates that variable data is stored in memory relative to the @@ -85,10 +91,6 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { }; static LocalVarDefRange createDefRangeMem(uint16_t CVRegister, int Offset); - static LocalVarDefRange createDefRangeGeneral(uint16_t CVRegister, - bool InMemory, int Offset, - bool IsSubfield, - uint16_t StructOffset); /// Similar to DbgVariable in DwarfDebug, but not dwarf-specific. struct LocalVariable { @@ -97,6 +99,11 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { bool UseReferenceType = false; }; + struct CVGlobalVariable { + const DIGlobalVariable *DIGV; + const GlobalVariable *GV; + }; + struct InlineSite { SmallVector<LocalVariable, 1> InlinedLocals; SmallVector<const DILocation *, 1> ChildSites; @@ -110,6 +117,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { // Combines information from DILexicalBlock and LexicalScope. struct LexicalBlock { SmallVector<LocalVariable, 1> Locals; + SmallVector<CVGlobalVariable, 1> Globals; SmallVector<LexicalBlock *, 1> Children; const MCSymbol *Begin; const MCSymbol *End; @@ -132,6 +140,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { SmallVector<const DILocation *, 1> ChildSites; SmallVector<LocalVariable, 1> Locals; + SmallVector<CVGlobalVariable, 1> Globals; std::unordered_map<const DILexicalBlockBase*, LexicalBlock> LexicalBlocks; @@ -144,6 +153,33 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { const MCSymbol *End = nullptr; unsigned FuncId = 0; unsigned LastFileId = 0; + + /// Number of bytes allocated in the prologue for all local stack objects. + unsigned FrameSize = 0; + + /// Number of bytes of parameters on the stack. + unsigned ParamSize = 0; + + /// Number of bytes pushed to save CSRs. + unsigned CSRSize = 0; + + /// Adjustment to apply on x86 when using the VFRAME frame pointer. + int OffsetAdjustment = 0; + + /// Two-bit value indicating which register is the designated frame pointer + /// register for local variables. Included in S_FRAMEPROC. + codeview::EncodedFramePtrReg EncodedLocalFramePtrReg = + codeview::EncodedFramePtrReg::None; + + /// Two-bit value indicating which register is the designated frame pointer + /// register for stack parameters. Included in S_FRAMEPROC. + codeview::EncodedFramePtrReg EncodedParamFramePtrReg = + codeview::EncodedFramePtrReg::None; + + codeview::FrameProcedureOptions FrameProcOpts; + + bool HasStackRealignment = false; + bool HaveLineInfo = false; }; FunctionInfo *CurFn = nullptr; @@ -154,6 +190,17 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { // and LexicalBlocks. DenseMap<const LexicalScope *, SmallVector<LocalVariable, 1>> ScopeVariables; + // Map to separate global variables according to the lexical scope they + // belong in. A null local scope represents the global scope. + typedef SmallVector<CVGlobalVariable, 1> GlobalVariableList; + DenseMap<const DIScope*, std::unique_ptr<GlobalVariableList> > ScopeGlobals; + + // Array of global variables which need to be emitted into a COMDAT section. + SmallVector<CVGlobalVariable, 1> ComdatVariables; + + // Array of non-COMDAT global variables. + SmallVector<CVGlobalVariable, 1> GlobalVariables; + /// The set of comdat .debug$S sections that we've seen so far. Each section /// must start with a magic version number that must only be emitted once. /// This set tracks which sections we've already opened. @@ -249,6 +296,8 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { void emitCompilerInformation(); + void emitBuildInfo(); + void emitInlineeLinesSubsection(); void emitDebugInfoForThunk(const Function *GV, @@ -257,13 +306,13 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { void emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI); - void emitDebugInfoForGlobals(); - void emitDebugInfoForRetainedTypes(); void emitDebugInfoForUDTs(ArrayRef<std::pair<std::string, const DIType *>> UDTs); + void emitDebugInfoForGlobals(); + void emitGlobalVariableList(ArrayRef<CVGlobalVariable> Globals); void emitDebugInfoForGlobal(const DIGlobalVariable *DIGV, const GlobalVariable *GV, MCSymbol *GVSym); @@ -271,36 +320,49 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { /// Returns an end label for use with endCVSubsection when the subsection is /// finished. MCSymbol *beginCVSubsection(codeview::DebugSubsectionKind Kind); - void endCVSubsection(MCSymbol *EndLabel); + /// Opens a symbol record of the given kind. Returns an end label for use with + /// endSymbolRecord. + MCSymbol *beginSymbolRecord(codeview::SymbolKind Kind); + void endSymbolRecord(MCSymbol *SymEnd); + + /// Emits an S_END, S_INLINESITE_END, or S_PROC_ID_END record. These records + /// are empty, so we emit them with a simpler assembly sequence that doesn't + /// involve labels. + void emitEndSymbolRecord(codeview::SymbolKind EndKind); + void emitInlinedCallSite(const FunctionInfo &FI, const DILocation *InlinedAt, const InlineSite &Site); - using InlinedVariable = DbgValueHistoryMap::InlinedVariable; + using InlinedEntity = DbgValueHistoryMap::InlinedEntity; + void collectGlobalVariableInfo(); void collectVariableInfo(const DISubprogram *SP); - void collectVariableInfoFromMFTable(DenseSet<InlinedVariable> &Processed); + void collectVariableInfoFromMFTable(DenseSet<InlinedEntity> &Processed); // Construct the lexical block tree for a routine, pruning emptpy lexical // scopes, and populate it with local variables. void collectLexicalBlockInfo(SmallVectorImpl<LexicalScope *> &Scopes, SmallVectorImpl<LexicalBlock *> &Blocks, - SmallVectorImpl<LocalVariable> &Locals); + SmallVectorImpl<LocalVariable> &Locals, + SmallVectorImpl<CVGlobalVariable> &Globals); void collectLexicalBlockInfo(LexicalScope &Scope, SmallVectorImpl<LexicalBlock *> &ParentBlocks, - SmallVectorImpl<LocalVariable> &ParentLocals); + SmallVectorImpl<LocalVariable> &ParentLocals, + SmallVectorImpl<CVGlobalVariable> &ParentGlobals); /// Records information about a local variable in the appropriate scope. In /// particular, locals from inlined code live inside the inlining site. void recordLocalVariable(LocalVariable &&Var, const LexicalScope *LS); /// Emits local variables in the appropriate order. - void emitLocalVariableList(ArrayRef<LocalVariable> Locals); + void emitLocalVariableList(const FunctionInfo &FI, + ArrayRef<LocalVariable> Locals); /// Emits an S_LOCAL record and its associated defined ranges. - void emitLocalVariable(const LocalVariable &Var); + void emitLocalVariable(const FunctionInfo &FI, const LocalVariable &Var); /// Emits a sequence of lexical block scopes and their children. void emitLexicalBlockList(ArrayRef<LexicalBlock *> Blocks, @@ -314,6 +376,10 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { codeview::TypeIndex getTypeIndex(DITypeRef TypeRef, DITypeRef ClassTyRef = DITypeRef()); + codeview::TypeIndex + getTypeIndexForThisPtr(const DIDerivedType *PtrTy, + const DISubroutineType *SubroutineTy); + codeview::TypeIndex getTypeIndexForReferenceTo(DITypeRef TypeRef); codeview::TypeIndex getMemberFunctionType(const DISubprogram *SP, @@ -340,10 +406,10 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase { codeview::TypeIndex lowerTypeModifier(const DIDerivedType *Ty); codeview::TypeIndex lowerTypeFunction(const DISubroutineType *Ty); codeview::TypeIndex lowerTypeVFTableShape(const DIDerivedType *Ty); - codeview::TypeIndex lowerTypeMemberFunction(const DISubroutineType *Ty, - const DIType *ClassTy, - int ThisAdjustment, - bool IsStaticMethod); + codeview::TypeIndex lowerTypeMemberFunction( + const DISubroutineType *Ty, const DIType *ClassTy, int ThisAdjustment, + bool IsStaticMethod, + codeview::FunctionOptions FO = codeview::FunctionOptions::None); codeview::TypeIndex lowerTypeEnum(const DICompositeType *Ty); codeview::TypeIndex lowerTypeClass(const DICompositeType *Ty); codeview::TypeIndex lowerTypeUnion(const DICompositeType *Ty); diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp index 570424a79c81..e27659494f08 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp @@ -414,6 +414,8 @@ void DIEInteger::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const { case dwarf::DW_FORM_GNU_addr_index: case dwarf::DW_FORM_ref_udata: case dwarf::DW_FORM_strx: + case dwarf::DW_FORM_addrx: + case dwarf::DW_FORM_rnglistx: case dwarf::DW_FORM_udata: Asm->EmitULEB128(Integer); return; @@ -440,6 +442,8 @@ unsigned DIEInteger::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { case dwarf::DW_FORM_GNU_addr_index: case dwarf::DW_FORM_ref_udata: case dwarf::DW_FORM_strx: + case dwarf::DW_FORM_addrx: + case dwarf::DW_FORM_rnglistx: case dwarf::DW_FORM_udata: return getULEB128Size(Integer); case dwarf::DW_FORM_sdata: @@ -461,7 +465,7 @@ void DIEInteger::print(raw_ostream &O) const { /// EmitValue - Emit expression value. /// void DIEExpr::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { - AP->EmitDebugThreadLocal(Expr, SizeOf(AP, Form)); + AP->EmitDebugValue(Expr, SizeOf(AP, Form)); } /// SizeOf - Determine size of expression value in bytes. @@ -585,8 +589,7 @@ void DIEString::print(raw_ostream &O) const { //===----------------------------------------------------------------------===// void DIEInlineString::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const { if (Form == dwarf::DW_FORM_string) { - for (char ch : S) - AP->emitInt8(ch); + AP->OutStreamer->EmitBytes(S); AP->emitInt8(0); return; } diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp index 25518a339c61..09867822c30a 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp @@ -1,4 +1,4 @@ -//===- llvm/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp --------------===// +//===- llvm/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp -------------===// // // The LLVM Compiler Infrastructure // @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "DbgValueHistoryCalculator.h" +#include "llvm/CodeGen/DbgEntityHistoryCalculator.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" @@ -42,7 +42,7 @@ static unsigned isDescribedByReg(const MachineInstr &MI) { return MI.getOperand(0).isReg() ? MI.getOperand(0).getReg() : 0; } -void DbgValueHistoryMap::startInstrRange(InlinedVariable Var, +void DbgValueHistoryMap::startInstrRange(InlinedEntity Var, const MachineInstr &MI) { // Instruction range should start with a DBG_VALUE instruction for the // variable. @@ -57,7 +57,7 @@ void DbgValueHistoryMap::startInstrRange(InlinedVariable Var, Ranges.push_back(std::make_pair(&MI, nullptr)); } -void DbgValueHistoryMap::endInstrRange(InlinedVariable Var, +void DbgValueHistoryMap::endInstrRange(InlinedEntity Var, const MachineInstr &MI) { auto &Ranges = VarInstrRanges[Var]; // Verify that the current instruction range is not yet closed. @@ -68,7 +68,7 @@ void DbgValueHistoryMap::endInstrRange(InlinedVariable Var, Ranges.back().second = &MI; } -unsigned DbgValueHistoryMap::getRegisterForVar(InlinedVariable Var) const { +unsigned DbgValueHistoryMap::getRegisterForVar(InlinedEntity Var) const { const auto &I = VarInstrRanges.find(Var); if (I == VarInstrRanges.end()) return 0; @@ -78,17 +78,22 @@ unsigned DbgValueHistoryMap::getRegisterForVar(InlinedVariable Var) const { return isDescribedByReg(*Ranges.back().first); } +void DbgLabelInstrMap::addInstr(InlinedEntity Label, const MachineInstr &MI) { + assert(MI.isDebugLabel() && "not a DBG_LABEL"); + LabelInstr[Label] = &MI; +} + namespace { // Maps physreg numbers to the variables they describe. -using InlinedVariable = DbgValueHistoryMap::InlinedVariable; -using RegDescribedVarsMap = std::map<unsigned, SmallVector<InlinedVariable, 1>>; +using InlinedEntity = DbgValueHistoryMap::InlinedEntity; +using RegDescribedVarsMap = std::map<unsigned, SmallVector<InlinedEntity, 1>>; } // end anonymous namespace // Claim that @Var is not described by @RegNo anymore. static void dropRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo, - InlinedVariable Var) { + InlinedEntity Var) { const auto &I = RegVars.find(RegNo); assert(RegNo != 0U && I != RegVars.end()); auto &VarSet = I->second; @@ -102,7 +107,7 @@ static void dropRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo, // Claim that @Var is now described by @RegNo. static void addRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo, - InlinedVariable Var) { + InlinedEntity Var) { assert(RegNo != 0U); auto &VarSet = RegVars[RegNo]; assert(!is_contained(VarSet, Var)); @@ -187,9 +192,10 @@ static void collectChangingRegs(const MachineFunction *MF, } } -void llvm::calculateDbgValueHistory(const MachineFunction *MF, - const TargetRegisterInfo *TRI, - DbgValueHistoryMap &Result) { +void llvm::calculateDbgEntityHistory(const MachineFunction *MF, + const TargetRegisterInfo *TRI, + DbgValueHistoryMap &DbgValues, + DbgLabelInstrMap &DbgLabels) { BitVector ChangingRegs(TRI->getNumRegs()); collectChangingRegs(MF, TRI, ChangingRegs); @@ -210,14 +216,14 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF, // If this is a virtual register, only clobber it since it doesn't // have aliases. if (TRI->isVirtualRegister(MO.getReg())) - clobberRegisterUses(RegVars, MO.getReg(), Result, MI); + clobberRegisterUses(RegVars, MO.getReg(), DbgValues, MI); // If this is a register def operand, it may end a debug value // range. else { for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); ++AI) if (ChangingRegs.test(*AI)) - clobberRegisterUses(RegVars, *AI, Result, MI); + clobberRegisterUses(RegVars, *AI, DbgValues, MI); } } else if (MO.isRegMask()) { // If this is a register mask operand, clobber all debug values in @@ -226,7 +232,7 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF, // Don't consider SP to be clobbered by register masks. if (unsigned(I) != SP && TRI->isPhysicalRegister(I) && MO.clobbersPhysReg(I)) { - clobberRegisterUses(RegVars, I, Result, MI); + clobberRegisterUses(RegVars, I, DbgValues, MI); } } } @@ -234,26 +240,34 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF, continue; } - // Skip DBG_LABEL instructions. - if (MI.isDebugLabel()) - continue; - - assert(MI.getNumOperands() > 1 && "Invalid DBG_VALUE instruction!"); - // Use the base variable (without any DW_OP_piece expressions) - // as index into History. The full variables including the - // piece expressions are attached to the MI. - const DILocalVariable *RawVar = MI.getDebugVariable(); - assert(RawVar->isValidLocationForIntrinsic(MI.getDebugLoc()) && - "Expected inlined-at fields to agree"); - InlinedVariable Var(RawVar, MI.getDebugLoc()->getInlinedAt()); - - if (unsigned PrevReg = Result.getRegisterForVar(Var)) - dropRegDescribedVar(RegVars, PrevReg, Var); - - Result.startInstrRange(Var, MI); - - if (unsigned NewReg = isDescribedByReg(MI)) - addRegDescribedVar(RegVars, NewReg, Var); + if (MI.isDebugValue()) { + assert(MI.getNumOperands() > 1 && "Invalid DBG_VALUE instruction!"); + // Use the base variable (without any DW_OP_piece expressions) + // as index into History. The full variables including the + // piece expressions are attached to the MI. + const DILocalVariable *RawVar = MI.getDebugVariable(); + assert(RawVar->isValidLocationForIntrinsic(MI.getDebugLoc()) && + "Expected inlined-at fields to agree"); + InlinedEntity Var(RawVar, MI.getDebugLoc()->getInlinedAt()); + + if (unsigned PrevReg = DbgValues.getRegisterForVar(Var)) + dropRegDescribedVar(RegVars, PrevReg, Var); + + DbgValues.startInstrRange(Var, MI); + + if (unsigned NewReg = isDescribedByReg(MI)) + addRegDescribedVar(RegVars, NewReg, Var); + } else if (MI.isDebugLabel()) { + assert(MI.getNumOperands() == 1 && "Invalid DBG_LABEL instruction!"); + const DILabel *RawLabel = MI.getDebugLabel(); + assert(RawLabel->isValidLocationForIntrinsic(MI.getDebugLoc()) && + "Expected inlined-at fields to agree"); + // When collecting debug information for labels, there is no MCSymbol + // generated for it. So, we keep MachineInstr in DbgLabels in order + // to query MCSymbol afterward. + InlinedEntity L(RawLabel, MI.getDebugLoc()->getInlinedAt()); + DbgLabels.addInstr(L, MI); + } } // Make sure locations for register-described variables are valid only @@ -264,7 +278,7 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF, auto CurElem = I++; // CurElem can be erased below. if (TRI->isVirtualRegister(CurElem->first) || ChangingRegs.test(CurElem->first)) - clobberRegisterUses(RegVars, CurElem, Result, MBB.back()); + clobberRegisterUses(RegVars, CurElem, DbgValues, MBB.back()); } } } @@ -274,10 +288,10 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF, LLVM_DUMP_METHOD void DbgValueHistoryMap::dump() const { dbgs() << "DbgValueHistoryMap:\n"; for (const auto &VarRangePair : *this) { - const InlinedVariable &Var = VarRangePair.first; + const InlinedEntity &Var = VarRangePair.first; const InstrRanges &Ranges = VarRangePair.second; - const DILocalVariable *LocalVar = Var.first; + const DILocalVariable *LocalVar = cast<DILocalVariable>(Var.first); const DILocation *Location = Var.second; dbgs() << " - " << LocalVar->getName() << " at "; diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h deleted file mode 100644 index a262cb38b175..000000000000 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h +++ /dev/null @@ -1,67 +0,0 @@ -//===- llvm/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H -#define LLVM_LIB_CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H - -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/IR/DebugInfoMetadata.h" -#include <utility> - -namespace llvm { - -class DILocalVariable; -class MachineFunction; -class MachineInstr; -class TargetRegisterInfo; - -// For each user variable, keep a list of instruction ranges where this variable -// is accessible. The variables are listed in order of appearance. -class DbgValueHistoryMap { - // Each instruction range starts with a DBG_VALUE instruction, specifying the - // location of a variable, which is assumed to be valid until the end of the - // range. If end is not specified, location is valid until the start - // instruction of the next instruction range, or until the end of the - // function. -public: - using InstrRange = std::pair<const MachineInstr *, const MachineInstr *>; - using InstrRanges = SmallVector<InstrRange, 4>; - using InlinedVariable = - std::pair<const DILocalVariable *, const DILocation *>; - using InstrRangesMap = MapVector<InlinedVariable, InstrRanges>; - -private: - InstrRangesMap VarInstrRanges; - -public: - void startInstrRange(InlinedVariable Var, const MachineInstr &MI); - void endInstrRange(InlinedVariable Var, const MachineInstr &MI); - - // Returns register currently describing @Var. If @Var is currently - // unaccessible or is not described by a register, returns 0. - unsigned getRegisterForVar(InlinedVariable Var) const; - - bool empty() const { return VarInstrRanges.empty(); } - void clear() { VarInstrRanges.clear(); } - InstrRangesMap::const_iterator begin() const { return VarInstrRanges.begin(); } - InstrRangesMap::const_iterator end() const { return VarInstrRanges.end(); } - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - LLVM_DUMP_METHOD void dump() const; -#endif -}; - -void calculateDbgValueHistory(const MachineFunction *MF, - const TargetRegisterInfo *TRI, - DbgValueHistoryMap &Result); - -} // end namespace llvm - -#endif // LLVM_LIB_CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp index 82e14dc13cb1..551cd36d1984 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -#include "DebugHandlerBase.h" +#include "llvm/CodeGen/DebugHandlerBase.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/AsmPrinter.h" @@ -125,6 +125,21 @@ MCSymbol *DebugHandlerBase::getLabelAfterInsn(const MachineInstr *MI) { return LabelsAfterInsn.lookup(MI); } +// Return the function-local offset of an instruction. +const MCExpr * +DebugHandlerBase::getFunctionLocalOffsetAfterInsn(const MachineInstr *MI) { + MCContext &MC = Asm->OutContext; + + MCSymbol *Start = Asm->getFunctionBegin(); + const auto *StartRef = MCSymbolRefExpr::create(Start, MC); + + MCSymbol *AfterInsn = getLabelAfterInsn(MI); + assert(AfterInsn && "Expected label after instruction"); + const auto *AfterRef = MCSymbolRefExpr::create(AfterInsn, MC); + + return MCBinaryExpr::createSub(AfterRef, StartRef, MC); +} + /// If this type is derived from a base type then return base type size. uint64_t DebugHandlerBase::getBaseTypeSize(const DITypeRef TyRef) { DIType *Ty = TyRef.resolve(); @@ -190,8 +205,9 @@ void DebugHandlerBase::beginFunction(const MachineFunction *MF) { // Calculate history for local variables. assert(DbgValues.empty() && "DbgValues map wasn't cleaned!"); - calculateDbgValueHistory(MF, Asm->MF->getSubtarget().getRegisterInfo(), - DbgValues); + assert(DbgLabels.empty() && "DbgLabels map wasn't cleaned!"); + calculateDbgEntityHistory(MF, Asm->MF->getSubtarget().getRegisterInfo(), + DbgValues, DbgLabels); LLVM_DEBUG(DbgValues.dump()); // Request labels for the full history. @@ -229,6 +245,12 @@ void DebugHandlerBase::beginFunction(const MachineFunction *MF) { } } + // Ensure there is a symbol before DBG_LABEL. + for (const auto &I : DbgLabels) { + const MachineInstr *MI = I.second; + requestLabelBeforeInsn(MI); + } + PrevInstLoc = DebugLoc(); PrevLabel = Asm->getFunctionBegin(); beginFunctionImpl(MF); @@ -296,6 +318,7 @@ void DebugHandlerBase::endFunction(const MachineFunction *MF) { if (hasDebugInfo(MMI, MF)) endFunctionImpl(MF); DbgValues.clear(); + DbgLabels.clear(); LabelsBeforeInsn.clear(); LabelsAfterInsn.clear(); } diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h deleted file mode 100644 index 1ccefe32be75..000000000000 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h +++ /dev/null @@ -1,131 +0,0 @@ -//===-- llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h --------*- C++ -*--===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Common functionality for different debug information format backends. -// LLVM currently supports DWARF and CodeView. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGHANDLERBASE_H -#define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGHANDLERBASE_H - -#include "AsmPrinterHandler.h" -#include "DbgValueHistoryCalculator.h" -#include "llvm/ADT/Optional.h" -#include "llvm/CodeGen/LexicalScopes.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/IR/DebugInfoMetadata.h" - -namespace llvm { - -class AsmPrinter; -class MachineInstr; -class MachineModuleInfo; - -/// Represents the location at which a variable is stored. -struct DbgVariableLocation { - /// Base register. - unsigned Register; - - /// Chain of offsetted loads necessary to load the value if it lives in - /// memory. Every load except for the last is pointer-sized. - SmallVector<int64_t, 1> LoadChain; - - /// Present if the location is part of a larger variable. - llvm::Optional<llvm::DIExpression::FragmentInfo> FragmentInfo; - - /// Extract a VariableLocation from a MachineInstr. - /// This will only work if Instruction is a debug value instruction - /// and the associated DIExpression is in one of the supported forms. - /// If these requirements are not met, the returned Optional will not - /// have a value. - static Optional<DbgVariableLocation> - extractFromMachineInstruction(const MachineInstr &Instruction); -}; - -/// Base class for debug information backends. Common functionality related to -/// tracking which variables and scopes are alive at a given PC live here. -class DebugHandlerBase : public AsmPrinterHandler { -protected: - DebugHandlerBase(AsmPrinter *A); - - /// Target of debug info emission. - AsmPrinter *Asm; - - /// Collected machine module information. - MachineModuleInfo *MMI; - - /// Previous instruction's location information. This is used to - /// determine label location to indicate scope boundaries in debug info. - /// We track the previous instruction's source location (if not line 0), - /// whether it was a label, and its parent BB. - DebugLoc PrevInstLoc; - MCSymbol *PrevLabel = nullptr; - const MachineBasicBlock *PrevInstBB = nullptr; - - /// This location indicates end of function prologue and beginning of - /// function body. - DebugLoc PrologEndLoc; - - /// If nonnull, stores the current machine instruction we're processing. - const MachineInstr *CurMI = nullptr; - - LexicalScopes LScopes; - - /// History of DBG_VALUE and clobber instructions for each user - /// variable. Variables are listed in order of appearance. - DbgValueHistoryMap DbgValues; - - /// Maps instruction with label emitted before instruction. - /// FIXME: Make this private from DwarfDebug, we have the necessary accessors - /// for it. - DenseMap<const MachineInstr *, MCSymbol *> LabelsBeforeInsn; - - /// Maps instruction with label emitted after instruction. - DenseMap<const MachineInstr *, MCSymbol *> LabelsAfterInsn; - - /// Indentify instructions that are marking the beginning of or - /// ending of a scope. - void identifyScopeMarkers(); - - /// Ensure that a label will be emitted before MI. - void requestLabelBeforeInsn(const MachineInstr *MI) { - LabelsBeforeInsn.insert(std::make_pair(MI, nullptr)); - } - - /// Ensure that a label will be emitted after MI. - void requestLabelAfterInsn(const MachineInstr *MI) { - LabelsAfterInsn.insert(std::make_pair(MI, nullptr)); - } - - virtual void beginFunctionImpl(const MachineFunction *MF) = 0; - virtual void endFunctionImpl(const MachineFunction *MF) = 0; - virtual void skippedNonDebugFunction() {} - - // AsmPrinterHandler overrides. -public: - void beginInstruction(const MachineInstr *MI) override; - void endInstruction() override; - - void beginFunction(const MachineFunction *MF) override; - void endFunction(const MachineFunction *MF) override; - - /// Return Label preceding the instruction. - MCSymbol *getLabelBeforeInsn(const MachineInstr *MI); - - /// Return Label immediately following the instruction. - MCSymbol *getLabelAfterInsn(const MachineInstr *MI); - - /// If this type is derived from a base type then return base type size. - static uint64_t getBaseTypeSize(const DITypeRef TyRef); -}; - -} - -#endif diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h index ac49657b68fa..befa4b941c8d 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h @@ -139,7 +139,7 @@ public: // Sort the pieces by offset. // Remove any duplicate entries by dropping all but the first. void sortUniqueValues() { - llvm::sort(Values.begin(), Values.end()); + llvm::sort(Values); Values.erase( std::unique( Values.begin(), Values.end(), [](const Value &A, const Value &B) { diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp index 32271a0ef24a..1dca3f0fce5b 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -69,14 +69,16 @@ void DwarfCompileUnit::addLabelAddress(DIE &Die, dwarf::Attribute Attribute, // pool from the skeleton - maybe even in non-fission (possibly fewer // relocations by sharing them in the pool, but we have other ideas about how // to reduce the number of relocations as well/instead). - if (!DD->useSplitDwarf() || !Skeleton) + if ((!DD->useSplitDwarf() || !Skeleton) && DD->getDwarfVersion() < 5) return addLocalLabelAddress(Die, Attribute, Label); if (Label) DD->addArangeLabel(SymbolCU(this, Label)); unsigned idx = DD->getAddressPool().getIndex(Label); - Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_GNU_addr_index, + Die.addValue(DIEValueAllocator, Attribute, + DD->getDwarfVersion() >= 5 ? dwarf::DW_FORM_addrx + : dwarf::DW_FORM_GNU_addr_index, DIEInteger(idx)); } @@ -160,6 +162,9 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE( addUInt(*VariableDIE, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata, AlignInBytes); + if (MDTuple *TP = GV->getTemplateParams()) + addTemplateParams(*VariableDIE, DINodeArray(TP)); + // Add location. bool addToAccelTable = false; DIELoc *Loc = nullptr; @@ -186,6 +191,10 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE( if (!Global && (!Expr || !Expr->isConstant())) continue; + if (Global && Global->isThreadLocal() && + !Asm->getObjFileLowering().supportDebugThreadLocalLocation()) + continue; + if (!Loc) { addToAccelTable = true; Loc = new (DIEValueAllocator) DIELoc; @@ -245,13 +254,13 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE( addLinkageName(*VariableDIE, GV->getLinkageName()); if (addToAccelTable) { - DD->addAccelName(GV->getName(), *VariableDIE); + DD->addAccelName(*CUNode, GV->getName(), *VariableDIE); // If the linkage name is different than the name, go ahead and output // that as well into the name table. if (GV->getLinkageName() != "" && GV->getName() != GV->getLinkageName() && DD->useAllLinkageNames()) - DD->addAccelName(GV->getLinkageName(), *VariableDIE); + DD->addAccelName(*CUNode, GV->getLinkageName(), *VariableDIE); } return VariableDIE; @@ -268,6 +277,7 @@ void DwarfCompileUnit::addRange(RangeSpan Range) { (&CURanges.back().getEnd()->getSection() != &Range.getEnd()->getSection())) { CURanges.push_back(Range); + DD->addSectionLabel(Range.getStart()); return; } @@ -275,6 +285,9 @@ void DwarfCompileUnit::addRange(RangeSpan Range) { } void DwarfCompileUnit::initStmtList() { + if (CUNode->isDebugDirectivesOnly()) + return; + // Define start line table label for each Compile Unit. MCSymbol *LineTableStartSym; const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); @@ -341,7 +354,7 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) { // Add name to the name table, we do this here because we're guaranteed // to have concrete versions of our DW_TAG_subprogram nodes. - DD->addSubprogramNames(SP, *SPDie); + DD->addSubprogramNames(*CUNode, SP, *SPDie); return *SPDie; } @@ -412,24 +425,29 @@ void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE, ? TLOF.getDwarfRnglistsSection()->getBeginSymbol() : TLOF.getDwarfRangesSection()->getBeginSymbol(); - RangeSpanList List(Asm->createTempSymbol("debug_ranges"), std::move(Range)); + HasRangeLists = true; + + // Add the range list to the set of ranges to be emitted. + auto IndexAndList = + (DD->getDwarfVersion() < 5 && Skeleton ? Skeleton->DU : DU) + ->addRange(*(Skeleton ? Skeleton : this), std::move(Range)); + + uint32_t Index = IndexAndList.first; + auto &List = *IndexAndList.second; // Under fission, ranges are specified by constant offsets relative to the // CU's DW_AT_GNU_ranges_base. // FIXME: For DWARF v5, do not generate the DW_AT_ranges attribute under // fission until we support the forms using the .debug_addr section // (DW_RLE_startx_endx etc.). - if (isDwoUnit()) { - if (DD->getDwarfVersion() < 5) - addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(), - RangeSectionSym); - } else { + if (DD->getDwarfVersion() >= 5) + addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_rnglistx, Index); + else if (isDwoUnit()) + addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(), + RangeSectionSym); + else addSectionLabel(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(), RangeSectionSym); - } - - // Add the range list to the set of ranges to be emitted. - (Skeleton ? Skeleton : this)->CURangeLists.push_back(std::move(List)); } void DwarfCompileUnit::attachRangesOrLowHighPC( @@ -479,7 +497,7 @@ DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope) { // Add name to the name table, we do this here because we're guaranteed // to have concrete versions of our DW_TAG_inlined_subprogram nodes. - DD->addSubprogramNames(InlinedSP, *ScopeDIE); + DD->addSubprogramNames(*CUNode, InlinedSP, *ScopeDIE); return ScopeDIE; } @@ -506,6 +524,18 @@ DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV, bool Abstract) { return D; } +DIE *DwarfCompileUnit::constructLabelDIE(DbgLabel &DL, + const LexicalScope &Scope) { + auto LabelDie = DIE::get(DIEValueAllocator, DL.getTag()); + insertDIE(DL.getLabel(), LabelDie); + DL.setDIE(*LabelDie); + + if (Scope.isAbstractScope()) + applyLabelAttributes(DL, *LabelDie); + + return LabelDie; +} + DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV, bool Abstract) { // Define variable debug information entry. @@ -699,13 +729,17 @@ DIE *DwarfCompileUnit::createScopeChildrenDIE(LexicalScope *Scope, if (HasNonScopeChildren) *HasNonScopeChildren = !Children.empty(); + for (DbgLabel *DL : DU->getScopeLabels().lookup(Scope)) + Children.push_back(constructLabelDIE(*DL, *Scope)); + for (LexicalScope *LS : Scope->getChildren()) constructScopeDIE(LS, Children); return ObjectPointer; } -void DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope) { +DIE &DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub, + LexicalScope *Scope) { DIE &ScopeDIE = updateSubprogramScopeDIE(Sub); if (Scope) { @@ -728,6 +762,8 @@ void DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub, Lexi !includeMinimalInlineScopes()) ScopeDIE.addChild( DIE::get(DIEValueAllocator, dwarf::DW_TAG_unspecified_parameters)); + + return ScopeDIE; } DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope, @@ -782,6 +818,32 @@ void DwarfCompileUnit::constructAbstractSubprogramScopeDIE( ContextCU->addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer); } +DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE, + const DISubprogram &CalleeSP, + bool IsTail, + const MCExpr *PCOffset) { + // Insert a call site entry DIE within ScopeDIE. + DIE &CallSiteDIE = + createAndAddDIE(dwarf::DW_TAG_call_site, ScopeDIE, nullptr); + + // For the purposes of showing tail call frames in backtraces, a key piece of + // information is DW_AT_call_origin, a pointer to the callee DIE. + DIE *CalleeDIE = getOrCreateSubprogramDIE(&CalleeSP); + assert(CalleeDIE && "Could not create DIE for call site entry origin"); + addDIEEntry(CallSiteDIE, dwarf::DW_AT_call_origin, *CalleeDIE); + + if (IsTail) { + // Attach DW_AT_call_tail_call to tail calls for standards compliance. + addFlag(CallSiteDIE, dwarf::DW_AT_call_tail_call); + } else { + // Attach the return PC to allow the debugger to disambiguate call paths + // from one function to another. + assert(PCOffset && "Missing return PC information for a call"); + addAddressExpr(CallSiteDIE, dwarf::DW_AT_call_return_pc, PCOffset); + } + return CallSiteDIE; +} + DIE *DwarfCompileUnit::constructImportedEntityDIE( const DIImportedEntity *Module) { DIE *IMDie = DIE::get(DIEValueAllocator, (dwarf::Tag)Module->getTag()); @@ -824,40 +886,51 @@ void DwarfCompileUnit::finishSubprogramDefinition(const DISubprogram *SP) { } } -void DwarfCompileUnit::finishVariableDefinition(const DbgVariable &Var) { - DbgVariable *AbsVar = getExistingAbstractVariable( - InlinedVariable(Var.getVariable(), Var.getInlinedAt())); - auto *VariableDie = Var.getDIE(); - if (AbsVar && AbsVar->getDIE()) { - addDIEEntry(*VariableDie, dwarf::DW_AT_abstract_origin, - *AbsVar->getDIE()); - } else - applyVariableAttributes(Var, *VariableDie); -} +void DwarfCompileUnit::finishEntityDefinition(const DbgEntity *Entity) { + DbgEntity *AbsEntity = getExistingAbstractEntity(Entity->getEntity()); -DbgVariable *DwarfCompileUnit::getExistingAbstractVariable(InlinedVariable IV) { - const DILocalVariable *Cleansed; - return getExistingAbstractVariable(IV, Cleansed); + auto *Die = Entity->getDIE(); + /// Label may be used to generate DW_AT_low_pc, so put it outside + /// if/else block. + const DbgLabel *Label = nullptr; + if (AbsEntity && AbsEntity->getDIE()) { + addDIEEntry(*Die, dwarf::DW_AT_abstract_origin, *AbsEntity->getDIE()); + Label = dyn_cast<const DbgLabel>(Entity); + } else { + if (const DbgVariable *Var = dyn_cast<const DbgVariable>(Entity)) + applyVariableAttributes(*Var, *Die); + else if ((Label = dyn_cast<const DbgLabel>(Entity))) + applyLabelAttributes(*Label, *Die); + else + llvm_unreachable("DbgEntity must be DbgVariable or DbgLabel."); + } + + if (Label) + if (const auto *Sym = Label->getSymbol()) + addLabelAddress(*Die, dwarf::DW_AT_low_pc, Sym); } -// Find abstract variable, if any, associated with Var. -DbgVariable *DwarfCompileUnit::getExistingAbstractVariable( - InlinedVariable IV, const DILocalVariable *&Cleansed) { - // More then one inlined variable corresponds to one abstract variable. - Cleansed = IV.first; - auto &AbstractVariables = getAbstractVariables(); - auto I = AbstractVariables.find(Cleansed); - if (I != AbstractVariables.end()) +DbgEntity *DwarfCompileUnit::getExistingAbstractEntity(const DINode *Node) { + auto &AbstractEntities = getAbstractEntities(); + auto I = AbstractEntities.find(Node); + if (I != AbstractEntities.end()) return I->second.get(); return nullptr; } -void DwarfCompileUnit::createAbstractVariable(const DILocalVariable *Var, - LexicalScope *Scope) { +void DwarfCompileUnit::createAbstractEntity(const DINode *Node, + LexicalScope *Scope) { assert(Scope && Scope->isAbstractScope()); - auto AbsDbgVariable = llvm::make_unique<DbgVariable>(Var, /* IA */ nullptr); - DU->addScopeVariable(Scope, AbsDbgVariable.get()); - getAbstractVariables()[Var] = std::move(AbsDbgVariable); + auto &Entity = getAbstractEntities()[Node]; + if (isa<const DILocalVariable>(Node)) { + Entity = llvm::make_unique<DbgVariable>( + cast<const DILocalVariable>(Node), nullptr /* IA */);; + DU->addScopeVariable(Scope, cast<DbgVariable>(Entity.get())); + } else if (isa<const DILabel>(Node)) { + Entity = llvm::make_unique<DbgLabel>( + cast<const DILabel>(Node), nullptr /* IA */); + DU->addScopeLabel(Scope, cast<DbgLabel>(Entity.get())); + } } void DwarfCompileUnit::emitHeader(bool UseOffsets) { @@ -876,13 +949,18 @@ void DwarfCompileUnit::emitHeader(bool UseOffsets) { } bool DwarfCompileUnit::hasDwarfPubSections() const { - // Opting in to GNU Pubnames/types overrides the default to ensure these are - // generated for things like Gold's gdb_index generation. - if (CUNode->getGnuPubnames()) + switch (CUNode->getNameTableKind()) { + case DICompileUnit::DebugNameTableKind::None: + return false; + // Opting in to GNU Pubnames/types overrides the default to ensure these are + // generated for things like Gold's gdb_index generation. + case DICompileUnit::DebugNameTableKind::GNU: return true; - - return DD->tuneForGDB() && DD->usePubSections() && - !includeMinimalInlineScopes(); + case DICompileUnit::DebugNameTableKind::Default: + return DD->tuneForGDB() && !includeMinimalInlineScopes() && + !CUNode->isDebugDirectivesOnly(); + } + llvm_unreachable("Unhandled DICompileUnit::DebugNameTableKind enum"); } /// addGlobalName - Add a new global name to the compile unit. @@ -939,8 +1017,6 @@ void DwarfCompileUnit::addVariableAddress(const DbgVariable &DV, DIE &Die, "block byref variable without a complex expression"); if (DV.hasComplexAddress()) addComplexAddress(DV, Die, dwarf::DW_AT_location, Location); - else if (DV.isBlockByrefVariable()) - addBlockByrefAddress(DV, Die, dwarf::DW_AT_location, Location); else addAddress(Die, dwarf::DW_AT_location, Location); } @@ -1012,12 +1088,27 @@ void DwarfCompileUnit::applyVariableAttributes(const DbgVariable &Var, addFlag(VariableDie, dwarf::DW_AT_artificial); } +void DwarfCompileUnit::applyLabelAttributes(const DbgLabel &Label, + DIE &LabelDie) { + StringRef Name = Label.getName(); + if (!Name.empty()) + addString(LabelDie, dwarf::DW_AT_name, Name); + const auto *DILabel = Label.getLabel(); + addSourceLine(LabelDie, DILabel); +} + /// Add a Dwarf expression attribute data and value. void DwarfCompileUnit::addExpr(DIELoc &Die, dwarf::Form Form, const MCExpr *Expr) { Die.addValue(DIEValueAllocator, (dwarf::Attribute)0, Form, DIEExpr(Expr)); } +void DwarfCompileUnit::addAddressExpr(DIE &Die, dwarf::Attribute Attribute, + const MCExpr *Expr) { + Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_addr, + DIEExpr(Expr)); +} + void DwarfCompileUnit::applySubprogramAttributesToDefinition( const DISubprogram *SP, DIE &SPDie) { auto *SPDecl = SP->getDeclaration(); @@ -1034,3 +1125,12 @@ bool DwarfCompileUnit::includeMinimalInlineScopes() const { return getCUNode()->getEmissionKind() == DICompileUnit::LineTablesOnly || (DD->useSplitDwarf() && !Skeleton); } + +void DwarfCompileUnit::addAddrTableBase() { + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + MCSymbol *Label = DD->getAddressPool().getLabel(); + addSectionLabel(getUnitDie(), + getDwarfVersion() >= 5 ? dwarf::DW_AT_addr_base + : dwarf::DW_AT_GNU_addr_base, + Label, TLOF.getDwarfAddrSection()->getBeginSymbol()); +} diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h index 51e1558fe4a3..9ec22f68c12f 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -14,7 +14,6 @@ #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H #define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H -#include "DbgValueHistoryCalculator.h" #include "DwarfDebug.h" #include "DwarfUnit.h" #include "llvm/ADT/ArrayRef.h" @@ -23,6 +22,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/CodeGen/DbgEntityHistoryCalculator.h" #include "llvm/CodeGen/DIE.h" #include "llvm/CodeGen/LexicalScopes.h" #include "llvm/IR/DebugInfoMetadata.h" @@ -44,6 +44,7 @@ class MDNode; class DwarfCompileUnit final : public DwarfUnit { /// A numeric ID unique among all CUs in the module unsigned UniqueID; + bool HasRangeLists = false; /// The attribute index of DW_AT_stmt_list in the compile unit DIE, avoiding /// the need to search for it in applyStmtList. @@ -69,10 +70,6 @@ class DwarfCompileUnit final : public DwarfUnit { /// GlobalTypes - A map of globally visible types for this unit. StringMap<const DIE *> GlobalTypes; - // List of range lists for a given compile unit, separate from the ranges for - // the CU itself. - SmallVector<RangeSpanList, 1> CURangeLists; - // List of ranges for a given compile unit. SmallVector<RangeSpan, 2> CURanges; @@ -81,7 +78,7 @@ class DwarfCompileUnit final : public DwarfUnit { const MCSymbol *BaseAddress = nullptr; DenseMap<const MDNode *, DIE *> AbstractSPDies; - DenseMap<const MDNode *, std::unique_ptr<DbgVariable>> AbstractVariables; + DenseMap<const DINode *, std::unique_ptr<DbgEntity>> AbstractEntities; /// DWO ID for correlating skeleton and split units. uint64_t DWOId = 0; @@ -98,16 +95,17 @@ class DwarfCompileUnit final : public DwarfUnit { return DU->getAbstractSPDies(); } - DenseMap<const MDNode *, std::unique_ptr<DbgVariable>> &getAbstractVariables() { + DenseMap<const DINode *, std::unique_ptr<DbgEntity>> &getAbstractEntities() { if (isDwoUnit() && !DD->shareAcrossDWOCUs()) - return AbstractVariables; - return DU->getAbstractVariables(); + return AbstractEntities; + return DU->getAbstractEntities(); } public: DwarfCompileUnit(unsigned UID, const DICompileUnit *Node, AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU); + bool hasRangeLists() const { return HasRangeLists; } unsigned getUniqueID() const { return UniqueID; } DwarfCompileUnit *getSkeleton() const { @@ -194,30 +192,39 @@ public: DIE *constructVariableDIE(DbgVariable &DV, const LexicalScope &Scope, DIE *&ObjectPointer); + /// Construct a DIE for the given DbgLabel. + DIE *constructLabelDIE(DbgLabel &DL, const LexicalScope &Scope); + /// A helper function to create children of a Scope DIE. DIE *createScopeChildrenDIE(LexicalScope *Scope, SmallVectorImpl<DIE *> &Children, bool *HasNonScopeChildren = nullptr); /// Construct a DIE for this subprogram scope. - void constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope); + DIE &constructSubprogramScopeDIE(const DISubprogram *Sub, + LexicalScope *Scope); DIE *createAndAddScopeChildren(LexicalScope *Scope, DIE &ScopeDIE); void constructAbstractSubprogramScopeDIE(LexicalScope *Scope); + /// Construct a call site entry DIE describing a call within \p Scope to a + /// callee described by \p CalleeSP. \p IsTail specifies whether the call is + /// a tail call. \p PCOffset must be non-zero for non-tail calls or be the + /// function-local offset to PC value after the call instruction. + DIE &constructCallSiteEntryDIE(DIE &ScopeDIE, const DISubprogram &CalleeSP, + bool IsTail, const MCExpr *PCOffset); + /// Construct import_module DIE. DIE *constructImportedEntityDIE(const DIImportedEntity *Module); void finishSubprogramDefinition(const DISubprogram *SP); - void finishVariableDefinition(const DbgVariable &Var); + void finishEntityDefinition(const DbgEntity *Entity); /// Find abstract variable associated with Var. - using InlinedVariable = DbgValueHistoryMap::InlinedVariable; - DbgVariable *getExistingAbstractVariable(InlinedVariable IV, - const DILocalVariable *&Cleansed); - DbgVariable *getExistingAbstractVariable(InlinedVariable IV); - void createAbstractVariable(const DILocalVariable *Var, LexicalScope *Scope); + using InlinedEntity = DbgValueHistoryMap::InlinedEntity; + DbgEntity *getExistingAbstractEntity(const DINode *Node); + void createAbstractEntity(const DINode *Node, LexicalScope *Scope); /// Set the skeleton unit associated with this unit. void setSkeleton(DwarfCompileUnit &Skel) { Skeleton = &Skel; } @@ -236,6 +243,9 @@ public: void emitHeader(bool UseOffsets) override; + /// Add the DW_AT_addr_base attribute to the unit DIE. + void addAddrTableBase(); + MCSymbol *getLabelBegin() const { assert(getSection()); return LabelBegin; @@ -285,13 +295,13 @@ public: /// Add a Dwarf expression attribute data and value. void addExpr(DIELoc &Die, dwarf::Form Form, const MCExpr *Expr); + /// Add an attribute containing an address expression to \p Die. + void addAddressExpr(DIE &Die, dwarf::Attribute Attribute, const MCExpr *Expr); + void applySubprogramAttributesToDefinition(const DISubprogram *SP, DIE &SPDie); - /// getRangeLists - Get the vector of range lists. - const SmallVectorImpl<RangeSpanList> &getRangeLists() const { - return (Skeleton ? Skeleton : this)->CURangeLists; - } + void applyLabelAttributes(const DbgLabel &Label, DIE &LabelDie); /// getRanges - Get the list of ranges for this unit. const SmallVectorImpl<RangeSpan> &getRanges() const { return CURanges; } diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 19b3afef34b5..1de2ffb6cfa1 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -39,6 +39,7 @@ #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineOperand.h" +#include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/Constants.h" @@ -130,11 +131,6 @@ DwarfInlinedStrings("dwarf-inlined-strings", cl::Hidden, cl::init(Default)); static cl::opt<bool> - NoDwarfPubSections("no-dwarf-pub-sections", cl::Hidden, - cl::desc("Disable emission of DWARF pub sections."), - cl::init(false)); - -static cl::opt<bool> NoDwarfRangesSection("no-dwarf-ranges-section", cl::Hidden, cl::desc("Disable emission .debug_ranges section."), cl::init(false)); @@ -188,12 +184,12 @@ bool DebugLocDwarfExpression::isFrameRegister(const TargetRegisterInfo &TRI, } bool DbgVariable::isBlockByrefVariable() const { - assert(Var && "Invalid complex DbgVariable!"); - return Var->getType().resolve()->isBlockByrefStruct(); + assert(getVariable() && "Invalid complex DbgVariable!"); + return getVariable()->getType().resolve()->isBlockByrefStruct(); } const DIType *DbgVariable::getType() const { - DIType *Ty = Var->getType().resolve(); + DIType *Ty = getVariable()->getType().resolve(); // FIXME: isBlockByrefVariable should be reformulated in terms of complex // addresses instead. if (Ty->isBlockByrefStruct()) { @@ -246,7 +242,7 @@ ArrayRef<DbgVariable::FrameIndexExpr> DbgVariable::getFrameIndexExprs() const { return A.Expr->isFragment(); }) && "multiple FI expressions without DW_OP_LLVM_fragment"); - llvm::sort(FrameIndexExprs.begin(), FrameIndexExprs.end(), + llvm::sort(FrameIndexExprs, [](const FrameIndexExpr &A, const FrameIndexExpr &B) -> bool { return A.Expr->getFragmentInfo()->OffsetInBits < B.Expr->getFragmentInfo()->OffsetInBits; @@ -258,8 +254,8 @@ ArrayRef<DbgVariable::FrameIndexExpr> DbgVariable::getFrameIndexExprs() const { void DbgVariable::addMMIEntry(const DbgVariable &V) { assert(DebugLocListIndex == ~0U && !MInsn && "not an MMI entry"); assert(V.DebugLocListIndex == ~0U && !V.MInsn && "not an MMI entry"); - assert(V.Var == Var && "conflicting variable"); - assert(V.IA == IA && "conflicting inlined-at location"); + assert(V.getVariable() == getVariable() && "conflicting variable"); + assert(V.getInlinedAt() == getInlinedAt() && "conflicting inlined-at location"); assert(!FrameIndexExprs.empty() && "Expected an MMI entry"); assert(!V.FrameIndexExprs.empty() && "Expected an MMI entry"); @@ -355,7 +351,6 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) DwarfVersion = TT.isNVPTX() ? 2 : (DwarfVersion ? DwarfVersion : dwarf::DWARF_VERSION); - UsePubSections = !NoDwarfPubSections && !TT.isNVPTX(); UseRangesSection = !NoDwarfRangesSection && !TT.isNVPTX(); // Use sections as references. Force for NVPTX. @@ -421,30 +416,35 @@ static StringRef getObjCMethodName(StringRef In) { } // Add the various names to the Dwarf accelerator table names. -void DwarfDebug::addSubprogramNames(const DISubprogram *SP, DIE &Die) { +void DwarfDebug::addSubprogramNames(const DICompileUnit &CU, + const DISubprogram *SP, DIE &Die) { + if (getAccelTableKind() != AccelTableKind::Apple && + CU.getNameTableKind() == DICompileUnit::DebugNameTableKind::None) + return; + if (!SP->isDefinition()) return; if (SP->getName() != "") - addAccelName(SP->getName(), Die); + addAccelName(CU, SP->getName(), Die); // If the linkage name is different than the name, go ahead and output that as // well into the name table. Only do that if we are going to actually emit // that name. if (SP->getLinkageName() != "" && SP->getName() != SP->getLinkageName() && (useAllLinkageNames() || InfoHolder.getAbstractSPDies().lookup(SP))) - addAccelName(SP->getLinkageName(), Die); + addAccelName(CU, SP->getLinkageName(), Die); // If this is an Objective-C selector name add it to the ObjC accelerator // too. if (isObjCClass(SP->getName())) { StringRef Class, Category; getObjCClassCategory(SP->getName(), Class, Category); - addAccelObjC(Class, Die); + addAccelObjC(CU, Class, Die); if (Category != "") - addAccelObjC(Category, Die); + addAccelObjC(CU, Category, Die); // Also add the base method name to the name table. - addAccelName(getObjCMethodName(SP->getName()), Die); + addAccelName(CU, getObjCMethodName(SP->getName()), Die); } } @@ -503,6 +503,64 @@ void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU, } } +void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP, + DwarfCompileUnit &CU, DIE &ScopeDIE, + const MachineFunction &MF) { + // Add a call site-related attribute (DWARF5, Sec. 3.3.1.3). Do this only if + // the subprogram is required to have one. + if (!SP.areAllCallsDescribed() || !SP.isDefinition()) + return; + + // Use DW_AT_call_all_calls to express that call site entries are present + // for both tail and non-tail calls. Don't use DW_AT_call_all_source_calls + // because one of its requirements is not met: call site entries for + // optimized-out calls are elided. + CU.addFlag(ScopeDIE, dwarf::DW_AT_call_all_calls); + + const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); + assert(TII && "TargetInstrInfo not found: cannot label tail calls"); + + // Emit call site entries for each call or tail call in the function. + for (const MachineBasicBlock &MBB : MF) { + for (const MachineInstr &MI : MBB.instrs()) { + // Skip instructions which aren't calls. Both calls and tail-calling jump + // instructions (e.g TAILJMPd64) are classified correctly here. + if (!MI.isCall()) + continue; + + // TODO: Add support for targets with delay slots (see: beginInstruction). + if (MI.hasDelaySlot()) + return; + + // If this is a direct call, find the callee's subprogram. + const MachineOperand &CalleeOp = MI.getOperand(0); + if (!CalleeOp.isGlobal()) + continue; + const Function *CalleeDecl = dyn_cast<Function>(CalleeOp.getGlobal()); + if (!CalleeDecl || !CalleeDecl->getSubprogram()) + continue; + + // TODO: Omit call site entries for runtime calls (objc_msgSend, etc). + // TODO: Add support for indirect calls. + + bool IsTail = TII->isTailCall(MI); + + // For tail calls, no return PC information is needed. For regular calls, + // the return PC is needed to disambiguate paths in the call graph which + // could lead to some target function. + const MCExpr *PCOffset = + IsTail ? nullptr : getFunctionLocalOffsetAfterInsn(&MI); + + assert((IsTail || PCOffset) && "Call without return PC information"); + LLVM_DEBUG(dbgs() << "CallSiteEntry: " << MF.getName() << " -> " + << CalleeDecl->getName() << (IsTail ? " [tail]" : "") + << "\n"); + CU.constructCallSiteEntryDIE(ScopeDIE, *CalleeDecl->getSubprogram(), + IsTail, PCOffset); + } + } +} + void DwarfDebug::addGnuPubAttributes(DwarfCompileUnit &U, DIE &D) const { if (!U.hasDwarfPubSections()) return; @@ -510,41 +568,14 @@ void DwarfDebug::addGnuPubAttributes(DwarfCompileUnit &U, DIE &D) const { U.addFlag(D, dwarf::DW_AT_GNU_pubnames); } -// Create new DwarfCompileUnit for the given metadata node with tag -// DW_TAG_compile_unit. -DwarfCompileUnit & -DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { - if (auto *CU = CUMap.lookup(DIUnit)) - return *CU; - StringRef FN = DIUnit->getFilename(); - CompilationDir = DIUnit->getDirectory(); - - auto OwnedUnit = llvm::make_unique<DwarfCompileUnit>( - InfoHolder.getUnits().size(), DIUnit, Asm, this, &InfoHolder); - DwarfCompileUnit &NewCU = *OwnedUnit; +void DwarfDebug::finishUnitAttributes(const DICompileUnit *DIUnit, + DwarfCompileUnit &NewCU) { DIE &Die = NewCU.getUnitDie(); - InfoHolder.addUnit(std::move(OwnedUnit)); - if (useSplitDwarf()) { - NewCU.setSkeleton(constructSkeletonCU(NewCU)); - NewCU.addString(Die, dwarf::DW_AT_GNU_dwo_name, - Asm->TM.Options.MCOptions.SplitDwarfFile); - } - - for (auto *IE : DIUnit->getImportedEntities()) - NewCU.addImportedEntity(IE); - - // LTO with assembly output shares a single line table amongst multiple CUs. - // To avoid the compilation directory being ambiguous, let the line table - // explicitly describe the directory of all files, never relying on the - // compilation directory. - if (!Asm->OutStreamer->hasRawTextSupport() || SingleCU) - Asm->OutStreamer->emitDwarfFile0Directive( - CompilationDir, FN, NewCU.getMD5AsBytes(DIUnit->getFile()), - DIUnit->getSource(), NewCU.getUniqueID()); + StringRef FN = DIUnit->getFilename(); StringRef Producer = DIUnit->getProducer(); StringRef Flags = DIUnit->getFlags(); - if (!Flags.empty()) { + if (!Flags.empty() && !useAppleExtensionAttributes()) { std::string ProducerWithFlags = Producer.str() + " " + Flags.str(); NewCU.addString(Die, dwarf::DW_AT_producer, ProducerWithFlags); } else @@ -582,11 +613,6 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { dwarf::DW_FORM_data1, RVer); } - if (useSplitDwarf()) - NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoDWOSection()); - else - NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection()); - if (DIUnit->getDWOId()) { // This CU is either a clang module DWO or a skeleton CU. NewCU.addUInt(Die, dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8, @@ -596,9 +622,44 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { NewCU.addString(Die, dwarf::DW_AT_GNU_dwo_name, DIUnit->getSplitDebugFilename()); } +} +// Create new DwarfCompileUnit for the given metadata node with tag +// DW_TAG_compile_unit. +DwarfCompileUnit & +DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { + if (auto *CU = CUMap.lookup(DIUnit)) + return *CU; + + CompilationDir = DIUnit->getDirectory(); + + auto OwnedUnit = llvm::make_unique<DwarfCompileUnit>( + InfoHolder.getUnits().size(), DIUnit, Asm, this, &InfoHolder); + DwarfCompileUnit &NewCU = *OwnedUnit; + InfoHolder.addUnit(std::move(OwnedUnit)); + + for (auto *IE : DIUnit->getImportedEntities()) + NewCU.addImportedEntity(IE); + + // LTO with assembly output shares a single line table amongst multiple CUs. + // To avoid the compilation directory being ambiguous, let the line table + // explicitly describe the directory of all files, never relying on the + // compilation directory. + if (!Asm->OutStreamer->hasRawTextSupport() || SingleCU) + Asm->OutStreamer->emitDwarfFile0Directive( + CompilationDir, DIUnit->getFilename(), + NewCU.getMD5AsBytes(DIUnit->getFile()), DIUnit->getSource(), + NewCU.getUniqueID()); + + if (useSplitDwarf()) { + NewCU.setSkeleton(constructSkeletonCU(NewCU)); + NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoDWOSection()); + } else { + finishUnitAttributes(DIUnit, NewCU); + NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection()); + } CUMap.insert({DIUnit, &NewCU}); - CUDieMap.insert({&Die, &NewCU}); + CUDieMap.insert({&NewCU.getUnitDie(), &NewCU}); return NewCU; } @@ -613,22 +674,21 @@ void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU, /// Sort and unique GVEs by comparing their fragment offset. static SmallVectorImpl<DwarfCompileUnit::GlobalExpr> & sortGlobalExprs(SmallVectorImpl<DwarfCompileUnit::GlobalExpr> &GVEs) { - llvm::sort(GVEs.begin(), GVEs.end(), - [](DwarfCompileUnit::GlobalExpr A, - DwarfCompileUnit::GlobalExpr B) { - // Sort order: first null exprs, then exprs without fragment - // info, then sort by fragment offset in bits. - // FIXME: Come up with a more comprehensive comparator so - // the sorting isn't non-deterministic, and so the following - // std::unique call works correctly. - if (!A.Expr || !B.Expr) - return !!B.Expr; - auto FragmentA = A.Expr->getFragmentInfo(); - auto FragmentB = B.Expr->getFragmentInfo(); - if (!FragmentA || !FragmentB) - return !!FragmentB; - return FragmentA->OffsetInBits < FragmentB->OffsetInBits; - }); + llvm::sort( + GVEs, [](DwarfCompileUnit::GlobalExpr A, DwarfCompileUnit::GlobalExpr B) { + // Sort order: first null exprs, then exprs without fragment + // info, then sort by fragment offset in bits. + // FIXME: Come up with a more comprehensive comparator so + // the sorting isn't non-deterministic, and so the following + // std::unique call works correctly. + if (!A.Expr || !B.Expr) + return !!B.Expr; + auto FragmentA = A.Expr->getFragmentInfo(); + auto FragmentB = B.Expr->getFragmentInfo(); + if (!FragmentA || !FragmentB) + return !!FragmentB; + return FragmentA->OffsetInBits < FragmentB->OffsetInBits; + }); GVEs.erase(std::unique(GVEs.begin(), GVEs.end(), [](DwarfCompileUnit::GlobalExpr A, DwarfCompileUnit::GlobalExpr B) { @@ -644,15 +704,18 @@ sortGlobalExprs(SmallVectorImpl<DwarfCompileUnit::GlobalExpr> &GVEs) { void DwarfDebug::beginModule() { NamedRegionTimer T(DbgTimerName, DbgTimerDescription, DWARFGroupName, DWARFGroupDescription, TimePassesIsEnabled); - if (DisableDebugInfoPrinting) + if (DisableDebugInfoPrinting) { + MMI->setDebugInfoAvailability(false); return; + } const Module *M = MMI->getModule(); unsigned NumDebugCUs = std::distance(M->debug_compile_units_begin(), M->debug_compile_units_end()); // Tell MMI whether we have debug info. - MMI->setDebugInfoAvailability(NumDebugCUs > 0); + assert(MMI->hasDebugInfo() == (NumDebugCUs > 0) && + "DebugInfoAvailabilty initialized unexpectedly"); SingleCU = NumDebugCUs == 1; DenseMap<DIGlobalVariable *, SmallVector<DwarfCompileUnit::GlobalExpr, 1>> GVMap; @@ -670,11 +733,24 @@ void DwarfDebug::beginModule() { (useSplitDwarf() ? SkeletonHolder : InfoHolder) .setStringOffsetsStartSym(Asm->createTempSymbol("str_offsets_base")); - // Create the symbol that designates the start of the DWARF v5 range list - // table. It is located past the header and before the offsets table. - if (getDwarfVersion() >= 5) - (useSplitDwarf() ? SkeletonHolder : InfoHolder) - .setRnglistsTableBaseSym(Asm->createTempSymbol("rnglists_table_base")); + + // Create the symbols that designates the start of the DWARF v5 range list + // and locations list tables. They are located past the table headers. + if (getDwarfVersion() >= 5) { + DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; + Holder.setRnglistsTableBaseSym( + Asm->createTempSymbol("rnglists_table_base")); + Holder.setLoclistsTableBaseSym( + Asm->createTempSymbol("loclists_table_base")); + + if (useSplitDwarf()) + InfoHolder.setRnglistsTableBaseSym( + Asm->createTempSymbol("rnglists_dwo_table_base")); + } + + // Create the symbol that points to the first entry following the debug + // address table (.debug_addr) header. + AddrPool.setLabel(Asm->createTempSymbol("addr_table_base")); for (DICompileUnit *CUNode : M->debug_compile_units()) { // FIXME: Move local imported entities into a list attached to the @@ -728,16 +804,16 @@ void DwarfDebug::beginModule() { } } -void DwarfDebug::finishVariableDefinitions() { - for (const auto &Var : ConcreteVariables) { - DIE *VariableDie = Var->getDIE(); - assert(VariableDie); +void DwarfDebug::finishEntityDefinitions() { + for (const auto &Entity : ConcreteEntities) { + DIE *Die = Entity->getDIE(); + assert(Die); // FIXME: Consider the time-space tradeoff of just storing the unit pointer - // in the ConcreteVariables list, rather than looking it up again here. + // in the ConcreteEntities list, rather than looking it up again here. // DIE::getUnit isn't simple - it walks parent pointers, etc. - DwarfCompileUnit *Unit = CUDieMap.lookup(VariableDie->getUnitDie()); + DwarfCompileUnit *Unit = CUDieMap.lookup(Die->getUnitDie()); assert(Unit); - Unit->finishVariableDefinition(*Var); + Unit->finishEntityDefinition(Entity.get()); } } @@ -755,7 +831,7 @@ void DwarfDebug::finalizeModuleInfo() { finishSubprogramDefinitions(); - finishVariableDefinitions(); + finishEntityDefinitions(); // Include the DWO file name in the hash if there's more than one CU. // This handles ThinLTO's situation where imported CUs may very easily be @@ -768,6 +844,8 @@ void DwarfDebug::finalizeModuleInfo() { // all other generation. for (const auto &P : CUMap) { auto &TheCU = *P.second; + if (TheCU.getCUNode()->isDebugDirectivesOnly()) + continue; // Emit DW_AT_containing_type attribute to connect types with their // vtable holding type. TheCU.constructContainingTypeDIEs(); @@ -776,7 +854,12 @@ void DwarfDebug::finalizeModuleInfo() { // If we're splitting the dwarf out now that we've got the entire // CU then add the dwo id to it. auto *SkCU = TheCU.getSkeleton(); - if (useSplitDwarf()) { + if (useSplitDwarf() && !empty(TheCU.getUnitDie().children())) { + finishUnitAttributes(TheCU.getCUNode(), TheCU); + TheCU.addString(TheCU.getUnitDie(), dwarf::DW_AT_GNU_dwo_name, + Asm->TM.Options.MCOptions.SplitDwarfFile); + SkCU->addString(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_name, + Asm->TM.Options.MCOptions.SplitDwarfFile); // Emit a unique identifier for this CU. uint64_t ID = DIEHash(Asm).computeCUSignature(DWOName, TheCU.getUnitDie()); @@ -789,18 +872,14 @@ void DwarfDebug::finalizeModuleInfo() { SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8, ID); } - // We don't keep track of which addresses are used in which CU so this - // is a bit pessimistic under LTO. - if (!AddrPool.isEmpty()) { - const MCSymbol *Sym = TLOF.getDwarfAddrSection()->getBeginSymbol(); - SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_addr_base, - Sym, Sym); - } - if (getDwarfVersion() < 5 && !SkCU->getRangeLists().empty()) { + + if (getDwarfVersion() < 5 && !SkeletonHolder.getRangeLists().empty()) { const MCSymbol *Sym = TLOF.getDwarfRangesSection()->getBeginSymbol(); SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_ranges_base, Sym, Sym); } + } else if (SkCU) { + finishUnitAttributes(SkCU->getCUNode(), *SkCU); } // If we have code split among multiple sections or non-contiguous @@ -810,6 +889,14 @@ void DwarfDebug::finalizeModuleInfo() { // .subsections_via_symbols in mach-o. This would mean turning on // ranges for all subprogram DIEs for mach-o. DwarfCompileUnit &U = SkCU ? *SkCU : TheCU; + + // We don't keep track of which addresses are used in which CU so this + // is a bit pessimistic under LTO. + if (!AddrPool.isEmpty() && + (getDwarfVersion() >= 5 || + (SkCU && !empty(TheCU.getUnitDie().children())))) + U.addAddrTableBase(); + if (unsigned NumRanges = TheCU.getRanges().size()) { if (NumRanges > 1 && useRangesSection()) // A DW_AT_low_pc attribute may also be specified in combination with @@ -822,9 +909,13 @@ void DwarfDebug::finalizeModuleInfo() { U.attachRangesOrLowHighPC(U.getUnitDie(), TheCU.takeRanges()); } - if (getDwarfVersion() >= 5 && !useSplitDwarf() && - !U.getRangeLists().empty()) - U.addRnglistsBase(); + if (getDwarfVersion() >= 5) { + if (U.hasRangeLists()) + U.addRnglistsBase(); + + if (!DebugLocs.getLists().empty() && !useSplitDwarf()) + U.addLoclistsBase(); + } auto *CUNode = cast<DICompileUnit>(P.first); // If compile Unit has macros, emit "DW_AT_macro_info" attribute. @@ -888,9 +979,11 @@ void DwarfDebug::endModule() { emitDebugInfoDWO(); emitDebugAbbrevDWO(); emitDebugLineDWO(); - emitDebugAddr(); + emitDebugRangesDWO(); } + emitDebugAddr(); + // Emit info into the dwarf accelerator table sections. switch (getAccelTableKind()) { case AccelTableKind::Apple: @@ -915,38 +1008,37 @@ void DwarfDebug::endModule() { // FIXME: AbstractVariables.clear(); } -void DwarfDebug::ensureAbstractVariableIsCreated(DwarfCompileUnit &CU, InlinedVariable IV, - const MDNode *ScopeNode) { - const DILocalVariable *Cleansed = nullptr; - if (CU.getExistingAbstractVariable(IV, Cleansed)) +void DwarfDebug::ensureAbstractEntityIsCreated(DwarfCompileUnit &CU, + const DINode *Node, + const MDNode *ScopeNode) { + if (CU.getExistingAbstractEntity(Node)) return; - CU.createAbstractVariable(Cleansed, LScopes.getOrCreateAbstractScope( + CU.createAbstractEntity(Node, LScopes.getOrCreateAbstractScope( cast<DILocalScope>(ScopeNode))); } -void DwarfDebug::ensureAbstractVariableIsCreatedIfScoped(DwarfCompileUnit &CU, - InlinedVariable IV, const MDNode *ScopeNode) { - const DILocalVariable *Cleansed = nullptr; - if (CU.getExistingAbstractVariable(IV, Cleansed)) +void DwarfDebug::ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU, + const DINode *Node, const MDNode *ScopeNode) { + if (CU.getExistingAbstractEntity(Node)) return; if (LexicalScope *Scope = LScopes.findAbstractScope(cast_or_null<DILocalScope>(ScopeNode))) - CU.createAbstractVariable(Cleansed, Scope); + CU.createAbstractEntity(Node, Scope); } // Collect variable information from side table maintained by MF. void DwarfDebug::collectVariableInfoFromMFTable( - DwarfCompileUnit &TheCU, DenseSet<InlinedVariable> &Processed) { - SmallDenseMap<InlinedVariable, DbgVariable *> MFVars; + DwarfCompileUnit &TheCU, DenseSet<InlinedEntity> &Processed) { + SmallDenseMap<InlinedEntity, DbgVariable *> MFVars; for (const auto &VI : Asm->MF->getVariableDbgInfo()) { if (!VI.Var) continue; assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) && "Expected inlined-at fields to agree"); - InlinedVariable Var(VI.Var, VI.Loc->getInlinedAt()); + InlinedEntity Var(VI.Var, VI.Loc->getInlinedAt()); Processed.insert(Var); LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc); @@ -954,14 +1046,15 @@ void DwarfDebug::collectVariableInfoFromMFTable( if (!Scope) continue; - ensureAbstractVariableIsCreatedIfScoped(TheCU, Var, Scope->getScopeNode()); - auto RegVar = llvm::make_unique<DbgVariable>(Var.first, Var.second); + ensureAbstractEntityIsCreatedIfScoped(TheCU, Var.first, Scope->getScopeNode()); + auto RegVar = llvm::make_unique<DbgVariable>( + cast<DILocalVariable>(Var.first), Var.second); RegVar->initializeMMI(VI.Expr, VI.Slot); if (DbgVariable *DbgVar = MFVars.lookup(Var)) DbgVar->addMMIEntry(*RegVar); else if (InfoHolder.addScopeVariable(Scope, RegVar.get())) { MFVars.insert({Var, RegVar.get()}); - ConcreteVariables.push_back(std::move(RegVar)); + ConcreteEntities.push_back(std::move(RegVar)); } } } @@ -1087,6 +1180,18 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, LLVM_DEBUG(dbgs() << "DotDebugLoc: " << *Begin << "\n"); auto Value = getDebugLocValue(Begin); + + // Omit entries with empty ranges as they do not have any effect in DWARF. + if (StartLabel == EndLabel) { + // If this is a fragment, we must still add the value to the list of + // open ranges, since it may describe non-overlapping parts of the + // variable. + if (DIExpr->isFragment()) + OpenRanges.push_back(Value); + LLVM_DEBUG(dbgs() << "Omitting location list entry with empty range.\n"); + continue; + } + DebugLocEntry Loc(StartLabel, EndLabel, Value); bool couldMerge = false; @@ -1126,14 +1231,26 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, } } -DbgVariable *DwarfDebug::createConcreteVariable(DwarfCompileUnit &TheCU, - LexicalScope &Scope, - InlinedVariable IV) { - ensureAbstractVariableIsCreatedIfScoped(TheCU, IV, Scope.getScopeNode()); - ConcreteVariables.push_back( - llvm::make_unique<DbgVariable>(IV.first, IV.second)); - InfoHolder.addScopeVariable(&Scope, ConcreteVariables.back().get()); - return ConcreteVariables.back().get(); +DbgEntity *DwarfDebug::createConcreteEntity(DwarfCompileUnit &TheCU, + LexicalScope &Scope, + const DINode *Node, + const DILocation *Location, + const MCSymbol *Sym) { + ensureAbstractEntityIsCreatedIfScoped(TheCU, Node, Scope.getScopeNode()); + if (isa<const DILocalVariable>(Node)) { + ConcreteEntities.push_back( + llvm::make_unique<DbgVariable>(cast<const DILocalVariable>(Node), + Location)); + InfoHolder.addScopeVariable(&Scope, + cast<DbgVariable>(ConcreteEntities.back().get())); + } else if (isa<const DILabel>(Node)) { + ConcreteEntities.push_back( + llvm::make_unique<DbgLabel>(cast<const DILabel>(Node), + Location, Sym)); + InfoHolder.addScopeLabel(&Scope, + cast<DbgLabel>(ConcreteEntities.back().get())); + } + return ConcreteEntities.back().get(); } /// Determine whether a *singular* DBG_VALUE is valid for the entirety of its @@ -1195,14 +1312,14 @@ static bool validThroughout(LexicalScopes &LScopes, } // Find variables for each lexical scope. -void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, - const DISubprogram *SP, - DenseSet<InlinedVariable> &Processed) { +void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, + const DISubprogram *SP, + DenseSet<InlinedEntity> &Processed) { // Grab the variable info that was squirreled away in the MMI side-table. collectVariableInfoFromMFTable(TheCU, Processed); for (const auto &I : DbgValues) { - InlinedVariable IV = I.first; + InlinedEntity IV = I.first; if (Processed.count(IV)) continue; @@ -1212,16 +1329,18 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, continue; LexicalScope *Scope = nullptr; + const DILocalVariable *LocalVar = cast<DILocalVariable>(IV.first); if (const DILocation *IA = IV.second) - Scope = LScopes.findInlinedScope(IV.first->getScope(), IA); + Scope = LScopes.findInlinedScope(LocalVar->getScope(), IA); else - Scope = LScopes.findLexicalScope(IV.first->getScope()); + Scope = LScopes.findLexicalScope(LocalVar->getScope()); // If variable scope is not found then skip this variable. if (!Scope) continue; Processed.insert(IV); - DbgVariable *RegVar = createConcreteVariable(TheCU, *Scope, IV); + DbgVariable *RegVar = cast<DbgVariable>(createConcreteEntity(TheCU, + *Scope, LocalVar, IV.second)); const MachineInstr *MInsn = Ranges.front().first; assert(MInsn->isDebugValue() && "History must begin with debug value"); @@ -1247,20 +1366,53 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, // unique identifiers, so don't bother resolving the type with the // identifier map. const DIBasicType *BT = dyn_cast<DIBasicType>( - static_cast<const Metadata *>(IV.first->getType())); + static_cast<const Metadata *>(LocalVar->getType())); // Finalize the entry by lowering it into a DWARF bytestream. for (auto &Entry : Entries) Entry.finalize(*Asm, List, BT); } - // Collect info for variables that were optimized out. + // For each InlinedEntity collected from DBG_LABEL instructions, convert to + // DWARF-related DbgLabel. + for (const auto &I : DbgLabels) { + InlinedEntity IL = I.first; + const MachineInstr *MI = I.second; + if (MI == nullptr) + continue; + + LexicalScope *Scope = nullptr; + const DILabel *Label = cast<DILabel>(IL.first); + // Get inlined DILocation if it is inlined label. + if (const DILocation *IA = IL.second) + Scope = LScopes.findInlinedScope(Label->getScope(), IA); + else + Scope = LScopes.findLexicalScope(Label->getScope()); + // If label scope is not found then skip this label. + if (!Scope) + continue; + + Processed.insert(IL); + /// At this point, the temporary label is created. + /// Save the temporary label to DbgLabel entity to get the + /// actually address when generating Dwarf DIE. + MCSymbol *Sym = getLabelBeforeInsn(MI); + createConcreteEntity(TheCU, *Scope, Label, IL.second, Sym); + } + + // Collect info for variables/labels that were optimized out. for (const DINode *DN : SP->getRetainedNodes()) { + if (!Processed.insert(InlinedEntity(DN, nullptr)).second) + continue; + LexicalScope *Scope = nullptr; if (auto *DV = dyn_cast<DILocalVariable>(DN)) { - if (Processed.insert(InlinedVariable(DV, nullptr)).second) - if (LexicalScope *Scope = LScopes.findLexicalScope(DV->getScope())) - createConcreteVariable(TheCU, *Scope, InlinedVariable(DV, nullptr)); + Scope = LScopes.findLexicalScope(DV->getScope()); + } else if (auto *DL = dyn_cast<DILabel>(DN)) { + Scope = LScopes.findLexicalScope(DL->getScope()); } + + if (Scope) + createConcreteEntity(TheCU, *Scope, DN, nullptr); } } @@ -1284,6 +1436,11 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { unsigned LastAsmLine = Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine(); + // Request a label after the call in order to emit AT_return_pc information + // in call site entries. TODO: Add support for targets with delay slots. + if (SP->areAllCallsDescribed() && MI->isCall() && !MI->hasDelaySlot()) + requestLabelAfterInsn(MI); + if (DL == PrevInstLoc) { // If we have an ongoing unspecified location, nothing to do here. if (!DL) @@ -1416,9 +1573,14 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) { LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); assert(!FnScope || SP == FnScope->getScopeNode()); DwarfCompileUnit &TheCU = *CUMap.lookup(SP->getUnit()); + if (TheCU.getCUNode()->isDebugDirectivesOnly()) { + PrevLabel = nullptr; + CurFn = nullptr; + return; + } - DenseSet<InlinedVariable> ProcessedVars; - collectVariableInfo(TheCU, SP, ProcessedVars); + DenseSet<InlinedEntity> Processed; + collectEntityInfo(TheCU, SP, Processed); // Add the range of this function to the list of ranges for the CU. TheCU.addRange(RangeSpan(Asm->getFunctionBegin(), Asm->getFunctionEnd())); @@ -1442,31 +1604,41 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) { for (LexicalScope *AScope : LScopes.getAbstractScopesList()) { auto *SP = cast<DISubprogram>(AScope->getScopeNode()); for (const DINode *DN : SP->getRetainedNodes()) { - if (auto *DV = dyn_cast<DILocalVariable>(DN)) { - // Collect info for variables that were optimized out. - if (!ProcessedVars.insert(InlinedVariable(DV, nullptr)).second) - continue; - ensureAbstractVariableIsCreated(TheCU, InlinedVariable(DV, nullptr), - DV->getScope()); - assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes - && "ensureAbstractVariableIsCreated inserted abstract scopes"); - } + if (!Processed.insert(InlinedEntity(DN, nullptr)).second) + continue; + + const MDNode *Scope = nullptr; + if (auto *DV = dyn_cast<DILocalVariable>(DN)) + Scope = DV->getScope(); + else if (auto *DL = dyn_cast<DILabel>(DN)) + Scope = DL->getScope(); + else + llvm_unreachable("Unexpected DI type!"); + + // Collect info for variables/labels that were optimized out. + ensureAbstractEntityIsCreated(TheCU, DN, Scope); + assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes + && "ensureAbstractEntityIsCreated inserted abstract scopes"); } constructAbstractSubprogramScopeDIE(TheCU, AScope); } ProcessedSPNodes.insert(SP); - TheCU.constructSubprogramScopeDIE(SP, FnScope); + DIE &ScopeDIE = TheCU.constructSubprogramScopeDIE(SP, FnScope); if (auto *SkelCU = TheCU.getSkeleton()) if (!LScopes.getAbstractScopesList().empty() && TheCU.getCUNode()->getSplitDebugInlining()) SkelCU->constructSubprogramScopeDIE(SP, FnScope); + // Construct call site entries. + constructCallSiteEntryDIEs(*SP, TheCU, ScopeDIE, *MF); + // Clear debug info // Ownership of DbgVariables is a bit subtle - ScopeVariables owns all the // DbgVariables except those that are also in AbstractVariables (since they // can be used cross-function) InfoHolder.getScopeVariables().clear(); + InfoHolder.getScopeLabels().clear(); PrevLabel = nullptr; CurFn = nullptr; } @@ -1530,8 +1702,6 @@ void DwarfDebug::emitAccelDebugNames() { if (getUnits().empty()) return; - Asm->OutStreamer->SwitchSection( - Asm->getObjFileLowering().getDwarfDebugNamesSection()); emitDWARF5AccelTable(Asm, AccelDebugNames, *this, getUnits()); } @@ -1636,7 +1806,8 @@ void DwarfDebug::emitDebugPubSections() { if (!TheU->hasDwarfPubSections()) continue; - bool GnuStyle = TheU->getCUNode()->getGnuPubnames(); + bool GnuStyle = TheU->getCUNode()->getNameTableKind() == + DICompileUnit::DebugNameTableKind::GNU; Asm->OutStreamer->SwitchSection( GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubNamesSection() @@ -1692,8 +1863,8 @@ void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name, if (GnuStyle) { dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheU, Entity); Asm->OutStreamer->AddComment( - Twine("Kind: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + ", " + - dwarf::GDBIndexEntryLinkageString(Desc.Linkage)); + Twine("Attributes: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + + ", " + dwarf::GDBIndexEntryLinkageString(Desc.Linkage)); Asm->emitInt8(Desc.toBits()); } @@ -1759,6 +1930,7 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, void DebugLocEntry::finalize(const AsmPrinter &AP, DebugLocStream::ListBuilder &List, const DIBasicType *BT) { + assert(Begin != End && "unexpected location list entry with empty range"); DebugLocStream::EntryBuilder Entry(List, Begin, End); BufferByteStreamer Streamer = Entry.getStreamer(); DebugLocDwarfExpression DwarfExpr(AP.getDwarfVersion(), Streamer); @@ -1791,25 +1963,119 @@ void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry) { emitDebugLocEntry(Streamer, Entry); } -// Emit locations into the debug loc section. +// Emit the common part of the DWARF 5 range/locations list tables header. +static void emitListsTableHeaderStart(AsmPrinter *Asm, const DwarfFile &Holder, + MCSymbol *TableStart, + MCSymbol *TableEnd) { + // Build the table header, which starts with the length field. + Asm->OutStreamer->AddComment("Length"); + Asm->EmitLabelDifference(TableEnd, TableStart, 4); + Asm->OutStreamer->EmitLabel(TableStart); + // Version number (DWARF v5 and later). + Asm->OutStreamer->AddComment("Version"); + Asm->emitInt16(Asm->OutStreamer->getContext().getDwarfVersion()); + // Address size. + Asm->OutStreamer->AddComment("Address size"); + Asm->emitInt8(Asm->MAI->getCodePointerSize()); + // Segment selector size. + Asm->OutStreamer->AddComment("Segment selector size"); + Asm->emitInt8(0); +} + +// Emit the header of a DWARF 5 range list table list table. Returns the symbol +// that designates the end of the table for the caller to emit when the table is +// complete. +static MCSymbol *emitRnglistsTableHeader(AsmPrinter *Asm, + const DwarfFile &Holder) { + MCSymbol *TableStart = Asm->createTempSymbol("debug_rnglist_table_start"); + MCSymbol *TableEnd = Asm->createTempSymbol("debug_rnglist_table_end"); + emitListsTableHeaderStart(Asm, Holder, TableStart, TableEnd); + + Asm->OutStreamer->AddComment("Offset entry count"); + Asm->emitInt32(Holder.getRangeLists().size()); + Asm->OutStreamer->EmitLabel(Holder.getRnglistsTableBaseSym()); + + for (const RangeSpanList &List : Holder.getRangeLists()) + Asm->EmitLabelDifference(List.getSym(), Holder.getRnglistsTableBaseSym(), + 4); + + return TableEnd; +} + +// Emit the header of a DWARF 5 locations list table. Returns the symbol that +// designates the end of the table for the caller to emit when the table is +// complete. +static MCSymbol *emitLoclistsTableHeader(AsmPrinter *Asm, + const DwarfFile &Holder) { + MCSymbol *TableStart = Asm->createTempSymbol("debug_loclist_table_start"); + MCSymbol *TableEnd = Asm->createTempSymbol("debug_loclist_table_end"); + emitListsTableHeaderStart(Asm, Holder, TableStart, TableEnd); + + // FIXME: Generate the offsets table and use DW_FORM_loclistx with the + // DW_AT_loclists_base attribute. Until then set the number of offsets to 0. + Asm->OutStreamer->AddComment("Offset entry count"); + Asm->emitInt32(0); + Asm->OutStreamer->EmitLabel(Holder.getLoclistsTableBaseSym()); + + return TableEnd; +} + +// Emit locations into the .debug_loc/.debug_rnglists section. void DwarfDebug::emitDebugLoc() { if (DebugLocs.getLists().empty()) return; - // Start the dwarf loc section. - Asm->OutStreamer->SwitchSection( - Asm->getObjFileLowering().getDwarfLocSection()); + bool IsLocLists = getDwarfVersion() >= 5; + MCSymbol *TableEnd = nullptr; + if (IsLocLists) { + Asm->OutStreamer->SwitchSection( + Asm->getObjFileLowering().getDwarfLoclistsSection()); + TableEnd = emitLoclistsTableHeader(Asm, useSplitDwarf() ? SkeletonHolder + : InfoHolder); + } else { + Asm->OutStreamer->SwitchSection( + Asm->getObjFileLowering().getDwarfLocSection()); + } + unsigned char Size = Asm->MAI->getCodePointerSize(); for (const auto &List : DebugLocs.getLists()) { Asm->OutStreamer->EmitLabel(List.Label); + const DwarfCompileUnit *CU = List.CU; + const MCSymbol *Base = CU->getBaseAddress(); for (const auto &Entry : DebugLocs.getEntries(List)) { - // Set up the range. This range is relative to the entry point of the - // compile unit. This is a hard coded 0 for low_pc when we're emitting - // ranges, or the DW_AT_low_pc on the compile unit otherwise. - if (auto *Base = CU->getBaseAddress()) { - Asm->EmitLabelDifference(Entry.BeginSym, Base, Size); - Asm->EmitLabelDifference(Entry.EndSym, Base, Size); + if (Base) { + // Set up the range. This range is relative to the entry point of the + // compile unit. This is a hard coded 0 for low_pc when we're emitting + // ranges, or the DW_AT_low_pc on the compile unit otherwise. + if (IsLocLists) { + Asm->OutStreamer->AddComment("DW_LLE_offset_pair"); + Asm->OutStreamer->EmitIntValue(dwarf::DW_LLE_offset_pair, 1); + Asm->OutStreamer->AddComment(" starting offset"); + Asm->EmitLabelDifferenceAsULEB128(Entry.BeginSym, Base); + Asm->OutStreamer->AddComment(" ending offset"); + Asm->EmitLabelDifferenceAsULEB128(Entry.EndSym, Base); + } else { + Asm->EmitLabelDifference(Entry.BeginSym, Base, Size); + Asm->EmitLabelDifference(Entry.EndSym, Base, Size); + } + + emitDebugLocEntryLocation(Entry); + continue; + } + + // We have no base address. + if (IsLocLists) { + // TODO: Use DW_LLE_base_addressx + DW_LLE_offset_pair, or + // DW_LLE_startx_length in case if there is only a single range. + // That should reduce the size of the debug data emited. + // For now just use the DW_LLE_startx_length for all cases. + Asm->OutStreamer->AddComment("DW_LLE_startx_length"); + Asm->emitInt8(dwarf::DW_LLE_startx_length); + Asm->OutStreamer->AddComment(" start idx"); + Asm->EmitULEB128(AddrPool.getIndex(Entry.BeginSym)); + Asm->OutStreamer->AddComment(" length"); + Asm->EmitLabelDifferenceAsULEB128(Entry.EndSym, Entry.BeginSym); } else { Asm->OutStreamer->EmitSymbolValue(Entry.BeginSym, Size); Asm->OutStreamer->EmitSymbolValue(Entry.EndSym, Size); @@ -1817,9 +2083,20 @@ void DwarfDebug::emitDebugLoc() { emitDebugLocEntryLocation(Entry); } - Asm->OutStreamer->EmitIntValue(0, Size); - Asm->OutStreamer->EmitIntValue(0, Size); + + if (IsLocLists) { + // .debug_loclists section ends with DW_LLE_end_of_list. + Asm->OutStreamer->AddComment("DW_LLE_end_of_list"); + Asm->OutStreamer->EmitIntValue(dwarf::DW_LLE_end_of_list, 1); + } else { + // Terminate the .debug_loc list with two 0 values. + Asm->OutStreamer->EmitIntValue(0, Size); + Asm->OutStreamer->EmitIntValue(0, Size); + } } + + if (TableEnd) + Asm->OutStreamer->EmitLabel(TableEnd); } void DwarfDebug::emitDebugLocDWO() { @@ -1828,10 +2105,13 @@ void DwarfDebug::emitDebugLocDWO() { for (const auto &List : DebugLocs.getLists()) { Asm->OutStreamer->EmitLabel(List.Label); for (const auto &Entry : DebugLocs.getEntries(List)) { - // Just always use start_length for now - at least that's one address - // rather than two. We could get fancier and try to, say, reuse an - // address we know we've emitted elsewhere (the start of the function? - // The start of the CU or CU subrange that encloses this range?) + // GDB only supports startx_length in pre-standard split-DWARF. + // (in v5 standard loclists, it currently* /only/ supports base_address + + // offset_pair, so the implementations can't really share much since they + // need to use different representations) + // * as of October 2018, at least + // Ideally/in v5, this could use SectionLabels to reuse existing addresses + // in the address pool to minimize object size/relocations. Asm->emitInt8(dwarf::DW_LLE_startx_length); unsigned idx = AddrPool.getIndex(Entry.BeginSym); Asm->EmitULEB128(idx); @@ -1939,10 +2219,9 @@ void DwarfDebug::emitDebugARanges() { } // Sort the CU list (again, to ensure consistent output order). - llvm::sort(CUs.begin(), CUs.end(), - [](const DwarfCompileUnit *A, const DwarfCompileUnit *B) { - return A->getUniqueID() < B->getUniqueID(); - }); + llvm::sort(CUs, [](const DwarfCompileUnit *A, const DwarfCompileUnit *B) { + return A->getUniqueID() < B->getUniqueID(); + }); // Emit an arange table for each CU we used. for (DwarfCompileUnit *CU : CUs) { @@ -2006,10 +2285,10 @@ void DwarfDebug::emitDebugARanges() { } /// Emit a single range list. We handle both DWARF v5 and earlier. -static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU, +static void emitRangeList(DwarfDebug &DD, AsmPrinter *Asm, const RangeSpanList &List) { - auto DwarfVersion = CU->getDwarfVersion(); + auto DwarfVersion = DD.getDwarfVersion(); // Emit our symbol so we can find the beginning of the range. Asm->OutStreamer->EmitLabel(List.getSym()); // Gather all the ranges that apply to the same section so they can share @@ -2021,7 +2300,8 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU, for (const RangeSpan &Range : List.getRanges()) SectionRanges[&Range.getStart()->getSection()].push_back(&Range); - auto *CUBase = CU->getBaseAddress(); + const DwarfCompileUnit &CU = List.getCU(); + const MCSymbol *CUBase = CU.getBaseAddress(); bool BaseIsSet = false; for (const auto &P : SectionRanges) { // Don't bother with a base address entry if there's only one range in @@ -2031,19 +2311,23 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU, // or optnone where there may be holes in a single CU's section // contributions. auto *Base = CUBase; - if (!Base && P.second.size() > 1 && - (UseDwarfRangesBaseAddressSpecifier || DwarfVersion >= 5)) { + if (!Base && (P.second.size() > 1 || DwarfVersion < 5) && + (CU.getCUNode()->getRangesBaseAddress() || DwarfVersion >= 5)) { BaseIsSet = true; // FIXME/use care: This may not be a useful base address if it's not // the lowest address/range in this object. Base = P.second.front()->getStart(); if (DwarfVersion >= 5) { - Asm->OutStreamer->AddComment("DW_RLE_base_address"); - Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_base_address, 1); - } else + Base = DD.getSectionLabel(&Base->getSection()); + Asm->OutStreamer->AddComment("DW_RLE_base_addressx"); + Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_base_addressx, 1); + Asm->OutStreamer->AddComment(" base address index"); + Asm->EmitULEB128(DD.getAddressPool().getIndex(Base)); + } else { Asm->OutStreamer->EmitIntValue(-1, Size); - Asm->OutStreamer->AddComment(" base address"); - Asm->OutStreamer->EmitSymbolValue(Base, Size); + Asm->OutStreamer->AddComment(" base address"); + Asm->OutStreamer->EmitSymbolValue(Base, Size); + } } else if (BaseIsSet && DwarfVersion < 5) { BaseIsSet = false; assert(!Base); @@ -2070,10 +2354,10 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU, Asm->EmitLabelDifference(End, Base, Size); } } else if (DwarfVersion >= 5) { - Asm->OutStreamer->AddComment("DW_RLE_start_length"); - Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_start_length, 1); - Asm->OutStreamer->AddComment(" start"); - Asm->OutStreamer->EmitSymbolValue(Begin, Size); + Asm->OutStreamer->AddComment("DW_RLE_startx_length"); + Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_startx_length, 1); + Asm->OutStreamer->AddComment(" start index"); + Asm->EmitULEB128(DD.getAddressPool().getIndex(Begin)); Asm->OutStreamer->AddComment(" length"); Asm->EmitLabelDifferenceAsULEB128(End, Begin); } else { @@ -2092,31 +2376,13 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU, } } -// Emit the header of a DWARF 5 range list table. Returns the symbol that -// designates the end of the table for the caller to emit when the table is -// complete. -static MCSymbol *emitRnglistsTableHeader(AsmPrinter *Asm, DwarfFile &Holder) { - // The length is described by a starting label right after the length field - // and an end label. - MCSymbol *TableStart = Asm->createTempSymbol("debug_rnglist_table_start"); - MCSymbol *TableEnd = Asm->createTempSymbol("debug_rnglist_table_end"); - // Build the range table header, which starts with the length field. - Asm->EmitLabelDifference(TableEnd, TableStart, 4); - Asm->OutStreamer->EmitLabel(TableStart); - // Version number (DWARF v5 and later). - Asm->emitInt16(Asm->OutStreamer->getContext().getDwarfVersion()); - // Address size. - Asm->emitInt8(Asm->MAI->getCodePointerSize()); - // Segment selector size. - Asm->emitInt8(0); - - MCSymbol *RnglistTableBaseSym = Holder.getRnglistsTableBaseSym(); +static void emitDebugRangesImpl(DwarfDebug &DD, AsmPrinter *Asm, + const DwarfFile &Holder, MCSymbol *TableEnd) { + for (const RangeSpanList &List : Holder.getRangeLists()) + emitRangeList(DD, Asm, List); - // FIXME: Generate the offsets table and use DW_FORM_rnglistx with the - // DW_AT_ranges attribute. Until then set the number of offsets to 0. - Asm->emitInt32(0); - Asm->OutStreamer->EmitLabel(RnglistTableBaseSym); - return TableEnd; + if (TableEnd) + Asm->OutStreamer->EmitLabel(TableEnd); } /// Emit address ranges into the .debug_ranges section or into the DWARF v5 @@ -2125,46 +2391,52 @@ void DwarfDebug::emitDebugRanges() { if (CUMap.empty()) return; - auto NoRangesPresent = [this]() { - return llvm::all_of( - CUMap, [](const decltype(CUMap)::value_type &Pair) { - return Pair.second->getRangeLists().empty(); - }); - }; + const auto &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; - if (!useRangesSection()) { - assert(NoRangesPresent() && "No debug ranges expected."); + if (Holder.getRangeLists().empty()) return; - } - if (NoRangesPresent()) - return; + assert(useRangesSection()); + assert(llvm::none_of(CUMap, [](const decltype(CUMap)::value_type &Pair) { + return Pair.second->getCUNode()->isDebugDirectivesOnly(); + })); // Start the dwarf ranges section. MCSymbol *TableEnd = nullptr; if (getDwarfVersion() >= 5) { Asm->OutStreamer->SwitchSection( Asm->getObjFileLowering().getDwarfRnglistsSection()); - TableEnd = emitRnglistsTableHeader(Asm, useSplitDwarf() ? SkeletonHolder - : InfoHolder); + TableEnd = emitRnglistsTableHeader(Asm, Holder); } else Asm->OutStreamer->SwitchSection( Asm->getObjFileLowering().getDwarfRangesSection()); - // Grab the specific ranges for the compile units in the module. - for (const auto &I : CUMap) { - DwarfCompileUnit *TheCU = I.second; + emitDebugRangesImpl(*this, Asm, Holder, TableEnd); +} - if (auto *Skel = TheCU->getSkeleton()) - TheCU = Skel; +void DwarfDebug::emitDebugRangesDWO() { + assert(useSplitDwarf()); - // Iterate over the misc ranges for the compile units in the module. - for (const RangeSpanList &List : TheCU->getRangeLists()) - emitRangeList(Asm, TheCU, List); - } + if (CUMap.empty()) + return; - if (TableEnd) - Asm->OutStreamer->EmitLabel(TableEnd); + const auto &Holder = InfoHolder; + + if (Holder.getRangeLists().empty()) + return; + + assert(getDwarfVersion() >= 5); + assert(useRangesSection()); + assert(llvm::none_of(CUMap, [](const decltype(CUMap)::value_type &Pair) { + return Pair.second->getCUNode()->isDebugDirectivesOnly(); + })); + + // Start the dwarf ranges section. + Asm->OutStreamer->SwitchSection( + Asm->getObjFileLowering().getDwarfRnglistsDWOSection()); + MCSymbol *TableEnd = emitRnglistsTableHeader(Asm, Holder); + + emitDebugRangesImpl(*this, Asm, Holder, TableEnd); } void DwarfDebug::handleMacroNodes(DIMacroNodeArray Nodes, DwarfCompileUnit &U) { @@ -2206,12 +2478,19 @@ void DwarfDebug::emitDebugMacinfo() { if (CUMap.empty()) return; + if (llvm::all_of(CUMap, [](const decltype(CUMap)::value_type &Pair) { + return Pair.second->getCUNode()->isDebugDirectivesOnly(); + })) + return; + // Start the dwarf macinfo section. Asm->OutStreamer->SwitchSection( Asm->getObjFileLowering().getDwarfMacinfoSection()); for (const auto &P : CUMap) { auto &TheCU = *P.second; + if (TheCU.getCUNode()->isDebugDirectivesOnly()) + continue; auto *SkCU = TheCU.getSkeleton(); DwarfCompileUnit &U = SkCU ? *SkCU : TheCU; auto *CUNode = cast<DICompileUnit>(P.first); @@ -2229,8 +2508,6 @@ void DwarfDebug::emitDebugMacinfo() { void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die, std::unique_ptr<DwarfCompileUnit> NewU) { - NewU->addString(Die, dwarf::DW_AT_GNU_dwo_name, - Asm->TM.Options.MCOptions.SplitDwarfFile); if (!CompilationDir.empty()) NewU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir); @@ -2298,9 +2575,8 @@ void DwarfDebug::emitDebugStrDWO() { OffSec, /* UseRelativeOffsets = */ false); } -// Emit DWO addresses. +// Emit address pool. void DwarfDebug::emitDebugAddr() { - assert(useSplitDwarf() && "No split dwarf?"); AddrPool.emit(*Asm, Asm->getObjFileLowering().getDwarfAddrSection()); } @@ -2356,10 +2632,18 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, NewTU.setTypeSignature(Signature); Ins.first->second = Signature; - if (useSplitDwarf()) - NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesDWOSection()); - else { - NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesSection(Signature)); + if (useSplitDwarf()) { + MCSection *Section = + getDwarfVersion() <= 4 + ? Asm->getObjFileLowering().getDwarfTypesDWOSection() + : Asm->getObjFileLowering().getDwarfInfoDWOSection(); + NewTU.setSection(Section); + } else { + MCSection *Section = + getDwarfVersion() <= 4 + ? Asm->getObjFileLowering().getDwarfTypesSection(Signature) + : Asm->getObjFileLowering().getDwarfInfoSection(Signature); + NewTU.setSection(Section); // Non-split type units reuse the compile unit's line table. CU.applyStmtList(UnitDie); } @@ -2408,14 +2692,18 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, // AccelTableKind::Apple, we use the table we got as an argument). If // accelerator tables are disabled, this function does nothing. template <typename DataT> -void DwarfDebug::addAccelNameImpl(AccelTable<DataT> &AppleAccel, StringRef Name, +void DwarfDebug::addAccelNameImpl(const DICompileUnit &CU, + AccelTable<DataT> &AppleAccel, StringRef Name, const DIE &Die) { if (getAccelTableKind() == AccelTableKind::None) return; + if (getAccelTableKind() != AccelTableKind::Apple && + CU.getNameTableKind() == DICompileUnit::DebugNameTableKind::None) + return; + DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; - DwarfStringPoolEntryRef Ref = - Holder.getStringPool().getEntry(*Asm, Name); + DwarfStringPoolEntryRef Ref = Holder.getStringPool().getEntry(*Asm, Name); switch (getAccelTableKind()) { case AccelTableKind::Apple: @@ -2431,24 +2719,36 @@ void DwarfDebug::addAccelNameImpl(AccelTable<DataT> &AppleAccel, StringRef Name, } } -void DwarfDebug::addAccelName(StringRef Name, const DIE &Die) { - addAccelNameImpl(AccelNames, Name, Die); +void DwarfDebug::addAccelName(const DICompileUnit &CU, StringRef Name, + const DIE &Die) { + addAccelNameImpl(CU, AccelNames, Name, Die); } -void DwarfDebug::addAccelObjC(StringRef Name, const DIE &Die) { +void DwarfDebug::addAccelObjC(const DICompileUnit &CU, StringRef Name, + const DIE &Die) { // ObjC names go only into the Apple accelerator tables. if (getAccelTableKind() == AccelTableKind::Apple) - addAccelNameImpl(AccelObjC, Name, Die); + addAccelNameImpl(CU, AccelObjC, Name, Die); } -void DwarfDebug::addAccelNamespace(StringRef Name, const DIE &Die) { - addAccelNameImpl(AccelNamespace, Name, Die); +void DwarfDebug::addAccelNamespace(const DICompileUnit &CU, StringRef Name, + const DIE &Die) { + addAccelNameImpl(CU, AccelNamespace, Name, Die); } -void DwarfDebug::addAccelType(StringRef Name, const DIE &Die, char Flags) { - addAccelNameImpl(AccelTypes, Name, Die); +void DwarfDebug::addAccelType(const DICompileUnit &CU, StringRef Name, + const DIE &Die, char Flags) { + addAccelNameImpl(CU, AccelTypes, Name, Die); } uint16_t DwarfDebug::getDwarfVersion() const { return Asm->OutStreamer->getContext().getDwarfVersion(); } + +void DwarfDebug::addSectionLabel(const MCSymbol *Sym) { + SectionLabels.insert(std::make_pair(&Sym->getSection(), Sym)); +} + +const MCSymbol *DwarfDebug::getSectionLabel(const MCSection *S) { + return SectionLabels.find(S)->second; +} diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h index abf2e43b1312..8a31e989b289 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -15,8 +15,6 @@ #define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFDEBUG_H #include "AddressPool.h" -#include "DbgValueHistoryCalculator.h" -#include "DebugHandlerBase.h" #include "DebugLocStream.h" #include "DwarfFile.h" #include "llvm/ADT/ArrayRef.h" @@ -31,6 +29,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/CodeGen/AccelTable.h" +#include "llvm/CodeGen/DbgEntityHistoryCalculator.h" +#include "llvm/CodeGen/DebugHandlerBase.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DebugLoc.h" @@ -62,6 +62,47 @@ class MDNode; class Module; //===----------------------------------------------------------------------===// +/// This class is defined as the common parent of DbgVariable and DbgLabel +/// such that it could levarage polymorphism to extract common code for +/// DbgVariable and DbgLabel. +class DbgEntity { + const DINode *Entity; + const DILocation *InlinedAt; + DIE *TheDIE = nullptr; + unsigned SubclassID; + +public: + enum DbgEntityKind { + DbgVariableKind, + DbgLabelKind + }; + + DbgEntity(const DINode *N, const DILocation *IA, unsigned ID) + : Entity(N), InlinedAt(IA), SubclassID(ID) {} + virtual ~DbgEntity() {} + + /// Accessors. + /// @{ + const DINode *getEntity() const { return Entity; } + const DILocation *getInlinedAt() const { return InlinedAt; } + DIE *getDIE() const { return TheDIE; } + unsigned getDbgEntityID() const { return SubclassID; } + /// @} + + void setDIE(DIE &D) { TheDIE = &D; } + + static bool classof(const DbgEntity *N) { + switch (N->getDbgEntityID()) { + default: + return false; + case DbgVariableKind: + case DbgLabelKind: + return true; + } + } +}; + +//===----------------------------------------------------------------------===// /// This class is used to track local variable information. /// /// Variables can be created from allocas, in which case they're generated from @@ -73,10 +114,7 @@ class Module; /// single instruction use \a MInsn and (optionally) a single entry of \a Expr. /// /// Variables that have been optimized out use none of these fields. -class DbgVariable { - const DILocalVariable *Var; /// Variable Descriptor. - const DILocation *IA; /// Inlined at location. - DIE *TheDIE = nullptr; /// Variable DIE. +class DbgVariable : public DbgEntity { unsigned DebugLocListIndex = ~0u; /// Offset in DebugLocs. const MachineInstr *MInsn = nullptr; /// DBG_VALUE instruction. @@ -93,7 +131,7 @@ public: /// Creates a variable without any DW_AT_location. Call \a initializeMMI() /// for MMI entries, or \a initializeDbgValue() for DBG_VALUE instructions. DbgVariable(const DILocalVariable *V, const DILocation *IA) - : Var(V), IA(IA) {} + : DbgEntity(V, IA, DbgVariableKind) {} /// Initialize from the MMI table. void initializeMMI(const DIExpression *E, int FI) { @@ -111,8 +149,9 @@ public: assert(FrameIndexExprs.empty() && "Already initialized?"); assert(!MInsn && "Already initialized?"); - assert(Var == DbgValue->getDebugVariable() && "Wrong variable"); - assert(IA == DbgValue->getDebugLoc()->getInlinedAt() && "Wrong inlined-at"); + assert(getVariable() == DbgValue->getDebugVariable() && "Wrong variable"); + assert(getInlinedAt() == DbgValue->getDebugLoc()->getInlinedAt() && + "Wrong inlined-at"); MInsn = DbgValue; if (auto *E = DbgValue->getDebugExpression()) @@ -121,19 +160,18 @@ public: } // Accessors. - const DILocalVariable *getVariable() const { return Var; } - const DILocation *getInlinedAt() const { return IA; } + const DILocalVariable *getVariable() const { + return cast<DILocalVariable>(getEntity()); + } const DIExpression *getSingleExpression() const { assert(MInsn && FrameIndexExprs.size() <= 1); return FrameIndexExprs.size() ? FrameIndexExprs[0].Expr : nullptr; } - void setDIE(DIE &D) { TheDIE = &D; } - DIE *getDIE() const { return TheDIE; } void setDebugLocListIndex(unsigned O) { DebugLocListIndex = O; } unsigned getDebugLocListIndex() const { return DebugLocListIndex; } - StringRef getName() const { return Var->getName(); } + StringRef getName() const { return getVariable()->getName(); } const MachineInstr *getMInsn() const { return MInsn; } /// Get the FI entries, sorted by fragment offset. ArrayRef<FrameIndexExpr> getFrameIndexExprs() const; @@ -143,7 +181,7 @@ public: // Translate tag to proper Dwarf tag. dwarf::Tag getTag() const { // FIXME: Why don't we just infer this tag and store it all along? - if (Var->isParameter()) + if (getVariable()->isParameter()) return dwarf::DW_TAG_formal_parameter; return dwarf::DW_TAG_variable; @@ -151,7 +189,7 @@ public: /// Return true if DbgVariable is artificial. bool isArtificial() const { - if (Var->isArtificial()) + if (getVariable()->isArtificial()) return true; if (getType()->isArtificial()) return true; @@ -159,7 +197,7 @@ public: } bool isObjectPointer() const { - if (Var->isObjectPointer()) + if (getVariable()->isObjectPointer()) return true; if (getType()->isObjectPointer()) return true; @@ -178,6 +216,45 @@ public: bool isBlockByrefVariable() const; const DIType *getType() const; + static bool classof(const DbgEntity *N) { + return N->getDbgEntityID() == DbgVariableKind; + } + +private: + template <typename T> T *resolve(TypedDINodeRef<T> Ref) const { + return Ref.resolve(); + } +}; + +//===----------------------------------------------------------------------===// +/// This class is used to track label information. +/// +/// Labels are collected from \c DBG_LABEL instructions. +class DbgLabel : public DbgEntity { + const MCSymbol *Sym; /// Symbol before DBG_LABEL instruction. + +public: + /// We need MCSymbol information to generate DW_AT_low_pc. + DbgLabel(const DILabel *L, const DILocation *IA, const MCSymbol *Sym = nullptr) + : DbgEntity(L, IA, DbgLabelKind), Sym(Sym) {} + + /// Accessors. + /// @{ + const DILabel *getLabel() const { return cast<DILabel>(getEntity()); } + const MCSymbol *getSymbol() const { return Sym; } + + StringRef getName() const { return getLabel()->getName(); } + /// @} + + /// Translate tag to proper Dwarf tag. + dwarf::Tag getTag() const { + return dwarf::DW_TAG_label; + } + + static bool classof(const DbgEntity *N) { + return N->getDbgEntityID() == DbgLabelKind; + } + private: template <typename T> T *resolve(TypedDINodeRef<T> Ref) const { return Ref.resolve(); @@ -217,8 +294,8 @@ class DwarfDebug : public DebugHandlerBase { /// Size of each symbol emitted (for those symbols that have a specific size). DenseMap<const MCSymbol *, uint64_t> SymSize; - /// Collection of abstract variables. - SmallVector<std::unique_ptr<DbgVariable>, 64> ConcreteVariables; + /// Collection of abstract variables/labels. + SmallVector<std::unique_ptr<DbgEntity>, 64> ConcreteEntities; /// Collection of DebugLocEntry. Stored in a linked list so that DIELocLists /// can refer to them in spite of insertions into this list. @@ -250,6 +327,8 @@ class DwarfDebug : public DebugHandlerBase { /// used to keep track of which types we have emitted type units for. DenseMap<const MDNode *, uint64_t> TypeSignatures; + DenseMap<const MCSection *, const MCSymbol *> SectionLabels; + SmallVector< std::pair<std::unique_ptr<DwarfTypeUnit>, const DICompositeType *>, 1> TypeUnitsUnderConstruction; @@ -266,9 +345,6 @@ class DwarfDebug : public DebugHandlerBase { /// Use inlined strings. bool UseInlineStrings = false; - /// Whether to emit DWARF pub sections or not. - bool UsePubSections = true; - /// Allow emission of .debug_ranges section. bool UseRangesSection = true; @@ -332,24 +408,33 @@ class DwarfDebug : public DebugHandlerBase { return InfoHolder.getUnits(); } - using InlinedVariable = DbgValueHistoryMap::InlinedVariable; + using InlinedEntity = DbgValueHistoryMap::InlinedEntity; - void ensureAbstractVariableIsCreated(DwarfCompileUnit &CU, InlinedVariable IV, - const MDNode *Scope); - void ensureAbstractVariableIsCreatedIfScoped(DwarfCompileUnit &CU, InlinedVariable IV, - const MDNode *Scope); + void ensureAbstractEntityIsCreated(DwarfCompileUnit &CU, + const DINode *Node, + const MDNode *Scope); + void ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU, + const DINode *Node, + const MDNode *Scope); - DbgVariable *createConcreteVariable(DwarfCompileUnit &TheCU, - LexicalScope &Scope, InlinedVariable IV); + DbgEntity *createConcreteEntity(DwarfCompileUnit &TheCU, + LexicalScope &Scope, + const DINode *Node, + const DILocation *Location, + const MCSymbol *Sym = nullptr); /// Construct a DIE for this abstract scope. void constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU, LexicalScope *Scope); + /// Construct DIEs for call site entries describing the calls in \p MF. + void constructCallSiteEntryDIEs(const DISubprogram &SP, DwarfCompileUnit &CU, + DIE &ScopeDIE, const MachineFunction &MF); + template <typename DataT> - void addAccelNameImpl(AccelTable<DataT> &AppleAccel, StringRef Name, - const DIE &Die); + void addAccelNameImpl(const DICompileUnit &CU, AccelTable<DataT> &AppleAccel, + StringRef Name, const DIE &Die); - void finishVariableDefinitions(); + void finishEntityDefinitions(); void finishSubprogramDefinitions(); @@ -407,9 +492,7 @@ class DwarfDebug : public DebugHandlerBase { /// Emit address ranges into a debug ranges section. void emitDebugRanges(); - - /// Emit range lists into a DWARF v5 debug rnglists section. - void emitDebugRnglists(); + void emitDebugRangesDWO(); /// Emit macros into a debug macinfo section. void emitDebugMacinfo(); @@ -457,6 +540,8 @@ class DwarfDebug : public DebugHandlerBase { /// Create new DwarfCompileUnit for the given metadata node with tag /// DW_TAG_compile_unit. DwarfCompileUnit &getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit); + void finishUnitAttributes(const DICompileUnit *DIUnit, + DwarfCompileUnit &NewCU); /// Construct imported_module or imported_declaration DIE. void constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU, @@ -469,8 +554,8 @@ class DwarfDebug : public DebugHandlerBase { unsigned Flags); /// Populate LexicalScope entries with variables' info. - void collectVariableInfo(DwarfCompileUnit &TheCU, const DISubprogram *SP, - DenseSet<InlinedVariable> &ProcessedVars); + void collectEntityInfo(DwarfCompileUnit &TheCU, const DISubprogram *SP, + DenseSet<InlinedEntity> &ProcessedVars); /// Build the location list for all DBG_VALUEs in the /// function that describe the same variable. @@ -479,7 +564,7 @@ class DwarfDebug : public DebugHandlerBase { /// Collect variable information from the side table maintained by MF. void collectVariableInfoFromMFTable(DwarfCompileUnit &TheCU, - DenseSet<InlinedVariable> &P); + DenseSet<InlinedEntity> &P); /// Emit the reference to the section. void emitSectionReference(const DwarfCompileUnit &CU); @@ -543,9 +628,6 @@ public: /// Returns whether to use inline strings. bool useInlineStrings() const { return UseInlineStrings; } - /// Returns whether GNU pub sections should be emitted. - bool usePubSections() const { return UsePubSections; } - /// Returns whether ranges section should be emitted. bool useRangesSection() const { return UseRangesSection; } @@ -608,17 +690,20 @@ public: return Ref.resolve(); } - void addSubprogramNames(const DISubprogram *SP, DIE &Die); + void addSubprogramNames(const DICompileUnit &CU, const DISubprogram *SP, + DIE &Die); AddressPool &getAddressPool() { return AddrPool; } - void addAccelName(StringRef Name, const DIE &Die); + void addAccelName(const DICompileUnit &CU, StringRef Name, const DIE &Die); - void addAccelObjC(StringRef Name, const DIE &Die); + void addAccelObjC(const DICompileUnit &CU, StringRef Name, const DIE &Die); - void addAccelNamespace(StringRef Name, const DIE &Die); + void addAccelNamespace(const DICompileUnit &CU, StringRef Name, + const DIE &Die); - void addAccelType(StringRef Name, const DIE &Die, char Flags); + void addAccelType(const DICompileUnit &CU, StringRef Name, const DIE &Die, + char Flags); const MachineFunction *getCurrentFunction() const { return CurFn; } @@ -640,6 +725,9 @@ public: bool tuneForLLDB() const { return DebuggerTuning == DebuggerKind::LLDB; } bool tuneForSCE() const { return DebuggerTuning == DebuggerKind::SCE; } /// @} + + void addSectionLabel(const MCSymbol *Sym); + const MCSymbol *getSectionLabel(const MCSection *S); }; } // end namespace llvm diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp index d8d1a5e8f841..19c350afbf17 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -24,6 +24,20 @@ using namespace llvm; +void DwarfExpression::emitConstu(uint64_t Value) { + if (Value < 32) + emitOp(dwarf::DW_OP_lit0 + Value); + else if (Value == std::numeric_limits<uint64_t>::max()) { + // Only do this for 64-bit values as the DWARF expression stack uses + // target-address-size values. + emitOp(dwarf::DW_OP_lit0); + emitOp(dwarf::DW_OP_not); + } else { + emitOp(dwarf::DW_OP_constu); + emitUnsigned(Value); + } +} + void DwarfExpression::addReg(int DwarfReg, const char *Comment) { assert(DwarfReg >= 0 && "invalid negative dwarf register number"); assert((LocationKind == Unknown || LocationKind == Register) && @@ -72,14 +86,12 @@ void DwarfExpression::addOpPiece(unsigned SizeInBits, unsigned OffsetInBits) { } void DwarfExpression::addShr(unsigned ShiftBy) { - emitOp(dwarf::DW_OP_constu); - emitUnsigned(ShiftBy); + emitConstu(ShiftBy); emitOp(dwarf::DW_OP_shr); } void DwarfExpression::addAnd(unsigned Mask) { - emitOp(dwarf::DW_OP_constu); - emitUnsigned(Mask); + emitConstu(Mask); emitOp(dwarf::DW_OP_and); } @@ -181,8 +193,7 @@ void DwarfExpression::addSignedConstant(int64_t Value) { void DwarfExpression::addUnsignedConstant(uint64_t Value) { assert(LocationKind == Implicit || LocationKind == Unknown); LocationKind = Implicit; - emitOp(dwarf::DW_OP_constu); - emitUnsigned(Value); + emitConstu(Value); } void DwarfExpression::addUnsignedConstant(const APInt &Value) { @@ -243,10 +254,9 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI, // Don't emit locations that cannot be expressed without DW_OP_stack_value. if (DwarfVersion < 4) - if (std::any_of(ExprCursor.begin(), ExprCursor.end(), - [](DIExpression::ExprOperand Op) -> bool { - return Op.getOp() == dwarf::DW_OP_stack_value; - })) { + if (any_of(ExprCursor, [](DIExpression::ExprOperand Op) -> bool { + return Op.getOp() == dwarf::DW_OP_stack_value; + })) { DwarfRegs.clear(); LocationKind = Unknown; return false; @@ -373,8 +383,7 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor, break; case dwarf::DW_OP_constu: assert(LocationKind != Register); - emitOp(dwarf::DW_OP_constu); - emitUnsigned(Op->getArg(0)); + emitConstu(Op->getArg(0)); break; case dwarf::DW_OP_stack_value: LocationKind = Implicit; diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h index 0637d952eba4..91568ba6d107 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h @@ -138,6 +138,9 @@ protected: /// Emit a raw unsigned value. virtual void emitUnsigned(uint64_t Value) = 0; + /// Emit a normalized unsigned constant. + void emitConstu(uint64_t Value); + /// Return whether the given machine register is the frame register in the /// current function. virtual bool isFrameRegister(const TargetRegisterInfo &TRI, unsigned MachineReg) = 0; @@ -187,7 +190,7 @@ protected: /// DW_OP_stack_value. Unfortunately, DW_OP_stack_value was not available /// until DWARF 4, so we will continue to generate DW_OP_constu <const> for /// DWARF 2 and DWARF 3. Technically, this is incorrect since DW_OP_const - /// <const> actually describes a value at a constant addess, not a constant + /// <const> actually describes a value at a constant address, not a constant /// value. However, in the past there was no better way to describe a /// constant value, so the producers and consumers started to rely on /// heuristics to disambiguate the value vs. location status of the diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp index 049f349b009a..78ccad481411 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp @@ -36,13 +36,20 @@ void DwarfFile::emitUnits(bool UseOffsets) { } void DwarfFile::emitUnit(DwarfUnit *TheU, bool UseOffsets) { - DIE &Die = TheU->getUnitDie(); - MCSection *USection = TheU->getSection(); - Asm->OutStreamer->SwitchSection(USection); + if (TheU->getCUNode()->isDebugDirectivesOnly()) + return; + MCSection *S = TheU->getSection(); + + if (!S) + return; + + Asm->OutStreamer->SwitchSection(S); TheU->emitHeader(UseOffsets); + Asm->emitDwarfDIE(TheU->getUnitDie()); - Asm->emitDwarfDIE(Die); + if (MCSymbol *EndLabel = TheU->getEndLabel()) + Asm->OutStreamer->EmitLabel(EndLabel); } // Compute the size and offset for each DIE. @@ -53,6 +60,9 @@ void DwarfFile::computeSizeAndOffsets() { // Iterate over each compile unit and set the size and offsets for each // DIE within each compile unit. All offsets are CU relative. for (const auto &TheU : CUs) { + if (TheU->getCUNode()->isDebugDirectivesOnly()) + continue; + TheU->setDebugSectionOffset(SecOffset); SecOffset += computeSizeAndOffsetsForUnit(TheU.get()); } @@ -98,3 +108,15 @@ bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) { } return true; } + +void DwarfFile::addScopeLabel(LexicalScope *LS, DbgLabel *Label) { + SmallVectorImpl<DbgLabel *> &Labels = ScopeLabels[LS]; + Labels.push_back(Label); +} + +std::pair<uint32_t, RangeSpanList *> +DwarfFile::addRange(const DwarfCompileUnit &CU, SmallVector<RangeSpan, 2> R) { + CURangeLists.push_back( + RangeSpanList(Asm->createTempSymbol("debug_ranges"), CU, std::move(R))); + return std::make_pair(CURangeLists.size() - 1, &CURangeLists.back()); +} diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h index 8dfbc4e1c434..51acca8c1e53 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h @@ -24,12 +24,44 @@ namespace llvm { class AsmPrinter; +class DbgEntity; class DbgVariable; +class DbgLabel; class DwarfCompileUnit; class DwarfUnit; class LexicalScope; class MCSection; +// Data structure to hold a range for range lists. +class RangeSpan { +public: + RangeSpan(MCSymbol *S, MCSymbol *E) : Start(S), End(E) {} + const MCSymbol *getStart() const { return Start; } + const MCSymbol *getEnd() const { return End; } + void setEnd(const MCSymbol *E) { End = E; } + +private: + const MCSymbol *Start, *End; +}; + +class RangeSpanList { +private: + // Index for locating within the debug_range section this particular span. + MCSymbol *RangeSym; + const DwarfCompileUnit *CU; + // List of ranges. + SmallVector<RangeSpan, 2> Ranges; + +public: + RangeSpanList(MCSymbol *Sym, const DwarfCompileUnit &CU, + SmallVector<RangeSpan, 2> Ranges) + : RangeSym(Sym), CU(&CU), Ranges(std::move(Ranges)) {} + MCSymbol *getSym() const { return RangeSym; } + const DwarfCompileUnit &getCU() const { return *CU; } + const SmallVectorImpl<RangeSpan> &getRanges() const { return Ranges; } + void addRange(RangeSpan Range) { Ranges.push_back(Range); } +}; + class DwarfFile { // Target of Dwarf emission, used for sizing of abbreviations. AsmPrinter *Asm; @@ -44,6 +76,10 @@ class DwarfFile { DwarfStringPool StrPool; + // List of range lists for a given compile unit, separate from the ranges for + // the CU itself. + SmallVector<RangeSpanList, 1> CURangeLists; + /// DWARF v5: The symbol that designates the start of the contribution to /// the string offsets table. The contribution is shared by all units. MCSymbol *StringOffsetsStartSym = nullptr; @@ -52,6 +88,10 @@ class DwarfFile { /// The table is shared by all units. MCSymbol *RnglistsTableBaseSym = nullptr; + /// DWARF v5: The symbol that designates the base of the locations list table. + /// The table is shared by all units. + MCSymbol *LoclistsTableBaseSym = nullptr; + /// The variables of a lexical scope. struct ScopeVars { /// We need to sort Args by ArgNo and check for duplicates. This could also @@ -62,9 +102,13 @@ class DwarfFile { /// Collection of DbgVariables of each lexical scope. DenseMap<LexicalScope *, ScopeVars> ScopeVariables; + /// Collection of DbgLabels of each lexical scope. + using LabelList = SmallVector<DbgLabel *, 4>; + DenseMap<LexicalScope *, LabelList> ScopeLabels; + // Collection of abstract subprogram DIEs. DenseMap<const MDNode *, DIE *> AbstractSPDies; - DenseMap<const MDNode *, std::unique_ptr<DbgVariable>> AbstractVariables; + DenseMap<const DINode *, std::unique_ptr<DbgEntity>> AbstractEntities; /// Maps MDNodes for type system with the corresponding DIEs. These DIEs can /// be shared across CUs, that is why we keep the map here instead @@ -78,6 +122,14 @@ public: return CUs; } + std::pair<uint32_t, RangeSpanList *> addRange(const DwarfCompileUnit &CU, + SmallVector<RangeSpan, 2> R); + + /// getRangeLists - Get the vector of range lists. + const SmallVectorImpl<RangeSpanList> &getRangeLists() const { + return CURangeLists; + } + /// Compute the size and offset of a DIE given an incoming Offset. unsigned computeSizeAndOffset(DIE &Die, unsigned Offset); @@ -112,26 +164,33 @@ public: DwarfStringPool &getStringPool() { return StrPool; } MCSymbol *getStringOffsetsStartSym() const { return StringOffsetsStartSym; } - void setStringOffsetsStartSym(MCSymbol *Sym) { StringOffsetsStartSym = Sym; } MCSymbol *getRnglistsTableBaseSym() const { return RnglistsTableBaseSym; } - void setRnglistsTableBaseSym(MCSymbol *Sym) { RnglistsTableBaseSym = Sym; } + MCSymbol *getLoclistsTableBaseSym() const { return LoclistsTableBaseSym; } + void setLoclistsTableBaseSym(MCSymbol *Sym) { LoclistsTableBaseSym = Sym; } + /// \returns false if the variable was merged with a previous one. bool addScopeVariable(LexicalScope *LS, DbgVariable *Var); + void addScopeLabel(LexicalScope *LS, DbgLabel *Label); + DenseMap<LexicalScope *, ScopeVars> &getScopeVariables() { return ScopeVariables; } + DenseMap<LexicalScope *, LabelList> &getScopeLabels() { + return ScopeLabels; + } + DenseMap<const MDNode *, DIE *> &getAbstractSPDies() { return AbstractSPDies; } - DenseMap<const MDNode *, std::unique_ptr<DbgVariable>> &getAbstractVariables() { - return AbstractVariables; + DenseMap<const DINode *, std::unique_ptr<DbgEntity>> &getAbstractEntities() { + return AbstractEntities; } void insertDIE(const MDNode *TypeMD, DIE *Die) { diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp index a61fa83cfb03..02016534a774 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp @@ -24,25 +24,39 @@ DwarfStringPool::DwarfStringPool(BumpPtrAllocator &A, AsmPrinter &Asm, : Pool(A), Prefix(Prefix), ShouldCreateSymbols(Asm.MAI->doesDwarfUseRelocationsAcrossSections()) {} -DwarfStringPool::EntryRef DwarfStringPool::getEntry(AsmPrinter &Asm, - StringRef Str) { +StringMapEntry<DwarfStringPool::EntryTy> & +DwarfStringPool::getEntryImpl(AsmPrinter &Asm, StringRef Str) { auto I = Pool.insert(std::make_pair(Str, EntryTy())); + auto &Entry = I.first->second; if (I.second) { - auto &Entry = I.first->second; - Entry.Index = Pool.size() - 1; + Entry.Index = EntryTy::NotIndexed; Entry.Offset = NumBytes; Entry.Symbol = ShouldCreateSymbols ? Asm.createTempSymbol(Prefix) : nullptr; NumBytes += Str.size() + 1; assert(NumBytes > Entry.Offset && "Unexpected overflow"); } - return EntryRef(*I.first); + return *I.first; +} + +DwarfStringPool::EntryRef DwarfStringPool::getEntry(AsmPrinter &Asm, + StringRef Str) { + auto &MapEntry = getEntryImpl(Asm, Str); + return EntryRef(MapEntry, false); +} + +DwarfStringPool::EntryRef DwarfStringPool::getIndexedEntry(AsmPrinter &Asm, + StringRef Str) { + auto &MapEntry = getEntryImpl(Asm, Str); + if (!MapEntry.getValue().isIndexed()) + MapEntry.getValue().Index = NumIndexedStrings++; + return EntryRef(MapEntry, true); } void DwarfStringPool::emitStringOffsetsTableHeader(AsmPrinter &Asm, MCSection *Section, MCSymbol *StartSym) { - if (empty()) + if (getNumIndexedStrings() == 0) return; Asm.OutStreamer->SwitchSection(Section); unsigned EntrySize = 4; @@ -51,7 +65,7 @@ void DwarfStringPool::emitStringOffsetsTableHeader(AsmPrinter &Asm, // table. The header consists of an entry with the contribution's // size (not including the size of the length field), the DWARF version and // 2 bytes of padding. - Asm.emitInt32(size() * EntrySize + 4); + Asm.emitInt32(getNumIndexedStrings() * EntrySize + 4); Asm.emitInt16(Asm.getDwarfVersion()); Asm.emitInt16(0); // Define the symbol that marks the start of the contribution. It is @@ -69,12 +83,17 @@ void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection, // Start the dwarf str section. Asm.OutStreamer->SwitchSection(StrSection); - // Get all of the string pool entries and put them in an array by their ID so - // we can sort them. - SmallVector<const StringMapEntry<EntryTy> *, 64> Entries(Pool.size()); + // Get all of the string pool entries and sort them by their offset. + SmallVector<const StringMapEntry<EntryTy> *, 64> Entries; + Entries.reserve(Pool.size()); for (const auto &E : Pool) - Entries[E.getValue().Index] = &E; + Entries.push_back(&E); + + llvm::sort(Entries, [](const StringMapEntry<EntryTy> *A, + const StringMapEntry<EntryTy> *B) { + return A->getValue().Offset < B->getValue().Offset; + }); for (const auto &Entry : Entries) { assert(ShouldCreateSymbols == static_cast<bool>(Entry->getValue().Symbol) && @@ -93,6 +112,14 @@ void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection, // If we've got an offset section go ahead and emit that now as well. if (OffsetSection) { + // Now only take the indexed entries and put them in an array by their ID so + // we can emit them in order. + Entries.resize(NumIndexedStrings); + for (const auto &Entry : Pool) { + if (Entry.getValue().isIndexed()) + Entries[Entry.getValue().Index] = &Entry; + } + Asm.OutStreamer->SwitchSection(OffsetSection); unsigned size = 4; // FIXME: DWARF64 is 8. for (const auto &Entry : Entries) diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h index 6e6988ea4ad4..f484540d8d37 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h @@ -30,8 +30,11 @@ class DwarfStringPool { StringMap<EntryTy, BumpPtrAllocator &> Pool; StringRef Prefix; unsigned NumBytes = 0; + unsigned NumIndexedStrings = 0; bool ShouldCreateSymbols; + StringMapEntry<EntryTy> &getEntryImpl(AsmPrinter &Asm, StringRef Str); + public: using EntryRef = DwarfStringPoolEntryRef; @@ -48,8 +51,15 @@ public: unsigned size() const { return Pool.size(); } + unsigned getNumIndexedStrings() const { return NumIndexedStrings; } + /// Get a reference to an entry in the string pool. EntryRef getEntry(AsmPrinter &Asm, StringRef Str); + + /// Same as getEntry, except that you can use EntryRef::getIndex to obtain a + /// unique ID of this entry (e.g., for use in indexed forms like + /// DW_FORM_strx). + EntryRef getIndexedEntry(AsmPrinter &Asm, StringRef Str); }; } // end namespace llvm diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 600f4a78fda0..80b365f1aa43 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -234,15 +234,23 @@ void DwarfUnit::addSInt(DIELoc &Die, Optional<dwarf::Form> Form, void DwarfUnit::addString(DIE &Die, dwarf::Attribute Attribute, StringRef String) { + if (CUNode->isDebugDirectivesOnly()) + return; + if (DD->useInlineStrings()) { Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_string, new (DIEValueAllocator) DIEInlineString(String, DIEValueAllocator)); return; } - auto StringPoolEntry = DU->getStringPool().getEntry(*Asm, String); dwarf::Form IxForm = isDwoUnit() ? dwarf::DW_FORM_GNU_str_index : dwarf::DW_FORM_strp; + + auto StringPoolEntry = + useSegmentedStringOffsetsTable() || IxForm == dwarf::DW_FORM_GNU_str_index + ? DU->getStringPool().getIndexedEntry(*Asm, String) + : DU->getStringPool().getEntry(*Asm, String); + // For DWARF v5 and beyond, use the smallest strx? form possible. if (useSegmentedStringOffsetsTable()) { IxForm = dwarf::DW_FORM_strx1; @@ -307,14 +315,21 @@ unsigned DwarfTypeUnit::getOrCreateSourceID(const DIFile *File) { } void DwarfUnit::addOpAddress(DIELoc &Die, const MCSymbol *Sym) { - if (!DD->useSplitDwarf()) { - addUInt(Die, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); - addLabel(Die, dwarf::DW_FORM_udata, Sym); - } else { + if (DD->getDwarfVersion() >= 5) { + addUInt(Die, dwarf::DW_FORM_data1, dwarf::DW_OP_addrx); + addUInt(Die, dwarf::DW_FORM_addrx, DD->getAddressPool().getIndex(Sym)); + return; + } + + if (DD->useSplitDwarf()) { addUInt(Die, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_addr_index); addUInt(Die, dwarf::DW_FORM_GNU_addr_index, DD->getAddressPool().getIndex(Sym)); + return; } + + addUInt(Die, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); + addLabel(Die, dwarf::DW_FORM_udata, Sym); } void DwarfUnit::addLabelDelta(DIE &Die, dwarf::Attribute Attribute, @@ -401,6 +416,12 @@ void DwarfUnit::addSourceLine(DIE &Die, const DISubprogram *SP) { addSourceLine(Die, SP->getLine(), SP->getFile()); } +void DwarfUnit::addSourceLine(DIE &Die, const DILabel *L) { + assert(L); + + addSourceLine(Die, L->getLine(), L->getFile()); +} + void DwarfUnit::addSourceLine(DIE &Die, const DIType *Ty) { assert(Ty); @@ -413,138 +434,6 @@ void DwarfUnit::addSourceLine(DIE &Die, const DIObjCProperty *Ty) { addSourceLine(Die, Ty->getLine(), Ty->getFile()); } -/* Byref variables, in Blocks, are declared by the programmer as "SomeType - VarName;", but the compiler creates a __Block_byref_x_VarName struct, and - gives the variable VarName either the struct, or a pointer to the struct, as - its type. This is necessary for various behind-the-scenes things the - compiler needs to do with by-reference variables in Blocks. - - However, as far as the original *programmer* is concerned, the variable - should still have type 'SomeType', as originally declared. - - The function getBlockByrefType dives into the __Block_byref_x_VarName - struct to find the original type of the variable, which is then assigned to - the variable's Debug Information Entry as its real type. So far, so good. - However now the debugger will expect the variable VarName to have the type - SomeType. So we need the location attribute for the variable to be an - expression that explains to the debugger how to navigate through the - pointers and struct to find the actual variable of type SomeType. - - The following function does just that. We start by getting - the "normal" location for the variable. This will be the location - of either the struct __Block_byref_x_VarName or the pointer to the - struct __Block_byref_x_VarName. - - The struct will look something like: - - struct __Block_byref_x_VarName { - ... <various fields> - struct __Block_byref_x_VarName *forwarding; - ... <various other fields> - SomeType VarName; - ... <maybe more fields> - }; - - If we are given the struct directly (as our starting point) we - need to tell the debugger to: - - 1). Add the offset of the forwarding field. - - 2). Follow that pointer to get the real __Block_byref_x_VarName - struct to use (the real one may have been copied onto the heap). - - 3). Add the offset for the field VarName, to find the actual variable. - - If we started with a pointer to the struct, then we need to - dereference that pointer first, before the other steps. - Translating this into DWARF ops, we will need to append the following - to the current location description for the variable: - - DW_OP_deref -- optional, if we start with a pointer - DW_OP_plus_uconst <forward_fld_offset> - DW_OP_deref - DW_OP_plus_uconst <varName_fld_offset> - - That is what this function does. */ - -void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE &Die, - dwarf::Attribute Attribute, - const MachineLocation &Location) { - const DIType *Ty = DV.getType(); - const DIType *TmpTy = Ty; - uint16_t Tag = Ty->getTag(); - bool isPointer = false; - - StringRef varName = DV.getName(); - - if (Tag == dwarf::DW_TAG_pointer_type) { - auto *DTy = cast<DIDerivedType>(Ty); - TmpTy = resolve(DTy->getBaseType()); - isPointer = true; - } - - // Find the __forwarding field and the variable field in the __Block_byref - // struct. - DINodeArray Fields = cast<DICompositeType>(TmpTy)->getElements(); - const DIDerivedType *varField = nullptr; - const DIDerivedType *forwardingField = nullptr; - - for (unsigned i = 0, N = Fields.size(); i < N; ++i) { - auto *DT = cast<DIDerivedType>(Fields[i]); - StringRef fieldName = DT->getName(); - if (fieldName == "__forwarding") - forwardingField = DT; - else if (fieldName == varName) - varField = DT; - } - - // Get the offsets for the forwarding field and the variable field. - unsigned forwardingFieldOffset = forwardingField->getOffsetInBits() >> 3; - unsigned varFieldOffset = varField->getOffsetInBits() >> 2; - - // Decode the original location, and use that as the start of the byref - // variable's location. - DIELoc *Loc = new (DIEValueAllocator) DIELoc; - DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); - if (Location.isIndirect()) - DwarfExpr.setMemoryLocationKind(); - - SmallVector<uint64_t, 6> Ops; - // If we started with a pointer to the __Block_byref... struct, then - // the first thing we need to do is dereference the pointer (DW_OP_deref). - if (isPointer) - Ops.push_back(dwarf::DW_OP_deref); - - // Next add the offset for the '__forwarding' field: - // DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in - // adding the offset if it's 0. - if (forwardingFieldOffset > 0) { - Ops.push_back(dwarf::DW_OP_plus_uconst); - Ops.push_back(forwardingFieldOffset); - } - - // Now dereference the __forwarding field to get to the real __Block_byref - // struct: DW_OP_deref. - Ops.push_back(dwarf::DW_OP_deref); - - // Now that we've got the real __Block_byref... struct, add the offset - // for the variable's field to get to the location of the actual variable: - // DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0. - if (varFieldOffset > 0) { - Ops.push_back(dwarf::DW_OP_plus_uconst); - Ops.push_back(varFieldOffset); - } - - DIExpressionCursor Cursor(Ops); - const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo(); - if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg())) - return; - DwarfExpr.addExpression(std::move(Cursor)); - - // Now attach the location information to the DIE. - addBlock(Die, Attribute, DwarfExpr.finalize()); -} - /// Return true if type encoding is unsigned. static bool isUnsignedDIType(DwarfDebug *DD, const DIType *Ty) { if (auto *CTy = dyn_cast<DICompositeType>(Ty)) { @@ -787,7 +676,7 @@ void DwarfUnit::updateAcceleratorTables(const DIScope *Context, IsImplementation = CT->getRuntimeLang() == 0 || CT->isObjcClassComplete(); } unsigned Flags = IsImplementation ? dwarf::DW_FLAG_type_implementation : 0; - DD->addAccelType(Ty->getName(), TyDIE, Flags); + DD->addAccelType(*CUNode, Ty->getName(), TyDIE, Flags); if (!Context || isa<DICompileUnit>(Context) || isa<DIFile>(Context) || isa<DINamespace>(Context)) @@ -851,6 +740,11 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIBasicType *BTy) { uint64_t Size = BTy->getSizeInBits() >> 3; addUInt(Buffer, dwarf::DW_AT_byte_size, None, Size); + + if (BTy->isBigEndian()) + addUInt(Buffer, dwarf::DW_AT_endianity, None, dwarf::DW_END_big); + else if (BTy->isLittleEndian()) + addUInt(Buffer, dwarf::DW_AT_endianity, None, dwarf::DW_END_little); } void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy) { @@ -1155,7 +1049,7 @@ DIE *DwarfUnit::getOrCreateNameSpace(const DINamespace *NS) { addString(NDie, dwarf::DW_AT_name, NS->getName()); else Name = "(anonymous namespace)"; - DD->addAccelNamespace(Name, NDie); + DD->addAccelNamespace(*CUNode, Name, NDie); addGlobalName(Name, NDie, NS->getScope()); if (NS->getExportSymbols()) addFlag(NDie, dwarf::DW_AT_export_symbols); @@ -1404,7 +1298,7 @@ DIE *DwarfUnit::getIndexTyDie() { addUInt(*IndexTyDie, dwarf::DW_AT_byte_size, None, sizeof(int64_t)); addUInt(*IndexTyDie, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, dwarf::DW_ATE_unsigned); - DD->addAccelType(Name, *IndexTyDie, /*Flags*/ 0); + DD->addAccelType(*CUNode, Name, *IndexTyDie, /*Flags*/ 0); return IndexTyDie; } @@ -1467,7 +1361,7 @@ void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) { if (DTy) { if (DD->getDwarfVersion() >= 3) addType(Buffer, DTy); - if (DD->getDwarfVersion() >= 4 && (CTy->getFlags() & DINode::FlagFixedEnum)) + if (DD->getDwarfVersion() >= 4 && (CTy->getFlags() & DINode::FlagEnumClass)) addFlag(Buffer, dwarf::DW_AT_enum_class); } @@ -1659,7 +1553,14 @@ DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT) { void DwarfUnit::emitCommonHeader(bool UseOffsets, dwarf::UnitType UT) { // Emit size of content not including length itself Asm->OutStreamer->AddComment("Length of Unit"); - Asm->emitInt32(getHeaderSize() + getUnitDie().getSize()); + if (!DD->useSectionsAsReferences()) { + StringRef Prefix = isDwoUnit() ? "debug_info_dwo_" : "debug_info_"; + MCSymbol *BeginLabel = Asm->createTempSymbol(Prefix + "start"); + EndLabel = Asm->createTempSymbol(Prefix + "end"); + Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); + Asm->OutStreamer->EmitLabel(BeginLabel); + } else + Asm->emitInt32(getHeaderSize() + getUnitDie().getSize()); Asm->OutStreamer->AddComment("DWARF version number"); unsigned Version = DD->getDwarfVersion(); @@ -1761,3 +1662,12 @@ void DwarfUnit::addRnglistsBase() { DU->getRnglistsTableBaseSym(), TLOF.getDwarfRnglistsSection()->getBeginSymbol()); } + +void DwarfUnit::addLoclistsBase() { + assert(DD->getDwarfVersion() >= 5 && + "DW_AT_loclists_base requires DWARF version 5 or later"); + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + addSectionLabel(getUnitDie(), dwarf::DW_AT_loclists_base, + DU->getLoclistsTableBaseSym(), + TLOF.getDwarfLoclistsSection()->getBeginSymbol()); +} diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h index 69696f626536..a59ebb7c1465 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -35,33 +35,6 @@ class ConstantFP; class DbgVariable; class DwarfCompileUnit; -// Data structure to hold a range for range lists. -class RangeSpan { -public: - RangeSpan(MCSymbol *S, MCSymbol *E) : Start(S), End(E) {} - const MCSymbol *getStart() const { return Start; } - const MCSymbol *getEnd() const { return End; } - void setEnd(const MCSymbol *E) { End = E; } - -private: - const MCSymbol *Start, *End; -}; - -class RangeSpanList { -private: - // Index for locating within the debug_range section this particular span. - MCSymbol *RangeSym; - // List of ranges. - SmallVector<RangeSpan, 2> Ranges; - -public: - RangeSpanList(MCSymbol *Sym, SmallVector<RangeSpan, 2> Ranges) - : RangeSym(Sym), Ranges(std::move(Ranges)) {} - MCSymbol *getSym() const { return RangeSym; } - const SmallVectorImpl<RangeSpan> &getRanges() const { return Ranges; } - void addRange(RangeSpan Range) { Ranges.push_back(Range); } -}; - //===----------------------------------------------------------------------===// /// This dwarf writer support class manages information associated with a /// source file. @@ -76,6 +49,9 @@ protected: /// Target of Dwarf emission. AsmPrinter *Asm; + /// Emitted at the end of the CU and used to compute the CU Length field. + MCSymbol *EndLabel = nullptr; + // Holders for some common dwarf information. DwarfDebug *DD; DwarfFile *DU; @@ -109,6 +85,7 @@ protected: public: // Accessors. AsmPrinter* getAsmPrinter() const { return Asm; } + MCSymbol *getEndLabel() const { return EndLabel; } uint16_t getLanguage() const { return CUNode->getSourceLanguage(); } const DICompileUnit *getCUNode() const { return CUNode; } @@ -213,6 +190,7 @@ public: void addSourceLine(DIE &Die, const DILocalVariable *V); void addSourceLine(DIE &Die, const DIGlobalVariable *G); void addSourceLine(DIE &Die, const DISubprogram *SP); + void addSourceLine(DIE &Die, const DILabel *L); void addSourceLine(DIE &Die, const DIType *Ty); void addSourceLine(DIE &Die, const DIObjCProperty *Ty); @@ -298,6 +276,9 @@ public: /// Add the DW_AT_rnglists_base attribute to the unit DIE. void addRnglistsBase(); + /// Add the DW_AT_loclists_base attribute to the unit DIE. + void addLoclistsBase(); + virtual DwarfCompileUnit &getCU() = 0; void constructTypeDIE(DIE &Buffer, const DICompositeType *CTy); diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp index 65de9d7e65a4..7599121de2b0 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp @@ -99,7 +99,7 @@ void EHStreamer::computeActionsTable( FirstActions.reserve(LandingPads.size()); int FirstAction = 0; - unsigned SizeActions = 0; + unsigned SizeActions = 0; // Total size of all action entries for a function const LandingPadInfo *PrevLPI = nullptr; for (SmallVectorImpl<const LandingPadInfo *>::const_iterator @@ -107,23 +107,24 @@ void EHStreamer::computeActionsTable( const LandingPadInfo *LPI = *I; const std::vector<int> &TypeIds = LPI->TypeIds; unsigned NumShared = PrevLPI ? sharedTypeIDs(LPI, PrevLPI) : 0; - unsigned SizeSiteActions = 0; + unsigned SizeSiteActions = 0; // Total size of all entries for a landingpad if (NumShared < TypeIds.size()) { - unsigned SizeAction = 0; + // Size of one action entry (typeid + next action) + unsigned SizeActionEntry = 0; unsigned PrevAction = (unsigned)-1; if (NumShared) { unsigned SizePrevIds = PrevLPI->TypeIds.size(); assert(Actions.size()); PrevAction = Actions.size() - 1; - SizeAction = getSLEB128Size(Actions[PrevAction].NextAction) + - getSLEB128Size(Actions[PrevAction].ValueForTypeID); + SizeActionEntry = getSLEB128Size(Actions[PrevAction].NextAction) + + getSLEB128Size(Actions[PrevAction].ValueForTypeID); for (unsigned j = NumShared; j != SizePrevIds; ++j) { assert(PrevAction != (unsigned)-1 && "PrevAction is invalid!"); - SizeAction -= getSLEB128Size(Actions[PrevAction].ValueForTypeID); - SizeAction += -Actions[PrevAction].NextAction; + SizeActionEntry -= getSLEB128Size(Actions[PrevAction].ValueForTypeID); + SizeActionEntry += -Actions[PrevAction].NextAction; PrevAction = Actions[PrevAction].Previous; } } @@ -136,9 +137,9 @@ void EHStreamer::computeActionsTable( isFilterEHSelector(TypeID) ? FilterOffsets[-1 - TypeID] : TypeID; unsigned SizeTypeID = getSLEB128Size(ValueForTypeID); - int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0; - SizeAction = SizeTypeID + getSLEB128Size(NextAction); - SizeSiteActions += SizeAction; + int NextAction = SizeActionEntry ? -(SizeActionEntry + SizeTypeID) : 0; + SizeActionEntry = SizeTypeID + getSLEB128Size(NextAction); + SizeSiteActions += SizeActionEntry; ActionEntry Action = { ValueForTypeID, NextAction, PrevAction }; Actions.push_back(Action); @@ -146,7 +147,7 @@ void EHStreamer::computeActionsTable( } // Record the first action of the landing pad site. - FirstAction = SizeActions + SizeSiteActions - SizeAction + 1; + FirstAction = SizeActions + SizeSiteActions - SizeActionEntry + 1; } // else identical - re-use previous FirstAction // Information used when creating the call-site table. The action record @@ -344,7 +345,9 @@ computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, /// unwound and handling continues. /// 3. Type ID table contains references to all the C++ typeinfo for all /// catches in the function. This tables is reverse indexed base 1. -void EHStreamer::emitExceptionTable() { +/// +/// Returns the starting symbol of an exception table. +MCSymbol *EHStreamer::emitExceptionTable() { const MachineFunction *MF = Asm->MF; const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos(); const std::vector<unsigned> &FilterIds = MF->getFilterIds(); @@ -359,9 +362,9 @@ void EHStreamer::emitExceptionTable() { LandingPads.push_back(&PadInfos[i]); // Order landing pads lexicographically by type id. - llvm::sort(LandingPads.begin(), LandingPads.end(), - [](const LandingPadInfo *L, - const LandingPadInfo *R) { return L->TypeIds < R->TypeIds; }); + llvm::sort(LandingPads, [](const LandingPadInfo *L, const LandingPadInfo *R) { + return L->TypeIds < R->TypeIds; + }); // Compute the actions table and gather the first action index for each // landing pad site. @@ -374,6 +377,7 @@ void EHStreamer::emitExceptionTable() { computeCallSiteTable(CallSites, LandingPads, FirstActions); bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; + bool IsWasm = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Wasm; unsigned CallSiteEncoding = IsSJLJ ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_uleb128; bool HaveTTData = !TypeInfos.empty() || !FilterIds.empty(); @@ -456,8 +460,8 @@ void EHStreamer::emitExceptionTable() { Asm->EmitLabelDifferenceAsULEB128(CstEndLabel, CstBeginLabel); Asm->OutStreamer->EmitLabel(CstBeginLabel); - // SjLj Exception handling - if (IsSJLJ) { + // SjLj / Wasm Exception handling + if (IsSJLJ || IsWasm) { unsigned idx = 0; for (SmallVectorImpl<CallSiteEntry>::const_iterator I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) { @@ -603,6 +607,7 @@ void EHStreamer::emitExceptionTable() { } Asm->EmitAlignment(2); + return GCCETSym; } void EHStreamer::emitTypeInfos(unsigned TTypeEncoding, MCSymbol *TTBaseLabel) { diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.h b/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.h index b89421a1e067..ce912d032c6d 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.h @@ -14,8 +14,8 @@ #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_EHSTREAMER_H #define LLVM_LIB_CODEGEN_ASMPRINTER_EHSTREAMER_H -#include "AsmPrinterHandler.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/AsmPrinterHandler.h" #include "llvm/Support/Compiler.h" namespace llvm { @@ -85,9 +85,10 @@ protected: /// zero for the landing pad and the action. Calls marked 'nounwind' have /// no entry and must not be contained in the try-range of any entry - they /// form gaps in the table. Entries must be ordered by try-range address. - void computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, - const SmallVectorImpl<const LandingPadInfo *> &LandingPads, - const SmallVectorImpl<unsigned> &FirstActions); + virtual void computeCallSiteTable( + SmallVectorImpl<CallSiteEntry> &CallSites, + const SmallVectorImpl<const LandingPadInfo *> &LandingPads, + const SmallVectorImpl<unsigned> &FirstActions); /// Emit landing pads and actions. /// @@ -108,7 +109,9 @@ protected: /// found the frame is unwound and handling continues. /// 3. Type id table contains references to all the C++ typeinfo for all /// catches in the function. This tables is reversed indexed base 1. - void emitExceptionTable(); + /// + /// Returns the starting symbol of an exception table. + MCSymbol *emitExceptionTable(); virtual void emitTypeInfos(unsigned TTypeEncoding, MCSymbol *TTBaseLabel); diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp index 49cc376fcc98..34677ecc9e69 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp @@ -15,10 +15,10 @@ #include "llvm/BinaryFormat/ELF.h" #include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/BuiltinGCs.h" #include "llvm/CodeGen/GCMetadata.h" #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/GCStrategy.h" -#include "llvm/CodeGen/GCs.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp index 59a57ed30d10..3479a00def23 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp @@ -15,9 +15,9 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/BuiltinGCs.h" #include "llvm/CodeGen/GCMetadata.h" #include "llvm/CodeGen/GCMetadataPrinter.h" -#include "llvm/CodeGen/GCs.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/IR/Mangler.h" diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/WasmException.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/WasmException.cpp new file mode 100644 index 000000000000..527e5ae50146 --- /dev/null +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/WasmException.cpp @@ -0,0 +1,97 @@ +//===-- CodeGen/AsmPrinter/WasmException.cpp - Wasm Exception Impl --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing WebAssembly exception info into asm +// files. +// +//===----------------------------------------------------------------------===// + +#include "WasmException.h" +#include "llvm/IR/Mangler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCStreamer.h" +using namespace llvm; + +void WasmException::endModule() { + // This is the symbol used in 'throw' and 'if_except' instruction to denote + // this is a C++ exception. This symbol has to be emitted somewhere once in + // the module. Check if the symbol has already been created, i.e., we have at + // least one 'throw' or 'if_except' instruction in the module, and emit the + // symbol only if so. + SmallString<60> NameStr; + Mangler::getNameWithPrefix(NameStr, "__cpp_exception", Asm->getDataLayout()); + if (Asm->OutContext.lookupSymbol(NameStr)) { + MCSymbol *ExceptionSym = Asm->GetExternalSymbolSymbol("__cpp_exception"); + Asm->OutStreamer->EmitLabel(ExceptionSym); + } +} + +void WasmException::markFunctionEnd() { + // Get rid of any dead landing pads. + if (!Asm->MF->getLandingPads().empty()) { + auto *NonConstMF = const_cast<MachineFunction *>(Asm->MF); + // Wasm does not set BeginLabel and EndLabel information for landing pads, + // so we should set the second argument false. + NonConstMF->tidyLandingPads(nullptr, /* TidyIfNoBeginLabels */ false); + } +} + +void WasmException::endFunction(const MachineFunction *MF) { + bool ShouldEmitExceptionTable = false; + for (const LandingPadInfo &Info : MF->getLandingPads()) { + if (MF->hasWasmLandingPadIndex(Info.LandingPadBlock)) { + ShouldEmitExceptionTable = true; + break; + } + } + if (!ShouldEmitExceptionTable) + return; + MCSymbol *LSDALabel = emitExceptionTable(); + assert(LSDALabel && ".GCC_exception_table has not been emitted!"); + + // Wasm requires every data section symbol to have a .size set. So we emit an + // end marker and set the size as the difference between the start end the end + // marker. + MCSymbol *LSDAEndLabel = Asm->createTempSymbol("GCC_except_table_end"); + Asm->OutStreamer->EmitLabel(LSDAEndLabel); + MCContext &OutContext = Asm->OutStreamer->getContext(); + const MCExpr *SizeExp = MCBinaryExpr::createSub( + MCSymbolRefExpr::create(LSDAEndLabel, OutContext), + MCSymbolRefExpr::create(LSDALabel, OutContext), OutContext); + Asm->OutStreamer->emitELFSize(LSDALabel, SizeExp); +} + +// Compute the call-site table for wasm EH. Even though we use the same function +// name to share the common routines, a call site entry in the table corresponds +// to not a call site for possibly-throwing functions but a landing pad. In wasm +// EH the VM is responsible for stack unwinding. After an exception occurs and +// the stack is unwound, the control flow is transferred to wasm 'catch' +// instruction by the VM, after which the personality function is called from +// the compiler-generated code. Refer to WasmEHPrepare pass for more +// information. +void WasmException::computeCallSiteTable( + SmallVectorImpl<CallSiteEntry> &CallSites, + const SmallVectorImpl<const LandingPadInfo *> &LandingPads, + const SmallVectorImpl<unsigned> &FirstActions) { + MachineFunction &MF = *Asm->MF; + for (unsigned I = 0, N = LandingPads.size(); I < N; ++I) { + const LandingPadInfo *Info = LandingPads[I]; + MachineBasicBlock *LPad = Info->LandingPadBlock; + // We don't emit LSDA for single catch (...). + if (!MF.hasWasmLandingPadIndex(LPad)) + continue; + // Wasm EH must maintain the EH pads in the order assigned to them by the + // WasmEHPrepare pass. + unsigned LPadIndex = MF.getWasmLandingPadIndex(LPad); + CallSiteEntry Site = {nullptr, nullptr, Info, FirstActions[I]}; + if (CallSites.size() < LPadIndex + 1) + CallSites.resize(LPadIndex + 1); + CallSites[LPadIndex] = Site; + } +} diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/WasmException.h b/contrib/llvm/lib/CodeGen/AsmPrinter/WasmException.h new file mode 100644 index 000000000000..cbdb42457cf8 --- /dev/null +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/WasmException.h @@ -0,0 +1,42 @@ +//===-- WasmException.h - Wasm Exception Framework -------------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing WebAssembly exception info into asm +// files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_WASMEXCEPTION_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_WASMEXCEPTION_H + +#include "EHStreamer.h" +#include "llvm/CodeGen/AsmPrinter.h" + +namespace llvm { + +class LLVM_LIBRARY_VISIBILITY WasmException : public EHStreamer { +public: + WasmException(AsmPrinter *A) : EHStreamer(A) {} + + void endModule() override; + void beginFunction(const MachineFunction *MF) override {} + virtual void markFunctionEnd() override; + void endFunction(const MachineFunction *MF) override; + +protected: + // Compute the call site table for wasm EH. + void computeCallSiteTable( + SmallVectorImpl<CallSiteEntry> &CallSites, + const SmallVectorImpl<const LandingPadInfo *> &LandingPads, + const SmallVectorImpl<unsigned> &FirstActions) override; +}; + +} // End of namespace llvm + +#endif diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h b/contrib/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h index 124e8f04bfad..28f119e35966 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h @@ -14,7 +14,7 @@ #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_WINCFGUARD_H #define LLVM_LIB_CODEGEN_ASMPRINTER_WINCFGUARD_H -#include "AsmPrinterHandler.h" +#include "llvm/CodeGen/AsmPrinterHandler.h" #include "llvm/Support/Compiler.h" namespace llvm { diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.cpp index eff73a58d8d2..cf8e8c69bc2a 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.cpp +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.cpp @@ -42,6 +42,7 @@ WinException::WinException(AsmPrinter *A) : EHStreamer(A) { // MSVC's EH tables are always composed of 32-bit words. All known 64-bit // platforms use an imagerel32 relocation to refer to symbols. useImageRel32 = (A->getDataLayout().getPointerSizeInBits() == 64); + isAArch64 = Asm->TM.getTargetTriple().isAArch64(); } WinException::~WinException() {} @@ -242,6 +243,17 @@ void WinException::endFunclet() { if (F.hasPersonalityFn()) Per = classifyEHPersonality(F.getPersonalityFn()->stripPointerCasts()); + // On funclet exit, we emit a fake "function" end marker, so that the call + // to EmitWinEHHandlerData below can calculate the size of the funclet or + // function. + if (isAArch64) { + Asm->OutStreamer->SwitchSection(CurrentFuncletTextSection); + Asm->OutStreamer->EmitWinCFIFuncletOrFuncEnd(); + MCSection *XData = Asm->OutStreamer->getAssociatedXDataSection( + Asm->OutStreamer->getCurrentSectionOnly()); + Asm->OutStreamer->SwitchSection(XData); + } + // Emit an UNWIND_INFO struct describing the prologue. Asm->OutStreamer->EmitWinEHHandlerData(); @@ -286,7 +298,10 @@ const MCExpr *WinException::create32bitRef(const GlobalValue *GV) { return create32bitRef(Asm->getSymbol(GV)); } -const MCExpr *WinException::getLabelPlusOne(const MCSymbol *Label) { +const MCExpr *WinException::getLabel(const MCSymbol *Label) { + if (isAArch64) + return MCSymbolRefExpr::create(Label, MCSymbolRefExpr::VK_COFF_IMGREL32, + Asm->OutContext); return MCBinaryExpr::createAdd(create32bitRef(Label), MCConstantExpr::create(1, Asm->OutContext), Asm->OutContext); @@ -531,7 +546,7 @@ void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) { }; // Emit a label assignment with the SEH frame offset so we can use it for - // llvm.x86.seh.recoverfp. + // llvm.eh.recoverfp. StringRef FLinkageName = GlobalValue::dropLLVMManglingEscape(MF->getFunction().getName()); MCSymbol *ParentFrameOffset = @@ -588,7 +603,6 @@ void WinException::emitSEHActionsForRange(const WinEHFuncInfo &FuncInfo, const MCSymbol *EndLabel, int State) { auto &OS = *Asm->OutStreamer; MCContext &Ctx = Asm->OutContext; - bool VerboseAsm = OS.isVerboseAsm(); auto AddComment = [&](const Twine &Comment) { if (VerboseAsm) @@ -613,9 +627,9 @@ void WinException::emitSEHActionsForRange(const WinEHFuncInfo &FuncInfo, } AddComment("LabelStart"); - OS.EmitValue(getLabelPlusOne(BeginLabel), 4); + OS.EmitValue(getLabel(BeginLabel), 4); AddComment("LabelEnd"); - OS.EmitValue(getLabelPlusOne(EndLabel), 4); + OS.EmitValue(getLabel(EndLabel), 4); AddComment(UME.IsFinally ? "FinallyFunclet" : UME.Filter ? "FilterFunction" : "CatchAll"); OS.EmitValue(FilterOrFinally, 4); @@ -799,7 +813,7 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { // TypeDescriptor *Type; // int32_t CatchObjOffset; // void (*Handler)(); - // int32_t ParentFrameOffset; // x64 only + // int32_t ParentFrameOffset; // x64 and AArch64 only // }; OS.EmitLabel(HandlerMapXData); for (const WinEHHandlerType &HT : TBME.HandlerArray) { @@ -901,7 +915,7 @@ void WinException::computeIP2StateTable( ChangeLabel = StateChange.PreviousEndLabel; // Emit an entry indicating that PCs after 'Label' have this EH state. IPToStateTable.push_back( - std::make_pair(getLabelPlusOne(ChangeLabel), StateChange.NewState)); + std::make_pair(getLabel(ChangeLabel), StateChange.NewState)); // FIXME: assert that NewState is between CatchLow and CatchHigh. } } diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.h b/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.h index eed3c4453ffc..37c796f89765 100644 --- a/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.h +++ b/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.h @@ -38,6 +38,9 @@ class LLVM_LIBRARY_VISIBILITY WinException : public EHStreamer { /// True if this is a 64-bit target and we should use image relative offsets. bool useImageRel32 = false; + /// True if we are generating exception handling on Windows for ARM64. + bool isAArch64 = false; + /// Pointer to the current funclet entry BB. const MachineBasicBlock *CurrentFuncletEntry = nullptr; @@ -65,14 +68,14 @@ class LLVM_LIBRARY_VISIBILITY WinException : public EHStreamer { const MachineFunction *MF, const WinEHFuncInfo &FuncInfo, SmallVectorImpl<std::pair<const MCExpr *, int>> &IPToStateTable); - /// Emits the label used with llvm.x86.seh.recoverfp, which is used by + /// Emits the label used with llvm.eh.recoverfp, which is used by /// outlined funclets. void emitEHRegistrationOffsetLabel(const WinEHFuncInfo &FuncInfo, StringRef FLinkageName); const MCExpr *create32bitRef(const MCSymbol *Value); const MCExpr *create32bitRef(const GlobalValue *GV); - const MCExpr *getLabelPlusOne(const MCSymbol *Label); + const MCExpr *getLabel(const MCSymbol *Label); const MCExpr *getOffset(const MCSymbol *OffsetOf, const MCSymbol *OffsetFrom); const MCExpr *getOffsetPlusOne(const MCSymbol *OffsetOf, const MCSymbol *OffsetFrom); |
