diff --git a/llvm/docs/AMDGPUDwarfExtensionsForHeterogeneousDebugging.rst b/llvm/docs/AMDGPUDwarfExtensionsForHeterogeneousDebugging.rst --- a/llvm/docs/AMDGPUDwarfExtensionsForHeterogeneousDebugging.rst +++ b/llvm/docs/AMDGPUDwarfExtensionsForHeterogeneousDebugging.rst @@ -4577,21 +4577,21 @@ of Operands ================================== ===== ======== =============================== - DW_OP_LLVM_form_aspace_address 0xe1 0 - DW_OP_LLVM_push_lane 0xe2 0 - DW_OP_LLVM_offset 0xe3 0 - DW_OP_LLVM_offset_uconst 0xe4 1 ULEB128 byte displacement - DW_OP_LLVM_bit_offset 0xe5 0 - DW_OP_LLVM_call_frame_entry_reg 0xe6 1 ULEB128 register number - DW_OP_LLVM_undefined 0xe7 0 - DW_OP_LLVM_aspace_bregx 0xe8 2 ULEB128 register number, + DW_OP_LLVM_form_aspace_address 0xe9 0 + DW_OP_LLVM_push_lane 0xea 0 + DW_OP_LLVM_offset 0xeb 0 + DW_OP_LLVM_offset_uconst 0xec 1 ULEB128 byte displacement + DW_OP_LLVM_bit_offset 0xf4 0 + DW_OP_LLVM_call_frame_entry_reg 0xf5 1 ULEB128 register number + DW_OP_LLVM_undefined 0xf6 0 + DW_OP_LLVM_aspace_bregx 0xf7 2 ULEB128 register number, ULEB128 byte displacement - DW_OP_LLVM_aspace_implicit_pointer 0xe9 2 4-byte or 8-byte offset of DIE, + DW_OP_LLVM_aspace_implicit_pointer 0xf9 2 4-byte or 8-byte offset of DIE, SLEB128 byte displacement - DW_OP_LLVM_piece_end 0xea 0 - DW_OP_LLVM_extend 0xeb 2 ULEB128 bit size, + DW_OP_LLVM_piece_end 0xfa 0 + DW_OP_LLVM_extend 0xfd 2 ULEB128 bit size, ULEB128 count - DW_OP_LLVM_select_bit_piece 0xec 2 ULEB128 bit size, + DW_OP_LLVM_select_bit_piece 0xfe 2 ULEB128 bit size, ULEB128 count DW_OP_LLVM_push_iteration TBA 0 DW_OP_LLVM_overlay TBA 0 diff --git a/llvm/docs/AMDGPUUsage.rst b/llvm/docs/AMDGPUUsage.rst --- a/llvm/docs/AMDGPUUsage.rst +++ b/llvm/docs/AMDGPUUsage.rst @@ -2338,7 +2338,7 @@ :: - [amdgpu:v0.0] + [amdgpu:v0.1] The "vX.Y" specifies the major X and minor Y version number of the AMDGPU extensions used in the DWARF of the compilation unit. The version number @@ -2357,7 +2357,7 @@ :: - [amd:v0.0] + [amd:v0.1] The ``vX.Y`` specifies the major X and minor Y version number of the AMDGPU extensions used in this CIE or to the FDEs that use it. The version number @@ -2418,7 +2418,7 @@ :: - [amdgpu:v0.0] + [amdgpu:v0.1] The "vX.Y" specifies the major X and minor Y version number of the AMDGPU extensions used in the DWARF of this index. The version number conforms to diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def --- a/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -599,6 +599,13 @@ HANDLE_DW_AT(0x3e03, LLVM_tag_offset, 0, LLVM) // The missing numbers here are reserved for ptrauth support. HANDLE_DW_AT(0x3e07, LLVM_apinotes, 0, APPLE) +// Heterogeneous Debugging Extension defined at +// https://llvm.org/docs/AMDGPUDwarfProposalForHeterogeneousDebugging.html. +HANDLE_DW_AT(0x3e08, LLVM_active_lane, 0, LLVM) +HANDLE_DW_AT(0x3e09, LLVM_augmentation, 0, LLVM) +HANDLE_DW_AT(0x3e0a, LLVM_lanes, 0, LLVM) +HANDLE_DW_AT(0x3e0b, LLVM_lane_pc, 0, LLVM) +HANDLE_DW_AT(0x3e0c, LLVM_vector_size, 0, LLVM) // Apple extensions. @@ -866,6 +873,23 @@ // Extensions for Fission proposal. HANDLE_DW_OP(0xfb, GNU_addr_index, 0, GNU) HANDLE_DW_OP(0xfc, GNU_const_index, 0, GNU) +// Heterogeneous Debugging Extension defined at +// https://llvm.org/docs/AMDGPUDwarfProposalForHeterogeneousDebugging.html. +// These collide with some HP and PGI vendor extensions, but this ambiguity is +// resolved by ensuring CIE augmentation strings and compilation unit +// DW_AT_LLVM_augmentation strings include "[llvm:v0.1]". +HANDLE_DW_OP(0xe9, LLVM_form_aspace_address, 0, LLVM) +HANDLE_DW_OP(0xea, LLVM_push_lane, 0, LLVM) +HANDLE_DW_OP(0xeb, LLVM_offset, 0, LLVM) +HANDLE_DW_OP(0xec, LLVM_offset_uconst, 0, LLVM) +HANDLE_DW_OP(0xf4, LLVM_bit_offset, 0, LLVM) +HANDLE_DW_OP(0xf5, LLVM_call_frame_entry_reg, 0, LLVM) +HANDLE_DW_OP(0xf6, LLVM_undefined, 0, LLVM) +HANDLE_DW_OP(0xf7, LLVM_aspace_bregx, 0, LLVM) +HANDLE_DW_OP(0xf9, LLVM_aspace_implicit_pointer, 0, LLVM) +HANDLE_DW_OP(0xfa, LLVM_piece_end, 0, LLVM) +HANDLE_DW_OP(0xfd, LLVM_extend, 0, LLVM) +HANDLE_DW_OP(0xfe, LLVM_select_bit_piece, 0, LLVM) // DWARF languages. HANDLE_DW_LANG(0x0001, C89, 0, 2, DWARF) 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 @@ -482,6 +482,11 @@ /// location is allowed. bool SupportsExtendedDwarfLocDirective = true; + /// True if the target supports the extensions defined at + /// https://llvm.org/docs/AMDGPUDwarfProposalForHeterogeneousDebugging.html. + /// Defaults to false. + bool SupportsHeterogeneousDebuggingExtensions = false; + //===--- Prologue State ----------------------------------------------===// std::vector InitialFrameState; @@ -791,6 +796,9 @@ bool supportsExtendedDwarfLocDirective() const { return SupportsExtendedDwarfLocDirective; } + bool supportsHeterogeneousDebuggingExtensions() const { + return SupportsHeterogeneousDebuggingExtensions; + } bool usesDwarfFileAndLocDirectives() const { return UsesDwarfFileAndLocDirectives; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -397,6 +397,9 @@ AccelTableKind TheAccelTableKind; bool HasAppleExtensionAttributes; bool HasSplitDwarf; + // Enables extensions defined at + // https://llvm.org/docs/AMDGPUDwarfProposalForHeterogeneousDebugging.html + bool HasHeterogeneousExtensionAttributes; /// Whether to generate the DWARF v5 string offsets table. /// It consists of a series of contributions, each preceded by a header. @@ -745,6 +748,13 @@ return HasAppleExtensionAttributes; } + /// Returns whether extensions defined at + /// https://llvm.org/docs/AMDGPUDwarfProposalForHeterogeneousDebugging.html + /// are enabled. + bool useHeterogeneousExtensionAttributes() const { + return HasHeterogeneousExtensionAttributes; + } + /// Returns whether or not to change the current debug info for the /// split dwarf proposal support. bool useSplitDwarf() const { return HasSplitDwarf; } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -375,6 +375,8 @@ UseLocSection = !TT.isNVPTX(); HasAppleExtensionAttributes = tuneForLLDB(); + HasHeterogeneousExtensionAttributes = + Asm->MAI->supportsHeterogeneousDebuggingExtensions(); // Handle split DWARF. HasSplitDwarf = !Asm->TM.Options.MCOptions.SplitDwarfFile.empty(); @@ -1054,6 +1056,10 @@ dwarf::DW_FORM_data1, RVer); } + if (useHeterogeneousExtensionAttributes()) { + NewCU.addString(Die, dwarf::DW_AT_LLVM_augmentation, "[amdgpu:v0.1]"); + } + if (DIUnit->getDWOId()) { // This CU is either a clang module DWO or a skeleton CU. NewCU.addUInt(Die, dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8, diff --git a/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp b/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp @@ -99,6 +99,21 @@ Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB); Descriptions[DW_OP_GNU_const_index] = Desc(Op::Dwarf4, Op::SizeLEB); Descriptions[DW_OP_GNU_entry_value] = Desc(Op::Dwarf4, Op::SizeLEB); + Descriptions[DW_OP_LLVM_form_aspace_address] = Desc(Op::Dwarf4); + Descriptions[DW_OP_LLVM_push_lane] = Desc(Op::Dwarf4); + Descriptions[DW_OP_LLVM_offset] = Desc(Op::Dwarf4); + Descriptions[DW_OP_LLVM_offset_uconst] = Desc(Op::Dwarf4, Op::SizeLEB); + Descriptions[DW_OP_LLVM_bit_offset] = Desc(Op::Dwarf4); + Descriptions[DW_OP_LLVM_call_frame_entry_reg] = Desc(Op::Dwarf4, Op::SizeLEB); + Descriptions[DW_OP_LLVM_undefined] = Desc(Op::Dwarf4); + Descriptions[DW_OP_LLVM_aspace_bregx] = + Desc(Op::Dwarf4, Op::SizeLEB, Op::SizeLEB); + Descriptions[DW_OP_LLVM_aspace_implicit_pointer] = + Desc(Op::Dwarf4, Op::SizeRefAddr, Op::SignedSizeLEB); + Descriptions[DW_OP_LLVM_piece_end] = Desc(Op::Dwarf4); + Descriptions[DW_OP_LLVM_extend] = Desc(Op::Dwarf4, Op::SizeLEB, Op::SizeLEB); + Descriptions[DW_OP_LLVM_select_bit_piece] = + Desc(Op::Dwarf4, Op::SizeLEB, Op::SizeLEB); Descriptions[DW_OP_convert] = Desc(Op::Dwarf5, Op::BaseTypeRef); Descriptions[DW_OP_entry_value] = Desc(Op::Dwarf5, Op::SizeLEB); @@ -236,8 +251,10 @@ unsigned OpNum = 0; if (Opcode == DW_OP_bregx || Opcode == DW_OP_regx || - Opcode == DW_OP_regval_type) + Opcode == DW_OP_regval_type || Opcode == DW_OP_LLVM_aspace_bregx) DwarfRegNum = Operands[OpNum++]; + else if (Opcode == DW_OP_LLVM_call_frame_entry_reg) + DwarfRegNum = Operands[OpNum]; else if (Opcode >= DW_OP_breg0 && Opcode < DW_OP_bregx) DwarfRegNum = Opcode - DW_OP_breg0; else @@ -246,7 +263,7 @@ if (Optional LLVMRegNum = MRI->getLLVMRegNum(DwarfRegNum, isEH)) { if (const char *RegName = MRI->getName(*LLVMRegNum)) { if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) || - Opcode == DW_OP_bregx) + Opcode == DW_OP_bregx || Opcode == DW_OP_LLVM_aspace_bregx) OS << format(" %s%+" PRId64, RegName, Operands[OpNum]); else OS << ' ' << RegName; @@ -276,7 +293,9 @@ if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) || (Opcode >= DW_OP_reg0 && Opcode <= DW_OP_reg31) || Opcode == DW_OP_bregx || Opcode == DW_OP_regx || - Opcode == DW_OP_regval_type) + Opcode == DW_OP_regval_type || + Opcode == DW_OP_LLVM_call_frame_entry_reg || + Opcode == DW_OP_LLVM_aspace_bregx) if (prettyPrintRegisterOp(U, OS, DumpOpts, Opcode, Operands, RegInfo, isEH)) return true; diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp --- a/llvm/lib/MC/MCDwarf.cpp +++ b/llvm/lib/MC/MCDwarf.cpp @@ -1558,6 +1558,7 @@ MCContext &context = Streamer.getContext(); const MCRegisterInfo *MRI = context.getRegisterInfo(); const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); + const MCAsmInfo *MAI = context.getAsmInfo(); MCSymbol *sectionStart = context.createTempSymbol(); Streamer.emitLabel(sectionStart); @@ -1587,8 +1588,8 @@ uint8_t CIEVersion = getCIEVersion(IsEH, context.getDwarfVersion()); Streamer.emitInt8(CIEVersion); + SmallString<8> Augmentation; if (IsEH) { - SmallString<8> Augmentation; Augmentation += "z"; if (Frame.Personality) Augmentation += "P"; @@ -1599,8 +1600,10 @@ Augmentation += "S"; if (Frame.IsBKeyFrame) Augmentation += "B"; - Streamer.emitBytes(Augmentation); } + if (MAI->supportsHeterogeneousDebuggingExtensions()) + Augmentation += "[amd:v0.1]"; + Streamer.emitBytes(Augmentation); Streamer.emitInt8(0); if (CIEVersion >= 4) { @@ -1664,7 +1667,6 @@ // Initial Instructions - const MCAsmInfo *MAI = context.getAsmInfo(); if (!Frame.IsSimple) { const std::vector &Instructions = MAI->getInitialFrameState(); 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,8 @@ UsesCFIForDebug = true; DwarfRegNumForCFI = true; + SupportsHeterogeneousDebuggingExtensions = true; + UseIntegratedAssembler = false; } diff --git a/llvm/test/DebugInfo/AMDGPU/cfi.ll b/llvm/test/DebugInfo/AMDGPU/cfi.ll --- a/llvm/test/DebugInfo/AMDGPU/cfi.ll +++ b/llvm/test/DebugInfo/AMDGPU/cfi.ll @@ -1,10 +1,10 @@ ; 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: 00000000 0000001c ffffffff CIE ; CHECK-NEXT: Format: DWARF32 ; CHECK-NEXT: Version: 4 -; CHECK-NEXT: Augmentation: "" +; CHECK-NEXT: Augmentation: "[amd:v0.1]" ; CHECK-NEXT: Address size: 8 ; CHECK-NEXT: Segment desc size: 0 ; CHECK-NEXT: Code alignment factor: 4 @@ -12,8 +12,15 @@ ; CHECK-NEXT: Return address column: 16 ; CHECK-EMPTY: ; CHECK: DW_CFA_nop: +; CHECK: DW_CFA_nop: +; CHECK: DW_CFA_nop: +; CHECK: DW_CFA_nop: +; CHECK: DW_CFA_nop: +; CHECK: DW_CFA_nop: +; CHECK: DW_CFA_nop: +; CHECK-EMPTY: ; CHECK-EMPTY: -; CHECK: 00000010 {{[0-9]+}} 00000000 FDE cie=00000000 pc=00000000...{{[0-9]+}} +; CHECK-NEXT: 00000020 {{[0-9]+}} 00000000 FDE cie=00000000 pc=00000000...{{[0-9]+}} ; CHECK-NEXT: Format: DWARF32 ; CHECK-EMPTY: ; CHECK: .eh_frame contents: diff --git a/llvm/test/DebugInfo/X86/heterogeneous_proposal.s b/llvm/test/DebugInfo/X86/heterogeneous_proposal.s new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/X86/heterogeneous_proposal.s @@ -0,0 +1,65 @@ +# RUN: llvm-mc -triple i686 %s -filetype=obj -o %t.o +# RUN: llvm-dwarfdump -debug-info %t.o | FileCheck %s +# RUN: llvm-dwarfdump -verify %t.o | FileCheck %s --check-prefix=VERIFY + +# Check that we can decode new ops described at +# llvm/docs/AMDGPUUsage.rst#expression-operation-encodings + +# VERIFY-NOT: error: DIE contains invalid DWARF expression: +# VERIFY: No errors. + + .section .debug_abbrev,"",@progbits + .uleb128 1 # Abbreviation Code + .uleb128 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .uleb128 5 # Abbreviation Code + .uleb128 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .uleb128 2 # DW_AT_location + .uleb128 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + + .section .debug_info,"",@progbits + .long .Lcu_end-.Lcu_start # Length of Unit +.Lcu_start: + .short 5 # DWARF version number + .byte 1 # DW_UT_compile + .byte 8 # Address Size + .long .debug_abbrev # Offset Into Abbrev. Section + .uleb128 1 # Abbrev [1] DW_TAG_compile_unit +# CHECK: DW_TAG_variable + .uleb128 5 # Abbrev [5] DW_TAG_variable + .byte .Lloc_end-.Lloc_begin # DW_AT_location +.Lloc_begin: +# CHECK-NEXT: DW_AT_location ( + # CHECK-SAME: DW_OP_LLVM_form_aspace_address, + .byte 0xe9 + # CHECK-SAME: DW_OP_LLVM_push_lane, + .byte 0xea + # CHECK-SAME: DW_OP_LLVM_offset, + .byte 0xeb + # CHECK-SAME: DW_OP_LLVM_offset_uconst 0x0, + .byte 0xec, 0x00 + # CHECK-SAME: DW_OP_LLVM_bit_offset, + .byte 0xf4 + # CHECK-SAME: DW_OP_LLVM_call_frame_entry_reg EAX, + .byte 0xf5, 0x00 + # CHECK-SAME: DW_OP_LLVM_undefined, + .byte 0xf6 + # CHECK-SAME: DW_OP_LLVM_aspace_bregx EAX+2, + .byte 0xf7, 0x0, 0x2 + # CHECK-SAME: DW_OP_LLVM_aspace_implicit_pointer 0x1 +2, + .byte 0xf9, 0x1, 0x0, 0x0, 0x0, 0x2 + # CHECK-SAME: DW_OP_LLVM_piece_end, + .byte 0xfa + # CHECK-SAME: DW_OP_LLVM_extend 0x0 0x0 + .byte 0xfd, 0x0, 0x0 + # CHECK-SAME: DW_OP_LLVM_select_bit_piece 0x0 0x0) + .byte 0xfe, 0x0, 0x0 +.Lloc_end: + .byte 0 # End Of Children Mark +.Lcu_end: diff --git a/llvm/test/MC/ELF/AMDGPU/cfi.s b/llvm/test/MC/ELF/AMDGPU/cfi.s --- a/llvm/test/MC/ELF/AMDGPU/cfi.s +++ b/llvm/test/MC/ELF/AMDGPU/cfi.s @@ -16,14 +16,15 @@ # 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: .debug_frame PROGBITS 0000000000000000 000048 000038 00 0 0 8 -# READELF: Relocation section '.rela.debug_frame' at offset 0xd0 contains 2 entries: +# READELF: Relocation section '.rela.debug_frame' at offset 0xe0 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-NEXT: 0000000000000024 0000000300000006 R_AMDGPU_ABS32 0000000000000000 .debug_frame + 0 +# READELF-NEXT: 0000000000000028 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 ........ +# READELF-NEXT: 0x00000000 1c000000 ffffffff 045b616d 643a7630 .........[amd:v0 +# READELF-NEXT: 0x00000010 2e315d00 08000404 10000000 00000000 .1]............. +# READELF-NEXT: 0x00000020 14000000 00000000 00000000 00000000 ................ +# READELF-NEXT: 0x00000030 04000000 00000000