Skip to content

Commit 2b06beb

Browse files
pratikasharsys_zuul
authored andcommitted
Emission of caller save ranges to debug info for stack call functions.
Change-Id: I4aeff51baf402fbf9d3d2f745943e40b09f391d6
1 parent f36246e commit 2b06beb

File tree

7 files changed

+246
-36
lines changed

7 files changed

+246
-36
lines changed

IGC/DebugInfo/DwarfCompileUnit.cpp

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,11 +1009,39 @@ void CompileUnit::addBindlessSamplerLocation(IGC::DIEBlock* Block, VISAVariableL
10091009
}
10101010
}
10111011

1012+
void CompileUnit::addBE_FP(IGC::DIEBlock* Block)
1013+
{
1014+
// Add BE_FP value to spill offset if BE_FP is non-null. This is required when generating
1015+
// debug info for stack call functions.
1016+
// DW_OP_constu <regNum>
1017+
// DW_OP_INTEL_regs
1018+
// DW_OP_const2u <subRegNum * 8>
1019+
// DW_OP_const2u <32>
1020+
// DW_OP_plus
1021+
uint32_t BE_FP_RegNum = 0, BE_FP_SubRegNum = 0;
1022+
bool hasValidBEFP = DD->GetVISAModule()->getCompileUnit()->cfi.getBEFPRegNum(BE_FP_RegNum, BE_FP_SubRegNum);
1023+
if (!hasValidBEFP)
1024+
return;
1025+
1026+
auto DWRegEncoded = GetEncodedRegNum<RegisterNumbering::GRFBase>(
1027+
BE_FP_RegNum, EmitSettings.UseNewRegisterEncoding);
1028+
addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
1029+
addUInt(Block, dwarf::DW_FORM_udata, DWRegEncoded); // Register ID is shifted by offset
1030+
addUInt(Block, dwarf::DW_FORM_data1, DW_OP_INTEL_regs);
1031+
1032+
addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_const2u);
1033+
addUInt(Block, dwarf::DW_FORM_data2, BE_FP_SubRegNum * 8u); // sub-reg offset in bits
1034+
addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_const1u);
1035+
addUInt(Block, dwarf::DW_FORM_data1, 32); // size of BE_FP ptr
1036+
addUInt(Block, dwarf::DW_FORM_data1, DW_OP_INTEL_push_bit_piece_stack);
1037+
addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_plus);
1038+
}
1039+
10121040
// addScratchLocation - add a sequence of attributes to emit scratch space location
10131041
// of variable
1014-
void CompileUnit::addScratchLocation(IGC::DIEBlock* Block, DbgDecoder::LiveIntervalsVISA* lr, int32_t vectorOffset)
1042+
void CompileUnit::addScratchLocation(IGC::DIEBlock* Block, uint32_t memoryOffset, int32_t vectorOffset)
10151043
{
1016-
uint32_t offset = lr->getSpillOffset().memoryOffset + vectorOffset;
1044+
uint32_t offset = memoryOffset + vectorOffset;
10171045

10181046
IGC_ASSERT_MESSAGE(EmitSettings.EnableSIMDLaneDebugging, "SIMD lane expressions support only");
10191047

@@ -2525,13 +2553,15 @@ IGC::DIEBlock* CompileUnit::buildGeneral(DbgVariable& var, std::vector<VISAVaria
25252553

25262554
addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_const8u);
25272555
addUInt(Block, dwarf::DW_FORM_data8, addr.GetAddress());
2556+
addBE_FP(Block);
25282557
addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
25292558
}
25302559
else
25312560
{
25322561
if (loc->IsVectorized() == false)
25332562
{
2534-
addScratchLocation(Block, &lrToUse, 0);
2563+
addScratchLocation(Block, lrToUse.getSpillOffset().memoryOffset, 0);
2564+
addBE_FP(Block);
25352565
}
25362566
else
25372567
{
@@ -2543,7 +2573,8 @@ IGC::DIEBlock* CompileUnit::buildGeneral(DbgVariable& var, std::vector<VISAVaria
25432573

25442574
for (unsigned int vectorElem = 0; vectorElem < loc->GetVectorNumElements(); ++vectorElem)
25452575
{
2546-
addScratchLocation(Block, &lrToUse, vectorElem * numOfRegs * grfSize);
2576+
addScratchLocation(Block, lrToUse.getSpillOffset().memoryOffset, vectorElem * numOfRegs * grfSize);
2577+
addBE_FP(Block);
25472578
addSimdLane(Block, var, loc, &lrToUse, 0, false, !firstHalf); // Emit SIMD lane for spill (unpacked)
25482579
}
25492580
}

IGC/DebugInfo/DwarfCompileUnit.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,12 @@ namespace IGC
281281
void addBindlessSamplerLocation(DIEBlock* Block, VISAVariableLocation* Loc);
282282

283283

284+
// addBE_FP - emits operations to add contents of BE_FP to current top of dwarf stack
285+
void addBE_FP(IGC::DIEBlock* Block);
286+
284287
// addScratchLocation - add a sequence of attributes to emit scratch space location
285288
// of variable
286-
void addScratchLocation(DIEBlock* Block, DbgDecoder::LiveIntervalsVISA* lr, int32_t vectorOffset);
289+
void addScratchLocation(DIEBlock* Block, uint32_t memoryOffset, int32_t vectorOffset);
287290

288291

289292
// addSLMLocation - add a sequence of attributes to emit SLM location of variable

IGC/DebugInfo/DwarfDebug.cpp

Lines changed: 80 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,6 +1333,8 @@ void DwarfDebug::collectVariableInfo(const Function* MF, SmallPtrSet<const MDNod
13331333
std::vector<std::tuple<MDNode*, DILocation*, DbgVariable*>> addedEntries;
13341334
std::map<llvm::DIScope*, std::vector<llvm::Instruction*>> instsInScope;
13351335

1336+
TempDotDebugLocEntries.clear();
1337+
13361338
auto isAdded = [&addedEntries](MDNode* md, DILocation* iat)
13371339
{
13381340
for (auto item : addedEntries)
@@ -1386,9 +1388,13 @@ void DwarfDebug::collectVariableInfo(const Function* MF, SmallPtrSet<const MDNod
13861388
return startEnd;
13871389
};
13881390

1389-
auto encodeImm = [&](IGC::DotDebugLocEntry& dotLoc, uint64_t rangeStart, uint64_t rangeEnd,
1391+
auto encodeImm = [&](IGC::DotDebugLocEntry& dotLoc, uint32_t offset,
1392+
llvm::SmallVector<DotDebugLocEntry, 4>& TempDotDebugLocEntries,
1393+
uint64_t rangeStart, uint64_t rangeEnd,
13901394
uint32_t pointerSize, DbgVariable* RegVar, const ConstantInt* pConstInt)
13911395
{
1396+
auto oldSize = dotLoc.loc.size();
1397+
13921398
auto op = llvm::dwarf::DW_OP_implicit_value;
13931399
const unsigned int lebSize = 8;
13941400
write(dotLoc.loc, (unsigned char*)&rangeStart, pointerSize);
@@ -1406,23 +1412,81 @@ void DwarfDebug::collectVariableInfo(const Function* MF, SmallPtrSet<const MDNod
14061412
int64_t constValue = pConstInt->getSExtValue();
14071413
write(dotLoc.loc, (unsigned char*)&constValue, lebSize);
14081414
}
1415+
offset += dotLoc.loc.size() - oldSize;
1416+
1417+
TempDotDebugLocEntries.push_back(dotLoc);
14091418
};
14101419

1411-
auto encodeReg = [&](IGC::DotDebugLocEntry& dotLoc, uint64_t startRange, uint64_t endRange,
1420+
auto encodeReg = [&](IGC::DotDebugLocEntry& dotLoc, uint32_t offset,
1421+
llvm::SmallVector<DotDebugLocEntry, 4>& TempDotDebugLocEntries,
1422+
uint64_t startRange, uint64_t endRange,
14121423
uint32_t pointerSize, DbgVariable* RegVar, std::vector<VISAVariableLocation>& Locs,
14131424
DbgDecoder::LiveIntervalsVISA& genIsaRange)
14141425
{
1415-
write(dotLoc.loc, (unsigned char*)&startRange, pointerSize);
1416-
write(dotLoc.loc, (unsigned char*)&endRange, pointerSize);
1417-
1426+
auto allCallerSave = m_pModule->getAllCallerSave(startRange, endRange, genIsaRange);
14181427
std::vector<DbgDecoder::LiveIntervalsVISA> vars = { genIsaRange };
1428+
1429+
auto oldSize = dotLoc.loc.size();
1430+
dotLoc.start = startRange;
1431+
TempDotDebugLocEntries.push_back(dotLoc);
1432+
write(TempDotDebugLocEntries.back().loc, (unsigned char*)&startRange, pointerSize);
1433+
1434+
for (auto it : allCallerSave)
1435+
{
1436+
TempDotDebugLocEntries.back().end = std::get<0>(it);
1437+
write(TempDotDebugLocEntries.back().loc, (unsigned char*)&std::get<0>(it), pointerSize);
1438+
auto block = FirstCU->buildGeneral(*RegVar, &Locs, &vars);
1439+
std::vector<unsigned char> buffer;
1440+
if (block)
1441+
block->EmitToRawBuffer(buffer);
1442+
write(TempDotDebugLocEntries.back().loc, (uint16_t)buffer.size());
1443+
write(TempDotDebugLocEntries.back().loc, buffer.data(), buffer.size());
1444+
1445+
offset += TempDotDebugLocEntries.back().loc.size() - oldSize;
1446+
1447+
DotDebugLocEntry another(dotLoc.getStart(), dotLoc.getEnd(), dotLoc.getDbgInst(), dotLoc.getVariable());
1448+
another.start = std::get<0>(it);
1449+
another.end = std::get<1>(it);
1450+
TempDotDebugLocEntries.push_back(another);
1451+
oldSize = TempDotDebugLocEntries.back().loc.size();
1452+
// write actual caller save location
1453+
write(TempDotDebugLocEntries.back().loc, (unsigned char*)&std::get<0>(it), pointerSize);
1454+
write(TempDotDebugLocEntries.back().loc, (unsigned char*)&std::get<1>(it), pointerSize);
1455+
auto callerSaveVars = vars;
1456+
callerSaveVars.front().var.physicalType = DbgDecoder::VarAlloc::PhysicalVarType::PhyTypeMemory;
1457+
callerSaveVars.front().var.mapping.m.isBaseOffBEFP = 0;
1458+
callerSaveVars.front().var.mapping.m.memoryOffset = std::get<2>(it);
1459+
block = FirstCU->buildGeneral(*RegVar, &Locs, &callerSaveVars);
1460+
buffer.clear();
1461+
if (block)
1462+
block->EmitToRawBuffer(buffer);
1463+
write(TempDotDebugLocEntries.back().loc, (uint16_t)buffer.size());
1464+
write(TempDotDebugLocEntries.back().loc, buffer.data(), buffer.size());
1465+
1466+
offset += TempDotDebugLocEntries.back().loc.size() - oldSize;
1467+
1468+
if (std::get<1>(it) >= endRange)
1469+
return;
1470+
1471+
// start new interval with original location
1472+
DotDebugLocEntry yetAnother(dotLoc.getStart(), dotLoc.getEnd(), dotLoc.getDbgInst(), dotLoc.getVariable());
1473+
yetAnother.start = std::get<1>(it);
1474+
TempDotDebugLocEntries.push_back(yetAnother);
1475+
oldSize = TempDotDebugLocEntries.back().loc.size();
1476+
write(TempDotDebugLocEntries.back().loc, (unsigned char*)&std::get<1>(it), pointerSize);
1477+
}
1478+
1479+
TempDotDebugLocEntries.back().end = endRange;
1480+
write(TempDotDebugLocEntries.back().loc, (unsigned char*)&endRange, pointerSize);
1481+
14191482
auto block = FirstCU->buildGeneral(*RegVar, &Locs, &vars);
14201483
std::vector<unsigned char> buffer;
14211484
if (block)
14221485
block->EmitToRawBuffer(buffer);
1423-
write(dotLoc.loc, (uint16_t)buffer.size());
1424-
write(dotLoc.loc, buffer.data(), buffer.size());
1486+
write(TempDotDebugLocEntries.back().loc, (uint16_t)buffer.size());
1487+
write(TempDotDebugLocEntries.back().loc, buffer.data(), buffer.size());
14251488

1489+
offset += TempDotDebugLocEntries.back().loc.size() - oldSize;
14261490
};
14271491

14281492
unsigned int offset = 0;
@@ -1508,7 +1572,8 @@ void DwarfDebug::collectVariableInfo(const Function* MF, SmallPtrSet<const MDNod
15081572
AbsVar->setDbgInst(pInst);
15091573
}
15101574

1511-
if (!m_pModule->isDirectElfInput || !EmitSettings.EmitDebugLoc)
1575+
bool needsCallerSave = m_pModule->getCompileUnit()->cfi.numCallerSaveEntries > 0;
1576+
if ((!m_pModule->isDirectElfInput || !EmitSettings.EmitDebugLoc) && !needsCallerSave)
15121577
continue;
15131578

15141579
// assume that VISA preserves location thoughout its lifetime
@@ -1540,7 +1605,7 @@ void DwarfDebug::collectVariableInfo(const Function* MF, SmallPtrSet<const MDNod
15401605
auto GenISARange = m_pModule->getGenISARange(InsnRange);
15411606

15421607
// Emit location within the DIE for dbg.declare
1543-
if (History.size() == 1 && isa<DbgDeclareInst>(pInst))
1608+
if (History.size() == 1 && isa<DbgDeclareInst>(pInst) && !needsCallerSave)
15441609
continue;
15451610

15461611
for (auto range : GenISARange)
@@ -1578,22 +1643,20 @@ void DwarfDebug::collectVariableInfo(const Function* MF, SmallPtrSet<const MDNod
15781643
};
15791644

15801645
PrevLoc p;
1581-
auto encodePrevLoc = [&](DotDebugLocEntry& dotLoc, unsigned int& offset)
1646+
auto encodePrevLoc = [&](DotDebugLocEntry& dotLoc, llvm::SmallVector<DotDebugLocEntry, 4>& TempDotDebugLocEntries, unsigned int& offset)
15821647
{
15831648
if (p.dbgVar->getDotDebugLocOffset() == ~0U)
15841649
{
15851650
p.dbgVar->setDotDebugLocOffset(offset);
15861651
}
1587-
auto oldSize = dotLoc.loc.size();
15881652
if (p.t == PrevLoc::Type::Imm)
15891653
{
1590-
encodeImm(dotLoc, p.start, p.end, pointerSize, p.dbgVar, p.imm);
1654+
encodeImm(dotLoc, offset, TempDotDebugLocEntries, p.start, p.end, pointerSize, p.dbgVar, p.imm);
15911655
}
15921656
else
15931657
{
1594-
encodeReg(dotLoc, p.start, p.end, pointerSize, p.dbgVar, p.Locs, p.genIsaRange);
1658+
encodeReg(dotLoc, offset, TempDotDebugLocEntries, p.start, p.end, pointerSize, p.dbgVar, p.Locs, p.genIsaRange);
15951659
}
1596-
offset += dotLoc.loc.size() - oldSize;
15971660
p.t = PrevLoc::Type::Empty;
15981661
};
15991662
for (auto& range : d.second)
@@ -1640,8 +1703,7 @@ void DwarfDebug::collectVariableInfo(const Function* MF, SmallPtrSet<const MDNod
16401703
if (p.t != PrevLoc::Type::Empty)
16411704
{
16421705
// Emit previous location to debug_loc
1643-
encodePrevLoc(dotLoc, offset);
1644-
TempDotDebugLocEntries.push_back(dotLoc);
1706+
encodePrevLoc(dotLoc, TempDotDebugLocEntries, offset);
16451707
}
16461708

16471709
p.t = PrevLoc::Type::Imm;
@@ -1697,8 +1759,7 @@ void DwarfDebug::collectVariableInfo(const Function* MF, SmallPtrSet<const MDNod
16971759

16981760
if (p.t != PrevLoc::Type::Empty)
16991761
{
1700-
encodePrevLoc(dotLoc, offset);
1701-
TempDotDebugLocEntries.push_back(dotLoc);
1762+
encodePrevLoc(dotLoc, TempDotDebugLocEntries, offset);
17021763
}
17031764

17041765
p.t = PrevLoc::Type::Reg;
@@ -1716,8 +1777,7 @@ void DwarfDebug::collectVariableInfo(const Function* MF, SmallPtrSet<const MDNod
17161777
{
17171778
DotDebugLocEntry dotLoc(p.start, p.end, p.pInst, DV);
17181779
dotLoc.setOffset(offset);
1719-
encodePrevLoc(dotLoc, offset);
1720-
TempDotDebugLocEntries.push_back(dotLoc);
1780+
encodePrevLoc(dotLoc, TempDotDebugLocEntries, offset);
17211781
}
17221782

17231783
if (TempDotDebugLocEntries.size() > origLocSize)
@@ -1786,7 +1846,6 @@ unsigned int DwarfDebug::CopyDebugLoc(unsigned int o)
17861846
{
17871847
// Append data to DotLocEntries
17881848
DotDebugLocEntries.push_back(TempDotDebugLocEntries[index]);
1789-
17901849
if (TempDotDebugLocEntries[index].isEmpty())
17911850
{
17921851
done = true;

IGC/DebugInfo/DwarfDebug.hpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,7 @@ namespace IGC
8585
/// section.
8686
class DotDebugLocEntry
8787
{
88-
// Begin and end symbols for the address range that this location is valid.
89-
const llvm::MCSymbol* Begin = nullptr;
90-
const llvm::MCSymbol* End = nullptr;
91-
9288
// start/end %ip
93-
const uint64_t start = 0;
94-
const uint64_t end = 0;
9589
uint32_t offset = 0;
9690

9791
// The location in the machine frame.
@@ -101,18 +95,19 @@ namespace IGC
10195
const llvm::MDNode* Variable;
10296

10397
public:
104-
DotDebugLocEntry() : Begin(0), End(0), m_pDbgInst(nullptr), Variable(nullptr) { }
98+
uint64_t start = 0;
99+
uint64_t end = 0;
100+
101+
DotDebugLocEntry() : m_pDbgInst(nullptr), Variable(nullptr) { }
105102
DotDebugLocEntry(const llvm::MCSymbol* B, const llvm::MCSymbol* E, const llvm::Instruction* pDbgInst, const llvm::MDNode* V)
106-
: Begin(B), End(E), m_pDbgInst(pDbgInst), Variable(V) { }
103+
: m_pDbgInst(pDbgInst), Variable(V) { }
107104
DotDebugLocEntry(const uint64_t s, const uint64_t e, const llvm::Instruction* pDbgInst, const llvm::MDNode* V)
108105
: start(s), end(e), m_pDbgInst(pDbgInst), Variable(V) {}
109106

110107
/// \brief Empty entries are also used as a trigger to emit temp label. Such
111108
/// labels are referenced is used to find debug_loc offset for a given DIE.
112109
bool isEmpty() { return start == 0 && end == 0; }
113110
const llvm::MDNode* getVariable() const { return Variable; }
114-
const llvm::MCSymbol* getBeginSym() const { return Begin; }
115-
const llvm::MCSymbol* getEndSym() const { return End; }
116111
const llvm::Instruction* getDbgInst() const { return m_pDbgInst; }
117112
uint64_t getStart() const { return start; }
118113
uint64_t getEnd() const { return end; }
@@ -645,6 +640,7 @@ namespace IGC
645640

646641
return m_pModule->isDirectElfInput;
647642
}
643+
648644
private:
649645
// Store all DISubprogram nodes from LLVM IR as they are no longer available
650646
// in DICompileUnit
@@ -706,6 +702,7 @@ namespace IGC
706702
}
707703
unsigned int CopyDebugLoc(unsigned int offset);
708704

705+
const VISAModule* GetVISAModule() { return m_pModule; }
709706

710707
private:
711708
void encodeRange(CompileUnit* TheCU, DIE* ScopeDIE, const llvm::SmallVectorImpl<InsnRange>* Ranges);

IGC/DebugInfo/VISAIDebugEmitter.hpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3232
#include "llvm/IR/Instruction.h"
3333
#include "common/LLVMWarningsPop.hpp"
3434

35+
#include "Probe/Assertion.h"
36+
3537
#include <string>
3638
#include <vector>
3739

@@ -186,6 +188,17 @@ namespace IGC
186188
return false;
187189
}
188190

191+
bool isSpillOnStack()
192+
{
193+
if (!isSpill())
194+
return false;
195+
196+
if(var.mapping.m.isBaseOffBEFP == 0)
197+
return true;
198+
199+
return false;
200+
}
201+
189202
Mapping::Register getGRF()
190203
{
191204
return var.mapping.r;
@@ -247,6 +260,22 @@ namespace IGC
247260
std::vector<PhyRegSaveInfoPerIP> calleeSaveEntry;
248261
uint16_t numCallerSaveEntries = 0;
249262
std::vector<PhyRegSaveInfoPerIP> callerSaveEntry;
263+
264+
bool getBEFPRegNum(uint32_t& regNum, uint32_t& subRegNum)
265+
{
266+
if (befp.size() == 0)
267+
return false;
268+
269+
// Assume that be_fp is available throughout the function
270+
// and at the same location.
271+
IGC_ASSERT(befp.front().var.physicalType == VarAlloc::PhyTypeGRF &&
272+
"BE_FP not in register");
273+
274+
regNum = befp.front().var.mapping.r.regNum;
275+
subRegNum = befp.front().var.mapping.r.subRegNum;
276+
277+
return true;
278+
}
250279
};
251280
class DbgInfoFormat
252281
{

0 commit comments

Comments
 (0)