summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/radeon/radeon_llvm_emit.c50
-rw-r--r--src/gallium/drivers/radeonsi/si_shader.c12
-rw-r--r--src/gallium/drivers/radeonsi/si_state.c2
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 <llvm-c/Target.h>
#include <llvm-c/TargetMachine.h>
+#include <llvm-c/Core.h>
#include <stdlib.h>
#include <stdio.h>
@@ -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;