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