summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/CodeGen/AsmPrinter
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/CodeGen/AsmPrinter')
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp141
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp45
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.h52
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp2626
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp290
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h67
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp573
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/ByteStreamer.h111
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp614
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp515
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DIEHash.h159
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp232
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h60
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h181
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.cpp46
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h193
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp289
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfAccelTable.h256
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp162
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp830
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h243
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp2018
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h617
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfException.h87
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp274
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h136
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp173
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h118
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp74
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h49
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp1553
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h403
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp689
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.h138
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp123
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp182
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp396
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h138
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/WinException.cpp1236
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/WinException.h106
40 files changed, 16195 insertions, 0 deletions
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp
new file mode 100644
index 0000000..ade2d71
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp
@@ -0,0 +1,141 @@
+//===-- CodeGen/AsmPrinter/ARMException.cpp - ARM EHABI 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 DWARF exception info into asm files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DwarfException.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Mangler.h"
+#include "llvm/IR/Module.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Target/TargetFrameLowering.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+using namespace llvm;
+
+ARMException::ARMException(AsmPrinter *A) : DwarfCFIExceptionBase(A) {}
+
+ARMException::~ARMException() {}
+
+ARMTargetStreamer &ARMException::getTargetStreamer() {
+ MCTargetStreamer &TS = *Asm->OutStreamer->getTargetStreamer();
+ return static_cast<ARMTargetStreamer &>(TS);
+}
+
+/// endModule - Emit all exception information that should come after the
+/// content.
+void ARMException::endModule() {
+ if (shouldEmitCFI)
+ Asm->OutStreamer->EmitCFISections(false, true);
+}
+
+void ARMException::beginFunction(const MachineFunction *MF) {
+ if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM)
+ getTargetStreamer().emitFnStart();
+ // See if we need call frame info.
+ AsmPrinter::CFIMoveType MoveType = Asm->needsCFIMoves();
+ assert(MoveType != AsmPrinter::CFI_M_EH &&
+ "non-EH CFI not yet supported in prologue with EHABI lowering");
+ if (MoveType == AsmPrinter::CFI_M_Debug) {
+ shouldEmitCFI = true;
+ Asm->OutStreamer->EmitCFIStartProc(false);
+ }
+}
+
+/// endFunction - Gather and emit post-function exception information.
+///
+void ARMException::endFunction(const MachineFunction *MF) {
+ ARMTargetStreamer &ATS = getTargetStreamer();
+ const Function *F = MF->getFunction();
+ const Function *Per = nullptr;
+ if (F->hasPersonalityFn())
+ Per = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
+ bool forceEmitPersonality =
+ F->hasPersonalityFn() && !isNoOpWithoutInvoke(classifyEHPersonality(Per)) &&
+ F->needsUnwindTableEntry();
+ bool shouldEmitPersonality = forceEmitPersonality ||
+ !MMI->getLandingPads().empty();
+ if (!Asm->MF->getFunction()->needsUnwindTableEntry() &&
+ !shouldEmitPersonality)
+ ATS.emitCantUnwind();
+ else if (shouldEmitPersonality) {
+ // Emit references to personality.
+ if (Per) {
+ MCSymbol *PerSym = Asm->getSymbol(Per);
+ Asm->OutStreamer->EmitSymbolAttribute(PerSym, MCSA_Global);
+ ATS.emitPersonality(PerSym);
+ }
+
+ // Emit .handlerdata directive.
+ ATS.emitHandlerData();
+
+ // Emit actual exception table
+ emitExceptionTable();
+ }
+
+ if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM)
+ ATS.emitFnEnd();
+}
+
+void ARMException::emitTypeInfos(unsigned TTypeEncoding) {
+ const std::vector<const GlobalValue *> &TypeInfos = MMI->getTypeInfos();
+ const std::vector<unsigned> &FilterIds = MMI->getFilterIds();
+
+ bool VerboseAsm = Asm->OutStreamer->isVerboseAsm();
+
+ int Entry = 0;
+ // Emit the Catch TypeInfos.
+ if (VerboseAsm && !TypeInfos.empty()) {
+ Asm->OutStreamer->AddComment(">> Catch TypeInfos <<");
+ Asm->OutStreamer->AddBlankLine();
+ Entry = TypeInfos.size();
+ }
+
+ for (const GlobalValue *GV : reverse(TypeInfos)) {
+ if (VerboseAsm)
+ Asm->OutStreamer->AddComment("TypeInfo " + Twine(Entry--));
+ Asm->EmitTTypeReference(GV, TTypeEncoding);
+ }
+
+ // Emit the Exception Specifications.
+ if (VerboseAsm && !FilterIds.empty()) {
+ Asm->OutStreamer->AddComment(">> Filter TypeInfos <<");
+ Asm->OutStreamer->AddBlankLine();
+ Entry = 0;
+ }
+ for (std::vector<unsigned>::const_iterator
+ I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) {
+ unsigned TypeID = *I;
+ if (VerboseAsm) {
+ --Entry;
+ if (TypeID != 0)
+ Asm->OutStreamer->AddComment("FilterInfo " + Twine(Entry));
+ }
+
+ Asm->EmitTTypeReference((TypeID == 0 ? nullptr : TypeInfos[TypeID - 1]),
+ TTypeEncoding);
+ }
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp
new file mode 100644
index 0000000..8c68383
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp
@@ -0,0 +1,45 @@
+//===-- llvm/CodeGen/AddressPool.cpp - Dwarf Debug Framework ---*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AddressPool.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+
+using namespace llvm;
+
+class MCExpr;
+
+unsigned AddressPool::getIndex(const MCSymbol *Sym, bool TLS) {
+ HasBeenUsed = true;
+ auto IterBool =
+ Pool.insert(std::make_pair(Sym, AddressPoolEntry(Pool.size(), TLS)));
+ return IterBool.first->second.Number;
+}
+
+// Emit addresses into the section given.
+void AddressPool::emit(AsmPrinter &Asm, MCSection *AddrSection) {
+ if (Pool.empty())
+ return;
+
+ // Start the dwarf addr section.
+ Asm.OutStreamer->SwitchSection(AddrSection);
+
+ // Order the address pool entries by ID
+ SmallVector<const MCExpr *, 64> Entries(Pool.size());
+
+ for (const auto &I : Pool)
+ Entries[I.second.Number] =
+ I.second.TLS
+ ? Asm.getObjFileLowering().getDebugThreadLocalSymbol(I.first)
+ : MCSymbolRefExpr::create(I.first, Asm.OutContext);
+
+ for (const MCExpr *Entry : Entries)
+ Asm.OutStreamer->EmitValue(Entry, Asm.getDataLayout().getPointerSize());
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.h b/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.h
new file mode 100644
index 0000000..211fc98
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.h
@@ -0,0 +1,52 @@
+//===-- llvm/CodeGen/AddressPool.h - Dwarf Debug Framework -----*- 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_ADDRESSPOOL_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_ADDRESSPOOL_H
+
+#include "llvm/ADT/DenseMap.h"
+
+namespace llvm {
+class MCSection;
+class MCSymbol;
+class AsmPrinter;
+// Collection of addresses for this unit and assorted labels.
+// A Symbol->unsigned mapping of addresses used by indirect
+// references.
+class AddressPool {
+ struct AddressPoolEntry {
+ unsigned Number;
+ bool TLS;
+ AddressPoolEntry(unsigned Number, bool TLS) : Number(Number), TLS(TLS) {}
+ };
+ DenseMap<const MCSymbol *, AddressPoolEntry> Pool;
+
+ /// Record whether the AddressPool has been queried for an address index since
+ /// the last "resetUsedFlag" call. Used to implement type unit fallback - a
+ /// type that references addresses cannot be placed in a type unit when using
+ /// fission.
+ bool HasBeenUsed;
+
+public:
+ AddressPool() : HasBeenUsed(false) {}
+
+ /// \brief Returns the index into the address pool with the given
+ /// label/symbol.
+ unsigned getIndex(const MCSymbol *Sym, bool TLS = false);
+
+ void emit(AsmPrinter &Asm, MCSection *AddrSection);
+
+ bool isEmpty() { return Pool.empty(); }
+
+ bool hasBeenUsed() const { return HasBeenUsed; }
+
+ void resetUsedFlag() { HasBeenUsed = false; }
+};
+}
+#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
new file mode 100644
index 0000000..be7eafb
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -0,0 +1,2626 @@
+//===-- AsmPrinter.cpp - Common AsmPrinter code ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the AsmPrinter class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "DwarfDebug.h"
+#include "DwarfException.h"
+#include "WinException.h"
+#include "WinCodeViewLineTables.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Analysis/ConstantFolding.h"
+#include "llvm/CodeGen/Analysis.h"
+#include "llvm/CodeGen/GCMetadataPrinter.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBundle.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/CodeGen/MachineLoopInfo.h"
+#include "llvm/CodeGen/MachineModuleInfoImpls.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/Mangler.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Operator.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbolELF.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Target/TargetFrameLowering.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetLowering.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+using namespace llvm;
+
+#define DEBUG_TYPE "asm-printer"
+
+static const char *const DWARFGroupName = "DWARF Emission";
+static const char *const DbgTimerName = "Debug Info Emission";
+static const char *const EHTimerName = "DWARF Exception Writer";
+static const char *const CodeViewLineTablesGroupName = "CodeView Line Tables";
+
+STATISTIC(EmittedInsts, "Number of machine instrs printed");
+
+char AsmPrinter::ID = 0;
+
+typedef DenseMap<GCStrategy*, std::unique_ptr<GCMetadataPrinter>> gcp_map_type;
+static gcp_map_type &getGCMap(void *&P) {
+ if (!P)
+ P = new gcp_map_type();
+ return *(gcp_map_type*)P;
+}
+
+
+/// getGVAlignmentLog2 - Return the alignment to use for the specified global
+/// value in log2 form. This rounds up to the preferred alignment if possible
+/// and legal.
+static unsigned getGVAlignmentLog2(const GlobalValue *GV, const DataLayout &DL,
+ unsigned InBits = 0) {
+ unsigned NumBits = 0;
+ if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV))
+ NumBits = DL.getPreferredAlignmentLog(GVar);
+
+ // If InBits is specified, round it to it.
+ if (InBits > NumBits)
+ NumBits = InBits;
+
+ // If the GV has a specified alignment, take it into account.
+ if (GV->getAlignment() == 0)
+ return NumBits;
+
+ unsigned GVAlign = Log2_32(GV->getAlignment());
+
+ // If the GVAlign is larger than NumBits, or if we are required to obey
+ // NumBits because the GV has an assigned section, obey it.
+ if (GVAlign > NumBits || GV->hasSection())
+ NumBits = GVAlign;
+ return NumBits;
+}
+
+AsmPrinter::AsmPrinter(TargetMachine &tm, std::unique_ptr<MCStreamer> Streamer)
+ : MachineFunctionPass(ID), TM(tm), MAI(tm.getMCAsmInfo()),
+ OutContext(Streamer->getContext()), OutStreamer(std::move(Streamer)),
+ LastMI(nullptr), LastFn(0), Counter(~0U) {
+ DD = nullptr;
+ MMI = nullptr;
+ LI = nullptr;
+ MF = nullptr;
+ CurExceptionSym = CurrentFnSym = CurrentFnSymForSize = nullptr;
+ CurrentFnBegin = nullptr;
+ CurrentFnEnd = nullptr;
+ GCMetadataPrinters = nullptr;
+ VerboseAsm = OutStreamer->isVerboseAsm();
+}
+
+AsmPrinter::~AsmPrinter() {
+ assert(!DD && Handlers.empty() && "Debug/EH info didn't get finalized");
+
+ if (GCMetadataPrinters) {
+ gcp_map_type &GCMap = getGCMap(GCMetadataPrinters);
+
+ delete &GCMap;
+ GCMetadataPrinters = nullptr;
+ }
+}
+
+/// getFunctionNumber - Return a unique ID for the current function.
+///
+unsigned AsmPrinter::getFunctionNumber() const {
+ return MF->getFunctionNumber();
+}
+
+const TargetLoweringObjectFile &AsmPrinter::getObjFileLowering() const {
+ return *TM.getObjFileLowering();
+}
+
+const DataLayout &AsmPrinter::getDataLayout() const {
+ return MMI->getModule()->getDataLayout();
+}
+
+// Do not use the cached DataLayout because some client use it without a Module
+// (llmv-dsymutil, llvm-dwarfdump).
+unsigned AsmPrinter::getPointerSize() const { return TM.getPointerSize(); }
+
+const MCSubtargetInfo &AsmPrinter::getSubtargetInfo() const {
+ assert(MF && "getSubtargetInfo requires a valid MachineFunction!");
+ return MF->getSubtarget<MCSubtargetInfo>();
+}
+
+void AsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
+ S.EmitInstruction(Inst, getSubtargetInfo());
+}
+
+StringRef AsmPrinter::getTargetTriple() const {
+ return TM.getTargetTriple().str();
+}
+
+/// getCurrentSection() - Return the current section we are emitting to.
+const MCSection *AsmPrinter::getCurrentSection() const {
+ return OutStreamer->getCurrentSection().first;
+}
+
+
+
+void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ AU.addRequired<MachineModuleInfo>();
+ AU.addRequired<GCModuleInfo>();
+ if (isVerbose())
+ AU.addRequired<MachineLoopInfo>();
+}
+
+bool AsmPrinter::doInitialization(Module &M) {
+ MMI = getAnalysisIfAvailable<MachineModuleInfo>();
+
+ // Initialize TargetLoweringObjectFile.
+ const_cast<TargetLoweringObjectFile&>(getObjFileLowering())
+ .Initialize(OutContext, TM);
+
+ OutStreamer->InitSections(false);
+
+ Mang = new Mangler();
+
+ // Emit the version-min deplyment target directive if needed.
+ //
+ // FIXME: If we end up with a collection of these sorts of Darwin-specific
+ // or ELF-specific things, it may make sense to have a platform helper class
+ // that will work with the target helper class. For now keep it here, as the
+ // alternative is duplicated code in each of the target asm printers that
+ // use the directive, where it would need the same conditionalization
+ // anyway.
+ Triple TT(getTargetTriple());
+ if (TT.isOSDarwin()) {
+ unsigned Major, Minor, Update;
+ TT.getOSVersion(Major, Minor, Update);
+ // If there is a version specified, Major will be non-zero.
+ if (Major) {
+ MCVersionMinType VersionType;
+ if (TT.isWatchOS())
+ VersionType = MCVM_WatchOSVersionMin;
+ else if (TT.isTvOS())
+ VersionType = MCVM_TvOSVersionMin;
+ else if (TT.isMacOSX())
+ VersionType = MCVM_OSXVersionMin;
+ else
+ VersionType = MCVM_IOSVersionMin;
+ OutStreamer->EmitVersionMin(VersionType, Major, Minor, Update);
+ }
+ }
+
+ // Allow the target to emit any magic that it wants at the start of the file.
+ EmitStartOfAsmFile(M);
+
+ // Very minimal debug info. It is ignored if we emit actual debug info. If we
+ // don't, this at least helps the user find where a global came from.
+ if (MAI->hasSingleParameterDotFile()) {
+ // .file "foo.c"
+ OutStreamer->EmitFileDirective(M.getModuleIdentifier());
+ }
+
+ GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
+ assert(MI && "AsmPrinter didn't require GCModuleInfo?");
+ for (auto &I : *MI)
+ if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*I))
+ MP->beginAssembly(M, *MI, *this);
+
+ // Emit module-level inline asm if it exists.
+ if (!M.getModuleInlineAsm().empty()) {
+ // We're at the module level. Construct MCSubtarget from the default CPU
+ // and target triple.
+ std::unique_ptr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo(
+ TM.getTargetTriple().str(), TM.getTargetCPU(),
+ TM.getTargetFeatureString()));
+ OutStreamer->AddComment("Start of file scope inline assembly");
+ OutStreamer->AddBlankLine();
+ EmitInlineAsm(M.getModuleInlineAsm()+"\n",
+ OutContext.getSubtargetCopy(*STI), TM.Options.MCOptions);
+ OutStreamer->AddComment("End of file scope inline assembly");
+ OutStreamer->AddBlankLine();
+ }
+
+ if (MAI->doesSupportDebugInformation()) {
+ bool EmitCodeView = MMI->getModule()->getCodeViewFlag();
+ if (EmitCodeView && TM.getTargetTriple().isKnownWindowsMSVCEnvironment()) {
+ Handlers.push_back(HandlerInfo(new WinCodeViewLineTables(this),
+ DbgTimerName,
+ CodeViewLineTablesGroupName));
+ }
+ if (!EmitCodeView || MMI->getModule()->getDwarfVersion()) {
+ DD = new DwarfDebug(this, &M);
+ Handlers.push_back(HandlerInfo(DD, DbgTimerName, DWARFGroupName));
+ }
+ }
+
+ EHStreamer *ES = nullptr;
+ switch (MAI->getExceptionHandlingType()) {
+ case ExceptionHandling::None:
+ break;
+ case ExceptionHandling::SjLj:
+ case ExceptionHandling::DwarfCFI:
+ ES = new DwarfCFIException(this);
+ break;
+ case ExceptionHandling::ARM:
+ ES = new ARMException(this);
+ break;
+ case ExceptionHandling::WinEH:
+ switch (MAI->getWinEHEncodingType()) {
+ default: llvm_unreachable("unsupported unwinding information encoding");
+ case WinEH::EncodingType::Invalid:
+ break;
+ case WinEH::EncodingType::X86:
+ case WinEH::EncodingType::Itanium:
+ ES = new WinException(this);
+ break;
+ }
+ break;
+ }
+ if (ES)
+ Handlers.push_back(HandlerInfo(ES, EHTimerName, DWARFGroupName));
+ return false;
+}
+
+static bool canBeHidden(const GlobalValue *GV, const MCAsmInfo &MAI) {
+ if (!MAI.hasWeakDefCanBeHiddenDirective())
+ return false;
+
+ return canBeOmittedFromSymbolTable(GV);
+}
+
+void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const {
+ GlobalValue::LinkageTypes Linkage = GV->getLinkage();
+ switch (Linkage) {
+ case GlobalValue::CommonLinkage:
+ case GlobalValue::LinkOnceAnyLinkage:
+ case GlobalValue::LinkOnceODRLinkage:
+ case GlobalValue::WeakAnyLinkage:
+ case GlobalValue::WeakODRLinkage:
+ if (MAI->hasWeakDefDirective()) {
+ // .globl _foo
+ OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Global);
+
+ if (!canBeHidden(GV, *MAI))
+ // .weak_definition _foo
+ OutStreamer->EmitSymbolAttribute(GVSym, MCSA_WeakDefinition);
+ else
+ OutStreamer->EmitSymbolAttribute(GVSym, MCSA_WeakDefAutoPrivate);
+ } else if (MAI->hasLinkOnceDirective()) {
+ // .globl _foo
+ OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Global);
+ //NOTE: linkonce is handled by the section the symbol was assigned to.
+ } else {
+ // .weak _foo
+ OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Weak);
+ }
+ return;
+ case GlobalValue::AppendingLinkage:
+ // FIXME: appending linkage variables should go into a section of
+ // their name or something. For now, just emit them as external.
+ case GlobalValue::ExternalLinkage:
+ // If external or appending, declare as a global symbol.
+ // .globl _foo
+ OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Global);
+ return;
+ case GlobalValue::PrivateLinkage:
+ case GlobalValue::InternalLinkage:
+ return;
+ case GlobalValue::AvailableExternallyLinkage:
+ llvm_unreachable("Should never emit this");
+ case GlobalValue::ExternalWeakLinkage:
+ llvm_unreachable("Don't know how to emit these");
+ }
+ llvm_unreachable("Unknown linkage type!");
+}
+
+void AsmPrinter::getNameWithPrefix(SmallVectorImpl<char> &Name,
+ const GlobalValue *GV) const {
+ TM.getNameWithPrefix(Name, GV, *Mang);
+}
+
+MCSymbol *AsmPrinter::getSymbol(const GlobalValue *GV) const {
+ return TM.getSymbol(GV, *Mang);
+}
+
+static MCSymbol *getOrCreateEmuTLSControlSym(MCSymbol *GVSym, MCContext &C) {
+ return C.getOrCreateSymbol(Twine("__emutls_v.") + GVSym->getName());
+}
+
+static MCSymbol *getOrCreateEmuTLSInitSym(MCSymbol *GVSym, MCContext &C) {
+ return C.getOrCreateSymbol(Twine("__emutls_t.") + GVSym->getName());
+}
+
+/// EmitEmulatedTLSControlVariable - Emit the control variable for an emulated TLS variable.
+void AsmPrinter::EmitEmulatedTLSControlVariable(const GlobalVariable *GV,
+ MCSymbol *EmittedSym,
+ bool AllZeroInitValue) {
+ MCSection *TLSVarSection = getObjFileLowering().getDataSection();
+ OutStreamer->SwitchSection(TLSVarSection);
+ MCSymbol *GVSym = getSymbol(GV);
+ EmitLinkage(GV, EmittedSym); // same linkage as GV
+ const DataLayout &DL = GV->getParent()->getDataLayout();
+ uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType());
+ unsigned AlignLog = getGVAlignmentLog2(GV, DL);
+ unsigned WordSize = DL.getPointerSize();
+ unsigned Alignment = DL.getPointerABIAlignment();
+ EmitAlignment(Log2_32(Alignment));
+ OutStreamer->EmitLabel(EmittedSym);
+ OutStreamer->EmitIntValue(Size, WordSize);
+ OutStreamer->EmitIntValue((1 << AlignLog), WordSize);
+ OutStreamer->EmitIntValue(0, WordSize);
+ if (GV->hasInitializer() && !AllZeroInitValue) {
+ OutStreamer->EmitSymbolValue(
+ getOrCreateEmuTLSInitSym(GVSym, OutContext), WordSize);
+ } else
+ OutStreamer->EmitIntValue(0, WordSize);
+ if (MAI->hasDotTypeDotSizeDirective())
+ OutStreamer->emitELFSize(cast<MCSymbolELF>(EmittedSym),
+ MCConstantExpr::create(4 * WordSize, OutContext));
+ OutStreamer->AddBlankLine(); // End of the __emutls_v.* variable.
+}
+
+/// EmitGlobalVariable - Emit the specified global variable to the .s file.
+void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
+ bool IsEmuTLSVar =
+ GV->getThreadLocalMode() != llvm::GlobalVariable::NotThreadLocal &&
+ TM.Options.EmulatedTLS;
+ assert(!(IsEmuTLSVar && GV->hasCommonLinkage()) &&
+ "No emulated TLS variables in the common section");
+
+ if (GV->hasInitializer()) {
+ // Check to see if this is a special global used by LLVM, if so, emit it.
+ if (EmitSpecialLLVMGlobal(GV))
+ return;
+
+ // Skip the emission of global equivalents. The symbol can be emitted later
+ // on by emitGlobalGOTEquivs in case it turns out to be needed.
+ if (GlobalGOTEquivs.count(getSymbol(GV)))
+ return;
+
+ if (isVerbose() && !IsEmuTLSVar) {
+ // When printing the control variable __emutls_v.*,
+ // we don't need to print the original TLS variable name.
+ GV->printAsOperand(OutStreamer->GetCommentOS(),
+ /*PrintType=*/false, GV->getParent());
+ OutStreamer->GetCommentOS() << '\n';
+ }
+ }
+
+ MCSymbol *GVSym = getSymbol(GV);
+ MCSymbol *EmittedSym = IsEmuTLSVar ?
+ getOrCreateEmuTLSControlSym(GVSym, OutContext) : GVSym;
+ // getOrCreateEmuTLSControlSym only creates the symbol with name and default attributes.
+ // GV's or GVSym's attributes will be used for the EmittedSym.
+
+ EmitVisibility(EmittedSym, GV->getVisibility(), !GV->isDeclaration());
+
+ if (!GV->hasInitializer()) // External globals require no extra code.
+ return;
+
+ GVSym->redefineIfPossible();
+ if (GVSym->isDefined() || GVSym->isVariable())
+ report_fatal_error("symbol '" + Twine(GVSym->getName()) +
+ "' is already defined");
+
+ if (MAI->hasDotTypeDotSizeDirective())
+ OutStreamer->EmitSymbolAttribute(EmittedSym, MCSA_ELF_TypeObject);
+
+ SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM);
+
+ const DataLayout &DL = GV->getParent()->getDataLayout();
+ uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType());
+
+ // If the alignment is specified, we *must* obey it. Overaligning a global
+ // with a specified alignment is a prompt way to break globals emitted to
+ // sections and expected to be contiguous (e.g. ObjC metadata).
+ unsigned AlignLog = getGVAlignmentLog2(GV, DL);
+
+ bool AllZeroInitValue = false;
+ const Constant *InitValue = GV->getInitializer();
+ if (isa<ConstantAggregateZero>(InitValue))
+ AllZeroInitValue = true;
+ else {
+ const ConstantInt *InitIntValue = dyn_cast<ConstantInt>(InitValue);
+ if (InitIntValue && InitIntValue->isZero())
+ AllZeroInitValue = true;
+ }
+ if (IsEmuTLSVar)
+ EmitEmulatedTLSControlVariable(GV, EmittedSym, AllZeroInitValue);
+
+ for (const HandlerInfo &HI : Handlers) {
+ NamedRegionTimer T(HI.TimerName, HI.TimerGroupName, TimePassesIsEnabled);
+ HI.Handler->setSymbolSize(GVSym, Size);
+ }
+
+ // Handle common and BSS local symbols (.lcomm).
+ if (GVKind.isCommon() || GVKind.isBSSLocal()) {
+ assert(!(IsEmuTLSVar && GVKind.isCommon()) &&
+ "No emulated TLS variables in the common section");
+ if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
+ unsigned Align = 1 << AlignLog;
+
+ // Handle common symbols.
+ if (GVKind.isCommon()) {
+ if (!getObjFileLowering().getCommDirectiveSupportsAlignment())
+ Align = 0;
+
+ // .comm _foo, 42, 4
+ OutStreamer->EmitCommonSymbol(GVSym, Size, Align);
+ return;
+ }
+
+ // Handle local BSS symbols.
+ if (MAI->hasMachoZeroFillDirective()) {
+ MCSection *TheSection =
+ getObjFileLowering().SectionForGlobal(GV, GVKind, *Mang, TM);
+ // .zerofill __DATA, __bss, _foo, 400, 5
+ OutStreamer->EmitZerofill(TheSection, GVSym, Size, Align);
+ return;
+ }
+
+ // Use .lcomm only if it supports user-specified alignment.
+ // Otherwise, while it would still be correct to use .lcomm in some
+ // cases (e.g. when Align == 1), the external assembler might enfore
+ // some -unknown- default alignment behavior, which could cause
+ // spurious differences between external and integrated assembler.
+ // Prefer to simply fall back to .local / .comm in this case.
+ if (MAI->getLCOMMDirectiveAlignmentType() != LCOMM::NoAlignment) {
+ // .lcomm _foo, 42
+ OutStreamer->EmitLocalCommonSymbol(GVSym, Size, Align);
+ return;
+ }
+
+ if (!getObjFileLowering().getCommDirectiveSupportsAlignment())
+ Align = 0;
+
+ // .local _foo
+ OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Local);
+ // .comm _foo, 42, 4
+ OutStreamer->EmitCommonSymbol(GVSym, Size, Align);
+ return;
+ }
+
+ if (IsEmuTLSVar && AllZeroInitValue)
+ return; // No need of initialization values.
+
+ MCSymbol *EmittedInitSym = IsEmuTLSVar ?
+ getOrCreateEmuTLSInitSym(GVSym, OutContext) : GVSym;
+ // getOrCreateEmuTLSInitSym only creates the symbol with name and default attributes.
+ // GV's or GVSym's attributes will be used for the EmittedInitSym.
+
+ MCSection *TheSection = IsEmuTLSVar ?
+ getObjFileLowering().getReadOnlySection() :
+ getObjFileLowering().SectionForGlobal(GV, GVKind, *Mang, TM);
+
+ // Handle the zerofill directive on darwin, which is a special form of BSS
+ // emission.
+ if (GVKind.isBSSExtern() && MAI->hasMachoZeroFillDirective() && !IsEmuTLSVar) {
+ if (Size == 0) Size = 1; // zerofill of 0 bytes is undefined.
+
+ // .globl _foo
+ OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Global);
+ // .zerofill __DATA, __common, _foo, 400, 5
+ OutStreamer->EmitZerofill(TheSection, GVSym, Size, 1 << AlignLog);
+ return;
+ }
+
+ // Handle thread local data for mach-o which requires us to output an
+ // additional structure of data and mangle the original symbol so that we
+ // can reference it later.
+ //
+ // TODO: This should become an "emit thread local global" method on TLOF.
+ // All of this macho specific stuff should be sunk down into TLOFMachO and
+ // stuff like "TLSExtraDataSection" should no longer be part of the parent
+ // TLOF class. This will also make it more obvious that stuff like
+ // MCStreamer::EmitTBSSSymbol is macho specific and only called from macho
+ // specific code.
+ if (GVKind.isThreadLocal() && MAI->hasMachoTBSSDirective() && !IsEmuTLSVar) {
+ // Emit the .tbss symbol
+ MCSymbol *MangSym =
+ OutContext.getOrCreateSymbol(GVSym->getName() + Twine("$tlv$init"));
+
+ if (GVKind.isThreadBSS()) {
+ TheSection = getObjFileLowering().getTLSBSSSection();
+ OutStreamer->EmitTBSSSymbol(TheSection, MangSym, Size, 1 << AlignLog);
+ } else if (GVKind.isThreadData()) {
+ OutStreamer->SwitchSection(TheSection);
+
+ EmitAlignment(AlignLog, GV);
+ OutStreamer->EmitLabel(MangSym);
+
+ EmitGlobalConstant(GV->getParent()->getDataLayout(),
+ GV->getInitializer());
+ }
+
+ OutStreamer->AddBlankLine();
+
+ // Emit the variable struct for the runtime.
+ MCSection *TLVSect = getObjFileLowering().getTLSExtraDataSection();
+
+ OutStreamer->SwitchSection(TLVSect);
+ // Emit the linkage here.
+ EmitLinkage(GV, GVSym);
+ OutStreamer->EmitLabel(GVSym);
+
+ // Three pointers in size:
+ // - __tlv_bootstrap - used to make sure support exists
+ // - spare pointer, used when mapped by the runtime
+ // - pointer to mangled symbol above with initializer
+ unsigned PtrSize = DL.getPointerTypeSize(GV->getType());
+ OutStreamer->EmitSymbolValue(GetExternalSymbolSymbol("_tlv_bootstrap"),
+ PtrSize);
+ OutStreamer->EmitIntValue(0, PtrSize);
+ OutStreamer->EmitSymbolValue(MangSym, PtrSize);
+
+ OutStreamer->AddBlankLine();
+ return;
+ }
+
+ OutStreamer->SwitchSection(TheSection);
+
+ // emutls_t.* symbols are only used in the current compilation unit.
+ if (!IsEmuTLSVar)
+ EmitLinkage(GV, EmittedInitSym);
+ EmitAlignment(AlignLog, GV);
+
+ OutStreamer->EmitLabel(EmittedInitSym);
+
+ EmitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer());
+
+ if (MAI->hasDotTypeDotSizeDirective())
+ // .size foo, 42
+ OutStreamer->emitELFSize(cast<MCSymbolELF>(EmittedInitSym),
+ MCConstantExpr::create(Size, OutContext));
+
+ OutStreamer->AddBlankLine();
+}
+
+/// EmitFunctionHeader - This method emits the header for the current
+/// function.
+void AsmPrinter::EmitFunctionHeader() {
+ // Print out constants referenced by the function
+ EmitConstantPool();
+
+ // Print the 'header' of function.
+ const Function *F = MF->getFunction();
+
+ OutStreamer->SwitchSection(
+ getObjFileLowering().SectionForGlobal(F, *Mang, TM));
+ EmitVisibility(CurrentFnSym, F->getVisibility());
+
+ EmitLinkage(F, CurrentFnSym);
+ if (MAI->hasFunctionAlignment())
+ EmitAlignment(MF->getAlignment(), F);
+
+ if (MAI->hasDotTypeDotSizeDirective())
+ OutStreamer->EmitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction);
+
+ if (isVerbose()) {
+ F->printAsOperand(OutStreamer->GetCommentOS(),
+ /*PrintType=*/false, F->getParent());
+ OutStreamer->GetCommentOS() << '\n';
+ }
+
+ // Emit the prefix data.
+ if (F->hasPrefixData())
+ EmitGlobalConstant(F->getParent()->getDataLayout(), F->getPrefixData());
+
+ // Emit the CurrentFnSym. This is a virtual function to allow targets to
+ // do their wild and crazy things as required.
+ EmitFunctionEntryLabel();
+
+ // If the function had address-taken blocks that got deleted, then we have
+ // references to the dangling symbols. Emit them at the start of the function
+ // so that we don't get references to undefined symbols.
+ std::vector<MCSymbol*> DeadBlockSyms;
+ MMI->takeDeletedSymbolsForFunction(F, DeadBlockSyms);
+ for (unsigned i = 0, e = DeadBlockSyms.size(); i != e; ++i) {
+ OutStreamer->AddComment("Address taken block that was later removed");
+ OutStreamer->EmitLabel(DeadBlockSyms[i]);
+ }
+
+ if (CurrentFnBegin) {
+ if (MAI->useAssignmentForEHBegin()) {
+ MCSymbol *CurPos = OutContext.createTempSymbol();
+ OutStreamer->EmitLabel(CurPos);
+ OutStreamer->EmitAssignment(CurrentFnBegin,
+ MCSymbolRefExpr::create(CurPos, OutContext));
+ } else {
+ OutStreamer->EmitLabel(CurrentFnBegin);
+ }
+ }
+
+ // Emit pre-function debug and/or EH information.
+ for (const HandlerInfo &HI : Handlers) {
+ NamedRegionTimer T(HI.TimerName, HI.TimerGroupName, TimePassesIsEnabled);
+ HI.Handler->beginFunction(MF);
+ }
+
+ // Emit the prologue data.
+ if (F->hasPrologueData())
+ EmitGlobalConstant(F->getParent()->getDataLayout(), F->getPrologueData());
+}
+
+/// EmitFunctionEntryLabel - Emit the label that is the entrypoint for the
+/// function. This can be overridden by targets as required to do custom stuff.
+void AsmPrinter::EmitFunctionEntryLabel() {
+ CurrentFnSym->redefineIfPossible();
+
+ // The function label could have already been emitted if two symbols end up
+ // conflicting due to asm renaming. Detect this and emit an error.
+ if (CurrentFnSym->isVariable())
+ report_fatal_error("'" + Twine(CurrentFnSym->getName()) +
+ "' is a protected alias");
+ if (CurrentFnSym->isDefined())
+ report_fatal_error("'" + Twine(CurrentFnSym->getName()) +
+ "' label emitted multiple times to assembly file");
+
+ return OutStreamer->EmitLabel(CurrentFnSym);
+}
+
+/// emitComments - Pretty-print comments for instructions.
+static void emitComments(const MachineInstr &MI, raw_ostream &CommentOS) {
+ const MachineFunction *MF = MI.getParent()->getParent();
+ const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
+
+ // Check for spills and reloads
+ int FI;
+
+ const MachineFrameInfo *FrameInfo = MF->getFrameInfo();
+
+ // We assume a single instruction only has a spill or reload, not
+ // both.
+ const MachineMemOperand *MMO;
+ if (TII->isLoadFromStackSlotPostFE(&MI, FI)) {
+ if (FrameInfo->isSpillSlotObjectIndex(FI)) {
+ MMO = *MI.memoperands_begin();
+ CommentOS << MMO->getSize() << "-byte Reload\n";
+ }
+ } else if (TII->hasLoadFromStackSlot(&MI, MMO, FI)) {
+ if (FrameInfo->isSpillSlotObjectIndex(FI))
+ CommentOS << MMO->getSize() << "-byte Folded Reload\n";
+ } else if (TII->isStoreToStackSlotPostFE(&MI, FI)) {
+ if (FrameInfo->isSpillSlotObjectIndex(FI)) {
+ MMO = *MI.memoperands_begin();
+ CommentOS << MMO->getSize() << "-byte Spill\n";
+ }
+ } else if (TII->hasStoreToStackSlot(&MI, MMO, FI)) {
+ if (FrameInfo->isSpillSlotObjectIndex(FI))
+ CommentOS << MMO->getSize() << "-byte Folded Spill\n";
+ }
+
+ // Check for spill-induced copies
+ if (MI.getAsmPrinterFlag(MachineInstr::ReloadReuse))
+ CommentOS << " Reload Reuse\n";
+}
+
+/// emitImplicitDef - This method emits the specified machine instruction
+/// that is an implicit def.
+void AsmPrinter::emitImplicitDef(const MachineInstr *MI) const {
+ unsigned RegNo = MI->getOperand(0).getReg();
+
+ SmallString<128> Str;
+ raw_svector_ostream OS(Str);
+ OS << "implicit-def: "
+ << PrintReg(RegNo, MF->getSubtarget().getRegisterInfo());
+
+ OutStreamer->AddComment(OS.str());
+ OutStreamer->AddBlankLine();
+}
+
+static void emitKill(const MachineInstr *MI, AsmPrinter &AP) {
+ std::string Str;
+ raw_string_ostream OS(Str);
+ OS << "kill:";
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ const MachineOperand &Op = MI->getOperand(i);
+ assert(Op.isReg() && "KILL instruction must have only register operands");
+ OS << ' '
+ << PrintReg(Op.getReg(),
+ AP.MF->getSubtarget().getRegisterInfo())
+ << (Op.isDef() ? "<def>" : "<kill>");
+ }
+ AP.OutStreamer->AddComment(Str);
+ AP.OutStreamer->AddBlankLine();
+}
+
+/// emitDebugValueComment - This method handles the target-independent form
+/// of DBG_VALUE, returning true if it was able to do so. A false return
+/// means the target will need to handle MI in EmitInstruction.
+static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
+ // This code handles only the 4-operand target-independent form.
+ if (MI->getNumOperands() != 4)
+ return false;
+
+ SmallString<128> Str;
+ raw_svector_ostream OS(Str);
+ OS << "DEBUG_VALUE: ";
+
+ const DILocalVariable *V = MI->getDebugVariable();
+ if (auto *SP = dyn_cast<DISubprogram>(V->getScope())) {
+ StringRef Name = SP->getDisplayName();
+ if (!Name.empty())
+ OS << Name << ":";
+ }
+ OS << V->getName();
+
+ const DIExpression *Expr = MI->getDebugExpression();
+ if (Expr->isBitPiece())
+ OS << " [bit_piece offset=" << Expr->getBitPieceOffset()
+ << " size=" << Expr->getBitPieceSize() << "]";
+ OS << " <- ";
+
+ // The second operand is only an offset if it's an immediate.
+ bool Deref = MI->getOperand(0).isReg() && MI->getOperand(1).isImm();
+ int64_t Offset = Deref ? MI->getOperand(1).getImm() : 0;
+
+ for (unsigned i = 0; i < Expr->getNumElements(); ++i) {
+ if (Deref) {
+ // We currently don't support extra Offsets or derefs after the first
+ // one. Bail out early instead of emitting an incorrect comment
+ OS << " [complex expression]";
+ AP.OutStreamer->emitRawComment(OS.str());
+ return true;
+ }
+ uint64_t Op = Expr->getElement(i);
+ if (Op == dwarf::DW_OP_deref) {
+ Deref = true;
+ continue;
+ } else if (Op == dwarf::DW_OP_bit_piece) {
+ // There can't be any operands after this in a valid expression
+ break;
+ }
+ uint64_t ExtraOffset = Expr->getElement(i++);
+ if (Op == dwarf::DW_OP_plus)
+ Offset += ExtraOffset;
+ else {
+ assert(Op == dwarf::DW_OP_minus);
+ Offset -= ExtraOffset;
+ }
+ }
+
+ // Register or immediate value. Register 0 means undef.
+ if (MI->getOperand(0).isFPImm()) {
+ APFloat APF = APFloat(MI->getOperand(0).getFPImm()->getValueAPF());
+ if (MI->getOperand(0).getFPImm()->getType()->isFloatTy()) {
+ OS << (double)APF.convertToFloat();
+ } else if (MI->getOperand(0).getFPImm()->getType()->isDoubleTy()) {
+ OS << APF.convertToDouble();
+ } else {
+ // There is no good way to print long double. Convert a copy to
+ // double. Ah well, it's only a comment.
+ bool ignored;
+ APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven,
+ &ignored);
+ OS << "(long double) " << APF.convertToDouble();
+ }
+ } else if (MI->getOperand(0).isImm()) {
+ OS << MI->getOperand(0).getImm();
+ } else if (MI->getOperand(0).isCImm()) {
+ MI->getOperand(0).getCImm()->getValue().print(OS, false /*isSigned*/);
+ } else {
+ unsigned Reg;
+ if (MI->getOperand(0).isReg()) {
+ Reg = MI->getOperand(0).getReg();
+ } else {
+ assert(MI->getOperand(0).isFI() && "Unknown operand type");
+ const TargetFrameLowering *TFI = AP.MF->getSubtarget().getFrameLowering();
+ Offset += TFI->getFrameIndexReference(*AP.MF,
+ MI->getOperand(0).getIndex(), Reg);
+ Deref = true;
+ }
+ if (Reg == 0) {
+ // Suppress offset, it is not meaningful here.
+ OS << "undef";
+ // NOTE: Want this comment at start of line, don't emit with AddComment.
+ AP.OutStreamer->emitRawComment(OS.str());
+ return true;
+ }
+ if (Deref)
+ OS << '[';
+ OS << PrintReg(Reg, AP.MF->getSubtarget().getRegisterInfo());
+ }
+
+ if (Deref)
+ OS << '+' << Offset << ']';
+
+ // NOTE: Want this comment at start of line, don't emit with AddComment.
+ AP.OutStreamer->emitRawComment(OS.str());
+ return true;
+}
+
+AsmPrinter::CFIMoveType AsmPrinter::needsCFIMoves() {
+ if (MAI->getExceptionHandlingType() == ExceptionHandling::DwarfCFI &&
+ MF->getFunction()->needsUnwindTableEntry())
+ return CFI_M_EH;
+
+ if (MMI->hasDebugInfo())
+ return CFI_M_Debug;
+
+ return CFI_M_None;
+}
+
+bool AsmPrinter::needsSEHMoves() {
+ return MAI->usesWindowsCFI() && MF->getFunction()->needsUnwindTableEntry();
+}
+
+void AsmPrinter::emitCFIInstruction(const MachineInstr &MI) {
+ ExceptionHandling ExceptionHandlingType = MAI->getExceptionHandlingType();
+ if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
+ ExceptionHandlingType != ExceptionHandling::ARM)
+ return;
+
+ if (needsCFIMoves() == CFI_M_None)
+ return;
+
+ const MachineModuleInfo &MMI = MF->getMMI();
+ const std::vector<MCCFIInstruction> &Instrs = MMI.getFrameInstructions();
+ unsigned CFIIndex = MI.getOperand(0).getCFIIndex();
+ const MCCFIInstruction &CFI = Instrs[CFIIndex];
+ emitCFIInstruction(CFI);
+}
+
+void AsmPrinter::emitFrameAlloc(const MachineInstr &MI) {
+ // The operands are the MCSymbol and the frame offset of the allocation.
+ MCSymbol *FrameAllocSym = MI.getOperand(0).getMCSymbol();
+ int FrameOffset = MI.getOperand(1).getImm();
+
+ // Emit a symbol assignment.
+ OutStreamer->EmitAssignment(FrameAllocSym,
+ MCConstantExpr::create(FrameOffset, OutContext));
+}
+
+/// EmitFunctionBody - This method emits the body and trailer for a
+/// function.
+void AsmPrinter::EmitFunctionBody() {
+ EmitFunctionHeader();
+
+ // Emit target-specific gunk before the function body.
+ EmitFunctionBodyStart();
+
+ bool ShouldPrintDebugScopes = MMI->hasDebugInfo();
+
+ // Print out code for the function.
+ bool HasAnyRealCode = false;
+ for (auto &MBB : *MF) {
+ // Print a label for the basic block.
+ EmitBasicBlockStart(MBB);
+ for (auto &MI : MBB) {
+
+ // Print the assembly for the instruction.
+ if (!MI.isPosition() && !MI.isImplicitDef() && !MI.isKill() &&
+ !MI.isDebugValue()) {
+ HasAnyRealCode = true;
+ ++EmittedInsts;
+ }
+
+ if (ShouldPrintDebugScopes) {
+ for (const HandlerInfo &HI : Handlers) {
+ NamedRegionTimer T(HI.TimerName, HI.TimerGroupName,
+ TimePassesIsEnabled);
+ HI.Handler->beginInstruction(&MI);
+ }
+ }
+
+ if (isVerbose())
+ emitComments(MI, OutStreamer->GetCommentOS());
+
+ switch (MI.getOpcode()) {
+ case TargetOpcode::CFI_INSTRUCTION:
+ emitCFIInstruction(MI);
+ break;
+
+ case TargetOpcode::LOCAL_ESCAPE:
+ emitFrameAlloc(MI);
+ break;
+
+ case TargetOpcode::EH_LABEL:
+ case TargetOpcode::GC_LABEL:
+ OutStreamer->EmitLabel(MI.getOperand(0).getMCSymbol());
+ break;
+ case TargetOpcode::INLINEASM:
+ EmitInlineAsm(&MI);
+ break;
+ case TargetOpcode::DBG_VALUE:
+ if (isVerbose()) {
+ if (!emitDebugValueComment(&MI, *this))
+ EmitInstruction(&MI);
+ }
+ break;
+ case TargetOpcode::IMPLICIT_DEF:
+ if (isVerbose()) emitImplicitDef(&MI);
+ break;
+ case TargetOpcode::KILL:
+ if (isVerbose()) emitKill(&MI, *this);
+ break;
+ default:
+ EmitInstruction(&MI);
+ break;
+ }
+
+ if (ShouldPrintDebugScopes) {
+ for (const HandlerInfo &HI : Handlers) {
+ NamedRegionTimer T(HI.TimerName, HI.TimerGroupName,
+ TimePassesIsEnabled);
+ HI.Handler->endInstruction();
+ }
+ }
+ }
+
+ EmitBasicBlockEnd(MBB);
+ }
+
+ // If the function is empty and the object file uses .subsections_via_symbols,
+ // then we need to emit *something* to the function body to prevent the
+ // labels from collapsing together. Just emit a noop.
+ if ((MAI->hasSubsectionsViaSymbols() && !HasAnyRealCode)) {
+ MCInst Noop;
+ MF->getSubtarget().getInstrInfo()->getNoopForMachoTarget(Noop);
+ OutStreamer->AddComment("avoids zero-length function");
+
+ // Targets can opt-out of emitting the noop here by leaving the opcode
+ // unspecified.
+ if (Noop.getOpcode())
+ OutStreamer->EmitInstruction(Noop, getSubtargetInfo());
+ }
+
+ const Function *F = MF->getFunction();
+ for (const auto &BB : *F) {
+ if (!BB.hasAddressTaken())
+ continue;
+ MCSymbol *Sym = GetBlockAddressSymbol(&BB);
+ if (Sym->isDefined())
+ continue;
+ OutStreamer->AddComment("Address of block that was removed by CodeGen");
+ OutStreamer->EmitLabel(Sym);
+ }
+
+ // Emit target-specific gunk after the function body.
+ EmitFunctionBodyEnd();
+
+ if (!MMI->getLandingPads().empty() || MMI->hasDebugInfo() ||
+ MMI->hasEHFunclets() || MAI->hasDotTypeDotSizeDirective()) {
+ // Create a symbol for the end of function.
+ CurrentFnEnd = createTempSymbol("func_end");
+ OutStreamer->EmitLabel(CurrentFnEnd);
+ }
+
+ // If the target wants a .size directive for the size of the function, emit
+ // it.
+ if (MAI->hasDotTypeDotSizeDirective()) {
+ // We can get the size as difference between the function label and the
+ // temp label.
+ const MCExpr *SizeExp = MCBinaryExpr::createSub(
+ MCSymbolRefExpr::create(CurrentFnEnd, OutContext),
+ MCSymbolRefExpr::create(CurrentFnSymForSize, OutContext), OutContext);
+ if (auto Sym = dyn_cast<MCSymbolELF>(CurrentFnSym))
+ OutStreamer->emitELFSize(Sym, SizeExp);
+ }
+
+ for (const HandlerInfo &HI : Handlers) {
+ NamedRegionTimer T(HI.TimerName, HI.TimerGroupName, TimePassesIsEnabled);
+ HI.Handler->markFunctionEnd();
+ }
+
+ // Print out jump tables referenced by the function.
+ EmitJumpTableInfo();
+
+ // Emit post-function debug and/or EH information.
+ for (const HandlerInfo &HI : Handlers) {
+ NamedRegionTimer T(HI.TimerName, HI.TimerGroupName, TimePassesIsEnabled);
+ HI.Handler->endFunction(MF);
+ }
+ MMI->EndFunction();
+
+ OutStreamer->AddBlankLine();
+}
+
+/// \brief Compute the number of Global Variables that uses a Constant.
+static unsigned getNumGlobalVariableUses(const Constant *C) {
+ if (!C)
+ return 0;
+
+ if (isa<GlobalVariable>(C))
+ return 1;
+
+ unsigned NumUses = 0;
+ for (auto *CU : C->users())
+ NumUses += getNumGlobalVariableUses(dyn_cast<Constant>(CU));
+
+ return NumUses;
+}
+
+/// \brief Only consider global GOT equivalents if at least one user is a
+/// cstexpr inside an initializer of another global variables. Also, don't
+/// handle cstexpr inside instructions. During global variable emission,
+/// candidates are skipped and are emitted later in case at least one cstexpr
+/// isn't replaced by a PC relative GOT entry access.
+static bool isGOTEquivalentCandidate(const GlobalVariable *GV,
+ unsigned &NumGOTEquivUsers) {
+ // Global GOT equivalents are unnamed private globals with a constant
+ // pointer initializer to another global symbol. They must point to a
+ // GlobalVariable or Function, i.e., as GlobalValue.
+ if (!GV->hasUnnamedAddr() || !GV->hasInitializer() || !GV->isConstant() ||
+ !GV->isDiscardableIfUnused() || !dyn_cast<GlobalValue>(GV->getOperand(0)))
+ return false;
+
+ // To be a got equivalent, at least one of its users need to be a constant
+ // expression used by another global variable.
+ for (auto *U : GV->users())
+ NumGOTEquivUsers += getNumGlobalVariableUses(dyn_cast<Constant>(U));
+
+ return NumGOTEquivUsers > 0;
+}
+
+/// \brief Unnamed constant global variables solely contaning a pointer to
+/// another globals variable is equivalent to a GOT table entry; it contains the
+/// the address of another symbol. Optimize it and replace accesses to these
+/// "GOT equivalents" by using the GOT entry for the final global instead.
+/// Compute GOT equivalent candidates among all global variables to avoid
+/// emitting them if possible later on, after it use is replaced by a GOT entry
+/// access.
+void AsmPrinter::computeGlobalGOTEquivs(Module &M) {
+ if (!getObjFileLowering().supportIndirectSymViaGOTPCRel())
+ return;
+
+ for (const auto &G : M.globals()) {
+ unsigned NumGOTEquivUsers = 0;
+ if (!isGOTEquivalentCandidate(&G, NumGOTEquivUsers))
+ continue;
+
+ const MCSymbol *GOTEquivSym = getSymbol(&G);
+ GlobalGOTEquivs[GOTEquivSym] = std::make_pair(&G, NumGOTEquivUsers);
+ }
+}
+
+/// \brief Constant expressions using GOT equivalent globals may not be eligible
+/// for PC relative GOT entry conversion, in such cases we need to emit such
+/// globals we previously omitted in EmitGlobalVariable.
+void AsmPrinter::emitGlobalGOTEquivs() {
+ if (!getObjFileLowering().supportIndirectSymViaGOTPCRel())
+ return;
+
+ SmallVector<const GlobalVariable *, 8> FailedCandidates;
+ for (auto &I : GlobalGOTEquivs) {
+ const GlobalVariable *GV = I.second.first;
+ unsigned Cnt = I.second.second;
+ if (Cnt)
+ FailedCandidates.push_back(GV);
+ }
+ GlobalGOTEquivs.clear();
+
+ for (auto *GV : FailedCandidates)
+ EmitGlobalVariable(GV);
+}
+
+bool AsmPrinter::doFinalization(Module &M) {
+ // Set the MachineFunction to nullptr so that we can catch attempted
+ // accesses to MF specific features at the module level and so that
+ // we can conditionalize accesses based on whether or not it is nullptr.
+ MF = nullptr;
+
+ // Gather all GOT equivalent globals in the module. We really need two
+ // passes over the globals: one to compute and another to avoid its emission
+ // in EmitGlobalVariable, otherwise we would not be able to handle cases
+ // where the got equivalent shows up before its use.
+ computeGlobalGOTEquivs(M);
+
+ // Emit global variables.
+ for (const auto &G : M.globals())
+ EmitGlobalVariable(&G);
+
+ // Emit remaining GOT equivalent globals.
+ emitGlobalGOTEquivs();
+
+ // Emit visibility info for declarations
+ for (const Function &F : M) {
+ if (!F.isDeclarationForLinker())
+ continue;
+ GlobalValue::VisibilityTypes V = F.getVisibility();
+ if (V == GlobalValue::DefaultVisibility)
+ continue;
+
+ MCSymbol *Name = getSymbol(&F);
+ EmitVisibility(Name, V, false);
+ }
+
+ const TargetLoweringObjectFile &TLOF = getObjFileLowering();
+
+ // Emit module flags.
+ SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags;
+ M.getModuleFlagsMetadata(ModuleFlags);
+ if (!ModuleFlags.empty())
+ TLOF.emitModuleFlags(*OutStreamer, ModuleFlags, *Mang, TM);
+
+ if (TM.getTargetTriple().isOSBinFormatELF()) {
+ MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
+
+ // Output stubs for external and common global variables.
+ MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList();
+ if (!Stubs.empty()) {
+ OutStreamer->SwitchSection(TLOF.getDataSection());
+ const DataLayout &DL = M.getDataLayout();
+
+ for (const auto &Stub : Stubs) {
+ 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.TimerGroupName,
+ TimePassesIsEnabled);
+ HI.Handler->endModule();
+ delete HI.Handler;
+ }
+ Handlers.clear();
+ DD = nullptr;
+
+ // If the target wants to know about weak references, print them all.
+ if (MAI->getWeakRefDirective()) {
+ // FIXME: This is not lazy, it would be nice to only print weak references
+ // to stuff that is actually used. Note that doing so would require targets
+ // to notice uses in operands (due to constant exprs etc). This should
+ // happen with the MC stuff eventually.
+
+ // Print out module-level global variables here.
+ for (const auto &G : M.globals()) {
+ if (!G.hasExternalWeakLinkage())
+ continue;
+ OutStreamer->EmitSymbolAttribute(getSymbol(&G), MCSA_WeakReference);
+ }
+
+ for (const auto &F : M) {
+ if (!F.hasExternalWeakLinkage())
+ continue;
+ OutStreamer->EmitSymbolAttribute(getSymbol(&F), MCSA_WeakReference);
+ }
+ }
+
+ OutStreamer->AddBlankLine();
+ for (const auto &Alias : M.aliases()) {
+ MCSymbol *Name = getSymbol(&Alias);
+
+ if (Alias.hasExternalLinkage() || !MAI->getWeakRefDirective())
+ OutStreamer->EmitSymbolAttribute(Name, MCSA_Global);
+ else if (Alias.hasWeakLinkage() || Alias.hasLinkOnceLinkage())
+ OutStreamer->EmitSymbolAttribute(Name, MCSA_WeakReference);
+ else
+ assert(Alias.hasLocalLinkage() && "Invalid alias linkage");
+
+ // Set the symbol type to function if the alias has a function type.
+ // This affects codegen when the aliasee is not a function.
+ if (Alias.getType()->getPointerElementType()->isFunctionTy())
+ OutStreamer->EmitSymbolAttribute(Name, MCSA_ELF_TypeFunction);
+
+ EmitVisibility(Name, Alias.getVisibility());
+
+ // Emit the directives as assignments aka .set:
+ OutStreamer->EmitAssignment(Name, lowerConstant(Alias.getAliasee()));
+
+ // If the aliasee does not correspond to a symbol in the output, i.e. the
+ // alias is not of an object or the aliased object is private, then set the
+ // size of the alias symbol from the type of the alias. We don't do this in
+ // other situations as the alias and aliasee having differing types but same
+ // size may be intentional.
+ const GlobalObject *BaseObject = Alias.getBaseObject();
+ if (MAI->hasDotTypeDotSizeDirective() && Alias.getValueType()->isSized() &&
+ (!BaseObject || BaseObject->hasPrivateLinkage())) {
+ const DataLayout &DL = M.getDataLayout();
+ uint64_t Size = DL.getTypeAllocSize(Alias.getValueType());
+ OutStreamer->emitELFSize(cast<MCSymbolELF>(Name),
+ MCConstantExpr::create(Size, OutContext));
+ }
+ }
+
+ GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
+ assert(MI && "AsmPrinter didn't require GCModuleInfo?");
+ for (GCModuleInfo::iterator I = MI->end(), E = MI->begin(); I != E; )
+ if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(**--I))
+ MP->finishAssembly(M, *MI, *this);
+
+ // Emit llvm.ident metadata in an '.ident' directive.
+ EmitModuleIdents(M);
+
+ // Emit __morestack address if needed for indirect calls.
+ if (MMI->usesMorestackAddr()) {
+ MCSection *ReadOnlySection = getObjFileLowering().getSectionForConstant(
+ getDataLayout(), SectionKind::getReadOnly(),
+ /*C=*/nullptr);
+ OutStreamer->SwitchSection(ReadOnlySection);
+
+ MCSymbol *AddrSymbol =
+ OutContext.getOrCreateSymbol(StringRef("__morestack_addr"));
+ OutStreamer->EmitLabel(AddrSymbol);
+
+ unsigned PtrSize = M.getDataLayout().getPointerSize(0);
+ OutStreamer->EmitSymbolValue(GetExternalSymbolSymbol("__morestack"),
+ PtrSize);
+ }
+
+ // If we don't have any trampolines, then we don't require stack memory
+ // to be executable. Some targets have a directive to declare this.
+ Function *InitTrampolineIntrinsic = M.getFunction("llvm.init.trampoline");
+ if (!InitTrampolineIntrinsic || InitTrampolineIntrinsic->use_empty())
+ if (MCSection *S = MAI->getNonexecutableStackSection(OutContext))
+ OutStreamer->SwitchSection(S);
+
+ // Allow the target to emit any magic that it wants at the end of the file,
+ // after everything else has gone out.
+ EmitEndOfAsmFile(M);
+
+ delete Mang; Mang = nullptr;
+ MMI = nullptr;
+
+ OutStreamer->Finish();
+ OutStreamer->reset();
+
+ return false;
+}
+
+MCSymbol *AsmPrinter::getCurExceptionSym() {
+ if (!CurExceptionSym)
+ CurExceptionSym = createTempSymbol("exception");
+ return CurExceptionSym;
+}
+
+void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
+ this->MF = &MF;
+ // Get the function symbol.
+ CurrentFnSym = getSymbol(MF.getFunction());
+ CurrentFnSymForSize = CurrentFnSym;
+ CurrentFnBegin = nullptr;
+ CurExceptionSym = nullptr;
+ bool NeedsLocalForSize = MAI->needsLocalForSize();
+ if (!MMI->getLandingPads().empty() || MMI->hasDebugInfo() ||
+ MMI->hasEHFunclets() || NeedsLocalForSize) {
+ CurrentFnBegin = createTempSymbol("func_begin");
+ if (NeedsLocalForSize)
+ CurrentFnSymForSize = CurrentFnBegin;
+ }
+
+ if (isVerbose())
+ LI = &getAnalysis<MachineLoopInfo>();
+}
+
+namespace {
+// Keep track the alignment, constpool entries per Section.
+ struct SectionCPs {
+ MCSection *S;
+ unsigned Alignment;
+ SmallVector<unsigned, 4> CPEs;
+ SectionCPs(MCSection *s, unsigned a) : S(s), Alignment(a) {}
+ };
+}
+
+/// EmitConstantPool - Print to the current output stream assembly
+/// representations of the constants in the constant pool MCP. This is
+/// used to print out constants which have been "spilled to memory" by
+/// the code generator.
+///
+void AsmPrinter::EmitConstantPool() {
+ const MachineConstantPool *MCP = MF->getConstantPool();
+ const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants();
+ if (CP.empty()) return;
+
+ // Calculate sections for constant pool entries. We collect entries to go into
+ // the same section together to reduce amount of section switch statements.
+ SmallVector<SectionCPs, 4> CPSections;
+ for (unsigned i = 0, e = CP.size(); i != e; ++i) {
+ const MachineConstantPoolEntry &CPE = CP[i];
+ unsigned Align = CPE.getAlignment();
+
+ SectionKind Kind = CPE.getSectionKind(&getDataLayout());
+
+ const Constant *C = nullptr;
+ if (!CPE.isMachineConstantPoolEntry())
+ C = CPE.Val.ConstVal;
+
+ MCSection *S =
+ getObjFileLowering().getSectionForConstant(getDataLayout(), Kind, C);
+
+ // The number of sections are small, just do a linear search from the
+ // last section to the first.
+ bool Found = false;
+ unsigned SecIdx = CPSections.size();
+ while (SecIdx != 0) {
+ if (CPSections[--SecIdx].S == S) {
+ Found = true;
+ break;
+ }
+ }
+ if (!Found) {
+ SecIdx = CPSections.size();
+ CPSections.push_back(SectionCPs(S, Align));
+ }
+
+ if (Align > CPSections[SecIdx].Alignment)
+ CPSections[SecIdx].Alignment = Align;
+ CPSections[SecIdx].CPEs.push_back(i);
+ }
+
+ // Now print stuff into the calculated sections.
+ const MCSection *CurSection = nullptr;
+ unsigned Offset = 0;
+ for (unsigned i = 0, e = CPSections.size(); i != e; ++i) {
+ for (unsigned j = 0, ee = CPSections[i].CPEs.size(); j != ee; ++j) {
+ unsigned CPI = CPSections[i].CPEs[j];
+ MCSymbol *Sym = GetCPISymbol(CPI);
+ if (!Sym->isUndefined())
+ continue;
+
+ if (CurSection != CPSections[i].S) {
+ OutStreamer->SwitchSection(CPSections[i].S);
+ EmitAlignment(Log2_32(CPSections[i].Alignment));
+ CurSection = CPSections[i].S;
+ Offset = 0;
+ }
+
+ MachineConstantPoolEntry CPE = CP[CPI];
+
+ // Emit inter-object padding for alignment.
+ unsigned AlignMask = CPE.getAlignment() - 1;
+ unsigned NewOffset = (Offset + AlignMask) & ~AlignMask;
+ OutStreamer->EmitZeros(NewOffset - Offset);
+
+ Type *Ty = CPE.getType();
+ Offset = NewOffset + getDataLayout().getTypeAllocSize(Ty);
+
+ OutStreamer->EmitLabel(Sym);
+ if (CPE.isMachineConstantPoolEntry())
+ EmitMachineConstantPoolValue(CPE.Val.MachineCPVal);
+ else
+ EmitGlobalConstant(getDataLayout(), CPE.Val.ConstVal);
+ }
+ }
+}
+
+/// EmitJumpTableInfo - Print assembly representations of the jump tables used
+/// by the current function to the current output stream.
+///
+void AsmPrinter::EmitJumpTableInfo() {
+ const DataLayout &DL = MF->getDataLayout();
+ const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
+ if (!MJTI) return;
+ if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_Inline) return;
+ const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
+ if (JT.empty()) return;
+
+ // Pick the directive to use to print the jump table entries, and switch to
+ // the appropriate section.
+ const Function *F = MF->getFunction();
+ const TargetLoweringObjectFile &TLOF = getObjFileLowering();
+ bool JTInDiffSection = !TLOF.shouldPutJumpTableInFunctionSection(
+ MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32,
+ *F);
+ if (JTInDiffSection) {
+ // Drop it in the readonly section.
+ MCSection *ReadOnlySection = TLOF.getSectionForJumpTable(*F, *Mang, TM);
+ OutStreamer->SwitchSection(ReadOnlySection);
+ }
+
+ EmitAlignment(Log2_32(MJTI->getEntryAlignment(DL)));
+
+ // Jump tables in code sections are marked with a data_region directive
+ // where that's supported.
+ if (!JTInDiffSection)
+ OutStreamer->EmitDataRegion(MCDR_DataRegionJT32);
+
+ for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) {
+ const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
+
+ // If this jump table was deleted, ignore it.
+ if (JTBBs.empty()) continue;
+
+ // For the EK_LabelDifference32 entry, if using .set avoids a relocation,
+ /// emit a .set directive for each unique entry.
+ if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 &&
+ MAI->doesSetDirectiveSuppressesReloc()) {
+ SmallPtrSet<const MachineBasicBlock*, 16> EmittedSets;
+ const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
+ const MCExpr *Base = TLI->getPICJumpTableRelocBaseExpr(MF,JTI,OutContext);
+ for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) {
+ const MachineBasicBlock *MBB = JTBBs[ii];
+ if (!EmittedSets.insert(MBB).second)
+ continue;
+
+ // .set LJTSet, LBB32-base
+ const MCExpr *LHS =
+ MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
+ OutStreamer->EmitAssignment(GetJTSetSymbol(JTI, MBB->getNumber()),
+ MCBinaryExpr::createSub(LHS, Base,
+ OutContext));
+ }
+ }
+
+ // On some targets (e.g. Darwin) we want to emit two consecutive labels
+ // before each jump table. The first label is never referenced, but tells
+ // the assembler and linker the extents of the jump table object. The
+ // second label is actually referenced by the code.
+ if (JTInDiffSection && DL.hasLinkerPrivateGlobalPrefix())
+ // FIXME: This doesn't have to have any specific name, just any randomly
+ // named and numbered 'l' label would work. Simplify GetJTISymbol.
+ OutStreamer->EmitLabel(GetJTISymbol(JTI, true));
+
+ OutStreamer->EmitLabel(GetJTISymbol(JTI));
+
+ for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii)
+ EmitJumpTableEntry(MJTI, JTBBs[ii], JTI);
+ }
+ if (!JTInDiffSection)
+ OutStreamer->EmitDataRegion(MCDR_DataRegionEnd);
+}
+
+/// EmitJumpTableEntry - Emit a jump table entry for the specified MBB to the
+/// current stream.
+void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI,
+ const MachineBasicBlock *MBB,
+ unsigned UID) const {
+ assert(MBB && MBB->getNumber() >= 0 && "Invalid basic block");
+ const MCExpr *Value = nullptr;
+ switch (MJTI->getEntryKind()) {
+ case MachineJumpTableInfo::EK_Inline:
+ llvm_unreachable("Cannot emit EK_Inline jump table entry");
+ case MachineJumpTableInfo::EK_Custom32:
+ Value = MF->getSubtarget().getTargetLowering()->LowerCustomJumpTableEntry(
+ MJTI, MBB, UID, OutContext);
+ break;
+ case MachineJumpTableInfo::EK_BlockAddress:
+ // EK_BlockAddress - Each entry is a plain address of block, e.g.:
+ // .word LBB123
+ Value = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
+ break;
+ case MachineJumpTableInfo::EK_GPRel32BlockAddress: {
+ // EK_GPRel32BlockAddress - Each entry is an address of block, encoded
+ // with a relocation as gp-relative, e.g.:
+ // .gprel32 LBB123
+ MCSymbol *MBBSym = MBB->getSymbol();
+ OutStreamer->EmitGPRel32Value(MCSymbolRefExpr::create(MBBSym, OutContext));
+ return;
+ }
+
+ case MachineJumpTableInfo::EK_GPRel64BlockAddress: {
+ // EK_GPRel64BlockAddress - Each entry is an address of block, encoded
+ // with a relocation as gp-relative, e.g.:
+ // .gpdword LBB123
+ MCSymbol *MBBSym = MBB->getSymbol();
+ OutStreamer->EmitGPRel64Value(MCSymbolRefExpr::create(MBBSym, OutContext));
+ return;
+ }
+
+ case MachineJumpTableInfo::EK_LabelDifference32: {
+ // Each entry is the address of the block minus the address of the jump
+ // table. This is used for PIC jump tables where gprel32 is not supported.
+ // e.g.:
+ // .word LBB123 - LJTI1_2
+ // If the .set directive avoids relocations, this is emitted as:
+ // .set L4_5_set_123, LBB123 - LJTI1_2
+ // .word L4_5_set_123
+ if (MAI->doesSetDirectiveSuppressesReloc()) {
+ Value = MCSymbolRefExpr::create(GetJTSetSymbol(UID, MBB->getNumber()),
+ OutContext);
+ break;
+ }
+ Value = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
+ const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
+ const MCExpr *Base = TLI->getPICJumpTableRelocBaseExpr(MF, UID, OutContext);
+ Value = MCBinaryExpr::createSub(Value, Base, OutContext);
+ break;
+ }
+ }
+
+ assert(Value && "Unknown entry kind!");
+
+ unsigned EntrySize = MJTI->getEntrySize(getDataLayout());
+ OutStreamer->EmitValue(Value, EntrySize);
+}
+
+
+/// EmitSpecialLLVMGlobal - Check to see if the specified global is a
+/// special global used by LLVM. If so, emit it and return true, otherwise
+/// do nothing and return false.
+bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
+ if (GV->getName() == "llvm.used") {
+ if (MAI->hasNoDeadStrip()) // No need to emit this at all.
+ EmitLLVMUsedList(cast<ConstantArray>(GV->getInitializer()));
+ return true;
+ }
+
+ // Ignore debug and non-emitted data. This handles llvm.compiler.used.
+ if (StringRef(GV->getSection()) == "llvm.metadata" ||
+ GV->hasAvailableExternallyLinkage())
+ return true;
+
+ if (!GV->hasAppendingLinkage()) return false;
+
+ assert(GV->hasInitializer() && "Not a special LLVM global!");
+
+ if (GV->getName() == "llvm.global_ctors") {
+ EmitXXStructorList(GV->getParent()->getDataLayout(), GV->getInitializer(),
+ /* isCtor */ true);
+
+ if (TM.getRelocationModel() == Reloc::Static &&
+ MAI->hasStaticCtorDtorReferenceInStaticMode()) {
+ StringRef Sym(".constructors_used");
+ OutStreamer->EmitSymbolAttribute(OutContext.getOrCreateSymbol(Sym),
+ MCSA_Reference);
+ }
+ return true;
+ }
+
+ if (GV->getName() == "llvm.global_dtors") {
+ EmitXXStructorList(GV->getParent()->getDataLayout(), GV->getInitializer(),
+ /* isCtor */ false);
+
+ if (TM.getRelocationModel() == Reloc::Static &&
+ MAI->hasStaticCtorDtorReferenceInStaticMode()) {
+ StringRef Sym(".destructors_used");
+ OutStreamer->EmitSymbolAttribute(OutContext.getOrCreateSymbol(Sym),
+ MCSA_Reference);
+ }
+ return true;
+ }
+
+ return false;
+}
+
+/// EmitLLVMUsedList - For targets that define a MAI::UsedDirective, mark each
+/// global in the specified llvm.used list for which emitUsedDirectiveFor
+/// is true, as being used with this directive.
+void AsmPrinter::EmitLLVMUsedList(const ConstantArray *InitList) {
+ // Should be an array of 'i8*'.
+ for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
+ const GlobalValue *GV =
+ dyn_cast<GlobalValue>(InitList->getOperand(i)->stripPointerCasts());
+ if (GV)
+ OutStreamer->EmitSymbolAttribute(getSymbol(GV), MCSA_NoDeadStrip);
+ }
+}
+
+namespace {
+struct Structor {
+ Structor() : Priority(0), Func(nullptr), ComdatKey(nullptr) {}
+ int Priority;
+ llvm::Constant *Func;
+ llvm::GlobalValue *ComdatKey;
+};
+} // end namespace
+
+/// EmitXXStructorList - Emit the ctor or dtor list taking into account the init
+/// priority.
+void AsmPrinter::EmitXXStructorList(const DataLayout &DL, const Constant *List,
+ bool isCtor) {
+ // Should be an array of '{ int, void ()* }' structs. The first value is the
+ // init priority.
+ if (!isa<ConstantArray>(List)) return;
+
+ // Sanity check the structors list.
+ const ConstantArray *InitList = dyn_cast<ConstantArray>(List);
+ if (!InitList) return; // Not an array!
+ StructType *ETy = dyn_cast<StructType>(InitList->getType()->getElementType());
+ // FIXME: Only allow the 3-field form in LLVM 4.0.
+ if (!ETy || ETy->getNumElements() < 2 || ETy->getNumElements() > 3)
+ return; // Not an array of two or three elements!
+ if (!isa<IntegerType>(ETy->getTypeAtIndex(0U)) ||
+ !isa<PointerType>(ETy->getTypeAtIndex(1U))) return; // Not (int, ptr).
+ if (ETy->getNumElements() == 3 && !isa<PointerType>(ETy->getTypeAtIndex(2U)))
+ return; // Not (int, ptr, ptr).
+
+ // Gather the structors in a form that's convenient for sorting by priority.
+ SmallVector<Structor, 8> Structors;
+ for (Value *O : InitList->operands()) {
+ ConstantStruct *CS = dyn_cast<ConstantStruct>(O);
+ if (!CS) continue; // Malformed.
+ if (CS->getOperand(1)->isNullValue())
+ break; // Found a null terminator, skip the rest.
+ ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0));
+ if (!Priority) continue; // Malformed.
+ Structors.push_back(Structor());
+ Structor &S = Structors.back();
+ S.Priority = Priority->getLimitedValue(65535);
+ S.Func = CS->getOperand(1);
+ if (ETy->getNumElements() == 3 && !CS->getOperand(2)->isNullValue())
+ S.ComdatKey = dyn_cast<GlobalValue>(CS->getOperand(2)->stripPointerCasts());
+ }
+
+ // Emit the function pointers in the target-specific order
+ unsigned Align = Log2_32(DL.getPointerPrefAlignment());
+ std::stable_sort(Structors.begin(), Structors.end(),
+ [](const Structor &L,
+ const Structor &R) { return L.Priority < R.Priority; });
+ for (Structor &S : Structors) {
+ const TargetLoweringObjectFile &Obj = getObjFileLowering();
+ const MCSymbol *KeySym = nullptr;
+ if (GlobalValue *GV = S.ComdatKey) {
+ if (GV->hasAvailableExternallyLinkage())
+ // If the associated variable is available_externally, some other TU
+ // will provide its dynamic initializer.
+ continue;
+
+ KeySym = getSymbol(GV);
+ }
+ MCSection *OutputSection =
+ (isCtor ? Obj.getStaticCtorSection(S.Priority, KeySym)
+ : Obj.getStaticDtorSection(S.Priority, KeySym));
+ OutStreamer->SwitchSection(OutputSection);
+ if (OutStreamer->getCurrentSection() != OutStreamer->getPreviousSection())
+ EmitAlignment(Align);
+ EmitXXStructor(DL, S.Func);
+ }
+}
+
+void AsmPrinter::EmitModuleIdents(Module &M) {
+ if (!MAI->hasIdentDirective())
+ return;
+
+ if (const NamedMDNode *NMD = M.getNamedMetadata("llvm.ident")) {
+ for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
+ const MDNode *N = NMD->getOperand(i);
+ assert(N->getNumOperands() == 1 &&
+ "llvm.ident metadata entry can have only one operand");
+ const MDString *S = cast<MDString>(N->getOperand(0));
+ OutStreamer->EmitIdent(S->getString());
+ }
+ }
+}
+
+//===--------------------------------------------------------------------===//
+// Emission and print routines
+//
+
+/// EmitInt8 - Emit a byte directive and value.
+///
+void AsmPrinter::EmitInt8(int Value) const {
+ OutStreamer->EmitIntValue(Value, 1);
+}
+
+/// EmitInt16 - Emit a short directive and value.
+///
+void AsmPrinter::EmitInt16(int Value) const {
+ OutStreamer->EmitIntValue(Value, 2);
+}
+
+/// EmitInt32 - Emit a long directive and value.
+///
+void AsmPrinter::EmitInt32(int Value) const {
+ OutStreamer->EmitIntValue(Value, 4);
+}
+
+/// Emit something like ".long Hi-Lo" where the size in bytes of the directive
+/// is specified by Size and Hi/Lo specify the labels. This implicitly uses
+/// .set if it avoids relocations.
+void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,
+ unsigned Size) const {
+ OutStreamer->emitAbsoluteSymbolDiff(Hi, Lo, Size);
+}
+
+/// EmitLabelPlusOffset - Emit something like ".long Label+Offset"
+/// where the size in bytes of the directive is specified by Size and Label
+/// specifies the label. This implicitly uses .set if it is available.
+void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset,
+ unsigned Size,
+ bool IsSectionRelative) const {
+ if (MAI->needsDwarfSectionOffsetDirective() && IsSectionRelative) {
+ OutStreamer->EmitCOFFSecRel32(Label);
+ return;
+ }
+
+ // Emit Label+Offset (or just Label if Offset is zero)
+ const MCExpr *Expr = MCSymbolRefExpr::create(Label, OutContext);
+ if (Offset)
+ Expr = MCBinaryExpr::createAdd(
+ Expr, MCConstantExpr::create(Offset, OutContext), OutContext);
+
+ OutStreamer->EmitValue(Expr, Size);
+}
+
+//===----------------------------------------------------------------------===//
+
+// EmitAlignment - Emit an alignment directive to the specified power of
+// two boundary. For example, if you pass in 3 here, you will get an 8
+// byte alignment. If a global value is specified, and if that global has
+// an explicit alignment requested, it will override the alignment request
+// if required for correctness.
+//
+void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalObject *GV) const {
+ if (GV)
+ NumBits = getGVAlignmentLog2(GV, GV->getParent()->getDataLayout(), NumBits);
+
+ if (NumBits == 0) return; // 1-byte aligned: no need to emit alignment.
+
+ assert(NumBits <
+ static_cast<unsigned>(std::numeric_limits<unsigned>::digits) &&
+ "undefined behavior");
+ if (getCurrentSection()->getKind().isText())
+ OutStreamer->EmitCodeAlignment(1u << NumBits);
+ else
+ OutStreamer->EmitValueToAlignment(1u << NumBits);
+}
+
+//===----------------------------------------------------------------------===//
+// Constant emission.
+//===----------------------------------------------------------------------===//
+
+const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) {
+ MCContext &Ctx = OutContext;
+
+ if (CV->isNullValue() || isa<UndefValue>(CV))
+ return MCConstantExpr::create(0, Ctx);
+
+ if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV))
+ return MCConstantExpr::create(CI->getZExtValue(), Ctx);
+
+ if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV))
+ return MCSymbolRefExpr::create(getSymbol(GV), Ctx);
+
+ if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV))
+ return MCSymbolRefExpr::create(GetBlockAddressSymbol(BA), Ctx);
+
+ const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV);
+ if (!CE) {
+ llvm_unreachable("Unknown constant value to lower!");
+ }
+
+ if (const MCExpr *RelocExpr
+ = getObjFileLowering().getExecutableRelativeSymbol(CE, *Mang, TM))
+ return RelocExpr;
+
+ switch (CE->getOpcode()) {
+ default:
+ // If the code isn't optimized, there may be outstanding folding
+ // opportunities. Attempt to fold the expression using DataLayout as a
+ // last resort before giving up.
+ if (Constant *C = ConstantFoldConstantExpression(CE, getDataLayout()))
+ if (C != CE)
+ return lowerConstant(C);
+
+ // Otherwise report the problem to the user.
+ {
+ std::string S;
+ raw_string_ostream OS(S);
+ OS << "Unsupported expression in static initializer: ";
+ CE->printAsOperand(OS, /*PrintType=*/false,
+ !MF ? nullptr : MF->getFunction()->getParent());
+ report_fatal_error(OS.str());
+ }
+ case Instruction::GetElementPtr: {
+ // Generate a symbolic expression for the byte address
+ APInt OffsetAI(getDataLayout().getPointerTypeSizeInBits(CE->getType()), 0);
+ cast<GEPOperator>(CE)->accumulateConstantOffset(getDataLayout(), OffsetAI);
+
+ const MCExpr *Base = lowerConstant(CE->getOperand(0));
+ if (!OffsetAI)
+ return Base;
+
+ int64_t Offset = OffsetAI.getSExtValue();
+ return MCBinaryExpr::createAdd(Base, MCConstantExpr::create(Offset, Ctx),
+ Ctx);
+ }
+
+ case Instruction::Trunc:
+ // We emit the value and depend on the assembler to truncate the generated
+ // expression properly. This is important for differences between
+ // blockaddress labels. Since the two labels are in the same function, it
+ // is reasonable to treat their delta as a 32-bit value.
+ // FALL THROUGH.
+ case Instruction::BitCast:
+ return lowerConstant(CE->getOperand(0));
+
+ case Instruction::IntToPtr: {
+ const DataLayout &DL = getDataLayout();
+
+ // Handle casts to pointers by changing them into casts to the appropriate
+ // integer type. This promotes constant folding and simplifies this code.
+ Constant *Op = CE->getOperand(0);
+ Op = ConstantExpr::getIntegerCast(Op, DL.getIntPtrType(CV->getType()),
+ false/*ZExt*/);
+ return lowerConstant(Op);
+ }
+
+ case Instruction::PtrToInt: {
+ const DataLayout &DL = getDataLayout();
+
+ // Support only foldable casts to/from pointers that can be eliminated by
+ // changing the pointer to the appropriately sized integer type.
+ Constant *Op = CE->getOperand(0);
+ Type *Ty = CE->getType();
+
+ const MCExpr *OpExpr = lowerConstant(Op);
+
+ // We can emit the pointer value into this slot if the slot is an
+ // integer slot equal to the size of the pointer.
+ if (DL.getTypeAllocSize(Ty) == DL.getTypeAllocSize(Op->getType()))
+ return OpExpr;
+
+ // Otherwise the pointer is smaller than the resultant integer, mask off
+ // the high bits so we are sure to get a proper truncation if the input is
+ // a constant expr.
+ unsigned InBits = DL.getTypeAllocSizeInBits(Op->getType());
+ const MCExpr *MaskExpr = MCConstantExpr::create(~0ULL >> (64-InBits), Ctx);
+ return MCBinaryExpr::createAnd(OpExpr, MaskExpr, Ctx);
+ }
+
+ // The MC library also has a right-shift operator, but it isn't consistently
+ // signed or unsigned between different targets.
+ case Instruction::Add:
+ case Instruction::Sub:
+ case Instruction::Mul:
+ case Instruction::SDiv:
+ case Instruction::SRem:
+ case Instruction::Shl:
+ case Instruction::And:
+ case Instruction::Or:
+ case Instruction::Xor: {
+ const MCExpr *LHS = lowerConstant(CE->getOperand(0));
+ const MCExpr *RHS = lowerConstant(CE->getOperand(1));
+ switch (CE->getOpcode()) {
+ default: llvm_unreachable("Unknown binary operator constant cast expr");
+ case Instruction::Add: return MCBinaryExpr::createAdd(LHS, RHS, Ctx);
+ case Instruction::Sub: return MCBinaryExpr::createSub(LHS, RHS, Ctx);
+ case Instruction::Mul: return MCBinaryExpr::createMul(LHS, RHS, Ctx);
+ case Instruction::SDiv: return MCBinaryExpr::createDiv(LHS, RHS, Ctx);
+ case Instruction::SRem: return MCBinaryExpr::createMod(LHS, RHS, Ctx);
+ case Instruction::Shl: return MCBinaryExpr::createShl(LHS, RHS, Ctx);
+ case Instruction::And: return MCBinaryExpr::createAnd(LHS, RHS, Ctx);
+ case Instruction::Or: return MCBinaryExpr::createOr (LHS, RHS, Ctx);
+ case Instruction::Xor: return MCBinaryExpr::createXor(LHS, RHS, Ctx);
+ }
+ }
+ }
+}
+
+static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *C,
+ AsmPrinter &AP,
+ const Constant *BaseCV = nullptr,
+ uint64_t Offset = 0);
+
+static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP);
+
+/// isRepeatedByteSequence - Determine whether the given value is
+/// composed of a repeated sequence of identical bytes and return the
+/// byte value. If it is not a repeated sequence, return -1.
+static int isRepeatedByteSequence(const ConstantDataSequential *V) {
+ StringRef Data = V->getRawDataValues();
+ assert(!Data.empty() && "Empty aggregates should be CAZ node");
+ char C = Data[0];
+ for (unsigned i = 1, e = Data.size(); i != e; ++i)
+ if (Data[i] != C) return -1;
+ return static_cast<uint8_t>(C); // Ensure 255 is not returned as -1.
+}
+
+
+/// isRepeatedByteSequence - Determine whether the given value is
+/// composed of a repeated sequence of identical bytes and return the
+/// byte value. If it is not a repeated sequence, return -1.
+static int isRepeatedByteSequence(const Value *V, const DataLayout &DL) {
+ if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
+ uint64_t Size = DL.getTypeAllocSizeInBits(V->getType());
+ assert(Size % 8 == 0);
+
+ // Extend the element to take zero padding into account.
+ APInt Value = CI->getValue().zextOrSelf(Size);
+ if (!Value.isSplat(8))
+ return -1;
+
+ return Value.zextOrTrunc(8).getZExtValue();
+ }
+ if (const ConstantArray *CA = dyn_cast<ConstantArray>(V)) {
+ // Make sure all array elements are sequences of the same repeated
+ // byte.
+ assert(CA->getNumOperands() != 0 && "Should be a CAZ");
+ Constant *Op0 = CA->getOperand(0);
+ int Byte = isRepeatedByteSequence(Op0, DL);
+ if (Byte == -1)
+ return -1;
+
+ // All array elements must be equal.
+ for (unsigned i = 1, e = CA->getNumOperands(); i != e; ++i)
+ if (CA->getOperand(i) != Op0)
+ return -1;
+ return Byte;
+ }
+
+ if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(V))
+ return isRepeatedByteSequence(CDS);
+
+ return -1;
+}
+
+static void emitGlobalConstantDataSequential(const DataLayout &DL,
+ const ConstantDataSequential *CDS,
+ AsmPrinter &AP) {
+
+ // See if we can aggregate this into a .fill, if so, emit it as such.
+ int Value = isRepeatedByteSequence(CDS, DL);
+ if (Value != -1) {
+ uint64_t Bytes = DL.getTypeAllocSize(CDS->getType());
+ // Don't emit a 1-byte object as a .fill.
+ if (Bytes > 1)
+ return AP.OutStreamer->EmitFill(Bytes, Value);
+ }
+
+ // If this can be emitted with .ascii/.asciz, emit it as such.
+ if (CDS->isString())
+ return AP.OutStreamer->EmitBytes(CDS->getAsString());
+
+ // Otherwise, emit the values in successive locations.
+ unsigned ElementByteSize = CDS->getElementByteSize();
+ if (isa<IntegerType>(CDS->getElementType())) {
+ for (unsigned i = 0, e = CDS->getNumElements(); i != e; ++i) {
+ if (AP.isVerbose())
+ AP.OutStreamer->GetCommentOS() << format("0x%" PRIx64 "\n",
+ CDS->getElementAsInteger(i));
+ AP.OutStreamer->EmitIntValue(CDS->getElementAsInteger(i),
+ ElementByteSize);
+ }
+ } else {
+ for (unsigned I = 0, E = CDS->getNumElements(); I != E; ++I)
+ emitGlobalConstantFP(cast<ConstantFP>(CDS->getElementAsConstant(I)), AP);
+ }
+
+ unsigned Size = DL.getTypeAllocSize(CDS->getType());
+ unsigned EmittedSize = DL.getTypeAllocSize(CDS->getType()->getElementType()) *
+ CDS->getNumElements();
+ if (unsigned Padding = Size - EmittedSize)
+ AP.OutStreamer->EmitZeros(Padding);
+
+}
+
+static void emitGlobalConstantArray(const DataLayout &DL,
+ const ConstantArray *CA, AsmPrinter &AP,
+ const Constant *BaseCV, uint64_t Offset) {
+ // See if we can aggregate some values. Make sure it can be
+ // represented as a series of bytes of the constant value.
+ int Value = isRepeatedByteSequence(CA, DL);
+
+ if (Value != -1) {
+ uint64_t Bytes = DL.getTypeAllocSize(CA->getType());
+ AP.OutStreamer->EmitFill(Bytes, Value);
+ }
+ else {
+ for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) {
+ emitGlobalConstantImpl(DL, CA->getOperand(i), AP, BaseCV, Offset);
+ Offset += DL.getTypeAllocSize(CA->getOperand(i)->getType());
+ }
+ }
+}
+
+static void emitGlobalConstantVector(const DataLayout &DL,
+ const ConstantVector *CV, AsmPrinter &AP) {
+ for (unsigned i = 0, e = CV->getType()->getNumElements(); i != e; ++i)
+ emitGlobalConstantImpl(DL, CV->getOperand(i), AP);
+
+ unsigned Size = DL.getTypeAllocSize(CV->getType());
+ unsigned EmittedSize = DL.getTypeAllocSize(CV->getType()->getElementType()) *
+ CV->getType()->getNumElements();
+ if (unsigned Padding = Size - EmittedSize)
+ AP.OutStreamer->EmitZeros(Padding);
+}
+
+static void emitGlobalConstantStruct(const DataLayout &DL,
+ const ConstantStruct *CS, AsmPrinter &AP,
+ const Constant *BaseCV, uint64_t Offset) {
+ // Print the fields in successive locations. Pad to align if needed!
+ unsigned Size = DL.getTypeAllocSize(CS->getType());
+ const StructLayout *Layout = DL.getStructLayout(CS->getType());
+ uint64_t SizeSoFar = 0;
+ for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) {
+ const Constant *Field = CS->getOperand(i);
+
+ // Print the actual field value.
+ emitGlobalConstantImpl(DL, Field, AP, BaseCV, Offset + SizeSoFar);
+
+ // Check if padding is needed and insert one or more 0s.
+ uint64_t FieldSize = DL.getTypeAllocSize(Field->getType());
+ uint64_t PadSize = ((i == e-1 ? Size : Layout->getElementOffset(i+1))
+ - Layout->getElementOffset(i)) - FieldSize;
+ SizeSoFar += FieldSize + PadSize;
+
+ // Insert padding - this may include padding to increase the size of the
+ // current field up to the ABI size (if the struct is not packed) as well
+ // as padding to ensure that the next field starts at the right offset.
+ AP.OutStreamer->EmitZeros(PadSize);
+ }
+ assert(SizeSoFar == Layout->getSizeInBytes() &&
+ "Layout of constant struct may be incorrect!");
+}
+
+static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP) {
+ APInt API = CFP->getValueAPF().bitcastToAPInt();
+
+ // First print a comment with what we think the original floating-point value
+ // should have been.
+ if (AP.isVerbose()) {
+ SmallString<8> StrVal;
+ CFP->getValueAPF().toString(StrVal);
+
+ if (CFP->getType())
+ CFP->getType()->print(AP.OutStreamer->GetCommentOS());
+ else
+ AP.OutStreamer->GetCommentOS() << "Printing <null> Type";
+ AP.OutStreamer->GetCommentOS() << ' ' << StrVal << '\n';
+ }
+
+ // Now iterate through the APInt chunks, emitting them in endian-correct
+ // order, possibly with a smaller chunk at beginning/end (e.g. for x87 80-bit
+ // floats).
+ unsigned NumBytes = API.getBitWidth() / 8;
+ unsigned TrailingBytes = NumBytes % sizeof(uint64_t);
+ const uint64_t *p = API.getRawData();
+
+ // PPC's long double has odd notions of endianness compared to how LLVM
+ // handles it: p[0] goes first for *big* endian on PPC.
+ if (AP.getDataLayout().isBigEndian() && !CFP->getType()->isPPC_FP128Ty()) {
+ int Chunk = API.getNumWords() - 1;
+
+ if (TrailingBytes)
+ AP.OutStreamer->EmitIntValue(p[Chunk--], TrailingBytes);
+
+ for (; Chunk >= 0; --Chunk)
+ AP.OutStreamer->EmitIntValue(p[Chunk], sizeof(uint64_t));
+ } else {
+ unsigned Chunk;
+ for (Chunk = 0; Chunk < NumBytes / sizeof(uint64_t); ++Chunk)
+ AP.OutStreamer->EmitIntValue(p[Chunk], sizeof(uint64_t));
+
+ if (TrailingBytes)
+ AP.OutStreamer->EmitIntValue(p[Chunk], TrailingBytes);
+ }
+
+ // Emit the tail padding for the long double.
+ const DataLayout &DL = AP.getDataLayout();
+ AP.OutStreamer->EmitZeros(DL.getTypeAllocSize(CFP->getType()) -
+ DL.getTypeStoreSize(CFP->getType()));
+}
+
+static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) {
+ const DataLayout &DL = AP.getDataLayout();
+ unsigned BitWidth = CI->getBitWidth();
+
+ // Copy the value as we may massage the layout for constants whose bit width
+ // is not a multiple of 64-bits.
+ APInt Realigned(CI->getValue());
+ uint64_t ExtraBits = 0;
+ unsigned ExtraBitsSize = BitWidth & 63;
+
+ if (ExtraBitsSize) {
+ // The bit width of the data is not a multiple of 64-bits.
+ // The extra bits are expected to be at the end of the chunk of the memory.
+ // Little endian:
+ // * Nothing to be done, just record the extra bits to emit.
+ // Big endian:
+ // * Record the extra bits to emit.
+ // * Realign the raw data to emit the chunks of 64-bits.
+ if (DL.isBigEndian()) {
+ // Basically the structure of the raw data is a chunk of 64-bits cells:
+ // 0 1 BitWidth / 64
+ // [chunk1][chunk2] ... [chunkN].
+ // The most significant chunk is chunkN and it should be emitted first.
+ // However, due to the alignment issue chunkN contains useless bits.
+ // Realign the chunks so that they contain only useless information:
+ // ExtraBits 0 1 (BitWidth / 64) - 1
+ // chu[nk1 chu][nk2 chu] ... [nkN-1 chunkN]
+ ExtraBits = Realigned.getRawData()[0] &
+ (((uint64_t)-1) >> (64 - ExtraBitsSize));
+ Realigned = Realigned.lshr(ExtraBitsSize);
+ } else
+ ExtraBits = Realigned.getRawData()[BitWidth / 64];
+ }
+
+ // We don't expect assemblers to support integer data directives
+ // for more than 64 bits, so we emit the data in at most 64-bit
+ // quantities at a time.
+ const uint64_t *RawData = Realigned.getRawData();
+ for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) {
+ uint64_t Val = DL.isBigEndian() ? RawData[e - i - 1] : RawData[i];
+ AP.OutStreamer->EmitIntValue(Val, 8);
+ }
+
+ if (ExtraBitsSize) {
+ // Emit the extra bits after the 64-bits chunks.
+
+ // Emit a directive that fills the expected size.
+ uint64_t Size = AP.getDataLayout().getTypeAllocSize(CI->getType());
+ Size -= (BitWidth / 64) * 8;
+ assert(Size && Size * 8 >= ExtraBitsSize &&
+ (ExtraBits & (((uint64_t)-1) >> (64 - ExtraBitsSize)))
+ == ExtraBits && "Directive too small for extra bits.");
+ AP.OutStreamer->EmitIntValue(ExtraBits, Size);
+ }
+}
+
+/// \brief Transform a not absolute MCExpr containing a reference to a GOT
+/// equivalent global, by a target specific GOT pc relative access to the
+/// final symbol.
+static void handleIndirectSymViaGOTPCRel(AsmPrinter &AP, const MCExpr **ME,
+ const Constant *BaseCst,
+ uint64_t Offset) {
+ // The global @foo below illustrates a global that uses a got equivalent.
+ //
+ // @bar = global i32 42
+ // @gotequiv = private unnamed_addr constant i32* @bar
+ // @foo = i32 trunc (i64 sub (i64 ptrtoint (i32** @gotequiv to i64),
+ // i64 ptrtoint (i32* @foo to i64))
+ // to i32)
+ //
+ // The cstexpr in @foo is converted into the MCExpr `ME`, where we actually
+ // check whether @foo is suitable to use a GOTPCREL. `ME` is usually in the
+ // form:
+ //
+ // foo = cstexpr, where
+ // cstexpr := <gotequiv> - "." + <cst>
+ // cstexpr := <gotequiv> - (<foo> - <offset from @foo base>) + <cst>
+ //
+ // After canonicalization by evaluateAsRelocatable `ME` turns into:
+ //
+ // cstexpr := <gotequiv> - <foo> + gotpcrelcst, where
+ // gotpcrelcst := <offset from @foo base> + <cst>
+ //
+ MCValue MV;
+ if (!(*ME)->evaluateAsRelocatable(MV, nullptr, nullptr) || MV.isAbsolute())
+ return;
+ const MCSymbolRefExpr *SymA = MV.getSymA();
+ if (!SymA)
+ return;
+
+ // Check that GOT equivalent symbol is cached.
+ const MCSymbol *GOTEquivSym = &SymA->getSymbol();
+ if (!AP.GlobalGOTEquivs.count(GOTEquivSym))
+ return;
+
+ const GlobalValue *BaseGV = dyn_cast_or_null<GlobalValue>(BaseCst);
+ if (!BaseGV)
+ return;
+
+ // Check for a valid base symbol
+ const MCSymbol *BaseSym = AP.getSymbol(BaseGV);
+ const MCSymbolRefExpr *SymB = MV.getSymB();
+
+ if (!SymB || BaseSym != &SymB->getSymbol())
+ return;
+
+ // Make sure to match:
+ //
+ // gotpcrelcst := <offset from @foo base> + <cst>
+ //
+ // If gotpcrelcst is positive it means that we can safely fold the pc rel
+ // displacement into the GOTPCREL. We can also can have an extra offset <cst>
+ // if the target knows how to encode it.
+ //
+ int64_t GOTPCRelCst = Offset + MV.getConstant();
+ if (GOTPCRelCst < 0)
+ return;
+ if (!AP.getObjFileLowering().supportGOTPCRelWithOffset() && GOTPCRelCst != 0)
+ return;
+
+ // Emit the GOT PC relative to replace the got equivalent global, i.e.:
+ //
+ // bar:
+ // .long 42
+ // gotequiv:
+ // .quad bar
+ // foo:
+ // .long gotequiv - "." + <cst>
+ //
+ // is replaced by the target specific equivalent to:
+ //
+ // bar:
+ // .long 42
+ // foo:
+ // .long bar@GOTPCREL+<gotpcrelcst>
+ //
+ AsmPrinter::GOTEquivUsePair Result = AP.GlobalGOTEquivs[GOTEquivSym];
+ const GlobalVariable *GV = Result.first;
+ int NumUses = (int)Result.second;
+ const GlobalValue *FinalGV = dyn_cast<GlobalValue>(GV->getOperand(0));
+ const MCSymbol *FinalSym = AP.getSymbol(FinalGV);
+ *ME = AP.getObjFileLowering().getIndirectSymViaGOTPCRel(
+ FinalSym, MV, Offset, AP.MMI, *AP.OutStreamer);
+
+ // Update GOT equivalent usage information
+ --NumUses;
+ if (NumUses >= 0)
+ AP.GlobalGOTEquivs[GOTEquivSym] = std::make_pair(GV, NumUses);
+}
+
+static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV,
+ AsmPrinter &AP, const Constant *BaseCV,
+ uint64_t Offset) {
+ uint64_t Size = DL.getTypeAllocSize(CV->getType());
+
+ // Globals with sub-elements such as combinations of arrays and structs
+ // are handled recursively by emitGlobalConstantImpl. Keep track of the
+ // constant symbol base and the current position with BaseCV and Offset.
+ if (!BaseCV && CV->hasOneUse())
+ BaseCV = dyn_cast<Constant>(CV->user_back());
+
+ if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV))
+ return AP.OutStreamer->EmitZeros(Size);
+
+ if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
+ switch (Size) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ if (AP.isVerbose())
+ AP.OutStreamer->GetCommentOS() << format("0x%" PRIx64 "\n",
+ CI->getZExtValue());
+ AP.OutStreamer->EmitIntValue(CI->getZExtValue(), Size);
+ return;
+ default:
+ emitGlobalConstantLargeInt(CI, AP);
+ return;
+ }
+ }
+
+ if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV))
+ return emitGlobalConstantFP(CFP, AP);
+
+ if (isa<ConstantPointerNull>(CV)) {
+ AP.OutStreamer->EmitIntValue(0, Size);
+ return;
+ }
+
+ if (const ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(CV))
+ return emitGlobalConstantDataSequential(DL, CDS, AP);
+
+ if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV))
+ return emitGlobalConstantArray(DL, CVA, AP, BaseCV, Offset);
+
+ if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV))
+ return emitGlobalConstantStruct(DL, CVS, AP, BaseCV, Offset);
+
+ if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
+ // Look through bitcasts, which might not be able to be MCExpr'ized (e.g. of
+ // vectors).
+ if (CE->getOpcode() == Instruction::BitCast)
+ return emitGlobalConstantImpl(DL, CE->getOperand(0), AP);
+
+ if (Size > 8) {
+ // If the constant expression's size is greater than 64-bits, then we have
+ // to emit the value in chunks. Try to constant fold the value and emit it
+ // that way.
+ Constant *New = ConstantFoldConstantExpression(CE, DL);
+ if (New && New != CE)
+ return emitGlobalConstantImpl(DL, New, AP);
+ }
+ }
+
+ if (const ConstantVector *V = dyn_cast<ConstantVector>(CV))
+ return emitGlobalConstantVector(DL, V, AP);
+
+ // Otherwise, it must be a ConstantExpr. Lower it to an MCExpr, then emit it
+ // thread the streamer with EmitValue.
+ const MCExpr *ME = AP.lowerConstant(CV);
+
+ // Since lowerConstant already folded and got rid of all IR pointer and
+ // integer casts, detect GOT equivalent accesses by looking into the MCExpr
+ // directly.
+ if (AP.getObjFileLowering().supportIndirectSymViaGOTPCRel())
+ handleIndirectSymViaGOTPCRel(AP, &ME, BaseCV, Offset);
+
+ AP.OutStreamer->EmitValue(ME, Size);
+}
+
+/// EmitGlobalConstant - Print a general LLVM constant to the .s file.
+void AsmPrinter::EmitGlobalConstant(const DataLayout &DL, const Constant *CV) {
+ uint64_t Size = DL.getTypeAllocSize(CV->getType());
+ if (Size)
+ emitGlobalConstantImpl(DL, CV, *this);
+ else if (MAI->hasSubsectionsViaSymbols()) {
+ // If the global has zero size, emit a single byte so that two labels don't
+ // look like they are at the same location.
+ OutStreamer->EmitIntValue(0, 1);
+ }
+}
+
+void AsmPrinter::EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
+ // Target doesn't support this yet!
+ llvm_unreachable("Target does not support EmitMachineConstantPoolValue");
+}
+
+void AsmPrinter::printOffset(int64_t Offset, raw_ostream &OS) const {
+ if (Offset > 0)
+ OS << '+' << Offset;
+ else if (Offset < 0)
+ OS << Offset;
+}
+
+//===----------------------------------------------------------------------===//
+// Symbol Lowering Routines.
+//===----------------------------------------------------------------------===//
+
+MCSymbol *AsmPrinter::createTempSymbol(const Twine &Name) const {
+ return OutContext.createTempSymbol(Name, true);
+}
+
+MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BlockAddress *BA) const {
+ return MMI->getAddrLabelSymbol(BA->getBasicBlock());
+}
+
+MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BasicBlock *BB) const {
+ return MMI->getAddrLabelSymbol(BB);
+}
+
+/// GetCPISymbol - Return the symbol for the specified constant pool entry.
+MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const {
+ const DataLayout &DL = getDataLayout();
+ return OutContext.getOrCreateSymbol(Twine(DL.getPrivateGlobalPrefix()) +
+ "CPI" + Twine(getFunctionNumber()) + "_" +
+ Twine(CPID));
+}
+
+/// GetJTISymbol - Return the symbol for the specified jump table entry.
+MCSymbol *AsmPrinter::GetJTISymbol(unsigned JTID, bool isLinkerPrivate) const {
+ return MF->getJTISymbol(JTID, OutContext, isLinkerPrivate);
+}
+
+/// GetJTSetSymbol - Return the symbol for the specified jump table .set
+/// FIXME: privatize to AsmPrinter.
+MCSymbol *AsmPrinter::GetJTSetSymbol(unsigned UID, unsigned MBBID) const {
+ const DataLayout &DL = getDataLayout();
+ return OutContext.getOrCreateSymbol(Twine(DL.getPrivateGlobalPrefix()) +
+ Twine(getFunctionNumber()) + "_" +
+ Twine(UID) + "_set_" + Twine(MBBID));
+}
+
+MCSymbol *AsmPrinter::getSymbolWithGlobalValueBase(const GlobalValue *GV,
+ StringRef Suffix) const {
+ return getObjFileLowering().getSymbolWithGlobalValueBase(GV, Suffix, *Mang,
+ TM);
+}
+
+/// Return the MCSymbol for the specified ExternalSymbol.
+MCSymbol *AsmPrinter::GetExternalSymbolSymbol(StringRef Sym) const {
+ SmallString<60> NameStr;
+ Mangler::getNameWithPrefix(NameStr, Sym, getDataLayout());
+ return OutContext.getOrCreateSymbol(NameStr);
+}
+
+
+
+/// PrintParentLoopComment - Print comments about parent loops of this one.
+static void PrintParentLoopComment(raw_ostream &OS, const MachineLoop *Loop,
+ unsigned FunctionNumber) {
+ if (!Loop) return;
+ PrintParentLoopComment(OS, Loop->getParentLoop(), FunctionNumber);
+ OS.indent(Loop->getLoopDepth()*2)
+ << "Parent Loop BB" << FunctionNumber << "_"
+ << Loop->getHeader()->getNumber()
+ << " Depth=" << Loop->getLoopDepth() << '\n';
+}
+
+
+/// PrintChildLoopComment - Print comments about child loops within
+/// the loop for this basic block, with nesting.
+static void PrintChildLoopComment(raw_ostream &OS, const MachineLoop *Loop,
+ unsigned FunctionNumber) {
+ // Add child loop information
+ for (const MachineLoop *CL : *Loop) {
+ OS.indent(CL->getLoopDepth()*2)
+ << "Child Loop BB" << FunctionNumber << "_"
+ << CL->getHeader()->getNumber() << " Depth " << CL->getLoopDepth()
+ << '\n';
+ PrintChildLoopComment(OS, CL, FunctionNumber);
+ }
+}
+
+/// emitBasicBlockLoopComments - Pretty-print comments for basic blocks.
+static void emitBasicBlockLoopComments(const MachineBasicBlock &MBB,
+ const MachineLoopInfo *LI,
+ const AsmPrinter &AP) {
+ // Add loop depth information
+ const MachineLoop *Loop = LI->getLoopFor(&MBB);
+ if (!Loop) return;
+
+ MachineBasicBlock *Header = Loop->getHeader();
+ assert(Header && "No header for loop");
+
+ // If this block is not a loop header, just print out what is the loop header
+ // and return.
+ if (Header != &MBB) {
+ AP.OutStreamer->AddComment(" in Loop: Header=BB" +
+ Twine(AP.getFunctionNumber())+"_" +
+ Twine(Loop->getHeader()->getNumber())+
+ " Depth="+Twine(Loop->getLoopDepth()));
+ return;
+ }
+
+ // Otherwise, it is a loop header. Print out information about child and
+ // parent loops.
+ raw_ostream &OS = AP.OutStreamer->GetCommentOS();
+
+ PrintParentLoopComment(OS, Loop->getParentLoop(), AP.getFunctionNumber());
+
+ OS << "=>";
+ OS.indent(Loop->getLoopDepth()*2-2);
+
+ OS << "This ";
+ if (Loop->empty())
+ OS << "Inner ";
+ OS << "Loop Header: Depth=" + Twine(Loop->getLoopDepth()) << '\n';
+
+ PrintChildLoopComment(OS, Loop, AP.getFunctionNumber());
+}
+
+
+/// EmitBasicBlockStart - This method prints the label for the specified
+/// MachineBasicBlock, an alignment (if present) and a comment describing
+/// it if appropriate.
+void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) const {
+ // End the previous funclet and start a new one.
+ if (MBB.isEHFuncletEntry()) {
+ for (const HandlerInfo &HI : Handlers) {
+ HI.Handler->endFunclet();
+ HI.Handler->beginFunclet(MBB);
+ }
+ }
+
+ // Emit an alignment directive for this block, if needed.
+ if (unsigned Align = MBB.getAlignment())
+ EmitAlignment(Align);
+
+ // If the block has its address taken, emit any labels that were used to
+ // reference the block. It is possible that there is more than one label
+ // here, because multiple LLVM BB's may have been RAUW'd to this block after
+ // the references were generated.
+ if (MBB.hasAddressTaken()) {
+ const BasicBlock *BB = MBB.getBasicBlock();
+ if (isVerbose())
+ OutStreamer->AddComment("Block address taken");
+
+ // MBBs can have their address taken as part of CodeGen without having
+ // their corresponding BB's address taken in IR
+ if (BB->hasAddressTaken())
+ for (MCSymbol *Sym : MMI->getAddrLabelSymbolToEmit(BB))
+ OutStreamer->EmitLabel(Sym);
+ }
+
+ // Print some verbose block comments.
+ if (isVerbose()) {
+ if (const BasicBlock *BB = MBB.getBasicBlock()) {
+ if (BB->hasName()) {
+ BB->printAsOperand(OutStreamer->GetCommentOS(),
+ /*PrintType=*/false, BB->getModule());
+ OutStreamer->GetCommentOS() << '\n';
+ }
+ }
+ emitBasicBlockLoopComments(MBB, LI, *this);
+ }
+
+ // Print the main label for the block.
+ if (MBB.pred_empty() ||
+ (isBlockOnlyReachableByFallthrough(&MBB) && !MBB.isEHFuncletEntry())) {
+ if (isVerbose()) {
+ // NOTE: Want this comment at start of line, don't emit with AddComment.
+ OutStreamer->emitRawComment(" BB#" + Twine(MBB.getNumber()) + ":", false);
+ }
+ } else {
+ OutStreamer->EmitLabel(MBB.getSymbol());
+ }
+}
+
+void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility,
+ bool IsDefinition) const {
+ MCSymbolAttr Attr = MCSA_Invalid;
+
+ switch (Visibility) {
+ default: break;
+ case GlobalValue::HiddenVisibility:
+ if (IsDefinition)
+ Attr = MAI->getHiddenVisibilityAttr();
+ else
+ Attr = MAI->getHiddenDeclarationVisibilityAttr();
+ break;
+ case GlobalValue::ProtectedVisibility:
+ Attr = MAI->getProtectedVisibilityAttr();
+ break;
+ }
+
+ if (Attr != MCSA_Invalid)
+ OutStreamer->EmitSymbolAttribute(Sym, Attr);
+}
+
+/// isBlockOnlyReachableByFallthough - Return true if the basic block has
+/// exactly one predecessor and the control transfer mechanism between
+/// the predecessor and this block is a fall-through.
+bool AsmPrinter::
+isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const {
+ // If this is a landing pad, it isn't a fall through. If it has no preds,
+ // then nothing falls through to it.
+ if (MBB->isEHPad() || MBB->pred_empty())
+ return false;
+
+ // If there isn't exactly one predecessor, it can't be a fall through.
+ if (MBB->pred_size() > 1)
+ return false;
+
+ // The predecessor has to be immediately before this block.
+ MachineBasicBlock *Pred = *MBB->pred_begin();
+ if (!Pred->isLayoutSuccessor(MBB))
+ return false;
+
+ // If the block is completely empty, then it definitely does fall through.
+ if (Pred->empty())
+ return true;
+
+ // Check the terminators in the previous blocks
+ for (const auto &MI : Pred->terminators()) {
+ // If it is not a simple branch, we are in a table somewhere.
+ if (!MI.isBranch() || MI.isIndirectBranch())
+ return false;
+
+ // If we are the operands of one of the branches, this is not a fall
+ // through. Note that targets with delay slots will usually bundle
+ // terminators with the delay slot instruction.
+ for (ConstMIBundleOperands OP(&MI); OP.isValid(); ++OP) {
+ if (OP->isJTI())
+ return false;
+ if (OP->isMBB() && OP->getMBB() == MBB)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+
+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())
+ return GCPI->second.get();
+
+ const char *Name = S.getName().c_str();
+
+ for (GCMetadataPrinterRegistry::iterator
+ I = GCMetadataPrinterRegistry::begin(),
+ E = GCMetadataPrinterRegistry::end(); I != E; ++I)
+ if (strcmp(Name, I->getName()) == 0) {
+ std::unique_ptr<GCMetadataPrinter> GMP = I->instantiate();
+ GMP->S = &S;
+ auto IterBool = GCMap.insert(std::make_pair(&S, std::move(GMP)));
+ return IterBool.first->second.get();
+ }
+
+ report_fatal_error("no GCMetadataPrinter registered for GC: " + Twine(Name));
+}
+
+/// Pin vtable to this file.
+AsmPrinterHandler::~AsmPrinterHandler() {}
+
+void AsmPrinterHandler::markFunctionEnd() {}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
new file mode 100644
index 0000000..504c5d2
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
@@ -0,0 +1,290 @@
+//===-- AsmPrinterDwarf.cpp - AsmPrinter Dwarf Support --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Dwarf emissions parts of AsmPrinter.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ByteStreamer.h"
+#include "DwarfDebug.h"
+#include "DwarfExpression.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/DIE.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MachineLocation.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+using namespace llvm;
+
+#define DEBUG_TYPE "asm-printer"
+
+//===----------------------------------------------------------------------===//
+// Dwarf Emission Helper Routines
+//===----------------------------------------------------------------------===//
+
+/// EmitSLEB128 - emit the specified signed leb128 value.
+void AsmPrinter::EmitSLEB128(int64_t Value, const char *Desc) const {
+ if (isVerbose() && Desc)
+ OutStreamer->AddComment(Desc);
+
+ OutStreamer->EmitSLEB128IntValue(Value);
+}
+
+/// EmitULEB128 - emit the specified unsigned leb128 value.
+void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc,
+ unsigned PadTo) const {
+ if (isVerbose() && Desc)
+ OutStreamer->AddComment(Desc);
+
+ OutStreamer->EmitULEB128IntValue(Value, PadTo);
+}
+
+static const char *DecodeDWARFEncoding(unsigned Encoding) {
+ switch (Encoding) {
+ case dwarf::DW_EH_PE_absptr:
+ return "absptr";
+ case dwarf::DW_EH_PE_omit:
+ return "omit";
+ case dwarf::DW_EH_PE_pcrel:
+ return "pcrel";
+ case dwarf::DW_EH_PE_udata4:
+ return "udata4";
+ case dwarf::DW_EH_PE_udata8:
+ return "udata8";
+ case dwarf::DW_EH_PE_sdata4:
+ return "sdata4";
+ case dwarf::DW_EH_PE_sdata8:
+ return "sdata8";
+ case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4:
+ return "pcrel udata4";
+ case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4:
+ return "pcrel sdata4";
+ case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8:
+ return "pcrel udata8";
+ case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8:
+ return "pcrel sdata8";
+ case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4
+ :
+ return "indirect pcrel udata4";
+ case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4
+ :
+ return "indirect pcrel sdata4";
+ case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8
+ :
+ return "indirect pcrel udata8";
+ case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8
+ :
+ return "indirect pcrel sdata8";
+ }
+
+ return "<unknown encoding>";
+}
+
+/// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an
+/// encoding. If verbose assembly output is enabled, we output comments
+/// describing the encoding. Desc is an optional string saying what the
+/// encoding is specifying (e.g. "LSDA").
+void AsmPrinter::EmitEncodingByte(unsigned Val, const char *Desc) const {
+ if (isVerbose()) {
+ if (Desc)
+ OutStreamer->AddComment(Twine(Desc) + " Encoding = " +
+ Twine(DecodeDWARFEncoding(Val)));
+ else
+ OutStreamer->AddComment(Twine("Encoding = ") + DecodeDWARFEncoding(Val));
+ }
+
+ OutStreamer->EmitIntValue(Val, 1);
+}
+
+/// GetSizeOfEncodedValue - Return the size of the encoding in bytes.
+unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const {
+ if (Encoding == dwarf::DW_EH_PE_omit)
+ return 0;
+
+ switch (Encoding & 0x07) {
+ default:
+ llvm_unreachable("Invalid encoded value.");
+ case dwarf::DW_EH_PE_absptr:
+ return MF->getDataLayout().getPointerSize();
+ case dwarf::DW_EH_PE_udata2:
+ return 2;
+ case dwarf::DW_EH_PE_udata4:
+ return 4;
+ case dwarf::DW_EH_PE_udata8:
+ return 8;
+ }
+}
+
+void AsmPrinter::EmitTTypeReference(const GlobalValue *GV,
+ unsigned Encoding) const {
+ if (GV) {
+ const TargetLoweringObjectFile &TLOF = getObjFileLowering();
+
+ const MCExpr *Exp =
+ TLOF.getTTypeGlobalReference(GV, Encoding, *Mang, TM, MMI,
+ *OutStreamer);
+ OutStreamer->EmitValue(Exp, GetSizeOfEncodedValue(Encoding));
+ } else
+ OutStreamer->EmitIntValue(0, GetSizeOfEncodedValue(Encoding));
+}
+
+void AsmPrinter::emitDwarfSymbolReference(const MCSymbol *Label,
+ bool ForceOffset) const {
+ if (!ForceOffset) {
+ // On COFF targets, we have to emit the special .secrel32 directive.
+ if (MAI->needsDwarfSectionOffsetDirective()) {
+ OutStreamer->EmitCOFFSecRel32(Label);
+ return;
+ }
+
+ // If the format uses relocations with dwarf, refer to the symbol directly.
+ if (MAI->doesDwarfUseRelocationsAcrossSections()) {
+ OutStreamer->EmitSymbolValue(Label, 4);
+ return;
+ }
+ }
+
+ // Otherwise, emit it as a label difference from the start of the section.
+ EmitLabelDifference(Label, Label->getSection().getBeginSymbol(), 4);
+}
+
+void AsmPrinter::emitDwarfStringOffset(DwarfStringPoolEntryRef S) const {
+ if (MAI->doesDwarfUseRelocationsAcrossSections()) {
+ emitDwarfSymbolReference(S.getSymbol());
+ return;
+ }
+
+ // Just emit the offset directly; no need for symbol math.
+ EmitInt32(S.getOffset());
+}
+
+/// EmitDwarfRegOp - Emit dwarf register operation.
+void AsmPrinter::EmitDwarfRegOp(ByteStreamer &Streamer,
+ const MachineLocation &MLoc) const {
+ DebugLocDwarfExpression Expr(*MF->getSubtarget().getRegisterInfo(),
+ getDwarfDebug()->getDwarfVersion(), Streamer);
+ const MCRegisterInfo *MRI = MMI->getContext().getRegisterInfo();
+ int Reg = MRI->getDwarfRegNum(MLoc.getReg(), false);
+ if (Reg < 0) {
+ // We assume that pointers are always in an addressable register.
+ if (MLoc.isIndirect())
+ // FIXME: We have no reasonable way of handling errors in here. The
+ // caller might be in the middle of a dwarf expression. We should
+ // probably assert that Reg >= 0 once debug info generation is more
+ // mature.
+ return Expr.EmitOp(dwarf::DW_OP_nop,
+ "nop (could not find a dwarf register number)");
+
+ // Attempt to find a valid super- or sub-register.
+ if (!Expr.AddMachineRegPiece(MLoc.getReg()))
+ Expr.EmitOp(dwarf::DW_OP_nop,
+ "nop (could not find a dwarf register number)");
+ return;
+ }
+
+ if (MLoc.isIndirect())
+ Expr.AddRegIndirect(Reg, MLoc.getOffset());
+ else
+ Expr.AddReg(Reg);
+}
+
+//===----------------------------------------------------------------------===//
+// Dwarf Lowering Routines
+//===----------------------------------------------------------------------===//
+
+void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const {
+ switch (Inst.getOperation()) {
+ default:
+ llvm_unreachable("Unexpected instruction");
+ case MCCFIInstruction::OpDefCfaOffset:
+ OutStreamer->EmitCFIDefCfaOffset(Inst.getOffset());
+ break;
+ case MCCFIInstruction::OpAdjustCfaOffset:
+ OutStreamer->EmitCFIAdjustCfaOffset(Inst.getOffset());
+ break;
+ case MCCFIInstruction::OpDefCfa:
+ OutStreamer->EmitCFIDefCfa(Inst.getRegister(), Inst.getOffset());
+ break;
+ case MCCFIInstruction::OpDefCfaRegister:
+ OutStreamer->EmitCFIDefCfaRegister(Inst.getRegister());
+ break;
+ case MCCFIInstruction::OpOffset:
+ OutStreamer->EmitCFIOffset(Inst.getRegister(), Inst.getOffset());
+ break;
+ case MCCFIInstruction::OpRegister:
+ OutStreamer->EmitCFIRegister(Inst.getRegister(), Inst.getRegister2());
+ break;
+ case MCCFIInstruction::OpWindowSave:
+ OutStreamer->EmitCFIWindowSave();
+ break;
+ case MCCFIInstruction::OpSameValue:
+ OutStreamer->EmitCFISameValue(Inst.getRegister());
+ break;
+ case MCCFIInstruction::OpGnuArgsSize:
+ OutStreamer->EmitCFIGnuArgsSize(Inst.getOffset());
+ break;
+ case MCCFIInstruction::OpEscape:
+ OutStreamer->EmitCFIEscape(Inst.getValues());
+ break;
+ }
+}
+
+void AsmPrinter::emitDwarfDIE(const DIE &Die) const {
+ // Emit the code (index) for the abbreviation.
+ if (isVerbose())
+ OutStreamer->AddComment("Abbrev [" + Twine(Die.getAbbrevNumber()) + "] 0x" +
+ Twine::utohexstr(Die.getOffset()) + ":0x" +
+ Twine::utohexstr(Die.getSize()) + " " +
+ dwarf::TagString(Die.getTag()));
+ EmitULEB128(Die.getAbbrevNumber());
+
+ // Emit the DIE attribute values.
+ for (const auto &V : Die.values()) {
+ dwarf::Attribute Attr = V.getAttribute();
+ assert(V.getForm() && "Too many attributes for DIE (check abbreviation)");
+
+ if (isVerbose()) {
+ OutStreamer->AddComment(dwarf::AttributeString(Attr));
+ if (Attr == dwarf::DW_AT_accessibility)
+ OutStreamer->AddComment(
+ dwarf::AccessibilityString(V.getDIEInteger().getValue()));
+ }
+
+ // Emit an attribute using the defined form.
+ V.EmitValue(this);
+ }
+
+ // Emit the DIE children if any.
+ if (Die.hasChildren()) {
+ for (auto &Child : Die.children())
+ emitDwarfDIE(Child);
+
+ OutStreamer->AddComment("End Of Children Mark");
+ EmitInt8(0);
+ }
+}
+
+void AsmPrinter::emitDwarfAbbrev(const DIEAbbrev &Abbrev) const {
+ // Emit the abbreviations code (base 1 index.)
+ EmitULEB128(Abbrev.getNumber(), "Abbreviation Code");
+
+ // Emit the abbreviations data.
+ Abbrev.Emit(this);
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h
new file mode 100644
index 0000000..e59961f
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h
@@ -0,0 +1,67 @@
+//===-- 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 MachineBasicBlock;
+class MachineFunction;
+class MachineInstr;
+class MCSymbol;
+
+/// \brief Collects and handles AsmPrinter objects required to build debug
+/// or EH information.
+class AsmPrinterHandler {
+public:
+ virtual ~AsmPrinterHandler();
+
+ /// \brief 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;
+
+ /// \brief Emit all sections that should come after the content.
+ virtual void endModule() = 0;
+
+ /// \brief Gather pre-function debug information.
+ /// Every beginFunction(MF) call should be followed by an endFunction(MF)
+ /// call.
+ virtual void beginFunction(const MachineFunction *MF) = 0;
+
+ // \brief Emit any of function marker (like .cfi_endproc). This is called
+ // before endFunction and cannot switch sections.
+ virtual void markFunctionEnd();
+
+ /// \brief Gather post-function debug information.
+ /// Please note that some AsmPrinter implementations may not call
+ /// beginFunction at all.
+ virtual void endFunction(const MachineFunction *MF) = 0;
+
+ /// \brief Emit target-specific EH funclet machinery.
+ virtual void beginFunclet(const MachineBasicBlock &MBB,
+ MCSymbol *Sym = nullptr) {}
+ virtual void endFunclet() {}
+
+ /// \brief Process beginning of an instruction.
+ virtual void beginInstruction(const MachineInstr *MI) = 0;
+
+ /// \brief 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
new file mode 100644
index 0000000..4171657
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
@@ -0,0 +1,573 @@
+//===-- AsmPrinterInlineAsm.cpp - AsmPrinter Inline Asm Handling ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the inline assembler pieces of the AsmPrinter class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCTargetAsmParser.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+using namespace llvm;
+
+#define DEBUG_TYPE "asm-printer"
+
+namespace {
+ struct SrcMgrDiagInfo {
+ const MDNode *LocInfo;
+ LLVMContext::InlineAsmDiagHandlerTy DiagHandler;
+ void *DiagContext;
+ };
+}
+
+/// srcMgrDiagHandler - This callback is invoked when the SourceMgr for an
+/// inline asm has an error in it. diagInfo is a pointer to the SrcMgrDiagInfo
+/// struct above.
+static void srcMgrDiagHandler(const SMDiagnostic &Diag, void *diagInfo) {
+ SrcMgrDiagInfo *DiagInfo = static_cast<SrcMgrDiagInfo *>(diagInfo);
+ assert(DiagInfo && "Diagnostic context not passed down?");
+
+ // If the inline asm had metadata associated with it, pull out a location
+ // cookie corresponding to which line the error occurred on.
+ unsigned LocCookie = 0;
+ if (const MDNode *LocInfo = DiagInfo->LocInfo) {
+ unsigned ErrorLine = Diag.getLineNo()-1;
+ if (ErrorLine >= LocInfo->getNumOperands())
+ ErrorLine = 0;
+
+ if (LocInfo->getNumOperands() != 0)
+ if (const ConstantInt *CI =
+ mdconst::dyn_extract<ConstantInt>(LocInfo->getOperand(ErrorLine)))
+ LocCookie = CI->getZExtValue();
+ }
+
+ DiagInfo->DiagHandler(Diag, DiagInfo->DiagContext, LocCookie);
+}
+
+/// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
+void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
+ const MCTargetOptions &MCOptions,
+ const MDNode *LocMDNode,
+ InlineAsm::AsmDialect Dialect) const {
+ assert(!Str.empty() && "Can't emit empty inline asm block");
+
+ // Remember if the buffer is nul terminated or not so we can avoid a copy.
+ bool isNullTerminated = Str.back() == 0;
+ if (isNullTerminated)
+ Str = Str.substr(0, Str.size()-1);
+
+ // If the output streamer does not have mature MC support or the integrated
+ // assembler has been disabled, just emit the blob textually.
+ // Otherwise parse the asm and emit it via MC support.
+ // This is useful in case the asm parser doesn't handle something but the
+ // system assembler does.
+ const MCAsmInfo *MCAI = TM.getMCAsmInfo();
+ assert(MCAI && "No MCAsmInfo");
+ if (!MCAI->useIntegratedAssembler() &&
+ !OutStreamer->isIntegratedAssemblerRequired()) {
+ emitInlineAsmStart();
+ OutStreamer->EmitRawText(Str);
+ emitInlineAsmEnd(STI, nullptr);
+ return;
+ }
+
+ SourceMgr SrcMgr;
+ SrcMgrDiagInfo DiagInfo;
+
+ // If the current LLVMContext has an inline asm handler, set it in SourceMgr.
+ LLVMContext &LLVMCtx = MMI->getModule()->getContext();
+ bool HasDiagHandler = false;
+ if (LLVMCtx.getInlineAsmDiagnosticHandler() != nullptr) {
+ // If the source manager has an issue, we arrange for srcMgrDiagHandler
+ // to be invoked, getting DiagInfo passed into it.
+ DiagInfo.LocInfo = LocMDNode;
+ DiagInfo.DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler();
+ DiagInfo.DiagContext = LLVMCtx.getInlineAsmDiagnosticContext();
+ SrcMgr.setDiagHandler(srcMgrDiagHandler, &DiagInfo);
+ HasDiagHandler = true;
+ }
+
+ std::unique_ptr<MemoryBuffer> Buffer;
+ if (isNullTerminated)
+ Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>");
+ else
+ Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>");
+
+ // Tell SrcMgr about this buffer, it takes ownership of the buffer.
+ SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
+
+ std::unique_ptr<MCAsmParser> Parser(
+ createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI));
+
+ // We create a new MCInstrInfo here since we might be at the module level
+ // and not have a MachineFunction to initialize the TargetInstrInfo from and
+ // we only need MCInstrInfo for asm parsing. We create one unconditionally
+ // because it's not subtarget dependent.
+ std::unique_ptr<MCInstrInfo> MII(TM.getTarget().createMCInstrInfo());
+ std::unique_ptr<MCTargetAsmParser> TAP(TM.getTarget().createMCAsmParser(
+ STI, *Parser, *MII, MCOptions));
+ if (!TAP)
+ report_fatal_error("Inline asm not supported by this streamer because"
+ " we don't have an asm parser for this target\n");
+ Parser->setAssemblerDialect(Dialect);
+ Parser->setTargetParser(*TAP.get());
+ if (MF) {
+ const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
+ TAP->SetFrameRegister(TRI->getFrameRegister(*MF));
+ }
+
+ emitInlineAsmStart();
+ // Don't implicitly switch to the text section before the asm.
+ int Res = Parser->Run(/*NoInitialTextSection*/ true,
+ /*NoFinalize*/ true);
+ emitInlineAsmEnd(STI, &TAP->getSTI());
+ if (Res && !HasDiagHandler)
+ report_fatal_error("Error parsing inline asm\n");
+}
+
+static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
+ MachineModuleInfo *MMI, int InlineAsmVariant,
+ AsmPrinter *AP, unsigned LocCookie,
+ raw_ostream &OS) {
+ // Switch to the inline assembly variant.
+ OS << "\t.intel_syntax\n\t";
+
+ const char *LastEmitted = AsmStr; // One past the last character emitted.
+ unsigned NumOperands = MI->getNumOperands();
+
+ while (*LastEmitted) {
+ switch (*LastEmitted) {
+ default: {
+ // Not a special case, emit the string section literally.
+ const char *LiteralEnd = LastEmitted+1;
+ while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' &&
+ *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n')
+ ++LiteralEnd;
+
+ OS.write(LastEmitted, LiteralEnd-LastEmitted);
+ LastEmitted = LiteralEnd;
+ break;
+ }
+ case '\n':
+ ++LastEmitted; // Consume newline character.
+ OS << '\n'; // Indent code with newline.
+ break;
+ case '$': {
+ ++LastEmitted; // Consume '$' character.
+ bool Done = true;
+
+ // Handle escapes.
+ switch (*LastEmitted) {
+ default: Done = false; break;
+ case '$':
+ ++LastEmitted; // Consume second '$' character.
+ break;
+ }
+ if (Done) break;
+
+ const char *IDStart = LastEmitted;
+ const char *IDEnd = IDStart;
+ while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd;
+
+ unsigned Val;
+ if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val))
+ report_fatal_error("Bad $ operand number in inline asm string: '" +
+ Twine(AsmStr) + "'");
+ LastEmitted = IDEnd;
+
+ if (Val >= NumOperands-1)
+ report_fatal_error("Invalid $ operand number in inline asm string: '" +
+ Twine(AsmStr) + "'");
+
+ // Okay, we finally have a value number. Ask the target to print this
+ // operand!
+ unsigned OpNo = InlineAsm::MIOp_FirstOperand;
+
+ bool Error = false;
+
+ // Scan to find the machine operand number for the operand.
+ for (; Val; --Val) {
+ if (OpNo >= MI->getNumOperands()) break;
+ unsigned OpFlags = MI->getOperand(OpNo).getImm();
+ OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
+ }
+
+ // We may have a location metadata attached to the end of the
+ // instruction, and at no point should see metadata at any
+ // other point while processing. It's an error if so.
+ if (OpNo >= MI->getNumOperands() ||
+ MI->getOperand(OpNo).isMetadata()) {
+ Error = true;
+ } else {
+ unsigned OpFlags = MI->getOperand(OpNo).getImm();
+ ++OpNo; // Skip over the ID number.
+
+ if (InlineAsm::isMemKind(OpFlags)) {
+ Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant,
+ /*Modifier*/ nullptr, OS);
+ } else {
+ Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant,
+ /*Modifier*/ nullptr, OS);
+ }
+ }
+ if (Error) {
+ std::string msg;
+ raw_string_ostream Msg(msg);
+ Msg << "invalid operand in inline asm: '" << AsmStr << "'";
+ MMI->getModule()->getContext().emitError(LocCookie, Msg.str());
+ }
+ break;
+ }
+ }
+ }
+ OS << "\n\t.att_syntax\n" << (char)0; // null terminate string.
+}
+
+static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
+ MachineModuleInfo *MMI, int InlineAsmVariant,
+ int AsmPrinterVariant, AsmPrinter *AP,
+ unsigned LocCookie, raw_ostream &OS) {
+ int CurVariant = -1; // The number of the {.|.|.} region we are in.
+ const char *LastEmitted = AsmStr; // One past the last character emitted.
+ unsigned NumOperands = MI->getNumOperands();
+
+ OS << '\t';
+
+ while (*LastEmitted) {
+ switch (*LastEmitted) {
+ default: {
+ // Not a special case, emit the string section literally.
+ const char *LiteralEnd = LastEmitted+1;
+ while (*LiteralEnd && *LiteralEnd != '{' && *LiteralEnd != '|' &&
+ *LiteralEnd != '}' && *LiteralEnd != '$' && *LiteralEnd != '\n')
+ ++LiteralEnd;
+ if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
+ OS.write(LastEmitted, LiteralEnd-LastEmitted);
+ LastEmitted = LiteralEnd;
+ break;
+ }
+ case '\n':
+ ++LastEmitted; // Consume newline character.
+ OS << '\n'; // Indent code with newline.
+ break;
+ case '$': {
+ ++LastEmitted; // Consume '$' character.
+ bool Done = true;
+
+ // Handle escapes.
+ switch (*LastEmitted) {
+ default: Done = false; break;
+ case '$': // $$ -> $
+ if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
+ OS << '$';
+ ++LastEmitted; // Consume second '$' character.
+ break;
+ case '(': // $( -> same as GCC's { character.
+ ++LastEmitted; // Consume '(' character.
+ if (CurVariant != -1)
+ report_fatal_error("Nested variants found in inline asm string: '" +
+ Twine(AsmStr) + "'");
+ CurVariant = 0; // We're in the first variant now.
+ break;
+ case '|':
+ ++LastEmitted; // consume '|' character.
+ if (CurVariant == -1)
+ OS << '|'; // this is gcc's behavior for | outside a variant
+ else
+ ++CurVariant; // We're in the next variant.
+ break;
+ case ')': // $) -> same as GCC's } char.
+ ++LastEmitted; // consume ')' character.
+ if (CurVariant == -1)
+ OS << '}'; // this is gcc's behavior for } outside a variant
+ else
+ CurVariant = -1;
+ break;
+ }
+ if (Done) break;
+
+ bool HasCurlyBraces = false;
+ if (*LastEmitted == '{') { // ${variable}
+ ++LastEmitted; // Consume '{' character.
+ HasCurlyBraces = true;
+ }
+
+ // If we have ${:foo}, then this is not a real operand reference, it is a
+ // "magic" string reference, just like in .td files. Arrange to call
+ // PrintSpecial.
+ if (HasCurlyBraces && *LastEmitted == ':') {
+ ++LastEmitted;
+ const char *StrStart = LastEmitted;
+ const char *StrEnd = strchr(StrStart, '}');
+ if (!StrEnd)
+ report_fatal_error("Unterminated ${:foo} operand in inline asm"
+ " string: '" + Twine(AsmStr) + "'");
+
+ std::string Val(StrStart, StrEnd);
+ AP->PrintSpecial(MI, OS, Val.c_str());
+ LastEmitted = StrEnd+1;
+ break;
+ }
+
+ const char *IDStart = LastEmitted;
+ const char *IDEnd = IDStart;
+ while (*IDEnd >= '0' && *IDEnd <= '9') ++IDEnd;
+
+ unsigned Val;
+ if (StringRef(IDStart, IDEnd-IDStart).getAsInteger(10, Val))
+ report_fatal_error("Bad $ operand number in inline asm string: '" +
+ Twine(AsmStr) + "'");
+ LastEmitted = IDEnd;
+
+ char Modifier[2] = { 0, 0 };
+
+ if (HasCurlyBraces) {
+ // If we have curly braces, check for a modifier character. This
+ // supports syntax like ${0:u}, which correspond to "%u0" in GCC asm.
+ if (*LastEmitted == ':') {
+ ++LastEmitted; // Consume ':' character.
+ if (*LastEmitted == 0)
+ report_fatal_error("Bad ${:} expression in inline asm string: '" +
+ Twine(AsmStr) + "'");
+
+ Modifier[0] = *LastEmitted;
+ ++LastEmitted; // Consume modifier character.
+ }
+
+ if (*LastEmitted != '}')
+ report_fatal_error("Bad ${} expression in inline asm string: '" +
+ Twine(AsmStr) + "'");
+ ++LastEmitted; // Consume '}' character.
+ }
+
+ if (Val >= NumOperands-1)
+ report_fatal_error("Invalid $ operand number in inline asm string: '" +
+ Twine(AsmStr) + "'");
+
+ // Okay, we finally have a value number. Ask the target to print this
+ // operand!
+ if (CurVariant == -1 || CurVariant == AsmPrinterVariant) {
+ unsigned OpNo = InlineAsm::MIOp_FirstOperand;
+
+ bool Error = false;
+
+ // Scan to find the machine operand number for the operand.
+ for (; Val; --Val) {
+ if (OpNo >= MI->getNumOperands()) break;
+ unsigned OpFlags = MI->getOperand(OpNo).getImm();
+ OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
+ }
+
+ // We may have a location metadata attached to the end of the
+ // instruction, and at no point should see metadata at any
+ // other point while processing. It's an error if so.
+ if (OpNo >= MI->getNumOperands() ||
+ MI->getOperand(OpNo).isMetadata()) {
+ Error = true;
+ } else {
+ unsigned OpFlags = MI->getOperand(OpNo).getImm();
+ ++OpNo; // Skip over the ID number.
+
+ if (Modifier[0] == 'l') { // Labels are target independent.
+ // FIXME: What if the operand isn't an MBB, report error?
+ const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol();
+ Sym->print(OS, AP->MAI);
+ } else {
+ if (InlineAsm::isMemKind(OpFlags)) {
+ Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant,
+ Modifier[0] ? Modifier : nullptr,
+ OS);
+ } else {
+ Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant,
+ Modifier[0] ? Modifier : nullptr, OS);
+ }
+ }
+ }
+ if (Error) {
+ std::string msg;
+ raw_string_ostream Msg(msg);
+ Msg << "invalid operand in inline asm: '" << AsmStr << "'";
+ MMI->getModule()->getContext().emitError(LocCookie, Msg.str());
+ }
+ }
+ break;
+ }
+ }
+ }
+ OS << '\n' << (char)0; // null terminate string.
+}
+
+/// EmitInlineAsm - This method formats and emits the specified machine
+/// instruction that is an inline asm.
+void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const {
+ assert(MI->isInlineAsm() && "printInlineAsm only works on inline asms");
+
+ // Count the number of register definitions to find the asm string.
+ unsigned NumDefs = 0;
+ for (; MI->getOperand(NumDefs).isReg() && MI->getOperand(NumDefs).isDef();
+ ++NumDefs)
+ assert(NumDefs != MI->getNumOperands()-2 && "No asm string?");
+
+ assert(MI->getOperand(NumDefs).isSymbol() && "No asm string?");
+
+ // Disassemble the AsmStr, printing out the literal pieces, the operands, etc.
+ const char *AsmStr = MI->getOperand(NumDefs).getSymbolName();
+
+ // If this asmstr is empty, just print the #APP/#NOAPP markers.
+ // These are useful to see where empty asm's wound up.
+ if (AsmStr[0] == 0) {
+ OutStreamer->emitRawComment(MAI->getInlineAsmStart());
+ OutStreamer->emitRawComment(MAI->getInlineAsmEnd());
+ return;
+ }
+
+ // Emit the #APP start marker. This has to happen even if verbose-asm isn't
+ // enabled, so we use emitRawComment.
+ OutStreamer->emitRawComment(MAI->getInlineAsmStart());
+
+ // Get the !srcloc metadata node if we have it, and decode the loc cookie from
+ // it.
+ unsigned LocCookie = 0;
+ const MDNode *LocMD = nullptr;
+ for (unsigned i = MI->getNumOperands(); i != 0; --i) {
+ if (MI->getOperand(i-1).isMetadata() &&
+ (LocMD = MI->getOperand(i-1).getMetadata()) &&
+ LocMD->getNumOperands() != 0) {
+ if (const ConstantInt *CI =
+ mdconst::dyn_extract<ConstantInt>(LocMD->getOperand(0))) {
+ LocCookie = CI->getZExtValue();
+ break;
+ }
+ }
+ }
+
+ // Emit the inline asm to a temporary string so we can emit it through
+ // EmitInlineAsm.
+ SmallString<256> StringData;
+ raw_svector_ostream OS(StringData);
+
+ // The variant of the current asmprinter.
+ int AsmPrinterVariant = MAI->getAssemblerDialect();
+ InlineAsm::AsmDialect InlineAsmVariant = MI->getInlineAsmDialect();
+ AsmPrinter *AP = const_cast<AsmPrinter*>(this);
+ if (InlineAsmVariant == InlineAsm::AD_ATT)
+ EmitGCCInlineAsmStr(AsmStr, MI, MMI, InlineAsmVariant, AsmPrinterVariant,
+ AP, LocCookie, OS);
+ else
+ EmitMSInlineAsmStr(AsmStr, MI, MMI, InlineAsmVariant, AP, LocCookie, OS);
+
+ // Reset SanitizeAddress based on the function's attribute.
+ MCTargetOptions MCOptions = TM.Options.MCOptions;
+ MCOptions.SanitizeAddress =
+ MF->getFunction()->hasFnAttribute(Attribute::SanitizeAddress);
+
+ EmitInlineAsm(OS.str(), getSubtargetInfo(), MCOptions, LocMD,
+ MI->getInlineAsmDialect());
+
+ // Emit the #NOAPP end marker. This has to happen even if verbose-asm isn't
+ // enabled, so we use emitRawComment.
+ OutStreamer->emitRawComment(MAI->getInlineAsmEnd());
+}
+
+
+/// PrintSpecial - Print information related to the specified machine instr
+/// that is independent of the operand, and may be independent of the instr
+/// itself. This can be useful for portably encoding the comment character
+/// or other bits of target-specific knowledge into the asmstrings. The
+/// syntax used is ${:comment}. Targets can override this to add support
+/// for their own strange codes.
+void AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS,
+ const char *Code) const {
+ if (!strcmp(Code, "private")) {
+ const DataLayout &DL = MF->getDataLayout();
+ OS << DL.getPrivateGlobalPrefix();
+ } else if (!strcmp(Code, "comment")) {
+ OS << MAI->getCommentString();
+ } else if (!strcmp(Code, "uid")) {
+ // Comparing the address of MI isn't sufficient, because machineinstrs may
+ // be allocated to the same address across functions.
+
+ // If this is a new LastFn instruction, bump the counter.
+ if (LastMI != MI || LastFn != getFunctionNumber()) {
+ ++Counter;
+ LastMI = MI;
+ LastFn = getFunctionNumber();
+ }
+ OS << Counter;
+ } else {
+ std::string msg;
+ raw_string_ostream Msg(msg);
+ Msg << "Unknown special formatter '" << Code
+ << "' for machine instr: " << *MI;
+ report_fatal_error(Msg.str());
+ }
+}
+
+/// PrintAsmOperand - Print the specified operand of MI, an INLINEASM
+/// instruction, using the specified assembler variant. Targets should
+/// override this to format as appropriate.
+bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+ unsigned AsmVariant, const char *ExtraCode,
+ raw_ostream &O) {
+ // Does this asm operand have a single letter operand modifier?
+ if (ExtraCode && ExtraCode[0]) {
+ if (ExtraCode[1] != 0) return true; // Unknown modifier.
+
+ const MachineOperand &MO = MI->getOperand(OpNo);
+ switch (ExtraCode[0]) {
+ default:
+ return true; // Unknown modifier.
+ case 'c': // Substitute immediate value without immediate syntax
+ if (MO.getType() != MachineOperand::MO_Immediate)
+ return true;
+ O << MO.getImm();
+ return false;
+ case 'n': // Negate the immediate constant.
+ if (MO.getType() != MachineOperand::MO_Immediate)
+ return true;
+ O << -MO.getImm();
+ return false;
+ }
+ }
+ return true;
+}
+
+bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
+ unsigned AsmVariant,
+ const char *ExtraCode, raw_ostream &O) {
+ // Target doesn't support this yet!
+ return true;
+}
+
+void AsmPrinter::emitInlineAsmStart() const {}
+
+void AsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
+ const MCSubtargetInfo *EndInfo) const {}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/ByteStreamer.h b/contrib/llvm/lib/CodeGen/AsmPrinter/ByteStreamer.h
new file mode 100644
index 0000000..df1997b
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/ByteStreamer.h
@@ -0,0 +1,111 @@
+//===-- llvm/CodeGen/ByteStreamer.h - ByteStreamer class --------*- 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 class that can take bytes that would normally be
+// streamed via the AsmPrinter.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_BYTESTREAMER_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_BYTESTREAMER_H
+
+#include "DIEHash.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/LEB128.h"
+#include <string>
+
+namespace llvm {
+class ByteStreamer {
+ protected:
+ ~ByteStreamer() = default;
+ ByteStreamer(const ByteStreamer&) = default;
+ ByteStreamer() = default;
+
+ public:
+ // For now we're just handling the calls we need for dwarf emission/hashing.
+ virtual void EmitInt8(uint8_t Byte, const Twine &Comment = "") = 0;
+ virtual void EmitSLEB128(uint64_t DWord, const Twine &Comment = "") = 0;
+ virtual void EmitULEB128(uint64_t DWord, const Twine &Comment = "") = 0;
+};
+
+class APByteStreamer final : public ByteStreamer {
+private:
+ AsmPrinter &AP;
+
+public:
+ APByteStreamer(AsmPrinter &Asm) : AP(Asm) {}
+ void EmitInt8(uint8_t Byte, const Twine &Comment) override {
+ AP.OutStreamer->AddComment(Comment);
+ AP.EmitInt8(Byte);
+ }
+ void EmitSLEB128(uint64_t DWord, const Twine &Comment) override {
+ AP.OutStreamer->AddComment(Comment);
+ AP.EmitSLEB128(DWord);
+ }
+ void EmitULEB128(uint64_t DWord, const Twine &Comment) override {
+ AP.OutStreamer->AddComment(Comment);
+ AP.EmitULEB128(DWord);
+ }
+};
+
+class HashingByteStreamer final : public ByteStreamer {
+ private:
+ DIEHash &Hash;
+ public:
+ HashingByteStreamer(DIEHash &H) : Hash(H) {}
+ void EmitInt8(uint8_t Byte, const Twine &Comment) override {
+ Hash.update(Byte);
+ }
+ void EmitSLEB128(uint64_t DWord, const Twine &Comment) override {
+ Hash.addSLEB128(DWord);
+ }
+ void EmitULEB128(uint64_t DWord, const Twine &Comment) override {
+ Hash.addULEB128(DWord);
+ }
+};
+
+class BufferByteStreamer final : public ByteStreamer {
+private:
+ SmallVectorImpl<char> &Buffer;
+ SmallVectorImpl<std::string> &Comments;
+
+ /// \brief Only verbose textual output needs comments. This will be set to
+ /// true for that case, and false otherwise. If false, comments passed in to
+ /// the emit methods will be ignored.
+ bool GenerateComments;
+
+public:
+ BufferByteStreamer(SmallVectorImpl<char> &Buffer,
+ SmallVectorImpl<std::string> &Comments,
+ bool GenerateComments)
+ : Buffer(Buffer), Comments(Comments), GenerateComments(GenerateComments) {}
+ void EmitInt8(uint8_t Byte, const Twine &Comment) override {
+ Buffer.push_back(Byte);
+ if (GenerateComments)
+ Comments.push_back(Comment.str());
+ }
+ void EmitSLEB128(uint64_t DWord, const Twine &Comment) override {
+ raw_svector_ostream OSE(Buffer);
+ encodeSLEB128(DWord, OSE);
+ if (GenerateComments)
+ Comments.push_back(Comment.str());
+ }
+ void EmitULEB128(uint64_t DWord, const Twine &Comment) override {
+ raw_svector_ostream OSE(Buffer);
+ encodeULEB128(DWord, OSE);
+ if (GenerateComments)
+ Comments.push_back(Comment.str());
+ }
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp
new file mode 100644
index 0000000..bf794f7
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp
@@ -0,0 +1,614 @@
+//===--- lib/CodeGen/DIE.cpp - DWARF Info Entries -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Data structures for DWARF info entries.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/DIE.h"
+#include "DwarfCompileUnit.h"
+#include "DwarfDebug.h"
+#include "DwarfUnit.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/LEB128.h"
+#include "llvm/Support/MD5.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// DIEAbbrevData Implementation
+//===----------------------------------------------------------------------===//
+
+/// Profile - Used to gather unique data for the abbreviation folding set.
+///
+void DIEAbbrevData::Profile(FoldingSetNodeID &ID) const {
+ // Explicitly cast to an integer type for which FoldingSetNodeID has
+ // overloads. Otherwise MSVC 2010 thinks this call is ambiguous.
+ ID.AddInteger(unsigned(Attribute));
+ ID.AddInteger(unsigned(Form));
+}
+
+//===----------------------------------------------------------------------===//
+// DIEAbbrev Implementation
+//===----------------------------------------------------------------------===//
+
+/// Profile - Used to gather unique data for the abbreviation folding set.
+///
+void DIEAbbrev::Profile(FoldingSetNodeID &ID) const {
+ ID.AddInteger(unsigned(Tag));
+ ID.AddInteger(unsigned(Children));
+
+ // For each attribute description.
+ for (unsigned i = 0, N = Data.size(); i < N; ++i)
+ Data[i].Profile(ID);
+}
+
+/// Emit - Print the abbreviation using the specified asm printer.
+///
+void DIEAbbrev::Emit(const AsmPrinter *AP) const {
+ // Emit its Dwarf tag type.
+ AP->EmitULEB128(Tag, dwarf::TagString(Tag));
+
+ // Emit whether it has children DIEs.
+ AP->EmitULEB128((unsigned)Children, dwarf::ChildrenString(Children));
+
+ // For each attribute description.
+ for (unsigned i = 0, N = Data.size(); i < N; ++i) {
+ const DIEAbbrevData &AttrData = Data[i];
+
+ // Emit attribute type.
+ AP->EmitULEB128(AttrData.getAttribute(),
+ dwarf::AttributeString(AttrData.getAttribute()));
+
+ // Emit form type.
+ AP->EmitULEB128(AttrData.getForm(),
+ dwarf::FormEncodingString(AttrData.getForm()));
+ }
+
+ // Mark end of abbreviation.
+ AP->EmitULEB128(0, "EOM(1)");
+ AP->EmitULEB128(0, "EOM(2)");
+}
+
+LLVM_DUMP_METHOD
+void DIEAbbrev::print(raw_ostream &O) {
+ O << "Abbreviation @"
+ << format("0x%lx", (long)(intptr_t)this)
+ << " "
+ << dwarf::TagString(Tag)
+ << " "
+ << dwarf::ChildrenString(Children)
+ << '\n';
+
+ for (unsigned i = 0, N = Data.size(); i < N; ++i) {
+ O << " "
+ << dwarf::AttributeString(Data[i].getAttribute())
+ << " "
+ << dwarf::FormEncodingString(Data[i].getForm())
+ << '\n';
+ }
+}
+
+LLVM_DUMP_METHOD
+void DIEAbbrev::dump() { print(dbgs()); }
+
+DIEAbbrev DIE::generateAbbrev() const {
+ DIEAbbrev Abbrev(Tag, hasChildren());
+ for (const DIEValue &V : values())
+ Abbrev.AddAttribute(V.getAttribute(), V.getForm());
+ return Abbrev;
+}
+
+/// Climb up the parent chain to get the unit DIE to which this DIE
+/// belongs.
+const DIE *DIE::getUnit() const {
+ const DIE *Cu = getUnitOrNull();
+ assert(Cu && "We should not have orphaned DIEs.");
+ return Cu;
+}
+
+/// Climb up the parent chain to get the unit DIE this DIE belongs
+/// to. Return NULL if DIE is not added to an owner yet.
+const DIE *DIE::getUnitOrNull() const {
+ const DIE *p = this;
+ while (p) {
+ if (p->getTag() == dwarf::DW_TAG_compile_unit ||
+ p->getTag() == dwarf::DW_TAG_type_unit)
+ return p;
+ p = p->getParent();
+ }
+ return nullptr;
+}
+
+DIEValue DIE::findAttribute(dwarf::Attribute Attribute) const {
+ // Iterate through all the attributes until we find the one we're
+ // looking for, if we can't find it return NULL.
+ for (const auto &V : values())
+ if (V.getAttribute() == Attribute)
+ return V;
+ return DIEValue();
+}
+
+LLVM_DUMP_METHOD
+static void printValues(raw_ostream &O, const DIEValueList &Values,
+ StringRef Type, unsigned Size, unsigned IndentCount) {
+ O << Type << ": Size: " << Size << "\n";
+
+ unsigned I = 0;
+ const std::string Indent(IndentCount, ' ');
+ for (const auto &V : Values.values()) {
+ O << Indent;
+ O << "Blk[" << I++ << "]";
+ O << " " << dwarf::FormEncodingString(V.getForm()) << " ";
+ V.print(O);
+ O << "\n";
+ }
+}
+
+LLVM_DUMP_METHOD
+void DIE::print(raw_ostream &O, unsigned IndentCount) const {
+ const std::string Indent(IndentCount, ' ');
+ O << Indent << "Die: " << format("0x%lx", (long)(intptr_t) this)
+ << ", Offset: " << Offset << ", Size: " << Size << "\n";
+
+ O << Indent << dwarf::TagString(getTag()) << " "
+ << dwarf::ChildrenString(hasChildren()) << "\n";
+
+ IndentCount += 2;
+ for (const auto &V : values()) {
+ O << Indent;
+ O << dwarf::AttributeString(V.getAttribute());
+ O << " " << dwarf::FormEncodingString(V.getForm()) << " ";
+ V.print(O);
+ O << "\n";
+ }
+ IndentCount -= 2;
+
+ for (const auto &Child : children())
+ Child.print(O, IndentCount + 4);
+
+ O << "\n";
+}
+
+LLVM_DUMP_METHOD
+void DIE::dump() {
+ print(dbgs());
+}
+
+void DIEValue::EmitValue(const AsmPrinter *AP) const {
+ switch (Ty) {
+ case isNone:
+ llvm_unreachable("Expected valid DIEValue");
+#define HANDLE_DIEVALUE(T) \
+ case is##T: \
+ getDIE##T().EmitValue(AP, Form); \
+ break;
+#include "llvm/CodeGen/DIEValue.def"
+ }
+}
+
+unsigned DIEValue::SizeOf(const AsmPrinter *AP) const {
+ switch (Ty) {
+ case isNone:
+ llvm_unreachable("Expected valid DIEValue");
+#define HANDLE_DIEVALUE(T) \
+ case is##T: \
+ return getDIE##T().SizeOf(AP, Form);
+#include "llvm/CodeGen/DIEValue.def"
+ }
+ llvm_unreachable("Unknown DIE kind");
+}
+
+LLVM_DUMP_METHOD
+void DIEValue::print(raw_ostream &O) const {
+ switch (Ty) {
+ case isNone:
+ llvm_unreachable("Expected valid DIEValue");
+#define HANDLE_DIEVALUE(T) \
+ case is##T: \
+ getDIE##T().print(O); \
+ break;
+#include "llvm/CodeGen/DIEValue.def"
+ }
+}
+
+LLVM_DUMP_METHOD
+void DIEValue::dump() const {
+ print(dbgs());
+}
+
+//===----------------------------------------------------------------------===//
+// DIEInteger Implementation
+//===----------------------------------------------------------------------===//
+
+/// EmitValue - Emit integer of appropriate size.
+///
+void DIEInteger::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const {
+ unsigned Size = ~0U;
+ switch (Form) {
+ case dwarf::DW_FORM_flag_present:
+ // Emit something to keep the lines and comments in sync.
+ // FIXME: Is there a better way to do this?
+ Asm->OutStreamer->AddBlankLine();
+ return;
+ case dwarf::DW_FORM_flag: // Fall thru
+ case dwarf::DW_FORM_ref1: // Fall thru
+ case dwarf::DW_FORM_data1: Size = 1; break;
+ case dwarf::DW_FORM_ref2: // Fall thru
+ case dwarf::DW_FORM_data2: Size = 2; break;
+ case dwarf::DW_FORM_sec_offset: // Fall thru
+ case dwarf::DW_FORM_strp: // Fall thru
+ case dwarf::DW_FORM_ref4: // Fall thru
+ case dwarf::DW_FORM_data4: Size = 4; break;
+ case dwarf::DW_FORM_ref8: // Fall thru
+ case dwarf::DW_FORM_ref_sig8: // Fall thru
+ case dwarf::DW_FORM_data8: Size = 8; break;
+ case dwarf::DW_FORM_GNU_str_index: Asm->EmitULEB128(Integer); return;
+ case dwarf::DW_FORM_GNU_addr_index: Asm->EmitULEB128(Integer); return;
+ case dwarf::DW_FORM_udata: Asm->EmitULEB128(Integer); return;
+ case dwarf::DW_FORM_sdata: Asm->EmitSLEB128(Integer); return;
+ case dwarf::DW_FORM_addr:
+ Size = Asm->getPointerSize();
+ break;
+ case dwarf::DW_FORM_ref_addr:
+ Size = SizeOf(Asm, dwarf::DW_FORM_ref_addr);
+ break;
+ default: llvm_unreachable("DIE Value form not supported yet");
+ }
+ Asm->OutStreamer->EmitIntValue(Integer, Size);
+}
+
+/// SizeOf - Determine size of integer value in bytes.
+///
+unsigned DIEInteger::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
+ switch (Form) {
+ case dwarf::DW_FORM_flag_present: return 0;
+ case dwarf::DW_FORM_flag: // Fall thru
+ case dwarf::DW_FORM_ref1: // Fall thru
+ case dwarf::DW_FORM_data1: return sizeof(int8_t);
+ case dwarf::DW_FORM_ref2: // Fall thru
+ case dwarf::DW_FORM_data2: return sizeof(int16_t);
+ case dwarf::DW_FORM_sec_offset: // Fall thru
+ case dwarf::DW_FORM_strp: // Fall thru
+ case dwarf::DW_FORM_ref4: // Fall thru
+ case dwarf::DW_FORM_data4: return sizeof(int32_t);
+ case dwarf::DW_FORM_ref8: // Fall thru
+ case dwarf::DW_FORM_ref_sig8: // Fall thru
+ case dwarf::DW_FORM_data8: return sizeof(int64_t);
+ case dwarf::DW_FORM_GNU_str_index: return getULEB128Size(Integer);
+ case dwarf::DW_FORM_GNU_addr_index: return getULEB128Size(Integer);
+ case dwarf::DW_FORM_udata: return getULEB128Size(Integer);
+ case dwarf::DW_FORM_sdata: return getSLEB128Size(Integer);
+ case dwarf::DW_FORM_addr:
+ return AP->getPointerSize();
+ case dwarf::DW_FORM_ref_addr:
+ if (AP->OutStreamer->getContext().getDwarfVersion() == 2)
+ return AP->getPointerSize();
+ return sizeof(int32_t);
+ default: llvm_unreachable("DIE Value form not supported yet");
+ }
+}
+
+LLVM_DUMP_METHOD
+void DIEInteger::print(raw_ostream &O) const {
+ O << "Int: " << (int64_t)Integer << " 0x";
+ O.write_hex(Integer);
+}
+
+//===----------------------------------------------------------------------===//
+// DIEExpr Implementation
+//===----------------------------------------------------------------------===//
+
+/// EmitValue - Emit expression value.
+///
+void DIEExpr::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
+ AP->OutStreamer->EmitValue(Expr, SizeOf(AP, Form));
+}
+
+/// SizeOf - Determine size of expression value in bytes.
+///
+unsigned DIEExpr::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
+ if (Form == dwarf::DW_FORM_data4) return 4;
+ if (Form == dwarf::DW_FORM_sec_offset) return 4;
+ if (Form == dwarf::DW_FORM_strp) return 4;
+ return AP->getPointerSize();
+}
+
+LLVM_DUMP_METHOD
+void DIEExpr::print(raw_ostream &O) const { O << "Expr: " << *Expr; }
+
+//===----------------------------------------------------------------------===//
+// DIELabel Implementation
+//===----------------------------------------------------------------------===//
+
+/// EmitValue - Emit label value.
+///
+void DIELabel::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
+ AP->EmitLabelReference(Label, SizeOf(AP, Form),
+ Form == dwarf::DW_FORM_strp ||
+ Form == dwarf::DW_FORM_sec_offset ||
+ Form == dwarf::DW_FORM_ref_addr);
+}
+
+/// SizeOf - Determine size of label value in bytes.
+///
+unsigned DIELabel::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
+ if (Form == dwarf::DW_FORM_data4) return 4;
+ if (Form == dwarf::DW_FORM_sec_offset) return 4;
+ if (Form == dwarf::DW_FORM_strp) return 4;
+ return AP->getPointerSize();
+}
+
+LLVM_DUMP_METHOD
+void DIELabel::print(raw_ostream &O) const { O << "Lbl: " << Label->getName(); }
+
+//===----------------------------------------------------------------------===//
+// DIEDelta Implementation
+//===----------------------------------------------------------------------===//
+
+/// EmitValue - Emit delta value.
+///
+void DIEDelta::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
+ AP->EmitLabelDifference(LabelHi, LabelLo, SizeOf(AP, Form));
+}
+
+/// SizeOf - Determine size of delta value in bytes.
+///
+unsigned DIEDelta::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
+ if (Form == dwarf::DW_FORM_data4) return 4;
+ if (Form == dwarf::DW_FORM_sec_offset) return 4;
+ if (Form == dwarf::DW_FORM_strp) return 4;
+ return AP->getPointerSize();
+}
+
+LLVM_DUMP_METHOD
+void DIEDelta::print(raw_ostream &O) const {
+ O << "Del: " << LabelHi->getName() << "-" << LabelLo->getName();
+}
+
+//===----------------------------------------------------------------------===//
+// DIEString Implementation
+//===----------------------------------------------------------------------===//
+
+/// EmitValue - Emit string value.
+///
+void DIEString::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
+ assert(
+ (Form == dwarf::DW_FORM_strp || Form == dwarf::DW_FORM_GNU_str_index) &&
+ "Expected valid string form");
+
+ // Index of string in symbol table.
+ if (Form == dwarf::DW_FORM_GNU_str_index) {
+ DIEInteger(S.getIndex()).EmitValue(AP, Form);
+ return;
+ }
+
+ // Relocatable symbol.
+ assert(Form == dwarf::DW_FORM_strp);
+ if (AP->MAI->doesDwarfUseRelocationsAcrossSections()) {
+ DIELabel(S.getSymbol()).EmitValue(AP, Form);
+ return;
+ }
+
+ // Offset into symbol table.
+ DIEInteger(S.getOffset()).EmitValue(AP, Form);
+}
+
+/// SizeOf - Determine size of delta value in bytes.
+///
+unsigned DIEString::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
+ assert(
+ (Form == dwarf::DW_FORM_strp || Form == dwarf::DW_FORM_GNU_str_index) &&
+ "Expected valid string form");
+
+ // Index of string in symbol table.
+ if (Form == dwarf::DW_FORM_GNU_str_index)
+ return DIEInteger(S.getIndex()).SizeOf(AP, Form);
+
+ // Relocatable symbol.
+ if (AP->MAI->doesDwarfUseRelocationsAcrossSections())
+ return DIELabel(S.getSymbol()).SizeOf(AP, Form);
+
+ // Offset into symbol table.
+ return DIEInteger(S.getOffset()).SizeOf(AP, Form);
+}
+
+LLVM_DUMP_METHOD
+void DIEString::print(raw_ostream &O) const {
+ O << "String: " << S.getString();
+}
+
+//===----------------------------------------------------------------------===//
+// DIEEntry Implementation
+//===----------------------------------------------------------------------===//
+
+/// EmitValue - Emit debug information entry offset.
+///
+void DIEEntry::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
+
+ if (Form == dwarf::DW_FORM_ref_addr) {
+ const DwarfDebug *DD = AP->getDwarfDebug();
+ unsigned Addr = Entry->getOffset();
+ assert(!DD->useSplitDwarf() && "TODO: dwo files can't have relocations.");
+ // For DW_FORM_ref_addr, output the offset from beginning of debug info
+ // section. Entry->getOffset() returns the offset from start of the
+ // compile unit.
+ DwarfCompileUnit *CU = DD->lookupUnit(Entry->getUnit());
+ assert(CU && "CUDie should belong to a CU.");
+ Addr += CU->getDebugInfoOffset();
+ if (AP->MAI->doesDwarfUseRelocationsAcrossSections())
+ AP->EmitLabelPlusOffset(CU->getSectionSym(), Addr,
+ DIEEntry::getRefAddrSize(AP));
+ else
+ AP->OutStreamer->EmitIntValue(Addr, DIEEntry::getRefAddrSize(AP));
+ } else
+ AP->EmitInt32(Entry->getOffset());
+}
+
+unsigned DIEEntry::getRefAddrSize(const AsmPrinter *AP) {
+ // DWARF4: References that use the attribute form DW_FORM_ref_addr are
+ // specified to be four bytes in the DWARF 32-bit format and eight bytes
+ // in the DWARF 64-bit format, while DWARF Version 2 specifies that such
+ // references have the same size as an address on the target system.
+ const DwarfDebug *DD = AP->getDwarfDebug();
+ assert(DD && "Expected Dwarf Debug info to be available");
+ if (DD->getDwarfVersion() == 2)
+ return AP->getPointerSize();
+ return sizeof(int32_t);
+}
+
+LLVM_DUMP_METHOD
+void DIEEntry::print(raw_ostream &O) const {
+ O << format("Die: 0x%lx", (long)(intptr_t)&Entry);
+}
+
+//===----------------------------------------------------------------------===//
+// DIETypeSignature Implementation
+//===----------------------------------------------------------------------===//
+void DIETypeSignature::EmitValue(const AsmPrinter *Asm,
+ dwarf::Form Form) const {
+ assert(Form == dwarf::DW_FORM_ref_sig8);
+ Asm->OutStreamer->EmitIntValue(Unit->getTypeSignature(), 8);
+}
+
+LLVM_DUMP_METHOD
+void DIETypeSignature::print(raw_ostream &O) const {
+ O << format("Type Unit: 0x%lx", Unit->getTypeSignature());
+}
+
+//===----------------------------------------------------------------------===//
+// DIELoc Implementation
+//===----------------------------------------------------------------------===//
+
+/// ComputeSize - calculate the size of the location expression.
+///
+unsigned DIELoc::ComputeSize(const AsmPrinter *AP) const {
+ if (!Size) {
+ for (const auto &V : values())
+ Size += V.SizeOf(AP);
+ }
+
+ return Size;
+}
+
+/// EmitValue - Emit location data.
+///
+void DIELoc::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const {
+ switch (Form) {
+ default: llvm_unreachable("Improper form for block");
+ case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break;
+ case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break;
+ case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break;
+ case dwarf::DW_FORM_block:
+ case dwarf::DW_FORM_exprloc:
+ Asm->EmitULEB128(Size); break;
+ }
+
+ for (const auto &V : values())
+ V.EmitValue(Asm);
+}
+
+/// SizeOf - Determine size of location data in bytes.
+///
+unsigned DIELoc::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
+ switch (Form) {
+ case dwarf::DW_FORM_block1: return Size + sizeof(int8_t);
+ case dwarf::DW_FORM_block2: return Size + sizeof(int16_t);
+ case dwarf::DW_FORM_block4: return Size + sizeof(int32_t);
+ case dwarf::DW_FORM_block:
+ case dwarf::DW_FORM_exprloc:
+ return Size + getULEB128Size(Size);
+ default: llvm_unreachable("Improper form for block");
+ }
+}
+
+LLVM_DUMP_METHOD
+void DIELoc::print(raw_ostream &O) const {
+ printValues(O, *this, "ExprLoc", Size, 5);
+}
+
+//===----------------------------------------------------------------------===//
+// DIEBlock Implementation
+//===----------------------------------------------------------------------===//
+
+/// ComputeSize - calculate the size of the block.
+///
+unsigned DIEBlock::ComputeSize(const AsmPrinter *AP) const {
+ if (!Size) {
+ for (const auto &V : values())
+ Size += V.SizeOf(AP);
+ }
+
+ return Size;
+}
+
+/// EmitValue - Emit block data.
+///
+void DIEBlock::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const {
+ switch (Form) {
+ default: llvm_unreachable("Improper form for block");
+ case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break;
+ case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break;
+ case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break;
+ case dwarf::DW_FORM_block: Asm->EmitULEB128(Size); break;
+ }
+
+ for (const auto &V : values())
+ V.EmitValue(Asm);
+}
+
+/// SizeOf - Determine size of block data in bytes.
+///
+unsigned DIEBlock::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
+ switch (Form) {
+ case dwarf::DW_FORM_block1: return Size + sizeof(int8_t);
+ case dwarf::DW_FORM_block2: return Size + sizeof(int16_t);
+ case dwarf::DW_FORM_block4: return Size + sizeof(int32_t);
+ case dwarf::DW_FORM_block: return Size + getULEB128Size(Size);
+ default: llvm_unreachable("Improper form for block");
+ }
+}
+
+LLVM_DUMP_METHOD
+void DIEBlock::print(raw_ostream &O) const {
+ printValues(O, *this, "Blk", Size, 5);
+}
+
+//===----------------------------------------------------------------------===//
+// DIELocList Implementation
+//===----------------------------------------------------------------------===//
+
+unsigned DIELocList::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
+ if (Form == dwarf::DW_FORM_data4)
+ return 4;
+ if (Form == dwarf::DW_FORM_sec_offset)
+ return 4;
+ return AP->getPointerSize();
+}
+
+/// EmitValue - Emit label value.
+///
+void DIELocList::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
+ DwarfDebug *DD = AP->getDwarfDebug();
+ MCSymbol *Label = DD->getDebugLocs().getList(Index).Label;
+ AP->emitDwarfSymbolReference(Label, /*ForceOffset*/ DD->useSplitDwarf());
+}
+
+LLVM_DUMP_METHOD
+void DIELocList::print(raw_ostream &O) const { O << "LocList: " << Index; }
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp
new file mode 100644
index 0000000..0201065
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp
@@ -0,0 +1,515 @@
+//===-- llvm/CodeGen/DIEHash.cpp - Dwarf Hashing Framework ----------------===//
+//
+// 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 DWARF4 hashing of DIEs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ByteStreamer.h"
+#include "DIEHash.h"
+#include "DwarfDebug.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/DIE.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/MD5.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "dwarfdebug"
+
+/// \brief Grabs the string in whichever attribute is passed in and returns
+/// a reference to it.
+static StringRef getDIEStringAttr(const DIE &Die, uint16_t Attr) {
+ // Iterate through all the attributes until we find the one we're
+ // looking for, if we can't find it return an empty string.
+ for (const auto &V : Die.values())
+ if (V.getAttribute() == Attr)
+ return V.getDIEString().getString();
+
+ return StringRef("");
+}
+
+/// \brief Adds the string in \p Str to the hash. This also hashes
+/// a trailing NULL with the string.
+void DIEHash::addString(StringRef Str) {
+ DEBUG(dbgs() << "Adding string " << Str << " to hash.\n");
+ Hash.update(Str);
+ Hash.update(makeArrayRef((uint8_t)'\0'));
+}
+
+// FIXME: The LEB128 routines are copied and only slightly modified out of
+// LEB128.h.
+
+/// \brief Adds the unsigned in \p Value to the hash encoded as a ULEB128.
+void DIEHash::addULEB128(uint64_t Value) {
+ DEBUG(dbgs() << "Adding ULEB128 " << Value << " to hash.\n");
+ do {
+ uint8_t Byte = Value & 0x7f;
+ Value >>= 7;
+ if (Value != 0)
+ Byte |= 0x80; // Mark this byte to show that more bytes will follow.
+ Hash.update(Byte);
+ } while (Value != 0);
+}
+
+void DIEHash::addSLEB128(int64_t Value) {
+ DEBUG(dbgs() << "Adding ULEB128 " << Value << " to hash.\n");
+ bool More;
+ do {
+ uint8_t Byte = Value & 0x7f;
+ Value >>= 7;
+ More = !((((Value == 0) && ((Byte & 0x40) == 0)) ||
+ ((Value == -1) && ((Byte & 0x40) != 0))));
+ if (More)
+ Byte |= 0x80; // Mark this byte to show that more bytes will follow.
+ Hash.update(Byte);
+ } while (More);
+}
+
+/// \brief Including \p Parent adds the context of Parent to the hash..
+void DIEHash::addParentContext(const DIE &Parent) {
+
+ DEBUG(dbgs() << "Adding parent context to hash...\n");
+
+ // [7.27.2] For each surrounding type or namespace beginning with the
+ // outermost such construct...
+ SmallVector<const DIE *, 1> Parents;
+ const DIE *Cur = &Parent;
+ while (Cur->getParent()) {
+ Parents.push_back(Cur);
+ Cur = Cur->getParent();
+ }
+ assert(Cur->getTag() == dwarf::DW_TAG_compile_unit ||
+ Cur->getTag() == dwarf::DW_TAG_type_unit);
+
+ // Reverse iterate over our list to go from the outermost construct to the
+ // innermost.
+ for (SmallVectorImpl<const DIE *>::reverse_iterator I = Parents.rbegin(),
+ E = Parents.rend();
+ I != E; ++I) {
+ const DIE &Die = **I;
+
+ // ... Append the letter "C" to the sequence...
+ addULEB128('C');
+
+ // ... Followed by the DWARF tag of the construct...
+ addULEB128(Die.getTag());
+
+ // ... Then the name, taken from the DW_AT_name attribute.
+ StringRef Name = getDIEStringAttr(Die, dwarf::DW_AT_name);
+ DEBUG(dbgs() << "... adding context: " << Name << "\n");
+ if (!Name.empty())
+ addString(Name);
+ }
+}
+
+// Collect all of the attributes for a particular DIE in single structure.
+void DIEHash::collectAttributes(const DIE &Die, DIEAttrs &Attrs) {
+#define COLLECT_ATTR(NAME) \
+ case dwarf::NAME: \
+ Attrs.NAME = V; \
+ break
+
+ for (const auto &V : Die.values()) {
+ DEBUG(dbgs() << "Attribute: "
+ << dwarf::AttributeString(V.getAttribute())
+ << " added.\n");
+ switch (V.getAttribute()) {
+ COLLECT_ATTR(DW_AT_name);
+ COLLECT_ATTR(DW_AT_accessibility);
+ COLLECT_ATTR(DW_AT_address_class);
+ COLLECT_ATTR(DW_AT_allocated);
+ COLLECT_ATTR(DW_AT_artificial);
+ COLLECT_ATTR(DW_AT_associated);
+ COLLECT_ATTR(DW_AT_binary_scale);
+ COLLECT_ATTR(DW_AT_bit_offset);
+ COLLECT_ATTR(DW_AT_bit_size);
+ COLLECT_ATTR(DW_AT_bit_stride);
+ COLLECT_ATTR(DW_AT_byte_size);
+ COLLECT_ATTR(DW_AT_byte_stride);
+ COLLECT_ATTR(DW_AT_const_expr);
+ COLLECT_ATTR(DW_AT_const_value);
+ COLLECT_ATTR(DW_AT_containing_type);
+ COLLECT_ATTR(DW_AT_count);
+ COLLECT_ATTR(DW_AT_data_bit_offset);
+ COLLECT_ATTR(DW_AT_data_location);
+ COLLECT_ATTR(DW_AT_data_member_location);
+ COLLECT_ATTR(DW_AT_decimal_scale);
+ COLLECT_ATTR(DW_AT_decimal_sign);
+ COLLECT_ATTR(DW_AT_default_value);
+ COLLECT_ATTR(DW_AT_digit_count);
+ COLLECT_ATTR(DW_AT_discr);
+ COLLECT_ATTR(DW_AT_discr_list);
+ COLLECT_ATTR(DW_AT_discr_value);
+ COLLECT_ATTR(DW_AT_encoding);
+ COLLECT_ATTR(DW_AT_enum_class);
+ COLLECT_ATTR(DW_AT_endianity);
+ COLLECT_ATTR(DW_AT_explicit);
+ COLLECT_ATTR(DW_AT_is_optional);
+ COLLECT_ATTR(DW_AT_location);
+ COLLECT_ATTR(DW_AT_lower_bound);
+ COLLECT_ATTR(DW_AT_mutable);
+ COLLECT_ATTR(DW_AT_ordering);
+ COLLECT_ATTR(DW_AT_picture_string);
+ COLLECT_ATTR(DW_AT_prototyped);
+ COLLECT_ATTR(DW_AT_small);
+ COLLECT_ATTR(DW_AT_segment);
+ COLLECT_ATTR(DW_AT_string_length);
+ COLLECT_ATTR(DW_AT_threads_scaled);
+ COLLECT_ATTR(DW_AT_upper_bound);
+ COLLECT_ATTR(DW_AT_use_location);
+ COLLECT_ATTR(DW_AT_use_UTF8);
+ COLLECT_ATTR(DW_AT_variable_parameter);
+ COLLECT_ATTR(DW_AT_virtuality);
+ COLLECT_ATTR(DW_AT_visibility);
+ COLLECT_ATTR(DW_AT_vtable_elem_location);
+ COLLECT_ATTR(DW_AT_type);
+ default:
+ break;
+ }
+ }
+}
+
+void DIEHash::hashShallowTypeReference(dwarf::Attribute Attribute,
+ const DIE &Entry, StringRef Name) {
+ // append the letter 'N'
+ addULEB128('N');
+
+ // the DWARF attribute code (DW_AT_type or DW_AT_friend),
+ addULEB128(Attribute);
+
+ // the context of the tag,
+ if (const DIE *Parent = Entry.getParent())
+ addParentContext(*Parent);
+
+ // the letter 'E',
+ addULEB128('E');
+
+ // and the name of the type.
+ addString(Name);
+
+ // Currently DW_TAG_friends are not used by Clang, but if they do become so,
+ // here's the relevant spec text to implement:
+ //
+ // For DW_TAG_friend, if the referenced entry is the DW_TAG_subprogram,
+ // the context is omitted and the name to be used is the ABI-specific name
+ // of the subprogram (e.g., the mangled linker name).
+}
+
+void DIEHash::hashRepeatedTypeReference(dwarf::Attribute Attribute,
+ unsigned DieNumber) {
+ // a) If T is in the list of [previously hashed types], use the letter
+ // 'R' as the marker
+ addULEB128('R');
+
+ addULEB128(Attribute);
+
+ // and use the unsigned LEB128 encoding of [the index of T in the
+ // list] as the attribute value;
+ addULEB128(DieNumber);
+}
+
+void DIEHash::hashDIEEntry(dwarf::Attribute Attribute, dwarf::Tag Tag,
+ const DIE &Entry) {
+ assert(Tag != dwarf::DW_TAG_friend && "No current LLVM clients emit friend "
+ "tags. Add support here when there's "
+ "a use case");
+ // Step 5
+ // If the tag in Step 3 is one of [the below tags]
+ if ((Tag == dwarf::DW_TAG_pointer_type ||
+ Tag == dwarf::DW_TAG_reference_type ||
+ Tag == dwarf::DW_TAG_rvalue_reference_type ||
+ Tag == dwarf::DW_TAG_ptr_to_member_type) &&
+ // and the referenced type (via the [below attributes])
+ // FIXME: This seems overly restrictive, and causes hash mismatches
+ // there's a decl/def difference in the containing type of a
+ // ptr_to_member_type, but it's what DWARF says, for some reason.
+ Attribute == dwarf::DW_AT_type) {
+ // ... has a DW_AT_name attribute,
+ StringRef Name = getDIEStringAttr(Entry, dwarf::DW_AT_name);
+ if (!Name.empty()) {
+ hashShallowTypeReference(Attribute, Entry, Name);
+ return;
+ }
+ }
+
+ unsigned &DieNumber = Numbering[&Entry];
+ if (DieNumber) {
+ hashRepeatedTypeReference(Attribute, DieNumber);
+ return;
+ }
+
+ // otherwise, b) use the letter 'T' as the marker, ...
+ addULEB128('T');
+
+ addULEB128(Attribute);
+
+ // ... process the type T recursively by performing Steps 2 through 7, and
+ // use the result as the attribute value.
+ DieNumber = Numbering.size();
+ computeHash(Entry);
+}
+
+// Hash all of the values in a block like set of values. This assumes that
+// all of the data is going to be added as integers.
+void DIEHash::hashBlockData(const DIE::const_value_range &Values) {
+ for (const auto &V : Values)
+ Hash.update((uint64_t)V.getDIEInteger().getValue());
+}
+
+// Hash the contents of a loclistptr class.
+void DIEHash::hashLocList(const DIELocList &LocList) {
+ HashingByteStreamer Streamer(*this);
+ DwarfDebug &DD = *AP->getDwarfDebug();
+ const DebugLocStream &Locs = DD.getDebugLocs();
+ for (const auto &Entry : Locs.getEntries(Locs.getList(LocList.getValue())))
+ DD.emitDebugLocEntry(Streamer, Entry);
+}
+
+// Hash an individual attribute \param Attr based on the type of attribute and
+// the form.
+void DIEHash::hashAttribute(DIEValue Value, dwarf::Tag Tag) {
+ dwarf::Attribute Attribute = Value.getAttribute();
+
+ // Other attribute values use the letter 'A' as the marker, and the value
+ // consists of the form code (encoded as an unsigned LEB128 value) followed by
+ // the encoding of the value according to the form code. To ensure
+ // reproducibility of the signature, the set of forms used in the signature
+ // computation is limited to the following: DW_FORM_sdata, DW_FORM_flag,
+ // DW_FORM_string, and DW_FORM_block.
+
+ switch (Value.getType()) {
+ case DIEValue::isNone:
+ llvm_unreachable("Expected valid DIEValue");
+
+ // 7.27 Step 3
+ // ... An attribute that refers to another type entry T is processed as
+ // follows:
+ case DIEValue::isEntry:
+ hashDIEEntry(Attribute, Tag, Value.getDIEEntry().getEntry());
+ break;
+ case DIEValue::isInteger: {
+ addULEB128('A');
+ addULEB128(Attribute);
+ switch (Value.getForm()) {
+ case dwarf::DW_FORM_data1:
+ case dwarf::DW_FORM_data2:
+ case dwarf::DW_FORM_data4:
+ case dwarf::DW_FORM_data8:
+ case dwarf::DW_FORM_udata:
+ case dwarf::DW_FORM_sdata:
+ addULEB128(dwarf::DW_FORM_sdata);
+ addSLEB128((int64_t)Value.getDIEInteger().getValue());
+ break;
+ // DW_FORM_flag_present is just flag with a value of one. We still give it a
+ // value so just use the value.
+ case dwarf::DW_FORM_flag_present:
+ case dwarf::DW_FORM_flag:
+ addULEB128(dwarf::DW_FORM_flag);
+ addULEB128((int64_t)Value.getDIEInteger().getValue());
+ break;
+ default:
+ llvm_unreachable("Unknown integer form!");
+ }
+ break;
+ }
+ case DIEValue::isString:
+ addULEB128('A');
+ addULEB128(Attribute);
+ addULEB128(dwarf::DW_FORM_string);
+ addString(Value.getDIEString().getString());
+ break;
+ case DIEValue::isBlock:
+ case DIEValue::isLoc:
+ case DIEValue::isLocList:
+ addULEB128('A');
+ addULEB128(Attribute);
+ addULEB128(dwarf::DW_FORM_block);
+ if (Value.getType() == DIEValue::isBlock) {
+ addULEB128(Value.getDIEBlock().ComputeSize(AP));
+ hashBlockData(Value.getDIEBlock().values());
+ } else if (Value.getType() == DIEValue::isLoc) {
+ addULEB128(Value.getDIELoc().ComputeSize(AP));
+ hashBlockData(Value.getDIELoc().values());
+ } else {
+ // We could add the block length, but that would take
+ // a bit of work and not add a lot of uniqueness
+ // to the hash in some way we could test.
+ hashLocList(Value.getDIELocList());
+ }
+ break;
+ // FIXME: It's uncertain whether or not we should handle this at the moment.
+ case DIEValue::isExpr:
+ case DIEValue::isLabel:
+ case DIEValue::isDelta:
+ case DIEValue::isTypeSignature:
+ llvm_unreachable("Add support for additional value types.");
+ }
+}
+
+// Go through the attributes from \param Attrs in the order specified in 7.27.4
+// and hash them.
+void DIEHash::hashAttributes(const DIEAttrs &Attrs, dwarf::Tag Tag) {
+#define ADD_ATTR(ATTR) \
+ { \
+ if (ATTR) \
+ hashAttribute(ATTR, Tag); \
+ }
+
+ ADD_ATTR(Attrs.DW_AT_name);
+ ADD_ATTR(Attrs.DW_AT_accessibility);
+ ADD_ATTR(Attrs.DW_AT_address_class);
+ ADD_ATTR(Attrs.DW_AT_allocated);
+ ADD_ATTR(Attrs.DW_AT_artificial);
+ ADD_ATTR(Attrs.DW_AT_associated);
+ ADD_ATTR(Attrs.DW_AT_binary_scale);
+ ADD_ATTR(Attrs.DW_AT_bit_offset);
+ ADD_ATTR(Attrs.DW_AT_bit_size);
+ ADD_ATTR(Attrs.DW_AT_bit_stride);
+ ADD_ATTR(Attrs.DW_AT_byte_size);
+ ADD_ATTR(Attrs.DW_AT_byte_stride);
+ ADD_ATTR(Attrs.DW_AT_const_expr);
+ ADD_ATTR(Attrs.DW_AT_const_value);
+ ADD_ATTR(Attrs.DW_AT_containing_type);
+ ADD_ATTR(Attrs.DW_AT_count);
+ ADD_ATTR(Attrs.DW_AT_data_bit_offset);
+ ADD_ATTR(Attrs.DW_AT_data_location);
+ ADD_ATTR(Attrs.DW_AT_data_member_location);
+ ADD_ATTR(Attrs.DW_AT_decimal_scale);
+ ADD_ATTR(Attrs.DW_AT_decimal_sign);
+ ADD_ATTR(Attrs.DW_AT_default_value);
+ ADD_ATTR(Attrs.DW_AT_digit_count);
+ ADD_ATTR(Attrs.DW_AT_discr);
+ ADD_ATTR(Attrs.DW_AT_discr_list);
+ ADD_ATTR(Attrs.DW_AT_discr_value);
+ ADD_ATTR(Attrs.DW_AT_encoding);
+ ADD_ATTR(Attrs.DW_AT_enum_class);
+ ADD_ATTR(Attrs.DW_AT_endianity);
+ ADD_ATTR(Attrs.DW_AT_explicit);
+ ADD_ATTR(Attrs.DW_AT_is_optional);
+ ADD_ATTR(Attrs.DW_AT_location);
+ ADD_ATTR(Attrs.DW_AT_lower_bound);
+ ADD_ATTR(Attrs.DW_AT_mutable);
+ ADD_ATTR(Attrs.DW_AT_ordering);
+ ADD_ATTR(Attrs.DW_AT_picture_string);
+ ADD_ATTR(Attrs.DW_AT_prototyped);
+ ADD_ATTR(Attrs.DW_AT_small);
+ ADD_ATTR(Attrs.DW_AT_segment);
+ ADD_ATTR(Attrs.DW_AT_string_length);
+ ADD_ATTR(Attrs.DW_AT_threads_scaled);
+ ADD_ATTR(Attrs.DW_AT_upper_bound);
+ ADD_ATTR(Attrs.DW_AT_use_location);
+ ADD_ATTR(Attrs.DW_AT_use_UTF8);
+ ADD_ATTR(Attrs.DW_AT_variable_parameter);
+ ADD_ATTR(Attrs.DW_AT_virtuality);
+ ADD_ATTR(Attrs.DW_AT_visibility);
+ ADD_ATTR(Attrs.DW_AT_vtable_elem_location);
+ ADD_ATTR(Attrs.DW_AT_type);
+
+ // FIXME: Add the extended attributes.
+}
+
+// Add all of the attributes for \param Die to the hash.
+void DIEHash::addAttributes(const DIE &Die) {
+ DIEAttrs Attrs = {};
+ collectAttributes(Die, Attrs);
+ hashAttributes(Attrs, Die.getTag());
+}
+
+void DIEHash::hashNestedType(const DIE &Die, StringRef Name) {
+ // 7.27 Step 7
+ // ... append the letter 'S',
+ addULEB128('S');
+
+ // the tag of C,
+ addULEB128(Die.getTag());
+
+ // and the name.
+ addString(Name);
+}
+
+// Compute the hash of a DIE. This is based on the type signature computation
+// given in section 7.27 of the DWARF4 standard. It is the md5 hash of a
+// flattened description of the DIE.
+void DIEHash::computeHash(const DIE &Die) {
+ // Append the letter 'D', followed by the DWARF tag of the DIE.
+ addULEB128('D');
+ addULEB128(Die.getTag());
+
+ // Add each of the attributes of the DIE.
+ addAttributes(Die);
+
+ // Then hash each of the children of the DIE.
+ for (auto &C : Die.children()) {
+ // 7.27 Step 7
+ // If C is a nested type entry or a member function entry, ...
+ if (isType(C.getTag()) || C.getTag() == dwarf::DW_TAG_subprogram) {
+ StringRef Name = getDIEStringAttr(C, dwarf::DW_AT_name);
+ // ... and has a DW_AT_name attribute
+ if (!Name.empty()) {
+ hashNestedType(C, Name);
+ continue;
+ }
+ }
+ computeHash(C);
+ }
+
+ // Following the last (or if there are no children), append a zero byte.
+ Hash.update(makeArrayRef((uint8_t)'\0'));
+}
+
+/// This is based on the type signature computation given in section 7.27 of the
+/// DWARF4 standard. It is an md5 hash of the flattened description of the DIE
+/// with the inclusion of the full CU and all top level CU entities.
+// TODO: Initialize the type chain at 0 instead of 1 for CU signatures.
+uint64_t DIEHash::computeCUSignature(const DIE &Die) {
+ Numbering.clear();
+ Numbering[&Die] = 1;
+
+ // Hash the DIE.
+ computeHash(Die);
+
+ // Now return the result.
+ MD5::MD5Result Result;
+ Hash.final(Result);
+
+ // ... take the least significant 8 bytes and return those. Our MD5
+ // implementation always returns its results in little endian, swap bytes
+ // appropriately.
+ return support::endian::read64le(Result + 8);
+}
+
+/// This is based on the type signature computation given in section 7.27 of the
+/// DWARF4 standard. It is an md5 hash of the flattened description of the DIE
+/// with the inclusion of additional forms not specifically called out in the
+/// standard.
+uint64_t DIEHash::computeTypeSignature(const DIE &Die) {
+ Numbering.clear();
+ Numbering[&Die] = 1;
+
+ if (const DIE *Parent = Die.getParent())
+ addParentContext(*Parent);
+
+ // Hash the DIE.
+ computeHash(Die);
+
+ // Now return the result.
+ MD5::MD5Result Result;
+ Hash.final(Result);
+
+ // ... take the least significant 8 bytes and return those. Our MD5
+ // implementation always returns its results in little endian, swap bytes
+ // appropriately.
+ return support::endian::read64le(Result + 8);
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DIEHash.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DIEHash.h
new file mode 100644
index 0000000..44f0ce8
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DIEHash.h
@@ -0,0 +1,159 @@
+//===-- llvm/CodeGen/DIEHash.h - Dwarf Hashing 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 DWARF4 hashing of DIEs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DIEHASH_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_DIEHASH_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/CodeGen/DIE.h"
+#include "llvm/Support/MD5.h"
+
+namespace llvm {
+
+class AsmPrinter;
+class CompileUnit;
+
+/// \brief An object containing the capability of hashing and adding hash
+/// attributes onto a DIE.
+class DIEHash {
+ // Collection of all attributes used in hashing a particular DIE.
+ struct DIEAttrs {
+ DIEValue DW_AT_name;
+ DIEValue DW_AT_accessibility;
+ DIEValue DW_AT_address_class;
+ DIEValue DW_AT_allocated;
+ DIEValue DW_AT_artificial;
+ DIEValue DW_AT_associated;
+ DIEValue DW_AT_binary_scale;
+ DIEValue DW_AT_bit_offset;
+ DIEValue DW_AT_bit_size;
+ DIEValue DW_AT_bit_stride;
+ DIEValue DW_AT_byte_size;
+ DIEValue DW_AT_byte_stride;
+ DIEValue DW_AT_const_expr;
+ DIEValue DW_AT_const_value;
+ DIEValue DW_AT_containing_type;
+ DIEValue DW_AT_count;
+ DIEValue DW_AT_data_bit_offset;
+ DIEValue DW_AT_data_location;
+ DIEValue DW_AT_data_member_location;
+ DIEValue DW_AT_decimal_scale;
+ DIEValue DW_AT_decimal_sign;
+ DIEValue DW_AT_default_value;
+ DIEValue DW_AT_digit_count;
+ DIEValue DW_AT_discr;
+ DIEValue DW_AT_discr_list;
+ DIEValue DW_AT_discr_value;
+ DIEValue DW_AT_encoding;
+ DIEValue DW_AT_enum_class;
+ DIEValue DW_AT_endianity;
+ DIEValue DW_AT_explicit;
+ DIEValue DW_AT_is_optional;
+ DIEValue DW_AT_location;
+ DIEValue DW_AT_lower_bound;
+ DIEValue DW_AT_mutable;
+ DIEValue DW_AT_ordering;
+ DIEValue DW_AT_picture_string;
+ DIEValue DW_AT_prototyped;
+ DIEValue DW_AT_small;
+ DIEValue DW_AT_segment;
+ DIEValue DW_AT_string_length;
+ DIEValue DW_AT_threads_scaled;
+ DIEValue DW_AT_upper_bound;
+ DIEValue DW_AT_use_location;
+ DIEValue DW_AT_use_UTF8;
+ DIEValue DW_AT_variable_parameter;
+ DIEValue DW_AT_virtuality;
+ DIEValue DW_AT_visibility;
+ DIEValue DW_AT_vtable_elem_location;
+ DIEValue DW_AT_type;
+
+ // Insert any additional ones here...
+ };
+
+public:
+ DIEHash(AsmPrinter *A = nullptr) : AP(A) {}
+
+ /// \brief Computes the CU signature.
+ uint64_t computeCUSignature(const DIE &Die);
+
+ /// \brief Computes the type signature.
+ uint64_t computeTypeSignature(const DIE &Die);
+
+ // Helper routines to process parts of a DIE.
+private:
+ /// \brief Adds the parent context of \param Die to the hash.
+ void addParentContext(const DIE &Die);
+
+ /// \brief Adds the attributes of \param Die to the hash.
+ void addAttributes(const DIE &Die);
+
+ /// \brief Computes the full DWARF4 7.27 hash of the DIE.
+ void computeHash(const DIE &Die);
+
+ // Routines that add DIEValues to the hash.
+public:
+ /// \brief Adds \param Value to the hash.
+ void update(uint8_t Value) { Hash.update(Value); }
+
+ /// \brief Encodes and adds \param Value to the hash as a ULEB128.
+ void addULEB128(uint64_t Value);
+
+ /// \brief Encodes and adds \param Value to the hash as a SLEB128.
+ void addSLEB128(int64_t Value);
+
+private:
+ /// \brief Adds \param Str to the hash and includes a NULL byte.
+ void addString(StringRef Str);
+
+ /// \brief Collects the attributes of DIE \param Die into the \param Attrs
+ /// structure.
+ void collectAttributes(const DIE &Die, DIEAttrs &Attrs);
+
+ /// \brief Hashes the attributes in \param Attrs in order.
+ void hashAttributes(const DIEAttrs &Attrs, dwarf::Tag Tag);
+
+ /// \brief Hashes the data in a block like DIEValue, e.g. DW_FORM_block or
+ /// DW_FORM_exprloc.
+ void hashBlockData(const DIE::const_value_range &Values);
+
+ /// \brief Hashes the contents pointed to in the .debug_loc section.
+ void hashLocList(const DIELocList &LocList);
+
+ /// \brief Hashes an individual attribute.
+ void hashAttribute(DIEValue Value, dwarf::Tag Tag);
+
+ /// \brief Hashes an attribute that refers to another DIE.
+ void hashDIEEntry(dwarf::Attribute Attribute, dwarf::Tag Tag,
+ const DIE &Entry);
+
+ /// \brief Hashes a reference to a named type in such a way that is
+ /// independent of whether that type is described by a declaration or a
+ /// definition.
+ void hashShallowTypeReference(dwarf::Attribute Attribute, const DIE &Entry,
+ StringRef Name);
+
+ /// \brief Hashes a reference to a previously referenced type DIE.
+ void hashRepeatedTypeReference(dwarf::Attribute Attribute,
+ unsigned DieNumber);
+
+ void hashNestedType(const DIE &Die, StringRef Name);
+
+private:
+ MD5 Hash;
+ AsmPrinter *AP;
+ DenseMap<const DIE *, unsigned> Numbering;
+};
+}
+
+#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp
new file mode 100644
index 0000000..3c46a99
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp
@@ -0,0 +1,232 @@
+//===-- llvm/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DbgValueHistoryCalculator.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include <algorithm>
+#include <map>
+using namespace llvm;
+
+#define DEBUG_TYPE "dwarfdebug"
+
+// \brief If @MI is a DBG_VALUE with debug value described by a
+// defined register, returns the number of this register.
+// In the other case, returns 0.
+static unsigned isDescribedByReg(const MachineInstr &MI) {
+ assert(MI.isDebugValue());
+ assert(MI.getNumOperands() == 4);
+ // If location of variable is described using a register (directly or
+ // indirecltly), this register is always a first operand.
+ return MI.getOperand(0).isReg() ? MI.getOperand(0).getReg() : 0;
+}
+
+void DbgValueHistoryMap::startInstrRange(InlinedVariable Var,
+ const MachineInstr &MI) {
+ // Instruction range should start with a DBG_VALUE instruction for the
+ // variable.
+ assert(MI.isDebugValue() && "not a DBG_VALUE");
+ auto &Ranges = VarInstrRanges[Var];
+ if (!Ranges.empty() && Ranges.back().second == nullptr &&
+ Ranges.back().first->isIdenticalTo(&MI)) {
+ DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n"
+ << "\t" << Ranges.back().first << "\t" << MI << "\n");
+ return;
+ }
+ Ranges.push_back(std::make_pair(&MI, nullptr));
+}
+
+void DbgValueHistoryMap::endInstrRange(InlinedVariable Var,
+ const MachineInstr &MI) {
+ auto &Ranges = VarInstrRanges[Var];
+ // Verify that the current instruction range is not yet closed.
+ assert(!Ranges.empty() && Ranges.back().second == nullptr);
+ // For now, instruction ranges are not allowed to cross basic block
+ // boundaries.
+ assert(Ranges.back().first->getParent() == MI.getParent());
+ Ranges.back().second = &MI;
+}
+
+unsigned DbgValueHistoryMap::getRegisterForVar(InlinedVariable Var) const {
+ const auto &I = VarInstrRanges.find(Var);
+ if (I == VarInstrRanges.end())
+ return 0;
+ const auto &Ranges = I->second;
+ if (Ranges.empty() || Ranges.back().second != nullptr)
+ return 0;
+ return isDescribedByReg(*Ranges.back().first);
+}
+
+namespace {
+// Maps physreg numbers to the variables they describe.
+typedef DbgValueHistoryMap::InlinedVariable InlinedVariable;
+typedef std::map<unsigned, SmallVector<InlinedVariable, 1>> RegDescribedVarsMap;
+}
+
+// \brief Claim that @Var is not described by @RegNo anymore.
+static void dropRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo,
+ InlinedVariable Var) {
+ const auto &I = RegVars.find(RegNo);
+ assert(RegNo != 0U && I != RegVars.end());
+ auto &VarSet = I->second;
+ const auto &VarPos = std::find(VarSet.begin(), VarSet.end(), Var);
+ assert(VarPos != VarSet.end());
+ VarSet.erase(VarPos);
+ // Don't keep empty sets in a map to keep it as small as possible.
+ if (VarSet.empty())
+ RegVars.erase(I);
+}
+
+// \brief Claim that @Var is now described by @RegNo.
+static void addRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo,
+ InlinedVariable Var) {
+ assert(RegNo != 0U);
+ auto &VarSet = RegVars[RegNo];
+ assert(std::find(VarSet.begin(), VarSet.end(), Var) == VarSet.end());
+ VarSet.push_back(Var);
+}
+
+// \brief Terminate the location range for variables described by register at
+// @I by inserting @ClobberingInstr to their history.
+static void clobberRegisterUses(RegDescribedVarsMap &RegVars,
+ RegDescribedVarsMap::iterator I,
+ DbgValueHistoryMap &HistMap,
+ const MachineInstr &ClobberingInstr) {
+ // Iterate over all variables described by this register and add this
+ // instruction to their history, clobbering it.
+ for (const auto &Var : I->second)
+ HistMap.endInstrRange(Var, ClobberingInstr);
+ RegVars.erase(I);
+}
+
+// \brief Terminate the location range for variables described by register
+// @RegNo by inserting @ClobberingInstr to their history.
+static void clobberRegisterUses(RegDescribedVarsMap &RegVars, unsigned RegNo,
+ DbgValueHistoryMap &HistMap,
+ const MachineInstr &ClobberingInstr) {
+ const auto &I = RegVars.find(RegNo);
+ if (I == RegVars.end())
+ return;
+ clobberRegisterUses(RegVars, I, HistMap, ClobberingInstr);
+}
+
+// \brief Collect all registers clobbered by @MI and apply the functor
+// @Func to their RegNo.
+// @Func should be a functor with a void(unsigned) signature. We're
+// not using std::function here for performance reasons. It has a
+// small but measurable impact. By using a functor instead of a
+// std::set& here, we can avoid the overhead of constructing
+// temporaries in calculateDbgValueHistory, which has a significant
+// performance impact.
+template<typename Callable>
+static void applyToClobberedRegisters(const MachineInstr &MI,
+ const TargetRegisterInfo *TRI,
+ Callable Func) {
+ for (const MachineOperand &MO : MI.operands()) {
+ if (!MO.isReg() || !MO.isDef() || !MO.getReg())
+ continue;
+ for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); ++AI)
+ Func(*AI);
+ }
+}
+
+// \brief Returns the first instruction in @MBB which corresponds to
+// the function epilogue, or nullptr if @MBB doesn't contain an epilogue.
+static const MachineInstr *getFirstEpilogueInst(const MachineBasicBlock &MBB) {
+ auto LastMI = MBB.getLastNonDebugInstr();
+ if (LastMI == MBB.end() || !LastMI->isReturn())
+ return nullptr;
+ // Assume that epilogue starts with instruction having the same debug location
+ // as the return instruction.
+ DebugLoc LastLoc = LastMI->getDebugLoc();
+ auto Res = LastMI;
+ for (MachineBasicBlock::const_reverse_iterator I(std::next(LastMI)),
+ E = MBB.rend();
+ I != E; ++I) {
+ if (I->getDebugLoc() != LastLoc)
+ return Res;
+ Res = &*I;
+ }
+ // If all instructions have the same debug location, assume whole MBB is
+ // an epilogue.
+ return MBB.begin();
+}
+
+// \brief Collect registers that are modified in the function body (their
+// contents is changed outside of the prologue and epilogue).
+static void collectChangingRegs(const MachineFunction *MF,
+ const TargetRegisterInfo *TRI,
+ BitVector &Regs) {
+ for (const auto &MBB : *MF) {
+ auto FirstEpilogueInst = getFirstEpilogueInst(MBB);
+
+ for (const auto &MI : MBB) {
+ if (&MI == FirstEpilogueInst)
+ break;
+ if (!MI.getFlag(MachineInstr::FrameSetup))
+ applyToClobberedRegisters(MI, TRI, [&](unsigned r) { Regs.set(r); });
+ }
+ }
+}
+
+void llvm::calculateDbgValueHistory(const MachineFunction *MF,
+ const TargetRegisterInfo *TRI,
+ DbgValueHistoryMap &Result) {
+ BitVector ChangingRegs(TRI->getNumRegs());
+ collectChangingRegs(MF, TRI, ChangingRegs);
+
+ RegDescribedVarsMap RegVars;
+ for (const auto &MBB : *MF) {
+ for (const auto &MI : MBB) {
+ if (!MI.isDebugValue()) {
+ // Not a DBG_VALUE instruction. It may clobber registers which describe
+ // some variables.
+ applyToClobberedRegisters(MI, TRI, [&](unsigned RegNo) {
+ if (ChangingRegs.test(RegNo))
+ clobberRegisterUses(RegVars, RegNo, Result, MI);
+ });
+ 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);
+ }
+
+ // Make sure locations for register-described variables are valid only
+ // until the end of the basic block (unless it's the last basic block, in
+ // which case let their liveness run off to the end of the function).
+ if (!MBB.empty() && &MBB != &MF->back()) {
+ for (auto I = RegVars.begin(), E = RegVars.end(); I != E;) {
+ auto CurElem = I++; // CurElem can be erased below.
+ if (ChangingRegs.test(CurElem->first))
+ clobberRegisterUses(RegVars, CurElem, Result, MBB.back());
+ }
+ }
+ }
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h
new file mode 100644
index 0000000..546d1b4
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h
@@ -0,0 +1,60 @@
+//===-- 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"
+
+namespace llvm {
+
+class MachineFunction;
+class MachineInstr;
+class DILocalVariable;
+class DILocation;
+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:
+ typedef std::pair<const MachineInstr *, const MachineInstr *> InstrRange;
+ typedef SmallVector<InstrRange, 4> InstrRanges;
+ typedef std::pair<const DILocalVariable *, const DILocation *>
+ InlinedVariable;
+ typedef MapVector<InlinedVariable, InstrRanges> InstrRangesMap;
+
+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(); }
+};
+
+void calculateDbgValueHistory(const MachineFunction *MF,
+ const TargetRegisterInfo *TRI,
+ DbgValueHistoryMap &Result);
+}
+
+#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h
new file mode 100644
index 0000000..bbe5324
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h
@@ -0,0 +1,181 @@
+//===-- llvm/CodeGen/DebugLocEntry.h - Entry in debug_loc list -*- 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_DEBUGLOCENTRY_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H
+
+#include "DebugLocStream.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MachineLocation.h"
+
+namespace llvm {
+class AsmPrinter;
+
+/// \brief This struct describes location entries emitted in the .debug_loc
+/// section.
+class DebugLocEntry {
+ /// Begin and end symbols for the address range that this location is valid.
+ const MCSymbol *Begin;
+ const MCSymbol *End;
+
+public:
+ /// \brief A single location or constant.
+ struct Value {
+ Value(const DIExpression *Expr, int64_t i)
+ : Expression(Expr), EntryKind(E_Integer) {
+ Constant.Int = i;
+ }
+ Value(const DIExpression *Expr, const ConstantFP *CFP)
+ : Expression(Expr), EntryKind(E_ConstantFP) {
+ Constant.CFP = CFP;
+ }
+ Value(const DIExpression *Expr, const ConstantInt *CIP)
+ : Expression(Expr), EntryKind(E_ConstantInt) {
+ Constant.CIP = CIP;
+ }
+ Value(const DIExpression *Expr, MachineLocation Loc)
+ : Expression(Expr), EntryKind(E_Location), Loc(Loc) {
+ assert(cast<DIExpression>(Expr)->isValid());
+ }
+
+ /// Any complex address location expression for this Value.
+ const DIExpression *Expression;
+
+ /// Type of entry that this represents.
+ enum EntryType { E_Location, E_Integer, E_ConstantFP, E_ConstantInt };
+ enum EntryType EntryKind;
+
+ /// Either a constant,
+ union {
+ int64_t Int;
+ const ConstantFP *CFP;
+ const ConstantInt *CIP;
+ } Constant;
+
+ // Or a location in the machine frame.
+ MachineLocation Loc;
+
+ bool isLocation() const { return EntryKind == E_Location; }
+ bool isInt() const { return EntryKind == E_Integer; }
+ bool isConstantFP() const { return EntryKind == E_ConstantFP; }
+ bool isConstantInt() const { return EntryKind == E_ConstantInt; }
+ int64_t getInt() const { return Constant.Int; }
+ const ConstantFP *getConstantFP() const { return Constant.CFP; }
+ const ConstantInt *getConstantInt() const { return Constant.CIP; }
+ MachineLocation getLoc() const { return Loc; }
+ bool isBitPiece() const { return getExpression()->isBitPiece(); }
+ const DIExpression *getExpression() const { return Expression; }
+ friend bool operator==(const Value &, const Value &);
+ friend bool operator<(const Value &, const Value &);
+ };
+
+private:
+ /// A nonempty list of locations/constants belonging to this entry,
+ /// sorted by offset.
+ SmallVector<Value, 1> Values;
+
+public:
+ DebugLocEntry(const MCSymbol *B, const MCSymbol *E, Value Val)
+ : Begin(B), End(E) {
+ Values.push_back(std::move(Val));
+ }
+
+ /// \brief If this and Next are describing different pieces of the same
+ /// variable, merge them by appending Next's values to the current
+ /// list of values.
+ /// Return true if the merge was successful.
+ bool MergeValues(const DebugLocEntry &Next) {
+ if (Begin == Next.Begin) {
+ auto *Expr = cast_or_null<DIExpression>(Values[0].Expression);
+ auto *NextExpr = cast_or_null<DIExpression>(Next.Values[0].Expression);
+ if (Expr->isBitPiece() && NextExpr->isBitPiece()) {
+ addValues(Next.Values);
+ End = Next.End;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /// \brief Attempt to merge this DebugLocEntry with Next and return
+ /// true if the merge was successful. Entries can be merged if they
+ /// share the same Loc/Constant and if Next immediately follows this
+ /// Entry.
+ bool MergeRanges(const DebugLocEntry &Next) {
+ // If this and Next are describing the same variable, merge them.
+ if ((End == Next.Begin && Values == Next.Values)) {
+ End = Next.End;
+ return true;
+ }
+ return false;
+ }
+
+ const MCSymbol *getBeginSym() const { return Begin; }
+ const MCSymbol *getEndSym() const { return End; }
+ ArrayRef<Value> getValues() const { return Values; }
+ void addValues(ArrayRef<DebugLocEntry::Value> Vals) {
+ Values.append(Vals.begin(), Vals.end());
+ sortUniqueValues();
+ assert(std::all_of(Values.begin(), Values.end(), [](DebugLocEntry::Value V){
+ return V.isBitPiece();
+ }) && "value must be a piece");
+ }
+
+ // \brief Sort the pieces by offset.
+ // Remove any duplicate entries by dropping all but the first.
+ void sortUniqueValues() {
+ std::sort(Values.begin(), Values.end());
+ Values.erase(
+ std::unique(
+ Values.begin(), Values.end(), [](const Value &A, const Value &B) {
+ return A.getExpression() == B.getExpression();
+ }),
+ Values.end());
+ }
+
+ /// \brief Lower this entry into a DWARF expression.
+ void finalize(const AsmPrinter &AP, DebugLocStream::ListBuilder &List,
+ const DIBasicType *BT);
+};
+
+/// \brief Compare two Values for equality.
+inline bool operator==(const DebugLocEntry::Value &A,
+ const DebugLocEntry::Value &B) {
+ if (A.EntryKind != B.EntryKind)
+ return false;
+
+ if (A.Expression != B.Expression)
+ return false;
+
+ switch (A.EntryKind) {
+ case DebugLocEntry::Value::E_Location:
+ return A.Loc == B.Loc;
+ case DebugLocEntry::Value::E_Integer:
+ return A.Constant.Int == B.Constant.Int;
+ case DebugLocEntry::Value::E_ConstantFP:
+ return A.Constant.CFP == B.Constant.CFP;
+ case DebugLocEntry::Value::E_ConstantInt:
+ return A.Constant.CIP == B.Constant.CIP;
+ }
+ llvm_unreachable("unhandled EntryKind");
+}
+
+/// \brief Compare two pieces based on their offset.
+inline bool operator<(const DebugLocEntry::Value &A,
+ const DebugLocEntry::Value &B) {
+ return A.getExpression()->getBitPieceOffset() <
+ B.getExpression()->getBitPieceOffset();
+}
+
+}
+
+#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.cpp
new file mode 100644
index 0000000..7e8ed71
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.cpp
@@ -0,0 +1,46 @@
+//===- DebugLocStream.cpp - DWARF debug_loc stream --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DebugLocStream.h"
+#include "DwarfDebug.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+
+using namespace llvm;
+
+bool DebugLocStream::finalizeList(AsmPrinter &Asm) {
+ if (Lists.back().EntryOffset == Entries.size()) {
+ // Empty list. Delete it.
+ Lists.pop_back();
+ return false;
+ }
+
+ // Real list. Generate a label for it.
+ Lists.back().Label = Asm.createTempSymbol("debug_loc");
+ return true;
+}
+
+void DebugLocStream::finalizeEntry() {
+ if (Entries.back().ByteOffset != DWARFBytes.size())
+ return;
+
+ // The last entry was empty. Delete it.
+ Comments.erase(Comments.begin() + Entries.back().CommentOffset,
+ Comments.end());
+ Entries.pop_back();
+
+ assert(Lists.back().EntryOffset <= Entries.size() &&
+ "Popped off more entries than are in the list");
+}
+
+DebugLocStream::ListBuilder::~ListBuilder() {
+ if (!Locs.finalizeList(Asm))
+ return;
+ V.initializeDbgValue(&MI);
+ V.setDebugLocListIndex(ListIndex);
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h
new file mode 100644
index 0000000..3656e9d
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocStream.h
@@ -0,0 +1,193 @@
+//===--- lib/CodeGen/DebugLocStream.h - DWARF debug_loc stream --*- 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_DEBUGLOCSTREAM_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCSTREAM_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "ByteStreamer.h"
+
+namespace llvm {
+
+class AsmPrinter;
+class DbgVariable;
+class DwarfCompileUnit;
+class MachineInstr;
+class MCSymbol;
+
+/// \brief Byte stream of .debug_loc entries.
+///
+/// Stores a unified stream of .debug_loc entries. There's \a List for each
+/// variable/inlined-at pair, and an \a Entry for each \a DebugLocEntry.
+///
+/// FIXME: Do we need all these temp symbols?
+/// FIXME: Why not output directly to the output stream?
+class DebugLocStream {
+public:
+ struct List {
+ DwarfCompileUnit *CU;
+ MCSymbol *Label = nullptr;
+ size_t EntryOffset;
+ List(DwarfCompileUnit *CU, size_t EntryOffset)
+ : CU(CU), EntryOffset(EntryOffset) {}
+ };
+ struct Entry {
+ const MCSymbol *BeginSym;
+ const MCSymbol *EndSym;
+ size_t ByteOffset;
+ size_t CommentOffset;
+ Entry(const MCSymbol *BeginSym, const MCSymbol *EndSym, size_t ByteOffset,
+ size_t CommentOffset)
+ : BeginSym(BeginSym), EndSym(EndSym), ByteOffset(ByteOffset),
+ CommentOffset(CommentOffset) {}
+ };
+
+private:
+ SmallVector<List, 4> Lists;
+ SmallVector<Entry, 32> Entries;
+ SmallString<256> DWARFBytes;
+ SmallVector<std::string, 32> Comments;
+
+ /// \brief Only verbose textual output needs comments. This will be set to
+ /// true for that case, and false otherwise.
+ bool GenerateComments;
+
+public:
+ DebugLocStream(bool GenerateComments) : GenerateComments(GenerateComments) { }
+ size_t getNumLists() const { return Lists.size(); }
+ const List &getList(size_t LI) const { return Lists[LI]; }
+ ArrayRef<List> getLists() const { return Lists; }
+
+ class ListBuilder;
+ class EntryBuilder;
+
+private:
+ /// \brief Start a new .debug_loc entry list.
+ ///
+ /// Start a new .debug_loc entry list. Return the new list's index so it can
+ /// be retrieved later via \a getList().
+ ///
+ /// Until the next call, \a startEntry() will add entries to this list.
+ size_t startList(DwarfCompileUnit *CU) {
+ size_t LI = Lists.size();
+ Lists.emplace_back(CU, Entries.size());
+ return LI;
+ }
+
+ /// Finalize a .debug_loc entry list.
+ ///
+ /// If there are no entries in this list, delete it outright. Otherwise,
+ /// create a label with \a Asm.
+ ///
+ /// \return false iff the list is deleted.
+ bool finalizeList(AsmPrinter &Asm);
+
+ /// \brief Start a new .debug_loc entry.
+ ///
+ /// Until the next call, bytes added to the stream will be added to this
+ /// entry.
+ void startEntry(const MCSymbol *BeginSym, const MCSymbol *EndSym) {
+ Entries.emplace_back(BeginSym, EndSym, DWARFBytes.size(), Comments.size());
+ }
+
+ /// Finalize a .debug_loc entry, deleting if it's empty.
+ void finalizeEntry();
+
+public:
+ BufferByteStreamer getStreamer() {
+ return BufferByteStreamer(DWARFBytes, Comments, GenerateComments);
+ }
+
+ ArrayRef<Entry> getEntries(const List &L) const {
+ size_t LI = getIndex(L);
+ return makeArrayRef(Entries)
+ .slice(Lists[LI].EntryOffset, getNumEntries(LI));
+ }
+
+ ArrayRef<char> getBytes(const Entry &E) const {
+ size_t EI = getIndex(E);
+ return makeArrayRef(DWARFBytes.begin(), DWARFBytes.end())
+ .slice(Entries[EI].ByteOffset, getNumBytes(EI));
+ }
+ ArrayRef<std::string> getComments(const Entry &E) const {
+ size_t EI = getIndex(E);
+ return makeArrayRef(Comments)
+ .slice(Entries[EI].CommentOffset, getNumComments(EI));
+ }
+
+private:
+ size_t getIndex(const List &L) const {
+ assert(&Lists.front() <= &L && &L <= &Lists.back() &&
+ "Expected valid list");
+ return &L - &Lists.front();
+ }
+ size_t getIndex(const Entry &E) const {
+ assert(&Entries.front() <= &E && &E <= &Entries.back() &&
+ "Expected valid entry");
+ return &E - &Entries.front();
+ }
+ size_t getNumEntries(size_t LI) const {
+ if (LI + 1 == Lists.size())
+ return Entries.size() - Lists[LI].EntryOffset;
+ return Lists[LI + 1].EntryOffset - Lists[LI].EntryOffset;
+ }
+ size_t getNumBytes(size_t EI) const {
+ if (EI + 1 == Entries.size())
+ return DWARFBytes.size() - Entries[EI].ByteOffset;
+ return Entries[EI + 1].ByteOffset - Entries[EI].ByteOffset;
+ }
+ size_t getNumComments(size_t EI) const {
+ if (EI + 1 == Entries.size())
+ return Comments.size() - Entries[EI].CommentOffset;
+ return Entries[EI + 1].CommentOffset - Entries[EI].CommentOffset;
+ }
+};
+
+/// Builder for DebugLocStream lists.
+class DebugLocStream::ListBuilder {
+ DebugLocStream &Locs;
+ AsmPrinter &Asm;
+ DbgVariable &V;
+ const MachineInstr &MI;
+ size_t ListIndex;
+
+public:
+ ListBuilder(DebugLocStream &Locs, DwarfCompileUnit &CU, AsmPrinter &Asm,
+ DbgVariable &V, const MachineInstr &MI)
+ : Locs(Locs), Asm(Asm), V(V), MI(MI), ListIndex(Locs.startList(&CU)) {}
+
+ /// Finalize the list.
+ ///
+ /// If the list is empty, delete it. Otherwise, finalize it by creating a
+ /// temp symbol in \a Asm and setting up the \a DbgVariable.
+ ~ListBuilder();
+
+ DebugLocStream &getLocs() { return Locs; }
+};
+
+/// Builder for DebugLocStream entries.
+class DebugLocStream::EntryBuilder {
+ DebugLocStream &Locs;
+
+public:
+ EntryBuilder(ListBuilder &List, const MCSymbol *Begin, const MCSymbol *End)
+ : Locs(List.getLocs()) {
+ Locs.startEntry(Begin, End);
+ }
+
+ /// Finalize the entry, deleting it if it's empty.
+ ~EntryBuilder() { Locs.finalizeEntry(); }
+
+ BufferByteStreamer getStreamer() { return Locs.getStreamer(); }
+};
+
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp
new file mode 100644
index 0000000..4ad3e18
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp
@@ -0,0 +1,289 @@
+//=-- llvm/CodeGen/DwarfAccelTable.cpp - Dwarf Accelerator Tables -*- 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 dwarf accelerator tables.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DwarfAccelTable.h"
+#include "DwarfCompileUnit.h"
+#include "DwarfDebug.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/DIE.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+// The length of the header data is always going to be 4 + 4 + 4*NumAtoms.
+DwarfAccelTable::DwarfAccelTable(ArrayRef<DwarfAccelTable::Atom> atomList)
+ : Header(8 + (atomList.size() * 4)), HeaderData(atomList),
+ Entries(Allocator) {}
+
+void DwarfAccelTable::AddName(DwarfStringPoolEntryRef Name, const DIE *die,
+ char Flags) {
+ assert(Data.empty() && "Already finalized!");
+ // If the string is in the list already then add this die to the list
+ // otherwise add a new one.
+ DataArray &DIEs = Entries[Name.getString()];
+ assert(!DIEs.Name || DIEs.Name == Name);
+ DIEs.Name = Name;
+ DIEs.Values.push_back(new (Allocator) HashDataContents(die, Flags));
+}
+
+void DwarfAccelTable::ComputeBucketCount() {
+ // First get the number of unique hashes.
+ std::vector<uint32_t> uniques(Data.size());
+ for (size_t i = 0, e = Data.size(); i < e; ++i)
+ uniques[i] = Data[i]->HashValue;
+ array_pod_sort(uniques.begin(), uniques.end());
+ std::vector<uint32_t>::iterator p =
+ std::unique(uniques.begin(), uniques.end());
+ uint32_t num = std::distance(uniques.begin(), p);
+
+ // Then compute the bucket size, minimum of 1 bucket.
+ if (num > 1024)
+ Header.bucket_count = num / 4;
+ else if (num > 16)
+ Header.bucket_count = num / 2;
+ else
+ Header.bucket_count = num > 0 ? num : 1;
+
+ Header.hashes_count = num;
+}
+
+// compareDIEs - comparison predicate that sorts DIEs by their offset.
+static bool compareDIEs(const DwarfAccelTable::HashDataContents *A,
+ const DwarfAccelTable::HashDataContents *B) {
+ return A->Die->getOffset() < B->Die->getOffset();
+}
+
+void DwarfAccelTable::FinalizeTable(AsmPrinter *Asm, StringRef Prefix) {
+ // Create the individual hash data outputs.
+ Data.reserve(Entries.size());
+ for (StringMap<DataArray>::iterator EI = Entries.begin(), EE = Entries.end();
+ EI != EE; ++EI) {
+
+ // Unique the entries.
+ std::stable_sort(EI->second.Values.begin(), EI->second.Values.end(), compareDIEs);
+ EI->second.Values.erase(
+ std::unique(EI->second.Values.begin(), EI->second.Values.end()),
+ EI->second.Values.end());
+
+ HashData *Entry = new (Allocator) HashData(EI->getKey(), EI->second);
+ Data.push_back(Entry);
+ }
+
+ // Figure out how many buckets we need, then compute the bucket
+ // contents and the final ordering. We'll emit the hashes and offsets
+ // by doing a walk during the emission phase. We add temporary
+ // symbols to the data so that we can reference them during the offset
+ // later, we'll emit them when we emit the data.
+ ComputeBucketCount();
+
+ // Compute bucket contents and final ordering.
+ Buckets.resize(Header.bucket_count);
+ for (size_t i = 0, e = Data.size(); i < e; ++i) {
+ uint32_t bucket = Data[i]->HashValue % Header.bucket_count;
+ Buckets[bucket].push_back(Data[i]);
+ Data[i]->Sym = Asm->createTempSymbol(Prefix);
+ }
+
+ // Sort the contents of the buckets by hash value so that hash
+ // collisions end up together. Stable sort makes testing easier and
+ // doesn't cost much more.
+ for (size_t i = 0; i < Buckets.size(); ++i)
+ std::stable_sort(Buckets[i].begin(), Buckets[i].end(),
+ [] (HashData *LHS, HashData *RHS) {
+ return LHS->HashValue < RHS->HashValue;
+ });
+}
+
+// Emits the header for the table via the AsmPrinter.
+void DwarfAccelTable::EmitHeader(AsmPrinter *Asm) {
+ Asm->OutStreamer->AddComment("Header Magic");
+ Asm->EmitInt32(Header.magic);
+ Asm->OutStreamer->AddComment("Header Version");
+ Asm->EmitInt16(Header.version);
+ Asm->OutStreamer->AddComment("Header Hash Function");
+ Asm->EmitInt16(Header.hash_function);
+ Asm->OutStreamer->AddComment("Header Bucket Count");
+ Asm->EmitInt32(Header.bucket_count);
+ Asm->OutStreamer->AddComment("Header Hash Count");
+ Asm->EmitInt32(Header.hashes_count);
+ Asm->OutStreamer->AddComment("Header Data Length");
+ Asm->EmitInt32(Header.header_data_len);
+ Asm->OutStreamer->AddComment("HeaderData Die Offset Base");
+ Asm->EmitInt32(HeaderData.die_offset_base);
+ Asm->OutStreamer->AddComment("HeaderData Atom Count");
+ Asm->EmitInt32(HeaderData.Atoms.size());
+ for (size_t i = 0; i < HeaderData.Atoms.size(); i++) {
+ Atom A = HeaderData.Atoms[i];
+ Asm->OutStreamer->AddComment(dwarf::AtomTypeString(A.type));
+ Asm->EmitInt16(A.type);
+ Asm->OutStreamer->AddComment(dwarf::FormEncodingString(A.form));
+ Asm->EmitInt16(A.form);
+ }
+}
+
+// Walk through and emit the buckets for the table. Each index is
+// an offset into the list of hashes.
+void DwarfAccelTable::EmitBuckets(AsmPrinter *Asm) {
+ unsigned index = 0;
+ for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
+ Asm->OutStreamer->AddComment("Bucket " + Twine(i));
+ if (Buckets[i].size() != 0)
+ Asm->EmitInt32(index);
+ else
+ Asm->EmitInt32(UINT32_MAX);
+ // Buckets point in the list of hashes, not to the data. Do not
+ // increment the index multiple times in case of hash collisions.
+ uint64_t PrevHash = UINT64_MAX;
+ for (auto *HD : Buckets[i]) {
+ uint32_t HashValue = HD->HashValue;
+ if (PrevHash != HashValue)
+ ++index;
+ PrevHash = HashValue;
+ }
+ }
+}
+
+// Walk through the buckets and emit the individual hashes for each
+// bucket.
+void DwarfAccelTable::EmitHashes(AsmPrinter *Asm) {
+ uint64_t PrevHash = UINT64_MAX;
+ for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
+ for (HashList::const_iterator HI = Buckets[i].begin(),
+ HE = Buckets[i].end();
+ HI != HE; ++HI) {
+ uint32_t HashValue = (*HI)->HashValue;
+ if (PrevHash == HashValue)
+ continue;
+ Asm->OutStreamer->AddComment("Hash in Bucket " + Twine(i));
+ Asm->EmitInt32(HashValue);
+ PrevHash = HashValue;
+ }
+ }
+}
+
+// Walk through the buckets and emit the individual offsets for each
+// element in each bucket. This is done via a symbol subtraction from the
+// beginning of the section. The non-section symbol will be output later
+// when we emit the actual data.
+void DwarfAccelTable::emitOffsets(AsmPrinter *Asm, const MCSymbol *SecBegin) {
+ uint64_t PrevHash = UINT64_MAX;
+ for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
+ for (HashList::const_iterator HI = Buckets[i].begin(),
+ HE = Buckets[i].end();
+ HI != HE; ++HI) {
+ uint32_t HashValue = (*HI)->HashValue;
+ if (PrevHash == HashValue)
+ continue;
+ PrevHash = HashValue;
+ Asm->OutStreamer->AddComment("Offset in Bucket " + Twine(i));
+ MCContext &Context = Asm->OutStreamer->getContext();
+ const MCExpr *Sub = MCBinaryExpr::createSub(
+ MCSymbolRefExpr::create((*HI)->Sym, Context),
+ MCSymbolRefExpr::create(SecBegin, Context), Context);
+ Asm->OutStreamer->EmitValue(Sub, sizeof(uint32_t));
+ }
+ }
+}
+
+// Walk through the buckets and emit the full data for each element in
+// the bucket. For the string case emit the dies and the various offsets.
+// Terminate each HashData bucket with 0.
+void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfDebug *D) {
+ for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
+ uint64_t PrevHash = UINT64_MAX;
+ for (HashList::const_iterator HI = Buckets[i].begin(),
+ HE = Buckets[i].end();
+ HI != HE; ++HI) {
+ // Terminate the previous entry if there is no hash collision
+ // with the current one.
+ if (PrevHash != UINT64_MAX && PrevHash != (*HI)->HashValue)
+ Asm->EmitInt32(0);
+ // Remember to emit the label for our offset.
+ Asm->OutStreamer->EmitLabel((*HI)->Sym);
+ Asm->OutStreamer->AddComment((*HI)->Str);
+ Asm->emitDwarfStringOffset((*HI)->Data.Name);
+ Asm->OutStreamer->AddComment("Num DIEs");
+ Asm->EmitInt32((*HI)->Data.Values.size());
+ for (HashDataContents *HD : (*HI)->Data.Values) {
+ // Emit the DIE offset
+ DwarfCompileUnit *CU = D->lookupUnit(HD->Die->getUnit());
+ assert(CU && "Accelerated DIE should belong to a CU.");
+ Asm->EmitInt32(HD->Die->getOffset() + CU->getDebugInfoOffset());
+ // If we have multiple Atoms emit that info too.
+ // FIXME: A bit of a hack, we either emit only one atom or all info.
+ if (HeaderData.Atoms.size() > 1) {
+ Asm->EmitInt16(HD->Die->getTag());
+ Asm->EmitInt8(HD->Flags);
+ }
+ }
+ PrevHash = (*HI)->HashValue;
+ }
+ // Emit the final end marker for the bucket.
+ if (!Buckets[i].empty())
+ Asm->EmitInt32(0);
+ }
+}
+
+// Emit the entire data structure to the output file.
+void DwarfAccelTable::emit(AsmPrinter *Asm, const MCSymbol *SecBegin,
+ DwarfDebug *D) {
+ // Emit the header.
+ EmitHeader(Asm);
+
+ // Emit the buckets.
+ EmitBuckets(Asm);
+
+ // Emit the hashes.
+ EmitHashes(Asm);
+
+ // Emit the offsets.
+ emitOffsets(Asm, SecBegin);
+
+ // Emit the hash data.
+ EmitData(Asm, D);
+}
+
+#ifndef NDEBUG
+void DwarfAccelTable::print(raw_ostream &O) {
+
+ Header.print(O);
+ HeaderData.print(O);
+
+ O << "Entries: \n";
+ for (StringMap<DataArray>::const_iterator EI = Entries.begin(),
+ EE = Entries.end();
+ EI != EE; ++EI) {
+ O << "Name: " << EI->getKeyData() << "\n";
+ for (HashDataContents *HD : EI->second.Values)
+ HD->print(O);
+ }
+
+ O << "Buckets and Hashes: \n";
+ for (size_t i = 0, e = Buckets.size(); i < e; ++i)
+ for (HashList::const_iterator HI = Buckets[i].begin(),
+ HE = Buckets[i].end();
+ HI != HE; ++HI)
+ (*HI)->print(O);
+
+ O << "Data: \n";
+ for (std::vector<HashData *>::const_iterator DI = Data.begin(),
+ DE = Data.end();
+ DI != DE; ++DI)
+ (*DI)->print(O);
+}
+#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfAccelTable.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfAccelTable.h
new file mode 100644
index 0000000..4d81441
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfAccelTable.h
@@ -0,0 +1,256 @@
+//==-- llvm/CodeGen/DwarfAccelTable.h - Dwarf Accelerator Tables -*- 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 dwarf accelerator tables.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFACCELTABLE_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFACCELTABLE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/CodeGen/DIE.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/FormattedStream.h"
+#include <vector>
+
+// The dwarf accelerator tables are an indirect hash table optimized
+// for null lookup rather than access to known data. They are output into
+// an on-disk format that looks like this:
+//
+// .-------------.
+// | HEADER |
+// |-------------|
+// | BUCKETS |
+// |-------------|
+// | HASHES |
+// |-------------|
+// | OFFSETS |
+// |-------------|
+// | DATA |
+// `-------------'
+//
+// where the header contains a magic number, version, type of hash function,
+// the number of buckets, total number of hashes, and room for a special
+// struct of data and the length of that struct.
+//
+// The buckets contain an index (e.g. 6) into the hashes array. The hashes
+// section contains all of the 32-bit hash values in contiguous memory, and
+// the offsets contain the offset into the data area for the particular
+// hash.
+//
+// For a lookup example, we could hash a function name and take it modulo the
+// number of buckets giving us our bucket. From there we take the bucket value
+// as an index into the hashes table and look at each successive hash as long
+// as the hash value is still the same modulo result (bucket value) as earlier.
+// If we have a match we look at that same entry in the offsets table and
+// grab the offset in the data for our final match.
+
+namespace llvm {
+
+class AsmPrinter;
+class DwarfDebug;
+
+class DwarfAccelTable {
+
+ static uint32_t HashDJB(StringRef Str) {
+ uint32_t h = 5381;
+ for (unsigned i = 0, e = Str.size(); i != e; ++i)
+ h = ((h << 5) + h) + Str[i];
+ return h;
+ }
+
+ // Helper function to compute the number of buckets needed based on
+ // the number of unique hashes.
+ void ComputeBucketCount(void);
+
+ struct TableHeader {
+ uint32_t magic; // 'HASH' magic value to allow endian detection
+ uint16_t version; // Version number.
+ uint16_t hash_function; // The hash function enumeration that was used.
+ uint32_t bucket_count; // The number of buckets in this hash table.
+ uint32_t hashes_count; // The total number of unique hash values
+ // and hash data offsets in this table.
+ uint32_t header_data_len; // The bytes to skip to get to the hash
+ // indexes (buckets) for correct alignment.
+ // Also written to disk is the implementation specific header data.
+
+ static const uint32_t MagicHash = 0x48415348;
+
+ TableHeader(uint32_t data_len)
+ : magic(MagicHash), version(1),
+ hash_function(dwarf::DW_hash_function_djb), bucket_count(0),
+ hashes_count(0), header_data_len(data_len) {}
+
+#ifndef NDEBUG
+ void print(raw_ostream &O) {
+ O << "Magic: " << format("0x%x", magic) << "\n"
+ << "Version: " << version << "\n"
+ << "Hash Function: " << hash_function << "\n"
+ << "Bucket Count: " << bucket_count << "\n"
+ << "Header Data Length: " << header_data_len << "\n";
+ }
+ void dump() { print(dbgs()); }
+#endif
+ };
+
+public:
+ // The HeaderData describes the form of each set of data. In general this
+ // is as a list of atoms (atom_count) where each atom contains a type
+ // (AtomType type) of data, and an encoding form (form). In the case of
+ // data that is referenced via DW_FORM_ref_* the die_offset_base is
+ // used to describe the offset for all forms in the list of atoms.
+ // This also serves as a public interface of sorts.
+ // When written to disk this will have the form:
+ //
+ // uint32_t die_offset_base
+ // uint32_t atom_count
+ // atom_count Atoms
+
+ // Make these public so that they can be used as a general interface to
+ // the class.
+ struct Atom {
+ uint16_t type; // enum AtomType
+ uint16_t form; // DWARF DW_FORM_ defines
+
+ LLVM_CONSTEXPR Atom(uint16_t type, uint16_t form)
+ : type(type), form(form) {}
+#ifndef NDEBUG
+ void print(raw_ostream &O) {
+ O << "Type: " << dwarf::AtomTypeString(type) << "\n"
+ << "Form: " << dwarf::FormEncodingString(form) << "\n";
+ }
+ void dump() { print(dbgs()); }
+#endif
+ };
+
+private:
+ struct TableHeaderData {
+ uint32_t die_offset_base;
+ SmallVector<Atom, 3> Atoms;
+
+ TableHeaderData(ArrayRef<Atom> AtomList, uint32_t offset = 0)
+ : die_offset_base(offset), Atoms(AtomList.begin(), AtomList.end()) {}
+
+#ifndef NDEBUG
+ void print(raw_ostream &O) {
+ O << "die_offset_base: " << die_offset_base << "\n";
+ for (size_t i = 0; i < Atoms.size(); i++)
+ Atoms[i].print(O);
+ }
+ void dump() { print(dbgs()); }
+#endif
+ };
+
+ // The data itself consists of a str_offset, a count of the DIEs in the
+ // hash and the offsets to the DIEs themselves.
+ // On disk each data section is ended with a 0 KeyType as the end of the
+ // hash chain.
+ // On output this looks like:
+ // uint32_t str_offset
+ // uint32_t hash_data_count
+ // HashData[hash_data_count]
+public:
+ struct HashDataContents {
+ const DIE *Die; // Offsets
+ char Flags; // Specific flags to output
+
+ HashDataContents(const DIE *D, char Flags) : Die(D), Flags(Flags) {}
+#ifndef NDEBUG
+ void print(raw_ostream &O) const {
+ O << " Offset: " << Die->getOffset() << "\n";
+ O << " Tag: " << dwarf::TagString(Die->getTag()) << "\n";
+ O << " Flags: " << Flags << "\n";
+ }
+#endif
+ };
+
+private:
+ // String Data
+ struct DataArray {
+ DwarfStringPoolEntryRef Name;
+ std::vector<HashDataContents *> Values;
+ };
+ friend struct HashData;
+ struct HashData {
+ StringRef Str;
+ uint32_t HashValue;
+ MCSymbol *Sym;
+ DwarfAccelTable::DataArray &Data; // offsets
+ HashData(StringRef S, DwarfAccelTable::DataArray &Data)
+ : Str(S), Data(Data) {
+ HashValue = DwarfAccelTable::HashDJB(S);
+ }
+#ifndef NDEBUG
+ void print(raw_ostream &O) {
+ O << "Name: " << Str << "\n";
+ O << " Hash Value: " << format("0x%x", HashValue) << "\n";
+ O << " Symbol: ";
+ if (Sym)
+ O << *Sym;
+ else
+ O << "<none>";
+ O << "\n";
+ for (HashDataContents *C : Data.Values) {
+ O << " Offset: " << C->Die->getOffset() << "\n";
+ O << " Tag: " << dwarf::TagString(C->Die->getTag()) << "\n";
+ O << " Flags: " << C->Flags << "\n";
+ }
+ }
+ void dump() { print(dbgs()); }
+#endif
+ };
+
+ DwarfAccelTable(const DwarfAccelTable &) = delete;
+ void operator=(const DwarfAccelTable &) = delete;
+
+ // Internal Functions
+ void EmitHeader(AsmPrinter *);
+ void EmitBuckets(AsmPrinter *);
+ void EmitHashes(AsmPrinter *);
+ void emitOffsets(AsmPrinter *, const MCSymbol *);
+ void EmitData(AsmPrinter *, DwarfDebug *D);
+
+ // Allocator for HashData and HashDataContents.
+ BumpPtrAllocator Allocator;
+
+ // Output Variables
+ TableHeader Header;
+ TableHeaderData HeaderData;
+ std::vector<HashData *> Data;
+
+ typedef StringMap<DataArray, BumpPtrAllocator &> StringEntries;
+ StringEntries Entries;
+
+ // Buckets/Hashes/Offsets
+ typedef std::vector<HashData *> HashList;
+ typedef std::vector<HashList> BucketList;
+ BucketList Buckets;
+ HashList Hashes;
+
+ // Public Implementation
+public:
+ DwarfAccelTable(ArrayRef<DwarfAccelTable::Atom>);
+ void AddName(DwarfStringPoolEntryRef Name, const DIE *Die, char Flags = 0);
+ void FinalizeTable(AsmPrinter *, StringRef);
+ void emit(AsmPrinter *, const MCSymbol *, DwarfDebug *);
+#ifndef NDEBUG
+ void print(raw_ostream &O);
+ void dump() { print(dbgs()); }
+#endif
+};
+}
+#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
new file mode 100644
index 0000000..6665c16
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
@@ -0,0 +1,162 @@
+//===-- CodeGen/AsmPrinter/DwarfException.cpp - Dwarf 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 DWARF exception info into asm files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DwarfException.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Mangler.h"
+#include "llvm/IR/Module.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MachineLocation.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Target/TargetFrameLowering.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+using namespace llvm;
+
+DwarfCFIExceptionBase::DwarfCFIExceptionBase(AsmPrinter *A)
+ : EHStreamer(A), shouldEmitCFI(false) {}
+
+void DwarfCFIExceptionBase::markFunctionEnd() {
+ if (shouldEmitCFI)
+ Asm->OutStreamer->EmitCFIEndProc();
+
+ if (MMI->getLandingPads().empty())
+ return;
+
+ // Map all labels and get rid of any dead landing pads.
+ MMI->TidyLandingPads();
+}
+
+DwarfCFIException::DwarfCFIException(AsmPrinter *A)
+ : DwarfCFIExceptionBase(A), shouldEmitPersonality(false),
+ shouldEmitLSDA(false), shouldEmitMoves(false),
+ moveTypeModule(AsmPrinter::CFI_M_None) {}
+
+DwarfCFIException::~DwarfCFIException() {}
+
+/// endModule - Emit all exception information that should come after the
+/// content.
+void DwarfCFIException::endModule() {
+ if (moveTypeModule == AsmPrinter::CFI_M_Debug)
+ Asm->OutStreamer->EmitCFISections(false, true);
+
+ // SjLj uses this pass and it doesn't need this info.
+ if (!Asm->MAI->usesCFIForEH())
+ return;
+
+ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
+
+ unsigned PerEncoding = TLOF.getPersonalityEncoding();
+
+ if ((PerEncoding & 0x80) != dwarf::DW_EH_PE_indirect)
+ return;
+
+ // Emit references to all used personality functions
+ for (const Function *Personality : MMI->getPersonalities()) {
+ if (!Personality)
+ continue;
+ MCSymbol *Sym = Asm->getSymbol(Personality);
+ TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym);
+ }
+}
+
+void DwarfCFIException::beginFunction(const MachineFunction *MF) {
+ shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false;
+ const Function *F = MF->getFunction();
+
+ // If any landing pads survive, we need an EH table.
+ bool hasLandingPads = !MMI->getLandingPads().empty();
+
+ // See if we need frame move info.
+ AsmPrinter::CFIMoveType MoveType = Asm->needsCFIMoves();
+ if (MoveType == AsmPrinter::CFI_M_EH ||
+ (MoveType == AsmPrinter::CFI_M_Debug &&
+ moveTypeModule == AsmPrinter::CFI_M_None))
+ moveTypeModule = MoveType;
+
+ shouldEmitMoves = MoveType != AsmPrinter::CFI_M_None;
+
+ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
+ unsigned PerEncoding = TLOF.getPersonalityEncoding();
+ const Function *Per = nullptr;
+ if (F->hasPersonalityFn())
+ Per = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
+
+ // Emit a personality function even when there are no landing pads
+ bool forceEmitPersonality =
+ // ...if a personality function is explicitly specified
+ F->hasPersonalityFn() &&
+ // ... and it's not known to be a noop in the absence of invokes
+ !isNoOpWithoutInvoke(classifyEHPersonality(Per)) &&
+ // ... and we're not explicitly asked not to emit it
+ F->needsUnwindTableEntry();
+
+ shouldEmitPersonality =
+ (forceEmitPersonality ||
+ (hasLandingPads && PerEncoding != dwarf::DW_EH_PE_omit)) &&
+ Per;
+
+ unsigned LSDAEncoding = TLOF.getLSDAEncoding();
+ shouldEmitLSDA = shouldEmitPersonality &&
+ LSDAEncoding != dwarf::DW_EH_PE_omit;
+
+ shouldEmitCFI = shouldEmitPersonality || shouldEmitMoves;
+ if (!shouldEmitCFI)
+ return;
+
+ Asm->OutStreamer->EmitCFIStartProc(/*IsSimple=*/false);
+
+ // Indicate personality routine, if any.
+ if (!shouldEmitPersonality)
+ return;
+
+ // If we are forced to emit this personality, make sure to record
+ // it because it might not appear in any landingpad
+ if (forceEmitPersonality)
+ MMI->addPersonality(Per);
+
+ const MCSymbol *Sym =
+ TLOF.getCFIPersonalitySymbol(Per, *Asm->Mang, Asm->TM, MMI);
+ Asm->OutStreamer->EmitCFIPersonality(Sym, PerEncoding);
+
+ // Provide LSDA information.
+ if (!shouldEmitLSDA)
+ return;
+
+ Asm->OutStreamer->EmitCFILsda(Asm->getCurExceptionSym(), LSDAEncoding);
+}
+
+/// endFunction - Gather and emit post-function exception information.
+///
+void DwarfCFIException::endFunction(const MachineFunction *) {
+ if (!shouldEmitPersonality)
+ return;
+
+ emitExceptionTable();
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
new file mode 100644
index 0000000..725063a
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -0,0 +1,830 @@
+#include "DwarfCompileUnit.h"
+#include "DwarfExpression.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Target/TargetFrameLowering.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+
+namespace llvm {
+
+DwarfCompileUnit::DwarfCompileUnit(unsigned UID, const DICompileUnit *Node,
+ AsmPrinter *A, DwarfDebug *DW,
+ DwarfFile *DWU)
+ : DwarfUnit(UID, dwarf::DW_TAG_compile_unit, Node, A, DW, DWU),
+ Skeleton(nullptr), BaseAddress(nullptr) {
+ insertDIE(Node, &getUnitDie());
+}
+
+/// addLabelAddress - Add a dwarf label attribute data and value using
+/// DW_FORM_addr or DW_FORM_GNU_addr_index.
+///
+void DwarfCompileUnit::addLabelAddress(DIE &Die, dwarf::Attribute Attribute,
+ const MCSymbol *Label) {
+
+ // Don't use the address pool in non-fission or in the skeleton unit itself.
+ // FIXME: Once GDB supports this, it's probably worthwhile using the address
+ // 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)
+ 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,
+ DIEInteger(idx));
+}
+
+void DwarfCompileUnit::addLocalLabelAddress(DIE &Die,
+ dwarf::Attribute Attribute,
+ const MCSymbol *Label) {
+ if (Label)
+ DD->addArangeLabel(SymbolCU(this, Label));
+
+ if (Label)
+ Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_addr,
+ DIELabel(Label));
+ else
+ Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_addr,
+ DIEInteger(0));
+}
+
+unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName,
+ StringRef DirName) {
+ // If we print assembly, we can't separate .file entries according to
+ // compile units. Thus all files will belong to the default compile unit.
+
+ // FIXME: add a better feature test than hasRawTextSupport. Even better,
+ // extend .file to support this.
+ return Asm->OutStreamer->EmitDwarfFileDirective(
+ 0, DirName, FileName,
+ Asm->OutStreamer->hasRawTextSupport() ? 0 : getUniqueID());
+}
+
+// Return const expression if value is a GEP to access merged global
+// constant. e.g.
+// i8* getelementptr ({ i8, i8, i8, i8 }* @_MergedGlobals, i32 0, i32 0)
+static const ConstantExpr *getMergedGlobalExpr(const Value *V) {
+ const ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(V);
+ if (!CE || CE->getNumOperands() != 3 ||
+ CE->getOpcode() != Instruction::GetElementPtr)
+ return nullptr;
+
+ // First operand points to a global struct.
+ Value *Ptr = CE->getOperand(0);
+ if (!isa<GlobalValue>(Ptr) ||
+ !isa<StructType>(cast<PointerType>(Ptr->getType())->getElementType()))
+ return nullptr;
+
+ // Second operand is zero.
+ const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CE->getOperand(1));
+ if (!CI || !CI->isZero())
+ return nullptr;
+
+ // Third operand is offset.
+ if (!isa<ConstantInt>(CE->getOperand(2)))
+ return nullptr;
+
+ return CE;
+}
+
+/// getOrCreateGlobalVariableDIE - get or create global variable DIE.
+DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
+ const DIGlobalVariable *GV) {
+ // Check for pre-existence.
+ if (DIE *Die = getDIE(GV))
+ return Die;
+
+ assert(GV);
+
+ auto *GVContext = GV->getScope();
+ auto *GTy = DD->resolve(GV->getType());
+
+ // Construct the context before querying for the existence of the DIE in
+ // case such construction creates the DIE.
+ DIE *ContextDIE = getOrCreateContextDIE(GVContext);
+
+ // Add to map.
+ DIE *VariableDIE = &createAndAddDIE(GV->getTag(), *ContextDIE, GV);
+ DIScope *DeclContext;
+ if (auto *SDMDecl = GV->getStaticDataMemberDeclaration()) {
+ DeclContext = resolve(SDMDecl->getScope());
+ assert(SDMDecl->isStaticMember() && "Expected static member decl");
+ assert(GV->isDefinition());
+ // We need the declaration DIE that is in the static member's class.
+ DIE *VariableSpecDIE = getOrCreateStaticMemberDIE(SDMDecl);
+ addDIEEntry(*VariableDIE, dwarf::DW_AT_specification, *VariableSpecDIE);
+ } else {
+ DeclContext = GV->getScope();
+ // Add name and type.
+ addString(*VariableDIE, dwarf::DW_AT_name, GV->getDisplayName());
+ addType(*VariableDIE, GTy);
+
+ // Add scoping info.
+ if (!GV->isLocalToUnit())
+ addFlag(*VariableDIE, dwarf::DW_AT_external);
+
+ // Add line number info.
+ addSourceLine(*VariableDIE, GV);
+ }
+
+ if (!GV->isDefinition())
+ addFlag(*VariableDIE, dwarf::DW_AT_declaration);
+ else
+ addGlobalName(GV->getName(), *VariableDIE, DeclContext);
+
+ // Add location.
+ bool addToAccelTable = false;
+ if (auto *Global = dyn_cast_or_null<GlobalVariable>(GV->getVariable())) {
+ addToAccelTable = true;
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+ const MCSymbol *Sym = Asm->getSymbol(Global);
+ if (Global->isThreadLocal()) {
+ if (Asm->TM.Options.EmulatedTLS) {
+ // TODO: add debug info for emulated thread local mode.
+ } else {
+ // FIXME: Make this work with -gsplit-dwarf.
+ unsigned PointerSize = Asm->getDataLayout().getPointerSize();
+ assert((PointerSize == 4 || PointerSize == 8) &&
+ "Add support for other sizes if necessary");
+ // Based on GCC's support for TLS:
+ if (!DD->useSplitDwarf()) {
+ // 1) Start with a constNu of the appropriate pointer size
+ addUInt(*Loc, dwarf::DW_FORM_data1, PointerSize == 4
+ ? dwarf::DW_OP_const4u
+ : dwarf::DW_OP_const8u);
+ // 2) containing the (relocated) offset of the TLS variable
+ // within the module's TLS block.
+ addExpr(*Loc, dwarf::DW_FORM_udata,
+ Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym));
+ } else {
+ addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_const_index);
+ addUInt(*Loc, dwarf::DW_FORM_udata,
+ DD->getAddressPool().getIndex(Sym, /* TLS */ true));
+ }
+ // 3) followed by an OP to make the debugger do a TLS lookup.
+ addUInt(*Loc, dwarf::DW_FORM_data1,
+ DD->useGNUTLSOpcode() ? dwarf::DW_OP_GNU_push_tls_address
+ : dwarf::DW_OP_form_tls_address);
+ }
+ } else {
+ DD->addArangeLabel(SymbolCU(this, Sym));
+ addOpAddress(*Loc, Sym);
+ }
+
+ addBlock(*VariableDIE, dwarf::DW_AT_location, Loc);
+ addLinkageName(*VariableDIE, GV->getLinkageName());
+ } else if (const ConstantInt *CI =
+ dyn_cast_or_null<ConstantInt>(GV->getVariable())) {
+ addConstantValue(*VariableDIE, CI, GTy);
+ } else if (const ConstantExpr *CE = getMergedGlobalExpr(GV->getVariable())) {
+ addToAccelTable = true;
+ // GV is a merged global.
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+ Value *Ptr = CE->getOperand(0);
+ MCSymbol *Sym = Asm->getSymbol(cast<GlobalValue>(Ptr));
+ DD->addArangeLabel(SymbolCU(this, Sym));
+ addOpAddress(*Loc, Sym);
+ addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
+ SmallVector<Value *, 3> Idx(CE->op_begin() + 1, CE->op_end());
+ addUInt(*Loc, dwarf::DW_FORM_udata,
+ Asm->getDataLayout().getIndexedOffset(Ptr->getType(), Idx));
+ addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus);
+ addBlock(*VariableDIE, dwarf::DW_AT_location, Loc);
+ }
+
+ if (addToAccelTable) {
+ DD->addAccelName(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->addAccelName(GV->getLinkageName(), *VariableDIE);
+ }
+
+ return VariableDIE;
+}
+
+void DwarfCompileUnit::addRange(RangeSpan Range) {
+ bool SameAsPrevCU = this == DD->getPrevCU();
+ DD->setPrevCU(this);
+ // If we have no current ranges just add the range and return, otherwise,
+ // check the current section and CU against the previous section and CU we
+ // emitted into and the subprogram was contained within. If these are the
+ // same then extend our current range, otherwise add this as a new range.
+ if (CURanges.empty() || !SameAsPrevCU ||
+ (&CURanges.back().getEnd()->getSection() !=
+ &Range.getEnd()->getSection())) {
+ CURanges.push_back(Range);
+ return;
+ }
+
+ CURanges.back().setEnd(Range.getEnd());
+}
+
+DIE::value_iterator
+DwarfCompileUnit::addSectionLabel(DIE &Die, dwarf::Attribute Attribute,
+ const MCSymbol *Label, const MCSymbol *Sec) {
+ if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
+ return addLabel(Die, Attribute,
+ DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset
+ : dwarf::DW_FORM_data4,
+ Label);
+ return addSectionDelta(Die, Attribute, Label, Sec);
+}
+
+void DwarfCompileUnit::initStmtList() {
+ // Define start line table label for each Compile Unit.
+ MCSymbol *LineTableStartSym =
+ Asm->OutStreamer->getDwarfLineTableSymbol(getUniqueID());
+
+ // DW_AT_stmt_list is a offset of line number information for this
+ // compile unit in debug_line section. For split dwarf this is
+ // left in the skeleton CU and so not included.
+ // The line table entries are not always emitted in assembly, so it
+ // is not okay to use line_table_start here.
+ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
+ StmtListValue =
+ addSectionLabel(UnitDie, dwarf::DW_AT_stmt_list, LineTableStartSym,
+ TLOF.getDwarfLineSection()->getBeginSymbol());
+}
+
+void DwarfCompileUnit::applyStmtList(DIE &D) {
+ D.addValue(DIEValueAllocator, *StmtListValue);
+}
+
+void DwarfCompileUnit::attachLowHighPC(DIE &D, const MCSymbol *Begin,
+ const MCSymbol *End) {
+ assert(Begin && "Begin label should not be null!");
+ assert(End && "End label should not be null!");
+ assert(Begin->isDefined() && "Invalid starting label");
+ assert(End->isDefined() && "Invalid end label");
+
+ addLabelAddress(D, dwarf::DW_AT_low_pc, Begin);
+ if (DD->getDwarfVersion() < 4)
+ addLabelAddress(D, dwarf::DW_AT_high_pc, End);
+ else
+ addLabelDelta(D, dwarf::DW_AT_high_pc, End, Begin);
+}
+
+// Find DIE for the given subprogram and attach appropriate DW_AT_low_pc
+// and DW_AT_high_pc attributes. If there are global variables in this
+// scope then create and insert DIEs for these variables.
+DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) {
+ DIE *SPDie = getOrCreateSubprogramDIE(SP, includeMinimalInlineScopes());
+
+ attachLowHighPC(*SPDie, Asm->getFunctionBegin(), Asm->getFunctionEnd());
+ if (!DD->getCurrentFunction()->getTarget().Options.DisableFramePointerElim(
+ *DD->getCurrentFunction()))
+ addFlag(*SPDie, dwarf::DW_AT_APPLE_omit_frame_ptr);
+
+ // Only include DW_AT_frame_base in full debug info
+ if (!includeMinimalInlineScopes()) {
+ const TargetRegisterInfo *RI = Asm->MF->getSubtarget().getRegisterInfo();
+ MachineLocation Location(RI->getFrameRegister(*Asm->MF));
+ if (RI->isPhysicalRegister(Location.getReg()))
+ addAddress(*SPDie, dwarf::DW_AT_frame_base, Location);
+ }
+
+ // 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);
+
+ return *SPDie;
+}
+
+// Construct a DIE for this scope.
+void DwarfCompileUnit::constructScopeDIE(
+ LexicalScope *Scope, SmallVectorImpl<DIE *> &FinalChildren) {
+ if (!Scope || !Scope->getScopeNode())
+ return;
+
+ auto *DS = Scope->getScopeNode();
+
+ assert((Scope->getInlinedAt() || !isa<DISubprogram>(DS)) &&
+ "Only handle inlined subprograms here, use "
+ "constructSubprogramScopeDIE for non-inlined "
+ "subprograms");
+
+ SmallVector<DIE *, 8> Children;
+
+ // We try to create the scope DIE first, then the children DIEs. This will
+ // avoid creating un-used children then removing them later when we find out
+ // the scope DIE is null.
+ DIE *ScopeDIE;
+ if (Scope->getParent() && isa<DISubprogram>(DS)) {
+ ScopeDIE = constructInlinedScopeDIE(Scope);
+ if (!ScopeDIE)
+ return;
+ // We create children when the scope DIE is not null.
+ createScopeChildrenDIE(Scope, Children);
+ } else {
+ // Early exit when we know the scope DIE is going to be null.
+ if (DD->isLexicalScopeDIENull(Scope))
+ return;
+
+ unsigned ChildScopeCount;
+
+ // We create children here when we know the scope DIE is not going to be
+ // null and the children will be added to the scope DIE.
+ createScopeChildrenDIE(Scope, Children, &ChildScopeCount);
+
+ // Skip imported directives in gmlt-like data.
+ if (!includeMinimalInlineScopes()) {
+ // There is no need to emit empty lexical block DIE.
+ for (const auto *IE : ImportedEntities[DS])
+ Children.push_back(
+ constructImportedEntityDIE(cast<DIImportedEntity>(IE)));
+ }
+
+ // If there are only other scopes as children, put them directly in the
+ // parent instead, as this scope would serve no purpose.
+ if (Children.size() == ChildScopeCount) {
+ FinalChildren.insert(FinalChildren.end(),
+ std::make_move_iterator(Children.begin()),
+ std::make_move_iterator(Children.end()));
+ return;
+ }
+ ScopeDIE = constructLexicalScopeDIE(Scope);
+ assert(ScopeDIE && "Scope DIE should not be null.");
+ }
+
+ // Add children
+ for (auto &I : Children)
+ ScopeDIE->addChild(std::move(I));
+
+ FinalChildren.push_back(std::move(ScopeDIE));
+}
+
+DIE::value_iterator
+DwarfCompileUnit::addSectionDelta(DIE &Die, dwarf::Attribute Attribute,
+ const MCSymbol *Hi, const MCSymbol *Lo) {
+ return Die.addValue(DIEValueAllocator, Attribute,
+ DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset
+ : dwarf::DW_FORM_data4,
+ new (DIEValueAllocator) DIEDelta(Hi, Lo));
+}
+
+void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE,
+ SmallVector<RangeSpan, 2> Range) {
+ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
+
+ // Emit offset in .debug_range as a relocatable label. emitDIE will handle
+ // emitting it appropriately.
+ const MCSymbol *RangeSectionSym =
+ TLOF.getDwarfRangesSection()->getBeginSymbol();
+
+ RangeSpanList List(Asm->createTempSymbol("debug_ranges"), std::move(Range));
+
+ // Under fission, ranges are specified by constant offsets relative to the
+ // CU's DW_AT_GNU_ranges_base.
+ 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(
+ DIE &Die, SmallVector<RangeSpan, 2> Ranges) {
+ if (Ranges.size() == 1) {
+ const auto &single = Ranges.front();
+ attachLowHighPC(Die, single.getStart(), single.getEnd());
+ } else
+ addScopeRangeList(Die, std::move(Ranges));
+}
+
+void DwarfCompileUnit::attachRangesOrLowHighPC(
+ DIE &Die, const SmallVectorImpl<InsnRange> &Ranges) {
+ SmallVector<RangeSpan, 2> List;
+ List.reserve(Ranges.size());
+ for (const InsnRange &R : Ranges)
+ List.push_back(RangeSpan(DD->getLabelBeforeInsn(R.first),
+ DD->getLabelAfterInsn(R.second)));
+ attachRangesOrLowHighPC(Die, std::move(List));
+}
+
+// This scope represents inlined body of a function. Construct DIE to
+// represent this concrete inlined copy of the function.
+DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope) {
+ assert(Scope->getScopeNode());
+ auto *DS = Scope->getScopeNode();
+ auto *InlinedSP = getDISubprogram(DS);
+ // Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram
+ // was inlined from another compile unit.
+ DIE *OriginDIE = DU->getAbstractSPDies()[InlinedSP];
+ assert(OriginDIE && "Unable to find original DIE for an inlined subprogram.");
+
+ auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_inlined_subroutine);
+ addDIEEntry(*ScopeDIE, dwarf::DW_AT_abstract_origin, *OriginDIE);
+
+ attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges());
+
+ // Add the call site information to the DIE.
+ const DILocation *IA = Scope->getInlinedAt();
+ addUInt(*ScopeDIE, dwarf::DW_AT_call_file, None,
+ getOrCreateSourceID(IA->getFilename(), IA->getDirectory()));
+ addUInt(*ScopeDIE, dwarf::DW_AT_call_line, None, IA->getLine());
+ if (IA->getDiscriminator())
+ addUInt(*ScopeDIE, dwarf::DW_AT_GNU_discriminator, None,
+ IA->getDiscriminator());
+
+ // 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);
+
+ return ScopeDIE;
+}
+
+// Construct new DW_TAG_lexical_block for this scope and attach
+// DW_AT_low_pc/DW_AT_high_pc labels.
+DIE *DwarfCompileUnit::constructLexicalScopeDIE(LexicalScope *Scope) {
+ if (DD->isLexicalScopeDIENull(Scope))
+ return nullptr;
+
+ auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_lexical_block);
+ if (Scope->isAbstractScope())
+ return ScopeDIE;
+
+ attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges());
+
+ return ScopeDIE;
+}
+
+/// constructVariableDIE - Construct a DIE for the given DbgVariable.
+DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV, bool Abstract) {
+ auto D = constructVariableDIEImpl(DV, Abstract);
+ DV.setDIE(*D);
+ return D;
+}
+
+DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
+ bool Abstract) {
+ // Define variable debug information entry.
+ auto VariableDie = DIE::get(DIEValueAllocator, DV.getTag());
+
+ if (Abstract) {
+ applyVariableAttributes(DV, *VariableDie);
+ return VariableDie;
+ }
+
+ // Add variable address.
+
+ unsigned Offset = DV.getDebugLocListIndex();
+ if (Offset != ~0U) {
+ addLocationList(*VariableDie, dwarf::DW_AT_location, Offset);
+ return VariableDie;
+ }
+
+ // Check if variable is described by a DBG_VALUE instruction.
+ if (const MachineInstr *DVInsn = DV.getMInsn()) {
+ assert(DVInsn->getNumOperands() == 4);
+ if (DVInsn->getOperand(0).isReg()) {
+ const MachineOperand RegOp = DVInsn->getOperand(0);
+ // If the second operand is an immediate, this is an indirect value.
+ if (DVInsn->getOperand(1).isImm()) {
+ MachineLocation Location(RegOp.getReg(),
+ DVInsn->getOperand(1).getImm());
+ addVariableAddress(DV, *VariableDie, Location);
+ } else if (RegOp.getReg())
+ addVariableAddress(DV, *VariableDie, MachineLocation(RegOp.getReg()));
+ } else if (DVInsn->getOperand(0).isImm())
+ addConstantValue(*VariableDie, DVInsn->getOperand(0), DV.getType());
+ else if (DVInsn->getOperand(0).isFPImm())
+ addConstantFPValue(*VariableDie, DVInsn->getOperand(0));
+ else if (DVInsn->getOperand(0).isCImm())
+ addConstantValue(*VariableDie, DVInsn->getOperand(0).getCImm(),
+ DV.getType());
+
+ return VariableDie;
+ }
+
+ // .. else use frame index.
+ if (DV.getFrameIndex().empty())
+ return VariableDie;
+
+ auto Expr = DV.getExpression().begin();
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+ DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
+ for (auto FI : DV.getFrameIndex()) {
+ unsigned FrameReg = 0;
+ const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
+ int Offset = TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg);
+ assert(Expr != DV.getExpression().end() && "Wrong number of expressions");
+ DwarfExpr.AddMachineRegIndirect(FrameReg, Offset);
+ DwarfExpr.AddExpression((*Expr)->expr_op_begin(), (*Expr)->expr_op_end());
+ ++Expr;
+ }
+ addBlock(*VariableDie, dwarf::DW_AT_location, Loc);
+
+ return VariableDie;
+}
+
+DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV,
+ const LexicalScope &Scope,
+ DIE *&ObjectPointer) {
+ auto Var = constructVariableDIE(DV, Scope.isAbstractScope());
+ if (DV.isObjectPointer())
+ ObjectPointer = Var;
+ return Var;
+}
+
+DIE *DwarfCompileUnit::createScopeChildrenDIE(LexicalScope *Scope,
+ SmallVectorImpl<DIE *> &Children,
+ unsigned *ChildScopeCount) {
+ DIE *ObjectPointer = nullptr;
+
+ for (DbgVariable *DV : DU->getScopeVariables().lookup(Scope))
+ Children.push_back(constructVariableDIE(*DV, *Scope, ObjectPointer));
+
+ unsigned ChildCountWithoutScopes = Children.size();
+
+ for (LexicalScope *LS : Scope->getChildren())
+ constructScopeDIE(LS, Children);
+
+ if (ChildScopeCount)
+ *ChildScopeCount = Children.size() - ChildCountWithoutScopes;
+
+ return ObjectPointer;
+}
+
+void DwarfCompileUnit::constructSubprogramScopeDIE(LexicalScope *Scope) {
+ assert(Scope && Scope->getScopeNode());
+ assert(!Scope->getInlinedAt());
+ assert(!Scope->isAbstractScope());
+ auto *Sub = cast<DISubprogram>(Scope->getScopeNode());
+
+ DD->getProcessedSPNodes().insert(Sub);
+
+ DIE &ScopeDIE = updateSubprogramScopeDIE(Sub);
+
+ // If this is a variadic function, add an unspecified parameter.
+ DITypeRefArray FnArgs = Sub->getType()->getTypeArray();
+
+ // Collect lexical scope children first.
+ // ObjectPointer might be a local (non-argument) local variable if it's a
+ // block's synthetic this pointer.
+ if (DIE *ObjectPointer = createAndAddScopeChildren(Scope, ScopeDIE))
+ addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer);
+
+ // If we have a single element of null, it is a function that returns void.
+ // If we have more than one elements and the last one is null, it is a
+ // variadic function.
+ if (FnArgs.size() > 1 && !FnArgs[FnArgs.size() - 1] &&
+ !includeMinimalInlineScopes())
+ ScopeDIE.addChild(
+ DIE::get(DIEValueAllocator, dwarf::DW_TAG_unspecified_parameters));
+}
+
+DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope,
+ DIE &ScopeDIE) {
+ // We create children when the scope DIE is not null.
+ SmallVector<DIE *, 8> Children;
+ DIE *ObjectPointer = createScopeChildrenDIE(Scope, Children);
+
+ // Add children
+ for (auto &I : Children)
+ ScopeDIE.addChild(std::move(I));
+
+ return ObjectPointer;
+}
+
+void DwarfCompileUnit::constructAbstractSubprogramScopeDIE(
+ LexicalScope *Scope) {
+ DIE *&AbsDef = DU->getAbstractSPDies()[Scope->getScopeNode()];
+ if (AbsDef)
+ return;
+
+ auto *SP = cast<DISubprogram>(Scope->getScopeNode());
+
+ DIE *ContextDIE;
+
+ if (includeMinimalInlineScopes())
+ ContextDIE = &getUnitDie();
+ // Some of this is duplicated from DwarfUnit::getOrCreateSubprogramDIE, with
+ // the important distinction that the debug node is not associated with the
+ // DIE (since the debug node will be associated with the concrete DIE, if
+ // any). It could be refactored to some common utility function.
+ else if (auto *SPDecl = SP->getDeclaration()) {
+ ContextDIE = &getUnitDie();
+ getOrCreateSubprogramDIE(SPDecl);
+ } else
+ ContextDIE = getOrCreateContextDIE(resolve(SP->getScope()));
+
+ // Passing null as the associated node because the abstract definition
+ // shouldn't be found by lookup.
+ AbsDef = &createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, nullptr);
+ applySubprogramAttributesToDefinition(SP, *AbsDef);
+
+ if (!includeMinimalInlineScopes())
+ addUInt(*AbsDef, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
+ if (DIE *ObjectPointer = createAndAddScopeChildren(Scope, *AbsDef))
+ addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer);
+}
+
+DIE *DwarfCompileUnit::constructImportedEntityDIE(
+ const DIImportedEntity *Module) {
+ DIE *IMDie = DIE::get(DIEValueAllocator, (dwarf::Tag)Module->getTag());
+ insertDIE(Module, IMDie);
+ DIE *EntityDie;
+ auto *Entity = resolve(Module->getEntity());
+ if (auto *NS = dyn_cast<DINamespace>(Entity))
+ EntityDie = getOrCreateNameSpace(NS);
+ else if (auto *M = dyn_cast<DIModule>(Entity))
+ EntityDie = getOrCreateModule(M);
+ else if (auto *SP = dyn_cast<DISubprogram>(Entity))
+ EntityDie = getOrCreateSubprogramDIE(SP);
+ else if (auto *T = dyn_cast<DIType>(Entity))
+ EntityDie = getOrCreateTypeDIE(T);
+ else if (auto *GV = dyn_cast<DIGlobalVariable>(Entity))
+ EntityDie = getOrCreateGlobalVariableDIE(GV);
+ else
+ EntityDie = getDIE(Entity);
+ assert(EntityDie);
+ addSourceLine(*IMDie, Module->getLine(), Module->getScope()->getFilename(),
+ Module->getScope()->getDirectory());
+ addDIEEntry(*IMDie, dwarf::DW_AT_import, *EntityDie);
+ StringRef Name = Module->getName();
+ if (!Name.empty())
+ addString(*IMDie, dwarf::DW_AT_name, Name);
+
+ return IMDie;
+}
+
+void DwarfCompileUnit::finishSubprogramDefinition(const DISubprogram *SP) {
+ DIE *D = getDIE(SP);
+ if (DIE *AbsSPDIE = DU->getAbstractSPDies().lookup(SP)) {
+ if (D)
+ // If this subprogram has an abstract definition, reference that
+ addDIEEntry(*D, dwarf::DW_AT_abstract_origin, *AbsSPDIE);
+ } else {
+ if (!D && !includeMinimalInlineScopes())
+ // Lazily construct the subprogram if we didn't see either concrete or
+ // inlined versions during codegen. (except in -gmlt ^ where we want
+ // to omit these entirely)
+ D = getOrCreateSubprogramDIE(SP);
+ if (D)
+ // And attach the attributes
+ applySubprogramAttributesToDefinition(SP, *D);
+ }
+}
+void DwarfCompileUnit::collectDeadVariables(const DISubprogram *SP) {
+ assert(SP && "CU's subprogram list contains a non-subprogram");
+ assert(SP->isDefinition() &&
+ "CU's subprogram list contains a subprogram declaration");
+ auto Variables = SP->getVariables();
+ if (Variables.size() == 0)
+ return;
+
+ DIE *SPDIE = DU->getAbstractSPDies().lookup(SP);
+ if (!SPDIE)
+ SPDIE = getDIE(SP);
+ assert(SPDIE);
+ for (const DILocalVariable *DV : Variables) {
+ DbgVariable NewVar(DV, /* IA */ nullptr, DD);
+ auto VariableDie = constructVariableDIE(NewVar);
+ applyVariableAttributes(NewVar, *VariableDie);
+ SPDIE->addChild(std::move(VariableDie));
+ }
+}
+
+void DwarfCompileUnit::emitHeader(bool UseOffsets) {
+ // Don't bother labeling the .dwo unit, as its offset isn't used.
+ if (!Skeleton) {
+ LabelBegin = Asm->createTempSymbol("cu_begin");
+ Asm->OutStreamer->EmitLabel(LabelBegin);
+ }
+
+ DwarfUnit::emitHeader(UseOffsets);
+}
+
+/// addGlobalName - Add a new global name to the compile unit.
+void DwarfCompileUnit::addGlobalName(StringRef Name, DIE &Die,
+ const DIScope *Context) {
+ if (includeMinimalInlineScopes())
+ return;
+ std::string FullName = getParentContextString(Context) + Name.str();
+ GlobalNames[FullName] = &Die;
+}
+
+/// Add a new global type to the unit.
+void DwarfCompileUnit::addGlobalType(const DIType *Ty, const DIE &Die,
+ const DIScope *Context) {
+ if (includeMinimalInlineScopes())
+ return;
+ std::string FullName = getParentContextString(Context) + Ty->getName().str();
+ GlobalTypes[FullName] = &Die;
+}
+
+/// addVariableAddress - Add DW_AT_location attribute for a
+/// DbgVariable based on provided MachineLocation.
+void DwarfCompileUnit::addVariableAddress(const DbgVariable &DV, DIE &Die,
+ MachineLocation Location) {
+ 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);
+}
+
+/// Add an address attribute to a die based on the location provided.
+void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute,
+ const MachineLocation &Location) {
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+
+ bool validReg;
+ if (Location.isReg())
+ validReg = addRegisterOpPiece(*Loc, Location.getReg());
+ else
+ validReg = addRegisterOffset(*Loc, Location.getReg(), Location.getOffset());
+
+ if (!validReg)
+ return;
+
+ // Now attach the location information to the DIE.
+ addBlock(Die, Attribute, Loc);
+}
+
+/// Start with the address based on the location provided, and generate the
+/// DWARF information necessary to find the actual variable given the extra
+/// address information encoded in the DbgVariable, starting from the starting
+/// location. Add the DWARF information to the die.
+void DwarfCompileUnit::addComplexAddress(const DbgVariable &DV, DIE &Die,
+ dwarf::Attribute Attribute,
+ const MachineLocation &Location) {
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+ DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
+ assert(DV.getExpression().size() == 1);
+ const DIExpression *Expr = DV.getExpression().back();
+ bool ValidReg;
+ if (Location.getOffset()) {
+ ValidReg = DwarfExpr.AddMachineRegIndirect(Location.getReg(),
+ Location.getOffset());
+ if (ValidReg)
+ DwarfExpr.AddExpression(Expr->expr_op_begin(), Expr->expr_op_end());
+ } else
+ ValidReg = DwarfExpr.AddMachineRegExpression(Expr, Location.getReg());
+
+ // Now attach the location information to the DIE.
+ if (ValidReg)
+ addBlock(Die, Attribute, Loc);
+}
+
+/// Add a Dwarf loclistptr attribute data and value.
+void DwarfCompileUnit::addLocationList(DIE &Die, dwarf::Attribute Attribute,
+ unsigned Index) {
+ dwarf::Form Form = DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset
+ : dwarf::DW_FORM_data4;
+ Die.addValue(DIEValueAllocator, Attribute, Form, DIELocList(Index));
+}
+
+void DwarfCompileUnit::applyVariableAttributes(const DbgVariable &Var,
+ DIE &VariableDie) {
+ StringRef Name = Var.getName();
+ if (!Name.empty())
+ addString(VariableDie, dwarf::DW_AT_name, Name);
+ addSourceLine(VariableDie, Var.getVariable());
+ addType(VariableDie, Var.getType());
+ if (Var.isArtificial())
+ addFlag(VariableDie, dwarf::DW_AT_artificial);
+}
+
+/// 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::applySubprogramAttributesToDefinition(
+ const DISubprogram *SP, DIE &SPDie) {
+ auto *SPDecl = SP->getDeclaration();
+ auto *Context = resolve(SPDecl ? SPDecl->getScope() : SP->getScope());
+ applySubprogramAttributes(SP, SPDie, includeMinimalInlineScopes());
+ addGlobalName(SP->getName(), SPDie, Context);
+}
+
+bool DwarfCompileUnit::isDwoUnit() const {
+ return DD->useSplitDwarf() && Skeleton;
+}
+
+bool DwarfCompileUnit::includeMinimalInlineScopes() const {
+ return getCUNode()->getEmissionKind() == DIBuilder::LineTablesOnly ||
+ (DD->useSplitDwarf() && !Skeleton);
+}
+} // end llvm namespace
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
new file mode 100644
index 0000000..2e28467
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
@@ -0,0 +1,243 @@
+//===-- llvm/CodeGen/DwarfCompileUnit.h - Dwarf Compile Unit ---*- 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 dwarf compile unit.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H
+
+#include "DwarfUnit.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/Support/Dwarf.h"
+
+namespace llvm {
+
+class AsmPrinter;
+class DIE;
+class DwarfDebug;
+class DwarfFile;
+class MCSymbol;
+class LexicalScope;
+
+class DwarfCompileUnit : public DwarfUnit {
+ /// The attribute index of DW_AT_stmt_list in the compile unit DIE, avoiding
+ /// the need to search for it in applyStmtList.
+ DIE::value_iterator StmtListValue;
+
+ /// Skeleton unit associated with this unit.
+ DwarfCompileUnit *Skeleton;
+
+ /// The start of the unit within its section.
+ MCSymbol *LabelBegin;
+
+ typedef llvm::SmallVector<const MDNode *, 8> ImportedEntityList;
+ typedef llvm::DenseMap<const MDNode *, ImportedEntityList>
+ ImportedEntityMap;
+
+ ImportedEntityMap ImportedEntities;
+
+ /// GlobalNames - A map of globally visible named entities for this unit.
+ StringMap<const DIE *> GlobalNames;
+
+ /// 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;
+
+ // The base address of this unit, if any. Used for relative references in
+ // ranges/locs.
+ const MCSymbol *BaseAddress;
+
+ /// \brief Construct a DIE for the given DbgVariable without initializing the
+ /// DbgVariable's DIE reference.
+ DIE *constructVariableDIEImpl(const DbgVariable &DV, bool Abstract);
+
+ bool isDwoUnit() const override;
+
+ bool includeMinimalInlineScopes() const;
+
+public:
+ DwarfCompileUnit(unsigned UID, const DICompileUnit *Node, AsmPrinter *A,
+ DwarfDebug *DW, DwarfFile *DWU);
+
+ DwarfCompileUnit *getSkeleton() const {
+ return Skeleton;
+ }
+
+ void initStmtList();
+
+ /// Apply the DW_AT_stmt_list from this compile unit to the specified DIE.
+ void applyStmtList(DIE &D);
+
+ /// getOrCreateGlobalVariableDIE - get or create global variable DIE.
+ DIE *getOrCreateGlobalVariableDIE(const DIGlobalVariable *GV);
+
+ /// addLabelAddress - Add a dwarf label attribute data and value using
+ /// either DW_FORM_addr or DW_FORM_GNU_addr_index.
+ void addLabelAddress(DIE &Die, dwarf::Attribute Attribute,
+ const MCSymbol *Label);
+
+ /// addLocalLabelAddress - Add a dwarf label attribute data and value using
+ /// DW_FORM_addr only.
+ void addLocalLabelAddress(DIE &Die, dwarf::Attribute Attribute,
+ const MCSymbol *Label);
+
+ /// addSectionDelta - Add a label delta attribute data and value.
+ DIE::value_iterator addSectionDelta(DIE &Die, dwarf::Attribute Attribute,
+ const MCSymbol *Hi, const MCSymbol *Lo);
+
+ DwarfCompileUnit &getCU() override { return *this; }
+
+ unsigned getOrCreateSourceID(StringRef FileName, StringRef DirName) override;
+
+ void addImportedEntity(const DIImportedEntity* IE) {
+ ImportedEntities[IE->getScope()].push_back(IE);
+ }
+
+ /// addRange - Add an address range to the list of ranges for this unit.
+ void addRange(RangeSpan Range);
+
+ void attachLowHighPC(DIE &D, const MCSymbol *Begin, const MCSymbol *End);
+
+ /// addSectionLabel - Add a Dwarf section label attribute data and value.
+ ///
+ DIE::value_iterator addSectionLabel(DIE &Die, dwarf::Attribute Attribute,
+ const MCSymbol *Label,
+ const MCSymbol *Sec);
+
+ /// \brief Find DIE for the given subprogram and attach appropriate
+ /// DW_AT_low_pc and DW_AT_high_pc attributes. If there are global
+ /// variables in this scope then create and insert DIEs for these
+ /// variables.
+ DIE &updateSubprogramScopeDIE(const DISubprogram *SP);
+
+ void constructScopeDIE(LexicalScope *Scope,
+ SmallVectorImpl<DIE *> &FinalChildren);
+
+ /// \brief A helper function to construct a RangeSpanList for a given
+ /// lexical scope.
+ void addScopeRangeList(DIE &ScopeDIE, SmallVector<RangeSpan, 2> Range);
+
+ void attachRangesOrLowHighPC(DIE &D, SmallVector<RangeSpan, 2> Ranges);
+
+ void attachRangesOrLowHighPC(DIE &D,
+ const SmallVectorImpl<InsnRange> &Ranges);
+ /// \brief This scope represents inlined body of a function. Construct
+ /// DIE to represent this concrete inlined copy of the function.
+ DIE *constructInlinedScopeDIE(LexicalScope *Scope);
+
+ /// \brief Construct new DW_TAG_lexical_block for this scope and
+ /// attach DW_AT_low_pc/DW_AT_high_pc labels.
+ DIE *constructLexicalScopeDIE(LexicalScope *Scope);
+
+ /// constructVariableDIE - Construct a DIE for the given DbgVariable.
+ DIE *constructVariableDIE(DbgVariable &DV, bool Abstract = false);
+
+ DIE *constructVariableDIE(DbgVariable &DV, const LexicalScope &Scope,
+ DIE *&ObjectPointer);
+
+ /// A helper function to create children of a Scope DIE.
+ DIE *createScopeChildrenDIE(LexicalScope *Scope,
+ SmallVectorImpl<DIE *> &Children,
+ unsigned *ChildScopeCount = nullptr);
+
+ /// \brief Construct a DIE for this subprogram scope.
+ void constructSubprogramScopeDIE(LexicalScope *Scope);
+
+ DIE *createAndAddScopeChildren(LexicalScope *Scope, DIE &ScopeDIE);
+
+ void constructAbstractSubprogramScopeDIE(LexicalScope *Scope);
+
+ /// \brief Construct import_module DIE.
+ DIE *constructImportedEntityDIE(const DIImportedEntity *Module);
+
+ void finishSubprogramDefinition(const DISubprogram *SP);
+
+ void collectDeadVariables(const DISubprogram *SP);
+
+ /// Set the skeleton unit associated with this unit.
+ void setSkeleton(DwarfCompileUnit &Skel) { Skeleton = &Skel; }
+
+ const MCSymbol *getSectionSym() const {
+ assert(Section);
+ return Section->getBeginSymbol();
+ }
+
+ unsigned getLength() {
+ return sizeof(uint32_t) + // Length field
+ getHeaderSize() + UnitDie.getSize();
+ }
+
+ void emitHeader(bool UseOffsets) override;
+
+ MCSymbol *getLabelBegin() const {
+ assert(Section);
+ return LabelBegin;
+ }
+
+ /// Add a new global name to the compile unit.
+ void addGlobalName(StringRef Name, DIE &Die, const DIScope *Context) override;
+
+ /// Add a new global type to the compile unit.
+ void addGlobalType(const DIType *Ty, const DIE &Die,
+ const DIScope *Context) override;
+
+ const StringMap<const DIE *> &getGlobalNames() const { return GlobalNames; }
+ const StringMap<const DIE *> &getGlobalTypes() const { return GlobalTypes; }
+
+ /// Add DW_AT_location attribute for a DbgVariable based on provided
+ /// MachineLocation.
+ void addVariableAddress(const DbgVariable &DV, DIE &Die,
+ MachineLocation Location);
+ /// Add an address attribute to a die based on the location provided.
+ void addAddress(DIE &Die, dwarf::Attribute Attribute,
+ const MachineLocation &Location);
+
+ /// Start with the address based on the location provided, and generate the
+ /// DWARF information necessary to find the actual variable (navigating the
+ /// extra location information encoded in the type) based on the starting
+ /// location. Add the DWARF information to the die.
+ void addComplexAddress(const DbgVariable &DV, DIE &Die,
+ dwarf::Attribute Attribute,
+ const MachineLocation &Location);
+
+ /// Add a Dwarf loclistptr attribute data and value.
+ void addLocationList(DIE &Die, dwarf::Attribute Attribute, unsigned Index);
+ void applyVariableAttributes(const DbgVariable &Var, DIE &VariableDie);
+
+ /// Add a Dwarf expression attribute data and value.
+ void addExpr(DIELoc &Die, dwarf::Form Form, 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;
+ }
+
+ /// getRanges - Get the list of ranges for this unit.
+ const SmallVectorImpl<RangeSpan> &getRanges() const { return CURanges; }
+ SmallVector<RangeSpan, 2> takeRanges() { return std::move(CURanges); }
+
+ void setBaseAddress(const MCSymbol *Base) { BaseAddress = Base; }
+ const MCSymbol *getBaseAddress() const { return BaseAddress; }
+};
+
+} // end llvm namespace
+
+#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
new file mode 100644
index 0000000..3466f34
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -0,0 +1,2018 @@
+//===-- llvm/CodeGen/DwarfDebug.cpp - Dwarf Debug Framework ---------------===//
+//
+// 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 dwarf debug info into asm files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DwarfDebug.h"
+#include "ByteStreamer.h"
+#include "DIEHash.h"
+#include "DebugLocEntry.h"
+#include "DwarfCompileUnit.h"
+#include "DwarfExpression.h"
+#include "DwarfUnit.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/CodeGen/DIE.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DIBuilder.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/ValueHandle.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCDwarf.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/LEB128.h"
+#include "llvm/Support/MD5.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetFrameLowering.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+using namespace llvm;
+
+#define DEBUG_TYPE "dwarfdebug"
+
+static cl::opt<bool>
+DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden,
+ cl::desc("Disable debug info printing"));
+
+static cl::opt<bool> UnknownLocations(
+ "use-unknown-locations", cl::Hidden,
+ cl::desc("Make an absence of debug location information explicit."),
+ cl::init(false));
+
+static cl::opt<bool>
+GenerateGnuPubSections("generate-gnu-dwarf-pub-sections", cl::Hidden,
+ cl::desc("Generate GNU-style pubnames and pubtypes"),
+ cl::init(false));
+
+static cl::opt<bool> GenerateARangeSection("generate-arange-section",
+ cl::Hidden,
+ cl::desc("Generate dwarf aranges"),
+ cl::init(false));
+
+namespace {
+enum DefaultOnOff { Default, Enable, Disable };
+}
+
+static cl::opt<DefaultOnOff>
+DwarfAccelTables("dwarf-accel-tables", cl::Hidden,
+ cl::desc("Output prototype dwarf accelerator tables."),
+ cl::values(clEnumVal(Default, "Default for platform"),
+ clEnumVal(Enable, "Enabled"),
+ clEnumVal(Disable, "Disabled"), clEnumValEnd),
+ cl::init(Default));
+
+static cl::opt<DefaultOnOff>
+SplitDwarf("split-dwarf", cl::Hidden,
+ cl::desc("Output DWARF5 split debug info."),
+ cl::values(clEnumVal(Default, "Default for platform"),
+ clEnumVal(Enable, "Enabled"),
+ clEnumVal(Disable, "Disabled"), clEnumValEnd),
+ cl::init(Default));
+
+static cl::opt<DefaultOnOff>
+DwarfPubSections("generate-dwarf-pub-sections", cl::Hidden,
+ cl::desc("Generate DWARF pubnames and pubtypes sections"),
+ cl::values(clEnumVal(Default, "Default for platform"),
+ clEnumVal(Enable, "Enabled"),
+ clEnumVal(Disable, "Disabled"), clEnumValEnd),
+ cl::init(Default));
+
+static cl::opt<DefaultOnOff>
+DwarfLinkageNames("dwarf-linkage-names", cl::Hidden,
+ cl::desc("Emit DWARF linkage-name attributes."),
+ cl::values(clEnumVal(Default, "Default for platform"),
+ clEnumVal(Enable, "Enabled"),
+ clEnumVal(Disable, "Disabled"), clEnumValEnd),
+ cl::init(Default));
+
+static const char *const DWARFGroupName = "DWARF Emission";
+static const char *const DbgTimerName = "DWARF Debug Writer";
+
+void DebugLocDwarfExpression::EmitOp(uint8_t Op, const char *Comment) {
+ BS.EmitInt8(
+ Op, Comment ? Twine(Comment) + " " + dwarf::OperationEncodingString(Op)
+ : dwarf::OperationEncodingString(Op));
+}
+
+void DebugLocDwarfExpression::EmitSigned(int64_t Value) {
+ BS.EmitSLEB128(Value, Twine(Value));
+}
+
+void DebugLocDwarfExpression::EmitUnsigned(uint64_t Value) {
+ BS.EmitULEB128(Value, Twine(Value));
+}
+
+bool DebugLocDwarfExpression::isFrameRegister(unsigned MachineReg) {
+ // This information is not available while emitting .debug_loc entries.
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+
+/// resolve - Look in the DwarfDebug map for the MDNode that
+/// corresponds to the reference.
+template <typename T> T *DbgVariable::resolve(TypedDINodeRef<T> Ref) const {
+ return DD->resolve(Ref);
+}
+
+bool DbgVariable::isBlockByrefVariable() const {
+ assert(Var && "Invalid complex DbgVariable!");
+ return Var->getType()
+ .resolve(DD->getTypeIdentifierMap())
+ ->isBlockByrefStruct();
+}
+
+const DIType *DbgVariable::getType() const {
+ DIType *Ty = Var->getType().resolve(DD->getTypeIdentifierMap());
+ // FIXME: isBlockByrefVariable should be reformulated in terms of complex
+ // addresses instead.
+ if (Ty->isBlockByrefStruct()) {
+ /* 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 following function dives into the __Block_byref_x_VarName
+ struct to find the original type of the variable. This will be
+ passed back to the code generating the type for the Debug
+ Information Entry for the variable 'VarName'. 'VarName' will then
+ have the original type 'SomeType' in its debug information.
+
+ The original type 'SomeType' will be the type of the field named
+ 'VarName' inside the __Block_byref_x_VarName struct.
+
+ NOTE: In order for this to not completely fail on the debugger
+ side, the Debug Information Entry for the variable VarName needs to
+ have a DW_AT_location that tells the debugger how to unwind through
+ the pointers and __Block_byref_x_VarName struct to find the actual
+ value of the variable. The function addBlockByrefType does this. */
+ DIType *subType = Ty;
+ uint16_t tag = Ty->getTag();
+
+ if (tag == dwarf::DW_TAG_pointer_type)
+ subType = resolve(cast<DIDerivedType>(Ty)->getBaseType());
+
+ auto Elements = cast<DICompositeType>(subType)->getElements();
+ for (unsigned i = 0, N = Elements.size(); i < N; ++i) {
+ auto *DT = cast<DIDerivedType>(Elements[i]);
+ if (getName() == DT->getName())
+ return resolve(DT->getBaseType());
+ }
+ }
+ return Ty;
+}
+
+static LLVM_CONSTEXPR DwarfAccelTable::Atom TypeAtoms[] = {
+ DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4),
+ DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2),
+ DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)};
+
+DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
+ : Asm(A), MMI(Asm->MMI), DebugLocs(A->OutStreamer->isVerboseAsm()),
+ PrevLabel(nullptr), InfoHolder(A, "info_string", DIEValueAllocator),
+ SkeletonHolder(A, "skel_string", DIEValueAllocator),
+ IsDarwin(Triple(A->getTargetTriple()).isOSDarwin()),
+ AccelNames(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
+ dwarf::DW_FORM_data4)),
+ AccelObjC(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
+ dwarf::DW_FORM_data4)),
+ AccelNamespace(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
+ dwarf::DW_FORM_data4)),
+ AccelTypes(TypeAtoms), DebuggerTuning(DebuggerKind::Default) {
+
+ CurFn = nullptr;
+ CurMI = nullptr;
+ Triple TT(Asm->getTargetTriple());
+
+ // Make sure we know our "debugger tuning." The target option takes
+ // precedence; fall back to triple-based defaults.
+ if (Asm->TM.Options.DebuggerTuning != DebuggerKind::Default)
+ DebuggerTuning = Asm->TM.Options.DebuggerTuning;
+ else if (IsDarwin || TT.isOSFreeBSD())
+ DebuggerTuning = DebuggerKind::LLDB;
+ else if (TT.isPS4CPU())
+ DebuggerTuning = DebuggerKind::SCE;
+ else
+ DebuggerTuning = DebuggerKind::GDB;
+
+ // Turn on accelerator tables for LLDB by default.
+ if (DwarfAccelTables == Default)
+ HasDwarfAccelTables = tuneForLLDB();
+ else
+ HasDwarfAccelTables = DwarfAccelTables == Enable;
+
+ // Handle split DWARF. Off by default for now.
+ if (SplitDwarf == Default)
+ HasSplitDwarf = false;
+ else
+ HasSplitDwarf = SplitDwarf == Enable;
+
+ // Pubnames/pubtypes on by default for GDB.
+ if (DwarfPubSections == Default)
+ HasDwarfPubSections = tuneForGDB();
+ else
+ HasDwarfPubSections = DwarfPubSections == Enable;
+
+ // SCE does not use linkage names.
+ if (DwarfLinkageNames == Default)
+ UseLinkageNames = !tuneForSCE();
+ else
+ UseLinkageNames = DwarfLinkageNames == Enable;
+
+ unsigned DwarfVersionNumber = Asm->TM.Options.MCOptions.DwarfVersion;
+ DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber
+ : MMI->getModule()->getDwarfVersion();
+ // Use dwarf 4 by default if nothing is requested.
+ DwarfVersion = DwarfVersion ? DwarfVersion : dwarf::DWARF_VERSION;
+
+ // Work around a GDB bug. GDB doesn't support the standard opcode;
+ // SCE doesn't support GNU's; LLDB prefers the standard opcode, which
+ // is defined as of DWARF 3.
+ // See GDB bug 11616 - DW_OP_form_tls_address is unimplemented
+ // https://sourceware.org/bugzilla/show_bug.cgi?id=11616
+ UseGNUTLSOpcode = tuneForGDB() || DwarfVersion < 3;
+
+ Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion);
+
+ {
+ NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
+ beginModule();
+ }
+}
+
+// Define out of line so we don't have to include DwarfUnit.h in DwarfDebug.h.
+DwarfDebug::~DwarfDebug() { }
+
+static bool isObjCClass(StringRef Name) {
+ return Name.startswith("+") || Name.startswith("-");
+}
+
+static bool hasObjCCategory(StringRef Name) {
+ if (!isObjCClass(Name))
+ return false;
+
+ return Name.find(") ") != StringRef::npos;
+}
+
+static void getObjCClassCategory(StringRef In, StringRef &Class,
+ StringRef &Category) {
+ if (!hasObjCCategory(In)) {
+ Class = In.slice(In.find('[') + 1, In.find(' '));
+ Category = "";
+ return;
+ }
+
+ Class = In.slice(In.find('[') + 1, In.find('('));
+ Category = In.slice(In.find('[') + 1, In.find(' '));
+ return;
+}
+
+static StringRef getObjCMethodName(StringRef In) {
+ return In.slice(In.find(' ') + 1, In.find(']'));
+}
+
+// Add the various names to the Dwarf accelerator table names.
+// TODO: Determine whether or not we should add names for programs
+// that do not have a DW_AT_name or DW_AT_linkage_name field - this
+// is only slightly different than the lookup of non-standard ObjC names.
+void DwarfDebug::addSubprogramNames(const DISubprogram *SP, DIE &Die) {
+ if (!SP->isDefinition())
+ return;
+ addAccelName(SP->getName(), Die);
+
+ // If the linkage name is different than the name, go ahead and output
+ // that as well into the name table.
+ if (SP->getLinkageName() != "" && SP->getName() != SP->getLinkageName())
+ addAccelName(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);
+ if (Category != "")
+ addAccelObjC(Category, Die);
+ // Also add the base method name to the name table.
+ addAccelName(getObjCMethodName(SP->getName()), Die);
+ }
+}
+
+/// Check whether we should create a DIE for the given Scope, return true
+/// if we don't create a DIE (the corresponding DIE is null).
+bool DwarfDebug::isLexicalScopeDIENull(LexicalScope *Scope) {
+ if (Scope->isAbstractScope())
+ return false;
+
+ // We don't create a DIE if there is no Range.
+ const SmallVectorImpl<InsnRange> &Ranges = Scope->getRanges();
+ if (Ranges.empty())
+ return true;
+
+ if (Ranges.size() > 1)
+ return false;
+
+ // We don't create a DIE if we have a single Range and the end label
+ // is null.
+ return !getLabelAfterInsn(Ranges.front().second);
+}
+
+template <typename Func> void forBothCUs(DwarfCompileUnit &CU, Func F) {
+ F(CU);
+ if (auto *SkelCU = CU.getSkeleton())
+ F(*SkelCU);
+}
+
+void DwarfDebug::constructAbstractSubprogramScopeDIE(LexicalScope *Scope) {
+ assert(Scope && Scope->getScopeNode());
+ assert(Scope->isAbstractScope());
+ assert(!Scope->getInlinedAt());
+
+ const MDNode *SP = Scope->getScopeNode();
+
+ ProcessedSPNodes.insert(SP);
+
+ // Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram
+ // was inlined from another compile unit.
+ auto &CU = SPMap[SP];
+ forBothCUs(*CU, [&](DwarfCompileUnit &CU) {
+ CU.constructAbstractSubprogramScopeDIE(Scope);
+ });
+}
+
+void DwarfDebug::addGnuPubAttributes(DwarfUnit &U, DIE &D) const {
+ if (!GenerateGnuPubSections)
+ return;
+
+ U.addFlag(D, dwarf::DW_AT_GNU_pubnames);
+}
+
+// Create new DwarfCompileUnit for the given metadata node with tag
+// DW_TAG_compile_unit.
+DwarfCompileUnit &
+DwarfDebug::constructDwarfCompileUnit(const DICompileUnit *DIUnit) {
+ StringRef FN = DIUnit->getFilename();
+ CompilationDir = DIUnit->getDirectory();
+
+ auto OwnedUnit = make_unique<DwarfCompileUnit>(
+ InfoHolder.getUnits().size(), DIUnit, Asm, this, &InfoHolder);
+ DwarfCompileUnit &NewCU = *OwnedUnit;
+ DIE &Die = NewCU.getUnitDie();
+ InfoHolder.addUnit(std::move(OwnedUnit));
+ if (useSplitDwarf())
+ NewCU.setSkeleton(constructSkeletonCU(NewCU));
+
+ // 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->getContext().setMCLineTableCompilationDir(
+ NewCU.getUniqueID(), CompilationDir);
+
+ NewCU.addString(Die, dwarf::DW_AT_producer, DIUnit->getProducer());
+ NewCU.addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
+ DIUnit->getSourceLanguage());
+ NewCU.addString(Die, dwarf::DW_AT_name, FN);
+
+ if (!useSplitDwarf()) {
+ NewCU.initStmtList();
+
+ // If we're using split dwarf the compilation dir is going to be in the
+ // skeleton CU and so we don't need to duplicate it here.
+ if (!CompilationDir.empty())
+ NewCU.addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
+
+ addGnuPubAttributes(NewCU, Die);
+ }
+
+ if (DIUnit->isOptimized())
+ NewCU.addFlag(Die, dwarf::DW_AT_APPLE_optimized);
+
+ StringRef Flags = DIUnit->getFlags();
+ if (!Flags.empty())
+ NewCU.addString(Die, dwarf::DW_AT_APPLE_flags, Flags);
+
+ if (unsigned RVer = DIUnit->getRuntimeVersion())
+ NewCU.addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
+ dwarf::DW_FORM_data1, RVer);
+
+ if (useSplitDwarf())
+ NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoDWOSection());
+ else
+ NewCU.initSection(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,
+ DIUnit->getDWOId());
+ if (!DIUnit->getSplitDebugFilename().empty())
+ // This is a prefabricated skeleton CU.
+ NewCU.addString(Die, dwarf::DW_AT_GNU_dwo_name,
+ DIUnit->getSplitDebugFilename());
+ }
+
+ CUMap.insert(std::make_pair(DIUnit, &NewCU));
+ CUDieMap.insert(std::make_pair(&Die, &NewCU));
+ return NewCU;
+}
+
+void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU,
+ const DIImportedEntity *N) {
+ if (DIE *D = TheCU.getOrCreateContextDIE(N->getScope()))
+ D->addChild(TheCU.constructImportedEntityDIE(N));
+}
+
+// Emit all Dwarf sections that should come prior to the content. Create
+// global DIEs and emit initial debug info sections. This is invoked by
+// the target AsmPrinter.
+void DwarfDebug::beginModule() {
+ if (DisableDebugInfoPrinting)
+ return;
+
+ const Module *M = MMI->getModule();
+
+ NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
+ if (!CU_Nodes)
+ return;
+ TypeIdentifierMap = generateDITypeIdentifierMap(CU_Nodes);
+
+ SingleCU = CU_Nodes->getNumOperands() == 1;
+
+ for (MDNode *N : CU_Nodes->operands()) {
+ auto *CUNode = cast<DICompileUnit>(N);
+ DwarfCompileUnit &CU = constructDwarfCompileUnit(CUNode);
+ for (auto *IE : CUNode->getImportedEntities())
+ CU.addImportedEntity(IE);
+ for (auto *GV : CUNode->getGlobalVariables())
+ CU.getOrCreateGlobalVariableDIE(GV);
+ for (auto *SP : CUNode->getSubprograms())
+ SPMap.insert(std::make_pair(SP, &CU));
+ for (auto *Ty : CUNode->getEnumTypes()) {
+ // The enum types array by design contains pointers to
+ // MDNodes rather than DIRefs. Unique them here.
+ CU.getOrCreateTypeDIE(cast<DIType>(resolve(Ty->getRef())));
+ }
+ for (auto *Ty : CUNode->getRetainedTypes()) {
+ // The retained types array by design contains pointers to
+ // MDNodes rather than DIRefs. Unique them here.
+ DIType *RT = cast<DIType>(resolve(Ty->getRef()));
+ if (!RT->isExternalTypeRef())
+ // There is no point in force-emitting a forward declaration.
+ CU.getOrCreateTypeDIE(RT);
+ }
+ // Emit imported_modules last so that the relevant context is already
+ // available.
+ for (auto *IE : CUNode->getImportedEntities())
+ constructAndAddImportedEntityDIE(CU, IE);
+ }
+
+ // Tell MMI that we have debug info.
+ MMI->setDebugInfoAvailability(true);
+}
+
+void DwarfDebug::finishVariableDefinitions() {
+ for (const auto &Var : ConcreteVariables) {
+ DIE *VariableDie = Var->getDIE();
+ assert(VariableDie);
+ // FIXME: Consider the time-space tradeoff of just storing the unit pointer
+ // in the ConcreteVariables list, rather than looking it up again here.
+ // DIE::getUnit isn't simple - it walks parent pointers, etc.
+ DwarfCompileUnit *Unit = lookupUnit(VariableDie->getUnit());
+ assert(Unit);
+ DbgVariable *AbsVar = getExistingAbstractVariable(
+ InlinedVariable(Var->getVariable(), Var->getInlinedAt()));
+ if (AbsVar && AbsVar->getDIE()) {
+ Unit->addDIEEntry(*VariableDie, dwarf::DW_AT_abstract_origin,
+ *AbsVar->getDIE());
+ } else
+ Unit->applyVariableAttributes(*Var, *VariableDie);
+ }
+}
+
+void DwarfDebug::finishSubprogramDefinitions() {
+ for (const auto &P : SPMap)
+ forBothCUs(*P.second, [&](DwarfCompileUnit &CU) {
+ CU.finishSubprogramDefinition(cast<DISubprogram>(P.first));
+ });
+}
+
+
+// Collect info for variables that were optimized out.
+void DwarfDebug::collectDeadVariables() {
+ const Module *M = MMI->getModule();
+
+ if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) {
+ for (MDNode *N : CU_Nodes->operands()) {
+ auto *TheCU = cast<DICompileUnit>(N);
+ // Construct subprogram DIE and add variables DIEs.
+ DwarfCompileUnit *SPCU =
+ static_cast<DwarfCompileUnit *>(CUMap.lookup(TheCU));
+ assert(SPCU && "Unable to find Compile Unit!");
+ for (auto *SP : TheCU->getSubprograms()) {
+ if (ProcessedSPNodes.count(SP) != 0)
+ continue;
+ SPCU->collectDeadVariables(SP);
+ }
+ }
+ }
+}
+
+void DwarfDebug::finalizeModuleInfo() {
+ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
+
+ finishSubprogramDefinitions();
+
+ finishVariableDefinitions();
+
+ // Collect info for variables that were optimized out.
+ collectDeadVariables();
+
+ // Handle anything that needs to be done on a per-unit basis after
+ // all other generation.
+ for (const auto &P : CUMap) {
+ auto &TheCU = *P.second;
+ // Emit DW_AT_containing_type attribute to connect types with their
+ // vtable holding type.
+ TheCU.constructContainingTypeDIEs();
+
+ // Add CU specific attributes if we need to add any.
+ // 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()) {
+ // Emit a unique identifier for this CU.
+ uint64_t ID = DIEHash(Asm).computeCUSignature(TheCU.getUnitDie());
+ TheCU.addUInt(TheCU.getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
+ dwarf::DW_FORM_data8, ID);
+ 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 (!SkCU->getRangeLists().empty()) {
+ const MCSymbol *Sym = TLOF.getDwarfRangesSection()->getBeginSymbol();
+ SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_ranges_base,
+ Sym, Sym);
+ }
+ }
+
+ // If we have code split among multiple sections or non-contiguous
+ // ranges of code then emit a DW_AT_ranges attribute on the unit that will
+ // remain in the .o file, otherwise add a DW_AT_low_pc.
+ // FIXME: We should use ranges allow reordering of code ala
+ // .subsections_via_symbols in mach-o. This would mean turning on
+ // ranges for all subprogram DIEs for mach-o.
+ DwarfCompileUnit &U = SkCU ? *SkCU : TheCU;
+ if (unsigned NumRanges = TheCU.getRanges().size()) {
+ if (NumRanges > 1)
+ // A DW_AT_low_pc attribute may also be specified in combination with
+ // DW_AT_ranges to specify the default base address for use in
+ // location lists (see Section 2.6.2) and range lists (see Section
+ // 2.17.3).
+ U.addUInt(U.getUnitDie(), dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0);
+ else
+ U.setBaseAddress(TheCU.getRanges().front().getStart());
+ U.attachRangesOrLowHighPC(U.getUnitDie(), TheCU.takeRanges());
+ }
+ }
+
+ // Compute DIE offsets and sizes.
+ InfoHolder.computeSizeAndOffsets();
+ if (useSplitDwarf())
+ SkeletonHolder.computeSizeAndOffsets();
+}
+
+// Emit all Dwarf sections that should come after the content.
+void DwarfDebug::endModule() {
+ assert(CurFn == nullptr);
+ assert(CurMI == nullptr);
+
+ // If we aren't actually generating debug info (check beginModule -
+ // conditionalized on !DisableDebugInfoPrinting and the presence of the
+ // llvm.dbg.cu metadata node)
+ if (!MMI->hasDebugInfo())
+ return;
+
+ // Finalize the debug info for the module.
+ finalizeModuleInfo();
+
+ emitDebugStr();
+
+ if (useSplitDwarf())
+ emitDebugLocDWO();
+ else
+ // Emit info into a debug loc section.
+ emitDebugLoc();
+
+ // Corresponding abbreviations into a abbrev section.
+ emitAbbreviations();
+
+ // Emit all the DIEs into a debug info section.
+ emitDebugInfo();
+
+ // Emit info into a debug aranges section.
+ if (GenerateARangeSection)
+ emitDebugARanges();
+
+ // Emit info into a debug ranges section.
+ emitDebugRanges();
+
+ if (useSplitDwarf()) {
+ emitDebugStrDWO();
+ emitDebugInfoDWO();
+ emitDebugAbbrevDWO();
+ emitDebugLineDWO();
+ // Emit DWO addresses.
+ AddrPool.emit(*Asm, Asm->getObjFileLowering().getDwarfAddrSection());
+ }
+
+ // Emit info into the dwarf accelerator table sections.
+ if (useDwarfAccelTables()) {
+ emitAccelNames();
+ emitAccelObjC();
+ emitAccelNamespaces();
+ emitAccelTypes();
+ }
+
+ // Emit the pubnames and pubtypes sections if requested.
+ if (HasDwarfPubSections) {
+ emitDebugPubNames(GenerateGnuPubSections);
+ emitDebugPubTypes(GenerateGnuPubSections);
+ }
+
+ // clean up.
+ SPMap.clear();
+ AbstractVariables.clear();
+}
+
+// Find abstract variable, if any, associated with Var.
+DbgVariable *
+DwarfDebug::getExistingAbstractVariable(InlinedVariable IV,
+ const DILocalVariable *&Cleansed) {
+ // More then one inlined variable corresponds to one abstract variable.
+ Cleansed = IV.first;
+ auto I = AbstractVariables.find(Cleansed);
+ if (I != AbstractVariables.end())
+ return I->second.get();
+ return nullptr;
+}
+
+DbgVariable *DwarfDebug::getExistingAbstractVariable(InlinedVariable IV) {
+ const DILocalVariable *Cleansed;
+ return getExistingAbstractVariable(IV, Cleansed);
+}
+
+void DwarfDebug::createAbstractVariable(const DILocalVariable *Var,
+ LexicalScope *Scope) {
+ auto AbsDbgVariable = make_unique<DbgVariable>(Var, /* IA */ nullptr, this);
+ InfoHolder.addScopeVariable(Scope, AbsDbgVariable.get());
+ AbstractVariables[Var] = std::move(AbsDbgVariable);
+}
+
+void DwarfDebug::ensureAbstractVariableIsCreated(InlinedVariable IV,
+ const MDNode *ScopeNode) {
+ const DILocalVariable *Cleansed = nullptr;
+ if (getExistingAbstractVariable(IV, Cleansed))
+ return;
+
+ createAbstractVariable(Cleansed, LScopes.getOrCreateAbstractScope(
+ cast<DILocalScope>(ScopeNode)));
+}
+
+void DwarfDebug::ensureAbstractVariableIsCreatedIfScoped(
+ InlinedVariable IV, const MDNode *ScopeNode) {
+ const DILocalVariable *Cleansed = nullptr;
+ if (getExistingAbstractVariable(IV, Cleansed))
+ return;
+
+ if (LexicalScope *Scope =
+ LScopes.findAbstractScope(cast_or_null<DILocalScope>(ScopeNode)))
+ createAbstractVariable(Cleansed, Scope);
+}
+
+// Collect variable information from side table maintained by MMI.
+void DwarfDebug::collectVariableInfoFromMMITable(
+ DenseSet<InlinedVariable> &Processed) {
+ for (const auto &VI : MMI->getVariableDbgInfo()) {
+ if (!VI.Var)
+ continue;
+ assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) &&
+ "Expected inlined-at fields to agree");
+
+ InlinedVariable Var(VI.Var, VI.Loc->getInlinedAt());
+ Processed.insert(Var);
+ LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc);
+
+ // If variable scope is not found then skip this variable.
+ if (!Scope)
+ continue;
+
+ ensureAbstractVariableIsCreatedIfScoped(Var, Scope->getScopeNode());
+ auto RegVar = make_unique<DbgVariable>(Var.first, Var.second, this);
+ RegVar->initializeMMI(VI.Expr, VI.Slot);
+ if (InfoHolder.addScopeVariable(Scope, RegVar.get()))
+ ConcreteVariables.push_back(std::move(RegVar));
+ }
+}
+
+// Get .debug_loc entry for the instruction range starting at MI.
+static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) {
+ const DIExpression *Expr = MI->getDebugExpression();
+
+ assert(MI->getNumOperands() == 4);
+ if (MI->getOperand(0).isReg()) {
+ MachineLocation MLoc;
+ // If the second operand is an immediate, this is a
+ // register-indirect address.
+ if (!MI->getOperand(1).isImm())
+ MLoc.set(MI->getOperand(0).getReg());
+ else
+ MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
+ return DebugLocEntry::Value(Expr, MLoc);
+ }
+ if (MI->getOperand(0).isImm())
+ return DebugLocEntry::Value(Expr, MI->getOperand(0).getImm());
+ if (MI->getOperand(0).isFPImm())
+ return DebugLocEntry::Value(Expr, MI->getOperand(0).getFPImm());
+ if (MI->getOperand(0).isCImm())
+ return DebugLocEntry::Value(Expr, MI->getOperand(0).getCImm());
+
+ llvm_unreachable("Unexpected 4-operand DBG_VALUE instruction!");
+}
+
+/// Determine whether two variable pieces overlap.
+static bool piecesOverlap(const DIExpression *P1, const DIExpression *P2) {
+ if (!P1->isBitPiece() || !P2->isBitPiece())
+ return true;
+ unsigned l1 = P1->getBitPieceOffset();
+ unsigned l2 = P2->getBitPieceOffset();
+ unsigned r1 = l1 + P1->getBitPieceSize();
+ unsigned r2 = l2 + P2->getBitPieceSize();
+ // True where [l1,r1[ and [r1,r2[ overlap.
+ return (l1 < r2) && (l2 < r1);
+}
+
+/// Build the location list for all DBG_VALUEs in the function that
+/// describe the same variable. If the ranges of several independent
+/// pieces of the same variable overlap partially, split them up and
+/// combine the ranges. The resulting DebugLocEntries are will have
+/// strict monotonically increasing begin addresses and will never
+/// overlap.
+//
+// Input:
+//
+// Ranges History [var, loc, piece ofs size]
+// 0 | [x, (reg0, piece 0, 32)]
+// 1 | | [x, (reg1, piece 32, 32)] <- IsPieceOfPrevEntry
+// 2 | | ...
+// 3 | [clobber reg0]
+// 4 [x, (mem, piece 0, 64)] <- overlapping with both previous pieces of
+// x.
+//
+// Output:
+//
+// [0-1] [x, (reg0, piece 0, 32)]
+// [1-3] [x, (reg0, piece 0, 32), (reg1, piece 32, 32)]
+// [3-4] [x, (reg1, piece 32, 32)]
+// [4- ] [x, (mem, piece 0, 64)]
+void
+DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
+ const DbgValueHistoryMap::InstrRanges &Ranges) {
+ SmallVector<DebugLocEntry::Value, 4> OpenRanges;
+
+ for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
+ const MachineInstr *Begin = I->first;
+ const MachineInstr *End = I->second;
+ assert(Begin->isDebugValue() && "Invalid History entry");
+
+ // Check if a variable is inaccessible in this range.
+ if (Begin->getNumOperands() > 1 &&
+ Begin->getOperand(0).isReg() && !Begin->getOperand(0).getReg()) {
+ OpenRanges.clear();
+ continue;
+ }
+
+ // If this piece overlaps with any open ranges, truncate them.
+ const DIExpression *DIExpr = Begin->getDebugExpression();
+ auto Last = std::remove_if(OpenRanges.begin(), OpenRanges.end(),
+ [&](DebugLocEntry::Value R) {
+ return piecesOverlap(DIExpr, R.getExpression());
+ });
+ OpenRanges.erase(Last, OpenRanges.end());
+
+ const MCSymbol *StartLabel = getLabelBeforeInsn(Begin);
+ assert(StartLabel && "Forgot label before DBG_VALUE starting a range!");
+
+ const MCSymbol *EndLabel;
+ if (End != nullptr)
+ EndLabel = getLabelAfterInsn(End);
+ else if (std::next(I) == Ranges.end())
+ EndLabel = Asm->getFunctionEnd();
+ else
+ EndLabel = getLabelBeforeInsn(std::next(I)->first);
+ assert(EndLabel && "Forgot label after instruction ending a range!");
+
+ DEBUG(dbgs() << "DotDebugLoc: " << *Begin << "\n");
+
+ auto Value = getDebugLocValue(Begin);
+ DebugLocEntry Loc(StartLabel, EndLabel, Value);
+ bool couldMerge = false;
+
+ // If this is a piece, it may belong to the current DebugLocEntry.
+ if (DIExpr->isBitPiece()) {
+ // Add this value to the list of open ranges.
+ OpenRanges.push_back(Value);
+
+ // Attempt to add the piece to the last entry.
+ if (!DebugLoc.empty())
+ if (DebugLoc.back().MergeValues(Loc))
+ couldMerge = true;
+ }
+
+ if (!couldMerge) {
+ // Need to add a new DebugLocEntry. Add all values from still
+ // valid non-overlapping pieces.
+ if (OpenRanges.size())
+ Loc.addValues(OpenRanges);
+
+ DebugLoc.push_back(std::move(Loc));
+ }
+
+ // Attempt to coalesce the ranges of two otherwise identical
+ // DebugLocEntries.
+ auto CurEntry = DebugLoc.rbegin();
+ DEBUG({
+ dbgs() << CurEntry->getValues().size() << " Values:\n";
+ for (auto &Value : CurEntry->getValues())
+ Value.getExpression()->dump();
+ dbgs() << "-----\n";
+ });
+
+ auto PrevEntry = std::next(CurEntry);
+ if (PrevEntry != DebugLoc.rend() && PrevEntry->MergeRanges(*CurEntry))
+ DebugLoc.pop_back();
+ }
+}
+
+DbgVariable *DwarfDebug::createConcreteVariable(LexicalScope &Scope,
+ InlinedVariable IV) {
+ ensureAbstractVariableIsCreatedIfScoped(IV, Scope.getScopeNode());
+ ConcreteVariables.push_back(
+ make_unique<DbgVariable>(IV.first, IV.second, this));
+ InfoHolder.addScopeVariable(&Scope, ConcreteVariables.back().get());
+ return ConcreteVariables.back().get();
+}
+
+// Find variables for each lexical scope.
+void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU,
+ const DISubprogram *SP,
+ DenseSet<InlinedVariable> &Processed) {
+ // Grab the variable info that was squirreled away in the MMI side-table.
+ collectVariableInfoFromMMITable(Processed);
+
+ for (const auto &I : DbgValues) {
+ InlinedVariable IV = I.first;
+ if (Processed.count(IV))
+ continue;
+
+ // Instruction ranges, specifying where IV is accessible.
+ const auto &Ranges = I.second;
+ if (Ranges.empty())
+ continue;
+
+ LexicalScope *Scope = nullptr;
+ if (const DILocation *IA = IV.second)
+ Scope = LScopes.findInlinedScope(IV.first->getScope(), IA);
+ else
+ Scope = LScopes.findLexicalScope(IV.first->getScope());
+ // If variable scope is not found then skip this variable.
+ if (!Scope)
+ continue;
+
+ Processed.insert(IV);
+ DbgVariable *RegVar = createConcreteVariable(*Scope, IV);
+
+ const MachineInstr *MInsn = Ranges.front().first;
+ assert(MInsn->isDebugValue() && "History must begin with debug value");
+
+ // Check if the first DBG_VALUE is valid for the rest of the function.
+ if (Ranges.size() == 1 && Ranges.front().second == nullptr) {
+ RegVar->initializeDbgValue(MInsn);
+ continue;
+ }
+
+ // Handle multiple DBG_VALUE instructions describing one variable.
+ DebugLocStream::ListBuilder List(DebugLocs, TheCU, *Asm, *RegVar, *MInsn);
+
+ // Build the location list for this variable.
+ SmallVector<DebugLocEntry, 8> Entries;
+ buildLocationList(Entries, Ranges);
+
+ // If the variable has an DIBasicType, extract it. Basic types cannot have
+ // 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()));
+
+ // 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 (const DILocalVariable *DV : SP->getVariables()) {
+ if (Processed.insert(InlinedVariable(DV, nullptr)).second)
+ if (LexicalScope *Scope = LScopes.findLexicalScope(DV->getScope()))
+ createConcreteVariable(*Scope, InlinedVariable(DV, nullptr));
+ }
+}
+
+// Return Label preceding the instruction.
+MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) {
+ MCSymbol *Label = LabelsBeforeInsn.lookup(MI);
+ assert(Label && "Didn't insert label before instruction");
+ return Label;
+}
+
+// Return Label immediately following the instruction.
+MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) {
+ return LabelsAfterInsn.lookup(MI);
+}
+
+// Process beginning of an instruction.
+void DwarfDebug::beginInstruction(const MachineInstr *MI) {
+ assert(CurMI == nullptr);
+ CurMI = MI;
+ // Check if source location changes, but ignore DBG_VALUE locations.
+ if (!MI->isDebugValue()) {
+ DebugLoc DL = MI->getDebugLoc();
+ if (DL != PrevInstLoc) {
+ if (DL) {
+ unsigned Flags = 0;
+ PrevInstLoc = DL;
+ if (DL == PrologEndLoc) {
+ Flags |= DWARF2_FLAG_PROLOGUE_END;
+ PrologEndLoc = DebugLoc();
+ Flags |= DWARF2_FLAG_IS_STMT;
+ }
+ if (DL.getLine() !=
+ Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine())
+ Flags |= DWARF2_FLAG_IS_STMT;
+
+ const MDNode *Scope = DL.getScope();
+ recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags);
+ } else if (UnknownLocations) {
+ PrevInstLoc = DL;
+ recordSourceLine(0, 0, nullptr, 0);
+ }
+ }
+ }
+
+ // Insert labels where requested.
+ DenseMap<const MachineInstr *, MCSymbol *>::iterator I =
+ LabelsBeforeInsn.find(MI);
+
+ // No label needed.
+ if (I == LabelsBeforeInsn.end())
+ return;
+
+ // Label already assigned.
+ if (I->second)
+ return;
+
+ if (!PrevLabel) {
+ PrevLabel = MMI->getContext().createTempSymbol();
+ Asm->OutStreamer->EmitLabel(PrevLabel);
+ }
+ I->second = PrevLabel;
+}
+
+// Process end of an instruction.
+void DwarfDebug::endInstruction() {
+ assert(CurMI != nullptr);
+ // Don't create a new label after DBG_VALUE instructions.
+ // They don't generate code.
+ if (!CurMI->isDebugValue())
+ PrevLabel = nullptr;
+
+ DenseMap<const MachineInstr *, MCSymbol *>::iterator I =
+ LabelsAfterInsn.find(CurMI);
+ CurMI = nullptr;
+
+ // No label needed.
+ if (I == LabelsAfterInsn.end())
+ return;
+
+ // Label already assigned.
+ if (I->second)
+ return;
+
+ // We need a label after this instruction.
+ if (!PrevLabel) {
+ PrevLabel = MMI->getContext().createTempSymbol();
+ Asm->OutStreamer->EmitLabel(PrevLabel);
+ }
+ I->second = PrevLabel;
+}
+
+// Each LexicalScope has first instruction and last instruction to mark
+// beginning and end of a scope respectively. Create an inverse map that list
+// scopes starts (and ends) with an instruction. One instruction may start (or
+// end) multiple scopes. Ignore scopes that are not reachable.
+void DwarfDebug::identifyScopeMarkers() {
+ SmallVector<LexicalScope *, 4> WorkList;
+ WorkList.push_back(LScopes.getCurrentFunctionScope());
+ while (!WorkList.empty()) {
+ LexicalScope *S = WorkList.pop_back_val();
+
+ const SmallVectorImpl<LexicalScope *> &Children = S->getChildren();
+ if (!Children.empty())
+ WorkList.append(Children.begin(), Children.end());
+
+ if (S->isAbstractScope())
+ continue;
+
+ for (const InsnRange &R : S->getRanges()) {
+ assert(R.first && "InsnRange does not have first instruction!");
+ assert(R.second && "InsnRange does not have second instruction!");
+ requestLabelBeforeInsn(R.first);
+ requestLabelAfterInsn(R.second);
+ }
+ }
+}
+
+static DebugLoc findPrologueEndLoc(const MachineFunction *MF) {
+ // First known non-DBG_VALUE and non-frame setup location marks
+ // the beginning of the function body.
+ for (const auto &MBB : *MF)
+ for (const auto &MI : MBB)
+ if (!MI.isDebugValue() && !MI.getFlag(MachineInstr::FrameSetup) &&
+ MI.getDebugLoc())
+ return MI.getDebugLoc();
+ return DebugLoc();
+}
+
+// Gather pre-function debug information. Assumes being called immediately
+// after the function entry point has been emitted.
+void DwarfDebug::beginFunction(const MachineFunction *MF) {
+ CurFn = MF;
+
+ // If there's no debug info for the function we're not going to do anything.
+ if (!MMI->hasDebugInfo())
+ return;
+
+ auto DI = MF->getFunction()->getSubprogram();
+ if (!DI)
+ return;
+
+ // Grab the lexical scopes for the function, if we don't have any of those
+ // then we're not going to be able to do anything.
+ LScopes.initialize(*MF);
+ if (LScopes.empty())
+ return;
+
+ assert(DbgValues.empty() && "DbgValues map wasn't cleaned!");
+
+ // Make sure that each lexical scope will have a begin/end label.
+ identifyScopeMarkers();
+
+ // Set DwarfDwarfCompileUnitID in MCContext to the Compile Unit this function
+ // belongs to so that we add to the correct per-cu line table in the
+ // non-asm case.
+ LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
+ // FnScope->getScopeNode() and DI->second should represent the same function,
+ // though they may not be the same MDNode due to inline functions merged in
+ // LTO where the debug info metadata still differs (either due to distinct
+ // written differences - two versions of a linkonce_odr function
+ // written/copied into two separate files, or some sub-optimal metadata that
+ // isn't structurally identical (see: file path/name info from clang, which
+ // includes the directory of the cpp file being built, even when the file name
+ // is absolute (such as an <> lookup header)))
+ DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
+ assert(TheCU && "Unable to find compile unit!");
+ if (Asm->OutStreamer->hasRawTextSupport())
+ // Use a single line table if we are generating assembly.
+ Asm->OutStreamer->getContext().setDwarfCompileUnitID(0);
+ else
+ Asm->OutStreamer->getContext().setDwarfCompileUnitID(TheCU->getUniqueID());
+
+ // Calculate history for local variables.
+ calculateDbgValueHistory(MF, Asm->MF->getSubtarget().getRegisterInfo(),
+ DbgValues);
+
+ // Request labels for the full history.
+ for (const auto &I : DbgValues) {
+ const auto &Ranges = I.second;
+ if (Ranges.empty())
+ continue;
+
+ // The first mention of a function argument gets the CurrentFnBegin
+ // label, so arguments are visible when breaking at function entry.
+ const DILocalVariable *DIVar = Ranges.front().first->getDebugVariable();
+ if (DIVar->isParameter() &&
+ getDISubprogram(DIVar->getScope())->describes(MF->getFunction())) {
+ LabelsBeforeInsn[Ranges.front().first] = Asm->getFunctionBegin();
+ if (Ranges.front().first->getDebugExpression()->isBitPiece()) {
+ // Mark all non-overlapping initial pieces.
+ for (auto I = Ranges.begin(); I != Ranges.end(); ++I) {
+ const DIExpression *Piece = I->first->getDebugExpression();
+ if (std::all_of(Ranges.begin(), I,
+ [&](DbgValueHistoryMap::InstrRange Pred) {
+ return !piecesOverlap(Piece, Pred.first->getDebugExpression());
+ }))
+ LabelsBeforeInsn[I->first] = Asm->getFunctionBegin();
+ else
+ break;
+ }
+ }
+ }
+
+ for (const auto &Range : Ranges) {
+ requestLabelBeforeInsn(Range.first);
+ if (Range.second)
+ requestLabelAfterInsn(Range.second);
+ }
+ }
+
+ PrevInstLoc = DebugLoc();
+ PrevLabel = Asm->getFunctionBegin();
+
+ // Record beginning of function.
+ PrologEndLoc = findPrologueEndLoc(MF);
+ if (DILocation *L = PrologEndLoc) {
+ // We'd like to list the prologue as "not statements" but GDB behaves
+ // poorly if we do that. Revisit this with caution/GDB (7.5+) testing.
+ auto *SP = L->getInlinedAtScope()->getSubprogram();
+ recordSourceLine(SP->getScopeLine(), 0, SP, DWARF2_FLAG_IS_STMT);
+ }
+}
+
+// Gather and emit post-function debug information.
+void DwarfDebug::endFunction(const MachineFunction *MF) {
+ assert(CurFn == MF &&
+ "endFunction should be called with the same function as beginFunction");
+
+ if (!MMI->hasDebugInfo() || LScopes.empty() ||
+ !MF->getFunction()->getSubprogram()) {
+ // If we don't have a lexical scope for this function then there will
+ // be a hole in the range information. Keep note of this by setting the
+ // previously used section to nullptr.
+ PrevCU = nullptr;
+ CurFn = nullptr;
+ return;
+ }
+
+ // Set DwarfDwarfCompileUnitID in MCContext to default value.
+ Asm->OutStreamer->getContext().setDwarfCompileUnitID(0);
+
+ LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
+ auto *SP = cast<DISubprogram>(FnScope->getScopeNode());
+ DwarfCompileUnit &TheCU = *SPMap.lookup(SP);
+
+ DenseSet<InlinedVariable> ProcessedVars;
+ collectVariableInfo(TheCU, SP, ProcessedVars);
+
+ // Add the range of this function to the list of ranges for the CU.
+ TheCU.addRange(RangeSpan(Asm->getFunctionBegin(), Asm->getFunctionEnd()));
+
+ // Under -gmlt, skip building the subprogram if there are no inlined
+ // subroutines inside it.
+ if (TheCU.getCUNode()->getEmissionKind() == DIBuilder::LineTablesOnly &&
+ LScopes.getAbstractScopesList().empty() && !IsDarwin) {
+ assert(InfoHolder.getScopeVariables().empty());
+ assert(DbgValues.empty());
+ // FIXME: This wouldn't be true in LTO with a -g (with inlining) CU followed
+ // by a -gmlt CU. Add a test and remove this assertion.
+ assert(AbstractVariables.empty());
+ LabelsBeforeInsn.clear();
+ LabelsAfterInsn.clear();
+ PrevLabel = nullptr;
+ CurFn = nullptr;
+ return;
+ }
+
+#ifndef NDEBUG
+ size_t NumAbstractScopes = LScopes.getAbstractScopesList().size();
+#endif
+ // Construct abstract scopes.
+ for (LexicalScope *AScope : LScopes.getAbstractScopesList()) {
+ auto *SP = cast<DISubprogram>(AScope->getScopeNode());
+ // Collect info for variables that were optimized out.
+ for (const DILocalVariable *DV : SP->getVariables()) {
+ if (!ProcessedVars.insert(InlinedVariable(DV, nullptr)).second)
+ continue;
+ ensureAbstractVariableIsCreated(InlinedVariable(DV, nullptr),
+ DV->getScope());
+ assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes
+ && "ensureAbstractVariableIsCreated inserted abstract scopes");
+ }
+ constructAbstractSubprogramScopeDIE(AScope);
+ }
+
+ TheCU.constructSubprogramScopeDIE(FnScope);
+ if (auto *SkelCU = TheCU.getSkeleton())
+ if (!LScopes.getAbstractScopesList().empty())
+ SkelCU->constructSubprogramScopeDIE(FnScope);
+
+ // 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();
+ DbgValues.clear();
+ LabelsBeforeInsn.clear();
+ LabelsAfterInsn.clear();
+ PrevLabel = nullptr;
+ CurFn = nullptr;
+}
+
+// Register a source line with debug info. Returns the unique label that was
+// emitted and which provides correspondence to the source line list.
+void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
+ unsigned Flags) {
+ StringRef Fn;
+ StringRef Dir;
+ unsigned Src = 1;
+ unsigned Discriminator = 0;
+ if (auto *Scope = cast_or_null<DIScope>(S)) {
+ Fn = Scope->getFilename();
+ Dir = Scope->getDirectory();
+ if (auto *LBF = dyn_cast<DILexicalBlockFile>(Scope))
+ Discriminator = LBF->getDiscriminator();
+
+ unsigned CUID = Asm->OutStreamer->getContext().getDwarfCompileUnitID();
+ Src = static_cast<DwarfCompileUnit &>(*InfoHolder.getUnits()[CUID])
+ .getOrCreateSourceID(Fn, Dir);
+ }
+ Asm->OutStreamer->EmitDwarfLocDirective(Src, Line, Col, Flags, 0,
+ Discriminator, Fn);
+}
+
+//===----------------------------------------------------------------------===//
+// Emit Methods
+//===----------------------------------------------------------------------===//
+
+// Emit the debug info section.
+void DwarfDebug::emitDebugInfo() {
+ DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
+ Holder.emitUnits(/* UseOffsets */ false);
+}
+
+// Emit the abbreviation section.
+void DwarfDebug::emitAbbreviations() {
+ DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
+
+ Holder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection());
+}
+
+void DwarfDebug::emitAccel(DwarfAccelTable &Accel, MCSection *Section,
+ StringRef TableName) {
+ Accel.FinalizeTable(Asm, TableName);
+ Asm->OutStreamer->SwitchSection(Section);
+
+ // Emit the full data.
+ Accel.emit(Asm, Section->getBeginSymbol(), this);
+}
+
+// Emit visible names into a hashed accelerator table section.
+void DwarfDebug::emitAccelNames() {
+ emitAccel(AccelNames, Asm->getObjFileLowering().getDwarfAccelNamesSection(),
+ "Names");
+}
+
+// Emit objective C classes and categories into a hashed accelerator table
+// section.
+void DwarfDebug::emitAccelObjC() {
+ emitAccel(AccelObjC, Asm->getObjFileLowering().getDwarfAccelObjCSection(),
+ "ObjC");
+}
+
+// Emit namespace dies into a hashed accelerator table.
+void DwarfDebug::emitAccelNamespaces() {
+ emitAccel(AccelNamespace,
+ Asm->getObjFileLowering().getDwarfAccelNamespaceSection(),
+ "namespac");
+}
+
+// Emit type dies into a hashed accelerator table.
+void DwarfDebug::emitAccelTypes() {
+ emitAccel(AccelTypes, Asm->getObjFileLowering().getDwarfAccelTypesSection(),
+ "types");
+}
+
+// Public name handling.
+// The format for the various pubnames:
+//
+// dwarf pubnames - offset/name pairs where the offset is the offset into the CU
+// for the DIE that is named.
+//
+// gnu pubnames - offset/index value/name tuples where the offset is the offset
+// into the CU and the index value is computed according to the type of value
+// for the DIE that is named.
+//
+// For type units the offset is the offset of the skeleton DIE. For split dwarf
+// it's the offset within the debug_info/debug_types dwo section, however, the
+// reference in the pubname header doesn't change.
+
+/// computeIndexValue - Compute the gdb index value for the DIE and CU.
+static dwarf::PubIndexEntryDescriptor computeIndexValue(DwarfUnit *CU,
+ const DIE *Die) {
+ dwarf::GDBIndexEntryLinkage Linkage = dwarf::GIEL_STATIC;
+
+ // We could have a specification DIE that has our most of our knowledge,
+ // look for that now.
+ if (DIEValue SpecVal = Die->findAttribute(dwarf::DW_AT_specification)) {
+ DIE &SpecDIE = SpecVal.getDIEEntry().getEntry();
+ if (SpecDIE.findAttribute(dwarf::DW_AT_external))
+ Linkage = dwarf::GIEL_EXTERNAL;
+ } else if (Die->findAttribute(dwarf::DW_AT_external))
+ Linkage = dwarf::GIEL_EXTERNAL;
+
+ switch (Die->getTag()) {
+ case dwarf::DW_TAG_class_type:
+ case dwarf::DW_TAG_structure_type:
+ case dwarf::DW_TAG_union_type:
+ case dwarf::DW_TAG_enumeration_type:
+ return dwarf::PubIndexEntryDescriptor(
+ dwarf::GIEK_TYPE, CU->getLanguage() != dwarf::DW_LANG_C_plus_plus
+ ? dwarf::GIEL_STATIC
+ : dwarf::GIEL_EXTERNAL);
+ case dwarf::DW_TAG_typedef:
+ case dwarf::DW_TAG_base_type:
+ case dwarf::DW_TAG_subrange_type:
+ return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_TYPE, dwarf::GIEL_STATIC);
+ case dwarf::DW_TAG_namespace:
+ return dwarf::GIEK_TYPE;
+ case dwarf::DW_TAG_subprogram:
+ return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_FUNCTION, Linkage);
+ case dwarf::DW_TAG_variable:
+ return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_VARIABLE, Linkage);
+ case dwarf::DW_TAG_enumerator:
+ return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_VARIABLE,
+ dwarf::GIEL_STATIC);
+ default:
+ return dwarf::GIEK_NONE;
+ }
+}
+
+/// emitDebugPubNames - Emit visible names into a debug pubnames section.
+///
+void DwarfDebug::emitDebugPubNames(bool GnuStyle) {
+ MCSection *PSec = GnuStyle
+ ? Asm->getObjFileLowering().getDwarfGnuPubNamesSection()
+ : Asm->getObjFileLowering().getDwarfPubNamesSection();
+
+ emitDebugPubSection(GnuStyle, PSec, "Names",
+ &DwarfCompileUnit::getGlobalNames);
+}
+
+void DwarfDebug::emitDebugPubSection(
+ bool GnuStyle, MCSection *PSec, StringRef Name,
+ const StringMap<const DIE *> &(DwarfCompileUnit::*Accessor)() const) {
+ for (const auto &NU : CUMap) {
+ DwarfCompileUnit *TheU = NU.second;
+
+ const auto &Globals = (TheU->*Accessor)();
+
+ if (Globals.empty())
+ continue;
+
+ if (auto *Skeleton = TheU->getSkeleton())
+ TheU = Skeleton;
+
+ // Start the dwarf pubnames section.
+ Asm->OutStreamer->SwitchSection(PSec);
+
+ // Emit the header.
+ Asm->OutStreamer->AddComment("Length of Public " + Name + " Info");
+ MCSymbol *BeginLabel = Asm->createTempSymbol("pub" + Name + "_begin");
+ MCSymbol *EndLabel = Asm->createTempSymbol("pub" + Name + "_end");
+ Asm->EmitLabelDifference(EndLabel, BeginLabel, 4);
+
+ Asm->OutStreamer->EmitLabel(BeginLabel);
+
+ Asm->OutStreamer->AddComment("DWARF Version");
+ Asm->EmitInt16(dwarf::DW_PUBNAMES_VERSION);
+
+ Asm->OutStreamer->AddComment("Offset of Compilation Unit Info");
+ Asm->emitDwarfSymbolReference(TheU->getLabelBegin());
+
+ Asm->OutStreamer->AddComment("Compilation Unit Length");
+ Asm->EmitInt32(TheU->getLength());
+
+ // Emit the pubnames for this compilation unit.
+ for (const auto &GI : Globals) {
+ const char *Name = GI.getKeyData();
+ const DIE *Entity = GI.second;
+
+ Asm->OutStreamer->AddComment("DIE offset");
+ Asm->EmitInt32(Entity->getOffset());
+
+ if (GnuStyle) {
+ dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheU, Entity);
+ Asm->OutStreamer->AddComment(
+ Twine("Kind: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + ", " +
+ dwarf::GDBIndexEntryLinkageString(Desc.Linkage));
+ Asm->EmitInt8(Desc.toBits());
+ }
+
+ Asm->OutStreamer->AddComment("External Name");
+ Asm->OutStreamer->EmitBytes(StringRef(Name, GI.getKeyLength() + 1));
+ }
+
+ Asm->OutStreamer->AddComment("End Mark");
+ Asm->EmitInt32(0);
+ Asm->OutStreamer->EmitLabel(EndLabel);
+ }
+}
+
+void DwarfDebug::emitDebugPubTypes(bool GnuStyle) {
+ MCSection *PSec = GnuStyle
+ ? Asm->getObjFileLowering().getDwarfGnuPubTypesSection()
+ : Asm->getObjFileLowering().getDwarfPubTypesSection();
+
+ emitDebugPubSection(GnuStyle, PSec, "Types",
+ &DwarfCompileUnit::getGlobalTypes);
+}
+
+// Emit visible names into a debug str section.
+void DwarfDebug::emitDebugStr() {
+ DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
+ Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection());
+}
+
+void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
+ const DebugLocStream::Entry &Entry) {
+ auto &&Comments = DebugLocs.getComments(Entry);
+ auto Comment = Comments.begin();
+ auto End = Comments.end();
+ for (uint8_t Byte : DebugLocs.getBytes(Entry))
+ Streamer.EmitInt8(Byte, Comment != End ? *(Comment++) : "");
+}
+
+static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
+ ByteStreamer &Streamer,
+ const DebugLocEntry::Value &Value,
+ unsigned PieceOffsetInBits) {
+ DebugLocDwarfExpression DwarfExpr(*AP.MF->getSubtarget().getRegisterInfo(),
+ AP.getDwarfDebug()->getDwarfVersion(),
+ Streamer);
+ // Regular entry.
+ if (Value.isInt()) {
+ if (BT && (BT->getEncoding() == dwarf::DW_ATE_signed ||
+ BT->getEncoding() == dwarf::DW_ATE_signed_char))
+ DwarfExpr.AddSignedConstant(Value.getInt());
+ else
+ DwarfExpr.AddUnsignedConstant(Value.getInt());
+ } else if (Value.isLocation()) {
+ MachineLocation Loc = Value.getLoc();
+ const DIExpression *Expr = Value.getExpression();
+ if (!Expr || !Expr->getNumElements())
+ // Regular entry.
+ AP.EmitDwarfRegOp(Streamer, Loc);
+ else {
+ // Complex address entry.
+ if (Loc.getOffset()) {
+ DwarfExpr.AddMachineRegIndirect(Loc.getReg(), Loc.getOffset());
+ DwarfExpr.AddExpression(Expr->expr_op_begin(), Expr->expr_op_end(),
+ PieceOffsetInBits);
+ } else
+ DwarfExpr.AddMachineRegExpression(Expr, Loc.getReg(),
+ PieceOffsetInBits);
+ }
+ }
+ // else ... ignore constant fp. There is not any good way to
+ // to represent them here in dwarf.
+ // FIXME: ^
+}
+
+void DebugLocEntry::finalize(const AsmPrinter &AP,
+ DebugLocStream::ListBuilder &List,
+ const DIBasicType *BT) {
+ DebugLocStream::EntryBuilder Entry(List, Begin, End);
+ BufferByteStreamer Streamer = Entry.getStreamer();
+ const DebugLocEntry::Value &Value = Values[0];
+ if (Value.isBitPiece()) {
+ // Emit all pieces that belong to the same variable and range.
+ assert(std::all_of(Values.begin(), Values.end(), [](DebugLocEntry::Value P) {
+ return P.isBitPiece();
+ }) && "all values are expected to be pieces");
+ assert(std::is_sorted(Values.begin(), Values.end()) &&
+ "pieces are expected to be sorted");
+
+ unsigned Offset = 0;
+ for (auto Piece : Values) {
+ const DIExpression *Expr = Piece.getExpression();
+ unsigned PieceOffset = Expr->getBitPieceOffset();
+ unsigned PieceSize = Expr->getBitPieceSize();
+ assert(Offset <= PieceOffset && "overlapping or duplicate pieces");
+ if (Offset < PieceOffset) {
+ // The DWARF spec seriously mandates pieces with no locations for gaps.
+ DebugLocDwarfExpression Expr(*AP.MF->getSubtarget().getRegisterInfo(),
+ AP.getDwarfDebug()->getDwarfVersion(),
+ Streamer);
+ Expr.AddOpPiece(PieceOffset-Offset, 0);
+ Offset += PieceOffset-Offset;
+ }
+ Offset += PieceSize;
+
+ emitDebugLocValue(AP, BT, Streamer, Piece, PieceOffset);
+ }
+ } else {
+ assert(Values.size() == 1 && "only pieces may have >1 value");
+ emitDebugLocValue(AP, BT, Streamer, Value, 0);
+ }
+}
+
+void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry) {
+ // Emit the size.
+ Asm->OutStreamer->AddComment("Loc expr size");
+ Asm->EmitInt16(DebugLocs.getBytes(Entry).size());
+
+ // Emit the entry.
+ APByteStreamer Streamer(*Asm);
+ emitDebugLocEntry(Streamer, Entry);
+}
+
+// Emit locations into the debug loc section.
+void DwarfDebug::emitDebugLoc() {
+ // Start the dwarf loc section.
+ Asm->OutStreamer->SwitchSection(
+ Asm->getObjFileLowering().getDwarfLocSection());
+ unsigned char Size = Asm->getDataLayout().getPointerSize();
+ for (const auto &List : DebugLocs.getLists()) {
+ Asm->OutStreamer->EmitLabel(List.Label);
+ const DwarfCompileUnit *CU = List.CU;
+ 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);
+ } else {
+ Asm->OutStreamer->EmitSymbolValue(Entry.BeginSym, Size);
+ Asm->OutStreamer->EmitSymbolValue(Entry.EndSym, Size);
+ }
+
+ emitDebugLocEntryLocation(Entry);
+ }
+ Asm->OutStreamer->EmitIntValue(0, Size);
+ Asm->OutStreamer->EmitIntValue(0, Size);
+ }
+}
+
+void DwarfDebug::emitDebugLocDWO() {
+ Asm->OutStreamer->SwitchSection(
+ Asm->getObjFileLowering().getDwarfLocDWOSection());
+ 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?)
+ Asm->EmitInt8(dwarf::DW_LLE_start_length_entry);
+ unsigned idx = AddrPool.getIndex(Entry.BeginSym);
+ Asm->EmitULEB128(idx);
+ Asm->EmitLabelDifference(Entry.EndSym, Entry.BeginSym, 4);
+
+ emitDebugLocEntryLocation(Entry);
+ }
+ Asm->EmitInt8(dwarf::DW_LLE_end_of_list_entry);
+ }
+}
+
+struct ArangeSpan {
+ const MCSymbol *Start, *End;
+};
+
+// Emit a debug aranges section, containing a CU lookup for any
+// address we can tie back to a CU.
+void DwarfDebug::emitDebugARanges() {
+ // Provides a unique id per text section.
+ MapVector<MCSection *, SmallVector<SymbolCU, 8>> SectionMap;
+
+ // Filter labels by section.
+ for (const SymbolCU &SCU : ArangeLabels) {
+ if (SCU.Sym->isInSection()) {
+ // Make a note of this symbol and it's section.
+ MCSection *Section = &SCU.Sym->getSection();
+ if (!Section->getKind().isMetadata())
+ SectionMap[Section].push_back(SCU);
+ } else {
+ // Some symbols (e.g. common/bss on mach-o) can have no section but still
+ // appear in the output. This sucks as we rely on sections to build
+ // arange spans. We can do it without, but it's icky.
+ SectionMap[nullptr].push_back(SCU);
+ }
+ }
+
+ // Add terminating symbols for each section.
+ for (const auto &I : SectionMap) {
+ MCSection *Section = I.first;
+ MCSymbol *Sym = nullptr;
+
+ if (Section)
+ Sym = Asm->OutStreamer->endSection(Section);
+
+ // Insert a final terminator.
+ SectionMap[Section].push_back(SymbolCU(nullptr, Sym));
+ }
+
+ DenseMap<DwarfCompileUnit *, std::vector<ArangeSpan>> Spans;
+
+ for (auto &I : SectionMap) {
+ const MCSection *Section = I.first;
+ SmallVector<SymbolCU, 8> &List = I.second;
+ if (List.size() < 2)
+ continue;
+
+ // If we have no section (e.g. common), just write out
+ // individual spans for each symbol.
+ if (!Section) {
+ for (const SymbolCU &Cur : List) {
+ ArangeSpan Span;
+ Span.Start = Cur.Sym;
+ Span.End = nullptr;
+ if (Cur.CU)
+ Spans[Cur.CU].push_back(Span);
+ }
+ continue;
+ }
+
+ // Sort the symbols by offset within the section.
+ std::sort(List.begin(), List.end(),
+ [&](const SymbolCU &A, const SymbolCU &B) {
+ unsigned IA = A.Sym ? Asm->OutStreamer->GetSymbolOrder(A.Sym) : 0;
+ unsigned IB = B.Sym ? Asm->OutStreamer->GetSymbolOrder(B.Sym) : 0;
+
+ // Symbols with no order assigned should be placed at the end.
+ // (e.g. section end labels)
+ if (IA == 0)
+ return false;
+ if (IB == 0)
+ return true;
+ return IA < IB;
+ });
+
+ // Build spans between each label.
+ const MCSymbol *StartSym = List[0].Sym;
+ for (size_t n = 1, e = List.size(); n < e; n++) {
+ const SymbolCU &Prev = List[n - 1];
+ const SymbolCU &Cur = List[n];
+
+ // Try and build the longest span we can within the same CU.
+ if (Cur.CU != Prev.CU) {
+ ArangeSpan Span;
+ Span.Start = StartSym;
+ Span.End = Cur.Sym;
+ Spans[Prev.CU].push_back(Span);
+ StartSym = Cur.Sym;
+ }
+ }
+ }
+
+ // Start the dwarf aranges section.
+ Asm->OutStreamer->SwitchSection(
+ Asm->getObjFileLowering().getDwarfARangesSection());
+
+ unsigned PtrSize = Asm->getDataLayout().getPointerSize();
+
+ // Build a list of CUs used.
+ std::vector<DwarfCompileUnit *> CUs;
+ for (const auto &it : Spans) {
+ DwarfCompileUnit *CU = it.first;
+ CUs.push_back(CU);
+ }
+
+ // Sort the CU list (again, to ensure consistent output order).
+ std::sort(CUs.begin(), CUs.end(), [](const DwarfUnit *A, const DwarfUnit *B) {
+ return A->getUniqueID() < B->getUniqueID();
+ });
+
+ // Emit an arange table for each CU we used.
+ for (DwarfCompileUnit *CU : CUs) {
+ std::vector<ArangeSpan> &List = Spans[CU];
+
+ // Describe the skeleton CU's offset and length, not the dwo file's.
+ if (auto *Skel = CU->getSkeleton())
+ CU = Skel;
+
+ // Emit size of content not including length itself.
+ unsigned ContentSize =
+ sizeof(int16_t) + // DWARF ARange version number
+ sizeof(int32_t) + // Offset of CU in the .debug_info section
+ sizeof(int8_t) + // Pointer Size (in bytes)
+ sizeof(int8_t); // Segment Size (in bytes)
+
+ unsigned TupleSize = PtrSize * 2;
+
+ // 7.20 in the Dwarf specs requires the table to be aligned to a tuple.
+ unsigned Padding =
+ OffsetToAlignment(sizeof(int32_t) + ContentSize, TupleSize);
+
+ ContentSize += Padding;
+ ContentSize += (List.size() + 1) * TupleSize;
+
+ // For each compile unit, write the list of spans it covers.
+ Asm->OutStreamer->AddComment("Length of ARange Set");
+ Asm->EmitInt32(ContentSize);
+ Asm->OutStreamer->AddComment("DWARF Arange version number");
+ Asm->EmitInt16(dwarf::DW_ARANGES_VERSION);
+ Asm->OutStreamer->AddComment("Offset Into Debug Info Section");
+ Asm->emitDwarfSymbolReference(CU->getLabelBegin());
+ Asm->OutStreamer->AddComment("Address Size (in bytes)");
+ Asm->EmitInt8(PtrSize);
+ Asm->OutStreamer->AddComment("Segment Size (in bytes)");
+ Asm->EmitInt8(0);
+
+ Asm->OutStreamer->EmitFill(Padding, 0xff);
+
+ for (const ArangeSpan &Span : List) {
+ Asm->EmitLabelReference(Span.Start, PtrSize);
+
+ // Calculate the size as being from the span start to it's end.
+ if (Span.End) {
+ Asm->EmitLabelDifference(Span.End, Span.Start, PtrSize);
+ } else {
+ // For symbols without an end marker (e.g. common), we
+ // write a single arange entry containing just that one symbol.
+ uint64_t Size = SymSize[Span.Start];
+ if (Size == 0)
+ Size = 1;
+
+ Asm->OutStreamer->EmitIntValue(Size, PtrSize);
+ }
+ }
+
+ Asm->OutStreamer->AddComment("ARange terminator");
+ Asm->OutStreamer->EmitIntValue(0, PtrSize);
+ Asm->OutStreamer->EmitIntValue(0, PtrSize);
+ }
+}
+
+// Emit visible names into a debug ranges section.
+void DwarfDebug::emitDebugRanges() {
+ // Start the dwarf ranges section.
+ Asm->OutStreamer->SwitchSection(
+ Asm->getObjFileLowering().getDwarfRangesSection());
+
+ // Size for our labels.
+ unsigned char Size = Asm->getDataLayout().getPointerSize();
+
+ // Grab the specific ranges for the compile units in the module.
+ for (const auto &I : CUMap) {
+ DwarfCompileUnit *TheCU = I.second;
+
+ if (auto *Skel = TheCU->getSkeleton())
+ TheCU = Skel;
+
+ // Iterate over the misc ranges for the compile units in the module.
+ for (const RangeSpanList &List : TheCU->getRangeLists()) {
+ // Emit our symbol so we can find the beginning of the range.
+ Asm->OutStreamer->EmitLabel(List.getSym());
+
+ for (const RangeSpan &Range : List.getRanges()) {
+ const MCSymbol *Begin = Range.getStart();
+ const MCSymbol *End = Range.getEnd();
+ assert(Begin && "Range without a begin symbol?");
+ assert(End && "Range without an end symbol?");
+ if (auto *Base = TheCU->getBaseAddress()) {
+ Asm->EmitLabelDifference(Begin, Base, Size);
+ Asm->EmitLabelDifference(End, Base, Size);
+ } else {
+ Asm->OutStreamer->EmitSymbolValue(Begin, Size);
+ Asm->OutStreamer->EmitSymbolValue(End, Size);
+ }
+ }
+
+ // And terminate the list with two 0 values.
+ Asm->OutStreamer->EmitIntValue(0, Size);
+ Asm->OutStreamer->EmitIntValue(0, Size);
+ }
+ }
+}
+
+// DWARF5 Experimental Separate Dwarf emitters.
+
+void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die,
+ std::unique_ptr<DwarfUnit> NewU) {
+ NewU->addString(Die, dwarf::DW_AT_GNU_dwo_name,
+ U.getCUNode()->getSplitDebugFilename());
+
+ if (!CompilationDir.empty())
+ NewU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
+
+ addGnuPubAttributes(*NewU, Die);
+
+ SkeletonHolder.addUnit(std::move(NewU));
+}
+
+// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list,
+// DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id,
+// DW_AT_addr_base, DW_AT_ranges_base.
+DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) {
+
+ auto OwnedUnit = make_unique<DwarfCompileUnit>(
+ CU.getUniqueID(), CU.getCUNode(), Asm, this, &SkeletonHolder);
+ DwarfCompileUnit &NewCU = *OwnedUnit;
+ NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoSection());
+
+ NewCU.initStmtList();
+
+ initSkeletonUnit(CU, NewCU.getUnitDie(), std::move(OwnedUnit));
+
+ return NewCU;
+}
+
+// Emit the .debug_info.dwo section for separated dwarf. This contains the
+// compile units that would normally be in debug_info.
+void DwarfDebug::emitDebugInfoDWO() {
+ assert(useSplitDwarf() && "No split dwarf debug info?");
+ // Don't emit relocations into the dwo file.
+ InfoHolder.emitUnits(/* UseOffsets */ true);
+}
+
+// Emit the .debug_abbrev.dwo section for separated dwarf. This contains the
+// abbreviations for the .debug_info.dwo section.
+void DwarfDebug::emitDebugAbbrevDWO() {
+ assert(useSplitDwarf() && "No split dwarf?");
+ InfoHolder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevDWOSection());
+}
+
+void DwarfDebug::emitDebugLineDWO() {
+ assert(useSplitDwarf() && "No split dwarf?");
+ Asm->OutStreamer->SwitchSection(
+ Asm->getObjFileLowering().getDwarfLineDWOSection());
+ SplitTypeUnitFileTable.Emit(*Asm->OutStreamer, MCDwarfLineTableParams());
+}
+
+// Emit the .debug_str.dwo section for separated dwarf. This contains the
+// string section and is identical in format to traditional .debug_str
+// sections.
+void DwarfDebug::emitDebugStrDWO() {
+ assert(useSplitDwarf() && "No split dwarf?");
+ MCSection *OffSec = Asm->getObjFileLowering().getDwarfStrOffDWOSection();
+ InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(),
+ OffSec);
+}
+
+MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) {
+ if (!useSplitDwarf())
+ return nullptr;
+ if (SingleCU)
+ SplitTypeUnitFileTable.setCompilationDir(CU.getCUNode()->getDirectory());
+ return &SplitTypeUnitFileTable;
+}
+
+uint64_t DwarfDebug::makeTypeSignature(StringRef Identifier) {
+ MD5 Hash;
+ Hash.update(Identifier);
+ // ... take the least significant 8 bytes and return those. Our MD5
+ // implementation always returns its results in little endian, swap bytes
+ // appropriately.
+ MD5::MD5Result Result;
+ Hash.final(Result);
+ return support::endian::read64le(Result + 8);
+}
+
+void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
+ StringRef Identifier, DIE &RefDie,
+ const DICompositeType *CTy) {
+ // Fast path if we're building some type units and one has already used the
+ // address pool we know we're going to throw away all this work anyway, so
+ // don't bother building dependent types.
+ if (!TypeUnitsUnderConstruction.empty() && AddrPool.hasBeenUsed())
+ return;
+
+ const DwarfTypeUnit *&TU = DwarfTypeUnits[CTy];
+ if (TU) {
+ CU.addDIETypeSignature(RefDie, *TU);
+ return;
+ }
+
+ bool TopLevelType = TypeUnitsUnderConstruction.empty();
+ AddrPool.resetUsedFlag();
+
+ auto OwnedUnit = make_unique<DwarfTypeUnit>(
+ InfoHolder.getUnits().size() + TypeUnitsUnderConstruction.size(), CU, Asm,
+ this, &InfoHolder, getDwoLineTable(CU));
+ DwarfTypeUnit &NewTU = *OwnedUnit;
+ DIE &UnitDie = NewTU.getUnitDie();
+ TU = &NewTU;
+ TypeUnitsUnderConstruction.push_back(
+ std::make_pair(std::move(OwnedUnit), CTy));
+
+ NewTU.addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
+ CU.getLanguage());
+
+ uint64_t Signature = makeTypeSignature(Identifier);
+ NewTU.setTypeSignature(Signature);
+
+ if (useSplitDwarf())
+ NewTU.initSection(Asm->getObjFileLowering().getDwarfTypesDWOSection());
+ else {
+ CU.applyStmtList(UnitDie);
+ NewTU.initSection(
+ Asm->getObjFileLowering().getDwarfTypesSection(Signature));
+ }
+
+ NewTU.setType(NewTU.createTypeDIE(CTy));
+
+ if (TopLevelType) {
+ auto TypeUnitsToAdd = std::move(TypeUnitsUnderConstruction);
+ TypeUnitsUnderConstruction.clear();
+
+ // Types referencing entries in the address table cannot be placed in type
+ // units.
+ if (AddrPool.hasBeenUsed()) {
+
+ // Remove all the types built while building this type.
+ // This is pessimistic as some of these types might not be dependent on
+ // the type that used an address.
+ for (const auto &TU : TypeUnitsToAdd)
+ DwarfTypeUnits.erase(TU.second);
+
+ // Construct this type in the CU directly.
+ // This is inefficient because all the dependent types will be rebuilt
+ // from scratch, including building them in type units, discovering that
+ // they depend on addresses, throwing them out and rebuilding them.
+ CU.constructTypeDIE(RefDie, cast<DICompositeType>(CTy));
+ return;
+ }
+
+ // If the type wasn't dependent on fission addresses, finish adding the type
+ // and all its dependent types.
+ for (auto &TU : TypeUnitsToAdd)
+ InfoHolder.addUnit(std::move(TU.first));
+ }
+ CU.addDIETypeSignature(RefDie, NewTU);
+}
+
+// Accelerator table mutators - add each name along with its companion
+// DIE to the proper table while ensuring that the name that we're going
+// to reference is in the string table. We do this since the names we
+// add may not only be identical to the names in the DIE.
+void DwarfDebug::addAccelName(StringRef Name, const DIE &Die) {
+ if (!useDwarfAccelTables())
+ return;
+ AccelNames.AddName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die);
+}
+
+void DwarfDebug::addAccelObjC(StringRef Name, const DIE &Die) {
+ if (!useDwarfAccelTables())
+ return;
+ AccelObjC.AddName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die);
+}
+
+void DwarfDebug::addAccelNamespace(StringRef Name, const DIE &Die) {
+ if (!useDwarfAccelTables())
+ return;
+ AccelNamespace.AddName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die);
+}
+
+void DwarfDebug::addAccelType(StringRef Name, const DIE &Die, char Flags) {
+ if (!useDwarfAccelTables())
+ return;
+ AccelTypes.AddName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die);
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
new file mode 100644
index 0000000..4c613a9
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -0,0 +1,617 @@
+//===-- llvm/CodeGen/DwarfDebug.h - Dwarf Debug 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 dwarf debug info into asm files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFDEBUG_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFDEBUG_H
+
+#include "AsmPrinterHandler.h"
+#include "DbgValueHistoryCalculator.h"
+#include "DebugLocStream.h"
+#include "DwarfAccelTable.h"
+#include "DwarfFile.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/CodeGen/DIE.h"
+#include "llvm/CodeGen/LexicalScopes.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/MC/MCDwarf.h"
+#include "llvm/MC/MachineLocation.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Target/TargetOptions.h"
+#include <memory>
+
+namespace llvm {
+
+class AsmPrinter;
+class ByteStreamer;
+class ConstantInt;
+class ConstantFP;
+class DebugLocEntry;
+class DwarfCompileUnit;
+class DwarfDebug;
+class DwarfTypeUnit;
+class DwarfUnit;
+class MachineModuleInfo;
+
+//===----------------------------------------------------------------------===//
+/// This class is used to track local variable information.
+///
+/// Variables can be created from allocas, in which case they're generated from
+/// the MMI table. Such variables can have multiple expressions and frame
+/// indices. The \a Expr and \a FrameIndices array must match.
+///
+/// Variables can be created from \c DBG_VALUE instructions. Those whose
+/// location changes over time use \a DebugLocListIndex, while those with a
+/// 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.
+ SmallVector<const DIExpression *, 1> Expr; /// Complex address.
+ DIE *TheDIE = nullptr; /// Variable DIE.
+ unsigned DebugLocListIndex = ~0u; /// Offset in DebugLocs.
+ const MachineInstr *MInsn = nullptr; /// DBG_VALUE instruction.
+ SmallVector<int, 1> FrameIndex; /// Frame index.
+ DwarfDebug *DD;
+
+public:
+ /// Construct a DbgVariable.
+ ///
+ /// 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, DwarfDebug *DD)
+ : Var(V), IA(IA), DD(DD) {}
+
+ /// Initialize from the MMI table.
+ void initializeMMI(const DIExpression *E, int FI) {
+ assert(Expr.empty() && "Already initialized?");
+ assert(FrameIndex.empty() && "Already initialized?");
+ assert(!MInsn && "Already initialized?");
+
+ assert((!E || E->isValid()) && "Expected valid expression");
+ assert(~FI && "Expected valid index");
+
+ Expr.push_back(E);
+ FrameIndex.push_back(FI);
+ }
+
+ /// Initialize from a DBG_VALUE instruction.
+ void initializeDbgValue(const MachineInstr *DbgValue) {
+ assert(Expr.empty() && "Already initialized?");
+ assert(FrameIndex.empty() && "Already initialized?");
+ assert(!MInsn && "Already initialized?");
+
+ assert(Var == DbgValue->getDebugVariable() && "Wrong variable");
+ assert(IA == DbgValue->getDebugLoc()->getInlinedAt() && "Wrong inlined-at");
+
+ MInsn = DbgValue;
+ if (auto *E = DbgValue->getDebugExpression())
+ if (E->getNumElements())
+ Expr.push_back(E);
+ }
+
+ // Accessors.
+ const DILocalVariable *getVariable() const { return Var; }
+ const DILocation *getInlinedAt() const { return IA; }
+ ArrayRef<const DIExpression *> getExpression() const { return Expr; }
+ 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(); }
+ const MachineInstr *getMInsn() const { return MInsn; }
+ ArrayRef<int> getFrameIndex() const { return FrameIndex; }
+
+ void 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(!FrameIndex.empty() && "Expected an MMI entry");
+ assert(!V.FrameIndex.empty() && "Expected an MMI entry");
+ assert(Expr.size() == FrameIndex.size() && "Mismatched expressions");
+ assert(V.Expr.size() == V.FrameIndex.size() && "Mismatched expressions");
+
+ Expr.append(V.Expr.begin(), V.Expr.end());
+ FrameIndex.append(V.FrameIndex.begin(), V.FrameIndex.end());
+ assert(std::all_of(Expr.begin(), Expr.end(), [](const DIExpression *E) {
+ return E && E->isBitPiece();
+ }) && "conflicting locations for variable");
+ }
+
+ // 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())
+ return dwarf::DW_TAG_formal_parameter;
+
+ return dwarf::DW_TAG_variable;
+ }
+ /// Return true if DbgVariable is artificial.
+ bool isArtificial() const {
+ if (Var->isArtificial())
+ return true;
+ if (getType()->isArtificial())
+ return true;
+ return false;
+ }
+
+ bool isObjectPointer() const {
+ if (Var->isObjectPointer())
+ return true;
+ if (getType()->isObjectPointer())
+ return true;
+ return false;
+ }
+
+ bool hasComplexAddress() const {
+ assert(MInsn && "Expected DBG_VALUE, not MMI variable");
+ assert(FrameIndex.empty() && "Expected DBG_VALUE, not MMI variable");
+ assert(
+ (Expr.empty() || (Expr.size() == 1 && Expr.back()->getNumElements())) &&
+ "Invalid Expr for DBG_VALUE");
+ return !Expr.empty();
+ }
+ bool isBlockByrefVariable() const;
+ const DIType *getType() const;
+
+private:
+ /// Look in the DwarfDebug map for the MDNode that
+ /// corresponds to the reference.
+ template <typename T> T *resolve(TypedDINodeRef<T> Ref) const;
+};
+
+
+/// Helper used to pair up a symbol and its DWARF compile unit.
+struct SymbolCU {
+ SymbolCU(DwarfCompileUnit *CU, const MCSymbol *Sym) : Sym(Sym), CU(CU) {}
+ const MCSymbol *Sym;
+ DwarfCompileUnit *CU;
+};
+
+/// Collects and handles dwarf debug information.
+class DwarfDebug : public AsmPrinterHandler {
+ /// Target of Dwarf emission.
+ AsmPrinter *Asm;
+
+ /// Collected machine module information.
+ MachineModuleInfo *MMI;
+
+ /// All DIEValues are allocated through this allocator.
+ BumpPtrAllocator DIEValueAllocator;
+
+ /// Maps MDNode with its corresponding DwarfCompileUnit.
+ MapVector<const MDNode *, DwarfCompileUnit *> CUMap;
+
+ /// Maps subprogram MDNode with its corresponding DwarfCompileUnit.
+ MapVector<const MDNode *, DwarfCompileUnit *> SPMap;
+
+ /// Maps a CU DIE with its corresponding DwarfCompileUnit.
+ DenseMap<const DIE *, DwarfCompileUnit *> CUDieMap;
+
+ /// List of all labels used in aranges generation.
+ std::vector<SymbolCU> ArangeLabels;
+
+ /// Size of each symbol emitted (for those symbols that have a specific size).
+ DenseMap<const MCSymbol *, uint64_t> SymSize;
+
+ LexicalScopes LScopes;
+
+ /// Collection of abstract variables.
+ DenseMap<const MDNode *, std::unique_ptr<DbgVariable>> AbstractVariables;
+ SmallVector<std::unique_ptr<DbgVariable>, 64> ConcreteVariables;
+
+ /// Collection of DebugLocEntry. Stored in a linked list so that DIELocLists
+ /// can refer to them in spite of insertions into this list.
+ DebugLocStream DebugLocs;
+
+ /// This is a collection of subprogram MDNodes that are processed to
+ /// create DIEs.
+ SmallPtrSet<const MDNode *, 16> ProcessedSPNodes;
+
+ /// Maps instruction with label emitted before instruction.
+ DenseMap<const MachineInstr *, MCSymbol *> LabelsBeforeInsn;
+
+ /// Maps instruction with label emitted after instruction.
+ DenseMap<const MachineInstr *, MCSymbol *> LabelsAfterInsn;
+
+ /// History of DBG_VALUE and clobber instructions for each user
+ /// variable. Variables are listed in order of appearance.
+ DbgValueHistoryMap DbgValues;
+
+ /// Previous instruction's location information. This is used to
+ /// determine label location to indicate scope boundries in dwarf
+ /// debug info.
+ DebugLoc PrevInstLoc;
+ MCSymbol *PrevLabel;
+
+ /// This location indicates end of function prologue and beginning of
+ /// function body.
+ DebugLoc PrologEndLoc;
+
+ /// If nonnull, stores the current machine function we're processing.
+ const MachineFunction *CurFn;
+
+ /// If nonnull, stores the current machine instruction we're processing.
+ const MachineInstr *CurMI;
+
+ /// If nonnull, stores the CU in which the previous subprogram was contained.
+ const DwarfCompileUnit *PrevCU;
+
+ /// As an optimization, there is no need to emit an entry in the directory
+ /// table for the same directory as DW_AT_comp_dir.
+ StringRef CompilationDir;
+
+ /// Holder for the file specific debug information.
+ DwarfFile InfoHolder;
+
+ /// Holders for the various debug information flags that we might need to
+ /// have exposed. See accessor functions below for description.
+
+ /// Map from MDNodes for user-defined types to the type units that
+ /// describe them.
+ DenseMap<const MDNode *, const DwarfTypeUnit *> DwarfTypeUnits;
+
+ SmallVector<
+ std::pair<std::unique_ptr<DwarfTypeUnit>, const DICompositeType *>, 1>
+ TypeUnitsUnderConstruction;
+
+ /// Whether to emit the pubnames/pubtypes sections.
+ bool HasDwarfPubSections;
+
+ /// Whether to use the GNU TLS opcode (instead of the standard opcode).
+ bool UseGNUTLSOpcode;
+
+ /// Whether to emit DW_AT_[MIPS_]linkage_name.
+ bool UseLinkageNames;
+
+ /// Version of dwarf we're emitting.
+ unsigned DwarfVersion;
+
+ /// Maps from a type identifier to the actual MDNode.
+ DITypeIdentifierMap TypeIdentifierMap;
+
+ /// DWARF5 Experimental Options
+ /// @{
+ bool HasDwarfAccelTables;
+ bool HasSplitDwarf;
+
+ /// Separated Dwarf Variables
+ /// In general these will all be for bits that are left in the
+ /// original object file, rather than things that are meant
+ /// to be in the .dwo sections.
+
+ /// Holder for the skeleton information.
+ DwarfFile SkeletonHolder;
+
+ /// Store file names for type units under fission in a line table
+ /// header that will be emitted into debug_line.dwo.
+ // FIXME: replace this with a map from comp_dir to table so that we
+ // can emit multiple tables during LTO each of which uses directory
+ // 0, referencing the comp_dir of all the type units that use it.
+ MCDwarfDwoLineTable SplitTypeUnitFileTable;
+ /// @}
+
+ /// True iff there are multiple CUs in this module.
+ bool SingleCU;
+ bool IsDarwin;
+
+ AddressPool AddrPool;
+
+ DwarfAccelTable AccelNames;
+ DwarfAccelTable AccelObjC;
+ DwarfAccelTable AccelNamespace;
+ DwarfAccelTable AccelTypes;
+
+ // Identify a debugger for "tuning" the debug info.
+ DebuggerKind DebuggerTuning;
+
+ MCDwarfDwoLineTable *getDwoLineTable(const DwarfCompileUnit &);
+
+ const SmallVectorImpl<std::unique_ptr<DwarfUnit>> &getUnits() {
+ return InfoHolder.getUnits();
+ }
+
+ typedef DbgValueHistoryMap::InlinedVariable InlinedVariable;
+
+ /// Find abstract variable associated with Var.
+ DbgVariable *getExistingAbstractVariable(InlinedVariable IV,
+ const DILocalVariable *&Cleansed);
+ DbgVariable *getExistingAbstractVariable(InlinedVariable IV);
+ void createAbstractVariable(const DILocalVariable *DV, LexicalScope *Scope);
+ void ensureAbstractVariableIsCreated(InlinedVariable Var,
+ const MDNode *Scope);
+ void ensureAbstractVariableIsCreatedIfScoped(InlinedVariable Var,
+ const MDNode *Scope);
+
+ DbgVariable *createConcreteVariable(LexicalScope &Scope, InlinedVariable IV);
+
+ /// Construct a DIE for this abstract scope.
+ void constructAbstractSubprogramScopeDIE(LexicalScope *Scope);
+
+ /// Collect info for variables that were optimized out.
+ void collectDeadVariables();
+
+ void finishVariableDefinitions();
+
+ void finishSubprogramDefinitions();
+
+ /// Finish off debug information after all functions have been
+ /// processed.
+ void finalizeModuleInfo();
+
+ /// Emit the debug info section.
+ void emitDebugInfo();
+
+ /// Emit the abbreviation section.
+ void emitAbbreviations();
+
+ /// Emit a specified accelerator table.
+ void emitAccel(DwarfAccelTable &Accel, MCSection *Section,
+ StringRef TableName);
+
+ /// Emit visible names into a hashed accelerator table section.
+ void emitAccelNames();
+
+ /// Emit objective C classes and categories into a hashed
+ /// accelerator table section.
+ void emitAccelObjC();
+
+ /// Emit namespace dies into a hashed accelerator table.
+ void emitAccelNamespaces();
+
+ /// Emit type dies into a hashed accelerator table.
+ void emitAccelTypes();
+
+ /// Emit visible names into a debug pubnames section.
+ /// \param GnuStyle determines whether or not we want to emit
+ /// additional information into the table ala newer gcc for gdb
+ /// index.
+ void emitDebugPubNames(bool GnuStyle = false);
+
+ /// Emit visible types into a debug pubtypes section.
+ /// \param GnuStyle determines whether or not we want to emit
+ /// additional information into the table ala newer gcc for gdb
+ /// index.
+ void emitDebugPubTypes(bool GnuStyle = false);
+
+ void emitDebugPubSection(
+ bool GnuStyle, MCSection *PSec, StringRef Name,
+ const StringMap<const DIE *> &(DwarfCompileUnit::*Accessor)() const);
+
+ /// Emit visible names into a debug str section.
+ void emitDebugStr();
+
+ /// Emit visible names into a debug loc section.
+ void emitDebugLoc();
+
+ /// Emit visible names into a debug loc dwo section.
+ void emitDebugLocDWO();
+
+ /// Emit visible names into a debug aranges section.
+ void emitDebugARanges();
+
+ /// Emit visible names into a debug ranges section.
+ void emitDebugRanges();
+
+ /// DWARF 5 Experimental Split Dwarf Emitters
+
+ /// Initialize common features of skeleton units.
+ void initSkeletonUnit(const DwarfUnit &U, DIE &Die,
+ std::unique_ptr<DwarfUnit> NewU);
+
+ /// Construct the split debug info compile unit for the debug info
+ /// section.
+ DwarfCompileUnit &constructSkeletonCU(const DwarfCompileUnit &CU);
+
+ /// Emit the debug info dwo section.
+ void emitDebugInfoDWO();
+
+ /// Emit the debug abbrev dwo section.
+ void emitDebugAbbrevDWO();
+
+ /// Emit the debug line dwo section.
+ void emitDebugLineDWO();
+
+ /// Emit the debug str dwo section.
+ void emitDebugStrDWO();
+
+ /// Flags to let the linker know we have emitted new style pubnames. Only
+ /// emit it here if we don't have a skeleton CU for split dwarf.
+ void addGnuPubAttributes(DwarfUnit &U, DIE &D) const;
+
+ /// Create new DwarfCompileUnit for the given metadata node with tag
+ /// DW_TAG_compile_unit.
+ DwarfCompileUnit &constructDwarfCompileUnit(const DICompileUnit *DIUnit);
+
+ /// Construct imported_module or imported_declaration DIE.
+ void constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU,
+ const DIImportedEntity *N);
+
+ /// Register a source line with debug info. Returns the unique
+ /// label that was emitted and which provides correspondence to the
+ /// source line list.
+ void recordSourceLine(unsigned Line, unsigned Col, const MDNode *Scope,
+ unsigned Flags);
+
+ /// Indentify instructions that are marking the beginning of or
+ /// ending of a scope.
+ void identifyScopeMarkers();
+
+ /// Populate LexicalScope entries with variables' info.
+ void collectVariableInfo(DwarfCompileUnit &TheCU, const DISubprogram *SP,
+ DenseSet<InlinedVariable> &ProcessedVars);
+
+ /// Build the location list for all DBG_VALUEs in the
+ /// function that describe the same variable.
+ void buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
+ const DbgValueHistoryMap::InstrRanges &Ranges);
+
+ /// Collect variable information from the side table maintained
+ /// by MMI.
+ void collectVariableInfoFromMMITable(DenseSet<InlinedVariable> &P);
+
+ /// 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));
+ }
+
+public:
+ //===--------------------------------------------------------------------===//
+ // Main entry points.
+ //
+ DwarfDebug(AsmPrinter *A, Module *M);
+
+ ~DwarfDebug() override;
+
+ /// Emit all Dwarf sections that should come prior to the
+ /// content.
+ void beginModule();
+
+ /// Emit all Dwarf sections that should come after the content.
+ void endModule() override;
+
+ /// Gather pre-function debug information.
+ void beginFunction(const MachineFunction *MF) override;
+
+ /// Gather and emit post-function debug information.
+ void endFunction(const MachineFunction *MF) override;
+
+ /// Process beginning of an instruction.
+ void beginInstruction(const MachineInstr *MI) override;
+
+ /// Process end of an instruction.
+ void endInstruction() override;
+
+ /// Perform an MD5 checksum of \p Identifier and return the lower 64 bits.
+ static uint64_t makeTypeSignature(StringRef Identifier);
+
+ /// Add a DIE to the set of types that we're going to pull into
+ /// type units.
+ void addDwarfTypeUnitType(DwarfCompileUnit &CU, StringRef Identifier,
+ DIE &Die, const DICompositeType *CTy);
+
+ /// Add a label so that arange data can be generated for it.
+ void addArangeLabel(SymbolCU SCU) { ArangeLabels.push_back(SCU); }
+
+ /// For symbols that have a size designated (e.g. common symbols),
+ /// this tracks that size.
+ void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override {
+ SymSize[Sym] = Size;
+ }
+
+ /// Returns whether to emit DW_AT_[MIPS_]linkage_name.
+ bool useLinkageNames() const { return UseLinkageNames; }
+
+ /// Returns whether to use DW_OP_GNU_push_tls_address, instead of the
+ /// standard DW_OP_form_tls_address opcode
+ bool useGNUTLSOpcode() const { return UseGNUTLSOpcode; }
+
+ /// \defgroup DebuggerTuning Predicates to tune DWARF for a given debugger.
+ ///
+ /// Returns whether we are "tuning" for a given debugger.
+ /// @{
+ bool tuneForGDB() const { return DebuggerTuning == DebuggerKind::GDB; }
+ bool tuneForLLDB() const { return DebuggerTuning == DebuggerKind::LLDB; }
+ bool tuneForSCE() const { return DebuggerTuning == DebuggerKind::SCE; }
+ /// @}
+
+ // Experimental DWARF5 features.
+
+ /// Returns whether or not to emit tables that dwarf consumers can
+ /// use to accelerate lookup.
+ bool useDwarfAccelTables() const { return HasDwarfAccelTables; }
+
+ /// Returns whether or not to change the current debug info for the
+ /// split dwarf proposal support.
+ bool useSplitDwarf() const { return HasSplitDwarf; }
+
+ /// Returns the Dwarf Version.
+ unsigned getDwarfVersion() const { return DwarfVersion; }
+
+ /// Returns the previous CU that was being updated
+ const DwarfCompileUnit *getPrevCU() const { return PrevCU; }
+ void setPrevCU(const DwarfCompileUnit *PrevCU) { this->PrevCU = PrevCU; }
+
+ /// Returns the entries for the .debug_loc section.
+ const DebugLocStream &getDebugLocs() const { return DebugLocs; }
+
+ /// Emit an entry for the debug loc section. This can be used to
+ /// handle an entry that's going to be emitted into the debug loc section.
+ void emitDebugLocEntry(ByteStreamer &Streamer,
+ const DebugLocStream::Entry &Entry);
+
+ /// Emit the location for a debug loc entry, including the size header.
+ void emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry);
+
+ /// Find the MDNode for the given reference.
+ template <typename T> T *resolve(TypedDINodeRef<T> Ref) const {
+ return Ref.resolve(TypeIdentifierMap);
+ }
+
+ /// Return the TypeIdentifierMap.
+ const DITypeIdentifierMap &getTypeIdentifierMap() const {
+ return TypeIdentifierMap;
+ }
+
+ /// Find the DwarfCompileUnit for the given CU Die.
+ DwarfCompileUnit *lookupUnit(const DIE *CU) const {
+ return CUDieMap.lookup(CU);
+ }
+
+ void addSubprogramNames(const DISubprogram *SP, DIE &Die);
+
+ AddressPool &getAddressPool() { return AddrPool; }
+
+ void addAccelName(StringRef Name, const DIE &Die);
+
+ void addAccelObjC(StringRef Name, const DIE &Die);
+
+ void addAccelNamespace(StringRef Name, const DIE &Die);
+
+ void addAccelType(StringRef Name, const DIE &Die, char Flags);
+
+ const MachineFunction *getCurrentFunction() const { return CurFn; }
+
+ /// A helper function to check whether the DIE for a given Scope is
+ /// going to be null.
+ bool isLexicalScopeDIENull(LexicalScope *Scope);
+
+ /// Return Label preceding the instruction.
+ MCSymbol *getLabelBeforeInsn(const MachineInstr *MI);
+
+ /// Return Label immediately following the instruction.
+ MCSymbol *getLabelAfterInsn(const MachineInstr *MI);
+
+ // FIXME: Sink these functions down into DwarfFile/Dwarf*Unit.
+
+ SmallPtrSet<const MDNode *, 16> &getProcessedSPNodes() {
+ return ProcessedSPNodes;
+ }
+};
+} // End of namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfException.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfException.h
new file mode 100644
index 0000000..f4667b4
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfException.h
@@ -0,0 +1,87 @@
+//===-- DwarfException.h - Dwarf 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 dwarf exception info into asm files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H
+
+#include "EHStreamer.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+
+namespace llvm {
+class MachineFunction;
+class ARMTargetStreamer;
+
+class LLVM_LIBRARY_VISIBILITY DwarfCFIExceptionBase : public EHStreamer {
+protected:
+ DwarfCFIExceptionBase(AsmPrinter *A);
+
+ /// Per-function flag to indicate if frame CFI info should be emitted.
+ bool shouldEmitCFI;
+
+ void markFunctionEnd() override;
+};
+
+class LLVM_LIBRARY_VISIBILITY DwarfCFIException : public DwarfCFIExceptionBase {
+ /// Per-function flag to indicate if .cfi_personality should be emitted.
+ bool shouldEmitPersonality;
+
+ /// Per-function flag to indicate if .cfi_lsda should be emitted.
+ bool shouldEmitLSDA;
+
+ /// Per-function flag to indicate if frame moves info should be emitted.
+ bool shouldEmitMoves;
+
+ AsmPrinter::CFIMoveType moveTypeModule;
+
+public:
+ //===--------------------------------------------------------------------===//
+ // Main entry points.
+ //
+ DwarfCFIException(AsmPrinter *A);
+ ~DwarfCFIException() override;
+
+ /// Emit all exception information that should come after the content.
+ void endModule() override;
+
+ /// Gather pre-function exception information. Assumes being emitted
+ /// immediately after the function entry point.
+ void beginFunction(const MachineFunction *MF) override;
+
+ /// Gather and emit post-function exception information.
+ void endFunction(const MachineFunction *) override;
+};
+
+class LLVM_LIBRARY_VISIBILITY ARMException : public DwarfCFIExceptionBase {
+ void emitTypeInfos(unsigned TTypeEncoding) override;
+ ARMTargetStreamer &getTargetStreamer();
+
+public:
+ //===--------------------------------------------------------------------===//
+ // Main entry points.
+ //
+ ARMException(AsmPrinter *A);
+ ~ARMException() override;
+
+ /// Emit all exception information that should come after the content.
+ void endModule() override;
+
+ /// Gather pre-function exception information. Assumes being emitted
+ /// immediately after the function entry point.
+ void beginFunction(const MachineFunction *MF) override;
+
+ /// Gather and emit post-function exception information.
+ void endFunction(const MachineFunction *) override;
+};
+} // End of namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
new file mode 100644
index 0000000..7b5b831
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -0,0 +1,274 @@
+//===-- llvm/CodeGen/DwarfExpression.cpp - Dwarf Debug Framework ----------===//
+//
+// 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 dwarf debug info into asm files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DwarfExpression.h"
+#include "DwarfDebug.h"
+#include "llvm/ADT/SmallBitVector.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+
+using namespace llvm;
+
+void DwarfExpression::AddReg(int DwarfReg, const char *Comment) {
+ assert(DwarfReg >= 0 && "invalid negative dwarf register number");
+ if (DwarfReg < 32) {
+ EmitOp(dwarf::DW_OP_reg0 + DwarfReg, Comment);
+ } else {
+ EmitOp(dwarf::DW_OP_regx, Comment);
+ EmitUnsigned(DwarfReg);
+ }
+}
+
+void DwarfExpression::AddRegIndirect(int DwarfReg, int Offset, bool Deref) {
+ assert(DwarfReg >= 0 && "invalid negative dwarf register number");
+ if (DwarfReg < 32) {
+ EmitOp(dwarf::DW_OP_breg0 + DwarfReg);
+ } else {
+ EmitOp(dwarf::DW_OP_bregx);
+ EmitUnsigned(DwarfReg);
+ }
+ EmitSigned(Offset);
+ if (Deref)
+ EmitOp(dwarf::DW_OP_deref);
+}
+
+void DwarfExpression::AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits) {
+ assert(SizeInBits > 0 && "piece has size zero");
+ const unsigned SizeOfByte = 8;
+ if (OffsetInBits > 0 || SizeInBits % SizeOfByte) {
+ EmitOp(dwarf::DW_OP_bit_piece);
+ EmitUnsigned(SizeInBits);
+ EmitUnsigned(OffsetInBits);
+ } else {
+ EmitOp(dwarf::DW_OP_piece);
+ unsigned ByteSize = SizeInBits / SizeOfByte;
+ EmitUnsigned(ByteSize);
+ }
+}
+
+void DwarfExpression::AddShr(unsigned ShiftBy) {
+ EmitOp(dwarf::DW_OP_constu);
+ EmitUnsigned(ShiftBy);
+ EmitOp(dwarf::DW_OP_shr);
+}
+
+bool DwarfExpression::AddMachineRegIndirect(unsigned MachineReg, int Offset) {
+ if (isFrameRegister(MachineReg)) {
+ // If variable offset is based in frame register then use fbreg.
+ EmitOp(dwarf::DW_OP_fbreg);
+ EmitSigned(Offset);
+ return true;
+ }
+
+ int DwarfReg = TRI.getDwarfRegNum(MachineReg, false);
+ if (DwarfReg < 0)
+ return false;
+
+ AddRegIndirect(DwarfReg, Offset);
+ return true;
+}
+
+bool DwarfExpression::AddMachineRegPiece(unsigned MachineReg,
+ unsigned PieceSizeInBits,
+ unsigned PieceOffsetInBits) {
+ if (!TRI.isPhysicalRegister(MachineReg))
+ return false;
+
+ int Reg = TRI.getDwarfRegNum(MachineReg, false);
+
+ // If this is a valid register number, emit it.
+ if (Reg >= 0) {
+ AddReg(Reg);
+ if (PieceSizeInBits)
+ AddOpPiece(PieceSizeInBits, PieceOffsetInBits);
+ return true;
+ }
+
+ // Walk up the super-register chain until we find a valid number.
+ // For example, EAX on x86_64 is a 32-bit piece of RAX with offset 0.
+ for (MCSuperRegIterator SR(MachineReg, &TRI); SR.isValid(); ++SR) {
+ Reg = TRI.getDwarfRegNum(*SR, false);
+ if (Reg >= 0) {
+ unsigned Idx = TRI.getSubRegIndex(*SR, MachineReg);
+ unsigned Size = TRI.getSubRegIdxSize(Idx);
+ unsigned RegOffset = TRI.getSubRegIdxOffset(Idx);
+ AddReg(Reg, "super-register");
+ if (PieceOffsetInBits == RegOffset) {
+ AddOpPiece(Size, RegOffset);
+ } else {
+ // If this is part of a variable in a sub-register at a
+ // non-zero offset, we need to manually shift the value into
+ // place, since the DW_OP_piece describes the part of the
+ // variable, not the position of the subregister.
+ if (RegOffset)
+ AddShr(RegOffset);
+ AddOpPiece(Size, PieceOffsetInBits);
+ }
+ return true;
+ }
+ }
+
+ // Otherwise, attempt to find a covering set of sub-register numbers.
+ // For example, Q0 on ARM is a composition of D0+D1.
+ //
+ // Keep track of the current position so we can emit the more
+ // efficient DW_OP_piece.
+ unsigned CurPos = PieceOffsetInBits;
+ // The size of the register in bits, assuming 8 bits per byte.
+ unsigned RegSize = TRI.getMinimalPhysRegClass(MachineReg)->getSize() * 8;
+ // Keep track of the bits in the register we already emitted, so we
+ // can avoid emitting redundant aliasing subregs.
+ SmallBitVector Coverage(RegSize, false);
+ for (MCSubRegIterator SR(MachineReg, &TRI); SR.isValid(); ++SR) {
+ unsigned Idx = TRI.getSubRegIndex(MachineReg, *SR);
+ unsigned Size = TRI.getSubRegIdxSize(Idx);
+ unsigned Offset = TRI.getSubRegIdxOffset(Idx);
+ Reg = TRI.getDwarfRegNum(*SR, false);
+
+ // Intersection between the bits we already emitted and the bits
+ // covered by this subregister.
+ SmallBitVector Intersection(RegSize, false);
+ Intersection.set(Offset, Offset + Size);
+ Intersection ^= Coverage;
+
+ // If this sub-register has a DWARF number and we haven't covered
+ // its range, emit a DWARF piece for it.
+ if (Reg >= 0 && Intersection.any()) {
+ AddReg(Reg, "sub-register");
+ AddOpPiece(Size, Offset == CurPos ? 0 : Offset);
+ CurPos = Offset + Size;
+
+ // Mark it as emitted.
+ Coverage.set(Offset, Offset + Size);
+ }
+ }
+
+ return CurPos > PieceOffsetInBits;
+}
+
+void DwarfExpression::AddSignedConstant(int Value) {
+ EmitOp(dwarf::DW_OP_consts);
+ EmitSigned(Value);
+ // The proper way to describe a constant value is
+ // DW_OP_constu <const>, 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 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 expression.
+ // See PR21176 for more details.
+ if (DwarfVersion >= 4)
+ EmitOp(dwarf::DW_OP_stack_value);
+}
+
+void DwarfExpression::AddUnsignedConstant(unsigned Value) {
+ EmitOp(dwarf::DW_OP_constu);
+ EmitUnsigned(Value);
+ // cf. comment in DwarfExpression::AddSignedConstant().
+ if (DwarfVersion >= 4)
+ EmitOp(dwarf::DW_OP_stack_value);
+}
+
+static unsigned getOffsetOrZero(unsigned OffsetInBits,
+ unsigned PieceOffsetInBits) {
+ if (OffsetInBits == PieceOffsetInBits)
+ return 0;
+ assert(OffsetInBits >= PieceOffsetInBits && "overlapping pieces");
+ return OffsetInBits;
+}
+
+bool DwarfExpression::AddMachineRegExpression(const DIExpression *Expr,
+ unsigned MachineReg,
+ unsigned PieceOffsetInBits) {
+ auto I = Expr->expr_op_begin();
+ auto E = Expr->expr_op_end();
+ if (I == E)
+ return AddMachineRegPiece(MachineReg);
+
+ // Pattern-match combinations for which more efficient representations exist
+ // first.
+ bool ValidReg = false;
+ switch (I->getOp()) {
+ case dwarf::DW_OP_bit_piece: {
+ unsigned OffsetInBits = I->getArg(0);
+ unsigned SizeInBits = I->getArg(1);
+ // Piece always comes at the end of the expression.
+ return AddMachineRegPiece(MachineReg, SizeInBits,
+ getOffsetOrZero(OffsetInBits, PieceOffsetInBits));
+ }
+ case dwarf::DW_OP_plus:
+ case dwarf::DW_OP_minus: {
+ // [DW_OP_reg,Offset,DW_OP_plus, DW_OP_deref] --> [DW_OP_breg, Offset].
+ // [DW_OP_reg,Offset,DW_OP_minus,DW_OP_deref] --> [DW_OP_breg,-Offset].
+ auto N = I.getNext();
+ if (N != E && N->getOp() == dwarf::DW_OP_deref) {
+ unsigned Offset = I->getArg(0);
+ ValidReg = AddMachineRegIndirect(
+ MachineReg, I->getOp() == dwarf::DW_OP_plus ? Offset : -Offset);
+ std::advance(I, 2);
+ break;
+ } else
+ ValidReg = AddMachineRegPiece(MachineReg);
+ }
+ case dwarf::DW_OP_deref: {
+ // [DW_OP_reg,DW_OP_deref] --> [DW_OP_breg].
+ ValidReg = AddMachineRegIndirect(MachineReg);
+ ++I;
+ break;
+ }
+ default:
+ llvm_unreachable("unsupported operand");
+ }
+
+ if (!ValidReg)
+ return false;
+
+ // Emit remaining elements of the expression.
+ AddExpression(I, E, PieceOffsetInBits);
+ return true;
+}
+
+void DwarfExpression::AddExpression(DIExpression::expr_op_iterator I,
+ DIExpression::expr_op_iterator E,
+ unsigned PieceOffsetInBits) {
+ for (; I != E; ++I) {
+ switch (I->getOp()) {
+ case dwarf::DW_OP_bit_piece: {
+ unsigned OffsetInBits = I->getArg(0);
+ unsigned SizeInBits = I->getArg(1);
+ AddOpPiece(SizeInBits, getOffsetOrZero(OffsetInBits, PieceOffsetInBits));
+ break;
+ }
+ case dwarf::DW_OP_plus:
+ EmitOp(dwarf::DW_OP_plus_uconst);
+ EmitUnsigned(I->getArg(0));
+ break;
+ case dwarf::DW_OP_minus:
+ // There is no OP_minus_uconst.
+ EmitOp(dwarf::DW_OP_constu);
+ EmitUnsigned(I->getArg(0));
+ EmitOp(dwarf::DW_OP_minus);
+ break;
+ case dwarf::DW_OP_deref:
+ EmitOp(dwarf::DW_OP_deref);
+ break;
+ default:
+ llvm_unreachable("unhandled opcode found in expression");
+ }
+ }
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
new file mode 100644
index 0000000..78ec937
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
@@ -0,0 +1,136 @@
+//===-- llvm/CodeGen/DwarfExpression.h - Dwarf Compile Unit ---*- 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 dwarf compile unit.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXPRESSION_H
+
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+
+class AsmPrinter;
+class ByteStreamer;
+class TargetRegisterInfo;
+class DwarfUnit;
+class DIELoc;
+
+/// Base class containing the logic for constructing DWARF expressions
+/// independently of whether they are emitted into a DIE or into a .debug_loc
+/// entry.
+class DwarfExpression {
+protected:
+ // Various convenience accessors that extract things out of AsmPrinter.
+ const TargetRegisterInfo &TRI;
+ unsigned DwarfVersion;
+
+public:
+ DwarfExpression(const TargetRegisterInfo &TRI,
+ unsigned DwarfVersion)
+ : TRI(TRI), DwarfVersion(DwarfVersion) {}
+ virtual ~DwarfExpression() {}
+
+ /// Output a dwarf operand and an optional assembler comment.
+ virtual void EmitOp(uint8_t Op, const char *Comment = nullptr) = 0;
+ /// Emit a raw signed value.
+ virtual void EmitSigned(int64_t Value) = 0;
+ /// Emit a raw unsigned value.
+ virtual void EmitUnsigned(uint64_t Value) = 0;
+ /// Return whether the given machine register is the frame register in the
+ /// current function.
+ virtual bool isFrameRegister(unsigned MachineReg) = 0;
+
+ /// Emit a dwarf register operation.
+ void AddReg(int DwarfReg, const char *Comment = nullptr);
+ /// Emit an (double-)indirect dwarf register operation.
+ void AddRegIndirect(int DwarfReg, int Offset, bool Deref = false);
+
+ /// Emit a dwarf register operation for describing
+ /// - a small value occupying only part of a register or
+ /// - a register representing only part of a value.
+ void AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0);
+ /// Emit a shift-right dwarf expression.
+ void AddShr(unsigned ShiftBy);
+
+ /// Emit an indirect dwarf register operation for the given machine register.
+ /// \return false if no DWARF register exists for MachineReg.
+ bool AddMachineRegIndirect(unsigned MachineReg, int Offset = 0);
+
+ /// \brief Emit a partial DWARF register operation.
+ /// \param MachineReg the register
+ /// \param PieceSizeInBits size and
+ /// \param PieceOffsetInBits offset of the piece in bits, if this is one
+ /// piece of an aggregate value.
+ ///
+ /// If size and offset is zero an operation for the entire
+ /// register is emitted: Some targets do not provide a DWARF
+ /// register number for every register. If this is the case, this
+ /// function will attempt to emit a DWARF register by emitting a
+ /// piece of a super-register or by piecing together multiple
+ /// subregisters that alias the register.
+ ///
+ /// \return false if no DWARF register exists for MachineReg.
+ bool AddMachineRegPiece(unsigned MachineReg, unsigned PieceSizeInBits = 0,
+ unsigned PieceOffsetInBits = 0);
+
+ /// Emit a signed constant.
+ void AddSignedConstant(int Value);
+ /// Emit an unsigned constant.
+ void AddUnsignedConstant(unsigned Value);
+
+ /// \brief Emit an entire expression on top of a machine register location.
+ ///
+ /// \param PieceOffsetInBits If this is one piece out of a fragmented
+ /// location, this is the offset of the piece inside the entire variable.
+ /// \return false if no DWARF register exists for MachineReg.
+ bool AddMachineRegExpression(const DIExpression *Expr, unsigned MachineReg,
+ unsigned PieceOffsetInBits = 0);
+ /// Emit a the operations remaining the DIExpressionIterator I.
+ /// \param PieceOffsetInBits If this is one piece out of a fragmented
+ /// location, this is the offset of the piece inside the entire variable.
+ void AddExpression(DIExpression::expr_op_iterator I,
+ DIExpression::expr_op_iterator E,
+ unsigned PieceOffsetInBits = 0);
+};
+
+/// DwarfExpression implementation for .debug_loc entries.
+class DebugLocDwarfExpression : public DwarfExpression {
+ ByteStreamer &BS;
+
+public:
+ DebugLocDwarfExpression(const TargetRegisterInfo &TRI,
+ unsigned DwarfVersion, ByteStreamer &BS)
+ : DwarfExpression(TRI, DwarfVersion), BS(BS) {}
+
+ void EmitOp(uint8_t Op, const char *Comment = nullptr) override;
+ void EmitSigned(int64_t Value) override;
+ void EmitUnsigned(uint64_t Value) override;
+ bool isFrameRegister(unsigned MachineReg) override;
+};
+
+/// DwarfExpression implementation for singular DW_AT_location.
+class DIEDwarfExpression : public DwarfExpression {
+const AsmPrinter &AP;
+ DwarfUnit &DU;
+ DIELoc &DIE;
+
+public:
+ DIEDwarfExpression(const AsmPrinter &AP, DwarfUnit &DU, DIELoc &DIE);
+ void EmitOp(uint8_t Op, const char *Comment = nullptr) override;
+ void EmitSigned(int64_t Value) override;
+ void EmitUnsigned(uint64_t Value) override;
+ bool isFrameRegister(unsigned MachineReg) override;
+};
+}
+
+#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp
new file mode 100644
index 0000000..51b27b4
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp
@@ -0,0 +1,173 @@
+//===-- llvm/CodeGen/DwarfFile.cpp - Dwarf Debug Framework ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DwarfFile.h"
+#include "DwarfDebug.h"
+#include "DwarfUnit.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/LEB128.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+
+namespace llvm {
+DwarfFile::DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA)
+ : Asm(AP), StrPool(DA, *Asm, Pref) {}
+
+DwarfFile::~DwarfFile() {
+ for (DIEAbbrev *Abbrev : Abbreviations)
+ Abbrev->~DIEAbbrev();
+}
+
+// Define a unique number for the abbreviation.
+//
+DIEAbbrev &DwarfFile::assignAbbrevNumber(DIE &Die) {
+ FoldingSetNodeID ID;
+ DIEAbbrev Abbrev = Die.generateAbbrev();
+ Abbrev.Profile(ID);
+
+ void *InsertPos;
+ if (DIEAbbrev *Existing =
+ AbbreviationsSet.FindNodeOrInsertPos(ID, InsertPos)) {
+ Die.setAbbrevNumber(Existing->getNumber());
+ return *Existing;
+ }
+
+ // Move the abbreviation to the heap and assign a number.
+ DIEAbbrev *New = new (AbbrevAllocator) DIEAbbrev(std::move(Abbrev));
+ Abbreviations.push_back(New);
+ New->setNumber(Abbreviations.size());
+ Die.setAbbrevNumber(Abbreviations.size());
+
+ // Store it for lookup.
+ AbbreviationsSet.InsertNode(New, InsertPos);
+ return *New;
+}
+
+void DwarfFile::addUnit(std::unique_ptr<DwarfUnit> U) {
+ CUs.push_back(std::move(U));
+}
+
+// Emit the various dwarf units to the unit section USection with
+// the abbreviations going into ASection.
+void DwarfFile::emitUnits(bool UseOffsets) {
+ for (const auto &TheU : CUs) {
+ DIE &Die = TheU->getUnitDie();
+ MCSection *USection = TheU->getSection();
+ Asm->OutStreamer->SwitchSection(USection);
+
+ TheU->emitHeader(UseOffsets);
+
+ Asm->emitDwarfDIE(Die);
+ }
+}
+
+// Compute the size and offset for each DIE.
+void DwarfFile::computeSizeAndOffsets() {
+ // Offset from the first CU in the debug info section is 0 initially.
+ unsigned SecOffset = 0;
+
+ // 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) {
+ TheU->setDebugInfoOffset(SecOffset);
+
+ // CU-relative offset is reset to 0 here.
+ unsigned Offset = sizeof(int32_t) + // Length of Unit Info
+ TheU->getHeaderSize(); // Unit-specific headers
+
+ // EndOffset here is CU-relative, after laying out
+ // all of the CU DIE.
+ unsigned EndOffset = computeSizeAndOffset(TheU->getUnitDie(), Offset);
+ SecOffset += EndOffset;
+ }
+}
+// Compute the size and offset of a DIE. The offset is relative to start of the
+// CU. It returns the offset after laying out the DIE.
+unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
+ // Record the abbreviation.
+ const DIEAbbrev &Abbrev = assignAbbrevNumber(Die);
+
+ // Set DIE offset
+ Die.setOffset(Offset);
+
+ // Start the size with the size of abbreviation code.
+ Offset += getULEB128Size(Die.getAbbrevNumber());
+
+ // Size the DIE attribute values.
+ for (const auto &V : Die.values())
+ // Size attribute value.
+ Offset += V.SizeOf(Asm);
+
+ // Size the DIE children if any.
+ if (Die.hasChildren()) {
+ (void)Abbrev;
+ assert(Abbrev.hasChildren() && "Children flag not set");
+
+ for (auto &Child : Die.children())
+ Offset = computeSizeAndOffset(Child, Offset);
+
+ // End of children marker.
+ Offset += sizeof(int8_t);
+ }
+
+ Die.setSize(Offset - Die.getOffset());
+ return Offset;
+}
+
+void DwarfFile::emitAbbrevs(MCSection *Section) {
+ // Check to see if it is worth the effort.
+ if (!Abbreviations.empty()) {
+ // Start the debug abbrev section.
+ Asm->OutStreamer->SwitchSection(Section);
+ Asm->emitDwarfAbbrevs(Abbreviations);
+ }
+}
+
+// Emit strings into a string section.
+void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection) {
+ StrPool.emit(*Asm, StrSection, OffsetSection);
+}
+
+bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
+ SmallVectorImpl<DbgVariable *> &Vars = ScopeVariables[LS];
+ const DILocalVariable *DV = Var->getVariable();
+ // Variables with positive arg numbers are parameters.
+ if (unsigned ArgNum = DV->getArg()) {
+ // Keep all parameters in order at the start of the variable list to ensure
+ // function types are correct (no out-of-order parameters)
+ //
+ // This could be improved by only doing it for optimized builds (unoptimized
+ // builds have the right order to begin with), searching from the back (this
+ // would catch the unoptimized case quickly), or doing a binary search
+ // rather than linear search.
+ auto I = Vars.begin();
+ while (I != Vars.end()) {
+ unsigned CurNum = (*I)->getVariable()->getArg();
+ // A local (non-parameter) variable has been found, insert immediately
+ // before it.
+ if (CurNum == 0)
+ break;
+ // A later indexed parameter has been found, insert immediately before it.
+ if (CurNum > ArgNum)
+ break;
+ if (CurNum == ArgNum) {
+ (*I)->addMMIEntry(*Var);
+ return false;
+ }
+ ++I;
+ }
+ Vars.insert(I, Var);
+ return true;
+ }
+
+ Vars.push_back(Var);
+ return true;
+}
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
new file mode 100644
index 0000000..8402027
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
@@ -0,0 +1,118 @@
+//===-- llvm/CodeGen/DwarfFile.h - Dwarf Debug Framework -------*- 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_DWARFFILE_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFFILE_H
+
+#include "AddressPool.h"
+#include "DwarfStringPool.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Allocator.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace llvm {
+class AsmPrinter;
+class DbgVariable;
+class DwarfUnit;
+class DIEAbbrev;
+class MCSymbol;
+class DIE;
+class LexicalScope;
+class StringRef;
+class DwarfDebug;
+class MCSection;
+class MDNode;
+class DwarfFile {
+ // Target of Dwarf emission, used for sizing of abbreviations.
+ AsmPrinter *Asm;
+
+ BumpPtrAllocator AbbrevAllocator;
+
+ // Used to uniquely define abbreviations.
+ FoldingSet<DIEAbbrev> AbbreviationsSet;
+
+ // A list of all the unique abbreviations in use.
+ std::vector<DIEAbbrev *> Abbreviations;
+
+ // A pointer to all units in the section.
+ SmallVector<std::unique_ptr<DwarfUnit>, 1> CUs;
+
+ DwarfStringPool StrPool;
+
+ // Collection of dbg variables of a scope.
+ DenseMap<LexicalScope *, SmallVector<DbgVariable *, 8>> ScopeVariables;
+
+ // Collection of abstract subprogram DIEs.
+ DenseMap<const MDNode *, DIE *> AbstractSPDies;
+
+ /// 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
+ /// of in DwarfCompileUnit.
+ DenseMap<const MDNode *, DIE *> DITypeNodeToDieMap;
+
+public:
+ DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA);
+
+ ~DwarfFile();
+
+ const SmallVectorImpl<std::unique_ptr<DwarfUnit>> &getUnits() { return CUs; }
+
+ /// \brief Compute the size and offset of a DIE given an incoming Offset.
+ unsigned computeSizeAndOffset(DIE &Die, unsigned Offset);
+
+ /// \brief Compute the size and offset of all the DIEs.
+ void computeSizeAndOffsets();
+
+ /// Define a unique number for the abbreviation.
+ ///
+ /// Compute the abbreviation for \c Die, look up its unique number, and
+ /// return a reference to it in the uniquing table.
+ DIEAbbrev &assignAbbrevNumber(DIE &Die);
+
+ /// \brief Add a unit to the list of CUs.
+ void addUnit(std::unique_ptr<DwarfUnit> U);
+
+ /// \brief Emit all of the units to the section listed with the given
+ /// abbreviation section.
+ void emitUnits(bool UseOffsets);
+
+ /// \brief Emit a set of abbreviations to the specific section.
+ void emitAbbrevs(MCSection *);
+
+ /// \brief Emit all of the strings to the section given.
+ void emitStrings(MCSection *StrSection, MCSection *OffsetSection = nullptr);
+
+ /// \brief Returns the string pool.
+ DwarfStringPool &getStringPool() { return StrPool; }
+
+ /// \returns false if the variable was merged with a previous one.
+ bool addScopeVariable(LexicalScope *LS, DbgVariable *Var);
+
+ DenseMap<LexicalScope *, SmallVector<DbgVariable *, 8>> &getScopeVariables() {
+ return ScopeVariables;
+ }
+
+ DenseMap<const MDNode *, DIE *> &getAbstractSPDies() {
+ return AbstractSPDies;
+ }
+
+ void insertDIE(const MDNode *TypeMD, DIE *Die) {
+ DITypeNodeToDieMap.insert(std::make_pair(TypeMD, Die));
+ }
+ DIE *getDIE(const MDNode *TypeMD) {
+ return DITypeNodeToDieMap.lookup(TypeMD);
+ }
+};
+}
+#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
new file mode 100644
index 0000000..2066f74
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
@@ -0,0 +1,74 @@
+//===-- llvm/CodeGen/DwarfStringPool.cpp - Dwarf Debug Framework ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DwarfStringPool.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCStreamer.h"
+
+using namespace llvm;
+
+DwarfStringPool::DwarfStringPool(BumpPtrAllocator &A, AsmPrinter &Asm,
+ StringRef Prefix)
+ : Pool(A), Prefix(Prefix),
+ ShouldCreateSymbols(Asm.MAI->doesDwarfUseRelocationsAcrossSections()) {}
+
+DwarfStringPool::EntryRef DwarfStringPool::getEntry(AsmPrinter &Asm,
+ StringRef Str) {
+ auto I = Pool.insert(std::make_pair(Str, EntryTy()));
+ if (I.second) {
+ auto &Entry = I.first->second;
+ Entry.Index = Pool.size() - 1;
+ Entry.Offset = NumBytes;
+ Entry.Symbol = ShouldCreateSymbols ? Asm.createTempSymbol(Prefix) : nullptr;
+
+ NumBytes += Str.size() + 1;
+ assert(NumBytes > Entry.Offset && "Unexpected overflow");
+ }
+ return EntryRef(*I.first);
+}
+
+void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection,
+ MCSection *OffsetSection) {
+ if (Pool.empty())
+ return;
+
+ // 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());
+
+ for (const auto &E : Pool)
+ Entries[E.getValue().Index] = &E;
+
+ for (const auto &Entry : Entries) {
+ assert(ShouldCreateSymbols == static_cast<bool>(Entry->getValue().Symbol) &&
+ "Mismatch between setting and entry");
+
+ // Emit a label for reference from debug information entries.
+ if (ShouldCreateSymbols)
+ Asm.OutStreamer->EmitLabel(Entry->getValue().Symbol);
+
+ // Emit the string itself with a terminating null byte.
+ Asm.OutStreamer->AddComment("string offset=" +
+ Twine(Entry->getValue().Offset));
+ Asm.OutStreamer->EmitBytes(
+ StringRef(Entry->getKeyData(), Entry->getKeyLength() + 1));
+ }
+
+ // If we've got an offset section go ahead and emit that now as well.
+ if (OffsetSection) {
+ Asm.OutStreamer->SwitchSection(OffsetSection);
+ unsigned size = 4; // FIXME: DWARF64 is 8.
+ for (const auto &Entry : Entries)
+ Asm.OutStreamer->EmitIntValue(Entry->getValue().Offset, size);
+ }
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h
new file mode 100644
index 0000000..93a1684
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h
@@ -0,0 +1,49 @@
+//===-- llvm/CodeGen/DwarfStringPool.h - Dwarf Debug Framework -*- 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_DWARFSTRINGPOOL_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFSTRINGPOOL_H
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/CodeGen/DwarfStringPoolEntry.h"
+#include "llvm/Support/Allocator.h"
+#include <utility>
+
+namespace llvm {
+
+class AsmPrinter;
+class MCSymbol;
+class MCSection;
+class StringRef;
+
+// Collection of strings for this unit and assorted symbols.
+// A String->Symbol mapping of strings used by indirect
+// references.
+class DwarfStringPool {
+ typedef DwarfStringPoolEntry EntryTy;
+ StringMap<EntryTy, BumpPtrAllocator &> Pool;
+ StringRef Prefix;
+ unsigned NumBytes = 0;
+ bool ShouldCreateSymbols;
+
+public:
+ typedef DwarfStringPoolEntryRef EntryRef;
+
+ DwarfStringPool(BumpPtrAllocator &A, AsmPrinter &Asm, StringRef Prefix);
+
+ void emit(AsmPrinter &Asm, MCSection *StrSection,
+ MCSection *OffsetSection = nullptr);
+
+ bool empty() const { return Pool.empty(); }
+
+ /// Get a reference to an entry in the string pool.
+ EntryRef getEntry(AsmPrinter &Asm, StringRef Str);
+};
+}
+#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
new file mode 100644
index 0000000..d75fea5
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -0,0 +1,1553 @@
+//===-- llvm/CodeGen/DwarfUnit.cpp - Dwarf Type and Compile Units ---------===//
+//
+// 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 constructing a dwarf compile unit.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DwarfUnit.h"
+#include "DwarfAccelTable.h"
+#include "DwarfCompileUnit.h"
+#include "DwarfDebug.h"
+#include "DwarfExpression.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DIBuilder.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Mangler.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Target/TargetFrameLowering.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "dwarfdebug"
+
+static cl::opt<bool>
+GenerateDwarfTypeUnits("generate-type-units", cl::Hidden,
+ cl::desc("Generate DWARF4 type units."),
+ cl::init(false));
+
+DIEDwarfExpression::DIEDwarfExpression(const AsmPrinter &AP, DwarfUnit &DU,
+ DIELoc &DIE)
+ : DwarfExpression(*AP.MF->getSubtarget().getRegisterInfo(),
+ AP.getDwarfDebug()->getDwarfVersion()),
+ AP(AP), DU(DU), DIE(DIE) {}
+
+void DIEDwarfExpression::EmitOp(uint8_t Op, const char* Comment) {
+ DU.addUInt(DIE, dwarf::DW_FORM_data1, Op);
+}
+void DIEDwarfExpression::EmitSigned(int64_t Value) {
+ DU.addSInt(DIE, dwarf::DW_FORM_sdata, Value);
+}
+void DIEDwarfExpression::EmitUnsigned(uint64_t Value) {
+ DU.addUInt(DIE, dwarf::DW_FORM_udata, Value);
+}
+bool DIEDwarfExpression::isFrameRegister(unsigned MachineReg) {
+ return MachineReg == TRI.getFrameRegister(*AP.MF);
+}
+
+DwarfUnit::DwarfUnit(unsigned UID, dwarf::Tag UnitTag,
+ const DICompileUnit *Node, AsmPrinter *A, DwarfDebug *DW,
+ DwarfFile *DWU)
+ : UniqueID(UID), CUNode(Node),
+ UnitDie(*DIE::get(DIEValueAllocator, UnitTag)), DebugInfoOffset(0),
+ Asm(A), DD(DW), DU(DWU), IndexTyDie(nullptr), Section(nullptr) {
+ assert(UnitTag == dwarf::DW_TAG_compile_unit ||
+ UnitTag == dwarf::DW_TAG_type_unit);
+}
+
+DwarfTypeUnit::DwarfTypeUnit(unsigned UID, DwarfCompileUnit &CU, AsmPrinter *A,
+ DwarfDebug *DW, DwarfFile *DWU,
+ MCDwarfDwoLineTable *SplitLineTable)
+ : DwarfUnit(UID, dwarf::DW_TAG_type_unit, CU.getCUNode(), A, DW, DWU),
+ CU(CU), SplitLineTable(SplitLineTable) {
+ if (SplitLineTable)
+ addSectionOffset(UnitDie, dwarf::DW_AT_stmt_list, 0);
+}
+
+DwarfUnit::~DwarfUnit() {
+ for (unsigned j = 0, M = DIEBlocks.size(); j < M; ++j)
+ DIEBlocks[j]->~DIEBlock();
+ for (unsigned j = 0, M = DIELocs.size(); j < M; ++j)
+ DIELocs[j]->~DIELoc();
+}
+
+int64_t DwarfUnit::getDefaultLowerBound() const {
+ switch (getLanguage()) {
+ default:
+ break;
+
+ case dwarf::DW_LANG_C89:
+ case dwarf::DW_LANG_C99:
+ case dwarf::DW_LANG_C:
+ case dwarf::DW_LANG_C_plus_plus:
+ case dwarf::DW_LANG_ObjC:
+ case dwarf::DW_LANG_ObjC_plus_plus:
+ return 0;
+
+ case dwarf::DW_LANG_Fortran77:
+ case dwarf::DW_LANG_Fortran90:
+ case dwarf::DW_LANG_Fortran95:
+ return 1;
+
+ // The languages below have valid values only if the DWARF version >= 4.
+ case dwarf::DW_LANG_Java:
+ case dwarf::DW_LANG_Python:
+ case dwarf::DW_LANG_UPC:
+ case dwarf::DW_LANG_D:
+ if (dwarf::DWARF_VERSION >= 4)
+ return 0;
+ break;
+
+ case dwarf::DW_LANG_Ada83:
+ case dwarf::DW_LANG_Ada95:
+ case dwarf::DW_LANG_Cobol74:
+ case dwarf::DW_LANG_Cobol85:
+ case dwarf::DW_LANG_Modula2:
+ case dwarf::DW_LANG_Pascal83:
+ case dwarf::DW_LANG_PLI:
+ if (dwarf::DWARF_VERSION >= 4)
+ return 1;
+ break;
+
+ // The languages below have valid values only if the DWARF version >= 5.
+ case dwarf::DW_LANG_OpenCL:
+ case dwarf::DW_LANG_Go:
+ case dwarf::DW_LANG_Haskell:
+ case dwarf::DW_LANG_C_plus_plus_03:
+ case dwarf::DW_LANG_C_plus_plus_11:
+ case dwarf::DW_LANG_OCaml:
+ case dwarf::DW_LANG_Rust:
+ case dwarf::DW_LANG_C11:
+ case dwarf::DW_LANG_Swift:
+ case dwarf::DW_LANG_Dylan:
+ case dwarf::DW_LANG_C_plus_plus_14:
+ if (dwarf::DWARF_VERSION >= 5)
+ return 0;
+ break;
+
+ case dwarf::DW_LANG_Modula3:
+ case dwarf::DW_LANG_Julia:
+ case dwarf::DW_LANG_Fortran03:
+ case dwarf::DW_LANG_Fortran08:
+ if (dwarf::DWARF_VERSION >= 5)
+ return 1;
+ break;
+ }
+
+ return -1;
+}
+
+/// Check whether the DIE for this MDNode can be shared across CUs.
+static bool isShareableAcrossCUs(const DINode *D) {
+ // When the MDNode can be part of the type system, the DIE can be shared
+ // across CUs.
+ // Combining type units and cross-CU DIE sharing is lower value (since
+ // cross-CU DIE sharing is used in LTO and removes type redundancy at that
+ // level already) but may be implementable for some value in projects
+ // building multiple independent libraries with LTO and then linking those
+ // together.
+ return (isa<DIType>(D) ||
+ (isa<DISubprogram>(D) && !cast<DISubprogram>(D)->isDefinition())) &&
+ !GenerateDwarfTypeUnits;
+}
+
+DIE *DwarfUnit::getDIE(const DINode *D) const {
+ if (isShareableAcrossCUs(D))
+ return DU->getDIE(D);
+ return MDNodeToDieMap.lookup(D);
+}
+
+void DwarfUnit::insertDIE(const DINode *Desc, DIE *D) {
+ if (isShareableAcrossCUs(Desc)) {
+ DU->insertDIE(Desc, D);
+ return;
+ }
+ MDNodeToDieMap.insert(std::make_pair(Desc, D));
+}
+
+void DwarfUnit::addFlag(DIE &Die, dwarf::Attribute Attribute) {
+ if (DD->getDwarfVersion() >= 4)
+ Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_flag_present,
+ DIEInteger(1));
+ else
+ Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_flag,
+ DIEInteger(1));
+}
+
+void DwarfUnit::addUInt(DIEValueList &Die, dwarf::Attribute Attribute,
+ Optional<dwarf::Form> Form, uint64_t Integer) {
+ if (!Form)
+ Form = DIEInteger::BestForm(false, Integer);
+ Die.addValue(DIEValueAllocator, Attribute, *Form, DIEInteger(Integer));
+}
+
+void DwarfUnit::addUInt(DIEValueList &Block, dwarf::Form Form,
+ uint64_t Integer) {
+ addUInt(Block, (dwarf::Attribute)0, Form, Integer);
+}
+
+void DwarfUnit::addSInt(DIEValueList &Die, dwarf::Attribute Attribute,
+ Optional<dwarf::Form> Form, int64_t Integer) {
+ if (!Form)
+ Form = DIEInteger::BestForm(true, Integer);
+ Die.addValue(DIEValueAllocator, Attribute, *Form, DIEInteger(Integer));
+}
+
+void DwarfUnit::addSInt(DIELoc &Die, Optional<dwarf::Form> Form,
+ int64_t Integer) {
+ addSInt(Die, (dwarf::Attribute)0, Form, Integer);
+}
+
+void DwarfUnit::addString(DIE &Die, dwarf::Attribute Attribute,
+ StringRef String) {
+ Die.addValue(DIEValueAllocator, Attribute,
+ isDwoUnit() ? dwarf::DW_FORM_GNU_str_index : dwarf::DW_FORM_strp,
+ DIEString(DU->getStringPool().getEntry(*Asm, String)));
+}
+
+DIEValueList::value_iterator DwarfUnit::addLabel(DIEValueList &Die,
+ dwarf::Attribute Attribute,
+ dwarf::Form Form,
+ const MCSymbol *Label) {
+ return Die.addValue(DIEValueAllocator, Attribute, Form, DIELabel(Label));
+}
+
+void DwarfUnit::addLabel(DIELoc &Die, dwarf::Form Form, const MCSymbol *Label) {
+ addLabel(Die, (dwarf::Attribute)0, Form, Label);
+}
+
+void DwarfUnit::addSectionOffset(DIE &Die, dwarf::Attribute Attribute,
+ uint64_t Integer) {
+ if (DD->getDwarfVersion() >= 4)
+ addUInt(Die, Attribute, dwarf::DW_FORM_sec_offset, Integer);
+ else
+ addUInt(Die, Attribute, dwarf::DW_FORM_data4, Integer);
+}
+
+unsigned DwarfTypeUnit::getOrCreateSourceID(StringRef FileName, StringRef DirName) {
+ return SplitLineTable ? SplitLineTable->getFile(DirName, FileName)
+ : getCU().getOrCreateSourceID(FileName, DirName);
+}
+
+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 {
+ addUInt(Die, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_addr_index);
+ addUInt(Die, dwarf::DW_FORM_GNU_addr_index,
+ DD->getAddressPool().getIndex(Sym));
+ }
+}
+
+void DwarfUnit::addLabelDelta(DIE &Die, dwarf::Attribute Attribute,
+ const MCSymbol *Hi, const MCSymbol *Lo) {
+ Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_data4,
+ new (DIEValueAllocator) DIEDelta(Hi, Lo));
+}
+
+void DwarfUnit::addDIEEntry(DIE &Die, dwarf::Attribute Attribute, DIE &Entry) {
+ addDIEEntry(Die, Attribute, DIEEntry(Entry));
+}
+
+void DwarfUnit::addDIETypeSignature(DIE &Die, const DwarfTypeUnit &Type) {
+ // Flag the type unit reference as a declaration so that if it contains
+ // members (implicit special members, static data member definitions, member
+ // declarations for definitions in this CU, etc) consumers don't get confused
+ // and think this is a full definition.
+ addFlag(Die, dwarf::DW_AT_declaration);
+
+ Die.addValue(DIEValueAllocator, dwarf::DW_AT_signature,
+ dwarf::DW_FORM_ref_sig8, DIETypeSignature(Type));
+}
+
+void DwarfUnit::addDIETypeSignature(DIE &Die, dwarf::Attribute Attribute,
+ StringRef Identifier) {
+ uint64_t Signature = DD->makeTypeSignature(Identifier);
+ Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_ref_sig8,
+ DIEInteger(Signature));
+}
+
+void DwarfUnit::addDIEEntry(DIE &Die, dwarf::Attribute Attribute,
+ DIEEntry Entry) {
+ const DIE *DieCU = Die.getUnitOrNull();
+ const DIE *EntryCU = Entry.getEntry().getUnitOrNull();
+ if (!DieCU)
+ // We assume that Die belongs to this CU, if it is not linked to any CU yet.
+ DieCU = &getUnitDie();
+ if (!EntryCU)
+ EntryCU = &getUnitDie();
+ Die.addValue(DIEValueAllocator, Attribute,
+ EntryCU == DieCU ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr,
+ Entry);
+}
+
+DIE &DwarfUnit::createAndAddDIE(unsigned Tag, DIE &Parent, const DINode *N) {
+ DIE &Die = Parent.addChild(DIE::get(DIEValueAllocator, (dwarf::Tag)Tag));
+ if (N)
+ insertDIE(N, &Die);
+ return Die;
+}
+
+void DwarfUnit::addBlock(DIE &Die, dwarf::Attribute Attribute, DIELoc *Loc) {
+ Loc->ComputeSize(Asm);
+ DIELocs.push_back(Loc); // Memoize so we can call the destructor later on.
+ Die.addValue(DIEValueAllocator, Attribute,
+ Loc->BestForm(DD->getDwarfVersion()), Loc);
+}
+
+void DwarfUnit::addBlock(DIE &Die, dwarf::Attribute Attribute,
+ DIEBlock *Block) {
+ Block->ComputeSize(Asm);
+ DIEBlocks.push_back(Block); // Memoize so we can call the destructor later on.
+ Die.addValue(DIEValueAllocator, Attribute, Block->BestForm(), Block);
+}
+
+void DwarfUnit::addSourceLine(DIE &Die, unsigned Line, StringRef File,
+ StringRef Directory) {
+ if (Line == 0)
+ return;
+
+ unsigned FileID = getOrCreateSourceID(File, Directory);
+ assert(FileID && "Invalid file id");
+ addUInt(Die, dwarf::DW_AT_decl_file, None, FileID);
+ addUInt(Die, dwarf::DW_AT_decl_line, None, Line);
+}
+
+void DwarfUnit::addSourceLine(DIE &Die, const DILocalVariable *V) {
+ assert(V);
+
+ addSourceLine(Die, V->getLine(), V->getScope()->getFilename(),
+ V->getScope()->getDirectory());
+}
+
+void DwarfUnit::addSourceLine(DIE &Die, const DIGlobalVariable *G) {
+ assert(G);
+
+ addSourceLine(Die, G->getLine(), G->getFilename(), G->getDirectory());
+}
+
+void DwarfUnit::addSourceLine(DIE &Die, const DISubprogram *SP) {
+ assert(SP);
+
+ addSourceLine(Die, SP->getLine(), SP->getFilename(), SP->getDirectory());
+}
+
+void DwarfUnit::addSourceLine(DIE &Die, const DIType *Ty) {
+ assert(Ty);
+
+ addSourceLine(Die, Ty->getLine(), Ty->getFilename(), Ty->getDirectory());
+}
+
+void DwarfUnit::addSourceLine(DIE &Die, const DIObjCProperty *Ty) {
+ assert(Ty);
+
+ addSourceLine(Die, Ty->getLine(), Ty->getFilename(), Ty->getDirectory());
+}
+
+void DwarfUnit::addSourceLine(DIE &Die, const DINamespace *NS) {
+ addSourceLine(Die, NS->getLine(), NS->getFilename(), NS->getDirectory());
+}
+
+bool DwarfUnit::addRegisterOpPiece(DIELoc &TheDie, unsigned Reg,
+ unsigned SizeInBits, unsigned OffsetInBits) {
+ DIEDwarfExpression Expr(*Asm, *this, TheDie);
+ Expr.AddMachineRegPiece(Reg, SizeInBits, OffsetInBits);
+ return true;
+}
+
+bool DwarfUnit::addRegisterOffset(DIELoc &TheDie, unsigned Reg,
+ int64_t Offset) {
+ DIEDwarfExpression Expr(*Asm, *this, TheDie);
+ return Expr.AddMachineRegIndirect(Reg, Offset);
+}
+
+/* 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;
+
+ bool validReg;
+ if (Location.isReg())
+ validReg = addRegisterOpPiece(*Loc, Location.getReg());
+ else
+ validReg = addRegisterOffset(*Loc, Location.getReg(), Location.getOffset());
+
+ if (!validReg)
+ return;
+
+ // 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)
+ addUInt(*Loc, dwarf::DW_FORM_data1, 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) {
+ addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
+ addUInt(*Loc, dwarf::DW_FORM_udata, forwardingFieldOffset);
+ }
+
+ // Now dereference the __forwarding field to get to the real __Block_byref
+ // struct: DW_OP_deref.
+ addUInt(*Loc, dwarf::DW_FORM_data1, 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) {
+ addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
+ addUInt(*Loc, dwarf::DW_FORM_udata, varFieldOffset);
+ }
+
+ // Now attach the location information to the DIE.
+ addBlock(Die, Attribute, Loc);
+}
+
+/// Return true if type encoding is unsigned.
+static bool isUnsignedDIType(DwarfDebug *DD, const DIType *Ty) {
+ if (auto *CTy = dyn_cast<DICompositeType>(Ty)) {
+ // FIXME: Enums without a fixed underlying type have unknown signedness
+ // here, leading to incorrectly emitted constants.
+ if (CTy->getTag() == dwarf::DW_TAG_enumeration_type)
+ return false;
+
+ // (Pieces of) aggregate types that get hacked apart by SROA may be
+ // represented by a constant. Encode them as unsigned bytes.
+ return true;
+ }
+
+ if (auto *DTy = dyn_cast<DIDerivedType>(Ty)) {
+ dwarf::Tag T = (dwarf::Tag)Ty->getTag();
+ // Encode pointer constants as unsigned bytes. This is used at least for
+ // null pointer constant emission.
+ // FIXME: reference and rvalue_reference /probably/ shouldn't be allowed
+ // here, but accept them for now due to a bug in SROA producing bogus
+ // dbg.values.
+ if (T == dwarf::DW_TAG_pointer_type ||
+ T == dwarf::DW_TAG_ptr_to_member_type ||
+ T == dwarf::DW_TAG_reference_type ||
+ T == dwarf::DW_TAG_rvalue_reference_type)
+ return true;
+ assert(T == dwarf::DW_TAG_typedef || T == dwarf::DW_TAG_const_type ||
+ T == dwarf::DW_TAG_volatile_type ||
+ T == dwarf::DW_TAG_restrict_type);
+ DITypeRef Deriv = DTy->getBaseType();
+ assert(Deriv && "Expected valid base type");
+ return isUnsignedDIType(DD, DD->resolve(Deriv));
+ }
+
+ auto *BTy = cast<DIBasicType>(Ty);
+ unsigned Encoding = BTy->getEncoding();
+ assert((Encoding == dwarf::DW_ATE_unsigned ||
+ Encoding == dwarf::DW_ATE_unsigned_char ||
+ Encoding == dwarf::DW_ATE_signed ||
+ Encoding == dwarf::DW_ATE_signed_char ||
+ Encoding == dwarf::DW_ATE_float || Encoding == dwarf::DW_ATE_UTF ||
+ Encoding == dwarf::DW_ATE_boolean ||
+ (Ty->getTag() == dwarf::DW_TAG_unspecified_type &&
+ Ty->getName() == "decltype(nullptr)")) &&
+ "Unsupported encoding");
+ return Encoding == dwarf::DW_ATE_unsigned ||
+ Encoding == dwarf::DW_ATE_unsigned_char ||
+ Encoding == dwarf::DW_ATE_UTF || Encoding == dwarf::DW_ATE_boolean ||
+ Ty->getTag() == dwarf::DW_TAG_unspecified_type;
+}
+
+/// If this type is derived from a base type then return base type size.
+static uint64_t getBaseTypeSize(DwarfDebug *DD, const DIDerivedType *Ty) {
+ unsigned Tag = Ty->getTag();
+
+ if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef &&
+ Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type &&
+ Tag != dwarf::DW_TAG_restrict_type)
+ return Ty->getSizeInBits();
+
+ auto *BaseType = DD->resolve(Ty->getBaseType());
+
+ assert(BaseType && "Unexpected invalid base type");
+
+ // If this is a derived type, go ahead and get the base type, unless it's a
+ // reference then it's just the size of the field. Pointer types have no need
+ // of this since they're a different type of qualification on the type.
+ if (BaseType->getTag() == dwarf::DW_TAG_reference_type ||
+ BaseType->getTag() == dwarf::DW_TAG_rvalue_reference_type)
+ return Ty->getSizeInBits();
+
+ if (auto *DT = dyn_cast<DIDerivedType>(BaseType))
+ return getBaseTypeSize(DD, DT);
+
+ return BaseType->getSizeInBits();
+}
+
+void DwarfUnit::addConstantFPValue(DIE &Die, const MachineOperand &MO) {
+ assert(MO.isFPImm() && "Invalid machine operand!");
+ DIEBlock *Block = new (DIEValueAllocator) DIEBlock;
+ APFloat FPImm = MO.getFPImm()->getValueAPF();
+
+ // Get the raw data form of the floating point.
+ const APInt FltVal = FPImm.bitcastToAPInt();
+ const char *FltPtr = (const char *)FltVal.getRawData();
+
+ int NumBytes = FltVal.getBitWidth() / 8; // 8 bits per byte.
+ bool LittleEndian = Asm->getDataLayout().isLittleEndian();
+ int Incr = (LittleEndian ? 1 : -1);
+ int Start = (LittleEndian ? 0 : NumBytes - 1);
+ int Stop = (LittleEndian ? NumBytes : -1);
+
+ // Output the constant to DWARF one byte at a time.
+ for (; Start != Stop; Start += Incr)
+ addUInt(*Block, dwarf::DW_FORM_data1, (unsigned char)0xFF & FltPtr[Start]);
+
+ addBlock(Die, dwarf::DW_AT_const_value, Block);
+}
+
+void DwarfUnit::addConstantFPValue(DIE &Die, const ConstantFP *CFP) {
+ // Pass this down to addConstantValue as an unsigned bag of bits.
+ addConstantValue(Die, CFP->getValueAPF().bitcastToAPInt(), true);
+}
+
+void DwarfUnit::addConstantValue(DIE &Die, const ConstantInt *CI,
+ const DIType *Ty) {
+ addConstantValue(Die, CI->getValue(), Ty);
+}
+
+void DwarfUnit::addConstantValue(DIE &Die, const MachineOperand &MO,
+ const DIType *Ty) {
+ assert(MO.isImm() && "Invalid machine operand!");
+
+ addConstantValue(Die, isUnsignedDIType(DD, Ty), MO.getImm());
+}
+
+void DwarfUnit::addConstantValue(DIE &Die, bool Unsigned, uint64_t Val) {
+ // FIXME: This is a bit conservative/simple - it emits negative values always
+ // sign extended to 64 bits rather than minimizing the number of bytes.
+ addUInt(Die, dwarf::DW_AT_const_value,
+ Unsigned ? dwarf::DW_FORM_udata : dwarf::DW_FORM_sdata, Val);
+}
+
+void DwarfUnit::addConstantValue(DIE &Die, const APInt &Val, const DIType *Ty) {
+ addConstantValue(Die, Val, isUnsignedDIType(DD, Ty));
+}
+
+void DwarfUnit::addConstantValue(DIE &Die, const APInt &Val, bool Unsigned) {
+ unsigned CIBitWidth = Val.getBitWidth();
+ if (CIBitWidth <= 64) {
+ addConstantValue(Die, Unsigned,
+ Unsigned ? Val.getZExtValue() : Val.getSExtValue());
+ return;
+ }
+
+ DIEBlock *Block = new (DIEValueAllocator) DIEBlock;
+
+ // Get the raw data form of the large APInt.
+ const uint64_t *Ptr64 = Val.getRawData();
+
+ int NumBytes = Val.getBitWidth() / 8; // 8 bits per byte.
+ bool LittleEndian = Asm->getDataLayout().isLittleEndian();
+
+ // Output the constant to DWARF one byte at a time.
+ for (int i = 0; i < NumBytes; i++) {
+ uint8_t c;
+ if (LittleEndian)
+ c = Ptr64[i / 8] >> (8 * (i & 7));
+ else
+ c = Ptr64[(NumBytes - 1 - i) / 8] >> (8 * ((NumBytes - 1 - i) & 7));
+ addUInt(*Block, dwarf::DW_FORM_data1, c);
+ }
+
+ addBlock(Die, dwarf::DW_AT_const_value, Block);
+}
+
+void DwarfUnit::addLinkageName(DIE &Die, StringRef LinkageName) {
+ if (!LinkageName.empty() && DD->useLinkageNames())
+ addString(Die,
+ DD->getDwarfVersion() >= 4 ? dwarf::DW_AT_linkage_name
+ : dwarf::DW_AT_MIPS_linkage_name,
+ GlobalValue::getRealLinkageName(LinkageName));
+}
+
+void DwarfUnit::addTemplateParams(DIE &Buffer, DINodeArray TParams) {
+ // Add template parameters.
+ for (const auto *Element : TParams) {
+ if (auto *TTP = dyn_cast<DITemplateTypeParameter>(Element))
+ constructTemplateTypeParameterDIE(Buffer, TTP);
+ else if (auto *TVP = dyn_cast<DITemplateValueParameter>(Element))
+ constructTemplateValueParameterDIE(Buffer, TVP);
+ }
+}
+
+DIE *DwarfUnit::getOrCreateContextDIE(const DIScope *Context) {
+ if (!Context || isa<DIFile>(Context))
+ return &getUnitDie();
+ if (auto *T = dyn_cast<DIType>(Context))
+ return getOrCreateTypeDIE(T);
+ if (auto *NS = dyn_cast<DINamespace>(Context))
+ return getOrCreateNameSpace(NS);
+ if (auto *SP = dyn_cast<DISubprogram>(Context))
+ return getOrCreateSubprogramDIE(SP);
+ if (auto *M = dyn_cast<DIModule>(Context))
+ return getOrCreateModule(M);
+ return getDIE(Context);
+}
+
+DIE *DwarfUnit::createTypeDIE(const DICompositeType *Ty) {
+ auto *Context = resolve(Ty->getScope());
+ DIE *ContextDIE = getOrCreateContextDIE(Context);
+
+ if (DIE *TyDIE = getDIE(Ty))
+ return TyDIE;
+
+ // Create new type.
+ DIE &TyDIE = createAndAddDIE(Ty->getTag(), *ContextDIE, Ty);
+
+ constructTypeDIE(TyDIE, cast<DICompositeType>(Ty));
+
+ if (!Ty->isExternalTypeRef())
+ updateAcceleratorTables(Context, Ty, TyDIE);
+ return &TyDIE;
+}
+
+DIE *DwarfUnit::getOrCreateTypeDIE(const MDNode *TyNode) {
+ if (!TyNode)
+ return nullptr;
+
+ auto *Ty = cast<DIType>(TyNode);
+ assert(Ty == resolve(Ty->getRef()) &&
+ "type was not uniqued, possible ODR violation.");
+
+ // DW_TAG_restrict_type is not supported in DWARF2
+ if (Ty->getTag() == dwarf::DW_TAG_restrict_type && DD->getDwarfVersion() <= 2)
+ return getOrCreateTypeDIE(resolve(cast<DIDerivedType>(Ty)->getBaseType()));
+
+ // Construct the context before querying for the existence of the DIE in case
+ // such construction creates the DIE.
+ auto *Context = resolve(Ty->getScope());
+ DIE *ContextDIE = getOrCreateContextDIE(Context);
+ assert(ContextDIE);
+
+ if (DIE *TyDIE = getDIE(Ty))
+ return TyDIE;
+
+ // Create new type.
+ DIE &TyDIE = createAndAddDIE(Ty->getTag(), *ContextDIE, Ty);
+
+ updateAcceleratorTables(Context, Ty, TyDIE);
+
+ if (auto *BT = dyn_cast<DIBasicType>(Ty))
+ constructTypeDIE(TyDIE, BT);
+ else if (auto *STy = dyn_cast<DISubroutineType>(Ty))
+ constructTypeDIE(TyDIE, STy);
+ else if (auto *CTy = dyn_cast<DICompositeType>(Ty)) {
+ if (GenerateDwarfTypeUnits && !Ty->isForwardDecl())
+ if (MDString *TypeId = CTy->getRawIdentifier()) {
+ DD->addDwarfTypeUnitType(getCU(), TypeId->getString(), TyDIE, CTy);
+ // Skip updating the accelerator tables since this is not the full type.
+ return &TyDIE;
+ }
+ constructTypeDIE(TyDIE, CTy);
+ } else {
+ constructTypeDIE(TyDIE, cast<DIDerivedType>(Ty));
+ }
+
+ return &TyDIE;
+}
+
+void DwarfUnit::updateAcceleratorTables(const DIScope *Context,
+ const DIType *Ty, const DIE &TyDIE) {
+ if (!Ty->getName().empty() && !Ty->isForwardDecl()) {
+ bool IsImplementation = 0;
+ if (auto *CT = dyn_cast<DICompositeType>(Ty)) {
+ // A runtime language of 0 actually means C/C++ and that any
+ // non-negative value is some version of Objective-C/C++.
+ IsImplementation = CT->getRuntimeLang() == 0 || CT->isObjcClassComplete();
+ }
+ unsigned Flags = IsImplementation ? dwarf::DW_FLAG_type_implementation : 0;
+ DD->addAccelType(Ty->getName(), TyDIE, Flags);
+
+ if (!Context || isa<DICompileUnit>(Context) || isa<DIFile>(Context) ||
+ isa<DINamespace>(Context))
+ addGlobalType(Ty, TyDIE, Context);
+ }
+}
+
+void DwarfUnit::addType(DIE &Entity, const DIType *Ty,
+ dwarf::Attribute Attribute) {
+ assert(Ty && "Trying to add a type that doesn't exist?");
+ addDIEEntry(Entity, Attribute, DIEEntry(*getOrCreateTypeDIE(Ty)));
+}
+
+std::string DwarfUnit::getParentContextString(const DIScope *Context) const {
+ if (!Context)
+ return "";
+
+ // FIXME: Decide whether to implement this for non-C++ languages.
+ if (getLanguage() != dwarf::DW_LANG_C_plus_plus)
+ return "";
+
+ std::string CS;
+ SmallVector<const DIScope *, 1> Parents;
+ while (!isa<DICompileUnit>(Context)) {
+ Parents.push_back(Context);
+ if (Context->getScope())
+ Context = resolve(Context->getScope());
+ else
+ // Structure, etc types will have a NULL context if they're at the top
+ // level.
+ break;
+ }
+
+ // Reverse iterate over our list to go from the outermost construct to the
+ // innermost.
+ for (const DIScope *Ctx : make_range(Parents.rbegin(), Parents.rend())) {
+ StringRef Name = Ctx->getName();
+ if (Name.empty() && isa<DINamespace>(Ctx))
+ Name = "(anonymous namespace)";
+ if (!Name.empty()) {
+ CS += Name;
+ CS += "::";
+ }
+ }
+ return CS;
+}
+
+void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIBasicType *BTy) {
+ // Get core information.
+ StringRef Name = BTy->getName();
+ // Add name if not anonymous or intermediate type.
+ if (!Name.empty())
+ addString(Buffer, dwarf::DW_AT_name, Name);
+
+ // An unspecified type only has a name attribute.
+ if (BTy->getTag() == dwarf::DW_TAG_unspecified_type)
+ return;
+
+ addUInt(Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
+ BTy->getEncoding());
+
+ uint64_t Size = BTy->getSizeInBits() >> 3;
+ addUInt(Buffer, dwarf::DW_AT_byte_size, None, Size);
+}
+
+void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy) {
+ // Get core information.
+ StringRef Name = DTy->getName();
+ uint64_t Size = DTy->getSizeInBits() >> 3;
+ uint16_t Tag = Buffer.getTag();
+
+ // Map to main type, void will not have a type.
+ const DIType *FromTy = resolve(DTy->getBaseType());
+ if (FromTy)
+ addType(Buffer, FromTy);
+
+ // Add name if not anonymous or intermediate type.
+ if (!Name.empty())
+ addString(Buffer, dwarf::DW_AT_name, Name);
+
+ // Add size if non-zero (derived types might be zero-sized.)
+ if (Size && Tag != dwarf::DW_TAG_pointer_type
+ && Tag != dwarf::DW_TAG_ptr_to_member_type
+ && Tag != dwarf::DW_TAG_reference_type
+ && Tag != dwarf::DW_TAG_rvalue_reference_type)
+ addUInt(Buffer, dwarf::DW_AT_byte_size, None, Size);
+
+ if (Tag == dwarf::DW_TAG_ptr_to_member_type)
+ addDIEEntry(
+ Buffer, dwarf::DW_AT_containing_type,
+ *getOrCreateTypeDIE(resolve(cast<DIDerivedType>(DTy)->getClassType())));
+ // Add source line info if available and TyDesc is not a forward declaration.
+ if (!DTy->isForwardDecl())
+ addSourceLine(Buffer, DTy);
+}
+
+void DwarfUnit::constructSubprogramArguments(DIE &Buffer, DITypeRefArray Args) {
+ for (unsigned i = 1, N = Args.size(); i < N; ++i) {
+ const DIType *Ty = resolve(Args[i]);
+ if (!Ty) {
+ assert(i == N-1 && "Unspecified parameter must be the last argument");
+ createAndAddDIE(dwarf::DW_TAG_unspecified_parameters, Buffer);
+ } else {
+ DIE &Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, Buffer);
+ addType(Arg, Ty);
+ if (Ty->isArtificial())
+ addFlag(Arg, dwarf::DW_AT_artificial);
+ }
+ }
+}
+
+void DwarfUnit::constructTypeDIE(DIE &Buffer, const DISubroutineType *CTy) {
+ // Add return type. A void return won't have a type.
+ auto Elements = cast<DISubroutineType>(CTy)->getTypeArray();
+ if (Elements.size())
+ if (auto RTy = resolve(Elements[0]))
+ addType(Buffer, RTy);
+
+ bool isPrototyped = true;
+ if (Elements.size() == 2 && !Elements[1])
+ isPrototyped = false;
+
+ constructSubprogramArguments(Buffer, Elements);
+
+ // Add prototype flag if we're dealing with a C language and the function has
+ // been prototyped.
+ uint16_t Language = getLanguage();
+ if (isPrototyped &&
+ (Language == dwarf::DW_LANG_C89 || Language == dwarf::DW_LANG_C99 ||
+ Language == dwarf::DW_LANG_ObjC))
+ addFlag(Buffer, dwarf::DW_AT_prototyped);
+
+ if (CTy->isLValueReference())
+ addFlag(Buffer, dwarf::DW_AT_reference);
+
+ if (CTy->isRValueReference())
+ addFlag(Buffer, dwarf::DW_AT_rvalue_reference);
+}
+
+void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
+ if (CTy->isExternalTypeRef()) {
+ StringRef Identifier = CTy->getIdentifier();
+ assert(!Identifier.empty() && "external type ref without identifier");
+ addFlag(Buffer, dwarf::DW_AT_declaration);
+ return addDIETypeSignature(Buffer, dwarf::DW_AT_signature, Identifier);
+ }
+
+ // Add name if not anonymous or intermediate type.
+ StringRef Name = CTy->getName();
+
+ uint64_t Size = CTy->getSizeInBits() >> 3;
+ uint16_t Tag = Buffer.getTag();
+
+ switch (Tag) {
+ case dwarf::DW_TAG_array_type:
+ constructArrayTypeDIE(Buffer, CTy);
+ break;
+ case dwarf::DW_TAG_enumeration_type:
+ constructEnumTypeDIE(Buffer, CTy);
+ break;
+ case dwarf::DW_TAG_structure_type:
+ case dwarf::DW_TAG_union_type:
+ case dwarf::DW_TAG_class_type: {
+ // Add elements to structure type.
+ DINodeArray Elements = CTy->getElements();
+ for (const auto *Element : Elements) {
+ if (!Element)
+ continue;
+ if (auto *SP = dyn_cast<DISubprogram>(Element))
+ getOrCreateSubprogramDIE(SP);
+ else if (auto *DDTy = dyn_cast<DIDerivedType>(Element)) {
+ if (DDTy->getTag() == dwarf::DW_TAG_friend) {
+ DIE &ElemDie = createAndAddDIE(dwarf::DW_TAG_friend, Buffer);
+ addType(ElemDie, resolve(DDTy->getBaseType()), dwarf::DW_AT_friend);
+ } else if (DDTy->isStaticMember()) {
+ getOrCreateStaticMemberDIE(DDTy);
+ } else {
+ constructMemberDIE(Buffer, DDTy);
+ }
+ } else if (auto *Property = dyn_cast<DIObjCProperty>(Element)) {
+ DIE &ElemDie = createAndAddDIE(Property->getTag(), Buffer);
+ StringRef PropertyName = Property->getName();
+ addString(ElemDie, dwarf::DW_AT_APPLE_property_name, PropertyName);
+ if (Property->getType())
+ addType(ElemDie, resolve(Property->getType()));
+ addSourceLine(ElemDie, Property);
+ StringRef GetterName = Property->getGetterName();
+ if (!GetterName.empty())
+ addString(ElemDie, dwarf::DW_AT_APPLE_property_getter, GetterName);
+ StringRef SetterName = Property->getSetterName();
+ if (!SetterName.empty())
+ addString(ElemDie, dwarf::DW_AT_APPLE_property_setter, SetterName);
+ if (unsigned PropertyAttributes = Property->getAttributes())
+ addUInt(ElemDie, dwarf::DW_AT_APPLE_property_attribute, None,
+ PropertyAttributes);
+ }
+ }
+
+ if (CTy->isAppleBlockExtension())
+ addFlag(Buffer, dwarf::DW_AT_APPLE_block);
+
+ // This is outside the DWARF spec, but GDB expects a DW_AT_containing_type
+ // inside C++ composite types to point to the base class with the vtable.
+ if (auto *ContainingType =
+ dyn_cast_or_null<DICompositeType>(resolve(CTy->getVTableHolder())))
+ addDIEEntry(Buffer, dwarf::DW_AT_containing_type,
+ *getOrCreateTypeDIE(ContainingType));
+
+ if (CTy->isObjcClassComplete())
+ addFlag(Buffer, dwarf::DW_AT_APPLE_objc_complete_type);
+
+ // Add template parameters to a class, structure or union types.
+ // FIXME: The support isn't in the metadata for this yet.
+ if (Tag == dwarf::DW_TAG_class_type ||
+ Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type)
+ addTemplateParams(Buffer, CTy->getTemplateParams());
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ // Add name if not anonymous or intermediate type.
+ if (!Name.empty())
+ addString(Buffer, dwarf::DW_AT_name, Name);
+
+ if (Tag == dwarf::DW_TAG_enumeration_type ||
+ Tag == dwarf::DW_TAG_class_type || Tag == dwarf::DW_TAG_structure_type ||
+ Tag == dwarf::DW_TAG_union_type) {
+ // Add size if non-zero (derived types might be zero-sized.)
+ // TODO: Do we care about size for enum forward declarations?
+ if (Size)
+ addUInt(Buffer, dwarf::DW_AT_byte_size, None, Size);
+ else if (!CTy->isForwardDecl())
+ // Add zero size if it is not a forward declaration.
+ addUInt(Buffer, dwarf::DW_AT_byte_size, None, 0);
+
+ // If we're a forward decl, say so.
+ if (CTy->isForwardDecl())
+ addFlag(Buffer, dwarf::DW_AT_declaration);
+
+ // Add source line info if available.
+ if (!CTy->isForwardDecl())
+ addSourceLine(Buffer, CTy);
+
+ // No harm in adding the runtime language to the declaration.
+ unsigned RLang = CTy->getRuntimeLang();
+ if (RLang)
+ addUInt(Buffer, dwarf::DW_AT_APPLE_runtime_class, dwarf::DW_FORM_data1,
+ RLang);
+ }
+}
+
+void DwarfUnit::constructTemplateTypeParameterDIE(
+ DIE &Buffer, const DITemplateTypeParameter *TP) {
+ DIE &ParamDIE =
+ createAndAddDIE(dwarf::DW_TAG_template_type_parameter, Buffer);
+ // Add the type if it exists, it could be void and therefore no type.
+ if (TP->getType())
+ addType(ParamDIE, resolve(TP->getType()));
+ if (!TP->getName().empty())
+ addString(ParamDIE, dwarf::DW_AT_name, TP->getName());
+}
+
+void DwarfUnit::constructTemplateValueParameterDIE(
+ DIE &Buffer, const DITemplateValueParameter *VP) {
+ DIE &ParamDIE = createAndAddDIE(VP->getTag(), Buffer);
+
+ // Add the type if there is one, template template and template parameter
+ // packs will not have a type.
+ if (VP->getTag() == dwarf::DW_TAG_template_value_parameter)
+ addType(ParamDIE, resolve(VP->getType()));
+ if (!VP->getName().empty())
+ addString(ParamDIE, dwarf::DW_AT_name, VP->getName());
+ if (Metadata *Val = VP->getValue()) {
+ if (ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(Val))
+ addConstantValue(ParamDIE, CI, resolve(VP->getType()));
+ else if (GlobalValue *GV = mdconst::dyn_extract<GlobalValue>(Val)) {
+ // For declaration non-type template parameters (such as global values and
+ // functions)
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+ addOpAddress(*Loc, Asm->getSymbol(GV));
+ // Emit DW_OP_stack_value to use the address as the immediate value of the
+ // parameter, rather than a pointer to it.
+ addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_stack_value);
+ addBlock(ParamDIE, dwarf::DW_AT_location, Loc);
+ } else if (VP->getTag() == dwarf::DW_TAG_GNU_template_template_param) {
+ assert(isa<MDString>(Val));
+ addString(ParamDIE, dwarf::DW_AT_GNU_template_name,
+ cast<MDString>(Val)->getString());
+ } else if (VP->getTag() == dwarf::DW_TAG_GNU_template_parameter_pack) {
+ addTemplateParams(ParamDIE, cast<MDTuple>(Val));
+ }
+ }
+}
+
+DIE *DwarfUnit::getOrCreateNameSpace(const DINamespace *NS) {
+ // Construct the context before querying for the existence of the DIE in case
+ // such construction creates the DIE.
+ DIE *ContextDIE = getOrCreateContextDIE(NS->getScope());
+
+ if (DIE *NDie = getDIE(NS))
+ return NDie;
+ DIE &NDie = createAndAddDIE(dwarf::DW_TAG_namespace, *ContextDIE, NS);
+
+ StringRef Name = NS->getName();
+ if (!Name.empty())
+ addString(NDie, dwarf::DW_AT_name, NS->getName());
+ else
+ Name = "(anonymous namespace)";
+ DD->addAccelNamespace(Name, NDie);
+ addGlobalName(Name, NDie, NS->getScope());
+ addSourceLine(NDie, NS);
+ return &NDie;
+}
+
+DIE *DwarfUnit::getOrCreateModule(const DIModule *M) {
+ // Construct the context before querying for the existence of the DIE in case
+ // such construction creates the DIE.
+ DIE *ContextDIE = getOrCreateContextDIE(M->getScope());
+
+ if (DIE *MDie = getDIE(M))
+ return MDie;
+ DIE &MDie = createAndAddDIE(dwarf::DW_TAG_module, *ContextDIE, M);
+
+ if (!M->getName().empty()) {
+ addString(MDie, dwarf::DW_AT_name, M->getName());
+ addGlobalName(M->getName(), MDie, M->getScope());
+ }
+ if (!M->getConfigurationMacros().empty())
+ addString(MDie, dwarf::DW_AT_LLVM_config_macros,
+ M->getConfigurationMacros());
+ if (!M->getIncludePath().empty())
+ addString(MDie, dwarf::DW_AT_LLVM_include_path, M->getIncludePath());
+ if (!M->getISysRoot().empty())
+ addString(MDie, dwarf::DW_AT_LLVM_isysroot, M->getISysRoot());
+
+ return &MDie;
+}
+
+DIE *DwarfUnit::getOrCreateSubprogramDIE(const DISubprogram *SP, bool Minimal) {
+ // Construct the context before querying for the existence of the DIE in case
+ // such construction creates the DIE (as is the case for member function
+ // declarations).
+ DIE *ContextDIE =
+ Minimal ? &getUnitDie() : getOrCreateContextDIE(resolve(SP->getScope()));
+
+ if (DIE *SPDie = getDIE(SP))
+ return SPDie;
+
+ if (auto *SPDecl = SP->getDeclaration()) {
+ if (!Minimal) {
+ // Add subprogram definitions to the CU die directly.
+ ContextDIE = &getUnitDie();
+ // Build the decl now to ensure it precedes the definition.
+ getOrCreateSubprogramDIE(SPDecl);
+ }
+ }
+
+ // DW_TAG_inlined_subroutine may refer to this DIE.
+ DIE &SPDie = createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, SP);
+
+ // Stop here and fill this in later, depending on whether or not this
+ // subprogram turns out to have inlined instances or not.
+ if (SP->isDefinition())
+ return &SPDie;
+
+ applySubprogramAttributes(SP, SPDie);
+ return &SPDie;
+}
+
+bool DwarfUnit::applySubprogramDefinitionAttributes(const DISubprogram *SP,
+ DIE &SPDie) {
+ DIE *DeclDie = nullptr;
+ StringRef DeclLinkageName;
+ if (auto *SPDecl = SP->getDeclaration()) {
+ DeclDie = getDIE(SPDecl);
+ assert(DeclDie && "This DIE should've already been constructed when the "
+ "definition DIE was created in "
+ "getOrCreateSubprogramDIE");
+ DeclLinkageName = SPDecl->getLinkageName();
+ unsigned DeclID =
+ getOrCreateSourceID(SPDecl->getFilename(), SPDecl->getDirectory());
+ unsigned DefID = getOrCreateSourceID(SP->getFilename(), SP->getDirectory());
+ if (DeclID != DefID)
+ addUInt(SPDie, dwarf::DW_AT_decl_file, None, DefID);
+
+ if (SP->getLine() != SPDecl->getLine())
+ addUInt(SPDie, dwarf::DW_AT_decl_line, None, SP->getLine());
+ }
+
+ // Add function template parameters.
+ addTemplateParams(SPDie, SP->getTemplateParams());
+
+ // Add the linkage name if we have one and it isn't in the Decl.
+ StringRef LinkageName = SP->getLinkageName();
+ assert(((LinkageName.empty() || DeclLinkageName.empty()) ||
+ LinkageName == DeclLinkageName) &&
+ "decl has a linkage name and it is different");
+ if (DeclLinkageName.empty())
+ addLinkageName(SPDie, LinkageName);
+
+ if (!DeclDie)
+ return false;
+
+ // Refer to the function declaration where all the other attributes will be
+ // found.
+ addDIEEntry(SPDie, dwarf::DW_AT_specification, *DeclDie);
+ return true;
+}
+
+void DwarfUnit::applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie,
+ bool Minimal) {
+ if (!Minimal)
+ if (applySubprogramDefinitionAttributes(SP, SPDie))
+ return;
+
+ // Constructors and operators for anonymous aggregates do not have names.
+ if (!SP->getName().empty())
+ addString(SPDie, dwarf::DW_AT_name, SP->getName());
+
+ // Skip the rest of the attributes under -gmlt to save space.
+ if (Minimal)
+ return;
+
+ addSourceLine(SPDie, SP);
+
+ // Add the prototype if we have a prototype and we have a C like
+ // language.
+ uint16_t Language = getLanguage();
+ if (SP->isPrototyped() &&
+ (Language == dwarf::DW_LANG_C89 || Language == dwarf::DW_LANG_C99 ||
+ Language == dwarf::DW_LANG_ObjC))
+ addFlag(SPDie, dwarf::DW_AT_prototyped);
+
+ DITypeRefArray Args;
+ if (const DISubroutineType *SPTy = SP->getType())
+ Args = SPTy->getTypeArray();
+
+ // Add a return type. If this is a type like a C/C++ void type we don't add a
+ // return type.
+ if (Args.size())
+ if (auto Ty = resolve(Args[0]))
+ addType(SPDie, Ty);
+
+ unsigned VK = SP->getVirtuality();
+ if (VK) {
+ addUInt(SPDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_data1, VK);
+ DIELoc *Block = getDIELoc();
+ addUInt(*Block, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
+ addUInt(*Block, dwarf::DW_FORM_udata, SP->getVirtualIndex());
+ addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, Block);
+ ContainingTypeMap.insert(
+ std::make_pair(&SPDie, resolve(SP->getContainingType())));
+ }
+
+ if (!SP->isDefinition()) {
+ addFlag(SPDie, dwarf::DW_AT_declaration);
+
+ // Add arguments. Do not add arguments for subprogram definition. They will
+ // be handled while processing variables.
+ constructSubprogramArguments(SPDie, Args);
+ }
+
+ if (SP->isArtificial())
+ addFlag(SPDie, dwarf::DW_AT_artificial);
+
+ if (!SP->isLocalToUnit())
+ addFlag(SPDie, dwarf::DW_AT_external);
+
+ if (SP->isOptimized())
+ addFlag(SPDie, dwarf::DW_AT_APPLE_optimized);
+
+ if (unsigned isa = Asm->getISAEncoding())
+ addUInt(SPDie, dwarf::DW_AT_APPLE_isa, dwarf::DW_FORM_flag, isa);
+
+ if (SP->isLValueReference())
+ addFlag(SPDie, dwarf::DW_AT_reference);
+
+ if (SP->isRValueReference())
+ addFlag(SPDie, dwarf::DW_AT_rvalue_reference);
+
+ if (SP->isProtected())
+ addUInt(SPDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
+ dwarf::DW_ACCESS_protected);
+ else if (SP->isPrivate())
+ addUInt(SPDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
+ dwarf::DW_ACCESS_private);
+ else if (SP->isPublic())
+ addUInt(SPDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
+ dwarf::DW_ACCESS_public);
+
+ if (SP->isExplicit())
+ addFlag(SPDie, dwarf::DW_AT_explicit);
+}
+
+void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR,
+ DIE *IndexTy) {
+ DIE &DW_Subrange = createAndAddDIE(dwarf::DW_TAG_subrange_type, Buffer);
+ addDIEEntry(DW_Subrange, dwarf::DW_AT_type, *IndexTy);
+
+ // The LowerBound value defines the lower bounds which is typically zero for
+ // C/C++. The Count value is the number of elements. Values are 64 bit. If
+ // Count == -1 then the array is unbounded and we do not emit
+ // DW_AT_lower_bound and DW_AT_count attributes.
+ int64_t LowerBound = SR->getLowerBound();
+ int64_t DefaultLowerBound = getDefaultLowerBound();
+ int64_t Count = SR->getCount();
+
+ if (DefaultLowerBound == -1 || LowerBound != DefaultLowerBound)
+ addUInt(DW_Subrange, dwarf::DW_AT_lower_bound, None, LowerBound);
+
+ if (Count != -1)
+ // FIXME: An unbounded array should reference the expression that defines
+ // the array.
+ addUInt(DW_Subrange, dwarf::DW_AT_count, None, Count);
+}
+
+DIE *DwarfUnit::getIndexTyDie() {
+ if (IndexTyDie)
+ return IndexTyDie;
+ // Construct an integer type to use for indexes.
+ IndexTyDie = &createAndAddDIE(dwarf::DW_TAG_base_type, UnitDie);
+ addString(*IndexTyDie, dwarf::DW_AT_name, "sizetype");
+ 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);
+ return IndexTyDie;
+}
+
+void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
+ if (CTy->isVector())
+ addFlag(Buffer, dwarf::DW_AT_GNU_vector);
+
+ // Emit the element type.
+ addType(Buffer, resolve(CTy->getBaseType()));
+
+ // Get an anonymous type for index type.
+ // FIXME: This type should be passed down from the front end
+ // as different languages may have different sizes for indexes.
+ DIE *IdxTy = getIndexTyDie();
+
+ // Add subranges to array type.
+ DINodeArray Elements = CTy->getElements();
+ for (unsigned i = 0, N = Elements.size(); i < N; ++i) {
+ // FIXME: Should this really be such a loose cast?
+ if (auto *Element = dyn_cast_or_null<DINode>(Elements[i]))
+ if (Element->getTag() == dwarf::DW_TAG_subrange_type)
+ constructSubrangeDIE(Buffer, cast<DISubrange>(Element), IdxTy);
+ }
+}
+
+void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
+ DINodeArray Elements = CTy->getElements();
+
+ // Add enumerators to enumeration type.
+ for (unsigned i = 0, N = Elements.size(); i < N; ++i) {
+ auto *Enum = dyn_cast_or_null<DIEnumerator>(Elements[i]);
+ if (Enum) {
+ DIE &Enumerator = createAndAddDIE(dwarf::DW_TAG_enumerator, Buffer);
+ StringRef Name = Enum->getName();
+ addString(Enumerator, dwarf::DW_AT_name, Name);
+ int64_t Value = Enum->getValue();
+ addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata,
+ Value);
+ }
+ }
+ const DIType *DTy = resolve(CTy->getBaseType());
+ if (DTy) {
+ addType(Buffer, DTy);
+ addFlag(Buffer, dwarf::DW_AT_enum_class);
+ }
+}
+
+void DwarfUnit::constructContainingTypeDIEs() {
+ for (auto CI = ContainingTypeMap.begin(), CE = ContainingTypeMap.end();
+ CI != CE; ++CI) {
+ DIE &SPDie = *CI->first;
+ const DINode *D = CI->second;
+ if (!D)
+ continue;
+ DIE *NDie = getDIE(D);
+ if (!NDie)
+ continue;
+ addDIEEntry(SPDie, dwarf::DW_AT_containing_type, *NDie);
+ }
+}
+
+void DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
+ DIE &MemberDie = createAndAddDIE(DT->getTag(), Buffer);
+ StringRef Name = DT->getName();
+ if (!Name.empty())
+ addString(MemberDie, dwarf::DW_AT_name, Name);
+
+ addType(MemberDie, resolve(DT->getBaseType()));
+
+ addSourceLine(MemberDie, DT);
+
+ if (DT->getTag() == dwarf::DW_TAG_inheritance && DT->isVirtual()) {
+
+ // For C++, virtual base classes are not at fixed offset. Use following
+ // expression to extract appropriate offset from vtable.
+ // BaseAddr = ObAddr + *((*ObAddr) - Offset)
+
+ DIELoc *VBaseLocationDie = new (DIEValueAllocator) DIELoc;
+ addUInt(*VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_dup);
+ addUInt(*VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
+ addUInt(*VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
+ addUInt(*VBaseLocationDie, dwarf::DW_FORM_udata, DT->getOffsetInBits());
+ addUInt(*VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_minus);
+ addUInt(*VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
+ addUInt(*VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus);
+
+ addBlock(MemberDie, dwarf::DW_AT_data_member_location, VBaseLocationDie);
+ } else {
+ uint64_t Size = DT->getSizeInBits();
+ uint64_t FieldSize = getBaseTypeSize(DD, DT);
+ uint64_t OffsetInBytes;
+
+ if (FieldSize && Size != FieldSize) {
+ // Handle bitfield, assume bytes are 8 bits.
+ addUInt(MemberDie, dwarf::DW_AT_byte_size, None, FieldSize/8);
+ addUInt(MemberDie, dwarf::DW_AT_bit_size, None, Size);
+ //
+ // The DWARF 2 DW_AT_bit_offset is counting the bits between the most
+ // significant bit of the aligned storage unit containing the bit field to
+ // the most significan bit of the bit field.
+ //
+ // FIXME: DWARF 4 states that DW_AT_data_bit_offset (which
+ // counts from the beginning, regardless of endianness) should
+ // be used instead.
+ //
+ //
+ // Struct Align Align Align
+ // v v v v
+ // +-----------+-----*-----+-----*-----+--
+ // | ... |b1|b2|b3|b4|
+ // +-----------+-----*-----+-----*-----+--
+ // | | |<-- Size ->| |
+ // |<---- Offset --->| |<--->|
+ // | | | \_ DW_AT_bit_offset (little endian)
+ // | |<--->|
+ // |<--------->| \_ StartBitOffset = DW_AT_bit_offset (big endian)
+ // \ = DW_AT_data_bit_offset (biendian)
+ // \_ OffsetInBytes
+ uint64_t Offset = DT->getOffsetInBits();
+ uint64_t Align = DT->getAlignInBits() ? DT->getAlignInBits() : FieldSize;
+ uint64_t AlignMask = ~(Align - 1);
+ // The bits from the start of the storage unit to the start of the field.
+ uint64_t StartBitOffset = Offset - (Offset & AlignMask);
+ // The endian-dependent DWARF 2 offset.
+ uint64_t DwarfBitOffset = Asm->getDataLayout().isLittleEndian()
+ ? OffsetToAlignment(Offset + Size, Align)
+ : StartBitOffset;
+
+ // The byte offset of the field's aligned storage unit inside the struct.
+ OffsetInBytes = (Offset - StartBitOffset) / 8;
+ addUInt(MemberDie, dwarf::DW_AT_bit_offset, None, DwarfBitOffset);
+ } else
+ // This is not a bitfield.
+ OffsetInBytes = DT->getOffsetInBits() / 8;
+
+ if (DD->getDwarfVersion() <= 2) {
+ DIELoc *MemLocationDie = new (DIEValueAllocator) DIELoc;
+ addUInt(*MemLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
+ addUInt(*MemLocationDie, dwarf::DW_FORM_udata, OffsetInBytes);
+ addBlock(MemberDie, dwarf::DW_AT_data_member_location, MemLocationDie);
+ } else
+ addUInt(MemberDie, dwarf::DW_AT_data_member_location, None,
+ OffsetInBytes);
+ }
+
+ if (DT->isProtected())
+ addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
+ dwarf::DW_ACCESS_protected);
+ else if (DT->isPrivate())
+ addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
+ dwarf::DW_ACCESS_private);
+ // Otherwise C++ member and base classes are considered public.
+ else if (DT->isPublic())
+ addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
+ dwarf::DW_ACCESS_public);
+ if (DT->isVirtual())
+ addUInt(MemberDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_data1,
+ dwarf::DW_VIRTUALITY_virtual);
+
+ // Objective-C properties.
+ if (DINode *PNode = DT->getObjCProperty())
+ if (DIE *PDie = getDIE(PNode))
+ MemberDie.addValue(DIEValueAllocator, dwarf::DW_AT_APPLE_property,
+ dwarf::DW_FORM_ref4, DIEEntry(*PDie));
+
+ if (DT->isArtificial())
+ addFlag(MemberDie, dwarf::DW_AT_artificial);
+}
+
+DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT) {
+ if (!DT)
+ return nullptr;
+
+ // Construct the context before querying for the existence of the DIE in case
+ // such construction creates the DIE.
+ DIE *ContextDIE = getOrCreateContextDIE(resolve(DT->getScope()));
+ assert(dwarf::isType(ContextDIE->getTag()) &&
+ "Static member should belong to a type.");
+
+ if (DIE *StaticMemberDIE = getDIE(DT))
+ return StaticMemberDIE;
+
+ DIE &StaticMemberDIE = createAndAddDIE(DT->getTag(), *ContextDIE, DT);
+
+ const DIType *Ty = resolve(DT->getBaseType());
+
+ addString(StaticMemberDIE, dwarf::DW_AT_name, DT->getName());
+ addType(StaticMemberDIE, Ty);
+ addSourceLine(StaticMemberDIE, DT);
+ addFlag(StaticMemberDIE, dwarf::DW_AT_external);
+ addFlag(StaticMemberDIE, dwarf::DW_AT_declaration);
+
+ // FIXME: We could omit private if the parent is a class_type, and
+ // public if the parent is something else.
+ if (DT->isProtected())
+ addUInt(StaticMemberDIE, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
+ dwarf::DW_ACCESS_protected);
+ else if (DT->isPrivate())
+ addUInt(StaticMemberDIE, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
+ dwarf::DW_ACCESS_private);
+ else if (DT->isPublic())
+ addUInt(StaticMemberDIE, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
+ dwarf::DW_ACCESS_public);
+
+ if (const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(DT->getConstant()))
+ addConstantValue(StaticMemberDIE, CI, Ty);
+ if (const ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(DT->getConstant()))
+ addConstantFPValue(StaticMemberDIE, CFP);
+
+ return &StaticMemberDIE;
+}
+
+void DwarfUnit::emitHeader(bool UseOffsets) {
+ // Emit size of content not including length itself
+ Asm->OutStreamer->AddComment("Length of Unit");
+ Asm->EmitInt32(getHeaderSize() + UnitDie.getSize());
+
+ Asm->OutStreamer->AddComment("DWARF version number");
+ Asm->EmitInt16(DD->getDwarfVersion());
+ Asm->OutStreamer->AddComment("Offset Into Abbrev. Section");
+
+ // We share one abbreviations table across all units so it's always at the
+ // start of the section. Use a relocatable offset where needed to ensure
+ // linking doesn't invalidate that offset.
+ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
+ Asm->emitDwarfSymbolReference(TLOF.getDwarfAbbrevSection()->getBeginSymbol(),
+ UseOffsets);
+
+ Asm->OutStreamer->AddComment("Address Size (in bytes)");
+ Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
+}
+
+void DwarfUnit::initSection(MCSection *Section) {
+ assert(!this->Section);
+ this->Section = Section;
+}
+
+void DwarfTypeUnit::emitHeader(bool UseOffsets) {
+ DwarfUnit::emitHeader(UseOffsets);
+ Asm->OutStreamer->AddComment("Type Signature");
+ Asm->OutStreamer->EmitIntValue(TypeSignature, sizeof(TypeSignature));
+ Asm->OutStreamer->AddComment("Type DIE Offset");
+ // In a skeleton type unit there is no type DIE so emit a zero offset.
+ Asm->OutStreamer->EmitIntValue(Ty ? Ty->getOffset() : 0,
+ sizeof(Ty->getOffset()));
+}
+
+bool DwarfTypeUnit::isDwoUnit() const {
+ // Since there are no skeleton type units, all type units are dwo type units
+ // when split DWARF is being used.
+ return DD->useSplitDwarf();
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
new file mode 100644
index 0000000..82760bf
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
@@ -0,0 +1,403 @@
+//===-- llvm/CodeGen/DwarfUnit.h - Dwarf Compile Unit ---*- 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 dwarf compile unit.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFUNIT_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFUNIT_H
+
+#include "DwarfDebug.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/DIE.h"
+#include "llvm/IR/DIBuilder.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/MC/MCDwarf.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCSection.h"
+
+namespace llvm {
+
+class MachineLocation;
+class MachineOperand;
+class ConstantInt;
+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.
+class DwarfUnit {
+protected:
+ /// A numeric ID unique among all CUs in the module
+ unsigned UniqueID;
+
+ /// MDNode for the compile unit.
+ const DICompileUnit *CUNode;
+
+ // All DIEValues are allocated through this allocator.
+ BumpPtrAllocator DIEValueAllocator;
+
+ /// Unit debug information entry.
+ DIE &UnitDie;
+
+ /// Offset of the UnitDie from beginning of debug info section.
+ unsigned DebugInfoOffset;
+
+ /// Target of Dwarf emission.
+ AsmPrinter *Asm;
+
+ // Holders for some common dwarf information.
+ DwarfDebug *DD;
+ DwarfFile *DU;
+
+ /// An anonymous type for index type. Owned by UnitDie.
+ DIE *IndexTyDie;
+
+ /// Tracks the mapping of unit level debug information variables to debug
+ /// information entries.
+ DenseMap<const MDNode *, DIE *> MDNodeToDieMap;
+
+ /// A list of all the DIEBlocks in use.
+ std::vector<DIEBlock *> DIEBlocks;
+
+ /// A list of all the DIELocs in use.
+ std::vector<DIELoc *> DIELocs;
+
+ /// This map is used to keep track of subprogram DIEs that need
+ /// DW_AT_containing_type attribute. This attribute points to a DIE that
+ /// corresponds to the MDNode mapped with the subprogram DIE.
+ DenseMap<DIE *, const DINode *> ContainingTypeMap;
+
+ /// The section this unit will be emitted in.
+ MCSection *Section;
+
+ DwarfUnit(unsigned UID, dwarf::Tag, const DICompileUnit *CU, AsmPrinter *A,
+ DwarfDebug *DW, DwarfFile *DWU);
+
+ bool applySubprogramDefinitionAttributes(const DISubprogram *SP, DIE &SPDie);
+
+public:
+ virtual ~DwarfUnit();
+
+ void initSection(MCSection *Section);
+
+ MCSection *getSection() const {
+ assert(Section);
+ return Section;
+ }
+
+ // Accessors.
+ AsmPrinter* getAsmPrinter() const { return Asm; }
+ unsigned getUniqueID() const { return UniqueID; }
+ uint16_t getLanguage() const { return CUNode->getSourceLanguage(); }
+ const DICompileUnit *getCUNode() const { return CUNode; }
+ DIE &getUnitDie() { return UnitDie; }
+
+ unsigned getDebugInfoOffset() const { return DebugInfoOffset; }
+ void setDebugInfoOffset(unsigned DbgInfoOff) { DebugInfoOffset = DbgInfoOff; }
+
+ /// Return true if this compile unit has something to write out.
+ bool hasContent() const { return UnitDie.hasChildren(); }
+
+ /// Get string containing language specific context for a global name.
+ ///
+ /// Walks the metadata parent chain in a language specific manner (using the
+ /// compile unit language) and returns it as a string. This is done at the
+ /// metadata level because DIEs may not currently have been added to the
+ /// parent context and walking the DIEs looking for names is more expensive
+ /// than walking the metadata.
+ std::string getParentContextString(const DIScope *Context) const;
+
+ /// Add a new global name to the compile unit.
+ virtual void addGlobalName(StringRef Name, DIE &Die, const DIScope *Context) {
+ }
+
+ /// Add a new global type to the compile unit.
+ virtual void addGlobalType(const DIType *Ty, const DIE &Die,
+ const DIScope *Context) {}
+
+ /// Returns the DIE map slot for the specified debug variable.
+ ///
+ /// We delegate the request to DwarfDebug when the MDNode can be part of the
+ /// type system, since DIEs for the type system can be shared across CUs and
+ /// the mappings are kept in DwarfDebug.
+ DIE *getDIE(const DINode *D) const;
+
+ /// Returns a fresh newly allocated DIELoc.
+ DIELoc *getDIELoc() { return new (DIEValueAllocator) DIELoc; }
+
+ /// Insert DIE into the map.
+ ///
+ /// We delegate the request to DwarfDebug when the MDNode can be part of the
+ /// type system, since DIEs for the type system can be shared across CUs and
+ /// the mappings are kept in DwarfDebug.
+ void insertDIE(const DINode *Desc, DIE *D);
+
+ /// Add a flag that is true to the DIE.
+ void addFlag(DIE &Die, dwarf::Attribute Attribute);
+
+ /// Add an unsigned integer attribute data and value.
+ void addUInt(DIEValueList &Die, dwarf::Attribute Attribute,
+ Optional<dwarf::Form> Form, uint64_t Integer);
+
+ void addUInt(DIEValueList &Block, dwarf::Form Form, uint64_t Integer);
+
+ /// Add an signed integer attribute data and value.
+ void addSInt(DIEValueList &Die, dwarf::Attribute Attribute,
+ Optional<dwarf::Form> Form, int64_t Integer);
+
+ void addSInt(DIELoc &Die, Optional<dwarf::Form> Form, int64_t Integer);
+
+ /// Add a string attribute data and value.
+ ///
+ /// We always emit a reference to the string pool instead of immediate
+ /// strings so that DIEs have more predictable sizes. In the case of split
+ /// dwarf we emit an index into another table which gets us the static offset
+ /// into the string table.
+ void addString(DIE &Die, dwarf::Attribute Attribute, StringRef Str);
+
+ /// Add a Dwarf label attribute data and value.
+ DIEValueList::value_iterator addLabel(DIEValueList &Die,
+ dwarf::Attribute Attribute,
+ dwarf::Form Form,
+ const MCSymbol *Label);
+
+ void addLabel(DIELoc &Die, dwarf::Form Form, const MCSymbol *Label);
+
+ /// Add an offset into a section attribute data and value.
+ void addSectionOffset(DIE &Die, dwarf::Attribute Attribute, uint64_t Integer);
+
+ /// Add a dwarf op address data and value using the form given and an
+ /// op of either DW_FORM_addr or DW_FORM_GNU_addr_index.
+ void addOpAddress(DIELoc &Die, const MCSymbol *Label);
+
+ /// Add a label delta attribute data and value.
+ void addLabelDelta(DIE &Die, dwarf::Attribute Attribute, const MCSymbol *Hi,
+ const MCSymbol *Lo);
+
+ /// Add a DIE attribute data and value.
+ void addDIEEntry(DIE &Die, dwarf::Attribute Attribute, DIE &Entry);
+
+ /// Add a DIE attribute data and value.
+ void addDIEEntry(DIE &Die, dwarf::Attribute Attribute, DIEEntry Entry);
+
+ /// Add a type's DW_AT_signature and set the declaration flag.
+ void addDIETypeSignature(DIE &Die, const DwarfTypeUnit &Type);
+ /// Add an attribute containing the type signature for a unique identifier.
+ void addDIETypeSignature(DIE &Die, dwarf::Attribute Attribute,
+ StringRef Identifier);
+
+ /// Add block data.
+ void addBlock(DIE &Die, dwarf::Attribute Attribute, DIELoc *Block);
+
+ /// Add block data.
+ void addBlock(DIE &Die, dwarf::Attribute Attribute, DIEBlock *Block);
+
+ /// Add location information to specified debug information entry.
+ void addSourceLine(DIE &Die, unsigned Line, StringRef File,
+ StringRef Directory);
+ 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 DIType *Ty);
+ void addSourceLine(DIE &Die, const DINamespace *NS);
+ void addSourceLine(DIE &Die, const DIObjCProperty *Ty);
+
+ /// Add constant value entry in variable DIE.
+ void addConstantValue(DIE &Die, const MachineOperand &MO, const DIType *Ty);
+ void addConstantValue(DIE &Die, const ConstantInt *CI, const DIType *Ty);
+ void addConstantValue(DIE &Die, const APInt &Val, const DIType *Ty);
+ void addConstantValue(DIE &Die, const APInt &Val, bool Unsigned);
+ void addConstantValue(DIE &Die, bool Unsigned, uint64_t Val);
+
+ /// Add constant value entry in variable DIE.
+ void addConstantFPValue(DIE &Die, const MachineOperand &MO);
+ void addConstantFPValue(DIE &Die, const ConstantFP *CFP);
+
+ /// Add a linkage name, if it isn't empty.
+ void addLinkageName(DIE &Die, StringRef LinkageName);
+
+ /// Add template parameters in buffer.
+ void addTemplateParams(DIE &Buffer, DINodeArray TParams);
+
+ /// Add register operand.
+ /// \returns false if the register does not exist, e.g., because it was never
+ /// materialized.
+ bool addRegisterOpPiece(DIELoc &TheDie, unsigned Reg,
+ unsigned SizeInBits = 0, unsigned OffsetInBits = 0);
+
+ /// Add register offset.
+ /// \returns false if the register does not exist, e.g., because it was never
+ /// materialized.
+ bool addRegisterOffset(DIELoc &TheDie, unsigned Reg, int64_t Offset);
+
+ // FIXME: Should be reformulated in terms of addComplexAddress.
+ /// Start with the address based on the location provided, and generate the
+ /// DWARF information necessary to find the actual Block variable (navigating
+ /// the Block struct) based on the starting location. Add the DWARF
+ /// information to the die. Obsolete, please use addComplexAddress instead.
+ void addBlockByrefAddress(const DbgVariable &DV, DIE &Die,
+ dwarf::Attribute Attribute,
+ const MachineLocation &Location);
+
+ /// Add a new type attribute to the specified entity.
+ ///
+ /// This takes and attribute parameter because DW_AT_friend attributes are
+ /// also type references.
+ void addType(DIE &Entity, const DIType *Ty,
+ dwarf::Attribute Attribute = dwarf::DW_AT_type);
+
+ DIE *getOrCreateNameSpace(const DINamespace *NS);
+ DIE *getOrCreateModule(const DIModule *M);
+ DIE *getOrCreateSubprogramDIE(const DISubprogram *SP, bool Minimal = false);
+
+ void applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie,
+ bool Minimal = false);
+
+ /// Find existing DIE or create new DIE for the given type.
+ DIE *getOrCreateTypeDIE(const MDNode *N);
+
+ /// Get context owner's DIE.
+ DIE *createTypeDIE(const DICompositeType *Ty);
+
+ /// Get context owner's DIE.
+ DIE *getOrCreateContextDIE(const DIScope *Context);
+
+ /// Construct DIEs for types that contain vtables.
+ void constructContainingTypeDIEs();
+
+ /// Construct function argument DIEs.
+ void constructSubprogramArguments(DIE &Buffer, DITypeRefArray Args);
+
+ /// Create a DIE with the given Tag, add the DIE to its parent, and
+ /// call insertDIE if MD is not null.
+ DIE &createAndAddDIE(unsigned Tag, DIE &Parent, const DINode *N = nullptr);
+
+ /// Compute the size of a header for this unit, not including the initial
+ /// length field.
+ virtual unsigned getHeaderSize() const {
+ return sizeof(int16_t) + // DWARF version number
+ sizeof(int32_t) + // Offset Into Abbrev. Section
+ sizeof(int8_t); // Pointer Size (in bytes)
+ }
+
+ /// Emit the header for this unit, not including the initial length field.
+ virtual void emitHeader(bool UseOffsets);
+
+ virtual DwarfCompileUnit &getCU() = 0;
+
+ void constructTypeDIE(DIE &Buffer, const DICompositeType *CTy);
+
+protected:
+ /// Create new static data member DIE.
+ DIE *getOrCreateStaticMemberDIE(const DIDerivedType *DT);
+
+ /// Look up the source ID with the given directory and source file names. If
+ /// none currently exists, create a new ID and insert it in the line table.
+ virtual unsigned getOrCreateSourceID(StringRef File, StringRef Directory) = 0;
+
+ /// Look in the DwarfDebug map for the MDNode that corresponds to the
+ /// reference.
+ template <typename T> T *resolve(TypedDINodeRef<T> Ref) const {
+ return DD->resolve(Ref);
+ }
+
+private:
+ void constructTypeDIE(DIE &Buffer, const DIBasicType *BTy);
+ void constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy);
+ void constructTypeDIE(DIE &Buffer, const DISubroutineType *DTy);
+ void constructSubrangeDIE(DIE &Buffer, const DISubrange *SR, DIE *IndexTy);
+ void constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy);
+ void constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy);
+ void constructMemberDIE(DIE &Buffer, const DIDerivedType *DT);
+ void constructTemplateTypeParameterDIE(DIE &Buffer,
+ const DITemplateTypeParameter *TP);
+ void constructTemplateValueParameterDIE(DIE &Buffer,
+ const DITemplateValueParameter *TVP);
+
+ /// Return the default lower bound for an array.
+ ///
+ /// If the DWARF version doesn't handle the language, return -1.
+ int64_t getDefaultLowerBound() const;
+
+ /// Get an anonymous type for index type.
+ DIE *getIndexTyDie();
+
+ /// Set D as anonymous type for index which can be reused later.
+ void setIndexTyDie(DIE *D) { IndexTyDie = D; }
+
+ /// If this is a named finished type then include it in the list of types for
+ /// the accelerator tables.
+ void updateAcceleratorTables(const DIScope *Context, const DIType *Ty,
+ const DIE &TyDIE);
+
+ virtual bool isDwoUnit() const = 0;
+};
+
+class DwarfTypeUnit : public DwarfUnit {
+ uint64_t TypeSignature;
+ const DIE *Ty;
+ DwarfCompileUnit &CU;
+ MCDwarfDwoLineTable *SplitLineTable;
+
+ unsigned getOrCreateSourceID(StringRef File, StringRef Directory) override;
+ bool isDwoUnit() const override;
+
+public:
+ DwarfTypeUnit(unsigned UID, DwarfCompileUnit &CU, AsmPrinter *A,
+ DwarfDebug *DW, DwarfFile *DWU,
+ MCDwarfDwoLineTable *SplitLineTable = nullptr);
+
+ void setTypeSignature(uint64_t Signature) { TypeSignature = Signature; }
+ uint64_t getTypeSignature() const { return TypeSignature; }
+ void setType(const DIE *Ty) { this->Ty = Ty; }
+
+ /// Emit the header for this unit, not including the initial length field.
+ void emitHeader(bool UseOffsets) override;
+ unsigned getHeaderSize() const override {
+ return DwarfUnit::getHeaderSize() + sizeof(uint64_t) + // Type Signature
+ sizeof(uint32_t); // Type DIE Offset
+ }
+ DwarfCompileUnit &getCU() override { return CU; }
+};
+} // end llvm namespace
+#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp
new file mode 100644
index 0000000..e24dcb1
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp
@@ -0,0 +1,689 @@
+//===-- CodeGen/AsmPrinter/EHStreamer.cpp - Exception Directive Streamer --===//
+//
+// 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 exception info into assembly files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EHStreamer.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/IR/Function.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/LEB128.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+
+using namespace llvm;
+
+EHStreamer::EHStreamer(AsmPrinter *A) : Asm(A), MMI(Asm->MMI) {}
+
+EHStreamer::~EHStreamer() {}
+
+/// How many leading type ids two landing pads have in common.
+unsigned EHStreamer::sharedTypeIDs(const LandingPadInfo *L,
+ const LandingPadInfo *R) {
+ const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds;
+ unsigned LSize = LIds.size(), RSize = RIds.size();
+ unsigned MinSize = LSize < RSize ? LSize : RSize;
+ unsigned Count = 0;
+
+ for (; Count != MinSize; ++Count)
+ if (LIds[Count] != RIds[Count])
+ return Count;
+
+ return Count;
+}
+
+/// Compute the actions table and gather the first action index for each landing
+/// pad site.
+unsigned EHStreamer::
+computeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads,
+ SmallVectorImpl<ActionEntry> &Actions,
+ SmallVectorImpl<unsigned> &FirstActions) {
+
+ // The action table follows the call-site table in the LSDA. The individual
+ // records are of two types:
+ //
+ // * Catch clause
+ // * Exception specification
+ //
+ // The two record kinds have the same format, with only small differences.
+ // They are distinguished by the "switch value" field: Catch clauses
+ // (TypeInfos) have strictly positive switch values, and exception
+ // specifications (FilterIds) have strictly negative switch values. Value 0
+ // indicates a catch-all clause.
+ //
+ // Negative type IDs index into FilterIds. Positive type IDs index into
+ // TypeInfos. The value written for a positive type ID is just the type ID
+ // itself. For a negative type ID, however, the value written is the
+ // (negative) byte offset of the corresponding FilterIds entry. The byte
+ // offset is usually equal to the type ID (because the FilterIds entries are
+ // written using a variable width encoding, which outputs one byte per entry
+ // as long as the value written is not too large) but can differ. This kind
+ // of complication does not occur for positive type IDs because type infos are
+ // output using a fixed width encoding. FilterOffsets[i] holds the byte
+ // offset corresponding to FilterIds[i].
+
+ const std::vector<unsigned> &FilterIds = MMI->getFilterIds();
+ SmallVector<int, 16> FilterOffsets;
+ FilterOffsets.reserve(FilterIds.size());
+ int Offset = -1;
+
+ for (std::vector<unsigned>::const_iterator
+ I = FilterIds.begin(), E = FilterIds.end(); I != E; ++I) {
+ FilterOffsets.push_back(Offset);
+ Offset -= getULEB128Size(*I);
+ }
+
+ FirstActions.reserve(LandingPads.size());
+
+ int FirstAction = 0;
+ unsigned SizeActions = 0;
+ const LandingPadInfo *PrevLPI = nullptr;
+
+ for (SmallVectorImpl<const LandingPadInfo *>::const_iterator
+ I = LandingPads.begin(), E = LandingPads.end(); I != E; ++I) {
+ const LandingPadInfo *LPI = *I;
+ const std::vector<int> &TypeIds = LPI->TypeIds;
+ unsigned NumShared = PrevLPI ? sharedTypeIDs(LPI, PrevLPI) : 0;
+ unsigned SizeSiteActions = 0;
+
+ if (NumShared < TypeIds.size()) {
+ unsigned SizeAction = 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);
+
+ for (unsigned j = NumShared; j != SizePrevIds; ++j) {
+ assert(PrevAction != (unsigned)-1 && "PrevAction is invalid!");
+ SizeAction -= getSLEB128Size(Actions[PrevAction].ValueForTypeID);
+ SizeAction += -Actions[PrevAction].NextAction;
+ PrevAction = Actions[PrevAction].Previous;
+ }
+ }
+
+ // Compute the actions.
+ for (unsigned J = NumShared, M = TypeIds.size(); J != M; ++J) {
+ int TypeID = TypeIds[J];
+ assert(-1 - TypeID < (int)FilterOffsets.size() && "Unknown filter id!");
+ int ValueForTypeID =
+ isFilterEHSelector(TypeID) ? FilterOffsets[-1 - TypeID] : TypeID;
+ unsigned SizeTypeID = getSLEB128Size(ValueForTypeID);
+
+ int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0;
+ SizeAction = SizeTypeID + getSLEB128Size(NextAction);
+ SizeSiteActions += SizeAction;
+
+ ActionEntry Action = { ValueForTypeID, NextAction, PrevAction };
+ Actions.push_back(Action);
+ PrevAction = Actions.size() - 1;
+ }
+
+ // Record the first action of the landing pad site.
+ FirstAction = SizeActions + SizeSiteActions - SizeAction + 1;
+ } // else identical - re-use previous FirstAction
+
+ // Information used when created the call-site table. The action record
+ // field of the call site record is the offset of the first associated
+ // action record, relative to the start of the actions table. This value is
+ // biased by 1 (1 indicating the start of the actions table), and 0
+ // indicates that there are no actions.
+ FirstActions.push_back(FirstAction);
+
+ // Compute this sites contribution to size.
+ SizeActions += SizeSiteActions;
+
+ PrevLPI = LPI;
+ }
+
+ return SizeActions;
+}
+
+/// Return `true' if this is a call to a function marked `nounwind'. Return
+/// `false' otherwise.
+bool EHStreamer::callToNoUnwindFunction(const MachineInstr *MI) {
+ assert(MI->isCall() && "This should be a call instruction!");
+
+ bool MarkedNoUnwind = false;
+ bool SawFunc = false;
+
+ for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
+ const MachineOperand &MO = MI->getOperand(I);
+
+ if (!MO.isGlobal()) continue;
+
+ const Function *F = dyn_cast<Function>(MO.getGlobal());
+ if (!F) continue;
+
+ if (SawFunc) {
+ // Be conservative. If we have more than one function operand for this
+ // call, then we can't make the assumption that it's the callee and
+ // not a parameter to the call.
+ //
+ // FIXME: Determine if there's a way to say that `F' is the callee or
+ // parameter.
+ MarkedNoUnwind = false;
+ break;
+ }
+
+ MarkedNoUnwind = F->doesNotThrow();
+ SawFunc = true;
+ }
+
+ return MarkedNoUnwind;
+}
+
+void EHStreamer::computePadMap(
+ const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
+ RangeMapType &PadMap) {
+ // Invokes and nounwind calls have entries in PadMap (due to being bracketed
+ // by try-range labels when lowered). Ordinary calls do not, so appropriate
+ // try-ranges for them need be deduced so we can put them in the LSDA.
+ for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
+ const LandingPadInfo *LandingPad = LandingPads[i];
+ for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) {
+ MCSymbol *BeginLabel = LandingPad->BeginLabels[j];
+ assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!");
+ PadRange P = { i, j };
+ PadMap[BeginLabel] = P;
+ }
+ }
+}
+
+/// Compute the call-site table. The entry for an invoke has a try-range
+/// containing the call, a non-zero landing pad, and an appropriate action. The
+/// entry for an ordinary call has a try-range containing the call and 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 EHStreamer::
+computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
+ const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
+ const SmallVectorImpl<unsigned> &FirstActions) {
+ RangeMapType PadMap;
+ computePadMap(LandingPads, PadMap);
+
+ // The end label of the previous invoke or nounwind try-range.
+ MCSymbol *LastLabel = nullptr;
+
+ // Whether there is a potentially throwing instruction (currently this means
+ // an ordinary call) between the end of the previous try-range and now.
+ bool SawPotentiallyThrowing = false;
+
+ // Whether the last CallSite entry was for an invoke.
+ bool PreviousIsInvoke = false;
+
+ bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj;
+
+ // Visit all instructions in order of address.
+ for (const auto &MBB : *Asm->MF) {
+ for (const auto &MI : MBB) {
+ if (!MI.isEHLabel()) {
+ if (MI.isCall())
+ SawPotentiallyThrowing |= !callToNoUnwindFunction(&MI);
+ continue;
+ }
+
+ // End of the previous try-range?
+ MCSymbol *BeginLabel = MI.getOperand(0).getMCSymbol();
+ if (BeginLabel == LastLabel)
+ SawPotentiallyThrowing = false;
+
+ // Beginning of a new try-range?
+ RangeMapType::const_iterator L = PadMap.find(BeginLabel);
+ if (L == PadMap.end())
+ // Nope, it was just some random label.
+ continue;
+
+ const PadRange &P = L->second;
+ const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
+ assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
+ "Inconsistent landing pad map!");
+
+ // For Dwarf exception handling (SjLj handling doesn't use this). If some
+ // instruction between the previous try-range and this one may throw,
+ // create a call-site entry with no landing pad for the region between the
+ // try-ranges.
+ if (SawPotentiallyThrowing && Asm->MAI->usesCFIForEH()) {
+ CallSiteEntry Site = { LastLabel, BeginLabel, nullptr, 0 };
+ CallSites.push_back(Site);
+ PreviousIsInvoke = false;
+ }
+
+ LastLabel = LandingPad->EndLabels[P.RangeIndex];
+ assert(BeginLabel && LastLabel && "Invalid landing pad!");
+
+ if (!LandingPad->LandingPadLabel) {
+ // Create a gap.
+ PreviousIsInvoke = false;
+ } else {
+ // This try-range is for an invoke.
+ CallSiteEntry Site = {
+ BeginLabel,
+ LastLabel,
+ LandingPad,
+ FirstActions[P.PadIndex]
+ };
+
+ // Try to merge with the previous call-site. SJLJ doesn't do this
+ if (PreviousIsInvoke && !IsSJLJ) {
+ CallSiteEntry &Prev = CallSites.back();
+ if (Site.LPad == Prev.LPad && Site.Action == Prev.Action) {
+ // Extend the range of the previous entry.
+ Prev.EndLabel = Site.EndLabel;
+ continue;
+ }
+ }
+
+ // Otherwise, create a new call-site.
+ if (!IsSJLJ)
+ CallSites.push_back(Site);
+ else {
+ // SjLj EH must maintain the call sites in the order assigned
+ // to them by the SjLjPrepare pass.
+ unsigned SiteNo = MMI->getCallSiteBeginLabel(BeginLabel);
+ if (CallSites.size() < SiteNo)
+ CallSites.resize(SiteNo);
+ CallSites[SiteNo - 1] = Site;
+ }
+ PreviousIsInvoke = true;
+ }
+ }
+ }
+
+ // If some instruction between the previous try-range and the end of the
+ // function may throw, create a call-site entry with no landing pad for the
+ // region following the try-range.
+ if (SawPotentiallyThrowing && !IsSJLJ && LastLabel != nullptr) {
+ CallSiteEntry Site = { LastLabel, nullptr, nullptr, 0 };
+ CallSites.push_back(Site);
+ }
+}
+
+/// Emit landing pads and actions.
+///
+/// The general organization of the table is complex, but the basic concepts are
+/// easy. First there is a header which describes the location and organization
+/// of the three components that follow.
+///
+/// 1. The landing pad site information describes the range of code covered by
+/// the try. In our case it's an accumulation of the ranges covered by the
+/// invokes in the try. There is also a reference to the landing pad that
+/// handles the exception once processed. Finally an index into the actions
+/// table.
+/// 2. The action table, in our case, is composed of pairs of type IDs and next
+/// action offset. Starting with the action index from the landing pad
+/// site, each type ID is checked for a match to the current exception. If
+/// it matches then the exception and type id are passed on to the landing
+/// pad. Otherwise the next action is looked up. This chain is terminated
+/// with a next action of zero. If no type id is found then 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 reverse indexed base 1.
+void EHStreamer::emitExceptionTable() {
+ const std::vector<const GlobalValue *> &TypeInfos = MMI->getTypeInfos();
+ const std::vector<unsigned> &FilterIds = MMI->getFilterIds();
+ const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
+
+ // Sort the landing pads in order of their type ids. This is used to fold
+ // duplicate actions.
+ SmallVector<const LandingPadInfo *, 64> LandingPads;
+ LandingPads.reserve(PadInfos.size());
+
+ for (unsigned i = 0, N = PadInfos.size(); i != N; ++i)
+ LandingPads.push_back(&PadInfos[i]);
+
+ // Order landing pads lexicographically by type id.
+ std::sort(LandingPads.begin(), LandingPads.end(),
+ [](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.
+ SmallVector<ActionEntry, 32> Actions;
+ SmallVector<unsigned, 64> FirstActions;
+ unsigned SizeActions =
+ computeActionsTable(LandingPads, Actions, FirstActions);
+
+ // Compute the call-site table.
+ SmallVector<CallSiteEntry, 64> CallSites;
+ computeCallSiteTable(CallSites, LandingPads, FirstActions);
+
+ // Final tallies.
+
+ // Call sites.
+ bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj;
+ bool HaveTTData = IsSJLJ ? (!TypeInfos.empty() || !FilterIds.empty()) : true;
+
+ unsigned CallSiteTableLength;
+ if (IsSJLJ)
+ CallSiteTableLength = 0;
+ else {
+ unsigned SiteStartSize = 4; // dwarf::DW_EH_PE_udata4
+ unsigned SiteLengthSize = 4; // dwarf::DW_EH_PE_udata4
+ unsigned LandingPadSize = 4; // dwarf::DW_EH_PE_udata4
+ CallSiteTableLength =
+ CallSites.size() * (SiteStartSize + SiteLengthSize + LandingPadSize);
+ }
+
+ for (unsigned i = 0, e = CallSites.size(); i < e; ++i) {
+ CallSiteTableLength += getULEB128Size(CallSites[i].Action);
+ if (IsSJLJ)
+ CallSiteTableLength += getULEB128Size(i);
+ }
+
+ // Type infos.
+ MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection();
+ unsigned TTypeEncoding;
+ unsigned TypeFormatSize;
+
+ if (!HaveTTData) {
+ // For SjLj exceptions, if there is no TypeInfo, then we just explicitly say
+ // that we're omitting that bit.
+ TTypeEncoding = dwarf::DW_EH_PE_omit;
+ // dwarf::DW_EH_PE_absptr
+ TypeFormatSize = Asm->getDataLayout().getPointerSize();
+ } else {
+ // Okay, we have actual filters or typeinfos to emit. As such, we need to
+ // pick a type encoding for them. We're about to emit a list of pointers to
+ // typeinfo objects at the end of the LSDA. However, unless we're in static
+ // mode, this reference will require a relocation by the dynamic linker.
+ //
+ // Because of this, we have a couple of options:
+ //
+ // 1) If we are in -static mode, we can always use an absolute reference
+ // from the LSDA, because the static linker will resolve it.
+ //
+ // 2) Otherwise, if the LSDA section is writable, we can output the direct
+ // reference to the typeinfo and allow the dynamic linker to relocate
+ // it. Since it is in a writable section, the dynamic linker won't
+ // have a problem.
+ //
+ // 3) Finally, if we're in PIC mode and the LDSA section isn't writable,
+ // we need to use some form of indirection. For example, on Darwin,
+ // we can output a statically-relocatable reference to a dyld stub. The
+ // offset to the stub is constant, but the contents are in a section
+ // that is updated by the dynamic linker. This is easy enough, but we
+ // need to tell the personality function of the unwinder to indirect
+ // through the dyld stub.
+ //
+ // FIXME: When (3) is actually implemented, we'll have to emit the stubs
+ // somewhere. This predicate should be moved to a shared location that is
+ // in target-independent code.
+ //
+ TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding();
+ TypeFormatSize = Asm->GetSizeOfEncodedValue(TTypeEncoding);
+ }
+
+ // Begin the exception table.
+ // Sometimes we want not to emit the data into separate section (e.g. ARM
+ // EHABI). In this case LSDASection will be NULL.
+ if (LSDASection)
+ Asm->OutStreamer->SwitchSection(LSDASection);
+ Asm->EmitAlignment(2);
+
+ // Emit the LSDA.
+ MCSymbol *GCCETSym =
+ Asm->OutContext.getOrCreateSymbol(Twine("GCC_except_table")+
+ Twine(Asm->getFunctionNumber()));
+ Asm->OutStreamer->EmitLabel(GCCETSym);
+ Asm->OutStreamer->EmitLabel(Asm->getCurExceptionSym());
+
+ // Emit the LSDA header.
+ Asm->EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart");
+ Asm->EmitEncodingByte(TTypeEncoding, "@TType");
+
+ // The type infos need to be aligned. GCC does this by inserting padding just
+ // before the type infos. However, this changes the size of the exception
+ // table, so you need to take this into account when you output the exception
+ // table size. However, the size is output using a variable length encoding.
+ // So by increasing the size by inserting padding, you may increase the number
+ // of bytes used for writing the size. If it increases, say by one byte, then
+ // you now need to output one less byte of padding to get the type infos
+ // aligned. However this decreases the size of the exception table. This
+ // changes the value you have to output for the exception table size. Due to
+ // the variable length encoding, the number of bytes used for writing the
+ // length may decrease. If so, you then have to increase the amount of
+ // padding. And so on. If you look carefully at the GCC code you will see that
+ // it indeed does this in a loop, going on and on until the values stabilize.
+ // We chose another solution: don't output padding inside the table like GCC
+ // does, instead output it before the table.
+ unsigned SizeTypes = TypeInfos.size() * TypeFormatSize;
+ unsigned CallSiteTableLengthSize = getULEB128Size(CallSiteTableLength);
+ unsigned TTypeBaseOffset =
+ sizeof(int8_t) + // Call site format
+ CallSiteTableLengthSize + // Call site table length size
+ CallSiteTableLength + // Call site table length
+ SizeActions + // Actions size
+ SizeTypes;
+ unsigned TTypeBaseOffsetSize = getULEB128Size(TTypeBaseOffset);
+ unsigned TotalSize =
+ sizeof(int8_t) + // LPStart format
+ sizeof(int8_t) + // TType format
+ (HaveTTData ? TTypeBaseOffsetSize : 0) + // TType base offset size
+ TTypeBaseOffset; // TType base offset
+ unsigned SizeAlign = (4 - TotalSize) & 3;
+
+ if (HaveTTData) {
+ // Account for any extra padding that will be added to the call site table
+ // length.
+ Asm->EmitULEB128(TTypeBaseOffset, "@TType base offset", SizeAlign);
+ SizeAlign = 0;
+ }
+
+ bool VerboseAsm = Asm->OutStreamer->isVerboseAsm();
+
+ // SjLj Exception handling
+ if (IsSJLJ) {
+ Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
+
+ // Add extra padding if it wasn't added to the TType base offset.
+ Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign);
+
+ // Emit the landing pad site information.
+ unsigned idx = 0;
+ for (SmallVectorImpl<CallSiteEntry>::const_iterator
+ I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) {
+ const CallSiteEntry &S = *I;
+
+ // Offset of the landing pad, counted in 16-byte bundles relative to the
+ // @LPStart address.
+ if (VerboseAsm) {
+ Asm->OutStreamer->AddComment(">> Call Site " + Twine(idx) + " <<");
+ Asm->OutStreamer->AddComment(" On exception at call site "+Twine(idx));
+ }
+ Asm->EmitULEB128(idx);
+
+ // Offset of the first associated action record, relative to the start of
+ // the action table. This value is biased by 1 (1 indicates the start of
+ // the action table), and 0 indicates that there are no actions.
+ if (VerboseAsm) {
+ if (S.Action == 0)
+ Asm->OutStreamer->AddComment(" Action: cleanup");
+ else
+ Asm->OutStreamer->AddComment(" Action: " +
+ Twine((S.Action - 1) / 2 + 1));
+ }
+ Asm->EmitULEB128(S.Action);
+ }
+ } else {
+ // Itanium LSDA exception handling
+
+ // The call-site table is a list of all call sites that may throw an
+ // exception (including C++ 'throw' statements) in the procedure
+ // fragment. It immediately follows the LSDA header. Each entry indicates,
+ // for a given call, the first corresponding action record and corresponding
+ // landing pad.
+ //
+ // The table begins with the number of bytes, stored as an LEB128
+ // compressed, unsigned integer. The records immediately follow the record
+ // count. They are sorted in increasing call-site address. Each record
+ // indicates:
+ //
+ // * The position of the call-site.
+ // * The position of the landing pad.
+ // * The first action record for that call site.
+ //
+ // A missing entry in the call-site table indicates that a call is not
+ // supposed to throw.
+
+ // Emit the landing pad call site table.
+ Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
+
+ // Add extra padding if it wasn't added to the TType base offset.
+ Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign);
+
+ unsigned Entry = 0;
+ for (SmallVectorImpl<CallSiteEntry>::const_iterator
+ I = CallSites.begin(), E = CallSites.end(); I != E; ++I) {
+ const CallSiteEntry &S = *I;
+
+ MCSymbol *EHFuncBeginSym = Asm->getFunctionBegin();
+
+ MCSymbol *BeginLabel = S.BeginLabel;
+ if (!BeginLabel)
+ BeginLabel = EHFuncBeginSym;
+ MCSymbol *EndLabel = S.EndLabel;
+ if (!EndLabel)
+ EndLabel = Asm->getFunctionEnd();
+
+ // Offset of the call site relative to the previous call site, counted in
+ // number of 16-byte bundles. The first call site is counted relative to
+ // the start of the procedure fragment.
+ if (VerboseAsm)
+ Asm->OutStreamer->AddComment(">> Call Site " + Twine(++Entry) + " <<");
+ Asm->EmitLabelDifference(BeginLabel, EHFuncBeginSym, 4);
+ if (VerboseAsm)
+ Asm->OutStreamer->AddComment(Twine(" Call between ") +
+ BeginLabel->getName() + " and " +
+ EndLabel->getName());
+ Asm->EmitLabelDifference(EndLabel, BeginLabel, 4);
+
+ // Offset of the landing pad, counted in 16-byte bundles relative to the
+ // @LPStart address.
+ if (!S.LPad) {
+ if (VerboseAsm)
+ Asm->OutStreamer->AddComment(" has no landing pad");
+ Asm->OutStreamer->EmitIntValue(0, 4/*size*/);
+ } else {
+ if (VerboseAsm)
+ Asm->OutStreamer->AddComment(Twine(" jumps to ") +
+ S.LPad->LandingPadLabel->getName());
+ Asm->EmitLabelDifference(S.LPad->LandingPadLabel, EHFuncBeginSym, 4);
+ }
+
+ // Offset of the first associated action record, relative to the start of
+ // the action table. This value is biased by 1 (1 indicates the start of
+ // the action table), and 0 indicates that there are no actions.
+ if (VerboseAsm) {
+ if (S.Action == 0)
+ Asm->OutStreamer->AddComment(" On action: cleanup");
+ else
+ Asm->OutStreamer->AddComment(" On action: " +
+ Twine((S.Action - 1) / 2 + 1));
+ }
+ Asm->EmitULEB128(S.Action);
+ }
+ }
+
+ // Emit the Action Table.
+ int Entry = 0;
+ for (SmallVectorImpl<ActionEntry>::const_iterator
+ I = Actions.begin(), E = Actions.end(); I != E; ++I) {
+ const ActionEntry &Action = *I;
+
+ if (VerboseAsm) {
+ // Emit comments that decode the action table.
+ Asm->OutStreamer->AddComment(">> Action Record " + Twine(++Entry) + " <<");
+ }
+
+ // Type Filter
+ //
+ // Used by the runtime to match the type of the thrown exception to the
+ // type of the catch clauses or the types in the exception specification.
+ if (VerboseAsm) {
+ if (Action.ValueForTypeID > 0)
+ Asm->OutStreamer->AddComment(" Catch TypeInfo " +
+ Twine(Action.ValueForTypeID));
+ else if (Action.ValueForTypeID < 0)
+ Asm->OutStreamer->AddComment(" Filter TypeInfo " +
+ Twine(Action.ValueForTypeID));
+ else
+ Asm->OutStreamer->AddComment(" Cleanup");
+ }
+ Asm->EmitSLEB128(Action.ValueForTypeID);
+
+ // Action Record
+ //
+ // Self-relative signed displacement in bytes of the next action record,
+ // or 0 if there is no next action record.
+ if (VerboseAsm) {
+ if (Action.NextAction == 0) {
+ Asm->OutStreamer->AddComment(" No further actions");
+ } else {
+ unsigned NextAction = Entry + (Action.NextAction + 1) / 2;
+ Asm->OutStreamer->AddComment(" Continue to action "+Twine(NextAction));
+ }
+ }
+ Asm->EmitSLEB128(Action.NextAction);
+ }
+
+ emitTypeInfos(TTypeEncoding);
+
+ Asm->EmitAlignment(2);
+}
+
+void EHStreamer::emitTypeInfos(unsigned TTypeEncoding) {
+ const std::vector<const GlobalValue *> &TypeInfos = MMI->getTypeInfos();
+ const std::vector<unsigned> &FilterIds = MMI->getFilterIds();
+
+ bool VerboseAsm = Asm->OutStreamer->isVerboseAsm();
+
+ int Entry = 0;
+ // Emit the Catch TypeInfos.
+ if (VerboseAsm && !TypeInfos.empty()) {
+ Asm->OutStreamer->AddComment(">> Catch TypeInfos <<");
+ Asm->OutStreamer->AddBlankLine();
+ Entry = TypeInfos.size();
+ }
+
+ for (const GlobalValue *GV : make_range(TypeInfos.rbegin(),
+ TypeInfos.rend())) {
+ if (VerboseAsm)
+ Asm->OutStreamer->AddComment("TypeInfo " + Twine(Entry--));
+ Asm->EmitTTypeReference(GV, TTypeEncoding);
+ }
+
+ // Emit the Exception Specifications.
+ if (VerboseAsm && !FilterIds.empty()) {
+ Asm->OutStreamer->AddComment(">> Filter TypeInfos <<");
+ Asm->OutStreamer->AddBlankLine();
+ Entry = 0;
+ }
+ for (std::vector<unsigned>::const_iterator
+ I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) {
+ unsigned TypeID = *I;
+ if (VerboseAsm) {
+ --Entry;
+ if (isFilterEHSelector(TypeID))
+ Asm->OutStreamer->AddComment("FilterInfo " + Twine(Entry));
+ }
+
+ Asm->EmitULEB128(TypeID);
+ }
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.h b/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.h
new file mode 100644
index 0000000..c6a0e9d
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.h
@@ -0,0 +1,138 @@
+//===-- EHStreamer.h - Exception Handling Directive Streamer ---*- 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 exception info into assembly files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_EHSTREAMER_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_EHSTREAMER_H
+
+#include "AsmPrinterHandler.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace llvm {
+struct LandingPadInfo;
+class MachineModuleInfo;
+class MachineInstr;
+class MachineFunction;
+class AsmPrinter;
+class MCSymbol;
+class MCSymbolRefExpr;
+
+template <typename T>
+class SmallVectorImpl;
+
+/// Emits exception handling directives.
+class LLVM_LIBRARY_VISIBILITY EHStreamer : public AsmPrinterHandler {
+protected:
+ /// Target of directive emission.
+ AsmPrinter *Asm;
+
+ /// Collected machine module information.
+ MachineModuleInfo *MMI;
+
+ /// How many leading type ids two landing pads have in common.
+ static unsigned sharedTypeIDs(const LandingPadInfo *L,
+ const LandingPadInfo *R);
+
+ /// Structure holding a try-range and the associated landing pad.
+ struct PadRange {
+ // The index of the landing pad.
+ unsigned PadIndex;
+ // The index of the begin and end labels in the landing pad's label lists.
+ unsigned RangeIndex;
+ };
+
+ typedef DenseMap<MCSymbol *, PadRange> RangeMapType;
+
+ /// Structure describing an entry in the actions table.
+ struct ActionEntry {
+ int ValueForTypeID; // The value to write - may not be equal to the type id.
+ int NextAction;
+ unsigned Previous;
+ };
+
+ /// Structure describing an entry in the call-site table.
+ struct CallSiteEntry {
+ // The 'try-range' is BeginLabel .. EndLabel.
+ MCSymbol *BeginLabel; // Null indicates the start of the function.
+ MCSymbol *EndLabel; // Null indicates the end of the function.
+
+ // LPad contains the landing pad start labels.
+ const LandingPadInfo *LPad; // Null indicates that there is no landing pad.
+ unsigned Action;
+ };
+
+ /// Compute the actions table and gather the first action index for each
+ /// landing pad site.
+ unsigned computeActionsTable(const SmallVectorImpl<const LandingPadInfo*>&LPs,
+ SmallVectorImpl<ActionEntry> &Actions,
+ SmallVectorImpl<unsigned> &FirstActions);
+
+ void computePadMap(const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
+ RangeMapType &PadMap);
+
+ /// Compute the call-site table. The entry for an invoke has a try-range
+ /// containing the call, a non-zero landing pad and an appropriate action.
+ /// The entry for an ordinary call has a try-range containing the call and
+ /// 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 *> &LPs,
+ const SmallVectorImpl<unsigned> &FirstActions);
+
+ /// Emit landing pads and actions.
+ ///
+ /// The general organization of the table is complex, but the basic concepts
+ /// are easy. First there is a header which describes the location and
+ /// organization of the three components that follow.
+ /// 1. The landing pad site information describes the range of code covered
+ /// by the try. In our case it's an accumulation of the ranges covered
+ /// by the invokes in the try. There is also a reference to the landing
+ /// pad that handles the exception once processed. Finally an index into
+ /// the actions table.
+ /// 2. The action table, in our case, is composed of pairs of type ids
+ /// and next action offset. Starting with the action index from the
+ /// landing pad site, each type Id is checked for a match to the current
+ /// exception. If it matches then the exception and type id are passed
+ /// on to the landing pad. Otherwise the next action is looked up. This
+ /// chain is terminated with a next action of zero. If no type id is
+ /// 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();
+
+ virtual void emitTypeInfos(unsigned TTypeEncoding);
+
+ // Helpers for for identifying what kind of clause an EH typeid or selector
+ // corresponds to. Negative selectors are for filter clauses, the zero
+ // selector is for cleanups, and positive selectors are for catch clauses.
+ static bool isFilterEHSelector(int Selector) { return Selector < 0; }
+ static bool isCleanupEHSelector(int Selector) { return Selector == 0; }
+ static bool isCatchEHSelector(int Selector) { return Selector > 0; }
+
+public:
+ EHStreamer(AsmPrinter *A);
+ ~EHStreamer() override;
+
+ // Unused.
+ void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override {}
+ void beginInstruction(const MachineInstr *MI) override {}
+ void endInstruction() override {}
+
+ /// Return `true' if this is a call to a function marked `nounwind'. Return
+ /// `false' otherwise.
+ static bool callToNoUnwindFunction(const MachineInstr *MI);
+};
+}
+
+#endif
+
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp
new file mode 100644
index 0000000..6a023b9
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp
@@ -0,0 +1,123 @@
+//===-- ErlangGCPrinter.cpp - Erlang/OTP frametable emitter -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the compiler plugin that is used in order to emit
+// garbage collection information in a convenient layout for parsing and
+// loading in the Erlang/OTP runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/GCMetadataPrinter.h"
+#include "llvm/CodeGen/GCs.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+
+using namespace llvm;
+
+namespace {
+
+class ErlangGCPrinter : public GCMetadataPrinter {
+public:
+ void finishAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) override;
+};
+}
+
+static GCMetadataPrinterRegistry::Add<ErlangGCPrinter>
+ X("erlang", "erlang-compatible garbage collector");
+
+void llvm::linkErlangGCPrinter() {}
+
+void ErlangGCPrinter::finishAssembly(Module &M, GCModuleInfo &Info,
+ AsmPrinter &AP) {
+ MCStreamer &OS = *AP.OutStreamer;
+ unsigned IntPtrSize = M.getDataLayout().getPointerSize();
+
+ // Put this in a custom .note section.
+ OS.SwitchSection(
+ AP.getObjFileLowering().getContext().getELFSection(".note.gc",
+ ELF::SHT_PROGBITS, 0));
+
+ // For each function...
+ for (GCModuleInfo::FuncInfoVec::iterator FI = Info.funcinfo_begin(),
+ IE = Info.funcinfo_end();
+ FI != IE; ++FI) {
+ GCFunctionInfo &MD = **FI;
+ if (MD.getStrategy().getName() != getStrategy().getName())
+ // this function is managed by some other GC
+ continue;
+ /** A compact GC layout. Emit this data structure:
+ *
+ * struct {
+ * int16_t PointCount;
+ * void *SafePointAddress[PointCount];
+ * int16_t StackFrameSize; (in words)
+ * int16_t StackArity;
+ * int16_t LiveCount;
+ * int16_t LiveOffsets[LiveCount];
+ * } __gcmap_<FUNCTIONNAME>;
+ **/
+
+ // Align to address width.
+ AP.EmitAlignment(IntPtrSize == 4 ? 2 : 3);
+
+ // Emit PointCount.
+ OS.AddComment("safe point count");
+ AP.EmitInt16(MD.size());
+
+ // And each safe point...
+ for (GCFunctionInfo::iterator PI = MD.begin(), PE = MD.end(); PI != PE;
+ ++PI) {
+ // Emit the address of the safe point.
+ OS.AddComment("safe point address");
+ MCSymbol *Label = PI->Label;
+ AP.EmitLabelPlusOffset(Label /*Hi*/, 0 /*Offset*/, 4 /*Size*/);
+ }
+
+ // Stack information never change in safe points! Only print info from the
+ // first call-site.
+ GCFunctionInfo::iterator PI = MD.begin();
+
+ // Emit the stack frame size.
+ OS.AddComment("stack frame size (in words)");
+ AP.EmitInt16(MD.getFrameSize() / IntPtrSize);
+
+ // Emit stack arity, i.e. the number of stacked arguments.
+ unsigned RegisteredArgs = IntPtrSize == 4 ? 5 : 6;
+ unsigned StackArity = MD.getFunction().arg_size() > RegisteredArgs
+ ? MD.getFunction().arg_size() - RegisteredArgs
+ : 0;
+ OS.AddComment("stack arity");
+ AP.EmitInt16(StackArity);
+
+ // Emit the number of live roots in the function.
+ OS.AddComment("live root count");
+ AP.EmitInt16(MD.live_size(PI));
+
+ // And for each live root...
+ for (GCFunctionInfo::live_iterator LI = MD.live_begin(PI),
+ LE = MD.live_end(PI);
+ LI != LE; ++LI) {
+ // Emit live root's offset within the stack frame.
+ OS.AddComment("stack index (offset / wordsize)");
+ AP.EmitInt16(LI->StackOffset / IntPtrSize);
+ }
+ }
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
new file mode 100644
index 0000000..c09ef6a
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
@@ -0,0 +1,182 @@
+//===-- OcamlGCPrinter.cpp - Ocaml frametable emitter ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements printing the assembly code for an Ocaml frametable.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/GCs.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/GCMetadataPrinter.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Mangler.h"
+#include "llvm/IR/Module.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+#include <cctype>
+using namespace llvm;
+
+namespace {
+
+class OcamlGCMetadataPrinter : public GCMetadataPrinter {
+public:
+ void beginAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) override;
+ void finishAssembly(Module &M, GCModuleInfo &Info, AsmPrinter &AP) override;
+};
+}
+
+static GCMetadataPrinterRegistry::Add<OcamlGCMetadataPrinter>
+ Y("ocaml", "ocaml 3.10-compatible collector");
+
+void llvm::linkOcamlGCPrinter() {}
+
+static void EmitCamlGlobal(const Module &M, AsmPrinter &AP, const char *Id) {
+ const std::string &MId = M.getModuleIdentifier();
+
+ std::string SymName;
+ SymName += "caml";
+ size_t Letter = SymName.size();
+ SymName.append(MId.begin(), std::find(MId.begin(), MId.end(), '.'));
+ SymName += "__";
+ SymName += Id;
+
+ // Capitalize the first letter of the module name.
+ SymName[Letter] = toupper(SymName[Letter]);
+
+ SmallString<128> TmpStr;
+ Mangler::getNameWithPrefix(TmpStr, SymName, M.getDataLayout());
+
+ MCSymbol *Sym = AP.OutContext.getOrCreateSymbol(TmpStr);
+
+ AP.OutStreamer->EmitSymbolAttribute(Sym, MCSA_Global);
+ AP.OutStreamer->EmitLabel(Sym);
+}
+
+void OcamlGCMetadataPrinter::beginAssembly(Module &M, GCModuleInfo &Info,
+ AsmPrinter &AP) {
+ AP.OutStreamer->SwitchSection(AP.getObjFileLowering().getTextSection());
+ EmitCamlGlobal(M, AP, "code_begin");
+
+ AP.OutStreamer->SwitchSection(AP.getObjFileLowering().getDataSection());
+ EmitCamlGlobal(M, AP, "data_begin");
+}
+
+/// emitAssembly - Print the frametable. The ocaml frametable format is thus:
+///
+/// extern "C" struct align(sizeof(intptr_t)) {
+/// uint16_t NumDescriptors;
+/// struct align(sizeof(intptr_t)) {
+/// void *ReturnAddress;
+/// uint16_t FrameSize;
+/// uint16_t NumLiveOffsets;
+/// uint16_t LiveOffsets[NumLiveOffsets];
+/// } Descriptors[NumDescriptors];
+/// } caml${module}__frametable;
+///
+/// Note that this precludes programs from stack frames larger than 64K
+/// (FrameSize and LiveOffsets would overflow). FrameTablePrinter will abort if
+/// either condition is detected in a function which uses the GC.
+///
+void OcamlGCMetadataPrinter::finishAssembly(Module &M, GCModuleInfo &Info,
+ AsmPrinter &AP) {
+ unsigned IntPtrSize = M.getDataLayout().getPointerSize();
+
+ AP.OutStreamer->SwitchSection(AP.getObjFileLowering().getTextSection());
+ EmitCamlGlobal(M, AP, "code_end");
+
+ AP.OutStreamer->SwitchSection(AP.getObjFileLowering().getDataSection());
+ EmitCamlGlobal(M, AP, "data_end");
+
+ // FIXME: Why does ocaml emit this??
+ AP.OutStreamer->EmitIntValue(0, IntPtrSize);
+
+ AP.OutStreamer->SwitchSection(AP.getObjFileLowering().getDataSection());
+ EmitCamlGlobal(M, AP, "frametable");
+
+ int NumDescriptors = 0;
+ for (GCModuleInfo::FuncInfoVec::iterator I = Info.funcinfo_begin(),
+ IE = Info.funcinfo_end();
+ I != IE; ++I) {
+ GCFunctionInfo &FI = **I;
+ if (FI.getStrategy().getName() != getStrategy().getName())
+ // this function is managed by some other GC
+ continue;
+ for (GCFunctionInfo::iterator J = FI.begin(), JE = FI.end(); J != JE; ++J) {
+ NumDescriptors++;
+ }
+ }
+
+ if (NumDescriptors >= 1 << 16) {
+ // Very rude!
+ report_fatal_error(" Too much descriptor for ocaml GC");
+ }
+ AP.EmitInt16(NumDescriptors);
+ AP.EmitAlignment(IntPtrSize == 4 ? 2 : 3);
+
+ for (GCModuleInfo::FuncInfoVec::iterator I = Info.funcinfo_begin(),
+ IE = Info.funcinfo_end();
+ I != IE; ++I) {
+ GCFunctionInfo &FI = **I;
+ if (FI.getStrategy().getName() != getStrategy().getName())
+ // this function is managed by some other GC
+ continue;
+
+ uint64_t FrameSize = FI.getFrameSize();
+ if (FrameSize >= 1 << 16) {
+ // Very rude!
+ report_fatal_error("Function '" + FI.getFunction().getName() +
+ "' is too large for the ocaml GC! "
+ "Frame size " +
+ Twine(FrameSize) + ">= 65536.\n"
+ "(" +
+ Twine(uintptr_t(&FI)) + ")");
+ }
+
+ AP.OutStreamer->AddComment("live roots for " +
+ Twine(FI.getFunction().getName()));
+ AP.OutStreamer->AddBlankLine();
+
+ for (GCFunctionInfo::iterator J = FI.begin(), JE = FI.end(); J != JE; ++J) {
+ size_t LiveCount = FI.live_size(J);
+ if (LiveCount >= 1 << 16) {
+ // Very rude!
+ report_fatal_error("Function '" + FI.getFunction().getName() +
+ "' is too large for the ocaml GC! "
+ "Live root count " +
+ Twine(LiveCount) + " >= 65536.");
+ }
+
+ AP.OutStreamer->EmitSymbolValue(J->Label, IntPtrSize);
+ AP.EmitInt16(FrameSize);
+ AP.EmitInt16(LiveCount);
+
+ for (GCFunctionInfo::live_iterator K = FI.live_begin(J),
+ KE = FI.live_end(J);
+ K != KE; ++K) {
+ if (K->StackOffset >= 1 << 16) {
+ // Very rude!
+ report_fatal_error(
+ "GC root stack offset is outside of fixed stack frame and out "
+ "of range for ocaml GC!");
+ }
+ AP.EmitInt16(K->StackOffset);
+ }
+
+ AP.EmitAlignment(IntPtrSize == 4 ? 2 : 3);
+ }
+ }
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp
new file mode 100644
index 0000000..c2c0f84
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp
@@ -0,0 +1,396 @@
+//===-- llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp --*- 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 line tables info into COFF files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "WinCodeViewLineTables.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/COFF.h"
+
+namespace llvm {
+
+StringRef WinCodeViewLineTables::getFullFilepath(const MDNode *S) {
+ assert(S);
+ assert((isa<DICompileUnit>(S) || isa<DIFile>(S) || isa<DISubprogram>(S) ||
+ isa<DILexicalBlockBase>(S)) &&
+ "Unexpected scope info");
+
+ auto *Scope = cast<DIScope>(S);
+ StringRef Dir = Scope->getDirectory(),
+ Filename = Scope->getFilename();
+ std::string &Filepath =
+ DirAndFilenameToFilepathMap[std::make_pair(Dir, Filename)];
+ if (!Filepath.empty())
+ return Filepath;
+
+ // Clang emits directory and relative filename info into the IR, but CodeView
+ // operates on full paths. We could change Clang to emit full paths too, but
+ // that would increase the IR size and probably not needed for other users.
+ // For now, just concatenate and canonicalize the path here.
+ if (Filename.find(':') == 1)
+ Filepath = Filename;
+ else
+ Filepath = (Dir + "\\" + Filename).str();
+
+ // Canonicalize the path. We have to do it textually because we may no longer
+ // have access the file in the filesystem.
+ // First, replace all slashes with backslashes.
+ std::replace(Filepath.begin(), Filepath.end(), '/', '\\');
+
+ // Remove all "\.\" with "\".
+ size_t Cursor = 0;
+ while ((Cursor = Filepath.find("\\.\\", Cursor)) != std::string::npos)
+ Filepath.erase(Cursor, 2);
+
+ // Replace all "\XXX\..\" with "\". Don't try too hard though as the original
+ // path should be well-formatted, e.g. start with a drive letter, etc.
+ Cursor = 0;
+ while ((Cursor = Filepath.find("\\..\\", Cursor)) != std::string::npos) {
+ // Something's wrong if the path starts with "\..\", abort.
+ if (Cursor == 0)
+ break;
+
+ size_t PrevSlash = Filepath.rfind('\\', Cursor - 1);
+ if (PrevSlash == std::string::npos)
+ // Something's wrong, abort.
+ break;
+
+ Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
+ // The next ".." might be following the one we've just erased.
+ Cursor = PrevSlash;
+ }
+
+ // Remove all duplicate backslashes.
+ Cursor = 0;
+ while ((Cursor = Filepath.find("\\\\", Cursor)) != std::string::npos)
+ Filepath.erase(Cursor, 1);
+
+ return Filepath;
+}
+
+void WinCodeViewLineTables::maybeRecordLocation(DebugLoc DL,
+ const MachineFunction *MF) {
+ const MDNode *Scope = DL.getScope();
+ if (!Scope)
+ return;
+ StringRef Filename = getFullFilepath(Scope);
+
+ // Skip this instruction if it has the same file:line as the previous one.
+ assert(CurFn);
+ if (!CurFn->Instrs.empty()) {
+ const InstrInfoTy &LastInstr = InstrInfo[CurFn->Instrs.back()];
+ if (LastInstr.Filename == Filename && LastInstr.LineNumber == DL.getLine())
+ return;
+ }
+ FileNameRegistry.add(Filename);
+
+ MCSymbol *MCL = Asm->MMI->getContext().createTempSymbol();
+ Asm->OutStreamer->EmitLabel(MCL);
+ CurFn->Instrs.push_back(MCL);
+ InstrInfo[MCL] = InstrInfoTy(Filename, DL.getLine(), DL.getCol());
+}
+
+WinCodeViewLineTables::WinCodeViewLineTables(AsmPrinter *AP)
+ : Asm(nullptr), CurFn(nullptr) {
+ MachineModuleInfo *MMI = AP->MMI;
+
+ // If module doesn't have named metadata anchors or COFF debug section
+ // is not available, skip any debug info related stuff.
+ if (!MMI->getModule()->getNamedMetadata("llvm.dbg.cu") ||
+ !AP->getObjFileLowering().getCOFFDebugSymbolsSection())
+ return;
+
+ // Tell MMI that we have debug info.
+ MMI->setDebugInfoAvailability(true);
+ Asm = AP;
+}
+
+void WinCodeViewLineTables::endModule() {
+ if (FnDebugInfo.empty())
+ return;
+
+ assert(Asm != nullptr);
+ Asm->OutStreamer->SwitchSection(
+ Asm->getObjFileLowering().getCOFFDebugSymbolsSection());
+ Asm->EmitInt32(COFF::DEBUG_SECTION_MAGIC);
+
+ // The COFF .debug$S section consists of several subsections, each starting
+ // with a 4-byte control code (e.g. 0xF1, 0xF2, etc) and then a 4-byte length
+ // of the payload followed by the payload itself. The subsections are 4-byte
+ // aligned.
+
+ // Emit per-function debug information. This code is extracted into a
+ // separate function for readability.
+ for (size_t I = 0, E = VisitedFunctions.size(); I != E; ++I)
+ emitDebugInfoForFunction(VisitedFunctions[I]);
+
+ // This subsection holds a file index to offset in string table table.
+ Asm->OutStreamer->AddComment("File index to string table offset subsection");
+ Asm->EmitInt32(COFF::DEBUG_INDEX_SUBSECTION);
+ size_t NumFilenames = FileNameRegistry.Infos.size();
+ Asm->EmitInt32(8 * NumFilenames);
+ for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) {
+ StringRef Filename = FileNameRegistry.Filenames[I];
+ // For each unique filename, just write its offset in the string table.
+ Asm->EmitInt32(FileNameRegistry.Infos[Filename].StartOffset);
+ // The function name offset is not followed by any additional data.
+ Asm->EmitInt32(0);
+ }
+
+ // This subsection holds the string table.
+ Asm->OutStreamer->AddComment("String table");
+ Asm->EmitInt32(COFF::DEBUG_STRING_TABLE_SUBSECTION);
+ Asm->EmitInt32(FileNameRegistry.LastOffset);
+ // The payload starts with a null character.
+ Asm->EmitInt8(0);
+
+ for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) {
+ // Just emit unique filenames one by one, separated by a null character.
+ Asm->OutStreamer->EmitBytes(FileNameRegistry.Filenames[I]);
+ Asm->EmitInt8(0);
+ }
+
+ // No more subsections. Fill with zeros to align the end of the section by 4.
+ Asm->OutStreamer->EmitFill((-FileNameRegistry.LastOffset) % 4, 0);
+
+ clear();
+}
+
+static void EmitLabelDiff(MCStreamer &Streamer,
+ const MCSymbol *From, const MCSymbol *To,
+ unsigned int Size = 4) {
+ MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
+ MCContext &Context = Streamer.getContext();
+ const MCExpr *FromRef = MCSymbolRefExpr::create(From, Variant, Context),
+ *ToRef = MCSymbolRefExpr::create(To, Variant, Context);
+ const MCExpr *AddrDelta =
+ MCBinaryExpr::create(MCBinaryExpr::Sub, ToRef, FromRef, Context);
+ Streamer.EmitValue(AddrDelta, Size);
+}
+
+void WinCodeViewLineTables::emitDebugInfoForFunction(const Function *GV) {
+ // For each function there is a separate subsection
+ // which holds the PC to file:line table.
+ const MCSymbol *Fn = Asm->getSymbol(GV);
+ assert(Fn);
+
+ const FunctionInfo &FI = FnDebugInfo[GV];
+ if (FI.Instrs.empty())
+ return;
+ assert(FI.End && "Don't know where the function ends?");
+
+ StringRef GVName = GV->getName();
+ StringRef FuncName;
+ if (auto *SP = getDISubprogram(GV))
+ FuncName = SP->getDisplayName();
+
+ // FIXME Clang currently sets DisplayName to "bar" for a C++
+ // "namespace_foo::bar" function, see PR21528. Luckily, dbghelp.dll is trying
+ // to demangle display names anyways, so let's just put a mangled name into
+ // the symbols subsection until Clang gives us what we need.
+ if (GVName.startswith("\01?"))
+ FuncName = GVName.substr(1);
+ // Emit a symbol subsection, required by VS2012+ to find function boundaries.
+ MCSymbol *SymbolsBegin = Asm->MMI->getContext().createTempSymbol(),
+ *SymbolsEnd = Asm->MMI->getContext().createTempSymbol();
+ Asm->OutStreamer->AddComment("Symbol subsection for " + Twine(FuncName));
+ Asm->EmitInt32(COFF::DEBUG_SYMBOL_SUBSECTION);
+ EmitLabelDiff(*Asm->OutStreamer, SymbolsBegin, SymbolsEnd);
+ Asm->OutStreamer->EmitLabel(SymbolsBegin);
+ {
+ MCSymbol *ProcSegmentBegin = Asm->MMI->getContext().createTempSymbol(),
+ *ProcSegmentEnd = Asm->MMI->getContext().createTempSymbol();
+ EmitLabelDiff(*Asm->OutStreamer, ProcSegmentBegin, ProcSegmentEnd, 2);
+ Asm->OutStreamer->EmitLabel(ProcSegmentBegin);
+
+ Asm->EmitInt16(COFF::DEBUG_SYMBOL_TYPE_PROC_START);
+ // Some bytes of this segment don't seem to be required for basic debugging,
+ // so just fill them with zeroes.
+ Asm->OutStreamer->EmitFill(12, 0);
+ // This is the important bit that tells the debugger where the function
+ // code is located and what's its size:
+ EmitLabelDiff(*Asm->OutStreamer, Fn, FI.End);
+ Asm->OutStreamer->EmitFill(12, 0);
+ Asm->OutStreamer->EmitCOFFSecRel32(Fn);
+ Asm->OutStreamer->EmitCOFFSectionIndex(Fn);
+ Asm->EmitInt8(0);
+ // Emit the function display name as a null-terminated string.
+ Asm->OutStreamer->EmitBytes(FuncName);
+ Asm->EmitInt8(0);
+ Asm->OutStreamer->EmitLabel(ProcSegmentEnd);
+
+ // We're done with this function.
+ Asm->EmitInt16(0x0002);
+ Asm->EmitInt16(COFF::DEBUG_SYMBOL_TYPE_PROC_END);
+ }
+ Asm->OutStreamer->EmitLabel(SymbolsEnd);
+ // Every subsection must be aligned to a 4-byte boundary.
+ Asm->OutStreamer->EmitFill((-FuncName.size()) % 4, 0);
+
+ // PCs/Instructions are grouped into segments sharing the same filename.
+ // Pre-calculate the lengths (in instructions) of these segments and store
+ // them in a map for convenience. Each index in the map is the sequential
+ // number of the respective instruction that starts a new segment.
+ DenseMap<size_t, size_t> FilenameSegmentLengths;
+ size_t LastSegmentEnd = 0;
+ StringRef PrevFilename = InstrInfo[FI.Instrs[0]].Filename;
+ for (size_t J = 1, F = FI.Instrs.size(); J != F; ++J) {
+ if (PrevFilename == InstrInfo[FI.Instrs[J]].Filename)
+ continue;
+ FilenameSegmentLengths[LastSegmentEnd] = J - LastSegmentEnd;
+ LastSegmentEnd = J;
+ PrevFilename = InstrInfo[FI.Instrs[J]].Filename;
+ }
+ FilenameSegmentLengths[LastSegmentEnd] = FI.Instrs.size() - LastSegmentEnd;
+
+ // Emit a line table subsection, required to do PC-to-file:line lookup.
+ Asm->OutStreamer->AddComment("Line table subsection for " + Twine(FuncName));
+ Asm->EmitInt32(COFF::DEBUG_LINE_TABLE_SUBSECTION);
+ MCSymbol *LineTableBegin = Asm->MMI->getContext().createTempSymbol(),
+ *LineTableEnd = Asm->MMI->getContext().createTempSymbol();
+ EmitLabelDiff(*Asm->OutStreamer, LineTableBegin, LineTableEnd);
+ Asm->OutStreamer->EmitLabel(LineTableBegin);
+
+ // Identify the function this subsection is for.
+ Asm->OutStreamer->EmitCOFFSecRel32(Fn);
+ Asm->OutStreamer->EmitCOFFSectionIndex(Fn);
+ // Insert flags after a 16-bit section index.
+ Asm->EmitInt16(COFF::DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS);
+
+ // Length of the function's code, in bytes.
+ EmitLabelDiff(*Asm->OutStreamer, Fn, FI.End);
+
+ // PC-to-linenumber lookup table:
+ MCSymbol *FileSegmentEnd = nullptr;
+
+ // The start of the last segment:
+ size_t LastSegmentStart = 0;
+
+ auto FinishPreviousChunk = [&] {
+ if (!FileSegmentEnd)
+ return;
+ for (size_t ColSegI = LastSegmentStart,
+ ColSegEnd = ColSegI + FilenameSegmentLengths[LastSegmentStart];
+ ColSegI != ColSegEnd; ++ColSegI) {
+ unsigned ColumnNumber = InstrInfo[FI.Instrs[ColSegI]].ColumnNumber;
+ Asm->EmitInt16(ColumnNumber); // Start column
+ Asm->EmitInt16(ColumnNumber); // End column
+ }
+ Asm->OutStreamer->EmitLabel(FileSegmentEnd);
+ };
+
+ for (size_t J = 0, F = FI.Instrs.size(); J != F; ++J) {
+ MCSymbol *Instr = FI.Instrs[J];
+ assert(InstrInfo.count(Instr));
+
+ if (FilenameSegmentLengths.count(J)) {
+ // We came to a beginning of a new filename segment.
+ FinishPreviousChunk();
+ StringRef CurFilename = InstrInfo[FI.Instrs[J]].Filename;
+ assert(FileNameRegistry.Infos.count(CurFilename));
+ size_t IndexInStringTable =
+ FileNameRegistry.Infos[CurFilename].FilenameID;
+ // Each segment starts with the offset of the filename
+ // in the string table.
+ Asm->OutStreamer->AddComment(
+ "Segment for file '" + Twine(CurFilename) + "' begins");
+ MCSymbol *FileSegmentBegin = Asm->MMI->getContext().createTempSymbol();
+ Asm->OutStreamer->EmitLabel(FileSegmentBegin);
+ Asm->EmitInt32(8 * IndexInStringTable);
+
+ // Number of PC records in the lookup table.
+ size_t SegmentLength = FilenameSegmentLengths[J];
+ Asm->EmitInt32(SegmentLength);
+
+ // Full size of the segment for this filename, including the prev two
+ // records.
+ FileSegmentEnd = Asm->MMI->getContext().createTempSymbol();
+ EmitLabelDiff(*Asm->OutStreamer, FileSegmentBegin, FileSegmentEnd);
+ LastSegmentStart = J;
+ }
+
+ // The first PC with the given linenumber and the linenumber itself.
+ EmitLabelDiff(*Asm->OutStreamer, Fn, Instr);
+ Asm->EmitInt32(InstrInfo[Instr].LineNumber);
+ }
+
+ FinishPreviousChunk();
+ Asm->OutStreamer->EmitLabel(LineTableEnd);
+}
+
+void WinCodeViewLineTables::beginFunction(const MachineFunction *MF) {
+ assert(!CurFn && "Can't process two functions at once!");
+
+ if (!Asm || !Asm->MMI->hasDebugInfo())
+ return;
+
+ const Function *GV = MF->getFunction();
+ assert(FnDebugInfo.count(GV) == false);
+ VisitedFunctions.push_back(GV);
+ CurFn = &FnDebugInfo[GV];
+
+ // Find the end of the function prolog.
+ // FIXME: is there a simpler a way to do this? Can we just search
+ // for the first instruction of the function, not the last of the prolog?
+ DebugLoc PrologEndLoc;
+ bool EmptyPrologue = true;
+ for (const auto &MBB : *MF) {
+ if (PrologEndLoc)
+ break;
+ for (const auto &MI : MBB) {
+ if (MI.isDebugValue())
+ continue;
+
+ // First known non-DBG_VALUE and non-frame setup location marks
+ // the beginning of the function body.
+ // FIXME: do we need the first subcondition?
+ if (!MI.getFlag(MachineInstr::FrameSetup) && MI.getDebugLoc()) {
+ PrologEndLoc = MI.getDebugLoc();
+ break;
+ }
+ EmptyPrologue = false;
+ }
+ }
+ // Record beginning of function if we have a non-empty prologue.
+ if (PrologEndLoc && !EmptyPrologue) {
+ DebugLoc FnStartDL = PrologEndLoc.getFnDebugLoc();
+ maybeRecordLocation(FnStartDL, MF);
+ }
+}
+
+void WinCodeViewLineTables::endFunction(const MachineFunction *MF) {
+ if (!Asm || !CurFn) // We haven't created any debug info for this function.
+ return;
+
+ const Function *GV = MF->getFunction();
+ assert(FnDebugInfo.count(GV));
+ assert(CurFn == &FnDebugInfo[GV]);
+
+ if (CurFn->Instrs.empty()) {
+ FnDebugInfo.erase(GV);
+ VisitedFunctions.pop_back();
+ } else {
+ CurFn->End = Asm->getFunctionEnd();
+ }
+ CurFn = nullptr;
+}
+
+void WinCodeViewLineTables::beginInstruction(const MachineInstr *MI) {
+ // Ignore DBG_VALUE locations and function prologue.
+ if (!Asm || MI->isDebugValue() || MI->getFlag(MachineInstr::FrameSetup))
+ return;
+ DebugLoc DL = MI->getDebugLoc();
+ if (DL == PrevInstLoc || !DL)
+ return;
+ maybeRecordLocation(DL, Asm->MF);
+}
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h b/contrib/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h
new file mode 100644
index 0000000..78068e0
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h
@@ -0,0 +1,138 @@
+//===-- llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.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 support for writing line tables info into COFF files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_WINCODEVIEWLINETABLES_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_WINCODEVIEWLINETABLES_H
+
+#include "AsmPrinterHandler.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/LexicalScopes.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+
+namespace llvm {
+/// \brief Collects and handles line tables information in a CodeView format.
+class LLVM_LIBRARY_VISIBILITY WinCodeViewLineTables : public AsmPrinterHandler {
+ AsmPrinter *Asm;
+ DebugLoc PrevInstLoc;
+
+ // For each function, store a vector of labels to its instructions, as well as
+ // to the end of the function.
+ struct FunctionInfo {
+ SmallVector<MCSymbol *, 10> Instrs;
+ MCSymbol *End;
+ FunctionInfo() : End(nullptr) {}
+ } *CurFn;
+
+ typedef DenseMap<const Function *, FunctionInfo> FnDebugInfoTy;
+ FnDebugInfoTy FnDebugInfo;
+ // Store the functions we've visited in a vector so we can maintain a stable
+ // order while emitting subsections.
+ SmallVector<const Function *, 10> VisitedFunctions;
+
+ // InstrInfoTy - Holds the Filename:LineNumber information for every
+ // instruction with a unique debug location.
+ struct InstrInfoTy {
+ StringRef Filename;
+ unsigned LineNumber;
+ unsigned ColumnNumber;
+
+ InstrInfoTy() : LineNumber(0), ColumnNumber(0) {}
+
+ InstrInfoTy(StringRef Filename, unsigned LineNumber, unsigned ColumnNumber)
+ : Filename(Filename), LineNumber(LineNumber),
+ ColumnNumber(ColumnNumber) {}
+ };
+ DenseMap<MCSymbol *, InstrInfoTy> InstrInfo;
+
+ // FileNameRegistry - Manages filenames observed while generating debug info
+ // by filtering out duplicates and bookkeeping the offsets in the string
+ // table to be generated.
+ struct FileNameRegistryTy {
+ SmallVector<StringRef, 10> Filenames;
+ struct PerFileInfo {
+ size_t FilenameID, StartOffset;
+ };
+ StringMap<PerFileInfo> Infos;
+
+ // The offset in the string table where we'll write the next unique
+ // filename.
+ size_t LastOffset;
+
+ FileNameRegistryTy() {
+ clear();
+ }
+
+ // Add Filename to the registry, if it was not observed before.
+ void add(StringRef Filename) {
+ if (Infos.count(Filename))
+ return;
+ size_t OldSize = Infos.size();
+ Infos[Filename].FilenameID = OldSize;
+ Infos[Filename].StartOffset = LastOffset;
+ LastOffset += Filename.size() + 1;
+ Filenames.push_back(Filename);
+ }
+
+ void clear() {
+ LastOffset = 1;
+ Infos.clear();
+ Filenames.clear();
+ }
+ } FileNameRegistry;
+
+ typedef std::map<std::pair<StringRef, StringRef>, std::string>
+ DirAndFilenameToFilepathMapTy;
+ DirAndFilenameToFilepathMapTy DirAndFilenameToFilepathMap;
+ StringRef getFullFilepath(const MDNode *S);
+
+ void maybeRecordLocation(DebugLoc DL, const MachineFunction *MF);
+
+ void clear() {
+ assert(CurFn == nullptr);
+ FileNameRegistry.clear();
+ InstrInfo.clear();
+ }
+
+ void emitDebugInfoForFunction(const Function *GV);
+
+public:
+ WinCodeViewLineTables(AsmPrinter *Asm);
+
+ void setSymbolSize(const llvm::MCSymbol *, uint64_t) override {}
+
+ /// \brief Emit the COFF section that holds the line table information.
+ void endModule() override;
+
+ /// \brief Gather pre-function debug information.
+ void beginFunction(const MachineFunction *MF) override;
+
+ /// \brief Gather post-function debug information.
+ void endFunction(const MachineFunction *) override;
+
+ /// \brief Process beginning of an instruction.
+ void beginInstruction(const MachineInstr *MI) override;
+
+ /// \brief Process end of an instruction.
+ void endInstruction() override {}
+};
+} // End of namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
new file mode 100644
index 0000000..48b7104
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
@@ -0,0 +1,1236 @@
+//===-- CodeGen/AsmPrinter/WinException.cpp - Dwarf 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 Win64 exception info into asm files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "WinException.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/WinEHFuncInfo.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Mangler.h"
+#include "llvm/IR/Module.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCWin64EH.h"
+#include "llvm/Support/COFF.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Target/TargetFrameLowering.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+using namespace llvm;
+
+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);
+}
+
+WinException::~WinException() {}
+
+/// endModule - Emit all exception information that should come after the
+/// content.
+void WinException::endModule() {
+ auto &OS = *Asm->OutStreamer;
+ const Module *M = MMI->getModule();
+ for (const Function &F : *M)
+ if (F.hasFnAttribute("safeseh"))
+ OS.EmitCOFFSafeSEH(Asm->getSymbol(&F));
+}
+
+void WinException::beginFunction(const MachineFunction *MF) {
+ shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false;
+
+ // If any landing pads survive, we need an EH table.
+ bool hasLandingPads = !MMI->getLandingPads().empty();
+ bool hasEHFunclets = MMI->hasEHFunclets();
+
+ const Function *F = MF->getFunction();
+
+ shouldEmitMoves = Asm->needsSEHMoves();
+
+ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
+ unsigned PerEncoding = TLOF.getPersonalityEncoding();
+ const Function *Per = nullptr;
+ if (F->hasPersonalityFn())
+ Per = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
+
+ bool forceEmitPersonality =
+ F->hasPersonalityFn() && !isNoOpWithoutInvoke(classifyEHPersonality(Per)) &&
+ F->needsUnwindTableEntry();
+
+ shouldEmitPersonality =
+ forceEmitPersonality || ((hasLandingPads || hasEHFunclets) &&
+ PerEncoding != dwarf::DW_EH_PE_omit && Per);
+
+ unsigned LSDAEncoding = TLOF.getLSDAEncoding();
+ shouldEmitLSDA = shouldEmitPersonality &&
+ LSDAEncoding != dwarf::DW_EH_PE_omit;
+
+ // If we're not using CFI, we don't want the CFI or the personality, but we
+ // might want EH tables if we had EH pads.
+ if (!Asm->MAI->usesWindowsCFI()) {
+ shouldEmitLSDA = hasEHFunclets;
+ shouldEmitPersonality = false;
+ return;
+ }
+
+ beginFunclet(MF->front(), Asm->CurrentFnSym);
+}
+
+/// endFunction - Gather and emit post-function exception information.
+///
+void WinException::endFunction(const MachineFunction *MF) {
+ if (!shouldEmitPersonality && !shouldEmitMoves && !shouldEmitLSDA)
+ return;
+
+ const Function *F = MF->getFunction();
+ EHPersonality Per = EHPersonality::Unknown;
+ if (F->hasPersonalityFn())
+ Per = classifyEHPersonality(F->getPersonalityFn());
+
+ // Get rid of any dead landing pads if we're not using funclets. In funclet
+ // schemes, the landing pad is not actually reachable. It only exists so
+ // that we can emit the right table data.
+ if (!isFuncletEHPersonality(Per))
+ MMI->TidyLandingPads();
+
+ endFunclet();
+
+ // endFunclet will emit the necessary .xdata tables for x64 SEH.
+ if (Per == EHPersonality::MSVC_Win64SEH && MMI->hasEHFunclets())
+ return;
+
+ if (shouldEmitPersonality || shouldEmitLSDA) {
+ Asm->OutStreamer->PushSection();
+
+ // Just switch sections to the right xdata section. This use of CurrentFnSym
+ // assumes that we only emit the LSDA when ending the parent function.
+ MCSection *XData = WinEH::UnwindEmitter::getXDataSection(Asm->CurrentFnSym,
+ Asm->OutContext);
+ Asm->OutStreamer->SwitchSection(XData);
+
+ // Emit the tables appropriate to the personality function in use. If we
+ // don't recognize the personality, assume it uses an Itanium-style LSDA.
+ if (Per == EHPersonality::MSVC_Win64SEH)
+ emitCSpecificHandlerTable(MF);
+ else if (Per == EHPersonality::MSVC_X86SEH)
+ emitExceptHandlerTable(MF);
+ else if (Per == EHPersonality::MSVC_CXX)
+ emitCXXFrameHandler3Table(MF);
+ else if (Per == EHPersonality::CoreCLR)
+ emitCLRExceptionTable(MF);
+ else
+ emitExceptionTable();
+
+ Asm->OutStreamer->PopSection();
+ }
+}
+
+/// Retreive the MCSymbol for a GlobalValue or MachineBasicBlock.
+static MCSymbol *getMCSymbolForMBB(AsmPrinter *Asm,
+ const MachineBasicBlock *MBB) {
+ if (!MBB)
+ return nullptr;
+
+ assert(MBB->isEHFuncletEntry());
+
+ // Give catches and cleanups a name based off of their parent function and
+ // their funclet entry block's number.
+ const MachineFunction *MF = MBB->getParent();
+ const Function *F = MF->getFunction();
+ StringRef FuncLinkageName = GlobalValue::getRealLinkageName(F->getName());
+ MCContext &Ctx = MF->getContext();
+ StringRef HandlerPrefix = MBB->isCleanupFuncletEntry() ? "dtor" : "catch";
+ return Ctx.getOrCreateSymbol("?" + HandlerPrefix + "$" +
+ Twine(MBB->getNumber()) + "@?0?" +
+ FuncLinkageName + "@4HA");
+}
+
+void WinException::beginFunclet(const MachineBasicBlock &MBB,
+ MCSymbol *Sym) {
+ CurrentFuncletEntry = &MBB;
+
+ const Function *F = Asm->MF->getFunction();
+ // If a symbol was not provided for the funclet, invent one.
+ if (!Sym) {
+ Sym = getMCSymbolForMBB(Asm, &MBB);
+
+ // Describe our funclet symbol as a function with internal linkage.
+ Asm->OutStreamer->BeginCOFFSymbolDef(Sym);
+ Asm->OutStreamer->EmitCOFFSymbolStorageClass(COFF::IMAGE_SYM_CLASS_STATIC);
+ Asm->OutStreamer->EmitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_FUNCTION
+ << COFF::SCT_COMPLEX_TYPE_SHIFT);
+ Asm->OutStreamer->EndCOFFSymbolDef();
+
+ // We want our funclet's entry point to be aligned such that no nops will be
+ // present after the label.
+ Asm->EmitAlignment(std::max(Asm->MF->getAlignment(), MBB.getAlignment()),
+ F);
+
+ // Now that we've emitted the alignment directive, point at our funclet.
+ Asm->OutStreamer->EmitLabel(Sym);
+ }
+
+ // Mark 'Sym' as starting our funclet.
+ if (shouldEmitMoves || shouldEmitPersonality)
+ Asm->OutStreamer->EmitWinCFIStartProc(Sym);
+
+ if (shouldEmitPersonality) {
+ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
+ const Function *PerFn = nullptr;
+
+ // Determine which personality routine we are using for this funclet.
+ if (F->hasPersonalityFn())
+ PerFn = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
+ const MCSymbol *PersHandlerSym =
+ TLOF.getCFIPersonalitySymbol(PerFn, *Asm->Mang, Asm->TM, MMI);
+
+ // Classify the personality routine so that we may reason about it.
+ EHPersonality Per = EHPersonality::Unknown;
+ if (F->hasPersonalityFn())
+ Per = classifyEHPersonality(F->getPersonalityFn());
+
+ // Do not emit a .seh_handler directive if it is a C++ cleanup funclet.
+ if (Per != EHPersonality::MSVC_CXX ||
+ !CurrentFuncletEntry->isCleanupFuncletEntry())
+ Asm->OutStreamer->EmitWinEHHandler(PersHandlerSym, true, true);
+ }
+}
+
+void WinException::endFunclet() {
+ // No funclet to process? Great, we have nothing to do.
+ if (!CurrentFuncletEntry)
+ return;
+
+ if (shouldEmitMoves || shouldEmitPersonality) {
+ const Function *F = Asm->MF->getFunction();
+ EHPersonality Per = EHPersonality::Unknown;
+ if (F->hasPersonalityFn())
+ Per = classifyEHPersonality(F->getPersonalityFn());
+
+ // The .seh_handlerdata directive implicitly switches section, push the
+ // current section so that we may return to it.
+ Asm->OutStreamer->PushSection();
+
+ // Emit an UNWIND_INFO struct describing the prologue.
+ Asm->OutStreamer->EmitWinEHHandlerData();
+
+ if (Per == EHPersonality::MSVC_CXX && shouldEmitPersonality &&
+ !CurrentFuncletEntry->isCleanupFuncletEntry()) {
+ // If this is a C++ catch funclet (or the parent function),
+ // emit a reference to the LSDA for the parent function.
+ StringRef FuncLinkageName = GlobalValue::getRealLinkageName(F->getName());
+ MCSymbol *FuncInfoXData = Asm->OutContext.getOrCreateSymbol(
+ Twine("$cppxdata$", FuncLinkageName));
+ Asm->OutStreamer->EmitValue(create32bitRef(FuncInfoXData), 4);
+ } else if (Per == EHPersonality::MSVC_Win64SEH && MMI->hasEHFunclets() &&
+ !CurrentFuncletEntry->isEHFuncletEntry()) {
+ // If this is the parent function in Win64 SEH, emit the LSDA immediately
+ // following .seh_handlerdata.
+ emitCSpecificHandlerTable(Asm->MF);
+ }
+
+ // Switch back to the previous section now that we are done writing to
+ // .xdata.
+ Asm->OutStreamer->PopSection();
+
+ // Emit a .seh_endproc directive to mark the end of the function.
+ Asm->OutStreamer->EmitWinCFIEndProc();
+ }
+
+ // Let's make sure we don't try to end the same funclet twice.
+ CurrentFuncletEntry = nullptr;
+}
+
+const MCExpr *WinException::create32bitRef(const MCSymbol *Value) {
+ if (!Value)
+ return MCConstantExpr::create(0, Asm->OutContext);
+ return MCSymbolRefExpr::create(Value, useImageRel32
+ ? MCSymbolRefExpr::VK_COFF_IMGREL32
+ : MCSymbolRefExpr::VK_None,
+ Asm->OutContext);
+}
+
+const MCExpr *WinException::create32bitRef(const GlobalValue *GV) {
+ if (!GV)
+ return MCConstantExpr::create(0, Asm->OutContext);
+ return create32bitRef(Asm->getSymbol(GV));
+}
+
+const MCExpr *WinException::getLabelPlusOne(const MCSymbol *Label) {
+ return MCBinaryExpr::createAdd(create32bitRef(Label),
+ MCConstantExpr::create(1, Asm->OutContext),
+ Asm->OutContext);
+}
+
+const MCExpr *WinException::getOffset(const MCSymbol *OffsetOf,
+ const MCSymbol *OffsetFrom) {
+ return MCBinaryExpr::createSub(
+ MCSymbolRefExpr::create(OffsetOf, Asm->OutContext),
+ MCSymbolRefExpr::create(OffsetFrom, Asm->OutContext), Asm->OutContext);
+}
+
+const MCExpr *WinException::getOffsetPlusOne(const MCSymbol *OffsetOf,
+ const MCSymbol *OffsetFrom) {
+ return MCBinaryExpr::createAdd(getOffset(OffsetOf, OffsetFrom),
+ MCConstantExpr::create(1, Asm->OutContext),
+ Asm->OutContext);
+}
+
+int WinException::getFrameIndexOffset(int FrameIndex,
+ const WinEHFuncInfo &FuncInfo) {
+ const TargetFrameLowering &TFI = *Asm->MF->getSubtarget().getFrameLowering();
+ unsigned UnusedReg;
+ if (Asm->MAI->usesWindowsCFI())
+ return TFI.getFrameIndexReferenceFromSP(*Asm->MF, FrameIndex, UnusedReg);
+ // For 32-bit, offsets should be relative to the end of the EH registration
+ // node. For 64-bit, it's relative to SP at the end of the prologue.
+ assert(FuncInfo.EHRegNodeEndOffset != INT_MAX);
+ int Offset = TFI.getFrameIndexReference(*Asm->MF, FrameIndex, UnusedReg);
+ Offset += FuncInfo.EHRegNodeEndOffset;
+ return Offset;
+}
+
+namespace {
+
+/// Top-level state used to represent unwind to caller
+const int NullState = -1;
+
+struct InvokeStateChange {
+ /// EH Label immediately after the last invoke in the previous state, or
+ /// nullptr if the previous state was the null state.
+ const MCSymbol *PreviousEndLabel;
+
+ /// EH label immediately before the first invoke in the new state, or nullptr
+ /// if the new state is the null state.
+ const MCSymbol *NewStartLabel;
+
+ /// State of the invoke following NewStartLabel, or NullState to indicate
+ /// the presence of calls which may unwind to caller.
+ int NewState;
+};
+
+/// Iterator that reports all the invoke state changes in a range of machine
+/// basic blocks. Changes to the null state are reported whenever a call that
+/// may unwind to caller is encountered. The MBB range is expected to be an
+/// entire function or funclet, and the start and end of the range are treated
+/// as being in the NullState even if there's not an unwind-to-caller call
+/// before the first invoke or after the last one (i.e., the first state change
+/// reported is the first change to something other than NullState, and a
+/// change back to NullState is always reported at the end of iteration).
+class InvokeStateChangeIterator {
+ InvokeStateChangeIterator(const WinEHFuncInfo &EHInfo,
+ MachineFunction::const_iterator MFI,
+ MachineFunction::const_iterator MFE,
+ MachineBasicBlock::const_iterator MBBI,
+ int BaseState)
+ : EHInfo(EHInfo), MFI(MFI), MFE(MFE), MBBI(MBBI), BaseState(BaseState) {
+ LastStateChange.PreviousEndLabel = nullptr;
+ LastStateChange.NewStartLabel = nullptr;
+ LastStateChange.NewState = BaseState;
+ scan();
+ }
+
+public:
+ static iterator_range<InvokeStateChangeIterator>
+ range(const WinEHFuncInfo &EHInfo, MachineFunction::const_iterator Begin,
+ MachineFunction::const_iterator End, int BaseState = NullState) {
+ // Reject empty ranges to simplify bookkeeping by ensuring that we can get
+ // the end of the last block.
+ assert(Begin != End);
+ auto BlockBegin = Begin->begin();
+ auto BlockEnd = std::prev(End)->end();
+ return make_range(
+ InvokeStateChangeIterator(EHInfo, Begin, End, BlockBegin, BaseState),
+ InvokeStateChangeIterator(EHInfo, End, End, BlockEnd, BaseState));
+ }
+
+ // Iterator methods.
+ bool operator==(const InvokeStateChangeIterator &O) const {
+ assert(BaseState == O.BaseState);
+ // Must be visiting same block.
+ if (MFI != O.MFI)
+ return false;
+ // Must be visiting same isntr.
+ if (MBBI != O.MBBI)
+ return false;
+ // At end of block/instr iteration, we can still have two distinct states:
+ // one to report the final EndLabel, and another indicating the end of the
+ // state change iteration. Check for CurrentEndLabel equality to
+ // distinguish these.
+ return CurrentEndLabel == O.CurrentEndLabel;
+ }
+
+ bool operator!=(const InvokeStateChangeIterator &O) const {
+ return !operator==(O);
+ }
+ InvokeStateChange &operator*() { return LastStateChange; }
+ InvokeStateChange *operator->() { return &LastStateChange; }
+ InvokeStateChangeIterator &operator++() { return scan(); }
+
+private:
+ InvokeStateChangeIterator &scan();
+
+ const WinEHFuncInfo &EHInfo;
+ const MCSymbol *CurrentEndLabel = nullptr;
+ MachineFunction::const_iterator MFI;
+ MachineFunction::const_iterator MFE;
+ MachineBasicBlock::const_iterator MBBI;
+ InvokeStateChange LastStateChange;
+ bool VisitingInvoke = false;
+ int BaseState;
+};
+
+} // end anonymous namespace
+
+InvokeStateChangeIterator &InvokeStateChangeIterator::scan() {
+ bool IsNewBlock = false;
+ for (; MFI != MFE; ++MFI, IsNewBlock = true) {
+ if (IsNewBlock)
+ MBBI = MFI->begin();
+ for (auto MBBE = MFI->end(); MBBI != MBBE; ++MBBI) {
+ const MachineInstr &MI = *MBBI;
+ if (!VisitingInvoke && LastStateChange.NewState != BaseState &&
+ MI.isCall() && !EHStreamer::callToNoUnwindFunction(&MI)) {
+ // Indicate a change of state to the null state. We don't have
+ // start/end EH labels handy but the caller won't expect them for
+ // null state regions.
+ LastStateChange.PreviousEndLabel = CurrentEndLabel;
+ LastStateChange.NewStartLabel = nullptr;
+ LastStateChange.NewState = BaseState;
+ CurrentEndLabel = nullptr;
+ // Don't re-visit this instr on the next scan
+ ++MBBI;
+ return *this;
+ }
+
+ // All other state changes are at EH labels before/after invokes.
+ if (!MI.isEHLabel())
+ continue;
+ MCSymbol *Label = MI.getOperand(0).getMCSymbol();
+ if (Label == CurrentEndLabel) {
+ VisitingInvoke = false;
+ continue;
+ }
+ auto InvokeMapIter = EHInfo.LabelToStateMap.find(Label);
+ // Ignore EH labels that aren't the ones inserted before an invoke
+ if (InvokeMapIter == EHInfo.LabelToStateMap.end())
+ continue;
+ auto &StateAndEnd = InvokeMapIter->second;
+ int NewState = StateAndEnd.first;
+ // Keep track of the fact that we're between EH start/end labels so
+ // we know not to treat the inoke we'll see as unwinding to caller.
+ VisitingInvoke = true;
+ if (NewState == LastStateChange.NewState) {
+ // The state isn't actually changing here. Record the new end and
+ // keep going.
+ CurrentEndLabel = StateAndEnd.second;
+ continue;
+ }
+ // Found a state change to report
+ LastStateChange.PreviousEndLabel = CurrentEndLabel;
+ LastStateChange.NewStartLabel = Label;
+ LastStateChange.NewState = NewState;
+ // Start keeping track of the new current end
+ CurrentEndLabel = StateAndEnd.second;
+ // Don't re-visit this instr on the next scan
+ ++MBBI;
+ return *this;
+ }
+ }
+ // Iteration hit the end of the block range.
+ if (LastStateChange.NewState != BaseState) {
+ // Report the end of the last new state
+ LastStateChange.PreviousEndLabel = CurrentEndLabel;
+ LastStateChange.NewStartLabel = nullptr;
+ LastStateChange.NewState = BaseState;
+ // Leave CurrentEndLabel non-null to distinguish this state from end.
+ assert(CurrentEndLabel != nullptr);
+ return *this;
+ }
+ // We've reported all state changes and hit the end state.
+ CurrentEndLabel = nullptr;
+ return *this;
+}
+
+/// Emit the language-specific data that __C_specific_handler expects. This
+/// handler lives in the x64 Microsoft C runtime and allows catching or cleaning
+/// up after faults with __try, __except, and __finally. The typeinfo values
+/// are not really RTTI data, but pointers to filter functions that return an
+/// integer (1, 0, or -1) indicating how to handle the exception. For __finally
+/// blocks and other cleanups, the landing pad label is zero, and the filter
+/// function is actually a cleanup handler with the same prototype. A catch-all
+/// entry is modeled with a null filter function field and a non-zero landing
+/// pad label.
+///
+/// Possible filter function return values:
+/// EXCEPTION_EXECUTE_HANDLER (1):
+/// Jump to the landing pad label after cleanups.
+/// EXCEPTION_CONTINUE_SEARCH (0):
+/// Continue searching this table or continue unwinding.
+/// EXCEPTION_CONTINUE_EXECUTION (-1):
+/// Resume execution at the trapping PC.
+///
+/// Inferred table structure:
+/// struct Table {
+/// int NumEntries;
+/// struct Entry {
+/// imagerel32 LabelStart;
+/// imagerel32 LabelEnd;
+/// imagerel32 FilterOrFinally; // One means catch-all.
+/// imagerel32 LabelLPad; // Zero means __finally.
+/// } Entries[NumEntries];
+/// };
+void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) {
+ auto &OS = *Asm->OutStreamer;
+ MCContext &Ctx = Asm->OutContext;
+ const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
+
+ bool VerboseAsm = OS.isVerboseAsm();
+ auto AddComment = [&](const Twine &Comment) {
+ if (VerboseAsm)
+ OS.AddComment(Comment);
+ };
+
+ // Emit a label assignment with the SEH frame offset so we can use it for
+ // llvm.x86.seh.recoverfp.
+ StringRef FLinkageName =
+ GlobalValue::getRealLinkageName(MF->getFunction()->getName());
+ MCSymbol *ParentFrameOffset =
+ Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName);
+ const MCExpr *MCOffset =
+ MCConstantExpr::create(FuncInfo.SEHSetFrameOffset, Ctx);
+ Asm->OutStreamer->EmitAssignment(ParentFrameOffset, MCOffset);
+
+ // Use the assembler to compute the number of table entries through label
+ // difference and division.
+ MCSymbol *TableBegin =
+ Ctx.createTempSymbol("lsda_begin", /*AlwaysAddSuffix=*/true);
+ MCSymbol *TableEnd =
+ Ctx.createTempSymbol("lsda_end", /*AlwaysAddSuffix=*/true);
+ const MCExpr *LabelDiff = getOffset(TableEnd, TableBegin);
+ const MCExpr *EntrySize = MCConstantExpr::create(16, Ctx);
+ const MCExpr *EntryCount = MCBinaryExpr::createDiv(LabelDiff, EntrySize, Ctx);
+ AddComment("Number of call sites");
+ OS.EmitValue(EntryCount, 4);
+
+ OS.EmitLabel(TableBegin);
+
+ // Iterate over all the invoke try ranges. Unlike MSVC, LLVM currently only
+ // models exceptions from invokes. LLVM also allows arbitrary reordering of
+ // the code, so our tables end up looking a bit different. Rather than
+ // trying to match MSVC's tables exactly, we emit a denormalized table. For
+ // each range of invokes in the same state, we emit table entries for all
+ // the actions that would be taken in that state. This means our tables are
+ // slightly bigger, which is OK.
+ const MCSymbol *LastStartLabel = nullptr;
+ int LastEHState = -1;
+ // Break out before we enter into a finally funclet.
+ // FIXME: We need to emit separate EH tables for cleanups.
+ MachineFunction::const_iterator End = MF->end();
+ MachineFunction::const_iterator Stop = std::next(MF->begin());
+ while (Stop != End && !Stop->isEHFuncletEntry())
+ ++Stop;
+ for (const auto &StateChange :
+ InvokeStateChangeIterator::range(FuncInfo, MF->begin(), Stop)) {
+ // Emit all the actions for the state we just transitioned out of
+ // if it was not the null state
+ if (LastEHState != -1)
+ emitSEHActionsForRange(FuncInfo, LastStartLabel,
+ StateChange.PreviousEndLabel, LastEHState);
+ LastStartLabel = StateChange.NewStartLabel;
+ LastEHState = StateChange.NewState;
+ }
+
+ OS.EmitLabel(TableEnd);
+}
+
+void WinException::emitSEHActionsForRange(const WinEHFuncInfo &FuncInfo,
+ const MCSymbol *BeginLabel,
+ const MCSymbol *EndLabel, int State) {
+ auto &OS = *Asm->OutStreamer;
+ MCContext &Ctx = Asm->OutContext;
+
+ bool VerboseAsm = OS.isVerboseAsm();
+ auto AddComment = [&](const Twine &Comment) {
+ if (VerboseAsm)
+ OS.AddComment(Comment);
+ };
+
+ assert(BeginLabel && EndLabel);
+ while (State != -1) {
+ const SEHUnwindMapEntry &UME = FuncInfo.SEHUnwindMap[State];
+ const MCExpr *FilterOrFinally;
+ const MCExpr *ExceptOrNull;
+ auto *Handler = UME.Handler.get<MachineBasicBlock *>();
+ if (UME.IsFinally) {
+ FilterOrFinally = create32bitRef(getMCSymbolForMBB(Asm, Handler));
+ ExceptOrNull = MCConstantExpr::create(0, Ctx);
+ } else {
+ // For an except, the filter can be 1 (catch-all) or a function
+ // label.
+ FilterOrFinally = UME.Filter ? create32bitRef(UME.Filter)
+ : MCConstantExpr::create(1, Ctx);
+ ExceptOrNull = create32bitRef(Handler->getSymbol());
+ }
+
+ AddComment("LabelStart");
+ OS.EmitValue(getLabelPlusOne(BeginLabel), 4);
+ AddComment("LabelEnd");
+ OS.EmitValue(getLabelPlusOne(EndLabel), 4);
+ AddComment(UME.IsFinally ? "FinallyFunclet" : UME.Filter ? "FilterFunction"
+ : "CatchAll");
+ OS.EmitValue(FilterOrFinally, 4);
+ AddComment(UME.IsFinally ? "Null" : "ExceptionHandler");
+ OS.EmitValue(ExceptOrNull, 4);
+
+ assert(UME.ToState < State && "states should decrease");
+ State = UME.ToState;
+ }
+}
+
+void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
+ const Function *F = MF->getFunction();
+ auto &OS = *Asm->OutStreamer;
+ const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
+
+ StringRef FuncLinkageName = GlobalValue::getRealLinkageName(F->getName());
+
+ SmallVector<std::pair<const MCExpr *, int>, 4> IPToStateTable;
+ MCSymbol *FuncInfoXData = nullptr;
+ if (shouldEmitPersonality) {
+ // If we're 64-bit, emit a pointer to the C++ EH data, and build a map from
+ // IPs to state numbers.
+ FuncInfoXData =
+ Asm->OutContext.getOrCreateSymbol(Twine("$cppxdata$", FuncLinkageName));
+ computeIP2StateTable(MF, FuncInfo, IPToStateTable);
+ } else {
+ FuncInfoXData = Asm->OutContext.getOrCreateLSDASymbol(FuncLinkageName);
+ }
+
+ int UnwindHelpOffset = 0;
+ if (Asm->MAI->usesWindowsCFI())
+ UnwindHelpOffset =
+ getFrameIndexOffset(FuncInfo.UnwindHelpFrameIdx, FuncInfo);
+
+ MCSymbol *UnwindMapXData = nullptr;
+ MCSymbol *TryBlockMapXData = nullptr;
+ MCSymbol *IPToStateXData = nullptr;
+ if (!FuncInfo.CxxUnwindMap.empty())
+ UnwindMapXData = Asm->OutContext.getOrCreateSymbol(
+ Twine("$stateUnwindMap$", FuncLinkageName));
+ if (!FuncInfo.TryBlockMap.empty())
+ TryBlockMapXData =
+ Asm->OutContext.getOrCreateSymbol(Twine("$tryMap$", FuncLinkageName));
+ if (!IPToStateTable.empty())
+ IPToStateXData =
+ Asm->OutContext.getOrCreateSymbol(Twine("$ip2state$", FuncLinkageName));
+
+ bool VerboseAsm = OS.isVerboseAsm();
+ auto AddComment = [&](const Twine &Comment) {
+ if (VerboseAsm)
+ OS.AddComment(Comment);
+ };
+
+ // FuncInfo {
+ // uint32_t MagicNumber
+ // int32_t MaxState;
+ // UnwindMapEntry *UnwindMap;
+ // uint32_t NumTryBlocks;
+ // TryBlockMapEntry *TryBlockMap;
+ // uint32_t IPMapEntries; // always 0 for x86
+ // IPToStateMapEntry *IPToStateMap; // always 0 for x86
+ // uint32_t UnwindHelp; // non-x86 only
+ // ESTypeList *ESTypeList;
+ // int32_t EHFlags;
+ // }
+ // EHFlags & 1 -> Synchronous exceptions only, no async exceptions.
+ // EHFlags & 2 -> ???
+ // EHFlags & 4 -> The function is noexcept(true), unwinding can't continue.
+ OS.EmitValueToAlignment(4);
+ OS.EmitLabel(FuncInfoXData);
+
+ AddComment("MagicNumber");
+ OS.EmitIntValue(0x19930522, 4);
+
+ AddComment("MaxState");
+ OS.EmitIntValue(FuncInfo.CxxUnwindMap.size(), 4);
+
+ AddComment("UnwindMap");
+ OS.EmitValue(create32bitRef(UnwindMapXData), 4);
+
+ AddComment("NumTryBlocks");
+ OS.EmitIntValue(FuncInfo.TryBlockMap.size(), 4);
+
+ AddComment("TryBlockMap");
+ OS.EmitValue(create32bitRef(TryBlockMapXData), 4);
+
+ AddComment("IPMapEntries");
+ OS.EmitIntValue(IPToStateTable.size(), 4);
+
+ AddComment("IPToStateXData");
+ OS.EmitValue(create32bitRef(IPToStateXData), 4);
+
+ if (Asm->MAI->usesWindowsCFI()) {
+ AddComment("UnwindHelp");
+ OS.EmitIntValue(UnwindHelpOffset, 4);
+ }
+
+ AddComment("ESTypeList");
+ OS.EmitIntValue(0, 4);
+
+ AddComment("EHFlags");
+ OS.EmitIntValue(1, 4);
+
+ // UnwindMapEntry {
+ // int32_t ToState;
+ // void (*Action)();
+ // };
+ if (UnwindMapXData) {
+ OS.EmitLabel(UnwindMapXData);
+ for (const CxxUnwindMapEntry &UME : FuncInfo.CxxUnwindMap) {
+ MCSymbol *CleanupSym =
+ getMCSymbolForMBB(Asm, UME.Cleanup.dyn_cast<MachineBasicBlock *>());
+ AddComment("ToState");
+ OS.EmitIntValue(UME.ToState, 4);
+
+ AddComment("Action");
+ OS.EmitValue(create32bitRef(CleanupSym), 4);
+ }
+ }
+
+ // TryBlockMap {
+ // int32_t TryLow;
+ // int32_t TryHigh;
+ // int32_t CatchHigh;
+ // int32_t NumCatches;
+ // HandlerType *HandlerArray;
+ // };
+ if (TryBlockMapXData) {
+ OS.EmitLabel(TryBlockMapXData);
+ SmallVector<MCSymbol *, 1> HandlerMaps;
+ for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
+ const WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
+
+ MCSymbol *HandlerMapXData = nullptr;
+ if (!TBME.HandlerArray.empty())
+ HandlerMapXData =
+ Asm->OutContext.getOrCreateSymbol(Twine("$handlerMap$")
+ .concat(Twine(I))
+ .concat("$")
+ .concat(FuncLinkageName));
+ HandlerMaps.push_back(HandlerMapXData);
+
+ // TBMEs should form intervals.
+ assert(0 <= TBME.TryLow && "bad trymap interval");
+ assert(TBME.TryLow <= TBME.TryHigh && "bad trymap interval");
+ assert(TBME.TryHigh < TBME.CatchHigh && "bad trymap interval");
+ assert(TBME.CatchHigh < int(FuncInfo.CxxUnwindMap.size()) &&
+ "bad trymap interval");
+
+ AddComment("TryLow");
+ OS.EmitIntValue(TBME.TryLow, 4);
+
+ AddComment("TryHigh");
+ OS.EmitIntValue(TBME.TryHigh, 4);
+
+ AddComment("CatchHigh");
+ OS.EmitIntValue(TBME.CatchHigh, 4);
+
+ AddComment("NumCatches");
+ OS.EmitIntValue(TBME.HandlerArray.size(), 4);
+
+ AddComment("HandlerArray");
+ OS.EmitValue(create32bitRef(HandlerMapXData), 4);
+ }
+
+ // All funclets use the same parent frame offset currently.
+ unsigned ParentFrameOffset = 0;
+ if (shouldEmitPersonality) {
+ const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering();
+ ParentFrameOffset = TFI->getWinEHParentFrameOffset(*MF);
+ }
+
+ for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
+ const WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
+ MCSymbol *HandlerMapXData = HandlerMaps[I];
+ if (!HandlerMapXData)
+ continue;
+ // HandlerType {
+ // int32_t Adjectives;
+ // TypeDescriptor *Type;
+ // int32_t CatchObjOffset;
+ // void (*Handler)();
+ // int32_t ParentFrameOffset; // x64 only
+ // };
+ OS.EmitLabel(HandlerMapXData);
+ for (const WinEHHandlerType &HT : TBME.HandlerArray) {
+ // Get the frame escape label with the offset of the catch object. If
+ // the index is INT_MAX, then there is no catch object, and we should
+ // emit an offset of zero, indicating that no copy will occur.
+ const MCExpr *FrameAllocOffsetRef = nullptr;
+ if (HT.CatchObj.FrameIndex != INT_MAX) {
+ int Offset = getFrameIndexOffset(HT.CatchObj.FrameIndex, FuncInfo);
+ FrameAllocOffsetRef = MCConstantExpr::create(Offset, Asm->OutContext);
+ } else {
+ FrameAllocOffsetRef = MCConstantExpr::create(0, Asm->OutContext);
+ }
+
+ MCSymbol *HandlerSym =
+ getMCSymbolForMBB(Asm, HT.Handler.dyn_cast<MachineBasicBlock *>());
+
+ AddComment("Adjectives");
+ OS.EmitIntValue(HT.Adjectives, 4);
+
+ AddComment("Type");
+ OS.EmitValue(create32bitRef(HT.TypeDescriptor), 4);
+
+ AddComment("CatchObjOffset");
+ OS.EmitValue(FrameAllocOffsetRef, 4);
+
+ AddComment("Handler");
+ OS.EmitValue(create32bitRef(HandlerSym), 4);
+
+ if (shouldEmitPersonality) {
+ AddComment("ParentFrameOffset");
+ OS.EmitIntValue(ParentFrameOffset, 4);
+ }
+ }
+ }
+ }
+
+ // IPToStateMapEntry {
+ // void *IP;
+ // int32_t State;
+ // };
+ if (IPToStateXData) {
+ OS.EmitLabel(IPToStateXData);
+ for (auto &IPStatePair : IPToStateTable) {
+ AddComment("IP");
+ OS.EmitValue(IPStatePair.first, 4);
+ AddComment("ToState");
+ OS.EmitIntValue(IPStatePair.second, 4);
+ }
+ }
+}
+
+void WinException::computeIP2StateTable(
+ const MachineFunction *MF, const WinEHFuncInfo &FuncInfo,
+ SmallVectorImpl<std::pair<const MCExpr *, int>> &IPToStateTable) {
+
+ for (MachineFunction::const_iterator FuncletStart = MF->begin(),
+ FuncletEnd = MF->begin(),
+ End = MF->end();
+ FuncletStart != End; FuncletStart = FuncletEnd) {
+ // Find the end of the funclet
+ while (++FuncletEnd != End) {
+ if (FuncletEnd->isEHFuncletEntry()) {
+ break;
+ }
+ }
+
+ // Don't emit ip2state entries for cleanup funclets. Any interesting
+ // exceptional actions in cleanups must be handled in a separate IR
+ // function.
+ if (FuncletStart->isCleanupFuncletEntry())
+ continue;
+
+ MCSymbol *StartLabel;
+ int BaseState;
+ if (FuncletStart == MF->begin()) {
+ BaseState = NullState;
+ StartLabel = Asm->getFunctionBegin();
+ } else {
+ auto *FuncletPad =
+ cast<FuncletPadInst>(FuncletStart->getBasicBlock()->getFirstNonPHI());
+ assert(FuncInfo.FuncletBaseStateMap.count(FuncletPad) != 0);
+ BaseState = FuncInfo.FuncletBaseStateMap.find(FuncletPad)->second;
+ StartLabel = getMCSymbolForMBB(Asm, &*FuncletStart);
+ }
+ assert(StartLabel && "need local function start label");
+ IPToStateTable.push_back(
+ std::make_pair(create32bitRef(StartLabel), BaseState));
+
+ for (const auto &StateChange : InvokeStateChangeIterator::range(
+ FuncInfo, FuncletStart, FuncletEnd, BaseState)) {
+ // Compute the label to report as the start of this entry; use the EH
+ // start label for the invoke if we have one, otherwise (this is a call
+ // which may unwind to our caller and does not have an EH start label, so)
+ // use the previous end label.
+ const MCSymbol *ChangeLabel = StateChange.NewStartLabel;
+ if (!ChangeLabel)
+ 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));
+ // FIXME: assert that NewState is between CatchLow and CatchHigh.
+ }
+ }
+}
+
+void WinException::emitEHRegistrationOffsetLabel(const WinEHFuncInfo &FuncInfo,
+ StringRef FLinkageName) {
+ // Outlined helpers called by the EH runtime need to know the offset of the EH
+ // registration in order to recover the parent frame pointer. Now that we know
+ // we've code generated the parent, we can emit the label assignment that
+ // those helpers use to get the offset of the registration node.
+ MCContext &Ctx = Asm->OutContext;
+ MCSymbol *ParentFrameOffset =
+ Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName);
+ unsigned UnusedReg;
+ const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
+ int64_t Offset = TFI->getFrameIndexReference(
+ *Asm->MF, FuncInfo.EHRegNodeFrameIndex, UnusedReg);
+ const MCExpr *MCOffset = MCConstantExpr::create(Offset, Ctx);
+ Asm->OutStreamer->EmitAssignment(ParentFrameOffset, MCOffset);
+}
+
+/// Emit the language-specific data that _except_handler3 and 4 expect. This is
+/// functionally equivalent to the __C_specific_handler table, except it is
+/// indexed by state number instead of IP.
+void WinException::emitExceptHandlerTable(const MachineFunction *MF) {
+ MCStreamer &OS = *Asm->OutStreamer;
+ const Function *F = MF->getFunction();
+ StringRef FLinkageName = GlobalValue::getRealLinkageName(F->getName());
+
+ bool VerboseAsm = OS.isVerboseAsm();
+ auto AddComment = [&](const Twine &Comment) {
+ if (VerboseAsm)
+ OS.AddComment(Comment);
+ };
+
+ const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
+ emitEHRegistrationOffsetLabel(FuncInfo, FLinkageName);
+
+ // Emit the __ehtable label that we use for llvm.x86.seh.lsda.
+ MCSymbol *LSDALabel = Asm->OutContext.getOrCreateLSDASymbol(FLinkageName);
+ OS.EmitValueToAlignment(4);
+ OS.EmitLabel(LSDALabel);
+
+ const Function *Per =
+ dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
+ StringRef PerName = Per->getName();
+ int BaseState = -1;
+ if (PerName == "_except_handler4") {
+ // The LSDA for _except_handler4 starts with this struct, followed by the
+ // scope table:
+ //
+ // struct EH4ScopeTable {
+ // int32_t GSCookieOffset;
+ // int32_t GSCookieXOROffset;
+ // int32_t EHCookieOffset;
+ // int32_t EHCookieXOROffset;
+ // ScopeTableEntry ScopeRecord[];
+ // };
+ //
+ // Only the EHCookieOffset field appears to vary, and it appears to be the
+ // offset from the final saved SP value to the retaddr.
+ AddComment("GSCookieOffset");
+ OS.EmitIntValue(-2, 4);
+ AddComment("GSCookieXOROffset");
+ OS.EmitIntValue(0, 4);
+ // FIXME: Calculate.
+ AddComment("EHCookieOffset");
+ OS.EmitIntValue(9999, 4);
+ AddComment("EHCookieXOROffset");
+ OS.EmitIntValue(0, 4);
+ BaseState = -2;
+ }
+
+ assert(!FuncInfo.SEHUnwindMap.empty());
+ for (const SEHUnwindMapEntry &UME : FuncInfo.SEHUnwindMap) {
+ auto *Handler = UME.Handler.get<MachineBasicBlock *>();
+ const MCSymbol *ExceptOrFinally =
+ UME.IsFinally ? getMCSymbolForMBB(Asm, Handler) : Handler->getSymbol();
+ // -1 is usually the base state for "unwind to caller", but for
+ // _except_handler4 it's -2. Do that replacement here if necessary.
+ int ToState = UME.ToState == -1 ? BaseState : UME.ToState;
+ AddComment("ToState");
+ OS.EmitIntValue(ToState, 4);
+ AddComment(UME.IsFinally ? "Null" : "FilterFunction");
+ OS.EmitValue(create32bitRef(UME.Filter), 4);
+ AddComment(UME.IsFinally ? "FinallyFunclet" : "ExceptionHandler");
+ OS.EmitValue(create32bitRef(ExceptOrFinally), 4);
+ }
+}
+
+static int getRank(const WinEHFuncInfo &FuncInfo, int State) {
+ int Rank = 0;
+ while (State != -1) {
+ ++Rank;
+ State = FuncInfo.ClrEHUnwindMap[State].Parent;
+ }
+ return Rank;
+}
+
+static int getAncestor(const WinEHFuncInfo &FuncInfo, int Left, int Right) {
+ int LeftRank = getRank(FuncInfo, Left);
+ int RightRank = getRank(FuncInfo, Right);
+
+ while (LeftRank < RightRank) {
+ Right = FuncInfo.ClrEHUnwindMap[Right].Parent;
+ --RightRank;
+ }
+
+ while (RightRank < LeftRank) {
+ Left = FuncInfo.ClrEHUnwindMap[Left].Parent;
+ --LeftRank;
+ }
+
+ while (Left != Right) {
+ Left = FuncInfo.ClrEHUnwindMap[Left].Parent;
+ Right = FuncInfo.ClrEHUnwindMap[Right].Parent;
+ }
+
+ return Left;
+}
+
+void WinException::emitCLRExceptionTable(const MachineFunction *MF) {
+ // CLR EH "states" are really just IDs that identify handlers/funclets;
+ // states, handlers, and funclets all have 1:1 mappings between them, and a
+ // handler/funclet's "state" is its index in the ClrEHUnwindMap.
+ MCStreamer &OS = *Asm->OutStreamer;
+ const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
+ MCSymbol *FuncBeginSym = Asm->getFunctionBegin();
+ MCSymbol *FuncEndSym = Asm->getFunctionEnd();
+
+ // A ClrClause describes a protected region.
+ struct ClrClause {
+ const MCSymbol *StartLabel; // Start of protected region
+ const MCSymbol *EndLabel; // End of protected region
+ int State; // Index of handler protecting the protected region
+ int EnclosingState; // Index of funclet enclosing the protected region
+ };
+ SmallVector<ClrClause, 8> Clauses;
+
+ // Build a map from handler MBBs to their corresponding states (i.e. their
+ // indices in the ClrEHUnwindMap).
+ int NumStates = FuncInfo.ClrEHUnwindMap.size();
+ assert(NumStates > 0 && "Don't need exception table!");
+ DenseMap<const MachineBasicBlock *, int> HandlerStates;
+ for (int State = 0; State < NumStates; ++State) {
+ MachineBasicBlock *HandlerBlock =
+ FuncInfo.ClrEHUnwindMap[State].Handler.get<MachineBasicBlock *>();
+ HandlerStates[HandlerBlock] = State;
+ // Use this loop through all handlers to verify our assumption (used in
+ // the MinEnclosingState computation) that ancestors have lower state
+ // numbers than their descendants.
+ assert(FuncInfo.ClrEHUnwindMap[State].Parent < State &&
+ "ill-formed state numbering");
+ }
+ // Map the main function to the NullState.
+ HandlerStates[&MF->front()] = NullState;
+
+ // Write out a sentinel indicating the end of the standard (Windows) xdata
+ // and the start of the additional (CLR) info.
+ OS.EmitIntValue(0xffffffff, 4);
+ // Write out the number of funclets
+ OS.EmitIntValue(NumStates, 4);
+
+ // Walk the machine blocks/instrs, computing and emitting a few things:
+ // 1. Emit a list of the offsets to each handler entry, in lexical order.
+ // 2. Compute a map (EndSymbolMap) from each funclet to the symbol at its end.
+ // 3. Compute the list of ClrClauses, in the required order (inner before
+ // outer, earlier before later; the order by which a forward scan with
+ // early termination will find the innermost enclosing clause covering
+ // a given address).
+ // 4. A map (MinClauseMap) from each handler index to the index of the
+ // outermost funclet/function which contains a try clause targeting the
+ // key handler. This will be used to determine IsDuplicate-ness when
+ // emitting ClrClauses. The NullState value is used to indicate that the
+ // top-level function contains a try clause targeting the key handler.
+ // HandlerStack is a stack of (PendingStartLabel, PendingState) pairs for
+ // try regions we entered before entering the PendingState try but which
+ // we haven't yet exited.
+ SmallVector<std::pair<const MCSymbol *, int>, 4> HandlerStack;
+ // EndSymbolMap and MinClauseMap are maps described above.
+ std::unique_ptr<MCSymbol *[]> EndSymbolMap(new MCSymbol *[NumStates]);
+ SmallVector<int, 4> MinClauseMap((size_t)NumStates, NumStates);
+
+ // Visit the root function and each funclet.
+
+ for (MachineFunction::const_iterator FuncletStart = MF->begin(),
+ FuncletEnd = MF->begin(),
+ End = MF->end();
+ FuncletStart != End; FuncletStart = FuncletEnd) {
+ int FuncletState = HandlerStates[&*FuncletStart];
+ // Find the end of the funclet
+ MCSymbol *EndSymbol = FuncEndSym;
+ while (++FuncletEnd != End) {
+ if (FuncletEnd->isEHFuncletEntry()) {
+ EndSymbol = getMCSymbolForMBB(Asm, &*FuncletEnd);
+ break;
+ }
+ }
+ // Emit the function/funclet end and, if this is a funclet (and not the
+ // root function), record it in the EndSymbolMap.
+ OS.EmitValue(getOffset(EndSymbol, FuncBeginSym), 4);
+ if (FuncletState != NullState) {
+ // Record the end of the handler.
+ EndSymbolMap[FuncletState] = EndSymbol;
+ }
+
+ // Walk the state changes in this function/funclet and compute its clauses.
+ // Funclets always start in the null state.
+ const MCSymbol *CurrentStartLabel = nullptr;
+ int CurrentState = NullState;
+ assert(HandlerStack.empty());
+ for (const auto &StateChange :
+ InvokeStateChangeIterator::range(FuncInfo, FuncletStart, FuncletEnd)) {
+ // Close any try regions we're not still under
+ int AncestorState =
+ getAncestor(FuncInfo, CurrentState, StateChange.NewState);
+ while (CurrentState != AncestorState) {
+ assert(CurrentState != NullState && "Failed to find ancestor!");
+ // Close the pending clause
+ Clauses.push_back({CurrentStartLabel, StateChange.PreviousEndLabel,
+ CurrentState, FuncletState});
+ // Now the parent handler is current
+ CurrentState = FuncInfo.ClrEHUnwindMap[CurrentState].Parent;
+ // Pop the new start label from the handler stack if we've exited all
+ // descendants of the corresponding handler.
+ if (HandlerStack.back().second == CurrentState)
+ CurrentStartLabel = HandlerStack.pop_back_val().first;
+ }
+
+ if (StateChange.NewState != CurrentState) {
+ // For each clause we're starting, update the MinClauseMap so we can
+ // know which is the topmost funclet containing a clause targeting
+ // it.
+ for (int EnteredState = StateChange.NewState;
+ EnteredState != CurrentState;
+ EnteredState = FuncInfo.ClrEHUnwindMap[EnteredState].Parent) {
+ int &MinEnclosingState = MinClauseMap[EnteredState];
+ if (FuncletState < MinEnclosingState)
+ MinEnclosingState = FuncletState;
+ }
+ // Save the previous current start/label on the stack and update to
+ // the newly-current start/state.
+ HandlerStack.emplace_back(CurrentStartLabel, CurrentState);
+ CurrentStartLabel = StateChange.NewStartLabel;
+ CurrentState = StateChange.NewState;
+ }
+ }
+ assert(HandlerStack.empty());
+ }
+
+ // Now emit the clause info, starting with the number of clauses.
+ OS.EmitIntValue(Clauses.size(), 4);
+ for (ClrClause &Clause : Clauses) {
+ // Emit a CORINFO_EH_CLAUSE :
+ /*
+ struct CORINFO_EH_CLAUSE
+ {
+ CORINFO_EH_CLAUSE_FLAGS Flags; // actually a CorExceptionFlag
+ DWORD TryOffset;
+ DWORD TryLength; // actually TryEndOffset
+ DWORD HandlerOffset;
+ DWORD HandlerLength; // actually HandlerEndOffset
+ union
+ {
+ DWORD ClassToken; // use for catch clauses
+ DWORD FilterOffset; // use for filter clauses
+ };
+ };
+
+ enum CORINFO_EH_CLAUSE_FLAGS
+ {
+ CORINFO_EH_CLAUSE_NONE = 0,
+ CORINFO_EH_CLAUSE_FILTER = 0x0001, // This clause is for a filter
+ CORINFO_EH_CLAUSE_FINALLY = 0x0002, // This clause is a finally clause
+ CORINFO_EH_CLAUSE_FAULT = 0x0004, // This clause is a fault clause
+ };
+ typedef enum CorExceptionFlag
+ {
+ COR_ILEXCEPTION_CLAUSE_NONE,
+ COR_ILEXCEPTION_CLAUSE_FILTER = 0x0001, // This is a filter clause
+ COR_ILEXCEPTION_CLAUSE_FINALLY = 0x0002, // This is a finally clause
+ COR_ILEXCEPTION_CLAUSE_FAULT = 0x0004, // This is a fault clause
+ COR_ILEXCEPTION_CLAUSE_DUPLICATED = 0x0008, // duplicated clause. This
+ // clause was duplicated
+ // to a funclet which was
+ // pulled out of line
+ } CorExceptionFlag;
+ */
+ // Add 1 to the start/end of the EH clause; the IP associated with a
+ // call when the runtime does its scan is the IP of the next instruction
+ // (the one to which control will return after the call), so we need
+ // to add 1 to the end of the clause to cover that offset. We also add
+ // 1 to the start of the clause to make sure that the ranges reported
+ // for all clauses are disjoint. Note that we'll need some additional
+ // logic when machine traps are supported, since in that case the IP
+ // that the runtime uses is the offset of the faulting instruction
+ // itself; if such an instruction immediately follows a call but the
+ // two belong to different clauses, we'll need to insert a nop between
+ // them so the runtime can distinguish the point to which the call will
+ // return from the point at which the fault occurs.
+
+ const MCExpr *ClauseBegin =
+ getOffsetPlusOne(Clause.StartLabel, FuncBeginSym);
+ const MCExpr *ClauseEnd = getOffsetPlusOne(Clause.EndLabel, FuncBeginSym);
+
+ const ClrEHUnwindMapEntry &Entry = FuncInfo.ClrEHUnwindMap[Clause.State];
+ MachineBasicBlock *HandlerBlock = Entry.Handler.get<MachineBasicBlock *>();
+ MCSymbol *BeginSym = getMCSymbolForMBB(Asm, HandlerBlock);
+ const MCExpr *HandlerBegin = getOffset(BeginSym, FuncBeginSym);
+ MCSymbol *EndSym = EndSymbolMap[Clause.State];
+ const MCExpr *HandlerEnd = getOffset(EndSym, FuncBeginSym);
+
+ uint32_t Flags = 0;
+ switch (Entry.HandlerType) {
+ case ClrHandlerType::Catch:
+ // Leaving bits 0-2 clear indicates catch.
+ break;
+ case ClrHandlerType::Filter:
+ Flags |= 1;
+ break;
+ case ClrHandlerType::Finally:
+ Flags |= 2;
+ break;
+ case ClrHandlerType::Fault:
+ Flags |= 4;
+ break;
+ }
+ if (Clause.EnclosingState != MinClauseMap[Clause.State]) {
+ // This is a "duplicate" clause; the handler needs to be entered from a
+ // frame above the one holding the invoke.
+ assert(Clause.EnclosingState > MinClauseMap[Clause.State]);
+ Flags |= 8;
+ }
+ OS.EmitIntValue(Flags, 4);
+
+ // Write the clause start/end
+ OS.EmitValue(ClauseBegin, 4);
+ OS.EmitValue(ClauseEnd, 4);
+
+ // Write out the handler start/end
+ OS.EmitValue(HandlerBegin, 4);
+ OS.EmitValue(HandlerEnd, 4);
+
+ // Write out the type token or filter offset
+ assert(Entry.HandlerType != ClrHandlerType::Filter && "NYI: filters");
+ OS.EmitIntValue(Entry.TypeToken, 4);
+ }
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.h b/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.h
new file mode 100644
index 0000000..acb3010
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.h
@@ -0,0 +1,106 @@
+//===-- WinException.h - Windows Exception Handling ----------*- 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 windows exception info into asm files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_WIN64EXCEPTION_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_WIN64EXCEPTION_H
+
+#include "EHStreamer.h"
+
+namespace llvm {
+class Function;
+class GlobalValue;
+class MachineFunction;
+class MCExpr;
+class Value;
+struct WinEHFuncInfo;
+
+class LLVM_LIBRARY_VISIBILITY WinException : public EHStreamer {
+ /// Per-function flag to indicate if personality info should be emitted.
+ bool shouldEmitPersonality = false;
+
+ /// Per-function flag to indicate if the LSDA should be emitted.
+ bool shouldEmitLSDA = false;
+
+ /// Per-function flag to indicate if frame moves info should be emitted.
+ bool shouldEmitMoves = false;
+
+ /// True if this is a 64-bit target and we should use image relative offsets.
+ bool useImageRel32 = false;
+
+ /// Pointer to the current funclet entry BB.
+ const MachineBasicBlock *CurrentFuncletEntry = nullptr;
+
+ void emitCSpecificHandlerTable(const MachineFunction *MF);
+
+ void emitSEHActionsForRange(const WinEHFuncInfo &FuncInfo,
+ const MCSymbol *BeginLabel,
+ const MCSymbol *EndLabel, int State);
+
+ /// Emit the EH table data for 32-bit and 64-bit functions using
+ /// the __CxxFrameHandler3 personality.
+ void emitCXXFrameHandler3Table(const MachineFunction *MF);
+
+ /// Emit the EH table data for _except_handler3 and _except_handler4
+ /// personality functions. These are only used on 32-bit and do not use CFI
+ /// tables.
+ void emitExceptHandlerTable(const MachineFunction *MF);
+
+ void emitCLRExceptionTable(const MachineFunction *MF);
+
+ void computeIP2StateTable(
+ 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
+ /// 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 *getOffset(const MCSymbol *OffsetOf, const MCSymbol *OffsetFrom);
+ const MCExpr *getOffsetPlusOne(const MCSymbol *OffsetOf,
+ const MCSymbol *OffsetFrom);
+
+ /// Gets the offset that we should use in a table for a stack object with the
+ /// given index. For targets using CFI (Win64, etc), this is relative to the
+ /// established SP at the end of the prologue. For targets without CFI (Win32
+ /// only), it is relative to the frame pointer.
+ int getFrameIndexOffset(int FrameIndex, const WinEHFuncInfo &FuncInfo);
+
+public:
+ //===--------------------------------------------------------------------===//
+ // Main entry points.
+ //
+ WinException(AsmPrinter *A);
+ ~WinException() override;
+
+ /// Emit all exception information that should come after the content.
+ void endModule() override;
+
+ /// Gather pre-function exception information. Assumes being emitted
+ /// immediately after the function entry point.
+ void beginFunction(const MachineFunction *MF) override;
+
+ /// Gather and emit post-function exception information.
+ void endFunction(const MachineFunction *) override;
+
+ /// \brief Emit target-specific EH funclet machinery.
+ void beginFunclet(const MachineBasicBlock &MBB, MCSymbol *Sym) override;
+ void endFunclet() override;
+};
+}
+
+#endif
+
OpenPOWER on IntegriCloud