From e1d363b3ffbfb85133a6871c63068a4ba841b2cd Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Tue, 30 Sep 2014 10:32:33 -0400 Subject: [PATCH] clover: Add environment variables for dumping kernel code v2 There are two debug variables: CLOVER_DEBUG which you can set to any combination of llvm,clc,asm (separated by commas) to dump llvm IR, OpenCL C, and native assembly. CLOVER_DEBUG_FILE which you can set to a file name for dumping output instead of stderr. If you set this variable, the output will be split into three separate files with different suffixes: .cl for OpenCL C, .ll for LLVM IR, and .asm for native assembly. Note that when data is written, it is always appended to the files. v2: - Code cleanups - Add CLOVER_DEBUG_FILE environment variable for dumping to a file. Reviewed-by: Francisco Jerez --- .../state_trackers/clover/llvm/invocation.cpp | 86 ++++++++++++++++--- 1 file changed, 75 insertions(+), 11 deletions(-) diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp b/src/gallium/state_trackers/clover/llvm/invocation.cpp index 56607615343..3cdf883e403 100644 --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp @@ -61,6 +61,8 @@ #include #include #include +#include + #if HAVE_LLVM < 0x0302 #include @@ -132,6 +134,15 @@ namespace { return module::deserialize(cs); } #endif + void debug_log(const std::string &msg, const std::string &suffix) { + const char *dbg_file = debug_get_option("CLOVER_DEBUG_FILE", "stderr"); + if (!strcmp("stderr", dbg_file)) { + std::cerr << msg; + } else { + std::ofstream file(dbg_file + suffix, std::ios::app); + file << msg; + } + } llvm::Module * compile_llvm(llvm::LLVMContext &llvm_ctx, const std::string &source, @@ -456,9 +467,32 @@ namespace { return m; } + void + emit_code(LLVMTargetMachineRef tm, LLVMModuleRef mod, + LLVMCodeGenFileType file_type, + LLVMMemoryBufferRef *out_buffer, + compat::string &r_log) { + LLVMBool err; + char *err_message = NULL; + + err = LLVMTargetMachineEmitToMemoryBuffer(tm, mod, file_type, + &err_message, out_buffer); + + if (err) { + r_log = std::string(err_message); + } + + LLVMDisposeMessage(err_message); + + if (err) { + throw build_error(); + } + } + std::vector compile_native(const llvm::Module *mod, const std::string &triple, - const std::string &processor, compat::string &r_log) { + const std::string &processor, unsigned dump_asm, + compat::string &r_log) { std::string log; LLVMTargetRef target; @@ -466,7 +500,6 @@ namespace { LLVMMemoryBufferRef out_buffer; unsigned buffer_size; const char *buffer_data; - LLVMBool err; LLVMModuleRef mod_ref = wrap(mod); if (LLVMGetTargetFromTriple(triple.c_str(), &target, &error_message)) { @@ -484,16 +517,21 @@ namespace { throw build_error(); } - err = LLVMTargetMachineEmitToMemoryBuffer(tm, mod_ref, LLVMObjectFile, - &error_message, &out_buffer); - - if (err) { - LLVMDisposeTargetMachine(tm); - r_log = std::string(error_message); - LLVMDisposeMessage(error_message); - throw build_error(); + if (dump_asm) { + LLVMSetTargetMachineAsmVerbosity(tm, true); + LLVMModuleRef debug_mod = wrap(llvm::CloneModule(mod)); + emit_code(tm, debug_mod, LLVMAssemblyFile, &out_buffer, r_log); + buffer_size = LLVMGetBufferSize(out_buffer); + buffer_data = LLVMGetBufferStart(out_buffer); + debug_log(std::string(buffer_data, buffer_size), ".asm"); + + LLVMSetTargetMachineAsmVerbosity(tm, false); + LLVMDisposeMemoryBuffer(out_buffer); + LLVMDisposeModule(debug_mod); } + emit_code(tm, mod_ref, LLVMObjectFile, &out_buffer, r_log); + buffer_size = LLVMGetBufferSize(out_buffer); buffer_data = LLVMGetBufferStart(out_buffer); @@ -632,6 +670,18 @@ namespace { } } // End anonymous namespace +#define DBG_CLC (1 << 0) +#define DBG_LLVM (1 << 1) +#define DBG_ASM (1 << 2) + +static const struct debug_named_value debug_options[] = { + {"clc", DBG_CLC, "Dump the OpenCL C code for all kernels."}, + {"llvm", DBG_LLVM, "Dump the generated LLVM IR for all kernels."}, + {"asm", DBG_ASM, "Dump kernel assembly code for targets specifying " + "PIPE_SHADER_IR_NATIVE"}, + DEBUG_NAMED_VALUE_END // must be last +}; + module clover::compile_program_llvm(const compat::string &source, enum pipe_shader_ir ir, @@ -640,6 +690,8 @@ clover::compile_program_llvm(const compat::string &source, compat::string &r_log) { init_targets(); + static unsigned debug_flags = debug_get_flags_option("CLOVER_DEBUG", + debug_options, 0); std::vector kernels; size_t processor_str_len = std::string(target.begin()).find_first_of("-"); @@ -664,6 +716,17 @@ clover::compile_program_llvm(const compat::string &source, optimize(mod, optimization_level, kernels); + if (debug_flags & DBG_CLC) + debug_log(source, ".cl"); + + if (debug_flags & DBG_LLVM) { + std::string log; + llvm::raw_string_ostream s_log(log); + mod->print(s_log, NULL); + s_log.flush(); + debug_log(log, ".ll"); + } + module m; // Build the clover::module switch (ir) { @@ -676,7 +739,8 @@ clover::compile_program_llvm(const compat::string &source, m = build_module_llvm(mod, kernels, address_spaces); break; case PIPE_SHADER_IR_NATIVE: { - std::vector code = compile_native(mod, triple, processor, r_log); + std::vector code = compile_native(mod, triple, processor, + debug_flags & DBG_ASM, r_log); m = build_module_native(code, mod, kernels, address_spaces, r_log); break; } -- 2.30.2