2 * Mesa 3-D graphics library
5 * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
26 * \file slang_assemble_conditional.c
27 * slang condtional expressions assembler
32 #include "slang_assemble.h"
33 #include "slang_compile.h"
36 * _slang_assemble_logicaland()
48 GLboolean
_slang_assemble_logicaland (slang_assemble_ctx
*A
, slang_operation
*op
)
50 GLuint zero_jump
, end_jump
;
52 /* evaluate left expression */
53 if (!_slang_assemble_operation (A
, &op
->children
[0], slang_ref_forbid
))
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
))
61 /* evaluate right expression */
62 if (!_slang_assemble_operation (A
, &op
->children
[1], slang_ref_forbid
))
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
))
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))
75 /* the end of the expression */
76 A
->file
->code
[end_jump
].param
[0] = A
->file
->count
;
82 * _slang_assemble_logicalor()
94 GLboolean
_slang_assemble_logicalor (slang_assemble_ctx
*A
, slang_operation
*op
)
96 GLuint right_jump
, end_jump
;
98 /* evaluate left expression */
99 if (!_slang_assemble_operation (A
, &op
->children
[0], slang_ref_forbid
))
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
))
107 /* push 1 on stack */
108 if (!slang_assembly_file_push_literal (A
->file
, slang_asm_bool_push
, (GLfloat
) 1))
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
))
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
))
121 /* the end of the expression */
122 A
->file
->code
[end_jump
].param
[0] = A
->file
->count
;
128 * _slang_assemble_select()
131 * <condition-expression>
140 GLboolean
_slang_assemble_select (slang_assemble_ctx
*A
, slang_operation
*op
)
142 GLuint cond_jump
, end_jump
;
144 /* execute condition expression */
145 if (!_slang_assemble_operation (A
, &op
->children
[0], slang_ref_forbid
))
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
))
153 /* execute true expression */
154 if (!_slang_assemble_operation (A
, &op
->children
[1], slang_ref_forbid
))
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
))
162 /* resolve false point */
163 A
->file
->code
[cond_jump
].param
[0] = A
->file
->count
;
165 /* execute false expression */
166 if (!_slang_assemble_operation (A
, &op
->children
[2], slang_ref_forbid
))
169 /* resolve the end of the expression */
170 A
->file
->code
[end_jump
].param
[0] = A
->file
->count
;
176 * _slang_assemble_for()
186 * <condition-statement>
193 GLboolean
_slang_assemble_for (slang_assemble_ctx
*A
, slang_operation
*op
)
195 GLuint start_jump
, end_jump
, cond_jump
;
196 GLuint break_label
, cont_label
;
197 slang_assembly_flow_control save_flow
= A
->flow
;
199 /* execute initialization statement */
200 if (!_slang_assemble_operation (A
, &op
->children
[0], slang_ref_forbid
/*slang_ref_freelance*/))
202 if (!_slang_cleanup_stack (A
, &op
->children
[0]))
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
))
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
))
216 /* resolve the beginning of the loop - continue statements are directed here */
217 cont_label
= A
->file
->count
;
219 /* execute loop-increment statement */
220 if (!_slang_assemble_operation (A
, &op
->children
[2], slang_ref_forbid
/*slang_ref_freelance*/))
222 if (!_slang_cleanup_stack (A
, &op
->children
[2]))
225 /* resolve the condition point */
226 A
->file
->code
[start_jump
].param
[0] = A
->file
->count
;
228 /* execute condition statement */
229 if (!_slang_assemble_operation (A
, &op
->children
[1], slang_ref_forbid
))
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
))
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*/))
242 if (!_slang_cleanup_stack (A
, &op
->children
[3]))
246 /* go to the beginning of the loop */
247 if (!slang_assembly_file_push_label (A
->file
, slang_asm_jump
, cont_label
))
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
;
258 * _slang_assemble_do()
269 * <condition-statement>
275 GLboolean
_slang_assemble_do (slang_assemble_ctx
*A
, slang_operation
*op
)
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
;
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
))
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
))
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
))
298 /* resolve the beginning of the loop */
299 A
->file
->code
[skip_jump
].param
[0] = A
->file
->count
;
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*/))
306 if (!_slang_cleanup_stack (A
, &op
->children
[0]))
310 /* resolve condition point */
311 A
->file
->code
[cont_jump
].param
[0] = A
->file
->count
;
313 /* execute condition statement */
314 if (!_slang_assemble_operation (A
, &op
->children
[1], slang_ref_forbid
))
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
))
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]))
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
;
334 * _slang_assemble_while()
341 * <condition-statement>
348 GLboolean
_slang_assemble_while (slang_assemble_ctx
*A
, slang_operation
*op
)
350 GLuint skip_jump
, end_jump
, cond_jump
;
352 slang_assembly_flow_control save_flow
= A
->flow
;
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
))
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
))
365 /* resolve the beginning of the loop - continue statements are directed here */
366 A
->file
->code
[skip_jump
].param
[0] = A
->file
->count
;
368 /* execute condition statement */
369 if (!_slang_assemble_operation (A
, &op
->children
[0], slang_ref_forbid
))
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
))
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*/))
382 if (!_slang_cleanup_stack (A
, &op
->children
[1]))
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]))
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
;
398 * _slang_assemble_if()
401 * <condition-statement>
410 GLboolean
_slang_assemble_if (slang_assemble_ctx
*A
, slang_operation
*op
)
412 GLuint cond_jump
, else_jump
;
414 /* execute condition statement */
415 if (!_slang_assemble_operation (A
, &op
->children
[0], slang_ref_forbid
))
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
))
423 /* execute true-statement */
424 if (!_slang_assemble_operation (A
, &op
->children
[1], slang_ref_forbid
/*slang_ref_freelance*/))
426 if (!_slang_cleanup_stack (A
, &op
->children
[1]))
429 /* skip if-false statement */
430 else_jump
= A
->file
->count
;
431 if (!slang_assembly_file_push (A
->file
, slang_asm_jump
))
434 /* resolve start of false-statement */
435 A
->file
->code
[cond_jump
].param
[0] = A
->file
->count
;
437 /* execute false-statement */
438 if (!_slang_assemble_operation (A
, &op
->children
[2], slang_ref_forbid
/*slang_ref_freelance*/))
440 if (!_slang_cleanup_stack (A
, &op
->children
[2]))
443 /* resolve end of if-false statement */
444 A
->file
->code
[else_jump
].param
[0] = A
->file
->count
;