[LLVMdev] [PATCH] R600/SI: Embed disassembly in ELF object

Tom Stellard tom at stellard.net
Thu Oct 10 06:36:22 PDT 2013


On Wed, Oct 09, 2013 at 08:06:42PM -0500, Jay Cornwall wrote:
> Hi,
> 
> This patch adds R600/SI disassembly text to compiled object files, when 
> a code dump is requested, to assist debugging in Mesa clients.
>
> Here's an example of the output in a Mesa client with a corresponding 
> patch and RADEON_DUMP_SHADERS set:
> 
> Shader Disassembly:
> 
>    S_WQM_B64 EXEC, EXEC                           ; BEFE0A7E
>    S_MOV_B32 M0, SGPR6                            ; BEFC0306
>    V_INTERP_MOV_F32 VGPR0, P0, 3, 0, [M0]         ; C8020302
>    V_INTERP_MOV_F32 VGPR1, P0, 2, 0, [M0]         ; C8060202
>    V_INTERP_MOV_F32 VGPR2, P0, 1, 0, [M0]         ; C80A0102
>    V_INTERP_MOV_F32 VGPR3, P0, 0, 0, [M0]         ; C80E0002
>    EXP 15, 0, 0, 1, 1, VGPR3, VGPR2, VGPR1, VGPR0 ; F800180F 00010203
>    S_ENDPGM                                       ; BF810000
> 
> A less verbose disassembler is included in Mesa for pre-SI clients, so 
> the patch does not embed disassembly for NI or earlier targets.

Hi Jay,

Thanks for working on this.  This patch looks good, but I think we
should enable it for all targets.  Do you have commit access?

> 
> Disassembling during compilation is preferred, as it avoids the overhead 
> of a second LLVM invocation. Further, the SILowerControlFlow pass 
> modifies the input LLVM IR, which makes a second invocation for 
> disassembly fail.
> 
> An example patch to Mesa to test functionality is available here: 
> https://gist.github.com/anonymous/6911363

The Mesa patch looks good, have you sent it to mesa-dev?


-Tom
> 
> -- 
> Jay Cornwall

> Index: lib/Target/R600/AMDGPUAsmPrinter.cpp
> ===================================================================
> --- lib/Target/R600/AMDGPUAsmPrinter.cpp	(revision 192067)
> +++ lib/Target/R600/AMDGPUAsmPrinter.cpp	(working copy)
> @@ -45,32 +45,63 @@
>    TargetRegistry::RegisterAsmPrinter(TheAMDGPUTarget, createAMDGPUAsmPrinterPass);
>  }
>  
> +AMDGPUAsmPrinter::AMDGPUAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
> +    : AsmPrinter(TM, Streamer)
> +{
> +  const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
> +
> +  DisasmEnabled = STM.dumpCode() && 
> +                  STM.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS &&
> +                  ! Streamer.hasRawTextSupport();
> +}
> +
>  /// We need to override this function so we can avoid
>  /// the call to EmitFunctionHeader(), which the MCPureStreamer can't handle.
>  bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
> -  const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
> -  if (STM.dumpCode()) {
> -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
> -    MF.dump();
> -#endif
> -  }
>    SetupMachineFunction(MF);
>    if (OutStreamer.hasRawTextSupport()) {
>      OutStreamer.EmitRawText("@" + MF.getName() + ":");
>    }
>  
> -  const MCSectionELF *ConfigSection = getObjFileLowering().getContext()
> -                                              .getELFSection(".AMDGPU.config",
> +  MCContext &Context = getObjFileLowering().getContext();
> +  const MCSectionELF *ConfigSection = Context.getELFSection(".AMDGPU.config",
>                                                ELF::SHT_PROGBITS, 0,
>                                                SectionKind::getReadOnly());
>    OutStreamer.SwitchSection(ConfigSection);
> +  const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
>    if (STM.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) {
>      EmitProgramInfoSI(MF);
>    } else {
>      EmitProgramInfoR600(MF);
>    }
> +
> +  DisasmLines.clear();
> +  HexLines.clear();
> +  DisasmLineMaxLen = 0;
> +
>    OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
>    EmitFunctionBody();
> +
> +  if (STM.dumpCode()) {
> +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
> +    MF.dump();
> +#endif
> +
> +    if (DisasmEnabled) {
> +      OutStreamer.SwitchSection(Context.getELFSection(".AMDGPU.disasm",
> +                                                  ELF::SHT_NOTE, 0,
> +                                                  SectionKind::getReadOnly()));
> +
> +      for (size_t i = 0; i < DisasmLines.size(); ++i) {
> +        std::string Comment(DisasmLineMaxLen - DisasmLines[i].size(), ' ');
> +        Comment += " ; " + HexLines[i] + "\n";
> +
> +        OutStreamer.EmitBytes(StringRef(DisasmLines[i]));
> +        OutStreamer.EmitBytes(StringRef(Comment));
> +      }
> +    }
> +  }
> +
>    return false;
>  }
>  
> Index: lib/Target/R600/AMDGPUAsmPrinter.h
> ===================================================================
> --- lib/Target/R600/AMDGPUAsmPrinter.h	(revision 192067)
> +++ lib/Target/R600/AMDGPUAsmPrinter.h	(working copy)
> @@ -16,6 +16,8 @@
>  #define AMDGPU_ASMPRINTER_H
>  
>  #include "llvm/CodeGen/AsmPrinter.h"
> +#include <string>
> +#include <vector>
>  
>  namespace llvm {
>  
> @@ -22,8 +24,7 @@
>  class AMDGPUAsmPrinter : public AsmPrinter {
>  
>  public:
> -  explicit AMDGPUAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
> -    : AsmPrinter(TM, Streamer) { }
> +  explicit AMDGPUAsmPrinter(TargetMachine &TM, MCStreamer &Streamer);
>  
>    virtual bool runOnMachineFunction(MachineFunction &MF);
>  
> @@ -38,6 +39,11 @@
>  
>    /// Implemented in AMDGPUMCInstLower.cpp
>    virtual void EmitInstruction(const MachineInstr *MI);
> +
> +protected:
> +  bool DisasmEnabled;
> +  std::vector<std::string> DisasmLines, HexLines;
> +  size_t DisasmLineMaxLen;
>  };
>  
>  } // End anonymous llvm
> Index: lib/Target/R600/AMDGPUMCInstLower.cpp
> ===================================================================
> --- lib/Target/R600/AMDGPUMCInstLower.cpp	(revision 192067)
> +++ lib/Target/R600/AMDGPUMCInstLower.cpp	(working copy)
> @@ -15,14 +15,19 @@
>  
>  #include "AMDGPUMCInstLower.h"
>  #include "AMDGPUAsmPrinter.h"
> +#include "InstPrinter/AMDGPUInstPrinter.h"
>  #include "R600InstrInfo.h"
>  #include "llvm/CodeGen/MachineBasicBlock.h"
>  #include "llvm/CodeGen/MachineInstr.h"
>  #include "llvm/IR/Constants.h"
> +#include "llvm/MC/MCCodeEmitter.h"
>  #include "llvm/MC/MCExpr.h"
>  #include "llvm/MC/MCInst.h"
> +#include "llvm/MC/MCObjectStreamer.h"
>  #include "llvm/MC/MCStreamer.h"
>  #include "llvm/Support/ErrorHandling.h"
> +#include "llvm/Support/Format.h"
> +#include <algorithm>
>  
>  using namespace llvm;
>  
> @@ -69,10 +74,7 @@
>      MachineBasicBlock::const_instr_iterator I = MI;
>      ++I;
>      while (I != MBB->end() && I->isInsideBundle()) {
> -      MCInst MCBundleInst;
> -      const MachineInstr *BundledInst = I;
> -      MCInstLowering.lower(BundledInst, MCBundleInst);
> -      OutStreamer.EmitInstruction(MCBundleInst);
> +      EmitInstruction(I);
>        ++I;
>      }
>    } else {
> @@ -79,5 +81,38 @@
>      MCInst TmpInst;
>      MCInstLowering.lower(MI, TmpInst);
>      OutStreamer.EmitInstruction(TmpInst);
> +
> +    if (DisasmEnabled) {
> +      // Disassemble instruction/operands to text.
> +      DisasmLines.resize(DisasmLines.size() + 1);
> +      std::string &DisasmLine = DisasmLines.back();
> +      raw_string_ostream DisasmStream(DisasmLine);
> +
> +      AMDGPUInstPrinter InstPrinter(*TM.getMCAsmInfo(), *TM.getInstrInfo(),
> +                                    *TM.getRegisterInfo());
> +      InstPrinter.printInst(&TmpInst, DisasmStream, StringRef());
> +
> +      // Disassemble instruction/operands to hex representation.
> +      SmallVector<MCFixup, 4> Fixups;
> +      SmallVector<char, 16> CodeBytes;
> +      raw_svector_ostream CodeStream(CodeBytes);
> +
> +      MCObjectStreamer &ObjStreamer = (MCObjectStreamer &)OutStreamer;
> +      MCCodeEmitter &InstEmitter = ObjStreamer.getAssembler().getEmitter();
> +      InstEmitter.EncodeInstruction(TmpInst, CodeStream, Fixups);
> +      CodeStream.flush();
> +
> +      HexLines.resize(HexLines.size() + 1);
> +      std::string &HexLine = HexLines.back();
> +      raw_string_ostream HexStream(HexLine);
> +
> +      for (size_t i = 0; i < CodeBytes.size(); i += 4) {
> +        unsigned int CodeDWord = *(unsigned int *)&CodeBytes[i];
> +        HexStream << format("%s%08X", (i > 0 ? " " : ""), CodeDWord);
> +      }
> +
> +      DisasmStream.flush();
> +      DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLine.size());
> +    }
>    }
>  }

> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev




More information about the llvm-dev mailing list