More GLSL code.
[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_utility.h"
33 #include "slang_assemble_conditional.h"
34 #include "slang_assemble.h"
35 #include "slang_execute.h"
36
37 /*
38 * _slang_assemble_logicaland()
39 *
40 * and:
41 * <left-expression>
42 * jumpz zero
43 * <right-expression>
44 * jump end
45 * zero:
46 * push 0
47 * end:
48 */
49
50 GLboolean _slang_assemble_logicaland (slang_assemble_ctx *A, slang_operation *op)
51 {
52 GLuint zero_jump, end_jump;
53
54 /* evaluate left expression */
55 if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid))
56 return GL_FALSE;
57
58 /* jump to pushing 0 if not true */
59 zero_jump = A->file->count;
60 if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
61 return GL_FALSE;
62
63 /* evaluate right expression */
64 if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid))
65 return GL_FALSE;
66
67 /* jump to the end of the expression */
68 end_jump = A->file->count;
69 if (!slang_assembly_file_push (A->file, slang_asm_jump))
70 return GL_FALSE;
71
72 /* push 0 on stack */
73 A->file->code[zero_jump].param[0] = A->file->count;
74 if (!slang_assembly_file_push_literal (A->file, slang_asm_bool_push, (GLfloat) 0))
75 return GL_FALSE;
76
77 /* the end of the expression */
78 A->file->code[end_jump].param[0] = A->file->count;
79
80 return GL_TRUE;
81 }
82
83 /*
84 * _slang_assemble_logicalor()
85 *
86 * or:
87 * <left-expression>
88 * jumpz right
89 * push 1
90 * jump end
91 * right:
92 * <right-expression>
93 * end:
94 */
95
96 GLboolean _slang_assemble_logicalor (slang_assemble_ctx *A, slang_operation *op)
97 {
98 GLuint right_jump, end_jump;
99
100 /* evaluate left expression */
101 if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid))
102 return GL_FALSE;
103
104 /* jump to evaluation of right expression if not true */
105 right_jump = A->file->count;
106 if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
107 return GL_FALSE;
108
109 /* push 1 on stack */
110 if (!slang_assembly_file_push_literal (A->file, slang_asm_bool_push, (GLfloat) 1))
111 return GL_FALSE;
112
113 /* jump to the end of the expression */
114 end_jump = A->file->count;
115 if (!slang_assembly_file_push (A->file, slang_asm_jump))
116 return GL_FALSE;
117
118 /* evaluate right expression */
119 A->file->code[right_jump].param[0] = A->file->count;
120 if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid))
121 return GL_FALSE;
122
123 /* the end of the expression */
124 A->file->code[end_jump].param[0] = A->file->count;
125
126 return GL_TRUE;
127 }
128
129 /*
130 * _slang_assemble_select()
131 *
132 * select:
133 * <condition-expression>
134 * jumpz false
135 * <true-expression>
136 * jump end
137 * false:
138 * <false-expression>
139 * end:
140 */
141
142 GLboolean _slang_assemble_select (slang_assemble_ctx *A, slang_operation *op)
143 {
144 GLuint cond_jump, end_jump;
145
146 /* execute condition expression */
147 if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid))
148 return GL_FALSE;
149
150 /* jump to false expression if not true */
151 cond_jump = A->file->count;
152 if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
153 return GL_FALSE;
154
155 /* execute true expression */
156 if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid))
157 return GL_FALSE;
158
159 /* jump to the end of the expression */
160 end_jump = A->file->count;
161 if (!slang_assembly_file_push (A->file, slang_asm_jump))
162 return GL_FALSE;
163
164 /* resolve false point */
165 A->file->code[cond_jump].param[0] = A->file->count;
166
167 /* execute false expression */
168 if (!_slang_assemble_operation_ (A, &op->children[2], slang_ref_forbid))
169 return GL_FALSE;
170
171 /* resolve the end of the expression */
172 A->file->code[end_jump].param[0] = A->file->count;
173
174 return GL_TRUE;
175 }
176
177 /*
178 * _slang_assemble_for()
179 *
180 * for:
181 * <init-statement>
182 * jump start
183 * break:
184 * jump end
185 * continue:
186 * <loop-increment>
187 * start:
188 * <condition-statement>
189 * jumpz end
190 * <loop-body>
191 * jump continue
192 * end:
193 */
194
195 GLboolean _slang_assemble_for (slang_assemble_ctx *A, slang_operation *op)
196 {
197 GLuint start_jump, end_jump, cond_jump;
198 GLuint break_label, cont_label;
199 slang_assembly_flow_control save_flow = A->flow;
200
201 /* execute initialization statement */
202 if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/))
203 return GL_FALSE;
204 if (!_slang_cleanup_stack_ (A, &op->children[0]))
205 return GL_FALSE;
206
207 /* skip the "go to the end of the loop" and loop-increment statements */
208 start_jump = A->file->count;
209 if (!slang_assembly_file_push (A->file, slang_asm_jump))
210 return GL_FALSE;
211
212 /* go to the end of the loop - break statements are directed here */
213 break_label = A->file->count;
214 end_jump = A->file->count;
215 if (!slang_assembly_file_push (A->file, slang_asm_jump))
216 return GL_FALSE;
217
218 /* resolve the beginning of the loop - continue statements are directed here */
219 cont_label = A->file->count;
220
221 /* execute loop-increment statement */
222 if (!_slang_assemble_operation_ (A, &op->children[2], slang_ref_forbid/*slang_ref_freelance*/))
223 return GL_FALSE;
224 if (!_slang_cleanup_stack_ (A, &op->children[2]))
225 return GL_FALSE;
226
227 /* resolve the condition point */
228 A->file->code[start_jump].param[0] = A->file->count;
229
230 /* execute condition statement */
231 if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid))
232 return GL_FALSE;
233
234 /* jump to the end of the loop if not true */
235 cond_jump = A->file->count;
236 if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
237 return GL_FALSE;
238
239 /* execute loop body */
240 A->flow.loop_start = cont_label;
241 A->flow.loop_end = break_label;
242 if (!_slang_assemble_operation_ (A, &op->children[3], slang_ref_forbid/*slang_ref_freelance*/))
243 return GL_FALSE;
244 if (!_slang_cleanup_stack_ (A, &op->children[3]))
245 return GL_FALSE;
246 A->flow = save_flow;
247
248 /* go to the beginning of the loop */
249 if (!slang_assembly_file_push_label (A->file, slang_asm_jump, cont_label))
250 return GL_FALSE;
251
252 /* resolve the end of the loop */
253 A->file->code[end_jump].param[0] = A->file->count;
254 A->file->code[cond_jump].param[0] = A->file->count;
255
256 return GL_TRUE;
257 }
258
259 /*
260 * _slang_assemble_do()
261 *
262 * do:
263 * jump start
264 * break:
265 * jump end
266 * continue:
267 * jump condition
268 * start:
269 * <loop-body>
270 * condition:
271 * <condition-statement>
272 * jumpz end
273 * jump start
274 * end:
275 */
276
277 GLboolean _slang_assemble_do (slang_assemble_ctx *A, slang_operation *op)
278 {
279 GLuint skip_jump, end_jump, cont_jump, cond_jump;
280 GLuint break_label, cont_label;
281 slang_assembly_flow_control save_flow = A->flow;
282
283 /* skip the "go to the end of the loop" and "go to condition" statements */
284 skip_jump = A->file->count;
285 if (!slang_assembly_file_push (A->file, slang_asm_jump))
286 return GL_FALSE;
287
288 /* go to the end of the loop - break statements are directed here */
289 break_label = A->file->count;
290 end_jump = A->file->count;
291 if (!slang_assembly_file_push (A->file, slang_asm_jump))
292 return GL_FALSE;
293
294 /* go to condition - continue statements are directed here */
295 cont_label = A->file->count;
296 cont_jump = A->file->count;
297 if (!slang_assembly_file_push (A->file, slang_asm_jump))
298 return GL_FALSE;
299
300 /* resolve the beginning of the loop */
301 A->file->code[skip_jump].param[0] = A->file->count;
302
303 /* execute loop body */
304 A->flow.loop_start = cont_label;
305 A->flow.loop_end = break_label;
306 if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/))
307 return GL_FALSE;
308 if (!_slang_cleanup_stack_ (A, &op->children[0]))
309 return GL_FALSE;
310 A->flow = save_flow;
311
312 /* resolve condition point */
313 A->file->code[cont_jump].param[0] = A->file->count;
314
315 /* execute condition statement */
316 if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid))
317 return GL_FALSE;
318
319 /* jump to the end of the loop if not true */
320 cond_jump = A->file->count;
321 if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
322 return GL_FALSE;
323
324 /* jump to the beginning of the loop */
325 if (!slang_assembly_file_push_label (A->file, slang_asm_jump, A->file->code[skip_jump].param[0]))
326 return GL_FALSE;
327
328 /* resolve the end of the loop */
329 A->file->code[end_jump].param[0] = A->file->count;
330 A->file->code[cond_jump].param[0] = A->file->count;
331
332 return GL_TRUE;
333 }
334
335 /*
336 * _slang_assemble_while()
337 *
338 * while:
339 * jump continue
340 * break:
341 * jump end
342 * continue:
343 * <condition-statement>
344 * jumpz end
345 * <loop-body>
346 * jump continue
347 * end:
348 */
349
350 GLboolean _slang_assemble_while (slang_assemble_ctx *A, slang_operation *op)
351 {
352 GLuint skip_jump, end_jump, cond_jump;
353 GLuint break_label;
354 slang_assembly_flow_control save_flow = A->flow;
355
356 /* skip the "go to the end of the loop" statement */
357 skip_jump = A->file->count;
358 if (!slang_assembly_file_push (A->file, slang_asm_jump))
359 return GL_FALSE;
360
361 /* go to the end of the loop - break statements are directed here */
362 break_label = A->file->count;
363 end_jump = A->file->count;
364 if (!slang_assembly_file_push (A->file, slang_asm_jump))
365 return GL_FALSE;
366
367 /* resolve the beginning of the loop - continue statements are directed here */
368 A->file->code[skip_jump].param[0] = A->file->count;
369
370 /* execute condition statement */
371 if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid))
372 return GL_FALSE;
373
374 /* jump to the end of the loop if not true */
375 cond_jump = A->file->count;
376 if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
377 return GL_FALSE;
378
379 /* execute loop body */
380 A->flow.loop_start = A->file->code[skip_jump].param[0];
381 A->flow.loop_end = break_label;
382 if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid/*slang_ref_freelance*/))
383 return GL_FALSE;
384 if (!_slang_cleanup_stack_ (A, &op->children[1]))
385 return GL_FALSE;
386 A->flow = save_flow;
387
388 /* jump to the beginning of the loop */
389 if (!slang_assembly_file_push_label (A->file, slang_asm_jump, A->file->code[skip_jump].param[0]))
390 return GL_FALSE;
391
392 /* resolve the end of the loop */
393 A->file->code[end_jump].param[0] = A->file->count;
394 A->file->code[cond_jump].param[0] = A->file->count;
395
396 return GL_TRUE;
397 }
398
399 /*
400 * _slang_assemble_if()
401 *
402 * if:
403 * <condition-statement>
404 * jumpz else
405 * <true-statement>
406 * jump end
407 * else:
408 * <false-statement>
409 * end:
410 */
411
412 GLboolean _slang_assemble_if (slang_assemble_ctx *A, slang_operation *op)
413 {
414 GLuint cond_jump, else_jump;
415
416 /* execute condition statement */
417 if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid))
418 return GL_FALSE;
419
420 /* jump to false-statement if not true */
421 cond_jump = A->file->count;
422 if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
423 return GL_FALSE;
424
425 /* execute true-statement */
426 if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid/*slang_ref_freelance*/))
427 return GL_FALSE;
428 if (!_slang_cleanup_stack_ (A, &op->children[1]))
429 return GL_FALSE;
430
431 /* skip if-false statement */
432 else_jump = A->file->count;
433 if (!slang_assembly_file_push (A->file, slang_asm_jump))
434 return GL_FALSE;
435
436 /* resolve start of false-statement */
437 A->file->code[cond_jump].param[0] = A->file->count;
438
439 /* execute false-statement */
440 if (!_slang_assemble_operation_ (A, &op->children[2], slang_ref_forbid/*slang_ref_freelance*/))
441 return GL_FALSE;
442 if (!_slang_cleanup_stack_ (A, &op->children[2]))
443 return GL_FALSE;
444
445 /* resolve end of if-false statement */
446 A->file->code[else_jump].param[0] = A->file->count;
447
448 return GL_TRUE;
449 }
450