Skip to content

Commit e70dcc9

Browse files
pratikasharigcbot
authored andcommitted
Simplify debug info unwinding DWARF operations
Simplify debug info unwinding DWARF operations. DW_CFA_def_cfa_expression refers to BE_SP of caller. This is same as BE_FP of current function post frame creation. As per DWARF4 spec, CFA is first pushed to stack and then DW_CFA_expression's expression is executed. This allowed IGC to emit a far simpler location expression with DW_CFA_expression.
1 parent 960ffd7 commit e70dcc9

File tree

2 files changed

+104
-75
lines changed

2 files changed

+104
-75
lines changed

IGC/DebugInfo/DwarfDebug.cpp

Lines changed: 83 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -2924,7 +2924,7 @@ uint32_t DwarfDebug::writeStackcallCIE() {
29242924
// return address register - uleb128
29252925
// set machine return register to one which is physically
29262926
// absent. later CFA instructions map this to a valid GRF.
2927-
writeULEB128(data, GetEncodedRegNum<RegisterNumbering::GRFBase>(numGRFs));
2927+
writeULEB128(data, RegisterNumbering::IP);
29282928

29292929
// initial instructions (array of ubyte)
29302930
// DW_OP_regx r125
@@ -2933,11 +2933,12 @@ uint32_t DwarfDebug::writeStackcallCIE() {
29332933

29342934
// The DW_CFA_def_cfa_expression instruction takes a single operand
29352935
// encoded as a DW_FORM_exprloc.
2936+
// We define DW_CFA_def_cfa_expression to point to caller's BE_SP.
29362937
auto DWRegEncoded = GetEncodedRegNum<RegisterNumbering::GRFBase>(specialGRF);
29372938
write(data1, (uint8_t)llvm::dwarf::DW_OP_const4u);
29382939
write(data1, (uint32_t)(DWRegEncoded));
29392940
write(data1, (uint8_t)llvm::dwarf::DW_OP_const2u);
2940-
write(data1, (uint16_t)(getBEFPSubReg() * 4 * 8));
2941+
write(data1, (uint16_t)(getBESPSubReg() * 4 * 8));
29412942
write(data1, (uint8_t)DW_OP_INTEL_regval_bits);
29422943
write(data1, (uint8_t)32);
29432944

@@ -2971,10 +2972,20 @@ uint32_t DwarfDebug::writeStackcallCIE() {
29712972
}
29722973

29732974
// move return address register to actual location
2974-
// DW_CFA_register numGRFs specialGRF
2975-
write(data, (uint8_t)llvm::dwarf::DW_CFA_register);
2976-
writeULEB128(data, GetEncodedRegNum<RegisterNumbering::GRFBase>(numGRFs));
2977-
writeULEB128(data, GetEncodedRegNum<RegisterNumbering::GRFBase>(specialGRF));
2975+
if (GetABIVersion() < 3) {
2976+
// DW_CFA_register IP specialGRF
2977+
write(data, (uint8_t)llvm::dwarf::DW_CFA_register);
2978+
writeULEB128(data, RegisterNumbering::IP);
2979+
writeULEB128(data,
2980+
GetEncodedRegNum<RegisterNumbering::GRFBase>(specialGRF));
2981+
} else {
2982+
write(data, (uint8_t)llvm::dwarf::DW_CFA_expression);
2983+
writeULEB128(data, RegisterNumbering::IP);
2984+
writeULEB128(data, 6);
2985+
write(data, (uint8_t)llvm::dwarf::DW_OP_const4u);
2986+
write(data, (uint32_t)getRetIPSubReg() * 4);
2987+
write(data, (uint8_t)llvm::dwarf::DW_OP_plus);
2988+
}
29782989

29792990
while ((lenSize + data.size()) % ptrSize != 0)
29802991
// Insert DW_CFA_nop
@@ -3103,7 +3114,6 @@ void DwarfDebug::writeFDEStackCall(VISAModule *m) {
31033114
auto sortAsc = [](uint64_t a, uint64_t b) { return a < b; };
31043115
std::map<uint64_t, std::vector<uint8_t>, decltype(sortAsc)> cfaOps(sortAsc);
31053116
const auto &DbgInfo = *VisaDbgInfo;
3106-
auto numGRFs = GetVISAModule()->getNumGRFs();
31073117
auto specialGRF = GetSpecialGRF();
31083118

31093119
auto advanceLoc = [&loc](std::vector<uint8_t> &data, uint64_t newLoc) {
@@ -3124,33 +3134,25 @@ void DwarfDebug::writeFDEStackCall(VISAModule *m) {
31243134
loc = newLoc;
31253135
};
31263136

3127-
// offset to read off be_fp
3128-
// deref - decide whether or not to emit DW_OP_deref
3129-
// normalizeResult - true when reading a value from scratch space that is a
3130-
// scratch space address
3131-
auto writeOffBEFP = [specialGRF, this](std::vector<uint8_t> &data,
3132-
uint32_t offset, bool deref,
3133-
bool normalizeResult) {
3134-
// DW_OP_const1u 12
3135-
// DW_OP_regx 125
3136-
// DW_OP_const2u 96
3137-
// DW_OP_const1u 32
3138-
// DW_OP_INTEL_push_bit_piece_stack
3139-
// DW_OP_const1u 16
3140-
// DW_OP_mul
3141-
// DW_OP_constu <memory offset>
3137+
// When useBEFP is true, expression refers to BEFP. Otherwise,
3138+
// expression refers to BESP.
3139+
auto writeOffBEStack = [specialGRF, this](std::vector<uint8_t> &data,
3140+
bool useBEFP) {
3141+
// DW_OP_const4u 127
3142+
// DW_OP_const2u BE_FP_SubReg
3143+
// DW_OP_INTEL_regval_bits 32
3144+
// DW_OP_breg6
31423145
// DW_OP_plus
3143-
// DW_OP_constu 0x900000000000000
3144-
// DW_OP_or
3145-
// DW_OP_deref
3146+
31463147
std::vector<uint8_t> data1;
31473148

31483149
auto DWRegEncoded =
31493150
GetEncodedRegNum<RegisterNumbering::GRFBase>(specialGRF);
31503151
write(data1, (uint8_t)llvm::dwarf::DW_OP_const4u);
31513152
write(data1, (uint32_t)(DWRegEncoded));
31523153
write(data1, (uint8_t)llvm::dwarf::DW_OP_const2u);
3153-
write(data1, (uint16_t)(getBEFPSubReg() * 4 * 8));
3154+
write(data1,
3155+
(uint16_t)((useBEFP ? getBEFPSubReg() : getBESPSubReg()) * 4 * 8));
31543156
write(data1, (uint8_t)DW_OP_INTEL_regval_bits);
31553157
write(data1, (uint8_t)32);
31563158

@@ -3163,49 +3165,20 @@ void DwarfDebug::writeFDEStackCall(VISAModule *m) {
31633165
write(data1, (uint8_t)llvm::dwarf::DW_OP_mul);
31643166
}
31653167

3166-
write(data1, (uint8_t)llvm::dwarf::DW_OP_constu);
3167-
writeULEB128(data1, offset);
3168-
write(data1, (uint8_t)llvm::dwarf::DW_OP_plus);
3169-
31703168
// indicate that the resulting address is on BE stack
31713169
encodeScratchAddrSpace(data1);
31723170

3173-
if (deref) {
3174-
write(data1, (uint8_t)llvm::dwarf::DW_OP_deref);
3175-
// DW_OP_deref reads as many bytes as size of address on target machine.
3176-
// We set address size to 64 bits in CIE. However, this expression
3177-
// refers to a slot in scratch space which uses 32-bit addressing. So
3178-
// mask upper 32 bits read from VISA frame descriptor.
3179-
write(data1, (uint8_t)llvm::dwarf::DW_OP_const4u);
3180-
write(data1, (uint32_t)0xffffffff);
3181-
write(data1, (uint8_t)llvm::dwarf::DW_OP_and);
3182-
}
3183-
3184-
if (EmitSettings.ScratchOffsetInOW && normalizeResult) {
3185-
// since data stored in scratch space is also in oword units, normalize it
3186-
write(data1, (uint8_t)llvm::dwarf::DW_OP_const1u);
3187-
write(data1, (uint8_t)16);
3188-
write(data1, (uint8_t)llvm::dwarf::DW_OP_mul);
3189-
}
3190-
3191-
if (deref) {
3192-
// DW_OP_deref earlier causes CFA to be put on top of dwarf stack.
3193-
// Indicate that the address space of CFA is scratch.
3194-
encodeScratchAddrSpace(data1);
3195-
}
3196-
31973171
writeULEB128(data, data1.size());
31983172
for (auto item : data1)
31993173
write(data, (uint8_t)item);
32003174
};
32013175

3202-
auto writeLR = [this, writeOffBEFP](std::vector<uint8_t> &data,
3203-
const DbgDecoder::LiveIntervalGenISA &lr,
3204-
bool deref, bool normalizeResult) {
3176+
auto writeLR = [this, writeOffBEStack](
3177+
std::vector<uint8_t> &data,
3178+
const DbgDecoder::LiveIntervalGenISA &lr, bool useBEFP) {
32053179
if (lr.var.physicalType ==
32063180
DbgDecoder::VarAlloc::PhysicalVarType::PhyTypeMemory) {
3207-
writeOffBEFP(data, (uint32_t)lr.var.mapping.m.memoryOffset, deref,
3208-
normalizeResult);
3181+
writeOffBEStack(data, useBEFP);
32093182

32103183
IGC_ASSERT_MESSAGE(!lr.var.mapping.m.isBaseOffBEFP,
32113184
"Expecting location offset from BE_FP");
@@ -3220,6 +3193,23 @@ void DwarfDebug::writeFDEStackCall(VISAModule *m) {
32203193
writeULEB128(data, srcReg);
32213194
};
32223195

3196+
// Caller has written DW_CFA_expression and a register. Here, we
3197+
// emit offset off CFA where the register is stored. For eg,
3198+
// DW_CFA_expression: r143 (DW_OP_const4u: 0; DW_OP_plus)
3199+
//
3200+
// means that r127 is stored at [CFA + 0]
3201+
auto writeCFAExpr = [](std::vector<uint8_t> &data, uint32_t offset) {
3202+
std::vector<uint8_t> data1;
3203+
3204+
write(data1, (uint8_t)llvm::dwarf::DW_OP_const4u);
3205+
write(data1, (uint32_t)offset);
3206+
write(data1, (uint8_t)llvm::dwarf::DW_OP_plus);
3207+
3208+
writeULEB128(data, data1.size());
3209+
for (auto item : data1)
3210+
write(data, (uint8_t)item);
3211+
};
3212+
32233213
auto ptrSize = Asm->GetPointerSize();
32243214
const auto &CFI = DbgInfo.getCFI();
32253215
// Emit CIE
@@ -3258,15 +3248,15 @@ void DwarfDebug::writeFDEStackCall(VISAModule *m) {
32583248
// map out CFA to an offset on be stack
32593249
write(cfaOps[item.start],
32603250
(uint8_t)llvm::dwarf::DW_CFA_def_cfa_expression);
3261-
writeLR(cfaOps[item.start], item, true, true);
3251+
writeLR(cfaOps[item.start], item, true);
32623252
}
32633253

32643254
// describe r125 is at [r125.3]:ud
32653255
auto ip = callerFP.front().start;
32663256
write(cfaOps[ip], (uint8_t)llvm::dwarf::DW_CFA_expression);
32673257
writeULEB128(cfaOps[ip],
32683258
GetEncodedRegNum<RegisterNumbering::GRFBase>(specialGRF));
3269-
writeOffBEFP(cfaOps[ip], 0, false, false);
3259+
writeCFAExpr(cfaOps[ip], 0);
32703260
writeSameValue(cfaOps[callerFP.back().end + MovGenInstSizeInBytes],
32713261
GetEncodedRegNum<RegisterNumbering::GRFBase>(specialGRF));
32723262
}
@@ -3277,9 +3267,8 @@ void DwarfDebug::writeFDEStackCall(VISAModule *m) {
32773267
for (auto &item : retAddr) {
32783268
// start live-range
32793269
write(cfaOps[item.start], (uint8_t)llvm::dwarf::DW_CFA_expression);
3280-
writeULEB128(cfaOps[item.start],
3281-
GetEncodedRegNum<RegisterNumbering::GRFBase>(numGRFs));
3282-
writeLR(cfaOps[item.start], item, false, false);
3270+
writeULEB128(cfaOps[item.start], RegisterNumbering::IP);
3271+
writeCFAExpr(cfaOps[item.start], getRetIPSubReg() * 4);
32833272

32843273
// end live-range
32853274
// VISA emits following:
@@ -3298,20 +3287,39 @@ void DwarfDebug::writeFDEStackCall(VISAModule *m) {
32983287
// offset 656 should we read ret %ip from r125 directly. This is achieved
32993288
// by taking offset 640 reported by VISA debug info and adding 16 to it
33003289
// which is size of the mov instruction.
3301-
write(cfaOps[item.end + MovGenInstSizeInBytes],
3302-
(uint8_t)llvm::dwarf::DW_CFA_register);
3303-
writeULEB128(cfaOps[item.end + MovGenInstSizeInBytes],
3304-
GetEncodedRegNum<RegisterNumbering::GRFBase>(numGRFs));
3305-
writeULEB128(
3306-
cfaOps[item.end + MovGenInstSizeInBytes],
3307-
GetEncodedRegNum<RegisterNumbering::GRFBase>(GetSpecialGRF()));
3290+
// move return address register to actual location
3291+
if (GetABIVersion() < 3) {
3292+
// DW_CFA_register IP specialGRF
3293+
write(cfaOps[item.end + MovGenInstSizeInBytes],
3294+
(uint8_t)llvm::dwarf::DW_CFA_register);
3295+
writeULEB128(cfaOps[item.end + MovGenInstSizeInBytes],
3296+
RegisterNumbering::IP);
3297+
writeULEB128(cfaOps[item.end + MovGenInstSizeInBytes],
3298+
GetEncodedRegNum<RegisterNumbering::GRFBase>(specialGRF));
3299+
} else {
3300+
std::vector<uint8_t> data1;
3301+
auto DWRegEncoded =
3302+
GetEncodedRegNum<RegisterNumbering::GRFBase>(specialGRF);
3303+
write(cfaOps[item.end + MovGenInstSizeInBytes],
3304+
(uint8_t)llvm::dwarf::DW_CFA_expression);
3305+
writeULEB128(cfaOps[item.end + MovGenInstSizeInBytes],
3306+
RegisterNumbering::IP);
3307+
write(data1, (uint8_t)llvm::dwarf::DW_OP_const4u);
3308+
write(data1, (uint32_t)(DWRegEncoded));
3309+
write(data1, (uint8_t)llvm::dwarf::DW_OP_const2u);
3310+
write(data1, (uint16_t)(getRetIPSubReg() * 4));
3311+
write(data1, (uint8_t)DW_OP_INTEL_regval_bits);
3312+
write(data1, (uint8_t)32);
3313+
writeULEB128(cfaOps[item.end + MovGenInstSizeInBytes], data1.size());
3314+
for (auto byte : data1)
3315+
write(cfaOps[item.end + MovGenInstSizeInBytes], (uint8_t)byte);
3316+
}
33083317
}
33093318
} else {
33103319
if (m->GetType() == VISAModule::ObjectType::KERNEL) {
33113320
// set return location to be undefined in top frame
33123321
write(cfaOps[0], (uint8_t)llvm::dwarf::DW_CFA_undefined);
3313-
writeULEB128(cfaOps[0],
3314-
GetEncodedRegNum<RegisterNumbering::GRFBase>(numGRFs));
3322+
writeULEB128(cfaOps[0], RegisterNumbering::IP);
33153323
}
33163324
}
33173325

@@ -3330,8 +3338,8 @@ void DwarfDebug::writeFDEStackCall(VISAModule *m) {
33303338
(uint8_t)llvm::dwarf::DW_CFA_expression);
33313339
writeULEB128(cfaOps[item.genIPOffset],
33323340
GetEncodedRegNum<RegisterNumbering::GRFBase>(regNum));
3333-
writeOffBEFP(cfaOps[item.genIPOffset],
3334-
item.data[idx].dst.m.memoryOffset, false, false);
3341+
writeCFAExpr(cfaOps[item.genIPOffset],
3342+
(uint32_t)item.data[idx].dst.m.memoryOffset);
33353343
calleeSaveRegsSaved.insert(regNum);
33363344
} else {
33373345
// already saved, so no need to emit same save again

IGC/DebugInfo/DwarfDebug.hpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,27 @@ class DwarfDebug {
745745
return BEFPSubReg_3;
746746
}
747747

748+
uint32_t getBESPSubReg() {
749+
auto ver = GetABIVersion();
750+
if (ver < 3)
751+
return BESPSubReg_1_2;
752+
return BESPSubReg_3;
753+
}
754+
755+
uint32_t getRetIPSubReg() {
756+
auto ver = GetABIVersion();
757+
if (ver < 3)
758+
return RetIpSubReg_1_2;
759+
return RetIpSubReg_3;
760+
}
761+
762+
uint32_t RetIpByteSize() {
763+
auto ver = GetABIVersion();
764+
if (ver < 3)
765+
return 4;
766+
return 8;
767+
}
768+
748769
private:
749770
void encodeRange(CompileUnit *TheCU, DIE *ScopeDIE,
750771
const llvm::SmallVectorImpl<InsnRange> *Ranges);

0 commit comments

Comments
 (0)