r300: Silence 'mixed declarations and code' warnings.
[mesa.git] / src / mesa / drivers / dri / r300 / compiler / radeon_compiler.c
1 /*
2 * Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22
23 #include "radeon_compiler.h"
24
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28
29 #include "radeon_program.h"
30
31
32 void rc_init(struct radeon_compiler * c)
33 {
34 memset(c, 0, sizeof(*c));
35
36 memory_pool_init(&c->Pool);
37 c->Program.Instructions.Prev = &c->Program.Instructions;
38 c->Program.Instructions.Next = &c->Program.Instructions;
39 c->Program.Instructions.U.I.Opcode = RC_OPCODE_ILLEGAL_OPCODE;
40 }
41
42 void rc_destroy(struct radeon_compiler * c)
43 {
44 rc_constants_destroy(&c->Program.Constants);
45 memory_pool_destroy(&c->Pool);
46 free(c->ErrorMsg);
47 }
48
49 void rc_debug(struct radeon_compiler * c, const char * fmt, ...)
50 {
51 va_list ap;
52
53 if (!c->Debug)
54 return;
55
56 va_start(ap, fmt);
57 vfprintf(stderr, fmt, ap);
58 va_end(ap);
59 }
60
61 void rc_error(struct radeon_compiler * c, const char * fmt, ...)
62 {
63 va_list ap;
64
65 c->Error = 1;
66
67 if (!c->ErrorMsg) {
68 /* Only remember the first error */
69 char buf[1024];
70 int written;
71
72 va_start(ap, fmt);
73 written = vsnprintf(buf, sizeof(buf), fmt, ap);
74 va_end(ap);
75
76 if (written < sizeof(buf)) {
77 c->ErrorMsg = strdup(buf);
78 } else {
79 c->ErrorMsg = malloc(written + 1);
80
81 va_start(ap, fmt);
82 vsnprintf(c->ErrorMsg, written + 1, fmt, ap);
83 va_end(ap);
84 }
85 }
86
87 if (c->Debug) {
88 fprintf(stderr, "r300compiler error: ");
89
90 va_start(ap, fmt);
91 vfprintf(stderr, fmt, ap);
92 va_end(ap);
93 }
94 }
95
96 int rc_if_fail_helper(struct radeon_compiler * c, const char * file, int line, const char * assertion)
97 {
98 rc_error(c, "ICE at %s:%i: assertion failed: %s\n", file, line, assertion);
99 return 1;
100 }
101
102 /**
103 * Recompute c->Program.InputsRead and c->Program.OutputsWritten
104 * based on which inputs and outputs are actually referenced
105 * in program instructions.
106 */
107 void rc_calculate_inputs_outputs(struct radeon_compiler * c)
108 {
109 struct rc_instruction *inst;
110
111 c->Program.InputsRead = 0;
112 c->Program.OutputsWritten = 0;
113
114 for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next)
115 {
116 const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
117 int i;
118
119 for (i = 0; i < opcode->NumSrcRegs; ++i) {
120 if (inst->U.I.SrcReg[i].File == RC_FILE_INPUT)
121 c->Program.InputsRead |= 1 << inst->U.I.SrcReg[i].Index;
122 }
123
124 if (opcode->HasDstReg) {
125 if (inst->U.I.DstReg.File == RC_FILE_OUTPUT)
126 c->Program.OutputsWritten |= 1 << inst->U.I.DstReg.Index;
127 }
128 }
129 }
130
131 /**
132 * Rewrite the program such that everything that source the given input
133 * register will source new_input instead.
134 */
135 void rc_move_input(struct radeon_compiler * c, unsigned input, struct rc_src_register new_input)
136 {
137 struct rc_instruction * inst;
138
139 c->Program.InputsRead &= ~(1 << input);
140
141 for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) {
142 const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
143 unsigned i;
144
145 for(i = 0; i < opcode->NumSrcRegs; ++i) {
146 if (inst->U.I.SrcReg[i].File == RC_FILE_INPUT && inst->U.I.SrcReg[i].Index == input) {
147 inst->U.I.SrcReg[i].File = new_input.File;
148 inst->U.I.SrcReg[i].Index = new_input.Index;
149 inst->U.I.SrcReg[i].Swizzle = combine_swizzles(new_input.Swizzle, inst->U.I.SrcReg[i].Swizzle);
150 if (!inst->U.I.SrcReg[i].Abs) {
151 inst->U.I.SrcReg[i].Negate ^= new_input.Negate;
152 inst->U.I.SrcReg[i].Abs = new_input.Abs;
153 }
154
155 c->Program.InputsRead |= 1 << new_input.Index;
156 }
157 }
158 }
159 }
160
161
162 /**
163 * Rewrite the program such that everything that writes into the given
164 * output register will instead write to new_output. The new_output
165 * writemask is honoured.
166 */
167 void rc_move_output(struct radeon_compiler * c, unsigned output, unsigned new_output, unsigned writemask)
168 {
169 struct rc_instruction * inst;
170
171 c->Program.OutputsWritten &= ~(1 << output);
172
173 for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) {
174 const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
175
176 if (opcode->HasDstReg) {
177 if (inst->U.I.DstReg.File == RC_FILE_OUTPUT && inst->U.I.DstReg.Index == output) {
178 inst->U.I.DstReg.Index = new_output;
179 inst->U.I.DstReg.WriteMask &= writemask;
180
181 c->Program.OutputsWritten |= 1 << new_output;
182 }
183 }
184 }
185 }
186
187
188 /**
189 * Rewrite the program such that a given output is duplicated.
190 */
191 void rc_copy_output(struct radeon_compiler * c, unsigned output, unsigned dup_output)
192 {
193 unsigned tempreg = rc_find_free_temporary(c);
194 struct rc_instruction * inst;
195
196 for(inst = c->Program.Instructions.Next; inst != &c->Program.Instructions; inst = inst->Next) {
197 const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
198
199 if (opcode->HasDstReg) {
200 if (inst->U.I.DstReg.File == RC_FILE_OUTPUT && inst->U.I.DstReg.Index == output) {
201 inst->U.I.DstReg.File = RC_FILE_TEMPORARY;
202 inst->U.I.DstReg.Index = tempreg;
203 }
204 }
205 }
206
207 inst = rc_insert_new_instruction(c, c->Program.Instructions.Prev);
208 inst->U.I.Opcode = RC_OPCODE_MOV;
209 inst->U.I.DstReg.File = RC_FILE_OUTPUT;
210 inst->U.I.DstReg.Index = output;
211
212 inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
213 inst->U.I.SrcReg[0].Index = tempreg;
214 inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
215
216 inst = rc_insert_new_instruction(c, c->Program.Instructions.Prev);
217 inst->U.I.Opcode = RC_OPCODE_MOV;
218 inst->U.I.DstReg.File = RC_FILE_OUTPUT;
219 inst->U.I.DstReg.Index = dup_output;
220
221 inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
222 inst->U.I.SrcReg[0].Index = tempreg;
223 inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
224
225 c->Program.OutputsWritten |= 1 << dup_output;
226 }
227
228
229 /**
230 * Introduce standard code fragment to deal with fragment.position.
231 */
232 void rc_transform_fragment_wpos(struct radeon_compiler * c, unsigned wpos, unsigned new_input)
233 {
234 unsigned tempregi = rc_find_free_temporary(c);
235 struct rc_instruction * inst_rcp;
236 struct rc_instruction * inst_mul;
237 struct rc_instruction * inst_mad;
238 struct rc_instruction * inst;
239
240 c->Program.InputsRead &= ~(1 << wpos);
241 c->Program.InputsRead |= 1 << new_input;
242
243 /* perspective divide */
244 inst_rcp = rc_insert_new_instruction(c, &c->Program.Instructions);
245 inst_rcp->U.I.Opcode = RC_OPCODE_RCP;
246
247 inst_rcp->U.I.DstReg.File = RC_FILE_TEMPORARY;
248 inst_rcp->U.I.DstReg.Index = tempregi;
249 inst_rcp->U.I.DstReg.WriteMask = RC_MASK_W;
250
251 inst_rcp->U.I.SrcReg[0].File = RC_FILE_INPUT;
252 inst_rcp->U.I.SrcReg[0].Index = new_input;
253 inst_rcp->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_WWWW;
254
255 inst_mul = rc_insert_new_instruction(c, inst_rcp);
256 inst_mul->U.I.Opcode = RC_OPCODE_MUL;
257
258 inst_mul->U.I.DstReg.File = RC_FILE_TEMPORARY;
259 inst_mul->U.I.DstReg.Index = tempregi;
260 inst_mul->U.I.DstReg.WriteMask = RC_MASK_XYZ;
261
262 inst_mul->U.I.SrcReg[0].File = RC_FILE_INPUT;
263 inst_mul->U.I.SrcReg[0].Index = new_input;
264
265 inst_mul->U.I.SrcReg[1].File = RC_FILE_TEMPORARY;
266 inst_mul->U.I.SrcReg[1].Index = tempregi;
267 inst_mul->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_WWWW;
268
269 /* viewport transformation */
270 inst_mad = rc_insert_new_instruction(c, inst_mul);
271 inst_mad->U.I.Opcode = RC_OPCODE_MAD;
272
273 inst_mad->U.I.DstReg.File = RC_FILE_TEMPORARY;
274 inst_mad->U.I.DstReg.Index = tempregi;
275 inst_mad->U.I.DstReg.WriteMask = RC_MASK_XYZ;
276
277 inst_mad->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
278 inst_mad->U.I.SrcReg[0].Index = tempregi;
279 inst_mad->U.I.SrcReg[0].Swizzle = RC_MAKE_SWIZZLE(RC_SWIZZLE_X, RC_SWIZZLE_Y, RC_SWIZZLE_Z, RC_SWIZZLE_ZERO);
280
281 inst_mad->U.I.SrcReg[1].File = RC_FILE_CONSTANT;
282 inst_mad->U.I.SrcReg[1].Index = rc_constants_add_state(&c->Program.Constants, RC_STATE_R300_WINDOW_DIMENSION, 0);
283 inst_mad->U.I.SrcReg[1].Swizzle = RC_MAKE_SWIZZLE(RC_SWIZZLE_X, RC_SWIZZLE_Y, RC_SWIZZLE_Z, RC_SWIZZLE_ZERO);
284
285 inst_mad->U.I.SrcReg[2].File = RC_FILE_CONSTANT;
286 inst_mad->U.I.SrcReg[2].Index = inst_mad->U.I.SrcReg[1].Index;
287 inst_mad->U.I.SrcReg[2].Swizzle = RC_MAKE_SWIZZLE(RC_SWIZZLE_X, RC_SWIZZLE_Y, RC_SWIZZLE_Z, RC_SWIZZLE_ZERO);
288
289 for (inst = inst_mad->Next; inst != &c->Program.Instructions; inst = inst->Next) {
290 const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->U.I.Opcode);
291 unsigned i;
292
293 for(i = 0; i < opcode->NumSrcRegs; i++) {
294 if (inst->U.I.SrcReg[i].File == RC_FILE_INPUT &&
295 inst->U.I.SrcReg[i].Index == wpos) {
296 inst->U.I.SrcReg[i].File = RC_FILE_TEMPORARY;
297 inst->U.I.SrcReg[i].Index = tempregi;
298 }
299 }
300 }
301 }
302