From bc86690f137a71a6f1cdcc0393a4b3f181df7240 Mon Sep 17 00:00:00 2001 From: Darren Powell Date: Mon, 31 Mar 2014 18:00:28 -0400 Subject: [PATCH] radeonsi: Added Diag Handler to receive LLVM Error messages Reviewed-by: Tom Stellard --- src/gallium/drivers/radeon/radeon_llvm_emit.c | 50 +++++++++++++++++++++++---- src/gallium/drivers/radeonsi/si_shader.c | 12 +++++-- src/gallium/drivers/radeonsi/si_state.c | 2 ++ 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/gallium/drivers/radeon/radeon_llvm_emit.c b/src/gallium/drivers/radeon/radeon_llvm_emit.c index 7bcdc2756f0..891781f6c83 100644 --- a/src/gallium/drivers/radeon/radeon_llvm_emit.c +++ b/src/gallium/drivers/radeon/radeon_llvm_emit.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -79,6 +80,22 @@ static LLVMTargetRef get_r600_target() { return target; } +#if HAVE_LLVM >= 0x0305 + +static void radeonDiagnosticHandler(LLVMDiagnosticInfoRef di, void *context) { + unsigned int *diagnosticflag; + char *diaginfo_message; + + diaginfo_message = LLVMGetDiagInfoDescription(di); + fprintf(stderr,"LLVM triggered Diagnostic Handler: %s\n", diaginfo_message); + LLVMDisposeMessage(diaginfo_message); + + diagnosticflag = (unsigned int *)context; + *diagnosticflag = ((LLVMDSError == LLVMGetDiagInfoSeverity(di)) ? 1 : 0); +} + +#endif + /** * Compile an LLVM module to machine code. * @@ -92,12 +109,15 @@ unsigned radeon_llvm_compile(LLVMModuleRef M, struct radeon_shader_binary *binar char cpu[CPU_STRING_LEN]; char fs[FS_STRING_LEN]; char *err; + LLVMContextRef llvm_ctx; + unsigned rval = 0; LLVMMemoryBufferRef out_buffer; unsigned buffer_size; const char *buffer_data; char triple[TRIPLE_STRING_LEN]; - LLVMBool r; + LLVMBool mem_err; + /* initialise */ init_r600_target(); target = get_r600_target(); @@ -112,24 +132,42 @@ unsigned radeon_llvm_compile(LLVMModuleRef M, struct radeon_shader_binary *binar strncpy(fs, "+DumpCode", FS_STRING_LEN); } strncpy(triple, "r600--", TRIPLE_STRING_LEN); + + /* Setup Diagnostic Handler*/ + llvm_ctx = LLVMGetModuleContext(M); + +#if HAVE_LLVM >= 0x0305 + LLVMContextSetDiagnosticHandler(llvm_ctx, radeonDiagnosticHandler, &rval); +#endif + rval = 0; + + /* Compile IR*/ tm = LLVMCreateTargetMachine(target, triple, cpu, fs, LLVMCodeGenLevelDefault, LLVMRelocDefault, LLVMCodeModelDefault); - - r = LLVMTargetMachineEmitToMemoryBuffer(tm, M, LLVMObjectFile, &err, + mem_err = LLVMTargetMachineEmitToMemoryBuffer(tm, M, LLVMObjectFile, &err, &out_buffer); - if (r) { - fprintf(stderr, "%s", err); + + /* Process Errors/Warnings */ + if (mem_err) { + fprintf(stderr, "%s: %s", __FUNCTION__, err); FREE(err); + LLVMDisposeTargetMachine(tm); return 1; } + if (0 != rval) { + fprintf(stderr, "%s: Processing Diag Flag\n", __FUNCTION__); + } + + /* Extract Shader Code*/ buffer_size = LLVMGetBufferSize(out_buffer); buffer_data = LLVMGetBufferStart(out_buffer); radeon_elf_read(buffer_data, buffer_size, binary, dump); + /* Clean up */ LLVMDisposeMemoryBuffer(out_buffer); LLVMDisposeTargetMachine(tm); - return 0; + return rval; } diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index e4390eeac1f..0d070d3cef6 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -2293,14 +2293,19 @@ static void preload_streamout_buffers(struct si_shader_context *si_shader_ctx) int si_compile_llvm(struct si_context *sctx, struct si_pipe_shader *shader, LLVMModuleRef mod) { + unsigned r; /* llvm_compile result */ unsigned i; uint32_t *ptr; struct radeon_shader_binary binary; bool dump = r600_can_dump_shader(&sctx->screen->b, shader->selector ? shader->selector->tokens : NULL); + const char * gpu_family = r600_get_llvm_processor_name(sctx->screen->b.family); + + /* Use LLVM to compile shader */ memset(&binary, 0, sizeof(binary)); - radeon_llvm_compile(mod, &binary, - r600_get_llvm_processor_name(sctx->screen->b.family), dump); + r = radeon_llvm_compile(mod, &binary, gpu_family, dump); + + /* Output binary dump if rscreen->debug_flags are set */ if (dump && ! binary.disassembled) { fprintf(stderr, "SI CODE:\n"); for (i = 0; i < binary.code_size; i+=4 ) { @@ -2313,6 +2318,7 @@ int si_compile_llvm(struct si_context *sctx, struct si_pipe_shader *shader, /* XXX: We may be able to emit some of these values directly rather than * extracting fields to be emitted later. */ + /* Parse config data in compiled binary */ for (i = 0; i < binary.config_size; i+= 8) { unsigned reg = util_le32_to_cpu(*(uint32_t*)(binary.config + i)); unsigned value = util_le32_to_cpu(*(uint32_t*)(binary.config + i + 4)); @@ -2361,7 +2367,7 @@ int si_compile_llvm(struct si_context *sctx, struct si_pipe_shader *shader, free(binary.code); free(binary.config); - return 0; + return r; } /* Generate code for the hardware VS shader stage to go with a geometry shader */ diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index d81354ebe8d..ab9c4cc2834 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -2208,9 +2208,11 @@ static void si_bind_ps_shader(struct pipe_context *ctx, void *state) struct si_context *sctx = (struct si_context *)ctx; struct si_pipe_shader_selector *sel = state; + /* skip if supplied shader is one already in use */ if (sctx->ps_shader == sel) return; + /* use dummy shader if supplied shader is corrupt */ if (!sel || !sel->current) sel = sctx->dummy_pixel_shader; -- 2.11.0