Imported Upstream version 5.18.0.167

Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-10-20 08:25:10 +00:00
parent e19d552987
commit b084638f15
28489 changed files with 184 additions and 3866856 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,184 +0,0 @@
//==- llvm/CodeGen/AggressiveAntiDepBreaker.h - Anti-Dep Support -*- 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 AggressiveAntiDepBreaker class, which
// implements register anti-dependence breaking during post-RA
// scheduling. It attempts to break all anti-dependencies within a
// block.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_CODEGEN_AGGRESSIVEANTIDEPBREAKER_H
#define LLVM_LIB_CODEGEN_AGGRESSIVEANTIDEPBREAKER_H
#include "AntiDepBreaker.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/Support/Compiler.h"
#include <map>
#include <set>
#include <vector>
namespace llvm {
class MachineBasicBlock;
class MachineFunction;
class MachineInstr;
class MachineOperand;
class MachineRegisterInfo;
class RegisterClassInfo;
class TargetInstrInfo;
class TargetRegisterClass;
class TargetRegisterInfo;
/// Contains all the state necessary for anti-dep breaking.
class LLVM_LIBRARY_VISIBILITY AggressiveAntiDepState {
public:
/// Information about a register reference within a liverange
struct RegisterReference {
/// The registers operand
MachineOperand *Operand;
/// The register class
const TargetRegisterClass *RC;
};
private:
/// Number of non-virtual target registers (i.e. TRI->getNumRegs()).
const unsigned NumTargetRegs;
/// Implements a disjoint-union data structure to
/// form register groups. A node is represented by an index into
/// the vector. A node can "point to" itself to indicate that it
/// is the parent of a group, or point to another node to indicate
/// that it is a member of the same group as that node.
std::vector<unsigned> GroupNodes;
/// For each register, the index of the GroupNode
/// currently representing the group that the register belongs to.
/// Register 0 is always represented by the 0 group, a group
/// composed of registers that are not eligible for anti-aliasing.
std::vector<unsigned> GroupNodeIndices;
/// Map registers to all their references within a live range.
std::multimap<unsigned, RegisterReference> RegRefs;
/// The index of the most recent kill (proceeding bottom-up),
/// or ~0u if the register is not live.
std::vector<unsigned> KillIndices;
/// The index of the most recent complete def (proceeding bottom
/// up), or ~0u if the register is live.
std::vector<unsigned> DefIndices;
public:
AggressiveAntiDepState(const unsigned TargetRegs, MachineBasicBlock *BB);
/// Return the kill indices.
std::vector<unsigned> &GetKillIndices() { return KillIndices; }
/// Return the define indices.
std::vector<unsigned> &GetDefIndices() { return DefIndices; }
/// Return the RegRefs map.
std::multimap<unsigned, RegisterReference>& GetRegRefs() { return RegRefs; }
// Get the group for a register. The returned value is
// the index of the GroupNode representing the group.
unsigned GetGroup(unsigned Reg);
// Return a vector of the registers belonging to a group.
// If RegRefs is non-NULL then only included referenced registers.
void GetGroupRegs(
unsigned Group,
std::vector<unsigned> &Regs,
std::multimap<unsigned,
AggressiveAntiDepState::RegisterReference> *RegRefs);
// Union Reg1's and Reg2's groups to form a new group.
// Return the index of the GroupNode representing the group.
unsigned UnionGroups(unsigned Reg1, unsigned Reg2);
// Remove a register from its current group and place
// it alone in its own group. Return the index of the GroupNode
// representing the registers new group.
unsigned LeaveGroup(unsigned Reg);
/// Return true if Reg is live.
bool IsLive(unsigned Reg);
};
class LLVM_LIBRARY_VISIBILITY AggressiveAntiDepBreaker
: public AntiDepBreaker {
MachineFunction &MF;
MachineRegisterInfo &MRI;
const TargetInstrInfo *TII;
const TargetRegisterInfo *TRI;
const RegisterClassInfo &RegClassInfo;
/// The set of registers that should only be
/// renamed if they are on the critical path.
BitVector CriticalPathSet;
/// The state used to identify and rename anti-dependence registers.
AggressiveAntiDepState *State = nullptr;
public:
AggressiveAntiDepBreaker(MachineFunction &MFi,
const RegisterClassInfo &RCI,
TargetSubtargetInfo::RegClassVector& CriticalPathRCs);
~AggressiveAntiDepBreaker() override;
/// Initialize anti-dep breaking for a new basic block.
void StartBlock(MachineBasicBlock *BB) override;
/// Identifiy anti-dependencies along the critical path
/// of the ScheduleDAG and break them by renaming registers.
unsigned BreakAntiDependencies(const std::vector<SUnit> &SUnits,
MachineBasicBlock::iterator Begin,
MachineBasicBlock::iterator End,
unsigned InsertPosIndex,
DbgValueVector &DbgValues) override;
/// Update liveness information to account for the current
/// instruction, which will not be scheduled.
void Observe(MachineInstr &MI, unsigned Count,
unsigned InsertPosIndex) override;
/// Finish anti-dep breaking for a basic block.
void FinishBlock() override;
private:
/// Keep track of a position in the allocation order for each regclass.
using RenameOrderType = std::map<const TargetRegisterClass *, unsigned>;
/// Return true if MO represents a register
/// that is both implicitly used and defined in MI
bool IsImplicitDefUse(MachineInstr &MI, MachineOperand &MO);
/// If MI implicitly def/uses a register, then
/// return that register and all subregisters.
void GetPassthruRegs(MachineInstr &MI, std::set<unsigned> &PassthruRegs);
void HandleLastUse(unsigned Reg, unsigned KillIdx, const char *tag,
const char *header = nullptr,
const char *footer = nullptr);
void PrescanInstruction(MachineInstr &MI, unsigned Count,
std::set<unsigned> &PassthruRegs);
void ScanInstruction(MachineInstr &MI, unsigned Count);
BitVector GetRenameRegisters(unsigned Reg);
bool FindSuitableFreeRegisters(unsigned AntiDepGroupIndex,
RenameOrderType& RenameOrder,
std::map<unsigned, unsigned> &RenameMap);
};
} // end namespace llvm
#endif // LLVM_LIB_CODEGEN_AGGRESSIVEANTIDEPBREAKER_H

View File

@ -1,55 +0,0 @@
//===-- llvm/CodeGen/AllocationOrder.cpp - Allocation Order ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements an allocation order for virtual registers.
//
// The preferred allocation order for a virtual register depends on allocation
// hints and target hooks. The AllocationOrder class encapsulates all of that.
//
//===----------------------------------------------------------------------===//
#include "AllocationOrder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterClassInfo.h"
#include "llvm/CodeGen/VirtRegMap.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
#define DEBUG_TYPE "regalloc"
// Compare VirtRegMap::getRegAllocPref().
AllocationOrder::AllocationOrder(unsigned VirtReg,
const VirtRegMap &VRM,
const RegisterClassInfo &RegClassInfo,
const LiveRegMatrix *Matrix)
: Pos(0), HardHints(false) {
const MachineFunction &MF = VRM.getMachineFunction();
const TargetRegisterInfo *TRI = &VRM.getTargetRegInfo();
Order = RegClassInfo.getOrder(MF.getRegInfo().getRegClass(VirtReg));
if (TRI->getRegAllocationHints(VirtReg, Order, Hints, MF, &VRM, Matrix))
HardHints = true;
rewind();
DEBUG({
if (!Hints.empty()) {
dbgs() << "hints:";
for (unsigned I = 0, E = Hints.size(); I != E; ++I)
dbgs() << ' ' << printReg(Hints[I], TRI);
dbgs() << '\n';
}
});
#ifndef NDEBUG
for (unsigned I = 0, E = Hints.size(); I != E; ++I)
assert(is_contained(Order, Hints[I]) &&
"Target hint is outside allocation order.");
#endif
}

View File

@ -1,96 +0,0 @@
//===-- llvm/CodeGen/AllocationOrder.h - Allocation Order -*- 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 an allocation order for virtual registers.
//
// The preferred allocation order for a virtual register depends on allocation
// hints and target hooks. The AllocationOrder class encapsulates all of that.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_CODEGEN_ALLOCATIONORDER_H
#define LLVM_LIB_CODEGEN_ALLOCATIONORDER_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/MC/MCRegisterInfo.h"
namespace llvm {
class RegisterClassInfo;
class VirtRegMap;
class LiveRegMatrix;
class LLVM_LIBRARY_VISIBILITY AllocationOrder {
SmallVector<MCPhysReg, 16> Hints;
ArrayRef<MCPhysReg> Order;
int Pos;
// If HardHints is true, *only* Hints will be returned.
bool HardHints;
public:
/// Create a new AllocationOrder for VirtReg.
/// @param VirtReg Virtual register to allocate for.
/// @param VRM Virtual register map for function.
/// @param RegClassInfo Information about reserved and allocatable registers.
AllocationOrder(unsigned VirtReg,
const VirtRegMap &VRM,
const RegisterClassInfo &RegClassInfo,
const LiveRegMatrix *Matrix);
/// Get the allocation order without reordered hints.
ArrayRef<MCPhysReg> getOrder() const { return Order; }
/// Return the next physical register in the allocation order, or 0.
/// It is safe to call next() again after it returned 0, it will keep
/// returning 0 until rewind() is called.
unsigned next(unsigned Limit = 0) {
if (Pos < 0)
return Hints.end()[Pos++];
if (HardHints)
return 0;
if (!Limit)
Limit = Order.size();
while (Pos < int(Limit)) {
unsigned Reg = Order[Pos++];
if (!isHint(Reg))
return Reg;
}
return 0;
}
/// As next(), but allow duplicates to be returned, and stop before the
/// Limit'th register in the RegisterClassInfo allocation order.
///
/// This can produce more than Limit registers if there are hints.
unsigned nextWithDups(unsigned Limit) {
if (Pos < 0)
return Hints.end()[Pos++];
if (HardHints)
return 0;
if (Pos < int(Limit))
return Order[Pos++];
return 0;
}
/// Start over from the beginning.
void rewind() { Pos = -int(Hints.size()); }
/// Return true if the last register returned from next() was a preferred register.
bool isHint() const { return Pos <= 0; }
/// Return true if PhysReg is a preferred register.
bool isHint(unsigned PhysReg) const { return is_contained(Hints, PhysReg); }
};
} // end namespace llvm
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,88 +0,0 @@
//===- llvm/CodeGen/AntiDepBreaker.h - Anti-Dependence Breaking -*- 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 AntiDepBreaker class, which implements
// anti-dependence breaking heuristics for post-register-allocation scheduling.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_CODEGEN_ANTIDEPBREAKER_H
#define LLVM_LIB_CODEGEN_ANTIDEPBREAKER_H
#include "llvm/ADT/iterator_range.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/Support/Compiler.h"
#include <cassert>
#include <utility>
#include <vector>
namespace llvm {
/// This class works in conjunction with the post-RA scheduler to rename
/// registers to break register anti-dependencies (WAR hazards).
class LLVM_LIBRARY_VISIBILITY AntiDepBreaker {
public:
using DbgValueVector =
std::vector<std::pair<MachineInstr *, MachineInstr *>>;
virtual ~AntiDepBreaker();
/// Initialize anti-dep breaking for a new basic block.
virtual void StartBlock(MachineBasicBlock *BB) = 0;
/// Identifiy anti-dependencies within a basic-block region and break them by
/// renaming registers. Return the number of anti-dependencies broken.
virtual unsigned BreakAntiDependencies(const std::vector<SUnit> &SUnits,
MachineBasicBlock::iterator Begin,
MachineBasicBlock::iterator End,
unsigned InsertPosIndex,
DbgValueVector &DbgValues) = 0;
/// Update liveness information to account for the current
/// instruction, which will not be scheduled.
virtual void Observe(MachineInstr &MI, unsigned Count,
unsigned InsertPosIndex) = 0;
/// Finish anti-dep breaking for a basic block.
virtual void FinishBlock() = 0;
/// Update DBG_VALUE if dependency breaker is updating
/// other machine instruction to use NewReg.
void UpdateDbgValue(MachineInstr &MI, unsigned OldReg, unsigned NewReg) {
assert(MI.isDebugValue() && "MI is not DBG_VALUE!");
if (MI.getOperand(0).isReg() && MI.getOperand(0).getReg() == OldReg)
MI.getOperand(0).setReg(NewReg);
}
/// Update all DBG_VALUE instructions that may be affected by the dependency
/// breaker's update of ParentMI to use NewReg.
void UpdateDbgValues(const DbgValueVector &DbgValues, MachineInstr *ParentMI,
unsigned OldReg, unsigned NewReg) {
// The following code is dependent on the order in which the DbgValues are
// constructed in ScheduleDAGInstrs::buildSchedGraph.
MachineInstr *PrevDbgMI = nullptr;
for (const auto &DV : make_range(DbgValues.crbegin(), DbgValues.crend())) {
MachineInstr *PrevMI = DV.second;
if ((PrevMI == ParentMI) || (PrevMI == PrevDbgMI)) {
MachineInstr *DbgMI = DV.first;
UpdateDbgValue(*DbgMI, OldReg, NewReg);
PrevDbgMI = DbgMI;
} else if (PrevDbgMI) {
break; // If no match and already found a DBG_VALUE, we're done.
}
}
}
};
} // end namespace llvm
#endif // LLVM_LIB_CODEGEN_ANTIDEPBREAKER_H

View File

@ -1,133 +0,0 @@
//===-- 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/Twine.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Target/TargetOptions.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);
}
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) {
if (!hasEmittedCFISections) {
if (Asm->needsOnlyDebugCFIMoves())
Asm->OutStreamer->EmitCFISections(false, true);
hasEmittedCFISections = true;
}
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 ||
!MF->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 MachineFunction *MF = Asm->MF;
const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos();
const std::vector<unsigned> &FilterIds = MF->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);
}
}

View File

@ -1,46 +0,0 @@
//===- llvm/CodeGen/AddressPool.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 "AddressPool.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/TargetLoweringObjectFile.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCStreamer.h"
#include <utility>
using namespace llvm;
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());
}

View File

@ -1,57 +0,0 @@
//===- 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 AsmPrinter;
class MCSection;
class MCSymbol;
// 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 = false;
public:
AddressPool() = default;
/// \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; }
};
} // end namespace llvm
#endif // LLVM_LIB_CODEGEN_ASMPRINTER_ADDRESSPOOL_H

View File

@ -1 +0,0 @@
bf36cccd750b62edff26214e0b80f7bf2db27d68

View File

@ -1,265 +0,0 @@
//===-- 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 "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DIE.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/TargetLoweringObjectFile.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/ErrorHandling.h"
#include "llvm/Target/TargetMachine.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::EmitPaddedULEB128(uint64_t Value, unsigned PadTo,
const char *Desc) const {
if (isVerbose() && Desc)
OutStreamer->AddComment(Desc);
OutStreamer->EmitPaddedULEB128IntValue(Value, PadTo);
}
void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc) const {
if (isVerbose() && Desc)
OutStreamer->AddComment(Desc);
OutStreamer->EmitULEB128IntValue(Value);
}
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, 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, /*Offset=*/0);
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());
}
//===----------------------------------------------------------------------===//
// 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;
case MCCFIInstruction::OpRestore:
OutStreamer->EmitCFIRestore(Inst.getRegister());
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);
}

View File

@ -1,74 +0,0 @@
//===-- lib/CodeGen/AsmPrinter/AsmPrinterHandler.h -------------*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a generic interface for AsmPrinter handlers,
// like debug and EH info emitters.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_ASMPRINTERHANDLER_H
#define LLVM_LIB_CODEGEN_ASMPRINTER_ASMPRINTERHANDLER_H
#include "llvm/Support/DataTypes.h"
namespace llvm {
class AsmPrinter;
class MachineBasicBlock;
class MachineFunction;
class MachineInstr;
class MCSymbol;
typedef MCSymbol *ExceptionSymbolProvider(AsmPrinter *Asm);
/// \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;
virtual void beginFragment(const MachineBasicBlock *MBB,
ExceptionSymbolProvider ESP) {}
virtual void endFragment() {}
/// \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

File diff suppressed because it is too large Load Diff

View File

@ -1,110 +0,0 @@
//===-- 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/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

View File

@ -1,29 +0,0 @@
add_llvm_library(LLVMAsmPrinter
AddressPool.cpp
ARMException.cpp
AsmPrinter.cpp
AsmPrinterDwarf.cpp
AsmPrinterInlineAsm.cpp
DbgValueHistoryCalculator.cpp
DebugHandlerBase.cpp
DebugLocStream.cpp
DIE.cpp
DIEHash.cpp
DwarfAccelTable.cpp
DwarfCFIException.cpp
DwarfCompileUnit.cpp
DwarfDebug.cpp
DwarfExpression.cpp
DwarfFile.cpp
DwarfStringPool.cpp
DwarfUnit.cpp
EHStreamer.cpp
ErlangGCPrinter.cpp
OcamlGCPrinter.cpp
WinException.cpp
CodeViewDebug.cpp
MonoException.cpp
DEPENDS
intrinsics_gen
)

File diff suppressed because it is too large Load Diff

View File

@ -1,350 +0,0 @@
//===- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.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 Microsoft CodeView debug info.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H
#define LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H
#include "DbgValueHistoryCalculator.h"
#include "DebugHandlerBase.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
#include <cstdint>
#include <map>
#include <string>
#include <tuple>
#include <unordered_map>
#include <utility>
#include <vector>
namespace llvm {
struct ClassInfo;
class StringRef;
class AsmPrinter;
class Function;
class GlobalVariable;
class MCSectionCOFF;
class MCStreamer;
class MCSymbol;
class MachineFunction;
/// \brief Collects and handles line tables information in a CodeView format.
class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
MCStreamer &OS;
BumpPtrAllocator Allocator;
codeview::GlobalTypeTableBuilder TypeTable;
/// Represents the most general definition range.
struct LocalVarDefRange {
/// Indicates that variable data is stored in memory relative to the
/// specified register.
int InMemory : 1;
/// Offset of variable data in memory.
int DataOffset : 31;
/// Non-zero if this is a piece of an aggregate.
uint16_t IsSubfield : 1;
/// Offset into aggregate.
uint16_t StructOffset : 15;
/// Register containing the data or the register base of the memory
/// location containing the data.
uint16_t CVRegister;
/// Compares all location fields. This includes all fields except the label
/// ranges.
bool isDifferentLocation(LocalVarDefRange &O) {
return InMemory != O.InMemory || DataOffset != O.DataOffset ||
IsSubfield != O.IsSubfield || StructOffset != O.StructOffset ||
CVRegister != O.CVRegister;
}
SmallVector<std::pair<const MCSymbol *, const MCSymbol *>, 1> Ranges;
};
static LocalVarDefRange createDefRangeMem(uint16_t CVRegister, int Offset);
static LocalVarDefRange createDefRangeGeneral(uint16_t CVRegister,
bool InMemory, int Offset,
bool IsSubfield,
uint16_t StructOffset);
/// Similar to DbgVariable in DwarfDebug, but not dwarf-specific.
struct LocalVariable {
const DILocalVariable *DIVar = nullptr;
SmallVector<LocalVarDefRange, 1> DefRanges;
bool UseReferenceType = false;
};
struct InlineSite {
SmallVector<LocalVariable, 1> InlinedLocals;
SmallVector<const DILocation *, 1> ChildSites;
const DISubprogram *Inlinee = nullptr;
/// The ID of the inline site or function used with .cv_loc. Not a type
/// index.
unsigned SiteFuncId = 0;
};
// For each function, store a vector of labels to its instructions, as well as
// to the end of the function.
struct FunctionInfo {
/// Map from inlined call site to inlined instructions and child inlined
/// call sites. Listed in program order.
std::unordered_map<const DILocation *, InlineSite> InlineSites;
/// Ordered list of top-level inlined call sites.
SmallVector<const DILocation *, 1> ChildSites;
SmallVector<LocalVariable, 1> Locals;
std::vector<std::pair<MCSymbol *, MDNode *>> Annotations;
const MCSymbol *Begin = nullptr;
const MCSymbol *End = nullptr;
unsigned FuncId = 0;
unsigned LastFileId = 0;
bool HaveLineInfo = false;
};
FunctionInfo *CurFn = nullptr;
/// The set of comdat .debug$S sections that we've seen so far. Each section
/// must start with a magic version number that must only be emitted once.
/// This set tracks which sections we've already opened.
DenseSet<MCSectionCOFF *> ComdatDebugSections;
/// Switch to the appropriate .debug$S section for GVSym. If GVSym, the symbol
/// of an emitted global value, is in a comdat COFF section, this will switch
/// to a new .debug$S section in that comdat. This method ensures that the
/// section starts with the magic version number on first use. If GVSym is
/// null, uses the main .debug$S section.
void switchToDebugSectionForSymbol(const MCSymbol *GVSym);
/// The next available function index for use with our .cv_* directives. Not
/// to be confused with type indices for LF_FUNC_ID records.
unsigned NextFuncId = 0;
InlineSite &getInlineSite(const DILocation *InlinedAt,
const DISubprogram *Inlinee);
codeview::TypeIndex getFuncIdForSubprogram(const DISubprogram *SP);
void calculateRanges(LocalVariable &Var,
const DbgValueHistoryMap::InstrRanges &Ranges);
static void collectInlineSiteChildren(SmallVectorImpl<unsigned> &Children,
const FunctionInfo &FI,
const InlineSite &Site);
/// Remember some debug info about each function. Keep it in a stable order to
/// emit at the end of the TU.
MapVector<const Function *, FunctionInfo> FnDebugInfo;
/// Map from full file path to .cv_file id. Full paths are built from DIFiles
/// and are stored in FileToFilepathMap;
DenseMap<StringRef, unsigned> FileIdMap;
/// All inlined subprograms in the order they should be emitted.
SmallSetVector<const DISubprogram *, 4> InlinedSubprograms;
/// Map from a pair of DI metadata nodes and its DI type (or scope) that can
/// be nullptr, to CodeView type indices. Primarily indexed by
/// {DIType*, DIType*} and {DISubprogram*, DIType*}.
///
/// The second entry in the key is needed for methods as DISubroutineType
/// representing static method type are shared with non-method function type.
DenseMap<std::pair<const DINode *, const DIType *>, codeview::TypeIndex>
TypeIndices;
/// Map from DICompositeType* to complete type index. Non-record types are
/// always looked up in the normal TypeIndices map.
DenseMap<const DICompositeType *, codeview::TypeIndex> CompleteTypeIndices;
/// Complete record types to emit after all active type lowerings are
/// finished.
SmallVector<const DICompositeType *, 4> DeferredCompleteTypes;
/// Number of type lowering frames active on the stack.
unsigned TypeEmissionLevel = 0;
codeview::TypeIndex VBPType;
const DISubprogram *CurrentSubprogram = nullptr;
// The UDTs we have seen while processing types; each entry is a pair of type
// index and type name.
std::vector<std::pair<std::string, const DIType *>> LocalUDTs;
std::vector<std::pair<std::string, const DIType *>> GlobalUDTs;
using FileToFilepathMapTy = std::map<const DIFile *, std::string>;
FileToFilepathMapTy FileToFilepathMap;
StringRef getFullFilepath(const DIFile *S);
unsigned maybeRecordFile(const DIFile *F);
void maybeRecordLocation(const DebugLoc &DL, const MachineFunction *MF);
void clear();
void setCurrentSubprogram(const DISubprogram *SP) {
CurrentSubprogram = SP;
LocalUDTs.clear();
}
/// Emit the magic version number at the start of a CodeView type or symbol
/// section. Appears at the front of every .debug$S or .debug$T section.
void emitCodeViewMagicVersion();
void emitTypeInformation();
void emitTypeGlobalHashes();
void emitCompilerInformation();
void emitInlineeLinesSubsection();
void emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI);
void emitDebugInfoForGlobals();
void emitDebugInfoForRetainedTypes();
void
emitDebugInfoForUDTs(ArrayRef<std::pair<std::string, const DIType *>> UDTs);
void emitDebugInfoForGlobal(const DIGlobalVariable *DIGV,
const GlobalVariable *GV, MCSymbol *GVSym);
/// Opens a subsection of the given kind in a .debug$S codeview section.
/// Returns an end label for use with endCVSubsection when the subsection is
/// finished.
MCSymbol *beginCVSubsection(codeview::DebugSubsectionKind Kind);
void endCVSubsection(MCSymbol *EndLabel);
void emitInlinedCallSite(const FunctionInfo &FI, const DILocation *InlinedAt,
const InlineSite &Site);
using InlinedVariable = DbgValueHistoryMap::InlinedVariable;
void collectVariableInfo(const DISubprogram *SP);
void collectVariableInfoFromMFTable(DenseSet<InlinedVariable> &Processed);
/// Records information about a local variable in the appropriate scope. In
/// particular, locals from inlined code live inside the inlining site.
void recordLocalVariable(LocalVariable &&Var, const DILocation *Loc);
/// Emits local variables in the appropriate order.
void emitLocalVariableList(ArrayRef<LocalVariable> Locals);
/// Emits an S_LOCAL record and its associated defined ranges.
void emitLocalVariable(const LocalVariable &Var);
/// Translates the DIType to codeview if necessary and returns a type index
/// for it.
codeview::TypeIndex getTypeIndex(DITypeRef TypeRef,
DITypeRef ClassTyRef = DITypeRef());
codeview::TypeIndex getTypeIndexForReferenceTo(DITypeRef TypeRef);
codeview::TypeIndex getMemberFunctionType(const DISubprogram *SP,
const DICompositeType *Class);
codeview::TypeIndex getScopeIndex(const DIScope *Scope);
codeview::TypeIndex getVBPTypeIndex();
void addToUDTs(const DIType *Ty);
codeview::TypeIndex lowerType(const DIType *Ty, const DIType *ClassTy);
codeview::TypeIndex lowerTypeAlias(const DIDerivedType *Ty);
codeview::TypeIndex lowerTypeArray(const DICompositeType *Ty);
codeview::TypeIndex lowerTypeBasic(const DIBasicType *Ty);
codeview::TypeIndex lowerTypePointer(const DIDerivedType *Ty);
codeview::TypeIndex lowerTypeMemberPointer(const DIDerivedType *Ty);
codeview::TypeIndex lowerTypeModifier(const DIDerivedType *Ty);
codeview::TypeIndex lowerTypeFunction(const DISubroutineType *Ty);
codeview::TypeIndex lowerTypeVFTableShape(const DIDerivedType *Ty);
codeview::TypeIndex lowerTypeMemberFunction(const DISubroutineType *Ty,
const DIType *ClassTy,
int ThisAdjustment,
bool IsStaticMethod);
codeview::TypeIndex lowerTypeEnum(const DICompositeType *Ty);
codeview::TypeIndex lowerTypeClass(const DICompositeType *Ty);
codeview::TypeIndex lowerTypeUnion(const DICompositeType *Ty);
/// Symbol records should point to complete types, but type records should
/// always point to incomplete types to avoid cycles in the type graph. Only
/// use this entry point when generating symbol records. The complete and
/// incomplete type indices only differ for record types. All other types use
/// the same index.
codeview::TypeIndex getCompleteTypeIndex(DITypeRef TypeRef);
codeview::TypeIndex lowerCompleteTypeClass(const DICompositeType *Ty);
codeview::TypeIndex lowerCompleteTypeUnion(const DICompositeType *Ty);
struct TypeLoweringScope;
void emitDeferredCompleteTypes();
void collectMemberInfo(ClassInfo &Info, const DIDerivedType *DDTy);
ClassInfo collectClassInfo(const DICompositeType *Ty);
/// Common record member lowering functionality for record types, which are
/// structs, classes, and unions. Returns the field list index and the member
/// count.
std::tuple<codeview::TypeIndex, codeview::TypeIndex, unsigned, bool>
lowerRecordFieldList(const DICompositeType *Ty);
/// Inserts {{Node, ClassTy}, TI} into TypeIndices and checks for duplicates.
codeview::TypeIndex recordTypeIndexForDINode(const DINode *Node,
codeview::TypeIndex TI,
const DIType *ClassTy = nullptr);
unsigned getPointerSizeInBytes();
protected:
/// \brief Gather pre-function debug information.
void beginFunctionImpl(const MachineFunction *MF) override;
/// \brief Gather post-function debug information.
void endFunctionImpl(const MachineFunction *) override;
public:
CodeViewDebug(AsmPrinter *Asm);
void setSymbolSize(const MCSymbol *, uint64_t) override {}
/// \brief Emit the COFF section that holds the line table information.
void endModule() override;
/// \brief Process beginning of an instruction.
void beginInstruction(const MachineInstr *MI) override;
};
} // end namespace llvm
#endif // LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H

File diff suppressed because it is too large Load Diff

View File

@ -1,424 +0,0 @@
//===-- 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 "DIEHash.h"
#include "ByteStreamer.h"
#include "DwarfDebug.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DIE.h"
#include "llvm/Support/Debug.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) {
for (const auto &V : Die.values()) {
DEBUG(dbgs() << "Attribute: "
<< dwarf::AttributeString(V.getAttribute())
<< " added.\n");
switch (V.getAttribute()) {
#define HANDLE_DIE_HASH_ATTR(NAME) \
case dwarf::NAME: \
Attrs.NAME = V; \
break;
#include "DIEHashAttributes.def"
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(const 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::isInlineString:
addULEB128('A');
addULEB128(Attribute);
addULEB128(dwarf::DW_FORM_string);
addString(Value.getDIEInlineString().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:
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 HANDLE_DIE_HASH_ATTR(NAME) \
{ \
if (Attrs.NAME) \
hashAttribute(Attrs.NAME, Tag); \
}
#include "DIEHashAttributes.def"
// 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(StringRef DWOName, const DIE &Die) {
Numbering.clear();
Numbering[&Die] = 1;
if (!DWOName.empty())
Hash.update(DWOName);
// 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, so we actually
// need the "high" word.
return Result.high();
}
/// 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, so we actually
// need the "high" word.
return Result.high();
}

View File

@ -1,110 +0,0 @@
//===-- 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 {
#define HANDLE_DIE_HASH_ATTR(NAME) DIEValue NAME;
#include "DIEHashAttributes.def"
};
public:
DIEHash(AsmPrinter *A = nullptr) : AP(A) {}
/// \brief Computes the CU signature.
uint64_t computeCUSignature(StringRef DWOName, 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(const 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

Some files were not shown because too many files have changed in this diff Show More