[Mesa-dev] [PATCH 1/2] gallivm: use sstream for dissasembling
Jose Fonseca
jfonseca at vmware.com
Thu Feb 18 21:01:53 UTC 2016
On 18/02/16 16:23, Oded Gabbay wrote:
> Currently, disassemble() directly prints to stdout. This has broke the
> profiling support for llvmpipe JIT code.
>
> This patch redirects the output to an sstream object, which is then
> either gets printed to stdout (for assembly debugging) or gets written
> to a file in /tmp/ (for profiling support).
>
> Signed-off-by: Oded Gabbay <oded.gabbay at gmail.com>
> ---
> src/gallium/auxiliary/gallivm/lp_bld_debug.cpp | 51 +++++++++++++++-----------
> 1 file changed, 30 insertions(+), 21 deletions(-)
>
> diff --git a/src/gallium/auxiliary/gallivm/lp_bld_debug.cpp b/src/gallium/auxiliary/gallivm/lp_bld_debug.cpp
> index 7283e2f..7e98f1a 100644
> --- a/src/gallium/auxiliary/gallivm/lp_bld_debug.cpp
> +++ b/src/gallium/auxiliary/gallivm/lp_bld_debug.cpp
> @@ -26,6 +26,9 @@
> **************************************************************************/
>
> #include <stddef.h>
> +#include <fstream>
> +#include <sstream>
> +#include <iomanip>
>
> #include <llvm-c/Core.h>
> #include <llvm-c/Disassembler.h>
> @@ -125,7 +128,7 @@ lp_debug_dump_value(LLVMValueRef value)
> * - http://blog.llvm.org/2010/04/intro-to-llvm-mc-project.html
> */
> static size_t
> -disassemble(const void* func)
> +disassemble(const void* func, std::stringstream &buffer)
> {
> const uint8_t *bytes = (const uint8_t *)func;
>
> @@ -143,8 +146,8 @@ disassemble(const void* func)
> char outline[1024];
>
> if (!D) {
> - _debug_printf("error: couldn't create disassembler for triple %s\n",
> - Triple.c_str());
> + buffer << "error: could not create disassembler for triple "
> + << Triple.c_str() << '\n';
> return 0;
> }
>
> @@ -158,13 +161,13 @@ disassemble(const void* func)
> * so that between runs.
> */
>
> - _debug_printf("%6lu:\t", (unsigned long)pc);
> + buffer << std::setw(6) << (unsigned long)pc << ":\t";
>
> Size = LLVMDisasmInstruction(D, (uint8_t *)bytes + pc, extent - pc, 0, outline,
> sizeof outline);
>
> if (!Size) {
> - _debug_printf("invalid\n");
> + buffer << "invalid\n";
> pc += 1;
> break;
> }
> @@ -176,10 +179,11 @@ disassemble(const void* func)
> if (0) {
> unsigned i;
> for (i = 0; i < Size; ++i) {
> - _debug_printf("%02x ", bytes[pc + i]);
> + buffer << std::hex << std::setfill('0') << std::setw(2)
> + << static_cast<int> (bytes[pc + i]);
> }
> for (; i < 16; ++i) {
> - _debug_printf(" ");
> + buffer << std::dec << " ";
> }
> }
>
> @@ -187,9 +191,7 @@ disassemble(const void* func)
> * Print the instruction.
> */
>
> - _debug_printf("%*s", Size, outline);
> -
> - _debug_printf("\n");
> + buffer << std::setw(Size) << outline << '\n';
>
> /*
> * Stop disassembling on return statements, if there is no record of a
> @@ -209,12 +211,12 @@ disassemble(const void* func)
> pc += Size;
>
> if (pc >= extent) {
> - _debug_printf("disassembly larger than %ull bytes, aborting\n", extent);
> + buffer << "disassembly larger than " << extent << " bytes, aborting\n";
> break;
> }
> }
>
> - _debug_printf("\n");
> + buffer << '\n';
>
> LLVMDisasmDispose(D);
>
> @@ -222,7 +224,8 @@ disassemble(const void* func)
> * Print GDB command, useful to verify output.
> */
> if (0) {
> - _debug_printf("disassemble %p %p\n", bytes, bytes + pc);
> + buffer << "disassemble " << static_cast<const void*>(bytes) << ' '
> + << static_cast<const void*>(bytes + pc) << '\n';
> }
>
> return pc;
> @@ -231,8 +234,14 @@ disassemble(const void* func)
>
> extern "C" void
> lp_disassemble(LLVMValueRef func, const void *code) {
> - _debug_printf("%s:\n", LLVMGetValueName(func));
> - disassemble(code);
> + std::stringstream buffer;
> + std::string s;
> +
> + buffer << LLVMGetValueName(func) << ":\n";
> + disassemble(code, buffer);
> + s = buffer.str();
> + _debug_printf("%s", s.c_str());
> + _debug_printf("\n");
> }
>
>
> @@ -248,9 +257,10 @@ extern "C" void
> lp_profile(LLVMValueRef func, const void *code)
> {
> #if defined(__linux__) && defined(PROFILE)
> + std::stringstream buffer;
> + static std::ofstream perf_asm_file;
> static boolean first_time = TRUE;
> static FILE *perf_map_file = NULL;
> - static int perf_asm_fd = -1;
> if (first_time) {
> /*
> * We rely on the disassembler for determining a function's size, but
> @@ -264,17 +274,16 @@ lp_profile(LLVMValueRef func, const void *code)
> util_snprintf(filename, sizeof filename, "/tmp/perf-%llu.map", (unsigned long long)pid);
> perf_map_file = fopen(filename, "wt");
> util_snprintf(filename, sizeof filename, "/tmp/perf-%llu.map.asm", (unsigned long long)pid);
> - mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
> - perf_asm_fd = open(filename, O_WRONLY | O_CREAT, mode);
> + perf_asm_file.open(filename);
> }
> first_time = FALSE;
> }
> if (perf_map_file) {
> const char *symbol = LLVMGetValueName(func);
> unsigned long addr = (uintptr_t)code;
> - llvm::raw_fd_ostream Out(perf_asm_fd, false);
> - Out << symbol << ":\n";
> - unsigned long size = disassemble(code);
> + buffer << symbol << ":\n";
> + unsigned long size = disassemble(code, buffer);
> + perf_asm_file << buffer.rdbuf() << std::flush;
> fprintf(perf_map_file, "%lx %lx %s\n", addr, size, symbol);
> fflush(perf_map_file);
> }
>
Series looks good AFAICT. Thanks for doing this!
Reviewed-by: Jose Fonseca <jfonseca at vmware.com>
More information about the mesa-dev
mailing list