diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h --- a/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -22,6 +22,7 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SourceMgr.h" #include @@ -211,8 +212,8 @@ /// context. PseudoProbeHandler *PP = nullptr; - /// If the current module uses dwarf CFI annotations strictly for debugging. - bool isCFIMoveForDebugging = false; + /// Cached bitwise OR of CFISection flags for all functions in the module. + unsigned ModuleCFISections = DwarfCFI::CFISection::None; protected: explicit AsmPrinter(TargetMachine &TM, std::unique_ptr Streamer); @@ -369,15 +370,22 @@ void emitRemarksSection(remarks::RemarkStreamer &RS); - enum CFIMoveType { CFI_M_None, CFI_M_EH, CFI_M_Debug }; - CFIMoveType needsCFIMoves() const; + /// Get the CFISection flags for a function. + unsigned getCFISectionsToEmit(const Function &F) const; - /// Returns false if needsCFIMoves() == CFI_M_EH for any function - /// in the module. - bool needsOnlyDebugCFIMoves() const { return isCFIMoveForDebugging; } + /// Get the CFISection flags for a function. + unsigned getCFISectionsToEmit(const MachineFunction &MF) const; + + /// Get the bitwise OR of CFISection flags for all functions in the module. + unsigned getCFISectionsToEmit() const { return ModuleCFISections; } bool needsSEHMoves(); + /// Returns whether or not we should ensure a .debug_frame section with DWARF + /// CFI unwind information is emitted, regardless of the exception handling + /// type. + bool needsDwarfFrameSection() const; + /// Print to the current output stream assembly representations of the /// constants in the constant pool MCP. This is used to print out constants /// which have been "spilled to memory" by the code generator. diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h --- a/llvm/include/llvm/MC/MCAsmInfo.h +++ b/llvm/include/llvm/MC/MCAsmInfo.h @@ -45,6 +45,17 @@ } // end namespace WinEH +namespace DwarfCFI { + +// Flags representing which CFI sections are required for a function. +enum CFISection : unsigned { + None = 0, ///< Do not emit both .eh_frame and .debug_frame + EH = 1, ///< Emit .eh_frame + Debug = 2 ///< Emit .debug_frame +}; + +} // end namespace DwarfCFI + namespace LCOMM { enum LCOMMType { NoAlignment, ByteAlignment, Log2Alignment }; @@ -374,6 +385,11 @@ /// false. bool SupportsDebugInformation = false; + /// True if target supports emitting .debug_frame unwind information when + /// ExceptionsType = ExceptionHandling::None and debug info is requested. + /// Defaults to false. + bool SupportsDebugOnlyCFI = false; + /// Exception handling format for the target. Defaults to None. ExceptionHandling ExceptionsType = ExceptionHandling::None; @@ -642,6 +658,8 @@ bool doesSupportDebugInformation() const { return SupportsDebugInformation; } + bool doesSupportDebugOnlyCFI() const { return SupportsDebugOnlyCFI; } + ExceptionHandling getExceptionHandlingType() const { return ExceptionsType; } WinEH::EncodingType getWinEHEncodingType() const { return WinEHEncodingType; } diff --git a/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp b/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp --- a/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp @@ -39,13 +39,13 @@ if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM) getTargetStreamer().emitFnStart(); // See if we need call frame info. - AsmPrinter::CFIMoveType MoveType = Asm->needsCFIMoves(); - assert(MoveType != AsmPrinter::CFI_M_EH && + unsigned CFISections = Asm->getCFISectionsToEmit(); + assert(!(CFISections & DwarfCFI::CFISection::EH) && "non-EH CFI not yet supported in prologue with EHABI lowering"); - if (MoveType == AsmPrinter::CFI_M_Debug) { + if (CFISections & DwarfCFI::CFISection::Debug) { if (!hasEmittedCFISections) { - if (Asm->needsOnlyDebugCFIMoves()) + if (Asm->getCFISectionsToEmit() == DwarfCFI::CFISection::Debug) Asm->OutStreamer->emitCFISections(false, true); hasEmittedCFISections = true; } diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -347,31 +347,25 @@ } switch (MAI->getExceptionHandlingType()) { + case ExceptionHandling::None: case ExceptionHandling::SjLj: case ExceptionHandling::DwarfCFI: case ExceptionHandling::ARM: - isCFIMoveForDebugging = true; - if (MAI->getExceptionHandlingType() != ExceptionHandling::DwarfCFI) - break; - for (auto &F: M.getFunctionList()) { - // If the module contains any function with unwind data, - // .eh_frame has to be emitted. - // Ignore functions that won't get emitted. - if (!F.isDeclarationForLinker() && F.needsUnwindTableEntry()) { - isCFIMoveForDebugging = false; - break; - } - } + for (auto &F : M.getFunctionList()) + ModuleCFISections |= getCFISectionsToEmit(F); + assert(MAI->getExceptionHandlingType() == ExceptionHandling::DwarfCFI || + !(ModuleCFISections & DwarfCFI::CFISection::EH)); break; default: - isCFIMoveForDebugging = false; break; } EHStreamer *ES = nullptr; switch (MAI->getExceptionHandlingType()) { case ExceptionHandling::None: - break; + if (!needsDwarfFrameSection()) + break; + LLVM_FALLTHROUGH; case ExceptionHandling::SjLj: case ExceptionHandling::DwarfCFI: ES = new DwarfCFIException(this); @@ -1012,28 +1006,47 @@ return true; } -AsmPrinter::CFIMoveType AsmPrinter::needsCFIMoves() const { +unsigned AsmPrinter::getCFISectionsToEmit(const Function &F) const { + unsigned CFISections = DwarfCFI::CFISection::None; + + // Ignore functions that won't get emitted. + if (F.isDeclarationForLinker()) + return CFISections; + if (MAI->getExceptionHandlingType() == ExceptionHandling::DwarfCFI && - MF->getFunction().needsUnwindTableEntry()) - return CFI_M_EH; + F.needsUnwindTableEntry()) { + CFISections |= DwarfCFI::CFISection::EH; + } else if (MMI->hasDebugInfo()) { + CFISections |= DwarfCFI::CFISection::Debug; + } - if (MMI->hasDebugInfo() || MF->getTarget().Options.ForceDwarfFrameSection) - return CFI_M_Debug; + if (TM.Options.ForceDwarfFrameSection) + CFISections |= DwarfCFI::CFISection::Debug; - return CFI_M_None; + return CFISections; +} + +unsigned AsmPrinter::getCFISectionsToEmit(const MachineFunction &MF) const { + return getCFISectionsToEmit(MF.getFunction()); } bool AsmPrinter::needsSEHMoves() { return MAI->usesWindowsCFI() && MF->getFunction().needsUnwindTableEntry(); } +bool AsmPrinter::needsDwarfFrameSection() const { + return TM.Options.ForceDwarfFrameSection || + (MMI->hasDebugInfo() && MAI->doesSupportDebugOnlyCFI()); +} + void AsmPrinter::emitCFIInstruction(const MachineInstr &MI) { ExceptionHandling ExceptionHandlingType = MAI->getExceptionHandlingType(); - if (ExceptionHandlingType != ExceptionHandling::DwarfCFI && + if (!needsDwarfFrameSection() && + ExceptionHandlingType != ExceptionHandling::DwarfCFI && ExceptionHandlingType != ExceptionHandling::ARM) return; - if (needsCFIMoves() == CFI_M_None) + if (getCFISectionsToEmit(*MF) == DwarfCFI::CFISection::None) return; // If there is no "real" instruction following this CFI instruction, skip diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -53,8 +53,7 @@ DwarfCFIException::DwarfCFIException(AsmPrinter *A) : DwarfCFIExceptionBase(A), shouldEmitPersonality(false), - forceEmitPersonality(false), shouldEmitLSDA(false), - shouldEmitMoves(false) {} + forceEmitPersonality(false), shouldEmitLSDA(false) {} DwarfCFIException::~DwarfCFIException() {} @@ -87,17 +86,12 @@ } void DwarfCFIException::beginFunction(const MachineFunction *MF) { - shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false; + shouldEmitPersonality = shouldEmitLSDA = false; const Function &F = MF->getFunction(); // If any landing pads survive, we need an EH table. bool hasLandingPads = !MF->getLandingPads().empty(); - // See if we need frame move info. - AsmPrinter::CFIMoveType MoveType = Asm->needsCFIMoves(); - - shouldEmitMoves = MoveType != AsmPrinter::CFI_M_None; - const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); unsigned PerEncoding = TLOF.getPersonalityEncoding(); const Function *Per = nullptr; @@ -122,8 +116,16 @@ shouldEmitLSDA = shouldEmitPersonality && LSDAEncoding != dwarf::DW_EH_PE_omit; - shouldEmitCFI = MF->getMMI().getContext().getAsmInfo()->usesCFIForEH() && - (shouldEmitPersonality || shouldEmitMoves); + bool EmitCFISections = + Asm->getCFISectionsToEmit(*MF) != DwarfCFI::CFISection::None; + const MCAsmInfo &MAI = *MF->getMMI().getContext().getAsmInfo(); + ExceptionHandling EHType = MAI.getExceptionHandlingType(); + if (EHType != ExceptionHandling::None) { + shouldEmitCFI = + MAI.usesCFIForEH() && (shouldEmitPersonality || EmitCFISections); + } else { + shouldEmitCFI = Asm->needsDwarfFrameSection() && EmitCFISections; + } beginFragment(&*MF->begin(), getExceptionSym); } @@ -133,10 +135,13 @@ return; if (!hasEmittedCFISections) { - if (Asm->needsOnlyDebugCFIMoves()) - Asm->OutStreamer->emitCFISections(false, true); - else if (Asm->TM.Options.ForceDwarfFrameSection) - Asm->OutStreamer->emitCFISections(true, true); + unsigned CFISections = Asm->getCFISectionsToEmit(); + // If we don't say anything it implies `.cfi_sections .eh_frame`, so we + // chose not to be verbose in that case. + if (CFISections & DwarfCFI::CFISection::Debug) + Asm->OutStreamer->emitCFISections(CFISections & DwarfCFI::CFISection::EH, + CFISections & + DwarfCFI::CFISection::Debug); hasEmittedCFISections = true; } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfException.h b/llvm/lib/CodeGen/AsmPrinter/DwarfException.h --- a/llvm/lib/CodeGen/AsmPrinter/DwarfException.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfException.h @@ -27,6 +27,7 @@ /// Per-function flag to indicate if frame CFI info should be emitted. bool shouldEmitCFI; + /// Per-module flag to indicate if .cfi_section has beeen emitted. bool hasEmittedCFISections; @@ -44,9 +45,6 @@ /// Per-function flag to indicate if .cfi_lsda should be emitted. bool shouldEmitLSDA; - /// Per-function flag to indicate if frame moves info should be emitted. - bool shouldEmitMoves; - public: //===--------------------------------------------------------------------===// // Main entry points. diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -214,7 +214,10 @@ const RegisterLocations InitialLocs = Row.getRegisterLocations(); if (Error FdeError = UT.parseRows(Fde->cfis(), Row, &InitialLocs)) return std::move(FdeError); - UT.Rows.push_back(Row); + // Do not add empty row + if (Row.getRegisterLocations().hasLocations() || + Row.getCFAValue().getLocation() != UnwindLocation::Unspecified) + UT.Rows.push_back(Row); return UT; } @@ -223,7 +226,10 @@ UnwindRow Row; if (Error CieError = UT.parseRows(Cie->cfis(), Row, nullptr)) return std::move(CieError); - UT.Rows.push_back(Row); + // Do not add empty row + if (Row.getRegisterLocations().hasLocations() || + Row.getCFAValue().getLocation() != UnwindLocation::Unspecified) + UT.Rows.push_back(Row); return UT; } diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -1200,7 +1200,7 @@ ExceptionHandlingType != ExceptionHandling::ARM) return; - if (needsCFIMoves() == CFI_M_None) + if (getCFISectionsToEmit(*MF) == DwarfCFI::CFISection::None) return; OutStreamer->emitCFIBKeyFrame(); diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCAsmInfo.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCAsmInfo.cpp --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCAsmInfo.cpp +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCAsmInfo.cpp @@ -43,6 +43,7 @@ //===--- Dwarf Emission Directives -----------------------------------===// SupportsDebugInformation = true; DwarfRegNumForCFI = true; + SupportsDebugOnlyCFI = true; UseIntegratedAssembler = false; } diff --git a/llvm/test/CodeGen/AMDGPU/debug_frame.ll b/llvm/test/CodeGen/AMDGPU/debug_frame.ll --- a/llvm/test/CodeGen/AMDGPU/debug_frame.ll +++ b/llvm/test/CodeGen/AMDGPU/debug_frame.ll @@ -3,10 +3,8 @@ ; RUN: llc -mtriple=amdgcn-amd-amdhsa -filetype=obj --exception-model=dwarf -o - < %s | llvm-readelf -S - | FileCheck --check-prefixes=EXCEPTIONS_NOFORCE-DEBUG %s ; RUN: llc -mtriple=amdgcn-amd-amdhsa -filetype=obj --force-dwarf-frame-section --exception-model=dwarf -o - < %s | llvm-readelf -S - | FileCheck --check-prefixes=EXCEPTIONS_FORCE-DEBUG %s -; Test that demonstrates we produce a .debug_frame only when exceptions are enabled even if --force-dwarf-frame-section is enabled - -; NOEXCEPTIONS_NOFORCE-DEBUG-NOT: .debug_frame -; NOEXCEPTIONS_FORCE-DEBUG-NOT: .debug_frame +; NOEXCEPTIONS_NOFORCE-DEBUG: .debug_frame +; NOEXCEPTIONS_FORCE-DEBUG: .debug_frame ; EXCEPTIONS_NOFORCE-DEBUG: .debug_frame ; EXCEPTIONS_FORCE-DEBUG: .debug_frame diff --git a/llvm/test/CodeGen/AMDGPU/split-arg-dbg-value.ll b/llvm/test/CodeGen/AMDGPU/split-arg-dbg-value.ll --- a/llvm/test/CodeGen/AMDGPU/split-arg-dbg-value.ll +++ b/llvm/test/CodeGen/AMDGPU/split-arg-dbg-value.ll @@ -6,6 +6,8 @@ ; GCN: .Lfunc_begin0: ; GCN-NEXT: .file 0 ; GCN-NEXT: .loc 0 3 0 ; /tmp/dbg.cl:3:0 +; GCN-NEXT: .cfi_sections .debug_frame +; GCN-NEXT: .cfi_startproc ; GCN-NEXT: ; %bb.0: ; GCN-NEXT: ;DEBUG_VALUE: split_v4f32_arg:arg <- [DW_OP_constu 1, DW_OP_swap, DW_OP_xderef, DW_OP_LLVM_fragment 96 32] $vgpr3 ; GCN-NEXT: ;DEBUG_VALUE: split_v4f32_arg:arg <- [DW_OP_constu 1, DW_OP_swap, DW_OP_xderef, DW_OP_LLVM_fragment 64 32] $vgpr2 @@ -16,6 +18,7 @@ ; GCN-NEXT: .loc 0 4 5 prologue_end ; /tmp/dbg.cl:4:5 ; GCN-NEXT: s_setpc_b64 s[30:31] ; GCN-NEXT: .Ltmp1: +; GCN: .cfi_endproc call void @llvm.dbg.value(metadata <4 x float> %arg, metadata !18, metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !19 ret <4 x float> %arg, !dbg !20 } @@ -24,6 +27,7 @@ ; GCN-LABEL: split_v4f32_multi_arg: ; GCN: .Lfunc_begin1: ; GCN-NEXT: .loc 0 7 0 ; /tmp/dbg.cl:7:0 +; GCN-NEXT: .cfi_startproc ; GCN-NEXT: ; %bb.0: ; GCN-NEXT: ;DEBUG_VALUE: split_v4f32_multi_arg:arg1 <- [DW_OP_constu 1, DW_OP_swap, DW_OP_xderef, DW_OP_LLVM_fragment 32 32] $vgpr5 ; GCN-NEXT: ;DEBUG_VALUE: split_v4f32_multi_arg:arg1 <- [DW_OP_constu 1, DW_OP_swap, DW_OP_xderef, DW_OP_LLVM_fragment 0 32] $vgpr4 @@ -45,6 +49,7 @@ ; GCN-NEXT: .loc 0 8 5 is_stmt 0 ; /tmp/dbg.cl:8:5 ; GCN-NEXT: s_setpc_b64 s[30:31] ; GCN-NEXT: .Ltmp7: +; GCN: .cfi_endproc call void @llvm.dbg.value(metadata <4 x float> %arg0, metadata !29, metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !31 call void @llvm.dbg.value(metadata <2 x float> %arg1, metadata !30, metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !31 %tmp = shufflevector <2 x float> %arg1, <2 x float> undef, <4 x i32> , !dbg !32 @@ -56,6 +61,7 @@ ; GCN-LABEL: split_v4f16_arg: ; GCN: .Lfunc_begin2: ; GCN-NEXT: .loc 0 11 0 is_stmt 1 ; /tmp/dbg.cl:11:0 +; GCN-NEXT: .cfi_startproc ; GCN-NEXT: ; %bb.0: ; GCN-NEXT: ;DEBUG_VALUE: split_v4f16_arg:arg <- [DW_OP_constu 1, DW_OP_swap, DW_OP_xderef, DW_OP_LLVM_fragment 32 32] $vgpr1 ; GCN-NEXT: ;DEBUG_VALUE: split_v4f16_arg:arg <- [DW_OP_constu 1, DW_OP_swap, DW_OP_xderef, DW_OP_LLVM_fragment 0 32] $vgpr0 @@ -64,6 +70,7 @@ ; GCN-NEXT: .loc 0 12 5 prologue_end ; /tmp/dbg.cl:12:5 ; GCN-NEXT: s_setpc_b64 s[30:31] ; GCN-NEXT: .Ltmp9: +; GCN: .cfi_endproc call void @llvm.dbg.value(metadata <4 x half> %arg, metadata !42, metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !43 ret <4 x half> %arg, !dbg !44 } @@ -72,6 +79,7 @@ ; GCN-LABEL: split_f64_arg: ; GCN: .Lfunc_begin3: ; GCN-NEXT: .loc 0 15 0 ; /tmp/dbg.cl:15:0 +; GCN-NEXT: .cfi_startproc ; GCN-NEXT: ; %bb.0: ; GCN-NEXT: ;DEBUG_VALUE: split_f64_arg:arg <- [DW_OP_constu 1, DW_OP_swap, DW_OP_xderef, DW_OP_LLVM_fragment 32 32] $vgpr1 ; GCN-NEXT: ;DEBUG_VALUE: split_f64_arg:arg <- [DW_OP_constu 1, DW_OP_swap, DW_OP_xderef, DW_OP_LLVM_fragment 0 32] $vgpr0 @@ -80,6 +88,7 @@ ; GCN-NEXT: .loc 0 16 5 prologue_end ; /tmp/dbg.cl:16:5 ; GCN-NEXT: s_setpc_b64 s[30:31] ; GCN-NEXT: .Ltmp11: +; GCN: .cfi_endproc call void @llvm.dbg.value(metadata double %arg, metadata !50, metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !51 ret double %arg, !dbg !52 } @@ -88,6 +97,7 @@ ; GCN-LABEL: split_v2f64_arg: ; GCN: .Lfunc_begin4: ; GCN-NEXT: .loc 0 19 0 ; /tmp/dbg.cl:19:0 +; GCN-NEXT: .cfi_startproc ; GCN-NEXT: ; %bb.0: ; GCN-NEXT: ;DEBUG_VALUE: split_v2f64_arg:arg <- [DW_OP_constu 1, DW_OP_swap, DW_OP_xderef, DW_OP_LLVM_fragment 96 32] $vgpr3 ; GCN-NEXT: ;DEBUG_VALUE: split_v2f64_arg:arg <- [DW_OP_constu 1, DW_OP_swap, DW_OP_xderef, DW_OP_LLVM_fragment 64 32] $vgpr2 @@ -98,6 +108,7 @@ ; GCN-NEXT: .loc 0 20 5 prologue_end ; /tmp/dbg.cl:20:5 ; GCN-NEXT: s_setpc_b64 s[30:31] ; GCN-NEXT: .Ltmp13: +; GCN: .cfi_endproc call void @llvm.dbg.value(metadata <2 x double> %arg, metadata !59, metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !60 ret <2 x double> %arg, !dbg !61 } @@ -106,6 +117,7 @@ ; GCN-LABEL: split_i64_arg: ; GCN: .Lfunc_begin5: ; GCN-NEXT: .loc 0 23 0 ; /tmp/dbg.cl:23:0 +; GCN-NEXT: .cfi_startproc ; GCN-NEXT: ; %bb.0: ; GCN-NEXT: ;DEBUG_VALUE: split_i64_arg:arg <- [DW_OP_constu 1, DW_OP_swap, DW_OP_xderef, DW_OP_LLVM_fragment 32 32] $vgpr1 ; GCN-NEXT: ;DEBUG_VALUE: split_i64_arg:arg <- [DW_OP_constu 1, DW_OP_swap, DW_OP_xderef, DW_OP_LLVM_fragment 0 32] $vgpr0 @@ -114,6 +126,7 @@ ; GCN-NEXT: .loc 0 24 5 prologue_end ; /tmp/dbg.cl:24:5 ; GCN-NEXT: s_setpc_b64 s[30:31] ; GCN-NEXT: .Ltmp15: +; GCN: .cfi_endproc call void @llvm.dbg.value(metadata i64 %arg, metadata !67, metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !68 ret i64 %arg, !dbg !69 } @@ -122,6 +135,7 @@ ; GCN-LABEL: split_ptr_arg: ; GCN: .Lfunc_begin6: ; GCN-NEXT: .loc 0 27 0 ; /tmp/dbg.cl:27:0 +; GCN-NEXT: .cfi_startproc ; GCN-NEXT: ; %bb.0: ; GCN-NEXT: ;DEBUG_VALUE: split_ptr_arg:arg <- [DW_OP_constu 1, DW_OP_swap, DW_OP_xderef, DW_OP_LLVM_fragment 32 32] $vgpr1 ; GCN-NEXT: ;DEBUG_VALUE: split_ptr_arg:arg <- [DW_OP_constu 1, DW_OP_swap, DW_OP_xderef, DW_OP_LLVM_fragment 0 32] $vgpr0 @@ -130,6 +144,7 @@ ; GCN-NEXT: .loc 0 28 5 prologue_end ; /tmp/dbg.cl:28:5 ; GCN-NEXT: s_setpc_b64 s[30:31] ; GCN-NEXT: .Ltmp17: +; GCN: .cfi_endproc call void @llvm.dbg.value(metadata i8 addrspace(1)* %arg, metadata !76, metadata !DIExpression(DW_OP_constu, 1, DW_OP_swap, DW_OP_xderef)), !dbg !77 ret i8 addrspace(1)* %arg, !dbg !78 } diff --git a/llvm/test/DebugInfo/AMDGPU/cfi.ll b/llvm/test/DebugInfo/AMDGPU/cfi.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/AMDGPU/cfi.ll @@ -0,0 +1,36 @@ +; RUN: llc -mcpu=gfx900 -mtriple=amdgcn-amd-amdhsa -filetype=obj -o - %s | llvm-dwarfdump -debug-frame - | FileCheck %s + +; CHECK: .debug_frame contents: +; CHECK: 00000000 0000000c ffffffff CIE +; CHECK-NEXT: Format: DWARF32 +; CHECK-NEXT: Version: 4 +; CHECK-NEXT: Augmentation: "" +; CHECK-NEXT: Address size: 8 +; CHECK-NEXT: Segment desc size: 0 +; CHECK-NEXT: Code alignment factor: 4 +; CHECK-NEXT: Data alignment factor: 4 +; CHECK-NEXT: Return address column: 16 +; CHECK-EMPTY: +; CHECK: DW_CFA_nop: +; CHECK-EMPTY: +; CHECK-EMPTY: +; CHECK-NEXT: 00000010 {{[0-9]+}} 00000000 FDE cie=00000000 pc=00000000...{{[0-9]+}} +; CHECK-NEXT: Format: DWARF32 +; CHECK-EMPTY: +; CHECK-EMPTY: +; CHECK: .eh_frame contents: +; CHECK-NOT: CIE + +define void @func() #0 { + ret void +} + +attributes #0 = { nounwind } + +!llvm.module.flags = !{!0, !1} +!llvm.dbg.cu = !{!2} + +!0 = !{i32 7, !"Dwarf Version", i32 5} +!1 = !{i32 2, !"Debug Info Version", i32 3} +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, emissionKind: FullDebug) +!3 = !DIFile(filename: "file", directory: "dir") diff --git a/llvm/test/MC/ELF/AMDGPU/cfi.s b/llvm/test/MC/ELF/AMDGPU/cfi.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/ELF/AMDGPU/cfi.s @@ -0,0 +1,29 @@ +# RUN: llvm-mc -filetype=asm -mcpu=gfx900 -triple amdgcn-amd-amdhsa %s -o - | FileCheck --check-prefix=ASM %s +# RUN: llvm-mc -filetype=obj -mcpu=gfx900 -triple amdgcn-amd-amdhsa %s -o %t +# RUN: llvm-readelf -S -r -x .debug_frame %t | FileCheck --check-prefix=READELF %s + +f: + .cfi_sections .debug_frame + .cfi_startproc + s_nop 0 + .cfi_endproc + +# ASM: f: +# ASM-NEXT: .cfi_sections .debug_frame +# ASM-NEXT: .cfi_startproc +# ASM-NEXT: s_nop 0 +# ASM-NEXT: .cfi_endproc + +# READELF: Section Headers: +# READELF: Name Type Address Off Size ES Flg Lk Inf Al +# READELF: .debug_frame PROGBITS 0000000000000000 000048 000028 00 0 0 8 + +# READELF: Relocation section '.rela.debug_frame' at offset 0xd0 contains 2 entries: +# READELF-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend +# READELF-NEXT: 0000000000000014 0000000300000006 R_AMDGPU_ABS32 0000000000000000 .debug_frame + 0 +# READELF-NEXT: 0000000000000018 0000000100000003 R_AMDGPU_ABS64 0000000000000000 .text + 0 + +# READELF: Hex dump of section '.debug_frame': +# READELF-NEXT: 0x00000000 0c000000 ffffffff 04000800 04041000 ................ +# READELF-NEXT: 0x00000010 14000000 00000000 00000000 00000000 ................ +# READELF-NEXT: 0x00000020 04000000 00000000 ........ diff --git a/llvm/test/MC/ELF/AMDGPU/lit.local.cfg b/llvm/test/MC/ELF/AMDGPU/lit.local.cfg new file mode 100644 --- /dev/null +++ b/llvm/test/MC/ELF/AMDGPU/lit.local.cfg @@ -0,0 +1,3 @@ +# We have to reset config.unsupported here because the parent directory is +# predicated on 'X86'. +config.unsupported = 'AMDGPU' not in config.root.targets