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 <currojerez@riseup.net>
This commit is contained in:
@@ -61,6 +61,8 @@
|
|||||||
#include <llvm/Support/TargetRegistry.h>
|
#include <llvm/Support/TargetRegistry.h>
|
||||||
#include <llvm/Transforms/IPO.h>
|
#include <llvm/Transforms/IPO.h>
|
||||||
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
|
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
|
||||||
|
#include <llvm/Transforms/Utils/Cloning.h>
|
||||||
|
|
||||||
|
|
||||||
#if HAVE_LLVM < 0x0302
|
#if HAVE_LLVM < 0x0302
|
||||||
#include <llvm/Target/TargetData.h>
|
#include <llvm/Target/TargetData.h>
|
||||||
@@ -132,6 +134,15 @@ namespace {
|
|||||||
return module::deserialize(cs);
|
return module::deserialize(cs);
|
||||||
}
|
}
|
||||||
#endif
|
#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 *
|
llvm::Module *
|
||||||
compile_llvm(llvm::LLVMContext &llvm_ctx, const std::string &source,
|
compile_llvm(llvm::LLVMContext &llvm_ctx, const std::string &source,
|
||||||
@@ -456,9 +467,32 @@ namespace {
|
|||||||
return m;
|
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>
|
std::vector<char>
|
||||||
compile_native(const llvm::Module *mod, const std::string &triple,
|
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;
|
std::string log;
|
||||||
LLVMTargetRef target;
|
LLVMTargetRef target;
|
||||||
@@ -466,7 +500,6 @@ namespace {
|
|||||||
LLVMMemoryBufferRef out_buffer;
|
LLVMMemoryBufferRef out_buffer;
|
||||||
unsigned buffer_size;
|
unsigned buffer_size;
|
||||||
const char *buffer_data;
|
const char *buffer_data;
|
||||||
LLVMBool err;
|
|
||||||
LLVMModuleRef mod_ref = wrap(mod);
|
LLVMModuleRef mod_ref = wrap(mod);
|
||||||
|
|
||||||
if (LLVMGetTargetFromTriple(triple.c_str(), &target, &error_message)) {
|
if (LLVMGetTargetFromTriple(triple.c_str(), &target, &error_message)) {
|
||||||
@@ -484,16 +517,21 @@ namespace {
|
|||||||
throw build_error();
|
throw build_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
err = LLVMTargetMachineEmitToMemoryBuffer(tm, mod_ref, LLVMObjectFile,
|
if (dump_asm) {
|
||||||
&error_message, &out_buffer);
|
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");
|
||||||
|
|
||||||
if (err) {
|
LLVMSetTargetMachineAsmVerbosity(tm, false);
|
||||||
LLVMDisposeTargetMachine(tm);
|
LLVMDisposeMemoryBuffer(out_buffer);
|
||||||
r_log = std::string(error_message);
|
LLVMDisposeModule(debug_mod);
|
||||||
LLVMDisposeMessage(error_message);
|
|
||||||
throw build_error();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit_code(tm, mod_ref, LLVMObjectFile, &out_buffer, r_log);
|
||||||
|
|
||||||
buffer_size = LLVMGetBufferSize(out_buffer);
|
buffer_size = LLVMGetBufferSize(out_buffer);
|
||||||
buffer_data = LLVMGetBufferStart(out_buffer);
|
buffer_data = LLVMGetBufferStart(out_buffer);
|
||||||
|
|
||||||
@@ -632,6 +670,18 @@ namespace {
|
|||||||
}
|
}
|
||||||
} // End anonymous 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
|
module
|
||||||
clover::compile_program_llvm(const compat::string &source,
|
clover::compile_program_llvm(const compat::string &source,
|
||||||
enum pipe_shader_ir ir,
|
enum pipe_shader_ir ir,
|
||||||
@@ -640,6 +690,8 @@ clover::compile_program_llvm(const compat::string &source,
|
|||||||
compat::string &r_log) {
|
compat::string &r_log) {
|
||||||
|
|
||||||
init_targets();
|
init_targets();
|
||||||
|
static unsigned debug_flags = debug_get_flags_option("CLOVER_DEBUG",
|
||||||
|
debug_options, 0);
|
||||||
|
|
||||||
std::vector<llvm::Function *> kernels;
|
std::vector<llvm::Function *> kernels;
|
||||||
size_t processor_str_len = std::string(target.begin()).find_first_of("-");
|
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);
|
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;
|
module m;
|
||||||
// Build the clover::module
|
// Build the clover::module
|
||||||
switch (ir) {
|
switch (ir) {
|
||||||
@@ -676,7 +739,8 @@ clover::compile_program_llvm(const compat::string &source,
|
|||||||
m = build_module_llvm(mod, kernels, address_spaces);
|
m = build_module_llvm(mod, kernels, address_spaces);
|
||||||
break;
|
break;
|
||||||
case PIPE_SHADER_IR_NATIVE: {
|
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);
|
m = build_module_native(code, mod, kernels, address_spaces, r_log);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user