Skip to content

Commit 56f1b63

Browse files
authored
[Dwarf] Support heterogeneous DW_{OP,AT}s needed for AMDGPU CFI (llvm#4057)
2 parents 85ae7aa + 18759d5 commit 56f1b63

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)