summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp100
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h18
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp187
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h16
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp36
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h11
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp4
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h2
-rw-r--r--llvm/lib/CodeGen/TargetInstrInfo.cpp40
-rw-r--r--llvm/lib/CodeGen/TargetRegisterInfo.cpp14
10 files changed, 390 insertions, 38 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 4163fdbb177..09780cc350e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -890,32 +890,106 @@ void DwarfCompileUnit::constructAbstractSubprogramScopeDIE(
ContextCU->addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer);
}
+dwarf::Tag DwarfCompileUnit::getDwarf5OrGNUCallSiteTag(dwarf::Tag Tag) {
+ bool ApplyGNUExtensions = DD->getDwarfVersion() == 4 && DD->tuneForGDB();
+ if (!ApplyGNUExtensions)
+ return Tag;
+ switch(Tag) {
+ case dwarf::DW_TAG_call_site:
+ return dwarf::DW_TAG_GNU_call_site;
+ case dwarf::DW_TAG_call_site_parameter:
+ return dwarf::DW_TAG_GNU_call_site_parameter;
+ default:
+ llvm_unreachable("unhandled call site tag");
+ }
+}
+
+dwarf::Attribute DwarfCompileUnit::getDwarf5OrGNUCallSiteAttr(dwarf::Attribute Attr) {
+ bool ApplyGNUExtensions = DD->getDwarfVersion() == 4 && DD->tuneForGDB();
+ if (!ApplyGNUExtensions)
+ return Attr;
+ switch(Attr) {
+ case dwarf::DW_AT_call_all_calls:
+ return dwarf::DW_AT_GNU_all_call_sites;
+ case dwarf::DW_AT_call_target:
+ return dwarf::DW_AT_GNU_call_site_target;
+ case dwarf::DW_AT_call_origin:
+ return dwarf::DW_AT_abstract_origin;
+ case dwarf::DW_AT_call_pc:
+ return dwarf::DW_AT_low_pc;
+ case dwarf::DW_AT_call_value:
+ return dwarf::DW_AT_GNU_call_site_value;
+ case dwarf::DW_AT_call_tail_call:
+ return dwarf::DW_AT_GNU_tail_call;
+ default:
+ llvm_unreachable("unhandled call site attribute");
+ }
+}
+
DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE,
- const DISubprogram &CalleeSP,
+ const DISubprogram *CalleeSP,
bool IsTail,
- const MCExpr *PCOffset) {
+ const MCSymbol *PCAddr,
+ const MCExpr *PCOffset,
+ unsigned CallReg) {
// Insert a call site entry DIE within ScopeDIE.
DIE &CallSiteDIE =
- createAndAddDIE(dwarf::DW_TAG_call_site, ScopeDIE, nullptr);
+ createAndAddDIE(getDwarf5OrGNUCallSiteTag(dwarf::DW_TAG_call_site),
+ ScopeDIE, nullptr);
- // For the purposes of showing tail call frames in backtraces, a key piece of
- // information is DW_AT_call_origin, a pointer to the callee DIE.
- DIE *CalleeDIE = getOrCreateSubprogramDIE(&CalleeSP);
- assert(CalleeDIE && "Could not create DIE for call site entry origin");
- addDIEEntry(CallSiteDIE, dwarf::DW_AT_call_origin, *CalleeDIE);
+ if (CallReg) {
+ // Indirect call.
+ addAddress(CallSiteDIE, getDwarf5OrGNUCallSiteAttr(dwarf::DW_AT_call_target),
+ MachineLocation(CallReg));
+ } else {
+ DIE *CalleeDIE = getOrCreateSubprogramDIE(CalleeSP);
+ assert(CalleeDIE && "Could not create DIE for call site entry origin");
+ addDIEEntry(CallSiteDIE, getDwarf5OrGNUCallSiteAttr(dwarf::DW_AT_call_origin),
+ *CalleeDIE);
+ }
- if (IsTail) {
+ if (IsTail)
// Attach DW_AT_call_tail_call to tail calls for standards compliance.
- addFlag(CallSiteDIE, dwarf::DW_AT_call_tail_call);
- } else {
- // Attach the return PC to allow the debugger to disambiguate call paths
- // from one function to another.
+ addFlag(CallSiteDIE, getDwarf5OrGNUCallSiteAttr(dwarf::DW_AT_call_tail_call));
+
+ // Attach the return PC to allow the debugger to disambiguate call paths
+ // from one function to another.
+ if (DD->getDwarfVersion() == 4 && DD->tuneForGDB()) {
+ assert(PCAddr && "Missing PC information for a call");
+ addLabelAddress(CallSiteDIE, dwarf::DW_AT_low_pc, PCAddr);
+ } else if (!IsTail || DD->tuneForGDB()) {
assert(PCOffset && "Missing return PC information for a call");
addAddressExpr(CallSiteDIE, dwarf::DW_AT_call_return_pc, PCOffset);
}
+
return CallSiteDIE;
}
+void DwarfCompileUnit::constructCallSiteParmEntryDIEs(
+ DIE &CallSiteDIE, SmallVector<DbgCallSiteParam, 4> &Params) {
+ for (auto &Param : Params) {
+ unsigned Register = Param.getRegister();
+ auto CallSiteDieParam =
+ DIE::get(DIEValueAllocator,
+ getDwarf5OrGNUCallSiteTag(dwarf::DW_TAG_call_site_parameter));
+ insertDIE(CallSiteDieParam);
+ addAddress(*CallSiteDieParam, dwarf::DW_AT_location,
+ MachineLocation(Register));
+
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+ DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
+ DwarfExpr.setCallSiteParamValueFlag();
+
+ DwarfDebug::emitDebugLocValue(*Asm, nullptr, Param.getValue(), DwarfExpr);
+
+ addBlock(*CallSiteDieParam,
+ getDwarf5OrGNUCallSiteAttr(dwarf::DW_AT_call_value),
+ DwarfExpr.finalize());
+
+ CallSiteDIE.addChild(CallSiteDieParam);
+ }
+}
+
DIE *DwarfCompileUnit::constructImportedEntityDIE(
const DIImportedEntity *Module) {
DIE *IMDie = DIE::get(DIEValueAllocator, (dwarf::Tag)Module->getTag());
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
index ea980dfda17..0c2e66d3f09 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
@@ -227,12 +227,22 @@ public:
void constructAbstractSubprogramScopeDIE(LexicalScope *Scope);
+ dwarf::Tag getDwarf5OrGNUCallSiteTag(dwarf::Tag Tag);
+ dwarf::Attribute getDwarf5OrGNUCallSiteAttr(dwarf::Attribute Attr);
+
/// Construct a call site entry DIE describing a call within \p Scope to a
/// callee described by \p CalleeSP. \p IsTail specifies whether the call is
- /// a tail call. \p PCOffset must be non-zero for non-tail calls or be the
- /// function-local offset to PC value after the call instruction.
- DIE &constructCallSiteEntryDIE(DIE &ScopeDIE, const DISubprogram &CalleeSP,
- bool IsTail, const MCExpr *PCOffset);
+ /// a tail call. \p PCAddr (used for GDB + DWARF 4 tuning) points to
+ /// the PC value after the call instruction. \p PCOffset (used for
+ /// cases other than GDB + DWARF 4 tuning) must be non-zero for non-tail calls
+ /// (in the case of non-gdb tuning) or be the function-local offset to PC value
+ /// after the call instruction. \p CallReg is a register location
+ /// for an indirect call.
+ DIE &constructCallSiteEntryDIE(DIE &ScopeDIE, const DISubprogram *CalleeSP,
+ bool IsTail, const MCSymbol *PCAddr,
+ const MCExpr *PCOffset, unsigned CallReg);
+ void constructCallSiteParmEntryDIEs(DIE &CallSiteDIE,
+ SmallVector<DbgCallSiteParam, 4> &Params);
/// Construct import_module DIE.
DIE *constructImportedEntityDIE(const DIImportedEntity *Module);
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 71bb2b0858c..6c6349d4987 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -26,6 +26,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/Dwarf.h"
@@ -39,6 +40,7 @@
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
@@ -83,6 +85,8 @@ using namespace llvm;
#define DEBUG_TYPE "dwarfdebug"
+STATISTIC(NumCSParams, "Number of dbg call site params created");
+
static cl::opt<bool>
DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden,
cl::desc("Disable debug info printing"));
@@ -551,6 +555,123 @@ void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU,
}
}
+/// Try to interpret values loaded into registers that forward parameters
+/// for \p CallMI. Store parameters with interpreted value into \p Params.
+static void collectCallSiteParameters(const MachineInstr *CallMI,
+ ParamSet &Params) {
+ auto *MF = CallMI->getMF();
+ auto CalleesMap = MF->getCallSitesInfo();
+ auto CallFwdRegsInfo = CalleesMap.find(CallMI);
+
+ // There is no information for the call instruction.
+ if (CallFwdRegsInfo == CalleesMap.end())
+ return;
+
+ auto *MBB = CallMI->getParent();
+ const auto &TRI = MF->getSubtarget().getRegisterInfo();
+ const auto &TII = MF->getSubtarget().getInstrInfo();
+ const auto &TLI = MF->getSubtarget().getTargetLowering();
+
+ // Skip the call instruction.
+ auto I = std::next(CallMI->getReverseIterator());
+
+ DenseSet<unsigned> ArgsRegsForProcess;
+ for (auto ArgReg : CallFwdRegsInfo->second)
+ ArgsRegsForProcess.insert(ArgReg.Reg);
+
+ // If we did not find loading a value into forwarding registers
+ // that means we can try generating 'DW_OP_entry_value' for the argument
+ // if a call is within entry MBB.
+ DenseMap<unsigned, unsigned> RegsForEntryValues;
+ bool ShouldTryEmitEntryVals = MBB->getIterator() == MF->begin();
+
+ // Return true if it is an instruction over a parameter's forwarding
+ // register that clobbers it.
+ auto shouldInterpret = [&](const MachineInstr &MI) -> unsigned {
+ if (MI.isDebugInstr())
+ return 0;
+ // If a MI clobbers a forwarding reg try to interpret
+ // a value loaded into the reg.
+ for (const MachineOperand &MO : MI.operands()) {
+ if (MO.isReg() && MO.isDef() && MO.getReg() &&
+ TRI->isPhysicalRegister(MO.getReg())) {
+ for (auto FwdReg : ArgsRegsForProcess)
+ if (TRI->regsOverlap(FwdReg, MO.getReg()))
+ return FwdReg;
+ }
+ }
+
+ return 0;
+ };
+
+ auto finishCallSiteParam = [&](DbgValueLoc &DbgLocVal,
+ unsigned &Reg) {
+ unsigned FwdReg = Reg;
+ if (ShouldTryEmitEntryVals && RegsForEntryValues.count(Reg))
+ FwdReg = RegsForEntryValues[Reg];
+ DbgCallSiteParam CSParm(FwdReg, DbgLocVal);
+ Params.push_back(CSParm);
+ NumCSParams++;
+ };
+
+ // Search for a loading value in forwaring registers.
+ while (I != MBB->rend()) {
+ // If the next instruction is a call we can not
+ // interpret parameter's forwarding registers or
+ // we finished interpretation of all parameters.
+ if (I->isCall())
+ return;
+
+ if (ArgsRegsForProcess.empty())
+ return;
+
+ if (unsigned Reg = shouldInterpret(*I)) {
+ ArgsRegsForProcess.erase(Reg);
+ const MachineOperand *Op;
+ DIExpression *Expr;
+ if (auto ParamValue = TII->describeLoadedValue(*I)) {
+ Op = ParamValue->first;
+ Expr = ParamValue->second;
+ if (Op->isImm()) {
+ unsigned Val = Op->getImm();
+ DbgValueLoc DbgLocVal(Expr, Val);
+ finishCallSiteParam(DbgLocVal, Reg);
+ } else if (Op->isReg()) {
+ unsigned RegLoc = Op->getReg();
+ unsigned SP = TLI->getStackPointerRegisterToSaveRestore();
+ unsigned FP = TRI->getFrameRegister(*MF);
+ bool IsSPorFP = (RegLoc == SP) || (RegLoc == FP);
+ if (TRI->isCallerPreservedPhysReg(RegLoc, *MF) || IsSPorFP) {
+ DbgValueLoc DbgLocVal(
+ Expr, MachineLocation(RegLoc, IsSPorFP));
+ finishCallSiteParam(DbgLocVal, Reg);
+ } else if (ShouldTryEmitEntryVals) {
+ ArgsRegsForProcess.insert(RegLoc);
+ RegsForEntryValues[RegLoc] = Reg;
+ }
+ }
+ }
+ }
+
+ ++I;
+ }
+
+ // Emit call site parameter's value as entry value.
+ if (ShouldTryEmitEntryVals) {
+ DIExpression *EntryExpr = DIExpression::get(MF->getFunction().getContext(),
+ {dwarf::DW_OP_entry_value, 1});
+ for (auto RegEntry : ArgsRegsForProcess) {
+ unsigned FwdReg = RegsForEntryValues.count(RegEntry)
+ ? RegsForEntryValues[RegEntry]
+ : RegEntry;
+ DbgValueLoc DbgLocVal(EntryExpr, MachineLocation(RegEntry));
+ DbgCallSiteParam CSParm(FwdReg, DbgLocVal);
+ Params.push_back(CSParm);
+ NumCSParams++;
+ }
+ }
+}
+
void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
DwarfCompileUnit &CU, DIE &ScopeDIE,
const MachineFunction &MF) {
@@ -563,10 +684,13 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
// for both tail and non-tail calls. Don't use DW_AT_call_all_source_calls
// because one of its requirements is not met: call site entries for
// optimized-out calls are elided.
- CU.addFlag(ScopeDIE, dwarf::DW_AT_call_all_calls);
+ CU.addFlag(ScopeDIE,
+ CU.getDwarf5OrGNUCallSiteAttr(dwarf::DW_AT_call_all_calls));
const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
assert(TII && "TargetInstrInfo not found: cannot label tail calls");
+ const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
+ bool ApplyGNUExtensions = getDwarfVersion() == 4 && tuneForGDB();
// Emit call site entries for each call or tail call in the function.
for (const MachineBasicBlock &MBB : MF) {
@@ -581,30 +705,65 @@ void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
return;
// If this is a direct call, find the callee's subprogram.
+ // In the case of an indirect call find the register that holds
+ // the callee.
const MachineOperand &CalleeOp = MI.getOperand(0);
- if (!CalleeOp.isGlobal())
- continue;
- const Function *CalleeDecl = dyn_cast<Function>(CalleeOp.getGlobal());
- if (!CalleeDecl || !CalleeDecl->getSubprogram())
+ if (!CalleeOp.isGlobal() && !CalleeOp.isReg())
continue;
+ unsigned CallReg = 0;
+ const DISubprogram *CalleeSP = nullptr;
+ const Function *CalleeDecl = nullptr;
+ if (CalleeOp.isReg()) {
+ CallReg = CalleeOp.getReg();
+ if (!CallReg)
+ continue;
+ } else {
+ CalleeDecl = dyn_cast<Function>(CalleeOp.getGlobal());
+ if (!CalleeDecl || !CalleeDecl->getSubprogram())
+ continue;
+ CalleeSP = CalleeDecl->getSubprogram();
+ }
+
// TODO: Omit call site entries for runtime calls (objc_msgSend, etc).
- // TODO: Add support for indirect calls.
bool IsTail = TII->isTailCall(MI);
- // For tail calls, no return PC information is needed. For regular calls,
- // the return PC is needed to disambiguate paths in the call graph which
- // could lead to some target function.
+ // For tail calls, for non-gdb tuning, no return PC information is needed.
+ // For regular calls (and tail calls in GDB tuning), the return PC
+ // is needed to disambiguate paths in the call graph which could lead to
+ // some target function.
const MCExpr *PCOffset =
- IsTail ? nullptr : getFunctionLocalOffsetAfterInsn(&MI);
+ (IsTail && !tuneForGDB()) ? nullptr
+ : getFunctionLocalOffsetAfterInsn(&MI);
+
+ // Address of a call-like instruction for a normal call or a jump-like
+ // instruction for a tail call. This is needed for GDB + DWARF 4 tuning.
+ const MCSymbol *PCAddr =
+ ApplyGNUExtensions ? const_cast<MCSymbol*>(getLabelAfterInsn(&MI))
+ : nullptr;
+
+ assert((IsTail || PCOffset || PCAddr) &&
+ "Call without return PC information");
- assert((IsTail || PCOffset) && "Call without return PC information");
LLVM_DEBUG(dbgs() << "CallSiteEntry: " << MF.getName() << " -> "
- << CalleeDecl->getName() << (IsTail ? " [tail]" : "")
+ << (CalleeDecl ? CalleeDecl->getName()
+ : StringRef(TRI->getName(CallReg)))
+ << (IsTail ? " [IsTail]" : "")
<< "\n");
- CU.constructCallSiteEntryDIE(ScopeDIE, *CalleeDecl->getSubprogram(),
- IsTail, PCOffset);
+
+ DIE &CallSiteDIE =
+ CU.constructCallSiteEntryDIE(ScopeDIE, CalleeSP, IsTail, PCAddr,
+ PCOffset, CallReg);
+
+ // For now only GDB supports call site parameter debug info.
+ if (Asm->TM.Options.EnableDebugEntryValues &&
+ tuneForGDB()) {
+ ParamSet Params;
+ // Try to interpret values of call site parameters.
+ collectCallSiteParameters(&MI, Params);
+ CU.constructCallSiteParmEntryDIEs(CallSiteDIE, Params);
+ }
}
}
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 3ac474e2bdd..1c9de983ea1 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -254,6 +254,22 @@ public:
}
};
+/// Used for tracking debug info about call site parameters.
+class DbgCallSiteParam {
+private:
+ unsigned Register;
+ DbgValueLoc Value;
+public:
+ DbgCallSiteParam(unsigned Reg, DbgValueLoc Val)
+ : Register(Reg), Value(Val) {}
+
+ unsigned getRegister() { return Register; }
+ DbgValueLoc getValue() { return Value; }
+};
+
+/// Collection used for storing debug call site parameters.
+using ParamSet = SmallVector<DbgCallSiteParam, 4>;
+
/// Helper used to pair up a symbol and its DWARF compile unit.
struct SymbolCU {
SymbolCU(DwarfCompileUnit *CU, const MCSymbol *Sym) : Sym(Sym), CU(CU) {}
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
index 2858afaa1cf..436852bda92 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -241,15 +241,20 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
return false;
}
- // Handle simple register locations.
- if (!isMemoryLocation() && !HasComplexExpression) {
+ // Handle simple register locations. If we are supposed to
+ // emit a call site parameter expression and if that expression
+ // is just a register location, emit it with addBReg and offset 0,
+ // because we should emit a DWARF expression representing a value,
+ // rather than a location.
+ if (!isMemoryLocation() && !HasComplexExpression &&
+ (!isParameterValue() || isEntryValue())) {
for (auto &Reg : DwarfRegs) {
if (Reg.DwarfRegNo >= 0)
addReg(Reg.DwarfRegNo, Reg.Comment);
addOpPiece(Reg.Size);
}
- if (isEntryValue() && DwarfVersion >= 4)
+ if (isEntryValue() && !isParameterValue() && DwarfVersion >= 4)
emitOp(dwarf::DW_OP_stack_value);
DwarfRegs.clear();
@@ -340,7 +345,16 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
while (ExprCursor) {
auto Op = ExprCursor.take();
- switch (Op->getOp()) {
+ uint64_t OpNum = Op->getOp();
+ if (OpNum >= dwarf::DW_OP_reg0 && OpNum <= dwarf::DW_OP_reg31) {
+ if (isParameterValue())
+ addBReg(OpNum - dwarf::DW_OP_reg0, 0);
+ else
+ emitOp(OpNum);
+ continue;
+ }
+
+ switch (OpNum) {
case dwarf::DW_OP_LLVM_fragment: {
unsigned SizeInBits = Op->getArg(1);
unsigned FragmentOffset = Op->getArg(0);
@@ -389,7 +403,7 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
case dwarf::DW_OP_lit0:
case dwarf::DW_OP_not:
case dwarf::DW_OP_dup:
- emitOp(Op->getOp());
+ emitOp(OpNum);
break;
case dwarf::DW_OP_deref:
assert(!isRegisterLocation());
@@ -458,12 +472,22 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
case dwarf::DW_OP_LLVM_tag_offset:
TagOffset = Op->getArg(0);
break;
+ case dwarf::DW_OP_regx:
+ if (isParameterValue()) {
+ emitOp(dwarf::DW_OP_bregx);
+ emitUnsigned(Op->getArg(0));
+ emitSigned(Op->getArg(1));
+ } else {
+ emitOp(dwarf::DW_OP_regx);
+ emitUnsigned(Op->getArg(0));
+ }
+ break;
default:
llvm_unreachable("unhandled opcode found in expression");
}
}
- if (isImplicitLocation())
+ if (isImplicitLocation() && !isParameterValue())
// Turn this into an implicit location description.
addStackValue();
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
index ec2ef6e575f..9f9baf8c1a1 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
@@ -120,7 +120,7 @@ protected:
enum { Unknown = 0, Register, Memory, Implicit };
/// The flags of location description being produced.
- enum { EntryValue = 1 };
+ enum { EntryValue = 1, CallSiteParamValue };
unsigned LocationKind : 3;
unsigned LocationFlags : 2;
@@ -147,6 +147,10 @@ public:
return LocationFlags & EntryValue;
}
+ bool isParameterValue() {
+ return LocationFlags & CallSiteParamValue;
+ }
+
Optional<uint8_t> TagOffset;
protected:
@@ -264,6 +268,11 @@ public:
LocationFlags |= EntryValue;
}
+ /// Lock this down to become a call site parameter location.
+ void setCallSiteParamValueFlag() {
+ LocationFlags |= CallSiteParamValue;
+ }
+
/// Emit a machine register location. As an optimization this may also consume
/// the prefix of a DwarfExpression if a more efficient representation for
/// combining the register location and the first operation exists.
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 991ab94b50a..4990ea66cc1 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -205,6 +205,10 @@ void DwarfUnit::insertDIE(const DINode *Desc, DIE *D) {
MDNodeToDieMap.insert(std::make_pair(Desc, D));
}
+void DwarfUnit::insertDIE(DIE *D) {
+ MDNodeToDieMap.insert(std::make_pair(nullptr, D));
+}
+
void DwarfUnit::addFlag(DIE &Die, dwarf::Attribute Attribute) {
if (DD->getDwarfVersion() >= 4)
Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_flag_present,
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
index 56c934a35ae..a376d5e75f6 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
@@ -127,6 +127,8 @@ public:
/// the mappings are kept in DwarfDebug.
void insertDIE(const DINode *Desc, DIE *D);
+ void insertDIE(DIE *D);
+
/// Add a flag that is true to the DIE.
void addFlag(DIE &Die, dwarf::Attribute Attribute);
diff --git a/llvm/lib/CodeGen/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp
index 868617ffe14..f7f3e11f18a 100644
--- a/llvm/lib/CodeGen/TargetInstrInfo.cpp
+++ b/llvm/lib/CodeGen/TargetInstrInfo.cpp
@@ -23,6 +23,7 @@
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSchedule.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCInstrItineraries.h"
#include "llvm/Support/CommandLine.h"
@@ -1120,6 +1121,45 @@ bool TargetInstrInfo::hasLowDefLatency(const TargetSchedModel &SchedModel,
return (DefCycle != -1 && DefCycle <= 1);
}
+Optional<ParamLoadedValue>
+TargetInstrInfo::describeLoadedValue(const MachineInstr &MI) const {
+ const MachineOperand *Op = nullptr;
+ DIExpression *Expr = nullptr;
+
+ const MachineOperand *SrcRegOp, *DestRegOp;
+ const MachineFunction *MF = MI.getMF();
+ if (isCopyInstr(MI, SrcRegOp, DestRegOp)) {
+ Expr = DIExpression::get(MF->getFunction().getContext(), {});
+ Op = SrcRegOp;
+ return ParamLoadedValue(Op, Expr);
+ } else if (MI.isMoveImmediate()) {
+ Expr = DIExpression::get(MF->getFunction().getContext(), {});
+ Op = &MI.getOperand(1);
+ return ParamLoadedValue(Op, Expr);
+ } else if (MI.hasOneMemOperand()) {
+ int64_t Offset;
+ const auto &TRI = MF->getSubtarget().getRegisterInfo();
+ const auto &TII = MF->getSubtarget().getInstrInfo();
+ const MachineOperand *BaseOp;
+ if (!TII->getMemOperandWithOffset(MI, BaseOp, Offset, TRI))
+ return None;
+ unsigned CastedOffset = static_cast<unsigned>(Offset);
+ if (Offset > 0)
+ Expr = DIExpression::get(
+ MF->getFunction().getContext(),
+ {dwarf::DW_OP_plus_uconst, CastedOffset, dwarf::DW_OP_deref});
+ else
+ Expr = DIExpression::get(MF->getFunction().getContext(),
+ {dwarf::DW_OP_constu, -CastedOffset,
+ dwarf::DW_OP_minus, dwarf::DW_OP_deref});
+
+ Op = BaseOp;
+ return ParamLoadedValue(Op, Expr);
+ }
+
+ return None;
+}
+
/// Both DefMI and UseMI must be valid. By default, call directly to the
/// itinerary. This may be overriden by the target.
int TargetInstrInfo::getOperandLatency(const InstrItineraryData *ItinData,
diff --git a/llvm/lib/CodeGen/TargetRegisterInfo.cpp b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
index f1b2ecf3243..b5a4419e6b8 100644
--- a/llvm/lib/CodeGen/TargetRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
@@ -433,6 +433,20 @@ TargetRegisterInfo::getRegAllocationHints(unsigned VirtReg,
return false;
}
+bool
+TargetRegisterInfo::isCallerPreservedPhysReg(unsigned PhysReg,
+ const MachineFunction &MF) const {
+ if (PhysReg == 0)
+ return false;
+ const uint32_t *callerPreservedRegs =
+ getCallPreservedMask(MF, MF.getFunction().getCallingConv());
+ if (callerPreservedRegs) {
+ assert(isPhysicalRegister(PhysReg) && "Expected physical register");
+ return (callerPreservedRegs[PhysReg / 32] >> PhysReg % 32) & 1;
+ }
+ return false;
+}
+
bool TargetRegisterInfo::canRealignStack(const MachineFunction &MF) const {
return !MF.getFunction().hasFnAttribute("no-realign-stack");
}
OpenPOWER on IntegriCloud