Skip to content

Commit 8c5e848

Browse files
committed
[WebAssembly] Add DBG_VALUE with local operands location in WebAssemblyExplicitLocals pass
Extends DWARF expression larguage to express locals/globals locations. (via target-index operands) The WebAssemblyExplicitLocals can replace virtual registers to target-index() operand type at the time when WebAssembly backend introduces local.{get,set,tee} instead of corresponding virtual registers. Reviewers: aprantl, dschuff Differential Revision: https://reviews.llvm.org/D52634
1 parent a27fbee commit 8c5e848

15 files changed

+171
-4
lines changed

llvm/include/llvm/BinaryFormat/Dwarf.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,8 @@ HANDLE_DW_OP(0xa9, reinterpret, 5, DWARF)
627627
// Vendor extensions:
628628
// Extensions for GNU-style thread-local storage.
629629
HANDLE_DW_OP(0xe0, GNU_push_tls_address, 0, GNU)
630+
// Extensions for WebAssembly.
631+
HANDLE_DW_OP(0xed, WASM_location, 0, WASM)
630632
// Extensions for Fission proposal.
631633
HANDLE_DW_OP(0xfb, GNU_addr_index, 0, GNU)
632634
HANDLE_DW_OP(0xfc, GNU_const_index, 0, GNU)

llvm/include/llvm/BinaryFormat/Dwarf.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ enum LLVMConstants : uint32_t {
5959
DWARF_VENDOR_GNU = 3,
6060
DWARF_VENDOR_GOOGLE = 4,
6161
DWARF_VENDOR_LLVM = 5,
62-
DWARF_VENDOR_MIPS = 6
62+
DWARF_VENDOR_MIPS = 6,
63+
DWARF_VENDOR_WASM = 7
6364
};
6465

6566
/// Constants that define the DWARF format as 32 or 64 bit.

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,10 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
895895
OS << MI->getOperand(0).getImm();
896896
} else if (MI->getOperand(0).isCImm()) {
897897
MI->getOperand(0).getCImm()->getValue().print(OS, false /*isSigned*/);
898+
} else if (MI->getOperand(0).isTargetIndex()) {
899+
auto Op = MI->getOperand(0);
900+
OS << "!target-index(" << Op.getIndex() << "," << Op.getOffset() << ")";
901+
return true;
898902
} else {
899903
unsigned Reg;
900904
if (MI->getOperand(0).isReg()) {

llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,19 @@
2121
namespace llvm {
2222
class AsmPrinter;
2323

24+
struct TargetIndexLocation {
25+
int Index;
26+
int Offset;
27+
28+
TargetIndexLocation() = default;
29+
TargetIndexLocation(unsigned Idx, int64_t Offset)
30+
: Index(Idx), Offset(Offset) {}
31+
32+
bool operator==(const TargetIndexLocation &Other) const {
33+
return Index == Other.Index && Offset == Other.Offset;
34+
}
35+
};
36+
2437
/// This struct describes location entries emitted in the .debug_loc
2538
/// section.
2639
class DebugLocEntry {
@@ -47,12 +60,20 @@ class DebugLocEntry {
4760
: Expression(Expr), EntryKind(E_Location), Loc(Loc) {
4861
assert(cast<DIExpression>(Expr)->isValid());
4962
}
63+
Value(const DIExpression *Expr, TargetIndexLocation Loc)
64+
: Expression(Expr), EntryKind(E_TargetIndexLocation), TIL(Loc) {}
5065

5166
/// Any complex address location expression for this Value.
5267
const DIExpression *Expression;
5368

5469
/// Type of entry that this represents.
55-
enum EntryType { E_Location, E_Integer, E_ConstantFP, E_ConstantInt };
70+
enum EntryType {
71+
E_Location,
72+
E_Integer,
73+
E_ConstantFP,
74+
E_ConstantInt,
75+
E_TargetIndexLocation
76+
};
5677
enum EntryType EntryKind;
5778

5879
/// Either a constant,
@@ -62,17 +83,25 @@ class DebugLocEntry {
6283
const ConstantInt *CIP;
6384
} Constant;
6485

65-
// Or a location in the machine frame.
66-
MachineLocation Loc;
86+
union {
87+
// Or a location in the machine frame.
88+
MachineLocation Loc;
89+
// Or a location from target specific location.
90+
TargetIndexLocation TIL;
91+
};
6792

6893
bool isLocation() const { return EntryKind == E_Location; }
94+
bool isTargetIndexLocation() const {
95+
return EntryKind == E_TargetIndexLocation;
96+
}
6997
bool isInt() const { return EntryKind == E_Integer; }
7098
bool isConstantFP() const { return EntryKind == E_ConstantFP; }
7199
bool isConstantInt() const { return EntryKind == E_ConstantInt; }
72100
int64_t getInt() const { return Constant.Int; }
73101
const ConstantFP *getConstantFP() const { return Constant.CFP; }
74102
const ConstantInt *getConstantInt() const { return Constant.CIP; }
75103
MachineLocation getLoc() const { return Loc; }
104+
TargetIndexLocation getTargetIndexLocation() const { return TIL; }
76105
bool isFragment() const { return getExpression()->isFragment(); }
77106
const DIExpression *getExpression() const { return Expression; }
78107
friend bool operator==(const Value &, const Value &);
@@ -165,6 +194,8 @@ inline bool operator==(const DebugLocEntry::Value &A,
165194
switch (A.EntryKind) {
166195
case DebugLocEntry::Value::E_Location:
167196
return A.Loc == B.Loc;
197+
case DebugLocEntry::Value::E_TargetIndexLocation:
198+
return A.TIL == B.TIL;
168199
case DebugLocEntry::Value::E_Integer:
169200
return A.Constant.Int == B.Constant.Int;
170201
case DebugLocEntry::Value::E_ConstantFP:

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,11 @@ static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) {
10721072
MachineLocation MLoc(RegOp.getReg(), Op1.isImm());
10731073
return DebugLocEntry::Value(Expr, MLoc);
10741074
}
1075+
if (MI->getOperand(0).isTargetIndex()) {
1076+
auto Op = MI->getOperand(0);
1077+
return DebugLocEntry::Value(
1078+
Expr, TargetIndexLocation(Op.getIndex(), Op.getOffset()));
1079+
}
10751080
if (MI->getOperand(0).isImm())
10761081
return DebugLocEntry::Value(Expr, MI->getOperand(0).getImm());
10771082
if (MI->getOperand(0).isFPImm())
@@ -1920,6 +1925,9 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
19201925
if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg()))
19211926
return;
19221927
return DwarfExpr.addExpression(std::move(Cursor));
1928+
} else if (Value.isTargetIndexLocation()) {
1929+
TargetIndexLocation Loc = Value.getTargetIndexLocation();
1930+
DwarfExpr.addTargetIndexLocation(Loc.Index, Loc.Offset);
19231931
} else if (Value.isConstantFP()) {
19241932
APInt RawBytes = Value.getConstantFP()->getValueAPF().bitcastToAPInt();
19251933
DwarfExpr.addUnsignedConstant(RawBytes);

llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,3 +437,11 @@ void DwarfExpression::addFragmentOffset(const DIExpression *Expr) {
437437
addOpPiece(FragmentOffset - OffsetInBits);
438438
OffsetInBits = FragmentOffset;
439439
}
440+
441+
void DwarfExpression::addTargetIndexLocation(unsigned Index, int64_t Offset) {
442+
assert(LocationKind == Implicit || LocationKind == Unknown);
443+
LocationKind = Implicit;
444+
emitOp(dwarf::DW_OP_WASM_location);
445+
emitUnsigned(Index);
446+
emitSigned(Offset);
447+
}

llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,10 @@ class DwarfExpression {
248248
/// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to
249249
/// the fragment described by \c Expr.
250250
void addFragmentOffset(const DIExpression *Expr);
251+
252+
/// Emit location information expressed via target's index + offset
253+
/// It is an extension for WebAssembly locals, globals and operand stack.
254+
void addTargetIndexLocation(unsigned Index, int64_t Offset);
251255
};
252256

253257
/// DwarfExpression implementation for .debug_loc entries.

llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ static DescVector getDescriptions() {
9393
Descriptions[DW_OP_implicit_value] =
9494
Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeBlock);
9595
Descriptions[DW_OP_stack_value] = Desc(Op::Dwarf3);
96+
Descriptions[DW_OP_WASM_location] =
97+
Desc(Op::Dwarf4, Op::SizeLEB, Op::SignedSizeLEB);
9698
Descriptions[DW_OP_GNU_push_tls_address] = Desc(Op::Dwarf3);
9799
Descriptions[DW_OP_addrx] = Desc(Op::Dwarf4, Op::SizeLEB);
98100
Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB);

llvm/lib/Target/WebAssembly/WebAssembly.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ void initializeWebAssemblyRegNumberingPass(PassRegistry &);
8282
void initializeWebAssemblyPeepholePass(PassRegistry &);
8383
void initializeWebAssemblyCallIndirectFixupPass(PassRegistry &);
8484

85+
namespace WebAssembly {
86+
enum TargetIndex { TI_LOCAL_START, TI_GLOBAL_START, TI_OPERAND_STACK_START };
87+
} // end namespace WebAssembly
88+
8589
} // end namespace llvm
8690

8791
#endif

llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
///
1313
//===----------------------------------------------------------------------===//
1414

15+
#include "WebAssembly.h"
1516
#include "WebAssemblyDebugValueManager.h"
1617
#include "WebAssemblyMachineFunctionInfo.h"
1718
#include "llvm/CodeGen/MachineInstr.h"
@@ -44,3 +45,10 @@ void WebAssemblyDebugValueManager::clone(MachineInstr *Insert,
4445
MBB->insert(Insert, Clone);
4546
}
4647
}
48+
49+
void WebAssemblyDebugValueManager::replaceWithLocal(unsigned LocalId) {
50+
for (auto *DBI : DbgValues) {
51+
MachineOperand &Op = DBI->getOperand(0);
52+
Op.ChangeToTargetIndex(llvm::WebAssembly::TI_LOCAL_START, LocalId);
53+
}
54+
}

llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class WebAssemblyDebugValueManager {
3131
void move(MachineInstr *Insert);
3232
void updateReg(unsigned Reg);
3333
void clone(MachineInstr *Insert, unsigned NewReg);
34+
void replaceWithLocal(unsigned LocalId);
3435
};
3536

3637
} // end namespace llvm

llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
2020
#include "WebAssembly.h"
21+
#include "WebAssemblyDebugValueManager.h"
2122
#include "WebAssemblyMachineFunctionInfo.h"
2223
#include "WebAssemblySubtarget.h"
2324
#include "WebAssemblyUtilities.h"
@@ -262,6 +263,8 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
262263
.addImm(LocalId)
263264
.addReg(MI.getOperand(2).getReg());
264265

266+
WebAssemblyDebugValueManager(&MI).replaceWithLocal(LocalId);
267+
265268
MI.eraseFromParent();
266269
Changed = true;
267270
continue;
@@ -291,6 +294,9 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
291294
} else {
292295
unsigned LocalId = getLocalId(Reg2Local, CurLocal, OldReg);
293296
unsigned Opc = getSetLocalOpcode(RC);
297+
298+
WebAssemblyDebugValueManager(&MI).replaceWithLocal(LocalId);
299+
294300
BuildMI(MBB, InsertPt, MI.getDebugLoc(), TII->get(Opc))
295301
.addImm(LocalId)
296302
.addReg(NewReg);

llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "WebAssemblyInstrInfo.h"
1717
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
18+
#include "WebAssembly.h"
1819
#include "WebAssemblyMachineFunctionInfo.h"
1920
#include "WebAssemblySubtarget.h"
2021
#include "llvm/CodeGen/MachineFrameInfo.h"
@@ -198,3 +199,12 @@ bool WebAssemblyInstrInfo::reverseBranchCondition(
198199
Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm());
199200
return false;
200201
}
202+
203+
ArrayRef<std::pair<int, const char *>>
204+
WebAssemblyInstrInfo::getSerializableTargetIndices() const {
205+
static const std::pair<int, const char *> TargetIndices[] = {
206+
{WebAssembly::TI_LOCAL_START, "wasm-local-start"},
207+
{WebAssembly::TI_GLOBAL_START, "wasm-global-start"},
208+
{WebAssembly::TI_OPERAND_STACK_START, "wasm-operator-stack-start"}};
209+
return makeArrayRef(TargetIndices);
210+
}

llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYINSTRINFO_H
1818

1919
#include "WebAssemblyRegisterInfo.h"
20+
#include "llvm/ADT/ArrayRef.h"
2021
#include "llvm/CodeGen/TargetInstrInfo.h"
2122

2223
#define GET_INSTRINFO_HEADER
@@ -56,6 +57,9 @@ class WebAssemblyInstrInfo final : public WebAssemblyGenInstrInfo {
5657
int *BytesAdded = nullptr) const override;
5758
bool
5859
reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
60+
61+
ArrayRef<std::pair<int, const char *>>
62+
getSerializableTargetIndices() const override;
5963
};
6064

6165
} // end namespace llvm
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
; RUN: llc < %s -stop-after=wasm-explicit-locals | FileCheck %s
2+
3+
; Checks if DBG_VALUEs that correspond to new `local.{tee,set}` are
4+
; using `target-index(wasm-local-start)` operands.
5+
6+
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
7+
target triple = "wasm32-unknown-unknown-wasm"
8+
9+
define hidden i32 @fib(i32 %n) local_unnamed_addr #0 !dbg !7 {
10+
; CHECK: body:
11+
entry:
12+
13+
; CHECK: %[[REG1:.*]]:i32 = CONST_I32 1,
14+
; CHECK: LOCAL_SET_I32 [[LOOP_LOCAL:.*]], %[[REG1]],
15+
; CHECK: DBG_VALUE 1, $noreg,
16+
call void @llvm.dbg.value(metadata i32 1, metadata !16, metadata !DIExpression()), !dbg !19
17+
%cmp8 = icmp sgt i32 %n, 0, !dbg !21
18+
br i1 %cmp8, label %for.body, label %for.end, !dbg !24
19+
20+
for.body: ; preds = %entry, %for.body
21+
%b.011 = phi i32 [ %add, %for.body ], [ 1, %entry ]
22+
%a.010 = phi i32 [ %b.011, %for.body ], [ 0, %entry ]
23+
%i.09 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
24+
25+
; CHECK: %[[REG2:.*]]:i32 = LOCAL_GET_I32 [[LOOP_LOCAL]],
26+
; CHECK: %[[REG3:.*]]:i32 = LOCAL_TEE_I32 [[TMP_LOCAL:.*]], %[[REG2]],
27+
; CHECK: DBG_VALUE target-index(wasm-local-start) + [[TMP_LOCAL]], $noreg,
28+
call void @llvm.dbg.value(metadata i32 %b.011, metadata !16, metadata !DIExpression()), !dbg !19
29+
30+
; CHECK: %[[REG4:.*]]:i32 = nsw ADD_I32
31+
; CHECK: LOCAL_SET_I32 [[LOOP_LOCAL]], %[[REG4]],
32+
; CHECK: DBG_VALUE target-index(wasm-local-start) + [[LOOP_LOCAL]], $noreg,
33+
%add = add nsw i32 %b.011, %a.010, !dbg !26
34+
%inc = add nuw nsw i32 %i.09, 1, !dbg !28
35+
call void @llvm.dbg.value(metadata i32 %add, metadata !16, metadata !DIExpression()), !dbg !19
36+
%exitcond = icmp eq i32 %inc, %n, !dbg !21
37+
br i1 %exitcond, label %for.end, label %for.body, !dbg !24, !llvm.loop !29
38+
39+
for.end: ; preds = %for.body, %entry
40+
%b.0.lcssa = phi i32 [ 1, %entry ], [ %add, %for.body ], !dbg !31
41+
call void @llvm.dbg.value(metadata i32 %b.0.lcssa, metadata !16, metadata !DIExpression()), !dbg !19
42+
ret i32 %b.0.lcssa, !dbg !32
43+
}
44+
45+
declare void @llvm.dbg.value(metadata, metadata, metadata) #1
46+
47+
!llvm.dbg.cu = !{!0}
48+
!llvm.module.flags = !{!4}
49+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 8.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
50+
!1 = !DIFile(filename: "<unknown>", directory: "")
51+
!2 = !{}
52+
!4 = !{i32 2, !"Debug Info Version", i32 3}
53+
!7 = distinct !DISubprogram(name: "fib", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
54+
!8 = !DISubroutineType(types: !9)
55+
!9 = !{!10, !10}
56+
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
57+
!11 = !{!16}
58+
!16 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 2, type: !10)
59+
!17 = !DILocation(line: 1, column: 13, scope: !7)
60+
!18 = !DILocation(line: 2, column: 13, scope: !7)
61+
!19 = !DILocation(line: 2, column: 20, scope: !7)
62+
!20 = !DILocation(line: 2, column: 7, scope: !7)
63+
!21 = !DILocation(line: 3, column: 17, scope: !22)
64+
!22 = distinct !DILexicalBlock(scope: !23, file: !1, line: 3, column: 3)
65+
!23 = distinct !DILexicalBlock(scope: !7, file: !1, line: 3, column: 3)
66+
!24 = !DILocation(line: 3, column: 3, scope: !23)
67+
!25 = !DILocation(line: 2, column: 10, scope: !7)
68+
!26 = !DILocation(line: 6, column: 7, scope: !27)
69+
!27 = distinct !DILexicalBlock(scope: !22, file: !1, line: 3, column: 27)
70+
!28 = !DILocation(line: 3, column: 23, scope: !22)
71+
!29 = distinct !{!29, !24, !30}
72+
!30 = !DILocation(line: 7, column: 3, scope: !23)
73+
!31 = !DILocation(line: 0, scope: !7)
74+
!32 = !DILocation(line: 8, column: 3, scope: !7)

0 commit comments

Comments
 (0)