gallium/radeon: Only print a message for LLVM diagnostic errors
[mesa.git] / src / gallium / drivers / radeon / radeon_llvm_emit.c
1 /*
2 * Copyright 2011 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors: Tom Stellard <thomas.stellard@amd.com>
24 *
25 */
26 #include "radeon_llvm_emit.h"
27 #include "radeon_elf_util.h"
28 #include "util/u_memory.h"
29
30 #include <llvm-c/Target.h>
31 #include <llvm-c/TargetMachine.h>
32 #include <llvm-c/Core.h>
33
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <string.h>
37
38 #define CPU_STRING_LEN 30
39 #define FS_STRING_LEN 30
40 #define TRIPLE_STRING_LEN 7
41
42 /**
43 * Set the shader type we want to compile
44 *
45 * @param type shader type to set
46 */
47 void radeon_llvm_shader_type(LLVMValueRef F, unsigned type)
48 {
49 char Str[2];
50 sprintf(Str, "%1d", type);
51
52 LLVMAddTargetDependentFunctionAttr(F, "ShaderType", Str);
53 }
54
55 static void init_r600_target() {
56 static unsigned initialized = 0;
57 if (!initialized) {
58 LLVMInitializeR600TargetInfo();
59 LLVMInitializeR600Target();
60 LLVMInitializeR600TargetMC();
61 LLVMInitializeR600AsmPrinter();
62 initialized = 1;
63 }
64 }
65
66 static LLVMTargetRef get_r600_target() {
67 LLVMTargetRef target = NULL;
68
69 for (target = LLVMGetFirstTarget(); target;
70 target = LLVMGetNextTarget(target)) {
71 if (!strncmp(LLVMGetTargetName(target), "r600", 4)) {
72 break;
73 }
74 }
75
76 if (!target) {
77 fprintf(stderr, "Can't find target r600\n");
78 return NULL;
79 }
80 return target;
81 }
82
83 #if HAVE_LLVM >= 0x0305
84
85 static void radeonDiagnosticHandler(LLVMDiagnosticInfoRef di, void *context) {
86 unsigned int *diagnosticflag;
87 char *diaginfo_message;
88
89 diaginfo_message = LLVMGetDiagInfoDescription(di);
90 LLVMDisposeMessage(diaginfo_message);
91
92 diagnosticflag = (unsigned int *)context;
93 if (LLVMGetDiagInfoSeverity(di) == LLVMDSError) {
94 *diagnosticflag = 1;
95 fprintf(stderr,"LLVM triggered Diagnostic Handler: %s\n", diaginfo_message);
96 }
97 }
98
99 #endif
100
101 /**
102 * Compile an LLVM module to machine code.
103 *
104 * @returns 0 for success, 1 for failure
105 */
106 unsigned radeon_llvm_compile(LLVMModuleRef M, struct radeon_shader_binary *binary,
107 const char * gpu_family, unsigned dump) {
108
109 LLVMTargetRef target;
110 LLVMTargetMachineRef tm;
111 char cpu[CPU_STRING_LEN];
112 char fs[FS_STRING_LEN];
113 char *err;
114 LLVMContextRef llvm_ctx;
115 unsigned rval = 0;
116 LLVMMemoryBufferRef out_buffer;
117 unsigned buffer_size;
118 const char *buffer_data;
119 char triple[TRIPLE_STRING_LEN];
120 LLVMBool mem_err;
121
122 /* initialise */
123 init_r600_target();
124
125 target = get_r600_target();
126 if (!target) {
127 return 1;
128 }
129
130 strncpy(cpu, gpu_family, CPU_STRING_LEN);
131 memset(fs, 0, sizeof(fs));
132 if (dump) {
133 LLVMDumpModule(M);
134 strncpy(fs, "+DumpCode", FS_STRING_LEN);
135 }
136 strncpy(triple, "r600--", TRIPLE_STRING_LEN);
137
138 /* Setup Diagnostic Handler*/
139 llvm_ctx = LLVMGetModuleContext(M);
140
141 #if HAVE_LLVM >= 0x0305
142 LLVMContextSetDiagnosticHandler(llvm_ctx, radeonDiagnosticHandler, &rval);
143 #endif
144 rval = 0;
145
146 /* Compile IR*/
147 tm = LLVMCreateTargetMachine(target, triple, cpu, fs,
148 LLVMCodeGenLevelDefault, LLVMRelocDefault,
149 LLVMCodeModelDefault);
150 mem_err = LLVMTargetMachineEmitToMemoryBuffer(tm, M, LLVMObjectFile, &err,
151 &out_buffer);
152
153 /* Process Errors/Warnings */
154 if (mem_err) {
155 fprintf(stderr, "%s: %s", __FUNCTION__, err);
156 FREE(err);
157 LLVMDisposeTargetMachine(tm);
158 return 1;
159 }
160
161 if (0 != rval) {
162 fprintf(stderr, "%s: Processing Diag Flag\n", __FUNCTION__);
163 }
164
165 /* Extract Shader Code*/
166 buffer_size = LLVMGetBufferSize(out_buffer);
167 buffer_data = LLVMGetBufferStart(out_buffer);
168
169 radeon_elf_read(buffer_data, buffer_size, binary, dump);
170
171 /* Clean up */
172 LLVMDisposeMemoryBuffer(out_buffer);
173 LLVMDisposeTargetMachine(tm);
174 return rval;
175 }