Skip to content

Commit 18759d5

Browse files
slinder1jmmartinezepilk
committed
[Dwarf] Support heterogeneous DW_{OP,AT}s needed for AMDGPU CFI
These are defined in the user range until standard versions of them get adopted into dwarf, which is expected in DWARF6. Some of these amount to reservations currently as no code to use them is included. It would be very helpful to get them committed to avoid conflicts necessitating encoding changes while we are in the process of upstreaming. Co-authored-by: Juan Martinez Fernandez <[email protected]> Co-authored-by: Emma Pilkington <[email protected]> (cherry picked from commit dc1c1aec483feba48fd0c0acd855c17d239d07ef)
1 parent ad07f49 commit 18759d5

File tree

6 files changed

+89
-42
lines changed

6 files changed

+89
-42
lines changed

llvm/include/llvm/BinaryFormat/Dwarf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1027,7 +1027,7 @@ LLVM_ABI StringRef FormatString(DwarfFormat Format);
10271027
LLVM_ABI StringRef FormatString(bool IsDWARF64);
10281028
LLVM_ABI StringRef RLEString(unsigned RLE);
10291029
LLVM_ABI StringRef MemorySpaceString(unsigned MS);
1030-
LLVM_ABI StringRef AddressSpaceString(unsigned AS, llvm::Triple TT);
1030+
LLVM_ABI StringRef AddressSpaceString(unsigned AS, const llvm::Triple &TT);
10311031
/// @}
10321032

10331033
/// \defgroup DwarfConstantsParsing Dwarf constants parsing functions

llvm/include/llvm/Support/AMDGPUAddrSpace.h

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,19 @@ enum : unsigned {
133133
};
134134
} // namespace DWARFAS
135135

136+
namespace impl {
137+
// TODO: Move this into mapToDWARFAddrSpace when we switch to C++23
138+
// (see https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2647r1.html)
139+
static constexpr unsigned LLVMToDWARFAddrSpaceMapping[] = {
140+
DWARFAS::GENERIC, //< AMDGPUAS::FLAT_ADDRESS
141+
DWARFAS::GLOBAL, //< AMDGPUAS::GLOBAL_ADDRESS
142+
DWARFAS::REGION, //< AMDGPUAS::REGION_ADDRESS
143+
DWARFAS::LOCAL, //< AMDGPUAS::LOCAL_ADDRESS
144+
DWARFAS::GLOBAL, //< AMDGPUAS::CONSTANT_ADDRESS
145+
DWARFAS::PRIVATE_LANE //< AMDGPUAS::PRIVATE_ADDRESS
146+
};
147+
} // end namespace impl
148+
136149
/// If @p LLVMAddressSpace has a corresponding DWARF encoding,
137150
/// return it; otherwise return the sentinel value -1 to indicate
138151
/// no such mapping exists.
@@ -144,20 +157,12 @@ enum : unsigned {
144157
///
145158
/// Note: This could return std::optional<int> but that would require
146159
/// an extra #include.
147-
inline int mapToDWARFAddrSpace(unsigned LLVMAddrSpace) {
148-
static constexpr unsigned LLVMToDWARFAddrSpaceMapping[] = {
149-
DWARFAS::GENERIC, //< AMDGPUAS::FLAT_ADDRESS
150-
DWARFAS::GLOBAL, //< AMDGPUAS::GLOBAL_ADDRESS
151-
DWARFAS::REGION, //< AMDGPUAS::REGION_ADDRESS
152-
DWARFAS::LOCAL, //< AMDGPUAS::LOCAL_ADDRESS
153-
DWARFAS::GLOBAL, //< AMDGPUAS::CONSTANT_ADDRESS
154-
DWARFAS::PRIVATE_LANE //< AMDGPUAS::PRIVATE_ADDRESS
155-
};
156-
static constexpr unsigned SizeOfLLVMToDWARFAddrSpaceMapping =
157-
sizeof(LLVMToDWARFAddrSpaceMapping) /
158-
sizeof(LLVMToDWARFAddrSpaceMapping[0]);
160+
constexpr int mapToDWARFAddrSpace(unsigned LLVMAddrSpace) {
161+
constexpr unsigned SizeOfLLVMToDWARFAddrSpaceMapping =
162+
sizeof(impl::LLVMToDWARFAddrSpaceMapping) /
163+
sizeof(impl::LLVMToDWARFAddrSpaceMapping[0]);
159164
if (LLVMAddrSpace < SizeOfLLVMToDWARFAddrSpaceMapping)
160-
return LLVMToDWARFAddrSpaceMapping[LLVMAddrSpace];
165+
return impl::LLVMToDWARFAddrSpaceMapping[LLVMAddrSpace];
161166
return -1;
162167
}
163168
} // end namespace AMDGPU

llvm/lib/BinaryFormat/Dwarf.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -939,7 +939,7 @@ StringRef llvm::dwarf::MemorySpaceString(unsigned MS) {
939939
}
940940
}
941941

942-
StringRef llvm::dwarf::AddressSpaceString(unsigned AS, llvm::Triple TT) {
942+
StringRef llvm::dwarf::AddressSpaceString(unsigned AS, const llvm::Triple &TT) {
943943
switch (AS) {
944944
#define HANDLE_DW_ASPACE(ID, NAME) \
945945
case DW_ASPACE_LLVM_##NAME: \

llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,8 @@ static bool printOp(const DWARFExpression::Operation *Op, raw_ostream &OS,
6767
(Op->getCode() >= DW_OP_reg0 && Op->getCode() <= DW_OP_reg31) ||
6868
Op->getCode() == DW_OP_bregx || Op->getCode() == DW_OP_regx ||
6969
Op->getCode() == DW_OP_regval_type ||
70-
Op->getCode() == DW_OP_LLVM_call_frame_entry_reg ||
71-
Op->getCode() == DW_OP_LLVM_aspace_bregx ||
72-
(SubOpcode && (*SubOpcode == DW_OP_LLVM_call_frame_entry_reg ||
73-
*SubOpcode == DW_OP_LLVM_aspace_bregx))) {
70+
SubOpcode == DW_OP_LLVM_call_frame_entry_reg ||
71+
SubOpcode == DW_OP_LLVM_aspace_bregx) {
7472
if (prettyPrintRegisterOp(U, OS, DumpOpts, Op->getCode(),
7573
Op->getRawOperands()))
7674
return true;
@@ -100,22 +98,20 @@ static bool printOp(const DWARFExpression::Operation *Op, raw_ostream &OS,
10098
StringRef Name = OperationEncodingString(Op->getCode());
10199
assert(!Name.empty() && "DW_OP has no name!");
102100
OS << Name;
103-
}
104101

105-
if (SubOpcode) {
106-
StringRef SubName = SubOperationEncodingString(Op->getCode(), *SubOpcode);
107-
assert(!SubName.empty() && "DW_OP SubOp has no name!");
108-
OS << " " << SubName;
102+
if (SubOpcode) {
103+
StringRef SubName = SubOperationEncodingString(Op->getCode(), *SubOpcode);
104+
assert(!SubName.empty() && "DW_OP SubOp has no name!");
105+
OS << ' ' << SubName;
106+
}
109107
}
110108

111109
if ((Op->getCode() >= DW_OP_breg0 && Op->getCode() <= DW_OP_breg31) ||
112110
(Op->getCode() >= DW_OP_reg0 && Op->getCode() <= DW_OP_reg31) ||
113111
Op->getCode() == DW_OP_bregx || Op->getCode() == DW_OP_regx ||
114112
Op->getCode() == DW_OP_regval_type ||
115-
Op->getCode() == DW_OP_LLVM_call_frame_entry_reg ||
116-
Op->getCode() == DW_OP_LLVM_aspace_bregx ||
117-
(SubOpcode && (*SubOpcode == DW_OP_LLVM_call_frame_entry_reg ||
118-
*SubOpcode == DW_OP_LLVM_aspace_bregx)))
113+
SubOpcode == DW_OP_LLVM_call_frame_entry_reg ||
114+
SubOpcode == DW_OP_LLVM_aspace_bregx)
119115
if (prettyPrintRegisterOp(U, OS, DumpOpts, Op->getCode(),
120116
Op->getRawOperands()))
121117
return true;
@@ -127,8 +123,8 @@ static bool printOp(const DWARFExpression::Operation *Op, raw_ostream &OS,
127123
unsigned Signed = Size & DWARFExpression::Operation::SignBit;
128124

129125
if (Size == DWARFExpression::Operation::SizeSubOpLEB) {
130-
assert(Operand == 0);
131-
assert(SubOpcode);
126+
assert(Operand == 0 && "DW_OP SubOp must be the first operand");
127+
assert(SubOpcode && "DW_OP SubOp description is inconsistent");
132128
} else if (Size == DWARFExpression::Operation::BaseTypeRef && U) {
133129
// For DW_OP_convert the operand may be 0 to indicate that conversion to
134130
// the generic type should be done. The same holds for
@@ -225,6 +221,19 @@ static bool printCompactDWARFExpr(
225221
nullptr) {
226222
SmallVector<PrintedExpr, 4> Stack;
227223

224+
auto UnknownOpcode = [](raw_ostream &OS, uint8_t Opcode,
225+
std::optional<unsigned> SubOpcode) -> bool {
226+
// If we hit an unknown operand, we don't know its effect on the stack,
227+
// so bail out on the whole expression.
228+
OS << "<unknown op " << dwarf::OperationEncodingString(Opcode) << " ("
229+
<< (int)Opcode;
230+
if (SubOpcode)
231+
OS << ") subop " << dwarf::SubOperationEncodingString(Opcode, *SubOpcode)
232+
<< " (" << *SubOpcode;
233+
OS << ")>";
234+
return false;
235+
};
236+
228237
while (I != E) {
229238
const DWARFExpression::Operation &Op = *I;
230239
uint8_t Opcode = Op.getCode();
@@ -277,8 +286,10 @@ static bool printCompactDWARFExpr(
277286
break;
278287
}
279288
case dwarf::DW_OP_LLVM_user: {
280-
assert(Op.getSubCode());
281-
break;
289+
std::optional<unsigned> SubOpcode = Op.getSubCode();
290+
if (SubOpcode == dwarf::DW_OP_LLVM_nop)
291+
break;
292+
return UnknownOpcode(OS, Opcode, SubOpcode);
282293
}
283294
default:
284295
if (Opcode >= dwarf::DW_OP_reg0 && Opcode <= dwarf::DW_OP_reg31) {
@@ -302,11 +313,7 @@ static bool printCompactDWARFExpr(
302313
if (Offset)
303314
S << format("%+" PRId64, Offset);
304315
} else {
305-
// If we hit an unknown operand, we don't know its effect on the stack,
306-
// so bail out on the whole expression.
307-
OS << "<unknown op " << dwarf::OperationEncodingString(Opcode) << " ("
308-
<< (int)Opcode << ")>";
309-
return false;
316+
return UnknownOpcode(OS, Opcode, std::nullopt);
310317
}
311318
break;
312319
}
@@ -346,8 +353,8 @@ bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS,
346353
SubOpcode = Operands[OpNum++];
347354

348355
if (Opcode == DW_OP_bregx || Opcode == DW_OP_regx ||
349-
Opcode == DW_OP_regval_type ||
350-
(SubOpcode && *SubOpcode == DW_OP_LLVM_aspace_bregx))
356+
Opcode == DW_OP_regval_type || SubOpcode == DW_OP_LLVM_aspace_bregx ||
357+
SubOpcode == DW_OP_LLVM_call_frame_entry_reg)
351358
DwarfRegNum = Operands[OpNum++];
352359
else if (Opcode == DW_OP_LLVM_call_frame_entry_reg ||
353360
(SubOpcode && *SubOpcode == DW_OP_LLVM_call_frame_entry_reg))
@@ -360,9 +367,7 @@ bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS,
360367
auto RegName = DumpOpts.GetNameForDWARFReg(DwarfRegNum, DumpOpts.IsEH);
361368
if (!RegName.empty()) {
362369
if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) ||
363-
Opcode == DW_OP_bregx ||
364-
(Opcode == DW_OP_LLVM_aspace_bregx ||
365-
(SubOpcode && *SubOpcode == DW_OP_LLVM_aspace_bregx)))
370+
Opcode == DW_OP_bregx || SubOpcode == DW_OP_LLVM_aspace_bregx)
366371
OS << ' ' << RegName << format("%+" PRId64, Operands[OpNum]);
367372
else
368373
OS << ' ' << RegName.data();
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# RUN: llvm-mc %s -filetype=obj -triple=i686-pc-linux -o - | llvm-dwarfdump --debug-frame - | FileCheck %s
2+
3+
# CHECK: .eh_frame contents:
4+
# CHECK: FDE
5+
# CHECK-NEXT: Format: DWARF32
6+
7+
foo:
8+
.cfi_startproc
9+
# CHECK-NEXT: DW_CFA_expression: EAX DW_OP_LLVM_user DW_OP_LLVM_form_aspace_address
10+
.cfi_escape 0x10, 0x00, 0x02, 0xe9, 0x02
11+
# CHECK-NEXT: DW_CFA_expression: EAX DW_OP_LLVM_user DW_OP_LLVM_push_lane
12+
.cfi_escape 0x10, 0x00, 0x02, 0xe9, 0x03
13+
# CHECK-NEXT: DW_CFA_expression: EAX DW_OP_LLVM_user DW_OP_LLVM_offset
14+
.cfi_escape 0x10, 0x00, 0x02, 0xe9, 0x04
15+
# CHECK-NEXT: DW_CFA_expression: EAX DW_OP_LLVM_user DW_OP_LLVM_offset_uconst 0x0
16+
.cfi_escape 0x10, 0x00, 0x03, 0xe9, 0x05, 0x00
17+
# CHECK-NEXT: DW_CFA_expression: EAX DW_OP_LLVM_user DW_OP_LLVM_bit_offset
18+
.cfi_escape 0x10, 0x00, 0x02, 0xe9, 0x06
19+
# CHECK-NEXT: DW_CFA_expression: EAX DW_OP_LLVM_user DW_OP_LLVM_call_frame_entry_reg EAX
20+
.cfi_escape 0x10, 0x00, 0x03, 0xe9, 0x07, 0x00
21+
# CHECK-NEXT: DW_CFA_expression: EAX DW_OP_LLVM_user DW_OP_LLVM_undefined
22+
.cfi_escape 0x10, 0x00, 0x02, 0xe9, 0x08
23+
# CHECK-NEXT: DW_CFA_expression: EAX DW_OP_LLVM_user DW_OP_LLVM_aspace_bregx EAX+2
24+
.cfi_escape 0x10, 0x00, 0x04, 0xe9, 0x09, 0x00, 0x02
25+
# CHECK-NEXT: DW_CFA_expression: EAX DW_OP_LLVM_user DW_OP_LLVM_piece_end
26+
.cfi_escape 0x10, 0x00, 0x02, 0xe9, 0x0a
27+
# CHECK-NEXT: DW_CFA_expression: EAX DW_OP_LLVM_user DW_OP_LLVM_extend 0x0 0x0
28+
.cfi_escape 0x10, 0x00, 0x04, 0xe9, 0x0b, 0x00, 0x00
29+
# CHECK-NEXT: DW_CFA_expression: EAX DW_OP_LLVM_user DW_OP_LLVM_select_bit_piece 0x0 0x0
30+
.cfi_escape 0x10, 0x00, 0x04, 0xe9, 0x0c, 0x00, 0x00
31+
.cfi_endproc

llvm/unittests/DebugInfo/DWARF/DWARFExpressionCompactPrinterTest.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,9 @@ TEST_F(DWARFExpressionCompactPrinterTest, Test_OP_nop_OP_reg) {
141141
TEST_F(DWARFExpressionCompactPrinterTest, Test_OP_LLVM_nop_OP_reg) {
142142
TestExprPrinter({DW_OP_LLVM_user, DW_OP_LLVM_nop, DW_OP_reg0}, "R0");
143143
}
144+
145+
TEST_F(DWARFExpressionCompactPrinterTest, Test_OP_LLVM_user_unknown_subop) {
146+
TestExprPrinter({DW_OP_LLVM_user, DW_OP_LLVM_form_aspace_address},
147+
"<unknown op DW_OP_LLVM_user (233) subop "
148+
"DW_OP_LLVM_form_aspace_address (2)>");
149+
}

0 commit comments

Comments
 (0)