You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.207
Former-commit-id: 3b152f462918d427ce18620a2cbe4f8b79650449
This commit is contained in:
parent
8e12397d70
commit
eb85e2fc17
1006
external/llvm/lib/CodeGen/AggressiveAntiDepBreaker.cpp
vendored
1006
external/llvm/lib/CodeGen/AggressiveAntiDepBreaker.cpp
vendored
File diff suppressed because it is too large
Load Diff
184
external/llvm/lib/CodeGen/AggressiveAntiDepBreaker.h
vendored
184
external/llvm/lib/CodeGen/AggressiveAntiDepBreaker.h
vendored
@ -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
|
55
external/llvm/lib/CodeGen/AllocationOrder.cpp
vendored
55
external/llvm/lib/CodeGen/AllocationOrder.cpp
vendored
@ -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
|
||||
}
|
96
external/llvm/lib/CodeGen/AllocationOrder.h
vendored
96
external/llvm/lib/CodeGen/AllocationOrder.h
vendored
@ -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
|
723
external/llvm/lib/CodeGen/Analysis.cpp
vendored
723
external/llvm/lib/CodeGen/Analysis.cpp
vendored
File diff suppressed because it is too large
Load Diff
88
external/llvm/lib/CodeGen/AntiDepBreaker.h
vendored
88
external/llvm/lib/CodeGen/AntiDepBreaker.h
vendored
@ -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
|
@ -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);
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
@ -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
|
@ -1 +0,0 @@
|
||||
bf36cccd750b62edff26214e0b80f7bf2db27d68
|
@ -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);
|
||||
}
|
@ -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
110
external/llvm/lib/CodeGen/AsmPrinter/ByteStreamer.h
vendored
110
external/llvm/lib/CodeGen/AsmPrinter/ByteStreamer.h
vendored
@ -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
|
@ -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
|
||||
)
|
2464
external/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
vendored
2464
external/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
vendored
File diff suppressed because it is too large
Load Diff
350
external/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
vendored
350
external/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
vendored
@ -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
|
826
external/llvm/lib/CodeGen/AsmPrinter/DIE.cpp
vendored
826
external/llvm/lib/CodeGen/AsmPrinter/DIE.cpp
vendored
File diff suppressed because it is too large
Load Diff
424
external/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp
vendored
424
external/llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp
vendored
@ -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();
|
||||
}
|
110
external/llvm/lib/CodeGen/AsmPrinter/DIEHash.h
vendored
110
external/llvm/lib/CodeGen/AsmPrinter/DIEHash.h
vendored
@ -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
Reference in New Issue
Block a user