diff --git a/llvm/docs/AMDGPUDwarfProposalForHeterogeneousDebugging.rst b/llvm/docs/AMDGPUDwarfProposalForHeterogeneousDebugging.rst --- a/llvm/docs/AMDGPUDwarfProposalForHeterogeneousDebugging.rst +++ b/llvm/docs/AMDGPUDwarfProposalForHeterogeneousDebugging.rst @@ -3541,15 +3541,15 @@ .. table:: Attribute encodings :name: amdgpu-dwarf-attribute-encodings-table - ================================== ===== ==================================== - Attribute Name Value Classes - ================================== ===== ==================================== - DW_AT_LLVM_active_lane *TBD* exprloc, loclist - DW_AT_LLVM_augmentation *TBD* string - DW_AT_LLVM_lanes *TBD* constant - DW_AT_LLVM_lane_pc *TBD* exprloc, loclist - DW_AT_LLVM_vector_size *TBD* constant - ================================== ===== ==================================== + ================================== ====== =================================== + Attribute Name Value Classes + ================================== ====== =================================== + DW_AT_LLVM_active_lane 0x3e08 exprloc, loclist + DW_AT_LLVM_augmentation 0x3e09 string + DW_AT_LLVM_lanes 0x3e0a constant + DW_AT_LLVM_lane_pc 0x3e0b exprloc, loclist + DW_AT_LLVM_vector_size 0x3e0c constant + ================================== ====== =================================== DWARF Expressions ~~~~~~~~~~~~~~~~~ @@ -3780,4 +3780,4 @@ .. _amdgpu-dwarf-SEMVER: -15. [SEMVER] `Semantic Versioning `__ \ No newline at end of file +15. [SEMVER] `Semantic Versioning `__ 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 @@ -418,6 +418,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. @@ -670,6 +677,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.0]". +HANDLE_DW_OP(0xe1, LLVM_form_aspace_address, 0, LLVM) +HANDLE_DW_OP(0xe2, LLVM_push_lane, 0, LLVM) +HANDLE_DW_OP(0xe3, LLVM_offset, 0, LLVM) +HANDLE_DW_OP(0xe4, LLVM_offset_uconst, 0, LLVM) +HANDLE_DW_OP(0xe5, LLVM_bit_offset, 0, LLVM) +HANDLE_DW_OP(0xe6, LLVM_call_frame_entry_reg, 0, LLVM) +HANDLE_DW_OP(0xe7, LLVM_undefined, 0, LLVM) +HANDLE_DW_OP(0xe8, LLVM_aspace_bregx, 0, LLVM) +HANDLE_DW_OP(0xe9, LLVM_aspace_implicit_pointer, 0, LLVM) +HANDLE_DW_OP(0xea, LLVM_piece_end, 0, LLVM) +HANDLE_DW_OP(0xeb, LLVM_extend, 0, LLVM) +HANDLE_DW_OP(0xec, 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 @@ -384,6 +384,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; @@ -652,6 +657,9 @@ bool supportsExtendedDwarfLocDirective() const { return SupportsExtendedDwarfLocDirective; } + bool supportsHeterogeneousDebuggingExtensions() const { + return SupportsHeterogeneousDebuggingExtensions; + } void addInitialFrameState(const MCCFIInstruction &Inst); 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 @@ -379,6 +379,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. @@ -702,6 +705,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(); @@ -972,6 +974,10 @@ dwarf::DW_FORM_data1, RVer); } + if (useHeterogeneousExtensionAttributes()) { + NewCU.addString(Die, dwarf::DW_AT_LLVM_augmentation, "[llvm:v0.0]"); + } + 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 @@ -100,6 +100,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); @@ -226,8 +241,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 @@ -236,7 +253,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; @@ -267,7 +284,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, 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 @@ -1603,6 +1603,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); @@ -1622,8 +1623,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"; @@ -1634,8 +1635,10 @@ Augmentation += "S"; if (Frame.IsBKeyFrame) Augmentation += "B"; - Streamer.emitBytes(Augmentation); } + if (MAI->supportsHeterogeneousDebuggingExtensions()) + Augmentation += "[llvm:v0.0]"; + Streamer.emitBytes(Augmentation); Streamer.emitInt8(0); if (CIEVersion >= 4) { @@ -1699,7 +1702,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 @@ -44,6 +44,7 @@ //===--- Dwarf Emission Directives -----------------------------------===// SupportsDebugInformation = true; DwarfRegNumForCFI = true; + SupportsHeterogeneousDebuggingExtensions = true; UseIntegratedAssembler = false; } diff --git a/llvm/test/tools/llvm-dwarfdump/X86/heterogeneous_proposal.s b/llvm/test/tools/llvm-dwarfdump/X86/heterogeneous_proposal.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/X86/heterogeneous_proposal.s @@ -0,0 +1,40 @@ +# RUN: llvm-mc %s -filetype=obj -triple=i686-pc-linux -o %t +# RUN: llvm-dwarfdump -v %t | FileCheck %s + +# Check that we can decode new ops described at +# llvm/docs/AMDGPUUsage.rst#expression-operation-encodings + +# FIXME: Is there a better approach than using `DW_CFA_expression reg0 `? + +# CHECK: .eh_frame contents: +# CHECK: FDE + +foo: + .cfi_startproc + # CHECK-NEXT: DW_CFA_expression: reg0 DW_OP_LLVM_form_aspace_address + .cfi_escape 0x10, 0x00, 0x01, 0xe1 + # CHECK-NEXT: DW_CFA_expression: reg0 DW_OP_LLVM_push_lane + .cfi_escape 0x10, 0x00, 0x01, 0xe2 + # CHECK-NEXT: DW_CFA_expression: reg0 DW_OP_LLVM_offset + .cfi_escape 0x10, 0x00, 0x01, 0xe3 + # CHECK-NEXT: DW_CFA_expression: reg0 DW_OP_LLVM_offset_uconst 0x0 + .cfi_escape 0x10, 0x00, 0x02, 0xe4, 0x00 + # CHECK-NEXT: DW_CFA_expression: reg0 DW_OP_LLVM_bit_offset + .cfi_escape 0x10, 0x00, 0x01, 0xe5 + # CHECK-NEXT: DW_CFA_expression: reg0 DW_OP_LLVM_call_frame_entry_reg EAX + .cfi_escape 0x10, 0x00, 0x02, 0xe6, 0x00 + # CHECK-NEXT: DW_CFA_expression: reg0 DW_OP_LLVM_undefined + .cfi_escape 0x10, 0x00, 0x01, 0xe7 + # CHECK-NEXT: DW_CFA_expression: reg0 DW_OP_LLVM_aspace_bregx EAX+2 + .cfi_escape 0x10, 0x00, 0x03, 0xe8, 0x0, 0x2 + # CHECK-NEXT: DW_CFA_expression: reg0 DW_OP_LLVM_aspace_implicit_pointer 0x1 +2 + .cfi_escape 0x10, 0x00, 0x06, 0xe9, 0x1, 0x0, 0x0, 0x0, 0x2 + # CHECK-NEXT: DW_CFA_expression: reg0 DW_OP_LLVM_piece_end + .cfi_escape 0x10, 0x00, 0x01, 0xea + # CHECK-NEXT: DW_CFA_expression: reg0 DW_OP_LLVM_extend 0x0 0x0 + .cfi_escape 0x10, 0x00, 0x03, 0xeb, 0x0, 0x0 + # CHECK-NEXT: DW_CFA_expression: reg0 DW_OP_LLVM_select_bit_piece 0x0 0x0 + .cfi_escape 0x10, 0x00, 0x03, 0xec, 0x0, 0x0 + .cfi_endproc + +# CHECK-NEXT: DW_CFA_nop: