summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Stellard <[email protected]>2014-09-30 10:32:33 -0400
committerTom Stellard <[email protected]>2014-10-16 19:42:52 -0400
commite1d363b3ffbfb85133a6871c63068a4ba841b2cd (patch)
tree1e4fea5cfca404dd9c3124246ce63b70b49828fa
parent76136c29bbd78ea414c86402d4031855218dc42b (diff)
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 <[email protected]>
-rw-r--r--src/gallium/state_trackers/clover/llvm/invocation.cpp86
1 files 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 <llvm/Support/TargetRegistry.h>
#include <llvm/Transforms/IPO.h>
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
+#include <llvm/Transforms/Utils/Cloning.h>
+
#if HAVE_LLVM < 0x0302
#include <llvm/Target/TargetData.h>
@@ -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<char>
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<llvm::Function *> 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<char> code = compile_native(mod, triple, processor, r_log);
+ std::vector<char> code = compile_native(mod, triple, processor,
+ debug_flags & DBG_ASM, r_log);
m = build_module_native(code, mod, kernels, address_spaces, r_log);
break;
}