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_utility.h"
33 #include "slang_assemble_conditional.h"
34 #include "slang_assemble.h"
35 #include "slang_execute.h"
38 * _slang_assemble_logicaland()
50 GLboolean
_slang_assemble_logicaland (slang_assemble_ctx
*A
, slang_operation
*op
)
52 GLuint zero_jump
, end_jump
;
54 /* evaluate left expression */
55 if (!_slang_assemble_operation_ (A
, &op
->children
[0], slang_ref_forbid
))
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
))
63 /* evaluate right expression */
64 if (!_slang_assemble_operation_ (A
, &op
->children
[1], slang_ref_forbid
))
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
))
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))
77 /* the end of the expression */
78 A
->file
->code
[end_jump
].param
[0] = A
->file
->count
;
84 * _slang_assemble_logicalor()
96 GLboolean
_slang_assemble_logicalor (slang_assemble_ctx
*A
, slang_operation
*op
)
98 GLuint right_jump
, end_jump
;
100 /* evaluate left expression */
101 if (!_slang_assemble_operation_ (A
, &op
->children
[0], slang_ref_forbid
))
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
))
109 /* push 1 on stack */
110 if (!slang_assembly_file_push_literal (A
->file
, slang_asm_bool_push
, (GLfloat
) 1))
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
))
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
))
123 /* the end of the expression */
124 A
->file
->code
[end_jump
].param
[0] = A
->file
->count
;
130 * _slang_assemble_select()
133 * <condition-expression>
142 GLboolean
_slang_assemble_select (slang_assemble_ctx
*A
, slang_operation
*op
)
144 GLuint cond_jump
, end_jump
;
146 /* execute condition expression */
147 if (!_slang_assemble_operation_ (A
, &op
->children
[0], slang_ref_forbid
))
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
))
155 /* execute true expression */
156 if (!_slang_assemble_operation_ (A
, &op
->children
[1], slang_ref_forbid
))
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
))
164 /* resolve false point */
165 A
->file
->code
[cond_jump
].param
[0] = A
->file
->count
;
167 /* execute false expression */
168 if (!_slang_assemble_operation_ (A
, &op
->children
[2], slang_ref_forbid
))
171 /* resolve the end of the expression */
172 A
->file
->code
[end_jump
].param
[0] = A
->file
->count
;
178 * _slang_assemble_for()
188 * <condition-statement>
195 GLboolean
_slang_assemble_for (slang_assemble_ctx
*A
, slang_operation
*op
)
197 GLuint start_jump
, end_jump
, cond_jump
;
198 GLuint break_label
, cont_label
;
199 slang_assembly_flow_control save_flow
= A
->flow
;
201 /* execute initialization statement */
202 if (!_slang_assemble_operation_ (A
, &op
->children
[0], slang_ref_forbid
/*slang_ref_freelance*/))
204 if (!_slang_cleanup_stack_ (A
, &op
->children
[0]))
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
))
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
))
218 /* resolve the beginning of the loop - continue statements are directed here */
219 cont_label
= A
->file
->count
;
221 /* execute loop-increment statement */
222 if (!_slang_assemble_operation_ (A
, &op
->children
[2], slang_ref_forbid
/*slang_ref_freelance*/))
224 if (!_slang_cleanup_stack_ (A
, &op
->children
[2]))
227 /* resolve the condition point */
228 A
->file
->code
[start_jump
].param
[0] = A
->file
->count
;
230 /* execute condition statement */
231 if (!_slang_assemble_operation_ (A
, &op
->children
[1], slang_ref_forbid
))
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
))
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*/))
244 if (!_slang_cleanup_stack_ (A
, &op
->children
[3]))
248 /* go to the beginning of the loop */
249 if (!slang_assembly_file_push_label (A
->file
, slang_asm_jump
, cont_label
))
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
;
260 * _slang_assemble_do()
271 * <condition-statement>
277 GLboolean
_slang_assemble_do (slang_assemble_ctx
*A
, slang_operation
*op
)
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
;
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
))
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
))
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
))
300 /* resolve the beginning of the loop */
301 A
->file
->code
[skip_jump
].param
[0] = A
->file
->count
;
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*/))
308 if (!_slang_cleanup_stack_ (A
, &op
->children
[0]))
312 /* resolve condition point */
313 A
->file
->code
[cont_jump
].param
[0] = A
->file
->count
;
315 /* execute condition statement */
316 if (!_slang_assemble_operation_ (A
, &op
->children
[1], slang_ref_forbid
))
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
))
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]))
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
;
336 * _slang_assemble_while()
343 * <condition-statement>
350 GLboolean
_slang_assemble_while (slang_assemble_ctx
*A
, slang_operation
*op
)
352 GLuint skip_jump
, end_jump
, cond_jump
;
354 slang_assembly_flow_control save_flow
= A
->flow
;
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
))
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
))
367 /* resolve the beginning of the loop - continue statements are directed here */
368 A
->file
->code
[skip_jump
].param
[0] = A
->file
->count
;
370 /* execute condition statement */
371 if (!_slang_assemble_operation_ (A
, &op
->children
[0], slang_ref_forbid
))
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
))
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*/))
384 if (!_slang_cleanup_stack_ (A
, &op
->children
[1]))
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]))
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
;
400 * _slang_assemble_if()
403 * <condition-statement>
412 GLboolean
_slang_assemble_if (slang_assemble_ctx
*A
, slang_operation
*op
)
414 GLuint cond_jump
, else_jump
;
416 /* execute condition statement */
417 if (!_slang_assemble_operation_ (A
, &op
->children
[0], slang_ref_forbid
))
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
))
425 /* execute true-statement */
426 if (!_slang_assemble_operation_ (A
, &op
->children
[1], slang_ref_forbid
/*slang_ref_freelance*/))
428 if (!_slang_cleanup_stack_ (A
, &op
->children
[1]))
431 /* skip if-false statement */
432 else_jump
= A
->file
->count
;
433 if (!slang_assembly_file_push (A
->file
, slang_asm_jump
))
436 /* resolve start of false-statement */
437 A
->file
->code
[cond_jump
].param
[0] = A
->file
->count
;
439 /* execute false-statement */
440 if (!_slang_assemble_operation_ (A
, &op
->children
[2], slang_ref_forbid
/*slang_ref_freelance*/))
442 if (!_slang_cleanup_stack_ (A
, &op
->children
[2]))
445 /* resolve end of if-false statement */
446 A
->file
->code
[else_jump
].param
[0] = A
->file
->count
;