[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