mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 12:50:30 +00:00
[WebAssembly] Use TargetIndex operands in DbgValue to track WebAssembly operands locations
Extends DWARF expression language to express locals/globals locations. (via target-index operands atm) (possible variants are: non-virtual registers or address spaces) The WebAssemblyExplicitLocals can replace virtual registers to targertindex operand type at the time when WebAssembly backend introduces {get,set,tee}_local instead of corresponding virtual registers. Reviewed By: aprantl, dschuff Tags: #debug-info, #llvm Differential Revision: https://reviews.llvm.org/D52634
This commit is contained in:
parent
28833b4485
commit
6939b086bb
@ -648,6 +648,8 @@ HANDLE_DW_OP(0xa9, reinterpret, 5, DWARF)
|
|||||||
// Vendor extensions:
|
// Vendor extensions:
|
||||||
// Extensions for GNU-style thread-local storage.
|
// Extensions for GNU-style thread-local storage.
|
||||||
HANDLE_DW_OP(0xe0, GNU_push_tls_address, 0, GNU)
|
HANDLE_DW_OP(0xe0, GNU_push_tls_address, 0, GNU)
|
||||||
|
// Extensions for WebAssembly.
|
||||||
|
HANDLE_DW_OP(0xed, WASM_location, 0, WASM)
|
||||||
// The GNU entry value extension.
|
// The GNU entry value extension.
|
||||||
HANDLE_DW_OP(0xf3, GNU_entry_value, 0, GNU)
|
HANDLE_DW_OP(0xf3, GNU_entry_value, 0, GNU)
|
||||||
// Extensions for Fission proposal.
|
// Extensions for Fission proposal.
|
||||||
|
@ -63,7 +63,8 @@ enum LLVMConstants : uint32_t {
|
|||||||
DWARF_VENDOR_GNU = 3,
|
DWARF_VENDOR_GNU = 3,
|
||||||
DWARF_VENDOR_GOOGLE = 4,
|
DWARF_VENDOR_GOOGLE = 4,
|
||||||
DWARF_VENDOR_LLVM = 5,
|
DWARF_VENDOR_LLVM = 5,
|
||||||
DWARF_VENDOR_MIPS = 6
|
DWARF_VENDOR_MIPS = 6,
|
||||||
|
DWARF_VENDOR_WASM = 7
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Constants that define the DWARF format as 32 or 64 bit.
|
/// Constants that define the DWARF format as 32 or 64 bit.
|
||||||
|
@ -879,6 +879,10 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
|
|||||||
OS << MI->getOperand(0).getImm();
|
OS << MI->getOperand(0).getImm();
|
||||||
} else if (MI->getOperand(0).isCImm()) {
|
} else if (MI->getOperand(0).isCImm()) {
|
||||||
MI->getOperand(0).getCImm()->getValue().print(OS, false /*isSigned*/);
|
MI->getOperand(0).getCImm()->getValue().print(OS, false /*isSigned*/);
|
||||||
|
} else if (MI->getOperand(0).isTargetIndex()) {
|
||||||
|
auto Op = MI->getOperand(0);
|
||||||
|
OS << "!target-index(" << Op.getIndex() << "," << Op.getOffset() << ")";
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
unsigned Reg;
|
unsigned Reg;
|
||||||
if (MI->getOperand(0).isReg()) {
|
if (MI->getOperand(0).isReg()) {
|
||||||
|
@ -20,13 +20,33 @@
|
|||||||
namespace llvm {
|
namespace llvm {
|
||||||
class AsmPrinter;
|
class AsmPrinter;
|
||||||
|
|
||||||
|
/// This struct describes target specific location.
|
||||||
|
struct TargetIndexLocation {
|
||||||
|
int Index;
|
||||||
|
int Offset;
|
||||||
|
|
||||||
|
TargetIndexLocation() = default;
|
||||||
|
TargetIndexLocation(unsigned Idx, int64_t Offset)
|
||||||
|
: Index(Idx), Offset(Offset) {}
|
||||||
|
|
||||||
|
bool operator==(const TargetIndexLocation &Other) const {
|
||||||
|
return Index == Other.Index && Offset == Other.Offset;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// A single location or constant.
|
/// A single location or constant.
|
||||||
class DbgValueLoc {
|
class DbgValueLoc {
|
||||||
/// Any complex address location expression for this DbgValueLoc.
|
/// Any complex address location expression for this DbgValueLoc.
|
||||||
const DIExpression *Expression;
|
const DIExpression *Expression;
|
||||||
|
|
||||||
/// Type of entry that this represents.
|
/// Type of entry that this represents.
|
||||||
enum EntryType { E_Location, E_Integer, E_ConstantFP, E_ConstantInt };
|
enum EntryType {
|
||||||
|
E_Location,
|
||||||
|
E_Integer,
|
||||||
|
E_ConstantFP,
|
||||||
|
E_ConstantInt,
|
||||||
|
E_TargetIndexLocation
|
||||||
|
};
|
||||||
enum EntryType EntryKind;
|
enum EntryType EntryKind;
|
||||||
|
|
||||||
/// Either a constant,
|
/// Either a constant,
|
||||||
@ -36,8 +56,12 @@ class DbgValueLoc {
|
|||||||
const ConstantInt *CIP;
|
const ConstantInt *CIP;
|
||||||
} Constant;
|
} Constant;
|
||||||
|
|
||||||
/// Or a location in the machine frame.
|
union {
|
||||||
MachineLocation Loc;
|
/// Or a location in the machine frame.
|
||||||
|
MachineLocation Loc;
|
||||||
|
/// Or a location from target specific location.
|
||||||
|
TargetIndexLocation TIL;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DbgValueLoc(const DIExpression *Expr, int64_t i)
|
DbgValueLoc(const DIExpression *Expr, int64_t i)
|
||||||
@ -56,8 +80,13 @@ public:
|
|||||||
: Expression(Expr), EntryKind(E_Location), Loc(Loc) {
|
: Expression(Expr), EntryKind(E_Location), Loc(Loc) {
|
||||||
assert(cast<DIExpression>(Expr)->isValid());
|
assert(cast<DIExpression>(Expr)->isValid());
|
||||||
}
|
}
|
||||||
|
DbgValueLoc(const DIExpression *Expr, TargetIndexLocation Loc)
|
||||||
|
: Expression(Expr), EntryKind(E_TargetIndexLocation), TIL(Loc) {}
|
||||||
|
|
||||||
bool isLocation() const { return EntryKind == E_Location; }
|
bool isLocation() const { return EntryKind == E_Location; }
|
||||||
|
bool isTargetIndexLocation() const {
|
||||||
|
return EntryKind == E_TargetIndexLocation;
|
||||||
|
}
|
||||||
bool isInt() const { return EntryKind == E_Integer; }
|
bool isInt() const { return EntryKind == E_Integer; }
|
||||||
bool isConstantFP() const { return EntryKind == E_ConstantFP; }
|
bool isConstantFP() const { return EntryKind == E_ConstantFP; }
|
||||||
bool isConstantInt() const { return EntryKind == E_ConstantInt; }
|
bool isConstantInt() const { return EntryKind == E_ConstantInt; }
|
||||||
@ -65,6 +94,7 @@ public:
|
|||||||
const ConstantFP *getConstantFP() const { return Constant.CFP; }
|
const ConstantFP *getConstantFP() const { return Constant.CFP; }
|
||||||
const ConstantInt *getConstantInt() const { return Constant.CIP; }
|
const ConstantInt *getConstantInt() const { return Constant.CIP; }
|
||||||
MachineLocation getLoc() const { return Loc; }
|
MachineLocation getLoc() const { return Loc; }
|
||||||
|
TargetIndexLocation getTargetIndexLocation() const { return TIL; }
|
||||||
bool isFragment() const { return getExpression()->isFragment(); }
|
bool isFragment() const { return getExpression()->isFragment(); }
|
||||||
bool isEntryVal() const { return getExpression()->isEntryValue(); }
|
bool isEntryVal() const { return getExpression()->isEntryValue(); }
|
||||||
const DIExpression *getExpression() const { return Expression; }
|
const DIExpression *getExpression() const { return Expression; }
|
||||||
@ -162,6 +192,8 @@ inline bool operator==(const DbgValueLoc &A,
|
|||||||
switch (A.EntryKind) {
|
switch (A.EntryKind) {
|
||||||
case DbgValueLoc::E_Location:
|
case DbgValueLoc::E_Location:
|
||||||
return A.Loc == B.Loc;
|
return A.Loc == B.Loc;
|
||||||
|
case DbgValueLoc::E_TargetIndexLocation:
|
||||||
|
return A.TIL == B.TIL;
|
||||||
case DbgValueLoc::E_Integer:
|
case DbgValueLoc::E_Integer:
|
||||||
return A.Constant.Int == B.Constant.Int;
|
return A.Constant.Int == B.Constant.Int;
|
||||||
case DbgValueLoc::E_ConstantFP:
|
case DbgValueLoc::E_ConstantFP:
|
||||||
|
@ -241,6 +241,11 @@ static DbgValueLoc getDebugLocValue(const MachineInstr *MI) {
|
|||||||
MachineLocation MLoc(RegOp.getReg(), Op1.isImm());
|
MachineLocation MLoc(RegOp.getReg(), Op1.isImm());
|
||||||
return DbgValueLoc(Expr, MLoc);
|
return DbgValueLoc(Expr, MLoc);
|
||||||
}
|
}
|
||||||
|
if (MI->getOperand(0).isTargetIndex()) {
|
||||||
|
auto Op = MI->getOperand(0);
|
||||||
|
return DbgValueLoc(Expr,
|
||||||
|
TargetIndexLocation(Op.getIndex(), Op.getOffset()));
|
||||||
|
}
|
||||||
if (MI->getOperand(0).isImm())
|
if (MI->getOperand(0).isImm())
|
||||||
return DbgValueLoc(Expr, MI->getOperand(0).getImm());
|
return DbgValueLoc(Expr, MI->getOperand(0).getImm());
|
||||||
if (MI->getOperand(0).isFPImm())
|
if (MI->getOperand(0).isFPImm())
|
||||||
@ -2241,6 +2246,11 @@ void DwarfDebug::emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
|
|||||||
if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg()))
|
if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg()))
|
||||||
return;
|
return;
|
||||||
return DwarfExpr.addExpression(std::move(Cursor));
|
return DwarfExpr.addExpression(std::move(Cursor));
|
||||||
|
} else if (Value.isTargetIndexLocation()) {
|
||||||
|
TargetIndexLocation Loc = Value.getTargetIndexLocation();
|
||||||
|
// TODO TargetIndexLocation is a target-independent. Currently only the WebAssembly-specific
|
||||||
|
// encoding is supported.
|
||||||
|
DwarfExpr.addWasmLocation(Loc.Index, Loc.Offset);
|
||||||
} else if (Value.isConstantFP()) {
|
} else if (Value.isConstantFP()) {
|
||||||
APInt RawBytes = Value.getConstantFP()->getValueAPF().bitcastToAPInt();
|
APInt RawBytes = Value.getConstantFP()->getValueAPF().bitcastToAPInt();
|
||||||
DwarfExpr.addUnsignedConstant(RawBytes);
|
DwarfExpr.addUnsignedConstant(RawBytes);
|
||||||
|
@ -572,3 +572,11 @@ void DwarfExpression::emitLegacyZExt(unsigned FromBits) {
|
|||||||
emitUnsigned((1ULL << FromBits) - 1);
|
emitUnsigned((1ULL << FromBits) - 1);
|
||||||
emitOp(dwarf::DW_OP_and);
|
emitOp(dwarf::DW_OP_and);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DwarfExpression::addWasmLocation(unsigned Index, int64_t Offset) {
|
||||||
|
assert(LocationKind == Implicit || LocationKind == Unknown);
|
||||||
|
LocationKind = Implicit;
|
||||||
|
emitOp(dwarf::DW_OP_WASM_location);
|
||||||
|
emitUnsigned(Index);
|
||||||
|
emitSigned(Offset);
|
||||||
|
}
|
||||||
|
@ -337,6 +337,10 @@ public:
|
|||||||
|
|
||||||
void emitLegacySExt(unsigned FromBits);
|
void emitLegacySExt(unsigned FromBits);
|
||||||
void emitLegacyZExt(unsigned FromBits);
|
void emitLegacyZExt(unsigned FromBits);
|
||||||
|
|
||||||
|
/// Emit location information expressed via WebAssembly location + offset
|
||||||
|
/// The Index is an identifier for locals, globals or operand stack.
|
||||||
|
void addWasmLocation(unsigned Index, int64_t Offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// DwarfExpression implementation for .debug_loc entries.
|
/// DwarfExpression implementation for .debug_loc entries.
|
||||||
|
@ -93,6 +93,8 @@ static DescVector getDescriptions() {
|
|||||||
Descriptions[DW_OP_implicit_value] =
|
Descriptions[DW_OP_implicit_value] =
|
||||||
Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeBlock);
|
Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeBlock);
|
||||||
Descriptions[DW_OP_stack_value] = Desc(Op::Dwarf3);
|
Descriptions[DW_OP_stack_value] = Desc(Op::Dwarf3);
|
||||||
|
Descriptions[DW_OP_WASM_location] =
|
||||||
|
Desc(Op::Dwarf4, Op::SizeLEB, Op::SignedSizeLEB);
|
||||||
Descriptions[DW_OP_GNU_push_tls_address] = Desc(Op::Dwarf3);
|
Descriptions[DW_OP_GNU_push_tls_address] = Desc(Op::Dwarf3);
|
||||||
Descriptions[DW_OP_addrx] = Desc(Op::Dwarf4, Op::SizeLEB);
|
Descriptions[DW_OP_addrx] = Desc(Op::Dwarf4, Op::SizeLEB);
|
||||||
Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB);
|
Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB);
|
||||||
|
@ -79,6 +79,10 @@ void initializeWebAssemblyRegNumberingPass(PassRegistry &);
|
|||||||
void initializeWebAssemblyPeepholePass(PassRegistry &);
|
void initializeWebAssemblyPeepholePass(PassRegistry &);
|
||||||
void initializeWebAssemblyCallIndirectFixupPass(PassRegistry &);
|
void initializeWebAssemblyCallIndirectFixupPass(PassRegistry &);
|
||||||
|
|
||||||
|
namespace WebAssembly {
|
||||||
|
enum TargetIndex { TI_LOCAL_START, TI_GLOBAL_START, TI_OPERAND_STACK_START };
|
||||||
|
} // end namespace WebAssembly
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "WebAssemblyDebugValueManager.h"
|
#include "WebAssemblyDebugValueManager.h"
|
||||||
|
#include "WebAssembly.h"
|
||||||
#include "WebAssemblyMachineFunctionInfo.h"
|
#include "WebAssemblyMachineFunctionInfo.h"
|
||||||
#include "llvm/CodeGen/MachineInstr.h"
|
#include "llvm/CodeGen/MachineInstr.h"
|
||||||
|
|
||||||
@ -43,3 +44,10 @@ void WebAssemblyDebugValueManager::clone(MachineInstr *Insert,
|
|||||||
MBB->insert(Insert, Clone);
|
MBB->insert(Insert, Clone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebAssemblyDebugValueManager::replaceWithLocal(unsigned LocalId) {
|
||||||
|
for (auto *DBI : DbgValues) {
|
||||||
|
MachineOperand &Op = DBI->getOperand(0);
|
||||||
|
Op.ChangeToTargetIndex(llvm::WebAssembly::TI_LOCAL_START, LocalId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -30,6 +30,7 @@ public:
|
|||||||
void move(MachineInstr *Insert);
|
void move(MachineInstr *Insert);
|
||||||
void updateReg(unsigned Reg);
|
void updateReg(unsigned Reg);
|
||||||
void clone(MachineInstr *Insert, unsigned NewReg);
|
void clone(MachineInstr *Insert, unsigned NewReg);
|
||||||
|
void replaceWithLocal(unsigned LocalId);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
|
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
|
||||||
#include "WebAssembly.h"
|
#include "WebAssembly.h"
|
||||||
|
#include "WebAssemblyDebugValueManager.h"
|
||||||
#include "WebAssemblyMachineFunctionInfo.h"
|
#include "WebAssemblyMachineFunctionInfo.h"
|
||||||
#include "WebAssemblySubtarget.h"
|
#include "WebAssemblySubtarget.h"
|
||||||
#include "WebAssemblyUtilities.h"
|
#include "WebAssemblyUtilities.h"
|
||||||
@ -261,6 +262,8 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
|
|||||||
.addImm(LocalId)
|
.addImm(LocalId)
|
||||||
.addReg(MI.getOperand(2).getReg());
|
.addReg(MI.getOperand(2).getReg());
|
||||||
|
|
||||||
|
WebAssemblyDebugValueManager(&MI).replaceWithLocal(LocalId);
|
||||||
|
|
||||||
MI.eraseFromParent();
|
MI.eraseFromParent();
|
||||||
Changed = true;
|
Changed = true;
|
||||||
continue;
|
continue;
|
||||||
@ -290,6 +293,9 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
|
|||||||
} else {
|
} else {
|
||||||
unsigned LocalId = getLocalId(Reg2Local, CurLocal, OldReg);
|
unsigned LocalId = getLocalId(Reg2Local, CurLocal, OldReg);
|
||||||
unsigned Opc = getLocalSetOpcode(RC);
|
unsigned Opc = getLocalSetOpcode(RC);
|
||||||
|
|
||||||
|
WebAssemblyDebugValueManager(&MI).replaceWithLocal(LocalId);
|
||||||
|
|
||||||
BuildMI(MBB, InsertPt, MI.getDebugLoc(), TII->get(Opc))
|
BuildMI(MBB, InsertPt, MI.getDebugLoc(), TII->get(Opc))
|
||||||
.addImm(LocalId)
|
.addImm(LocalId)
|
||||||
.addReg(NewReg);
|
.addReg(NewReg);
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "WebAssemblyInstrInfo.h"
|
#include "WebAssemblyInstrInfo.h"
|
||||||
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
|
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
|
||||||
|
#include "WebAssembly.h"
|
||||||
#include "WebAssemblyMachineFunctionInfo.h"
|
#include "WebAssemblyMachineFunctionInfo.h"
|
||||||
#include "WebAssemblySubtarget.h"
|
#include "WebAssemblySubtarget.h"
|
||||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||||
@ -230,3 +231,12 @@ bool WebAssemblyInstrInfo::reverseBranchCondition(
|
|||||||
Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm());
|
Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrayRef<std::pair<int, const char *>>
|
||||||
|
WebAssemblyInstrInfo::getSerializableTargetIndices() const {
|
||||||
|
static const std::pair<int, const char *> TargetIndices[] = {
|
||||||
|
{WebAssembly::TI_LOCAL_START, "wasm-local-start"},
|
||||||
|
{WebAssembly::TI_GLOBAL_START, "wasm-global-start"},
|
||||||
|
{WebAssembly::TI_OPERAND_STACK_START, "wasm-operator-stack-start"}};
|
||||||
|
return makeArrayRef(TargetIndices);
|
||||||
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYINSTRINFO_H
|
#define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYINSTRINFO_H
|
||||||
|
|
||||||
#include "WebAssemblyRegisterInfo.h"
|
#include "WebAssemblyRegisterInfo.h"
|
||||||
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/CodeGen/TargetInstrInfo.h"
|
#include "llvm/CodeGen/TargetInstrInfo.h"
|
||||||
|
|
||||||
#define GET_INSTRINFO_HEADER
|
#define GET_INSTRINFO_HEADER
|
||||||
@ -64,6 +65,9 @@ public:
|
|||||||
int *BytesAdded = nullptr) const override;
|
int *BytesAdded = nullptr) const override;
|
||||||
bool
|
bool
|
||||||
reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
|
reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
|
||||||
|
|
||||||
|
ArrayRef<std::pair<int, const char *>>
|
||||||
|
getSerializableTargetIndices() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
70
test/DebugInfo/WebAssembly/dbg-value-dwarfdump.ll
Normal file
70
test/DebugInfo/WebAssembly/dbg-value-dwarfdump.ll
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
; RUN: llc < %s -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s
|
||||||
|
|
||||||
|
; Verify if dwarfdump contains DBG_VALUE associated with locals.
|
||||||
|
; See also dgb-value-ti.ll test.
|
||||||
|
|
||||||
|
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
|
||||||
|
target triple = "wasm32-unknown-unknown-wasm"
|
||||||
|
|
||||||
|
define hidden i32 @fib(i32 %n) local_unnamed_addr #0 !dbg !7 {
|
||||||
|
|
||||||
|
entry:
|
||||||
|
; CHECK: DW_TAG_subprogram
|
||||||
|
; CHECK: DW_TAG_variable
|
||||||
|
|
||||||
|
call void @llvm.dbg.value(metadata i32 1, metadata !16, metadata !DIExpression()), !dbg !19
|
||||||
|
%cmp8 = icmp sgt i32 %n, 0, !dbg !21
|
||||||
|
br i1 %cmp8, label %for.body, label %for.end, !dbg !24
|
||||||
|
|
||||||
|
for.body: ; preds = %entry, %for.body
|
||||||
|
%b.011 = phi i32 [ %add, %for.body ], [ 1, %entry ]
|
||||||
|
%a.010 = phi i32 [ %b.011, %for.body ], [ 0, %entry ]
|
||||||
|
%i.09 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
|
||||||
|
|
||||||
|
; CHECK: DW_OP_WASM_location 0x0 +[[LOCAL_1:[0-9]+]]
|
||||||
|
call void @llvm.dbg.value(metadata i32 %b.011, metadata !16, metadata !DIExpression()), !dbg !19
|
||||||
|
|
||||||
|
; CHECK-NOT: DW_OP_WASM_location 0x0 +[[LOCAL_1]]
|
||||||
|
; CHECK: DW_OP_WASM_location 0x0 +[[LOCAL_2:[0-9]+]]
|
||||||
|
%add = add nsw i32 %b.011, %a.010, !dbg !26
|
||||||
|
%inc = add nuw nsw i32 %i.09, 1, !dbg !28
|
||||||
|
call void @llvm.dbg.value(metadata i32 %add, metadata !16, metadata !DIExpression()), !dbg !19
|
||||||
|
%exitcond = icmp eq i32 %inc, %n, !dbg !21
|
||||||
|
br i1 %exitcond, label %for.end, label %for.body, !dbg !24, !llvm.loop !29
|
||||||
|
|
||||||
|
for.end: ; preds = %for.body, %entry
|
||||||
|
%b.0.lcssa = phi i32 [ 1, %entry ], [ %add, %for.body ], !dbg !31
|
||||||
|
call void @llvm.dbg.value(metadata i32 %b.0.lcssa, metadata !16, metadata !DIExpression()), !dbg !19
|
||||||
|
ret i32 %b.0.lcssa, !dbg !32
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @llvm.dbg.value(metadata, metadata, metadata) #1
|
||||||
|
|
||||||
|
!llvm.dbg.cu = !{!0}
|
||||||
|
!llvm.module.flags = !{!4}
|
||||||
|
!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)
|
||||||
|
!1 = !DIFile(filename: "<unknown>", directory: "")
|
||||||
|
!2 = !{}
|
||||||
|
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||||
|
!7 = distinct !DISubprogram(name: "fib", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
|
||||||
|
!8 = !DISubroutineType(types: !9)
|
||||||
|
!9 = !{!10, !10}
|
||||||
|
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
||||||
|
!11 = !{!16}
|
||||||
|
!16 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 2, type: !10)
|
||||||
|
!17 = !DILocation(line: 1, column: 13, scope: !7)
|
||||||
|
!18 = !DILocation(line: 2, column: 13, scope: !7)
|
||||||
|
!19 = !DILocation(line: 2, column: 20, scope: !7)
|
||||||
|
!20 = !DILocation(line: 2, column: 7, scope: !7)
|
||||||
|
!21 = !DILocation(line: 3, column: 17, scope: !22)
|
||||||
|
!22 = distinct !DILexicalBlock(scope: !23, file: !1, line: 3, column: 3)
|
||||||
|
!23 = distinct !DILexicalBlock(scope: !7, file: !1, line: 3, column: 3)
|
||||||
|
!24 = !DILocation(line: 3, column: 3, scope: !23)
|
||||||
|
!25 = !DILocation(line: 2, column: 10, scope: !7)
|
||||||
|
!26 = !DILocation(line: 6, column: 7, scope: !27)
|
||||||
|
!27 = distinct !DILexicalBlock(scope: !22, file: !1, line: 3, column: 27)
|
||||||
|
!28 = !DILocation(line: 3, column: 23, scope: !22)
|
||||||
|
!29 = distinct !{!29, !24, !30}
|
||||||
|
!30 = !DILocation(line: 7, column: 3, scope: !23)
|
||||||
|
!31 = !DILocation(line: 0, scope: !7)
|
||||||
|
!32 = !DILocation(line: 8, column: 3, scope: !7)
|
74
test/DebugInfo/WebAssembly/dbg-value-ti.ll
Normal file
74
test/DebugInfo/WebAssembly/dbg-value-ti.ll
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
; RUN: llc < %s -stop-after=wasm-explicit-locals | FileCheck %s
|
||||||
|
|
||||||
|
; Checks if DBG_VALUEs that correspond to new `local.{tee,set}` are
|
||||||
|
; using `target-index(wasm-local-start)` operands.
|
||||||
|
|
||||||
|
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
|
||||||
|
target triple = "wasm32-unknown-unknown-wasm"
|
||||||
|
|
||||||
|
define hidden i32 @fib(i32 %n) local_unnamed_addr #0 !dbg !7 {
|
||||||
|
; CHECK: body:
|
||||||
|
entry:
|
||||||
|
|
||||||
|
; CHECK: %[[REG1:.*]]:i32 = CONST_I32 1,
|
||||||
|
; CHECK: LOCAL_SET_I32 [[LOOP_LOCAL:.*]], %[[REG1]],
|
||||||
|
; CHECK: DBG_VALUE 1, $noreg,
|
||||||
|
call void @llvm.dbg.value(metadata i32 1, metadata !16, metadata !DIExpression()), !dbg !19
|
||||||
|
%cmp8 = icmp sgt i32 %n, 0, !dbg !21
|
||||||
|
br i1 %cmp8, label %for.body, label %for.end, !dbg !24
|
||||||
|
|
||||||
|
for.body: ; preds = %entry, %for.body
|
||||||
|
%b.011 = phi i32 [ %add, %for.body ], [ 1, %entry ]
|
||||||
|
%a.010 = phi i32 [ %b.011, %for.body ], [ 0, %entry ]
|
||||||
|
%i.09 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
|
||||||
|
|
||||||
|
; CHECK: %[[REG2:.*]]:i32 = LOCAL_GET_I32 [[LOOP_LOCAL]],
|
||||||
|
; CHECK: %[[REG3:.*]]:i32 = LOCAL_TEE_I32 [[TMP_LOCAL:.*]], %[[REG2]],
|
||||||
|
; CHECK: DBG_VALUE target-index(wasm-local-start) + [[TMP_LOCAL]], $noreg,
|
||||||
|
call void @llvm.dbg.value(metadata i32 %b.011, metadata !16, metadata !DIExpression()), !dbg !19
|
||||||
|
|
||||||
|
; CHECK: %[[REG4:.*]]:i32 = nsw ADD_I32
|
||||||
|
; CHECK: LOCAL_SET_I32 [[LOOP_LOCAL]], %[[REG4]],
|
||||||
|
; CHECK: DBG_VALUE target-index(wasm-local-start) + [[LOOP_LOCAL]], $noreg,
|
||||||
|
%add = add nsw i32 %b.011, %a.010, !dbg !26
|
||||||
|
%inc = add nuw nsw i32 %i.09, 1, !dbg !28
|
||||||
|
call void @llvm.dbg.value(metadata i32 %add, metadata !16, metadata !DIExpression()), !dbg !19
|
||||||
|
%exitcond = icmp eq i32 %inc, %n, !dbg !21
|
||||||
|
br i1 %exitcond, label %for.end, label %for.body, !dbg !24, !llvm.loop !29
|
||||||
|
|
||||||
|
for.end: ; preds = %for.body, %entry
|
||||||
|
%b.0.lcssa = phi i32 [ 1, %entry ], [ %add, %for.body ], !dbg !31
|
||||||
|
call void @llvm.dbg.value(metadata i32 %b.0.lcssa, metadata !16, metadata !DIExpression()), !dbg !19
|
||||||
|
ret i32 %b.0.lcssa, !dbg !32
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @llvm.dbg.value(metadata, metadata, metadata) #1
|
||||||
|
|
||||||
|
!llvm.dbg.cu = !{!0}
|
||||||
|
!llvm.module.flags = !{!4}
|
||||||
|
!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)
|
||||||
|
!1 = !DIFile(filename: "<unknown>", directory: "")
|
||||||
|
!2 = !{}
|
||||||
|
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||||
|
!7 = distinct !DISubprogram(name: "fib", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
|
||||||
|
!8 = !DISubroutineType(types: !9)
|
||||||
|
!9 = !{!10, !10}
|
||||||
|
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
||||||
|
!11 = !{!16}
|
||||||
|
!16 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 2, type: !10)
|
||||||
|
!17 = !DILocation(line: 1, column: 13, scope: !7)
|
||||||
|
!18 = !DILocation(line: 2, column: 13, scope: !7)
|
||||||
|
!19 = !DILocation(line: 2, column: 20, scope: !7)
|
||||||
|
!20 = !DILocation(line: 2, column: 7, scope: !7)
|
||||||
|
!21 = !DILocation(line: 3, column: 17, scope: !22)
|
||||||
|
!22 = distinct !DILexicalBlock(scope: !23, file: !1, line: 3, column: 3)
|
||||||
|
!23 = distinct !DILexicalBlock(scope: !7, file: !1, line: 3, column: 3)
|
||||||
|
!24 = !DILocation(line: 3, column: 3, scope: !23)
|
||||||
|
!25 = !DILocation(line: 2, column: 10, scope: !7)
|
||||||
|
!26 = !DILocation(line: 6, column: 7, scope: !27)
|
||||||
|
!27 = distinct !DILexicalBlock(scope: !22, file: !1, line: 3, column: 27)
|
||||||
|
!28 = !DILocation(line: 3, column: 23, scope: !22)
|
||||||
|
!29 = distinct !{!29, !24, !30}
|
||||||
|
!30 = !DILocation(line: 7, column: 3, scope: !23)
|
||||||
|
!31 = !DILocation(line: 0, scope: !7)
|
||||||
|
!32 = !DILocation(line: 8, column: 3, scope: !7)
|
Loading…
Reference in New Issue
Block a user