forked from OSchip/llvm-project
[WebAssembly] Track frame registers through VReg and local allocation
This change has 2 components: Target-independent: add a method getDwarfFrameBase to TargetFrameLowering. It describes how the Dwarf frame base will be encoded. That can be a register (the default), the CFA (which replaces NVPTX-specific logic in DwarfCompileUnit), or a DW_OP_WASM_location descriptr. WebAssembly: Allow WebAssemblyFunctionInfo::getFrameRegister to return the correct virtual register instead of FP32/SP32 after WebAssemblyReplacePhysRegs has run. Make WebAssemblyExplicitLocals store the local it allocates for the frame register. Use this local information to implement getDwarfFrameBase The result is that the DW_AT_frame_base attribute is correctly encoded for each subprogram, and each param and local variable has a correct DW_AT_location that uses DW_OP_fbreg to refer to the frame base. This is a reland of rG3a05c3969c18 with fixes for the expensive-checks and Windows builds Differential Revision: https://reviews.llvm.org/D71681
This commit is contained in:
parent
ee2de95507
commit
ff171acf84
|
@ -14,6 +14,7 @@ CHECK-NEXT: DW_AT_name ("hi.c")
|
|||
CHECK: DW_TAG_subprogram
|
||||
CHECK-NEXT: DW_AT_low_pc
|
||||
CHECK-NEXT: DW_AT_high_pc
|
||||
CHECK-NEXT: DW_AT_frame_base
|
||||
CHECK-NEXT: DW_AT_name ("test")
|
||||
CHECK-NEXT: DW_AT_decl_file ("/Users/yury/llvmwasm{{(/|\\)}}hi.c")
|
||||
CHECK-NEXT: DW_AT_decl_line (3)
|
||||
|
@ -27,6 +28,7 @@ CHECK-NEXT: DW_AT_decl_line (3)
|
|||
CHECK: DW_TAG_subprogram
|
||||
CHECK-NEXT: DW_AT_low_pc
|
||||
CHECK-NEXT: DW_AT_high_pc
|
||||
CHECK-NEXT: DW_AT_frame_base
|
||||
CHECK-NEXT: DW_AT_name ("_start")
|
||||
CHECK-NEXT: DW_AT_decl_file ("/Users/yury/llvmwasm{{(/|\\)}}hi.c")
|
||||
CHECK-NEXT: DW_AT_decl_line (7)
|
||||
|
@ -43,7 +45,7 @@ CHECK-NEXT: DW_AT_name ("hi_foo.c")
|
|||
|
||||
CHECK: DW_TAG_variable
|
||||
CHECK-NEXT: DW_AT_name ("y")
|
||||
CHECK-NEXT: DW_AT_type (0x00000097 "int[2]")
|
||||
CHECK-NEXT: DW_AT_type (0x000000a1 "int[2]")
|
||||
CHECK-NEXT: DW_AT_external (true)
|
||||
CHECK-NEXT: DW_AT_decl_file ("{{.*}}hi_foo.c")
|
||||
CHECK-NEXT: DW_AT_decl_line (1)
|
||||
|
@ -65,7 +67,7 @@ CHECK-NEXT: DW_AT_encoding (DW_ATE_unsigned)
|
|||
|
||||
CHECK: DW_TAG_variable
|
||||
CHECK-NEXT: DW_AT_name ("z")
|
||||
CHECK-NEXT: DW_AT_type (0x00000097 "int[2]")
|
||||
CHECK-NEXT: DW_AT_type (0x000000a1 "int[2]")
|
||||
CHECK-NEXT: DW_AT_external (true)
|
||||
CHECK-NEXT: DW_AT_decl_file ("{{.*}}hi_foo.c")
|
||||
CHECK-NEXT: DW_AT_decl_line (8)
|
||||
|
@ -74,6 +76,7 @@ CHECK-NEXT: DW_AT_location (DW_OP_addr 0x0)
|
|||
CHECK: DW_TAG_subprogram
|
||||
CHECK-NEXT: DW_AT_low_pc
|
||||
CHECK-NEXT: DW_AT_high_pc
|
||||
CHECK-NEXT: DW_AT_frame_base
|
||||
CHECK-NEXT: DW_AT_name ("foo")
|
||||
CHECK-NEXT: DW_AT_decl_file ("{{.*}}hi_foo.c")
|
||||
CHECK-NEXT: DW_AT_decl_line (3)
|
||||
|
|
|
@ -52,6 +52,21 @@ public:
|
|||
unsigned Reg;
|
||||
int Offset; // Offset relative to stack pointer on function entry.
|
||||
};
|
||||
|
||||
struct DwarfFrameBase {
|
||||
// The frame base may be either a register (the default), the CFA,
|
||||
// or a WebAssembly-specific location description.
|
||||
enum FrameBaseKind { Register, CFA, WasmFrameBase } Kind;
|
||||
struct WasmFrameBase {
|
||||
unsigned Kind; // Wasm local, global, or value stack
|
||||
unsigned Index;
|
||||
};
|
||||
union {
|
||||
unsigned Reg;
|
||||
struct WasmFrameBase WasmLoc;
|
||||
} Location;
|
||||
};
|
||||
|
||||
private:
|
||||
StackDirection StackDir;
|
||||
Align StackAlignment;
|
||||
|
@ -401,6 +416,10 @@ public:
|
|||
/// Return initial CFA register value i.e. the one valid at the beginning of
|
||||
/// the function (before any stack operations).
|
||||
virtual unsigned getInitialCFARegister(const MachineFunction &MF) const;
|
||||
|
||||
/// Return the frame base information to be encoded in the DWARF subprogram
|
||||
/// debug info.
|
||||
virtual DwarfFrameBase getDwarfFrameBase(const MachineFunction &MF) const;
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
|
|
@ -400,15 +400,33 @@ 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 TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
|
||||
TargetFrameLowering::DwarfFrameBase FrameBase =
|
||||
TFI->getDwarfFrameBase(*Asm->MF);
|
||||
switch (FrameBase.Kind) {
|
||||
case TargetFrameLowering::DwarfFrameBase::Register: {
|
||||
if (Register::isPhysicalRegister(FrameBase.Location.Reg)) {
|
||||
MachineLocation Location(FrameBase.Location.Reg);
|
||||
addAddress(*SPDie, dwarf::DW_AT_frame_base, Location);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TargetFrameLowering::DwarfFrameBase::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 {
|
||||
const TargetRegisterInfo *RI = Asm->MF->getSubtarget().getRegisterInfo();
|
||||
MachineLocation Location(RI->getFrameRegister(*Asm->MF));
|
||||
if (Register::isPhysicalRegister(Location.getReg()))
|
||||
addAddress(*SPDie, dwarf::DW_AT_frame_base, Location);
|
||||
break;
|
||||
}
|
||||
case TargetFrameLowering::DwarfFrameBase::WasmFrameBase: {
|
||||
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
|
||||
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
|
||||
DIExpressionCursor Cursor({});
|
||||
DwarfExpr.addWasmLocation(FrameBase.Location.WasmLoc.Kind,
|
||||
FrameBase.Location.WasmLoc.Index);
|
||||
DwarfExpr.addExpression(std::move(Cursor));
|
||||
addBlock(*SPDie, dwarf::DW_AT_frame_base, DwarfExpr.finalize());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -154,3 +154,9 @@ unsigned TargetFrameLowering::getInitialCFARegister(const MachineFunction &MF)
|
|||
const {
|
||||
llvm_unreachable("getInitialCFARegister() not implemented!");
|
||||
}
|
||||
|
||||
TargetFrameLowering::DwarfFrameBase
|
||||
TargetFrameLowering::getDwarfFrameBase(const MachineFunction &MF) const {
|
||||
const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo();
|
||||
return DwarfFrameBase{DwarfFrameBase::Register, {RI->getFrameRegister(MF)}};
|
||||
}
|
||||
|
|
|
@ -83,3 +83,8 @@ MachineBasicBlock::iterator NVPTXFrameLowering::eliminateCallFramePseudoInstr(
|
|||
// ADJCALLSTACKUP instructions.
|
||||
return MBB.erase(I);
|
||||
}
|
||||
|
||||
TargetFrameLowering::DwarfFrameBase
|
||||
NVPTXFrameLowering::getDwarfFrameBase(const MachineFunction &MF) const {
|
||||
return {DwarfFrameBase::CFA, {0}};
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ public:
|
|||
MachineBasicBlock::iterator
|
||||
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I) const override;
|
||||
DwarfFrameBase getDwarfFrameBase(const MachineFunction &MF) const override;
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
|
|
@ -72,10 +72,15 @@ FunctionPass *llvm::createWebAssemblyExplicitLocals() {
|
|||
/// Return a local id number for the given register, assigning it a new one
|
||||
/// if it doesn't yet have one.
|
||||
static unsigned getLocalId(DenseMap<unsigned, unsigned> &Reg2Local,
|
||||
unsigned &CurLocal, unsigned Reg) {
|
||||
WebAssemblyFunctionInfo &MFI, unsigned &CurLocal,
|
||||
unsigned Reg) {
|
||||
auto P = Reg2Local.insert(std::make_pair(Reg, CurLocal));
|
||||
if (P.second)
|
||||
if (P.second) {
|
||||
// Mark the local allocated for the frame base vreg.
|
||||
if (MFI.isFrameBaseVirtual() && Reg == MFI.getFrameBaseVreg())
|
||||
MFI.setFrameBaseLocal(CurLocal);
|
||||
++CurLocal;
|
||||
}
|
||||
return P.first->second;
|
||||
}
|
||||
|
||||
|
@ -244,7 +249,7 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
|
|||
|
||||
// Stackify the input if it isn't stackified yet.
|
||||
if (!MFI.isVRegStackified(OldReg)) {
|
||||
unsigned LocalId = getLocalId(Reg2Local, CurLocal, OldReg);
|
||||
unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg);
|
||||
Register NewReg = MRI.createVirtualRegister(RC);
|
||||
unsigned Opc = getLocalGetOpcode(RC);
|
||||
BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(Opc), NewReg)
|
||||
|
@ -255,7 +260,7 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
|
|||
|
||||
// Replace the TEE with a LOCAL_TEE.
|
||||
unsigned LocalId =
|
||||
getLocalId(Reg2Local, CurLocal, MI.getOperand(1).getReg());
|
||||
getLocalId(Reg2Local, MFI, CurLocal, MI.getOperand(1).getReg());
|
||||
unsigned Opc = getLocalTeeOpcode(RC);
|
||||
BuildMI(MBB, &MI, MI.getDebugLoc(), TII->get(Opc),
|
||||
MI.getOperand(0).getReg())
|
||||
|
@ -291,7 +296,7 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
|
|||
// After the drop instruction, this reg operand will not be used
|
||||
Drop->getOperand(0).setIsKill();
|
||||
} else {
|
||||
unsigned LocalId = getLocalId(Reg2Local, CurLocal, OldReg);
|
||||
unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg);
|
||||
unsigned Opc = getLocalSetOpcode(RC);
|
||||
|
||||
WebAssemblyDebugValueManager(&MI).replaceWithLocal(LocalId);
|
||||
|
@ -323,7 +328,7 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
|
|||
// immediates.
|
||||
if (MO.isDef()) {
|
||||
assert(MI.isInlineAsm());
|
||||
unsigned LocalId = getLocalId(Reg2Local, CurLocal, OldReg);
|
||||
unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg);
|
||||
// If this register operand is tied to another operand, we can't
|
||||
// change it to an immediate. Untie it first.
|
||||
MI.untieRegOperand(MI.getOperandNo(&MO));
|
||||
|
@ -341,7 +346,7 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
|
|||
// Our contract with inline asm register operands is to provide local
|
||||
// indices as immediates.
|
||||
if (MI.isInlineAsm()) {
|
||||
unsigned LocalId = getLocalId(Reg2Local, CurLocal, OldReg);
|
||||
unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg);
|
||||
// Untie it first if this reg operand is tied to another operand.
|
||||
MI.untieRegOperand(MI.getOperandNo(&MO));
|
||||
MO.ChangeToImmediate(LocalId);
|
||||
|
@ -349,7 +354,7 @@ bool WebAssemblyExplicitLocals::runOnMachineFunction(MachineFunction &MF) {
|
|||
}
|
||||
|
||||
// Insert a local.get.
|
||||
unsigned LocalId = getLocalId(Reg2Local, CurLocal, OldReg);
|
||||
unsigned LocalId = getLocalId(Reg2Local, MFI, CurLocal, OldReg);
|
||||
const TargetRegisterClass *RC = MRI.getRegClass(OldReg);
|
||||
Register NewReg = MRI.createVirtualRegister(RC);
|
||||
unsigned Opc = getLocalGetOpcode(RC);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "WebAssemblyFrameLowering.h"
|
||||
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
|
||||
#include "WebAssembly.h"
|
||||
#include "WebAssemblyInstrInfo.h"
|
||||
#include "WebAssemblyMachineFunctionInfo.h"
|
||||
#include "WebAssemblySubtarget.h"
|
||||
|
@ -259,3 +260,20 @@ void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF,
|
|||
|
||||
writeSPToGlobal(SPReg, MF, MBB, InsertPt, DL);
|
||||
}
|
||||
|
||||
TargetFrameLowering::DwarfFrameBase
|
||||
WebAssemblyFrameLowering::getDwarfFrameBase(const MachineFunction &MF) const {
|
||||
DwarfFrameBase Loc;
|
||||
Loc.Kind = DwarfFrameBase::WasmFrameBase;
|
||||
const WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
|
||||
if (needsSP(MF)) {
|
||||
unsigned LocalNum = MFI.getFrameBaseLocal();
|
||||
Loc.Location.WasmLoc = {WebAssembly::TI_LOCAL_START, LocalNum};
|
||||
} else {
|
||||
// TODO: This should work on a breakpoint at a function with no frame,
|
||||
// but probably won't work for traversing up the stack.
|
||||
// TODO: This needs a relocation for correct __stack_pointer
|
||||
Loc.Location.WasmLoc = {WebAssembly::TI_GLOBAL_START, 0};
|
||||
}
|
||||
return Loc;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ public:
|
|||
|
||||
bool hasFP(const MachineFunction &MF) const override;
|
||||
bool hasReservedCallFrame(const MachineFunction &MF) const override;
|
||||
DwarfFrameBase getDwarfFrameBase(const MachineFunction &MF) const override;
|
||||
|
||||
bool needsPrologForEH(const MachineFunction &MF) const;
|
||||
|
||||
|
|
|
@ -55,6 +55,12 @@ class WebAssemblyFunctionInfo final : public MachineFunctionInfo {
|
|||
// A virtual register holding the base pointer for functions that have
|
||||
// overaligned values on the user stack.
|
||||
unsigned BasePtrVreg = -1U;
|
||||
// A virtual register holding the frame base. This is either FP or SP
|
||||
// after it has been replaced by a vreg
|
||||
unsigned FrameBaseVreg = -1U;
|
||||
// The local holding the frame base. This is either FP or SP
|
||||
// after WebAssemblyExplicitLocals
|
||||
unsigned FrameBaseLocal = -1U;
|
||||
|
||||
// Function properties.
|
||||
bool CFGStackified = false;
|
||||
|
@ -90,6 +96,18 @@ public:
|
|||
assert(BasePtrVreg != -1U && "Base ptr vreg hasn't been set");
|
||||
return BasePtrVreg;
|
||||
}
|
||||
void setFrameBaseVreg(unsigned Reg) { FrameBaseVreg = Reg; }
|
||||
unsigned getFrameBaseVreg() const {
|
||||
assert(FrameBaseVreg != -1U && "Frame base vreg hasn't been set");
|
||||
return FrameBaseVreg;
|
||||
}
|
||||
// Return true if the frame base physreg has been replaced by a virtual reg.
|
||||
bool isFrameBaseVirtual() const { return FrameBaseVreg != -1U; }
|
||||
void setFrameBaseLocal(unsigned Local) { FrameBaseLocal = Local; }
|
||||
unsigned getFrameBaseLocal() const {
|
||||
assert(FrameBaseLocal != -1U && "Frame base local hasn't been set");
|
||||
return FrameBaseLocal;
|
||||
}
|
||||
void setBasePointerVreg(unsigned Reg) { BasePtrVreg = Reg; }
|
||||
|
||||
static const unsigned UnusedReg = -1u;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "WebAssembly.h"
|
||||
#include "WebAssemblyMachineFunctionInfo.h"
|
||||
#include "WebAssemblySubtarget.h"
|
||||
#include "llvm/CodeGen/LiveIntervals.h"
|
||||
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
|
||||
|
@ -82,10 +83,22 @@ bool WebAssemblyOptimizeLiveIntervals::runOnMachineFunction(
|
|||
SmallVector<LiveInterval *, 4> SplitLIs;
|
||||
for (unsigned I = 0, E = MRI.getNumVirtRegs(); I < E; ++I) {
|
||||
unsigned Reg = Register::index2VirtReg(I);
|
||||
auto &TRI = *MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo();
|
||||
|
||||
if (MRI.reg_nodbg_empty(Reg))
|
||||
continue;
|
||||
|
||||
LIS.splitSeparateComponents(LIS.getInterval(Reg), SplitLIs);
|
||||
if (Reg == TRI.getFrameRegister(MF) && SplitLIs.size() > 0) {
|
||||
// The live interval for the frame register was split, resulting in a new
|
||||
// VReg. For now we only support debug info output for a single frame base
|
||||
// value for the function, so just use the last one. It will certainly be
|
||||
// wrong for some part of the function, but until we are able to track
|
||||
// values through live-range splitting and stackification, it will have to
|
||||
// do.
|
||||
MF.getInfo<WebAssemblyFunctionInfo>()->setFrameBaseVreg(
|
||||
SplitLIs.back()->reg);
|
||||
}
|
||||
SplitLIs.clear();
|
||||
}
|
||||
|
||||
|
@ -103,5 +116,5 @@ bool WebAssemblyOptimizeLiveIntervals::runOnMachineFunction(
|
|||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -132,6 +132,10 @@ void WebAssemblyRegisterInfo::eliminateFrameIndex(
|
|||
|
||||
Register
|
||||
WebAssemblyRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
|
||||
// If the PReg has been replaced by a VReg, return that.
|
||||
const auto &MFI = MF.getInfo<WebAssemblyFunctionInfo>();
|
||||
if (MFI->isFrameBaseVirtual())
|
||||
return MFI->getFrameBaseVreg();
|
||||
static const unsigned Regs[2][2] = {
|
||||
/* !isArch64Bit isArch64Bit */
|
||||
/* !hasFP */ {WebAssembly::SP32, WebAssembly::SP64},
|
||||
|
|
|
@ -67,7 +67,7 @@ bool WebAssemblyReplacePhysRegs::runOnMachineFunction(MachineFunction &MF) {
|
|||
});
|
||||
|
||||
MachineRegisterInfo &MRI = MF.getRegInfo();
|
||||
const auto &TRI = *MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo();
|
||||
auto &TRI = *MF.getSubtarget<WebAssemblySubtarget>().getRegisterInfo();
|
||||
bool Changed = false;
|
||||
|
||||
assert(!mustPreserveAnalysisID(LiveIntervalsID) &&
|
||||
|
@ -88,8 +88,18 @@ bool WebAssemblyReplacePhysRegs::runOnMachineFunction(MachineFunction &MF) {
|
|||
for (auto I = MRI.reg_begin(PReg), E = MRI.reg_end(); I != E;) {
|
||||
MachineOperand &MO = *I++;
|
||||
if (!MO.isImplicit()) {
|
||||
if (VReg == WebAssembly::NoRegister)
|
||||
if (VReg == WebAssembly::NoRegister) {
|
||||
VReg = MRI.createVirtualRegister(RC);
|
||||
if (PReg == TRI.getFrameRegister(MF)) {
|
||||
auto FI = MF.getInfo<WebAssemblyFunctionInfo>();
|
||||
assert(!FI->isFrameBaseVirtual());
|
||||
FI->setFrameBaseVreg(VReg);
|
||||
LLVM_DEBUG({
|
||||
dbgs() << "replacing preg " << PReg << " with " << VReg << " ("
|
||||
<< Register::virtReg2Index(VReg) << ")\n";
|
||||
});
|
||||
}
|
||||
}
|
||||
MO.setReg(VReg);
|
||||
if (MO.getParent()->isDebugValue())
|
||||
MO.setIsDebug();
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s
|
||||
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
|
||||
|
@ -12,8 +11,8 @@ declare { i64, i128, i192, i128, i64 } @return_multi_multi()
|
|||
define i64 @test0() {
|
||||
; CHECK-LABEL: test0
|
||||
; CHECK: call return_multi_multi
|
||||
; CHECK: i64.load $0=, 8($1)
|
||||
; CHECK: local.copy $push8=, $0
|
||||
; CHECK: i64.load $[[RV:[0-9]+]]=, 8(${{[0-9]+}})
|
||||
; CHECK: local.copy $push8=, $[[RV]]
|
||||
%t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
|
||||
%t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0
|
||||
ret i64 %t1
|
||||
|
@ -22,12 +21,12 @@ define i64 @test0() {
|
|||
define i128 @test1() {
|
||||
; CHECK-LABEL: test1
|
||||
; CHECK: call return_multi_multi
|
||||
; CHECK: i64.load $1=, 16($2)
|
||||
; CHECK: i64.load $[[RV:[0-9]+]]=, 16($[[SP:[0-9]+]])
|
||||
; CHECK: i32.const $push0=, 24
|
||||
; CHECK: i32.add $push1=, $2, $pop0
|
||||
; CHECK: i32.add $push1=, $[[SP]], $pop0
|
||||
; CHECK: i64.load $push2=, 0($pop1)
|
||||
; CHECK: i64.store 8($0), $pop2
|
||||
; CHECK: i64.store 0($0), $1
|
||||
; CHECK: i64.store 0($0), $[[RV]]
|
||||
%t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
|
||||
%t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1
|
||||
ret i128 %t1
|
||||
|
@ -37,15 +36,15 @@ define i192 @test2() {
|
|||
; CHECK-LABEL: test2
|
||||
; CHECK: call return_multi_multi
|
||||
; CHECK: i32.const $push0=, 40
|
||||
; CHECK: i32.add $push1=, $3, $pop0
|
||||
; CHECK: i64.load $1=, 0($pop1)
|
||||
; CHECK: i64.load $2=, 32($3)
|
||||
; CHECK: i32.add $push1=, $[[SP:[0-9]+]], $pop0
|
||||
; CHECK: i64.load $[[L1:[0-9]+]]=, 0($pop1)
|
||||
; CHECK: i64.load $[[L2:[0-9]+]]=, 32($[[SP]])
|
||||
; CHECK: i32.const $push2=, 48
|
||||
; CHECK: i32.add $push3=, $3, $pop2
|
||||
; CHECK: i32.add $push3=, $[[SP]], $pop2
|
||||
; CHECK: i64.load $push4=, 0($pop3)
|
||||
; CHECK: i64.store 16($0), $pop4
|
||||
; CHECK: i64.store 0($0), $2
|
||||
; CHECK: i64.store 8($0), $1
|
||||
; CHECK: i64.store 0($0), $[[L2]]
|
||||
; CHECK: i64.store 8($0), $[[L1]]
|
||||
%t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
|
||||
%t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 2
|
||||
ret i192 %t1
|
||||
|
@ -54,12 +53,12 @@ define i192 @test2() {
|
|||
define i128 @test3() {
|
||||
; CHECK-LABEL: test3
|
||||
; CHECK: call return_multi_multi
|
||||
; CHECK: i64.load $1=, 56($2)
|
||||
; CHECK: i64.load $[[L1:[0-9]+]]=, 56($[[SP:[0-9]+]])
|
||||
; CHECK: i32.const $push0=, 64
|
||||
; CHECK: i32.add $push1=, $2, $pop0
|
||||
; CHECK: i32.add $push1=, $[[SP]], $pop0
|
||||
; CHECK: i64.load $push2=, 0($pop1)
|
||||
; CHECK: i64.store 8($0), $pop2
|
||||
; CHECK: i64.store 0($0), $1
|
||||
; CHECK: i64.store 0($0), $[[L1]]
|
||||
%t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
|
||||
%t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 3
|
||||
ret i128 %t1
|
||||
|
@ -68,8 +67,8 @@ define i128 @test3() {
|
|||
define i64 @test4() {
|
||||
; CHECK-LABEL: test4
|
||||
; CHECK: call return_multi_multi
|
||||
; CHECK: i64.load $0=, 72($1)
|
||||
; CHECK: local.copy $push8=, $0
|
||||
; CHECK: i64.load $[[L1:[0-9]+]]=, 72($[[SP:[0-9]+]])
|
||||
; CHECK: local.copy $push8=, $[[L1]]
|
||||
%t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
|
||||
%t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 4
|
||||
ret i64 %t1
|
||||
|
@ -81,17 +80,17 @@ define { i64, i128 } @test5() {
|
|||
; CHECK-LABEL: test5
|
||||
; CHECK: call return_multi_multi
|
||||
; CHECK: i32.const $push10=, 8
|
||||
; CHECK: i32.add $push11=, $3, $pop10
|
||||
; CHECK: i32.add $push11=, $[[SP:[0-9]+]], $pop10
|
||||
; CHECK: i32.const $push0=, 16
|
||||
; CHECK: i32.add $push1=, $pop11, $pop0
|
||||
; CHECK: i64.load $1=, 0($pop1)
|
||||
; CHECK: i64.load $2=, 8($3)
|
||||
; CHECK: i64.load $push2=, 16($3)
|
||||
; CHECK: i64.load $[[L1:[0-9]+]]=, 0($pop1)
|
||||
; CHECK: i64.load $[[L2:[0-9]+]]=, 8($[[SP]])
|
||||
; CHECK: i64.load $push2=, 16($[[SP]])
|
||||
; CHECK: i64.store 8($0), $pop2
|
||||
; CHECK: i32.const $push12=, 16
|
||||
; CHECK: i32.add $push3=, $0, $pop12
|
||||
; CHECK: i64.store 0($pop3), $1
|
||||
; CHECK: i64.store 0($0), $2
|
||||
; CHECK: i64.store 0($pop3), $[[L1]]
|
||||
; CHECK: i64.store 0($0), $[[L2]]
|
||||
%t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
|
||||
%r0 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0
|
||||
%r1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1
|
||||
|
@ -104,19 +103,19 @@ define { i128, i128 } @test6() {
|
|||
; CHECK-LABEL: test6
|
||||
; CHECK: call return_multi_multi
|
||||
; CHECK: i32.const $push0=, 24
|
||||
; CHECK: i32.add $push1=, $4, $pop0
|
||||
; CHECK: i64.load $1=, 0($pop1)
|
||||
; CHECK: i32.add $push1=, $[[SP:[0-9]+]], $pop0
|
||||
; CHECK: i64.load $[[L1:[0-9]+]]=, 0($pop1)
|
||||
; CHECK: i32.const $push2=, 64
|
||||
; CHECK: i32.add $push3=, $4, $pop2
|
||||
; CHECK: i64.load $2=, 0($pop3)
|
||||
; CHECK: i64.load $3=, 16($4)
|
||||
; CHECK: i64.load $push4=, 56($4)
|
||||
; CHECK: i32.add $push3=, $[[SP]], $pop2
|
||||
; CHECK: i64.load $[[L2:[0-9]+]]=, 0($pop3)
|
||||
; CHECK: i64.load $[[L3:[0-9]+]]=, 16($[[SP]])
|
||||
; CHECK: i64.load $push4=, 56($[[SP]])
|
||||
; CHECK: i64.store 16($0), $pop4
|
||||
; CHECK: i32.const $push5=, 24
|
||||
; CHECK: i32.add $push6=, $0, $pop5
|
||||
; CHECK: i64.store 0($pop6), $2
|
||||
; CHECK: i64.store 0($0), $3
|
||||
; CHECK: i64.store 8($0), $1
|
||||
; CHECK: i64.store 0($pop6), $[[L2]]
|
||||
; CHECK: i64.store 0($0), $[[L3]]
|
||||
; CHECK: i64.store 8($0), $[[L1]]
|
||||
%t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
|
||||
%r1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1
|
||||
%r3 = extractvalue { i64, i128, i192, i128, i64 } %t0, 3
|
||||
|
@ -129,21 +128,21 @@ define { i64, i192 } @test7() {
|
|||
; CHECK-LABEL: test7
|
||||
; CHECK: call return_multi_multi
|
||||
; CHECK: i32.const $push2=, 40
|
||||
; CHECK: i32.add $push3=, $4, $pop2
|
||||
; CHECK: i64.load $1=, 0($pop3)
|
||||
; CHECK: i64.load $2=, 8($4)
|
||||
; CHECK: i64.load $3=, 32($4)
|
||||
; CHECK: i32.add $push3=, $[[SP:[0-9]+]], $pop2
|
||||
; CHECK: i64.load $[[L1:[0-9]+]]=, 0($pop3)
|
||||
; CHECK: i64.load $[[L2:[0-9]+]]=, 8($[[SP]])
|
||||
; CHECK: i64.load $[[L3:[0-9]+]]=, 32($[[SP]])
|
||||
; CHECK: i32.const $push0=, 24
|
||||
; CHECK: i32.add $push1=, $0, $pop0
|
||||
; CHECK: i32.const $push4=, 48
|
||||
; CHECK: i32.add $push5=, $4, $pop4
|
||||
; CHECK: i32.add $push5=, $[[SP]], $pop4
|
||||
; CHECK: i64.load $push6=, 0($pop5)
|
||||
; CHECK: i64.store 0($pop1), $pop6
|
||||
; CHECK: i64.store 8($0), $3
|
||||
; CHECK: i64.store 8($0), $[[L3]]
|
||||
; CHECK: i32.const $push7=, 16
|
||||
; CHECK: i32.add $push8=, $0, $pop7
|
||||
; CHECK: i64.store 0($pop8), $1
|
||||
; CHECK: i64.store 0($0), $2
|
||||
; CHECK: i64.store 0($pop8), $[[L1]]
|
||||
; CHECK: i64.store 0($0), $[[L2]]
|
||||
%t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
|
||||
%r0 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0
|
||||
%r2 = extractvalue { i64, i128, i192, i128, i64 } %t0, 2
|
||||
|
@ -156,37 +155,37 @@ define { i128, i192, i128, i64 } @test8() {
|
|||
; CHECK-LABEL: test8
|
||||
; CHECK: call return_multi_multi
|
||||
; CHECK: i32.const $push0=, 64
|
||||
; CHECK: i32.add $push1=, $8, $pop0
|
||||
; CHECK: i64.load $1=, 0($pop1)
|
||||
; CHECK: i32.add $push1=, $[[SP:[0-9]+]], $pop0
|
||||
; CHECK: i64.load $[[L1:[0-9]+]]=, 0($pop1)
|
||||
; CHECK: i32.const $push20=, 8
|
||||
; CHECK: i32.add $push21=, $8, $pop20
|
||||
; CHECK: i32.add $push21=, $[[SP]], $pop20
|
||||
; CHECK: i32.const $push2=, 32
|
||||
; CHECK: i32.add $push3=, $pop21, $pop2
|
||||
; CHECK: i64.load $2=, 0($pop3)
|
||||
; CHECK: i64.load $[[L2:[0-9]+]]=, 0($pop3)
|
||||
; CHECK: i32.const $push4=, 48
|
||||
; CHECK: i32.add $push5=, $8, $pop4
|
||||
; CHECK: i64.load $3=, 0($pop5)
|
||||
; CHECK: i32.add $push5=, $[[SP]], $pop4
|
||||
; CHECK: i64.load $[[L3:[0-9]+]]=, 0($pop5)
|
||||
; CHECK: i32.const $push6=, 24
|
||||
; CHECK: i32.add $push7=, $8, $pop6
|
||||
; CHECK: i64.load $4=, 0($pop7)
|
||||
; CHECK: i64.load $5=, 8($8)
|
||||
; CHECK: i64.load $6=, 56($8)
|
||||
; CHECK: i64.load $7=, 32($8)
|
||||
; CHECK: i64.load $push8=, 16($8)
|
||||
; CHECK: i32.add $push7=, $[[SP]], $pop6
|
||||
; CHECK: i64.load $[[L4:[0-9]+]]=, 0($pop7)
|
||||
; CHECK: i64.load $[[L5:[0-9]+]]=, 8($[[SP]])
|
||||
; CHECK: i64.load $[[L6:[0-9]+]]=, 56($[[SP]])
|
||||
; CHECK: i64.load $[[L7:[0-9]+]]=, 32($[[SP]])
|
||||
; CHECK: i64.load $push8=, 16($[[SP]])
|
||||
; CHECK: i64.store 40($0), $pop8
|
||||
; CHECK: i32.const $push9=, 48
|
||||
; CHECK: i32.add $push10=, $0, $pop9
|
||||
; CHECK: i64.store 0($pop10), $4
|
||||
; CHECK: i64.store 0($pop10), $[[L4]]
|
||||
; CHECK: i32.const $push22=, 32
|
||||
; CHECK: i32.add $push11=, $0, $pop22
|
||||
; CHECK: i64.store 0($pop11), $3
|
||||
; CHECK: i64.store 16($0), $7
|
||||
; CHECK: i64.store 0($pop11), $[[L3]]
|
||||
; CHECK: i64.store 16($0), $[[L7]]
|
||||
; CHECK: i32.const $push12=, 24
|
||||
; CHECK: i32.add $push13=, $0, $pop12
|
||||
; CHECK: i64.store 0($pop13), $2
|
||||
; CHECK: i64.store 0($0), $6
|
||||
; CHECK: i64.store 8($0), $1
|
||||
; CHECK: i64.store 56($0), $5
|
||||
; CHECK: i64.store 0($pop13), $[[L2]]
|
||||
; CHECK: i64.store 0($0), $[[L6]]
|
||||
; CHECK: i64.store 8($0), $[[L1]]
|
||||
; CHECK: i64.store 56($0), $[[L5]]
|
||||
%t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi()
|
||||
%r0 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0
|
||||
%r1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1
|
||||
|
|
|
@ -59,74 +59,74 @@
|
|||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: Section {
|
||||
; CHECK-NEXT: Type: CUSTOM (0x0)
|
||||
; CHECK-NEXT: Size: 84
|
||||
; CHECK-NEXT: Size: 86
|
||||
; CHECK-NEXT: Offset: 283
|
||||
; CHECK-NEXT: Name: .debug_abbrev
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: Section {
|
||||
; CHECK-NEXT: Type: CUSTOM (0x0)
|
||||
; CHECK-NEXT: Size: 106
|
||||
; CHECK-NEXT: Offset: 387
|
||||
; CHECK-NEXT: Size: 111
|
||||
; CHECK-NEXT: Offset: 389
|
||||
; CHECK-NEXT: Name: .debug_info
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: Section {
|
||||
; CHECK-NEXT: Type: CUSTOM (0x0)
|
||||
; CHECK-NEXT: Size: 42
|
||||
; CHECK-NEXT: Offset: 511
|
||||
; CHECK-NEXT: Offset: 518
|
||||
; CHECK-NEXT: Name: .debug_pubnames
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: Section {
|
||||
; CHECK-NEXT: Type: CUSTOM (0x0)
|
||||
; CHECK-NEXT: Size: 26
|
||||
; CHECK-NEXT: Offset: 575
|
||||
; CHECK-NEXT: Offset: 582
|
||||
; CHECK-NEXT: Name: .debug_pubtypes
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: Section {
|
||||
; CHECK-NEXT: Type: CUSTOM (0x0)
|
||||
; CHECK-NEXT: Size: 57
|
||||
; CHECK-NEXT: Offset: 623
|
||||
; CHECK-NEXT: Offset: 630
|
||||
; CHECK-NEXT: Name: .debug_line
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: Section {
|
||||
; CHECK-NEXT: Type: CUSTOM (0x0)
|
||||
; CHECK-NEXT: Size: 88
|
||||
; CHECK-NEXT: Offset: 698
|
||||
; CHECK-NEXT: Offset: 705
|
||||
; CHECK-NEXT: Name: linking
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: Section {
|
||||
; CHECK-NEXT: Type: CUSTOM (0x0)
|
||||
; CHECK-NEXT: Size: 9
|
||||
; CHECK-NEXT: Offset: 800
|
||||
; CHECK-NEXT: Offset: 807
|
||||
; CHECK-NEXT: Name: reloc.DATA
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: Section {
|
||||
; CHECK-NEXT: Type: CUSTOM (0x0)
|
||||
; CHECK-NEXT: Size: 58
|
||||
; CHECK-NEXT: Offset: 826
|
||||
; CHECK-NEXT: Offset: 833
|
||||
; CHECK-NEXT: Name: reloc..debug_info
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: Section {
|
||||
; CHECK-NEXT: Type: CUSTOM (0x0)
|
||||
; CHECK-NEXT: Size: 6
|
||||
; CHECK-NEXT: Offset: 908
|
||||
; CHECK-NEXT: Offset: 915
|
||||
; CHECK-NEXT: Name: reloc..debug_pubnames
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: Section {
|
||||
; CHECK-NEXT: Type: CUSTOM (0x0)
|
||||
; CHECK-NEXT: Size: 6
|
||||
; CHECK-NEXT: Offset: 942
|
||||
; CHECK-NEXT: Offset: 949
|
||||
; CHECK-NEXT: Name: reloc..debug_pubtypes
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: Section {
|
||||
; CHECK-NEXT: Type: CUSTOM (0x0)
|
||||
; CHECK-NEXT: Size: 6
|
||||
; CHECK-NEXT: Offset: 976
|
||||
; CHECK-NEXT: Offset: 983
|
||||
; CHECK-NEXT: Name: reloc..debug_line
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: Section {
|
||||
; CHECK-NEXT: Type: CUSTOM (0x0)
|
||||
; CHECK-NEXT: Size: 77
|
||||
; CHECK-NEXT: Offset: 1006
|
||||
; CHECK-NEXT: Offset: 1013
|
||||
; CHECK-NEXT: Name: producers
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT:]
|
||||
|
@ -148,7 +148,7 @@
|
|||
; CHECK-NEXT: 0x44 R_WASM_SECTION_OFFSET_I32 .debug_str 113
|
||||
; CHECK-NEXT: 0x50 R_WASM_MEMORY_ADDR_I32 ptr2 0
|
||||
; CHECK-NEXT: 0x5B R_WASM_FUNCTION_OFFSET_I32 f2 0
|
||||
; CHECK-NEXT: 0x63 R_WASM_SECTION_OFFSET_I32 .debug_str 118
|
||||
; CHECK-NEXT: 0x68 R_WASM_SECTION_OFFSET_I32 .debug_str 118
|
||||
; CHECK-NEXT: }
|
||||
; CHECK-NEXT: Section (11) .debug_pubnames {
|
||||
; CHECK-NEXT: 0x6 R_WASM_SECTION_OFFSET_I32 .debug_info 0
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
; RUN: llc -filetype=obj %s -o - | llvm-dwarfdump - | FileCheck %s
|
||||
|
||||
; ModuleID = 'debugtest.c'
|
||||
source_filename = "debugtest.c"
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
|
||||
target triple = "wasm32"
|
||||
; Function Attrs: noinline nounwind optnone
|
||||
define hidden i32 @foo(i32 %arg) #0 !dbg !7 {
|
||||
entry:
|
||||
%arg.addr = alloca i32, align 4
|
||||
%a = alloca i32, align 4
|
||||
%b = alloca i32, align 4
|
||||
store i32 %arg, i32* %arg.addr, align 4
|
||||
call void @llvm.dbg.declare(metadata i32* %arg.addr, metadata !11, metadata !DIExpression()), !dbg !12
|
||||
call void @llvm.dbg.declare(metadata i32* %a, metadata !13, metadata !DIExpression()), !dbg !14
|
||||
store i32 1, i32* %a, align 4, !dbg !14
|
||||
call void @llvm.dbg.declare(metadata i32* %b, metadata !15, metadata !DIExpression()), !dbg !17
|
||||
store i32 2, i32* %b, align 4, !dbg !17
|
||||
%0 = load i32, i32* %b, align 4, !dbg !18
|
||||
store i32 %0, i32* %arg.addr, align 4, !dbg !19
|
||||
%1 = load i32, i32* %arg.addr, align 4, !dbg !20
|
||||
%2 = load i32, i32* %a, align 4, !dbg !21
|
||||
%add = add nsw i32 %1, %2, !dbg !22
|
||||
ret i32 %add, !dbg !23
|
||||
}
|
||||
; Function Attrs: nounwind readnone speculatable willreturn
|
||||
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
|
||||
|
||||
attributes #0 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
||||
attributes #1 = { nounwind readnone speculatable willreturn }
|
||||
attributes #2 = { nounwind }
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!3, !4, !5}
|
||||
!llvm.ident = !{!6}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (https://github.com/llvm/llvm-project.git 6b38826e3a5f402498f0ea721b8c90d727f36205)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
|
||||
!1 = !DIFile(filename: "debugtest.c", directory: "/s/llvm-upstream")
|
||||
!2 = !{}
|
||||
!3 = !{i32 7, !"Dwarf Version", i32 4}
|
||||
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!5 = !{i32 1, !"wchar_size", i32 4}
|
||||
!6 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project.git 6b38826e3a5f402498f0ea721b8c90d727f36205)"}
|
||||
!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
|
||||
!8 = !DISubroutineType(types: !9)
|
||||
!9 = !{!10, !10}
|
||||
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
||||
!11 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 1, type: !10)
|
||||
!12 = !DILocation(line: 1, column: 14, scope: !7)
|
||||
!13 = !DILocalVariable(name: "a", scope: !7, file: !1, line: 2, type: !10)
|
||||
!14 = !DILocation(line: 2, column: 7, scope: !7)
|
||||
!15 = !DILocalVariable(name: "b", scope: !16, file: !1, line: 4, type: !10)
|
||||
!16 = distinct !DILexicalBlock(scope: !7, file: !1, line: 3, column: 3)
|
||||
!17 = !DILocation(line: 4, column: 9, scope: !16)
|
||||
!18 = !DILocation(line: 5, column: 11, scope: !16)
|
||||
!19 = !DILocation(line: 5, column: 9, scope: !16)
|
||||
!20 = !DILocation(line: 7, column: 10, scope: !7)
|
||||
!21 = !DILocation(line: 7, column: 16, scope: !7)
|
||||
!22 = !DILocation(line: 7, column: 14, scope: !7)
|
||||
!23 = !DILocation(line: 7, column: 3, scope: !7)
|
||||
!24 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 10, type: !8, scopeLine: 10, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
|
||||
!25 = !DILocalVariable(name: "arg", arg: 1, scope: !24, file: !1, line: 10, type: !10)
|
||||
!26 = !DILocation(line: 10, column: 14, scope: !24)
|
||||
!27 = !DILocation(line: 11, column: 10, scope: !24)
|
||||
!28 = !DILocation(line: 11, column: 3, scope: !24)
|
||||
!29 = !DILocalVariable(name: "__vla_expr0", scope: !24, type: !30, flags: DIFlagArtificial)
|
||||
!30 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
|
||||
!31 = !DILocation(line: 0, scope: !24)
|
||||
!32 = !DILocalVariable(name: "aa", scope: !24, file: !1, line: 11, type: !33)
|
||||
!33 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, elements: !34)
|
||||
!34 = !{!35}
|
||||
!35 = !DISubrange(count: !29)
|
||||
!36 = !DILocation(line: 11, column: 7, scope: !24)
|
||||
!37 = !DILocalVariable(name: "cc", scope: !24, file: !1, line: 13, type: !38)
|
||||
!38 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
|
||||
!39 = !DILocation(line: 13, column: 8, scope: !24)
|
||||
!40 = !DILocation(line: 15, column: 1, scope: !24)
|
||||
|
||||
; CHECK-LABEL: DW_TAG_compile_unit
|
||||
; CHECK-LABEL: DW_TAG_subprogram
|
||||
; CHECK-NEXT: DW_AT_low_pc (0x0000000000000002)
|
||||
; CHECK-NEXT: DW_AT_high_pc (0x0000000000000039)
|
||||
; CHECK-NEXT: DW_AT_frame_base (DW_OP_WASM_location 0x0 +1, DW_OP_stack_value)
|
||||
; CHECK-NEXT: DW_AT_name ("foo")
|
||||
; CHECK-NEXT: DW_AT_decl_file ("/s/llvm-upstream{{(/|\\)}}debugtest.c")
|
||||
; CHECK-NEXT: DW_AT_decl_line (1)
|
||||
; CHECK-NEXT: DW_AT_prototyped (true)
|
||||
; CHECK-NEXT: DW_AT_type (0x00000073 "int")
|
||||
; CHECK-NEXT: DW_AT_external (true)
|
||||
; CHECK-LABEL: DW_TAG_formal_parameter
|
||||
; CHECK-NEXT: DW_AT_location (DW_OP_fbreg +12)
|
||||
; CHECK-NEXT: DW_AT_name ("arg")
|
||||
; CHECK-NEXT: DW_AT_decl_file ("/s/llvm-upstream{{(/|\\)}}debugtest.c")
|
||||
; CHECK-NEXT: DW_AT_decl_line (1)
|
||||
; CHECK-NEXT: DW_AT_type (0x00000073 "int")
|
||||
|
||||
; CHECK-LABEL: DW_TAG_variable
|
||||
; CHECK-NEXT: DW_AT_location (DW_OP_fbreg +8)
|
||||
; CHECK-NEXT: DW_AT_name ("a")
|
||||
; CHECK-NEXT: DW_AT_decl_file ("/s/llvm-upstream{{(/|\\)}}debugtest.c")
|
||||
; CHECK-NEXT: DW_AT_decl_line (2)
|
||||
; CHECK-NEXT: DW_AT_type (0x00000073 "int")
|
||||
|
||||
; CHECK-LABEL: DW_TAG_lexical_block
|
||||
; CHECK-NEXT: DW_AT_low_pc (0x000000000000001c)
|
||||
; CHECK-NEXT: DW_AT_high_pc (0x000000000000002d)
|
||||
|
||||
; CHECK-LABEL: DW_TAG_variable
|
||||
; CHECK-NEXT: DW_AT_location (DW_OP_fbreg +4)
|
||||
; CHECK-NEXT: DW_AT_name ("b")
|
||||
; CHECK-NEXT: DW_AT_decl_file ("/s/llvm-upstream{{(/|\\)}}debugtest.c")
|
||||
; CHECK-NEXT: DW_AT_decl_line (4)
|
||||
; CHECK-NEXT: DW_AT_type (0x00000073 "int")
|
|
@ -1,7 +1,7 @@
|
|||
; RUN: llc -filetype=obj %s -o - | llvm-dwarfdump - | FileCheck %s
|
||||
|
||||
; CHECK: .debug_info contents:
|
||||
; CHECK-NEXT: 0x00000000: Compile Unit: length = 0x00000066 version = 0x0004 abbr_offset = 0x0000 addr_size = 0x04 (next unit at 0x0000006a)
|
||||
; CHECK-NEXT: 0x00000000: Compile Unit: length = 0x0000006b version = 0x0004 abbr_offset = 0x0000 addr_size = 0x04 (next unit at 0x0000006f)
|
||||
|
||||
; CHECK: 0x0000000b: DW_TAG_compile_unit
|
||||
; CHECK-NEXT: DW_AT_producer ("clang version 6.0.0 (trunk 315924) (llvm/trunk 315960)")
|
||||
|
@ -46,13 +46,14 @@
|
|||
; CHECK: 0x0000005a: DW_TAG_subprogram
|
||||
; CHECK-NEXT: DW_AT_low_pc (0x0000000000000002)
|
||||
; CHECK-NEXT: DW_AT_high_pc (0x0000000000000004)
|
||||
; CHECK-NEXT: DW_AT_frame_base (DW_OP_WASM_location 0x1 +0, DW_OP_stack_value)
|
||||
; CHECK-NEXT: DW_AT_name ("f2")
|
||||
; CHECK-NEXT: DW_AT_decl_file ("/usr/local/google/home/sbc/dev/wasm/simple{{[/\\]}}test.c")
|
||||
; CHECK-NEXT: DW_AT_decl_line (2)
|
||||
; CHECK-NEXT: DW_AT_prototyped (true)
|
||||
; CHECK-NEXT: DW_AT_external (true)
|
||||
|
||||
; CHECK: 0x00000069: NULL
|
||||
; CHECK: 0x0000006e: NULL
|
||||
|
||||
target triple = "wasm32-unknown-unknown"
|
||||
|
||||
|
|
Loading…
Reference in New Issue