Skip to content
This repository has been archived by the owner on Feb 5, 2019. It is now read-only.

[WIP] Encode WebAssembly specific locations in DBG_VALUEs and DW_AT_frame_base #134

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/llvm/BinaryFormat/Dwarf.def
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,8 @@ HANDLE_DW_OP(0xfb, GNU_addr_index, 0, GNU)
HANDLE_DW_OP(0xfc, GNU_const_index, 0, GNU)

// DWARF languages.
// Extensions for WebAssembly.
HANDLE_DW_OP(0xed, WASM_location, 0, WASM)
HANDLE_DW_LANG(0x0001, C89, 2, DWARF)
HANDLE_DW_LANG(0x0002, C, 2, DWARF)
HANDLE_DW_LANG(0x0003, Ada83, 2, DWARF)
Expand Down
3 changes: 2 additions & 1 deletion include/llvm/BinaryFormat/Dwarf.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ enum LLVMConstants : uint32_t {
DWARF_VENDOR_GNU = 3,
DWARF_VENDOR_GOOGLE = 4,
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.
Expand Down
23 changes: 23 additions & 0 deletions include/llvm/CodeGen/TargetRegisterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,22 @@ struct RegClassWeight {
unsigned WeightLimit;
};

struct FrameBaseLocation {
enum LocationKind {
Register,
CFA,
TargetIndex
} Kind;
struct TargetIndexInfo {
unsigned Index;
signed Offset;
};
union {
unsigned Reg;
TargetIndexInfo TI;
};
};

/// TargetRegisterInfo base class - We assume that the target defines a static
/// array of TargetRegisterDesc objects that represent all of the machine
/// registers that the target has. As such, we simply have to track a pointer
Expand Down Expand Up @@ -988,6 +1004,13 @@ class TargetRegisterInfo : public MCRegisterInfo {
/// for values allocated in the current stack frame.
virtual unsigned getFrameRegister(const MachineFunction &MF) const = 0;

virtual FrameBaseLocation getFrameBaseLocation(const MachineFunction &MF) const {
FrameBaseLocation Loc;
Loc.Kind = FrameBaseLocation::Register;
Loc.Reg = getFrameRegister(MF);
return Loc;
}

/// Mark a register and all its aliases as reserved in the given set.
void markSuperRegs(BitVector &RegisterSet, unsigned Reg) const;

Expand Down
4 changes: 4 additions & 0 deletions lib/CodeGen/AsmPrinter/AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -895,6 +895,10 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
OS << MI->getOperand(0).getImm();
} else if (MI->getOperand(0).isCImm()) {
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 {
unsigned Reg;
if (MI->getOperand(0).isReg()) {
Expand Down
37 changes: 34 additions & 3 deletions lib/CodeGen/AsmPrinter/DebugLocEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,19 @@
namespace llvm {
class AsmPrinter;

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;
}
};

/// This struct describes location entries emitted in the .debug_loc
/// section.
class DebugLocEntry {
Expand All @@ -47,12 +60,20 @@ class DebugLocEntry {
: Expression(Expr), EntryKind(E_Location), Loc(Loc) {
assert(cast<DIExpression>(Expr)->isValid());
}
Value(const DIExpression *Expr, TargetIndexLocation Loc)
: Expression(Expr), EntryKind(E_TargetIndexLocation), TIL(Loc) {}

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

/// 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;

/// Either a constant,
Expand All @@ -62,17 +83,25 @@ class DebugLocEntry {
const ConstantInt *CIP;
} Constant;

// Or a location in the machine frame.
MachineLocation Loc;
union {
// Or a location in the machine frame.
MachineLocation Loc;
// Or a location from target specific location.
TargetIndexLocation TIL;
};

bool isLocation() const { return EntryKind == E_Location; }
bool isTargetIndexLocation() const {
return EntryKind == E_TargetIndexLocation;
}
bool isInt() const { return EntryKind == E_Integer; }
bool isConstantFP() const { return EntryKind == E_ConstantFP; }
bool isConstantInt() const { return EntryKind == E_ConstantInt; }
int64_t getInt() const { return Constant.Int; }
const ConstantFP *getConstantFP() const { return Constant.CFP; }
const ConstantInt *getConstantInt() const { return Constant.CIP; }
MachineLocation getLoc() const { return Loc; }
TargetIndexLocation getTargetIndexLocation() const { return TIL; }
bool isFragment() const { return getExpression()->isFragment(); }
const DIExpression *getExpression() const { return Expression; }
friend bool operator==(const Value &, const Value &);
Expand Down Expand Up @@ -165,6 +194,8 @@ inline bool operator==(const DebugLocEntry::Value &A,
switch (A.EntryKind) {
case DebugLocEntry::Value::E_Location:
return A.Loc == B.Loc;
case DebugLocEntry::Value::E_TargetIndexLocation:
return A.TIL == B.TIL;
case DebugLocEntry::Value::E_Integer:
return A.Constant.Int == B.Constant.Int;
case DebugLocEntry::Value::E_ConstantFP:
Expand Down
19 changes: 15 additions & 4 deletions lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,13 +340,24 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) {

// Only include DW_AT_frame_base in full debug info
if (!includeMinimalInlineScopes()) {
if (Asm->MF->getTarget().getTargetTriple().isNVPTX()) {
const TargetRegisterInfo *RI = Asm->MF->getSubtarget().getRegisterInfo();
auto FBL = RI->getFrameBaseLocation(*Asm->MF);
if (FBL.Kind == FrameBaseLocation::CFA) {
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_call_frame_cfa);
addBlock(*SPDie, dwarf::DW_AT_frame_base, Loc);
} else if (FBL.Kind == FrameBaseLocation::TargetIndex) {
if (FBL.TI.Offset >= 0) {
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
DIExpressionCursor Cursor({});
DwarfExpr.addTargetIndexLocation(FBL.TI.Index, FBL.TI.Offset);
DwarfExpr.addExpression(std::move(Cursor));
addBlock(*SPDie, dwarf::DW_AT_frame_base, DwarfExpr.finalize());
}
} else {
const TargetRegisterInfo *RI = Asm->MF->getSubtarget().getRegisterInfo();
MachineLocation Location(RI->getFrameRegister(*Asm->MF));
assert(FBL.Kind == FrameBaseLocation::Register);
MachineLocation Location(FBL.Reg);
if (RI->isPhysicalRegister(Location.getReg()))
addAddress(*SPDie, dwarf::DW_AT_frame_base, Location);
}
Expand Down Expand Up @@ -1023,7 +1034,7 @@ void DwarfCompileUnit::addVariableAddress(const DbgVariable &DV, DIE &Die,

/// Add an address attribute to a die based on the location provided.
void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute,
const MachineLocation &Location) {
const MachineLocation &Location) {
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
if (Location.isIndirect())
Expand Down
8 changes: 8 additions & 0 deletions lib/CodeGen/AsmPrinter/DwarfDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,11 @@ static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) {
MachineLocation MLoc(RegOp.getReg(), Op1.isImm());
return DebugLocEntry::Value(Expr, MLoc);
}
if (MI->getOperand(0).isTargetIndex()) {
auto Op = MI->getOperand(0);
return DebugLocEntry::Value(
Expr, TargetIndexLocation(Op.getIndex(), Op.getOffset()));
}
if (MI->getOperand(0).isImm())
return DebugLocEntry::Value(Expr, MI->getOperand(0).getImm());
if (MI->getOperand(0).isFPImm())
Expand Down Expand Up @@ -1899,6 +1904,9 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
} else if (Value.isConstantFP()) {
APInt RawBytes = Value.getConstantFP()->getValueAPF().bitcastToAPInt();
DwarfExpr.addUnsignedConstant(RawBytes);
} else if (Value.isTargetIndexLocation()) {
TargetIndexLocation Loc = Value.getTargetIndexLocation();
DwarfExpr.addTargetIndexLocation(Loc.Index, Loc.Offset);
}
DwarfExpr.addExpression(std::move(ExprCursor));
}
Expand Down
8 changes: 8 additions & 0 deletions lib/CodeGen/AsmPrinter/DwarfExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,3 +437,11 @@ void DwarfExpression::addFragmentOffset(const DIExpression *Expr) {
addOpPiece(FragmentOffset - OffsetInBits);
OffsetInBits = FragmentOffset;
}

void DwarfExpression::addTargetIndexLocation(unsigned Index, int64_t Offset) {
assert(LocationKind == Implicit || LocationKind == Unknown);
LocationKind = Implicit;
emitOp(dwarf::DW_OP_WASM_location);
emitUnsigned(Index);
emitSigned(Offset);
}
4 changes: 4 additions & 0 deletions lib/CodeGen/AsmPrinter/DwarfExpression.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,10 @@ class DwarfExpression {
/// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to
/// the fragment described by \c Expr.
void addFragmentOffset(const DIExpression *Expr);

/// Emit location information expressed via target's index + offset
/// It is an extension for WebAssembly locals, globals and operand stack.
void addTargetIndexLocation(unsigned Index, int64_t Offset);
};

/// DwarfExpression implementation for .debug_loc entries.
Expand Down
2 changes: 2 additions & 0 deletions lib/DebugInfo/DWARF/DWARFExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ static DescVector getDescriptions() {
Descriptions[DW_OP_implicit_value] =
Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeBlock);
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_addrx] = Desc(Op::Dwarf4, Op::SizeLEB);
Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB);
Expand Down
6 changes: 6 additions & 0 deletions lib/Target/NVPTX/NVPTXRegisterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ class NVPTXRegisterInfo : public NVPTXGenRegisterInfo {

unsigned getFrameRegister(const MachineFunction &MF) const override;

FrameBaseLocation getFrameBaseLocation(const MachineFunction &MF) const override {
FrameBaseLocation Loc;
Loc.Kind = FrameBaseLocation::CFA;
return Loc;
}

ManagedStringPool *getStrPool() const {
return const_cast<ManagedStringPool *>(&ManagedStrPool);
}
Expand Down
8 changes: 8 additions & 0 deletions lib/Target/WebAssembly/WebAssembly.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ void initializeWebAssemblyRegNumberingPass(PassRegistry &);
void initializeWebAssemblyPeepholePass(PassRegistry &);
void initializeWebAssemblyCallIndirectFixupPass(PassRegistry &);

namespace WebAssembly {
enum TargetIndex { TI_LOCAL_START, TI_GLOBAL_START, TI_OPERAND_STACK_START };
} // end namespace WebAssembly

namespace WebAssembly {
enum TargetIndex { TI_LOCAL_START, TI_GLOBAL_START, TI_OPERAND_STACK_START };
} // end namespace WebAssembly

} // end namespace llvm

#endif
58 changes: 58 additions & 0 deletions lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,45 @@ static MVT typeForRegClass(const TargetRegisterClass *RC) {
llvm_unreachable("unrecognized register class");
}

static void fixupFollowingDebugValues(DenseMap<unsigned, unsigned> &Reg2Local,
MachineRegisterInfo &MRI,
MachineBasicBlock::iterator B,
MachineBasicBlock::iterator E) {
// Scan DBG_VALUE and modify virtual registers with known locals.
// Stop at first non-DBG_VALUE instruction.
for (auto I = B; I != E && I->isDebugInstr();) {
MachineInstr &MI = *I++;
for (MachineOperand &MO : reverse(MI.uses())) {
if (!MO.isReg())
continue;

unsigned OldReg = MO.getReg();
auto I = Reg2Local.find(OldReg);
if (I == Reg2Local.end())
continue;

unsigned LocalId = I->second;
MO.ChangeToTargetIndex(llvm::WebAssembly::TI_LOCAL_START, LocalId);
}
}
}

static void fixupFollowingDebugValues(unsigned Reg, unsigned LocalId,
MachineRegisterInfo &MRI,
MachineBasicBlock::iterator B,
MachineBasicBlock::iterator E) {
// Scan DBG_VALUE and modify the specified virtual registers with the local.
// Stop at first non-DBG_VALUE instruction.
for (auto I = B; I != E && I->isDebugInstr();) {
MachineInstr &MI = *I++;
for (MachineOperand &MO : reverse(MI.uses())) {
if (!MO.isReg() || MO.getReg() != Reg)
continue;
MO.ChangeToTargetIndex(llvm::WebAssembly::TI_LOCAL_START, LocalId);
}
}
}

/// Given a MachineOperand of a stackified vreg, return the instruction at the
/// start of the expression tree.
static MachineInstr *findStartOfTree(MachineOperand &MO,
Expand Down Expand Up @@ -262,6 +301,11 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
.addImm(LocalId)
.addReg(MI.getOperand(2).getReg());

auto Next = std::next(MachineBasicBlock::iterator(&MI));
fixupFollowingDebugValues(Reg2Local, MRI, Next, MBB.end());
fixupFollowingDebugValues(MI.getOperand(0).getReg(), LocalId, MRI, Next,
MBB.end());

MI.eraseFromParent();
Changed = true;
continue;
Expand Down Expand Up @@ -294,13 +338,18 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
BuildMI(MBB, InsertPt, MI.getDebugLoc(), TII->get(Opc))
.addImm(LocalId)
.addReg(NewReg);
fixupFollowingDebugValues(NewReg, LocalId, MRI, InsertPt,
MBB.end());
}
MI.getOperand(0).setReg(NewReg);
// This register operand is now being used by the inserted drop
// instruction, so make it undead.
MI.getOperand(0).setIsDead(false);
MFI.stackifyVReg(NewReg);
Changed = true;

fixupFollowingDebugValues(Reg2Local, MRI, InsertPt, MBB.end());

}
}

Expand Down Expand Up @@ -353,6 +402,8 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
MO.setReg(NewReg);
MFI.stackifyVReg(NewReg);
Changed = true;

fixupFollowingDebugValues(OldReg, LocalId, MRI, InsertPt, MBB.end());
}

// Coalesce and eliminate COPY instructions.
Expand All @@ -379,6 +430,13 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
Changed = true;
}

{
auto RL = Reg2Local.find(MFI.SPVReg);
if (RL != Reg2Local.end()) {
MFI.SPLocal = RL->second;
}
}

#ifndef NDEBUG
// Assert that all registers have been stackified at this point.
for (const MachineBasicBlock &MBB : MF) {
Expand Down
9 changes: 9 additions & 0 deletions lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,12 @@ bool WebAssemblyInstrInfo::reverseBranchCondition(
Cond.front() = MachineOperand::CreateImm(!Cond.front().getImm());
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);
}
5 changes: 5 additions & 0 deletions lib/Target/WebAssembly/WebAssemblyInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
#ifndef LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYINSTRINFO_H
#define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYINSTRINFO_H

#include "WebAssembly.h"
#include "WebAssemblyRegisterInfo.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/CodeGen/TargetInstrInfo.h"

#define GET_INSTRINFO_HEADER
Expand Down Expand Up @@ -56,6 +58,9 @@ class WebAssemblyInstrInfo final : public WebAssemblyGenInstrInfo {
int *BytesAdded = nullptr) const override;
bool
reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;

ArrayRef<std::pair<int, const char *>>
getSerializableTargetIndices() const override;
};

} // end namespace llvm
Expand Down
Loading