diff --git a/llvm/lib/Target/AMDGPU/SIFrameLowering.h b/llvm/lib/Target/AMDGPU/SIFrameLowering.h --- a/llvm/lib/Target/AMDGPU/SIFrameLowering.h +++ b/llvm/lib/Target/AMDGPU/SIFrameLowering.h @@ -73,6 +73,9 @@ bool hasFP(const MachineFunction &MF) const override; bool requiresStackPointerReference(const MachineFunction &MF) const; + /// Create a CFI index for CFIInst and build a MachineInstr around it. + void buildCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + const DebugLoc &DL, const MCCFIInstruction &CFIInst) const; }; } // end namespace llvm diff --git a/llvm/lib/Target/AMDGPU/SIFrameLowering.cpp b/llvm/lib/Target/AMDGPU/SIFrameLowering.cpp --- a/llvm/lib/Target/AMDGPU/SIFrameLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIFrameLowering.cpp @@ -17,7 +17,9 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/MC/MCDwarf.h" using namespace llvm; @@ -452,6 +454,7 @@ const SIRegisterInfo *TRI = &TII->getRegisterInfo(); MachineRegisterInfo &MRI = MF.getRegInfo(); const Function &F = MF.getFunction(); + const MCRegisterInfo *MCRI = MF.getMMI().getContext().getRegisterInfo(); assert(MFI->isEntryFunction()); @@ -497,6 +500,24 @@ DebugLoc DL; MachineBasicBlock::iterator I = MBB.begin(); + // On entry the SP/FP are not set up, so we need to define the CFA in terms + // of a literal location expression. + static const char CFAEncodedInst[] = { + dwarf::DW_CFA_def_cfa_expression, + 3, // length + static_cast(dwarf::DW_OP_lit0), + static_cast( + dwarf::DW_OP_lit6), // DW_ASPACE_AMDGPU_private_wave FIXME: + // should be defined elsewhere + static_cast(dwarf::DW_OP_LLVM_form_aspace_address)}; + buildCFI(MBB, I, DL, + MCCFIInstruction::createEscape( + nullptr, StringRef(CFAEncodedInst, sizeof(CFAEncodedInst)))); + // Unwinding halts when the return address (PC) is undefined. + buildCFI(MBB, I, DL, + MCCFIInstruction::createUndefined( + nullptr, MCRI->getDwarfRegNum(AMDGPU::PC_REG, false))); + // We found the SRSRC first because it needs four registers and has an // alignment requirement. If the SRSRC that we found is clobbering with // the scratch wave offset, which may be in a fixed SGPR or a free SGPR @@ -1395,3 +1416,15 @@ // references the SP, like variable sized stack objects. return frameTriviallyRequiresSP(MFI); } + +// Build a CFI MachineInstr for the \p CFIInst CFI rule +void SIFrameLowering::buildCFI(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + const DebugLoc &DL, + const MCCFIInstruction &CFIInst) const { + MachineFunction &MF = *MBB.getParent(); + const SIInstrInfo *TII = MF.getSubtarget().getInstrInfo(); + BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(MF.addFrameInst(CFIInst)) + .setMIFlag(MachineInstr::FrameSetup); +} diff --git a/llvm/test/CodeGen/AMDGPU/debug-frame.ll b/llvm/test/CodeGen/AMDGPU/debug-frame.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/debug-frame.ll @@ -0,0 +1,34 @@ +; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -filetype=asm -o - %s | FileCheck %s + +; CHECK-LABEL: kern1: +; CHECK: .cfi_startproc + +; CHECK-NOT: .cfi_{{.*}} + +; CHECK: %bb.0: +; DW_CFA_def_cfa_expression [0x0f] +; BLOCK_LENGTH ULEB128(3)=[0x03] +; DW_OP_lit0 [0x30] +; DW_OP_lit6 [0x36] +; DW_OP_LLVM_form_aspace_address [0xe1] +; CHECK-NEXT: .cfi_escape 0x0f, 0x03, 0x30, 0x36, 0xe1 +; PC_64 = 16 +; CHECK-NEXT: .cfi_undefined 16 + +; CHECK-NOT: .cfi_{{.*}} + +; CHECK: .cfi_endproc +define protected amdgpu_kernel void @kern1() #0 { +entry: + ret void +} + +attributes #0 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, emissionKind: FullDebug) +!1 = !DIFile(filename: "filename", directory: "directory") +!2 = !{i32 7, !"Dwarf Version", i32 4} +!3 = !{i32 2, !"Debug Info Version", i32 3} diff --git a/llvm/test/CodeGen/AMDGPU/entry-function-cfi.mir b/llvm/test/CodeGen/AMDGPU/entry-function-cfi.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/entry-function-cfi.mir @@ -0,0 +1,31 @@ +# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -run-pass=prologepilog -o - %s | FileCheck %s + +--- | + + define protected amdgpu_kernel void @kern1() { + entry: + ret void + } +... +--- +name: kern1 +alignment: 1 +tracksRegLiveness: true +frameInfo: + maxAlignment: 1 +machineFunctionInfo: + maxKernArgAlign: 1 + isEntryFunction: true + scratchRSrcReg: '$sgpr100_sgpr101_sgpr102_sgpr103' + stackPtrOffsetReg: '$sgpr32' + argumentInfo: + workGroupIDX: { reg: '$sgpr0' } + privateSegmentWaveByteOffset: { reg: '$sgpr1' } + workItemIDX: { reg: '$vgpr0' } +body: | + bb.0: + ; CHECK: frame-setup CFI_INSTRUCTION escape 0x0f, 0x03, 0x30, 0x36, 0xe1 + ; CHECK: frame-setup CFI_INSTRUCTION undefined $pc_reg + S_ENDPGM 0 + +... diff --git a/llvm/test/CodeGen/AMDGPU/llvm.dbg.value.ll b/llvm/test/CodeGen/AMDGPU/llvm.dbg.value.ll --- a/llvm/test/CodeGen/AMDGPU/llvm.dbg.value.ll +++ b/llvm/test/CodeGen/AMDGPU/llvm.dbg.value.ll @@ -21,6 +21,8 @@ ; GCN-LABEL: {{^}}only_undef_dbg_value: ; NOOPT: ;DEBUG_VALUE: test_debug_value:globalptr_arg <- [DW_OP_constu 1, DW_OP_swap, DW_OP_xderef] undef +; NOOPT-NEXT: .cfi_escape 0x0f, 0x03, 0x30, 0x36, 0xe1 +; NOOPT-NEXT: .cfi_undefined 16 ; NOOPT-NEXT: s_endpgm ; OPT: s_endpgm