GLSL fixes:
[mesa.git] / src / mesa / shader / slang / slang_assemble_conditional.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file slang_assemble_conditional.c
27 * slang condtional expressions assembler
28 * \author Michal Krol
29 */
30
31 #include "imports.h"
32 #include "slang_assemble.h"
33 #include "slang_compile.h"
34
35 /*
36 * _slang_assemble_logicaland()
37 *
38 * and:
39 * <left-expression>
40 * jumpz zero
41 * <right-expression>
42 * jump end
43 * zero:
44 * push 0
45 * end:
46 */
47
48 GLboolean _slang_assemble_logicaland (slang_assemble_ctx *A, slang_operation *op)
49 {
50 GLuint zero_jump, end_jump;
51
52 /* evaluate left expression */
53 if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
54 return GL_FALSE;
55
56 /* jump to pushing 0 if not true */
57 zero_jump = A->file->count;
58 if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
59 return GL_FALSE;
60
61 /* evaluate right expression */
62 if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
63 return GL_FALSE;
64
65 /* jump to the end of the expression */
66 end_jump = A->file->count;
67 if (!slang_assembly_file_push (A->file, slang_asm_jump))
68 return GL_FALSE;
69
70 /* push 0 on stack */
71 A->file->code[zero_jump].param[0] = A->file->count;
72 if (!slang_assembly_file_push_literal (A->file, slang_asm_bool_push, (GLfloat) 0))
73 return GL_FALSE;
74
75 /* the end of the expression */
76 A->file->code[end_jump].param[0] = A->file->count;
77
78 return GL_TRUE;
79 }
80
81 /*
82 * _slang_assemble_logicalor()
83 *
84 * or:
85 * <left-expression>
86 * jumpz right
87 * push 1
88 * jump end
89 * right:
90 * <right-expression>
91 * end:
92 */
93
94 GLboolean _slang_assemble_logicalor (slang_assemble_ctx *A, slang_operation *op)
95 {
96 GLuint right_jump, end_jump;
97
98 /* evaluate left expression */
99 if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
100 return GL_FALSE;
101
102 /* jump to evaluation of right expression if not true */
103 right_jump = A->file->count;
104 if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
105 return GL_FALSE;
106
107 /* push 1 on stack */
108 if (!slang_assembly_file_push_literal (A->file, slang_asm_bool_push, (GLfloat) 1))
109 return GL_FALSE;
110
111 /* jump to the end of the expression */
112 end_jump = A->file->count;
113 if (!slang_assembly_file_push (A->file, slang_asm_jump))
114 return GL_FALSE;
115
116 /* evaluate right expression */
117 A->file->code[right_jump].param[0] = A->file->count;
118 if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
119 return GL_FALSE;
120
121 /* the end of the expression */
122 A->file->code[end_jump].param[0] = A->file->count;
123
124 return GL_TRUE;
125 }
126
127 /*
128 * _slang_assemble_select()
129 *
130 * select:
131 * <condition-expression>
132 * jumpz false
133 * <true-expression>
134 * jump end
135 * false:
136 * <false-expression>
137 * end:
138 */
139
140 GLboolean _slang_assemble_select (slang_assemble_ctx *A, slang_operation *op)
141 {
142 GLuint cond_jump, end_jump;
143
144 /* execute condition expression */
145 if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
146 return GL_FALSE;
147
148 /* jump to false expression if not true */
149 cond_jump = A->file->count;
150 if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
151 return GL_FALSE;
152
153 /* execute true expression */
154 if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
155 return GL_FALSE;
156
157 /* jump to the end of the expression */
158 end_jump = A->file->count;
159 if (!slang_assembly_file_push (A->file, slang_asm_jump))
160 return GL_FALSE;
161
162 /* resolve false point */
163 A->file->code[cond_jump].param[0] = A->file->count;
164
165 /* execute false expression */
166 if (!_slang_assemble_operation (A, &op->children[2], slang_ref_forbid))
167 return GL_FALSE;
168
169 /* resolve the end of the expression */
170 A->file->code[end_jump].param[0] = A->file->count;
171
172 return GL_TRUE;
173 }
174
175 /*
176 * _slang_assemble_for()
177 *
178 * for:
179 * <init-statement>
180 * jump start
181 * break:
182 * jump end
183 * continue:
184 * <loop-increment>
185 * start:
186 * <condition-statement>
187 * jumpz end
188 * <loop-body>
189 * jump continue
190 * end:
191 */
192
193 GLboolean _slang_assemble_for (slang_assemble_ctx *A, slang_operation *op)
194 {
195 GLuint start_jump, end_jump, cond_jump;
196 GLuint break_label, cont_label;
197 slang_assembly_flow_control save_flow = A->flow;
198
199 /* execute initialization statement */
200 if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/))
201 return GL_FALSE;
202 if (!_slang_cleanup_stack (A, &op->children[0]))
203 return GL_FALSE;
204
205 /* skip the "go to the end of the loop" and loop-increment statements */
206 start_jump = A->file->count;
207 if (!slang_assembly_file_push (A->file, slang_asm_jump))
208 return GL_FALSE;
209
210 /* go to the end of the loop - break statements are directed here */
211 break_label = A->file->count;
212 end_jump = A->file->count;
213 if (!slang_assembly_file_push (A->file, slang_asm_jump))
214 return GL_FALSE;
215
216 /* resolve the beginning of the loop - continue statements are directed here */
217 cont_label = A->file->count;
218
219 /* execute loop-increment statement */
220 if (!_slang_assemble_operation (A, &op->children[2], slang_ref_forbid/*slang_ref_freelance*/))
221 return GL_FALSE;
222 if (!_slang_cleanup_stack (A, &op->children[2]))
223 return GL_FALSE;
224
225 /* resolve the condition point */
226 A->file->code[start_jump].param[0] = A->file->count;
227
228 /* execute condition statement */
229 if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
230 return GL_FALSE;
231
232 /* jump to the end of the loop if not true */
233 cond_jump = A->file->count;
234 if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
235 return GL_FALSE;
236
237 /* execute loop body */
238 A->flow.loop_start = cont_label;
239 A->flow.loop_end = break_label;
240 if (!_slang_assemble_operation (A, &op->children[3], slang_ref_forbid/*slang_ref_freelance*/))
241 return GL_FALSE;
242 if (!_slang_cleanup_stack (A, &op->children[3]))
243 return GL_FALSE;
244 A->flow = save_flow;
245
246 /* go to the beginning of the loop */
247 if (!slang_assembly_file_push_label (A->file, slang_asm_jump, cont_label))
248 return GL_FALSE;
249
250 /* resolve the end of the loop */
251 A->file->code[end_jump].param[0] = A->file->count;
252 A->file->code[cond_jump].param[0] = A->file->count;
253
254 return GL_TRUE;
255 }
256
257 /*
258 * _slang_assemble_do()
259 *
260 * do:
261 * jump start
262 * break:
263 * jump end
264 * continue:
265 * jump condition
266 * start:
267 * <loop-body>
268 * condition:
269 * <condition-statement>
270 * jumpz end
271 * jump start
272 * end:
273 */
274
275 GLboolean _slang_assemble_do (slang_assemble_ctx *A, slang_operation *op)
276 {
277 GLuint skip_jump, end_jump, cont_jump, cond_jump;
278 GLuint break_label, cont_label;
279 slang_assembly_flow_control save_flow = A->flow;
280
281 /* skip the "go to the end of the loop" and "go to condition" statements */
282 skip_jump = A->file->count;
283 if (!slang_assembly_file_push (A->file, slang_asm_jump))
284 return GL_FALSE;
285
286 /* go to the end of the loop - break statements are directed here */
287 break_label = A->file->count;
288 end_jump = A->file->count;
289 if (!slang_assembly_file_push (A->file, slang_asm_jump))
290 return GL_FALSE;
291
292 /* go to condition - continue statements are directed here */
293 cont_label = A->file->count;
294 cont_jump = A->file->count;
295 if (!slang_assembly_file_push (A->file, slang_asm_jump))
296 return GL_FALSE;
297
298 /* resolve the beginning of the loop */
299 A->file->code[skip_jump].param[0] = A->file->count;
300
301 /* execute loop body */
302 A->flow.loop_start = cont_label;
303 A->flow.loop_end = break_label;
304 if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/))
305 return GL_FALSE;
306 if (!_slang_cleanup_stack (A, &op->children[0]))
307 return GL_FALSE;
308 A->flow = save_flow;
309
310 /* resolve condition point */
311 A->file->code[cont_jump].param[0] = A->file->count;
312
313 /* execute condition statement */
314 if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
315 return GL_FALSE;
316
317 /* jump to the end of the loop if not true */
318 cond_jump = A->file->count;
319 if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
320 return GL_FALSE;
321
322 /* jump to the beginning of the loop */
323 if (!slang_assembly_file_push_label (A->file, slang_asm_jump, A->file->code[skip_jump].param[0]))
324 return GL_FALSE;
325
326 /* resolve the end of the loop */
327 A->file->code[end_jump].param[0] = A->file->count;
328 A->file->code[cond_jump].param[0] = A->file->count;
329
330 return GL_TRUE;
331 }
332
333 /*
334 * _slang_assemble_while()
335 *
336 * while:
337 * jump continue
338 * break:
339 * jump end
340 * continue:
341 * <condition-statement>
342 * jumpz end
343 * <loop-body>
344 * jump continue
345 * end:
346 */
347
348 GLboolean _slang_assemble_while (slang_assemble_ctx *A, slang_operation *op)
349 {
350 GLuint skip_jump, end_jump, cond_jump;
351 GLuint break_label;
352 slang_assembly_flow_control save_flow = A->flow;
353
354 /* skip the "go to the end of the loop" statement */
355 skip_jump = A->file->count;
356 if (!slang_assembly_file_push (A->file, slang_asm_jump))
357 return GL_FALSE;
358
359 /* go to the end of the loop - break statements are directed here */
360 break_label = A->file->count;
361 end_jump = A->file->count;
362 if (!slang_assembly_file_push (A->file, slang_asm_jump))
363 return GL_FALSE;
364
365 /* resolve the beginning of the loop - continue statements are directed here */
366 A->file->code[skip_jump].param[0] = A->file->count;
367
368 /* execute condition statement */
369 if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
370 return GL_FALSE;
371
372 /* jump to the end of the loop if not true */
373 cond_jump = A->file->count;
374 if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
375 return GL_FALSE;
376
377 /* execute loop body */
378 A->flow.loop_start = A->file->code[skip_jump].param[0];
379 A->flow.loop_end = break_label;
380 if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid/*slang_ref_freelance*/))
381 return GL_FALSE;
382 if (!_slang_cleanup_stack (A, &op->children[1]))
383 return GL_FALSE;
384 A->flow = save_flow;
385
386 /* jump to the beginning of the loop */
387 if (!slang_assembly_file_push_label (A->file, slang_asm_jump, A->file->code[skip_jump].param[0]))
388 return GL_FALSE;
389
390 /* resolve the end of the loop */
391 A->file->code[end_jump].param[0] = A->file->count;
392 A->file->code[cond_jump].param[0] = A->file->count;
393
394 return GL_TRUE;
395 }
396
397 /*
398 * _slang_assemble_if()
399 *
400 * if:
401 * <condition-statement>
402 * jumpz else
403 * <true-statement>
404 * jump end
405 * else:
406 * <false-statement>
407 * end:
408 */
409
410 GLboolean _slang_assemble_if (slang_assemble_ctx *A, slang_operation *op)
411 {
412 GLuint cond_jump, else_jump;
413
414 /* execute condition statement */
415 if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
416 return GL_FALSE;
417
418 /* jump to false-statement if not true */
419 cond_jump = A->file->count;
420 if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
421 return GL_FALSE;
422
423 /* execute true-statement */
424 if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid/*slang_ref_freelance*/))
425 return GL_FALSE;
426 if (!_slang_cleanup_stack (A, &op->children[1]))
427 return GL_FALSE;
428
429 /* skip if-false statement */
430 else_jump = A->file->count;
431 if (!slang_assembly_file_push (A->file, slang_asm_jump))
432 return GL_FALSE;
433
434 /* resolve start of false-statement */
435 A->file->code[cond_jump].param[0] = A->file->count;
436
437 /* execute false-statement */
438 if (!_slang_assemble_operation (A, &op->children[2], slang_ref_forbid/*slang_ref_freelance*/))
439 return GL_FALSE;
440 if (!_slang_cleanup_stack (A, &op->children[2]))
441 return GL_FALSE;
442
443 /* resolve end of if-false statement */
444 A->file->code[else_jump].param[0] = A->file->count;
445
446 return GL_TRUE;
447 }
448