More GLSL code.
[mesa.git] / src / mesa / shader / slang / slang_assemble.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.c
27 * slang intermediate code assembler
28 * \author Michal Krol
29 */
30
31 #include "imports.h"
32 #include "slang_utility.h"
33 #include "slang_assemble.h"
34 #include "slang_storage.h"
35 #include "slang_assemble_typeinfo.h"
36 #include "slang_assemble_conditional.h"
37 #include "slang_assemble_assignment.h"
38 #include "slang_execute.h"
39
40 /* slang_assembly */
41
42 static GLboolean slang_assembly_construct (slang_assembly *assem)
43 {
44 assem->type = slang_asm_none;
45 return GL_TRUE;
46 }
47
48 static GLvoid slang_assembly_destruct (slang_assembly *assem)
49 {
50 }
51
52 /* slang_assembly_file */
53
54 GLboolean slang_assembly_file_construct (slang_assembly_file *file)
55 {
56 file->code = NULL;
57 file->count = 0;
58 file->capacity = 0;
59 return GL_TRUE;
60 }
61
62 GLvoid slang_assembly_file_destruct (slang_assembly_file *file)
63 {
64 GLuint i;
65
66 for (i = 0; i < file->count; i++)
67 slang_assembly_destruct (&file->code[i]);
68 slang_alloc_free (file->code);
69 }
70
71 static GLboolean push_new (slang_assembly_file *file)
72 {
73 if (file->count == file->capacity)
74 {
75 GLuint n;
76
77 if (file->capacity == 0)
78 n = 256;
79 else
80 n = file->capacity * 2;
81 file->code = (slang_assembly *) slang_alloc_realloc (file->code,
82 file->capacity * sizeof (slang_assembly), n * sizeof (slang_assembly));
83 if (file->code == NULL)
84 return GL_FALSE;
85 file->capacity = n;
86 }
87 if (!slang_assembly_construct (&file->code[file->count]))
88 return GL_FALSE;
89 file->count++;
90 return GL_TRUE;
91 }
92
93 static GLboolean push_gen (slang_assembly_file *file, slang_assembly_type type, GLfloat literal,
94 GLuint label, GLuint size)
95 {
96 slang_assembly *assem;
97
98 if (!push_new (file))
99 return GL_FALSE;
100 assem = &file->code[file->count - 1];
101 assem->type = type;
102 assem->literal = literal;
103 assem->param[0] = label;
104 assem->param[1] = size;
105 return GL_TRUE;
106 }
107
108 GLboolean slang_assembly_file_push (slang_assembly_file *file, slang_assembly_type type)
109 {
110 return push_gen (file, type, (GLfloat) 0, 0, 0);
111 }
112
113 GLboolean slang_assembly_file_push_label (slang_assembly_file *file, slang_assembly_type type,
114 GLuint label)
115 {
116 return push_gen (file, type, (GLfloat) 0, label, 0);
117 }
118
119 GLboolean slang_assembly_file_push_label2 (slang_assembly_file *file, slang_assembly_type type,
120 GLuint label1, GLuint label2)
121 {
122 return push_gen (file, type, (GLfloat) 0, label1, label2);
123 }
124
125 GLboolean slang_assembly_file_push_literal (slang_assembly_file *file, slang_assembly_type type,
126 GLfloat literal)
127 {
128 return push_gen (file, type, literal, 0, 0);
129 }
130
131 #define PUSH slang_assembly_file_push
132 #define PLAB slang_assembly_file_push_label
133 #define PLAB2 slang_assembly_file_push_label2
134 #define PLIT slang_assembly_file_push_literal
135
136 /* slang_assembly_file_restore_point */
137
138 GLboolean slang_assembly_file_restore_point_save (slang_assembly_file *file,
139 slang_assembly_file_restore_point *point)
140 {
141 point->count = file->count;
142 return GL_TRUE;
143 }
144
145 GLboolean slang_assembly_file_restore_point_load (slang_assembly_file *file,
146 slang_assembly_file_restore_point *point)
147 {
148 GLuint i;
149
150 for (i = point->count; i < file->count; i++)
151 slang_assembly_destruct (&file->code[i]);
152 file->count = point->count;
153 return GL_TRUE;
154 }
155
156 /* utility functions */
157
158 static GLboolean sizeof_variable (slang_assemble_ctx *A, slang_type_specifier *spec,
159 slang_type_qualifier qual, slang_operation *array_size, GLuint *size)
160 {
161 slang_storage_aggregate agg;
162
163 /* calculate the size of the variable's aggregate */
164 if (!slang_storage_aggregate_construct (&agg))
165 return GL_FALSE;
166 if (!_slang_aggregate_variable (&agg, spec, array_size, A->space.funcs, A->space.structs,
167 A->space.vars, A->mach, A->file, A->atoms))
168 {
169 slang_storage_aggregate_destruct (&agg);
170 return GL_FALSE;
171 }
172 *size += _slang_sizeof_aggregate (&agg);
173 slang_storage_aggregate_destruct (&agg);
174
175 /* for reference variables consider the additional address overhead */
176 if (qual == slang_qual_out || qual == slang_qual_inout)
177 *size += 4;
178
179 return GL_TRUE;
180 }
181
182 static GLboolean sizeof_variable2 (slang_assemble_ctx *A, slang_variable *var, GLuint *size)
183 {
184 var->address = *size;
185 if (var->type.qualifier == slang_qual_out || var->type.qualifier == slang_qual_inout)
186 var->address += 4;
187 return sizeof_variable (A, &var->type.specifier, var->type.qualifier, var->array_size, size);
188 }
189
190 static GLboolean sizeof_variables (slang_assemble_ctx *A, slang_variable_scope *vars, GLuint start,
191 GLuint stop, GLuint *size)
192 {
193 GLuint i;
194
195 for (i = start; i < stop; i++)
196 if (!sizeof_variable2 (A, &vars->variables[i], size))
197 return GL_FALSE;
198 return GL_TRUE;
199 }
200
201 static GLboolean collect_locals (slang_assemble_ctx *A, slang_operation *op, GLuint *size)
202 {
203 GLuint i;
204
205 if (!sizeof_variables (A, op->locals, 0, op->locals->num_variables, size))
206 return GL_FALSE;
207 for (i = 0; i < op->num_children; i++)
208 if (!collect_locals (A, &op->children[i], size))
209 return GL_FALSE;
210 return GL_TRUE;
211 }
212
213 /* _slang_locate_function() */
214
215 slang_function *_slang_locate_function (slang_function_scope *funcs, slang_atom a_name,
216 slang_operation *params, GLuint num_params, slang_assembly_name_space *space,
217 slang_atom_pool *atoms)
218 {
219 GLuint i;
220
221 for (i = 0; i < funcs->num_functions; i++)
222 {
223 GLuint j;
224 slang_function *f = &funcs->functions[i];
225
226 if (a_name != f->header.a_name)
227 continue;
228 if (f->param_count != num_params)
229 continue;
230 for (j = 0; j < num_params; j++)
231 {
232 slang_assembly_typeinfo ti;
233
234 if (!slang_assembly_typeinfo_construct (&ti))
235 return NULL;
236 if (!_slang_typeof_operation (&params[j], space, &ti, atoms))
237 {
238 slang_assembly_typeinfo_destruct (&ti);
239 return NULL;
240 }
241 if (!slang_type_specifier_equal (&ti.spec, &f->parameters->variables[j].type.specifier))
242 {
243 slang_assembly_typeinfo_destruct (&ti);
244 break;
245 }
246 slang_assembly_typeinfo_destruct (&ti);
247
248 /* "out" and "inout" formal parameter requires the actual parameter to be l-value */
249 if (!ti.can_be_referenced &&
250 (f->parameters->variables[j].type.qualifier == slang_qual_out ||
251 f->parameters->variables[j].type.qualifier == slang_qual_inout))
252 break;
253 }
254 if (j == num_params)
255 return f;
256 }
257 if (funcs->outer_scope != NULL)
258 return _slang_locate_function (funcs->outer_scope, a_name, params, num_params, space, atoms);
259 return NULL;
260 }
261
262 /* _slang_assemble_function() */
263
264 GLboolean _slang_assemble_function (slang_assemble_ctx *A, slang_function *fun)
265 {
266 GLuint param_size, local_size;
267 GLuint skip, cleanup;
268
269 fun->address = A->file->count;
270
271 if (fun->body == NULL)
272 {
273 /* jump to the actual function body - we do not know it, so add the instruction
274 * to fixup table */
275 fun->fixups.table = (GLuint *) slang_alloc_realloc (fun->fixups.table,
276 fun->fixups.count * sizeof (GLuint), (fun->fixups.count + 1) * sizeof (GLuint));
277 if (fun->fixups.table == NULL)
278 return GL_FALSE;
279 fun->fixups.table[fun->fixups.count] = fun->address;
280 fun->fixups.count++;
281 if (!PUSH (A->file, slang_asm_jump))
282 return GL_FALSE;
283 return GL_TRUE;
284 }
285 else
286 {
287 GLuint i;
288
289 /* resolve all fixup table entries and delete it */
290 for (i = 0; i < fun->fixups.count; i++)
291 A->file->code[fun->fixups.table[i]].param[0] = fun->address;
292 slang_fixup_table_free (&fun->fixups);
293 }
294
295 /* At this point traverse function formal parameters and code to calculate
296 * total memory size to be allocated on the stack.
297 * During this process the variables will be assigned local addresses to
298 * reference them in the code.
299 * No storage optimizations are performed so exclusive scopes are not detected and shared. */
300
301 /* calculate return value size */
302 param_size = 0;
303 if (fun->header.type.specifier.type != slang_spec_void)
304 if (!sizeof_variable (A, &fun->header.type.specifier, slang_qual_none, NULL, &param_size))
305 return GL_FALSE;
306 A->local.ret_size = param_size;
307
308 /* calculate formal parameter list size */
309 if (!sizeof_variables (A, fun->parameters, 0, fun->param_count, &param_size))
310 return GL_FALSE;
311
312 /* calculate local variables size - take into account the four-byte return address and
313 * temporaries for various tasks (4 for addr and 16 for swizzle temporaries).
314 * these include variables from the formal parameter scope and from the code */
315 A->local.addr_tmp = param_size + 4;
316 A->local.swizzle_tmp = param_size + 4 + 4;
317 local_size = param_size + 4 + 4 + 16;
318 if (!sizeof_variables (A, fun->parameters, fun->param_count, fun->parameters->num_variables,
319 &local_size))
320 return GL_FALSE;
321 if (!collect_locals (A, fun->body, &local_size))
322 return GL_FALSE;
323
324 /* allocate local variable storage */
325 if (!PLAB (A->file, slang_asm_local_alloc, local_size - param_size - 4))
326 return GL_FALSE;
327
328 /* mark a new frame for function variable storage */
329 if (!PLAB (A->file, slang_asm_enter, local_size))
330 return GL_FALSE;
331
332 /* jump directly to the actual code */
333 skip = A->file->count;
334 if (!push_new (A->file))
335 return GL_FALSE;
336 A->file->code[skip].type = slang_asm_jump;
337
338 /* all "return" statements will be directed here */
339 A->flow.function_end = A->file->count;
340 cleanup = A->file->count;
341 if (!push_new (A->file))
342 return GL_FALSE;
343 A->file->code[cleanup].type = slang_asm_jump;
344
345 /* execute the function body */
346 A->file->code[skip].param[0] = A->file->count;
347 if (!_slang_assemble_operation_ (A, fun->body, /*slang_ref_freelance*/slang_ref_forbid))
348 return GL_FALSE;
349
350 /* this is the end of the function - restore the old function frame */
351 A->file->code[cleanup].param[0] = A->file->count;
352 if (!PUSH (A->file, slang_asm_leave))
353 return GL_FALSE;
354
355 /* free local variable storage */
356 if (!PLAB (A->file, slang_asm_local_free, local_size - param_size - 4))
357 return GL_FALSE;
358
359 /* return from the function */
360 if (!PUSH (A->file, slang_asm_return))
361 return GL_FALSE;
362
363 return GL_TRUE;
364 }
365
366 GLboolean _slang_cleanup_stack_ (slang_assemble_ctx *A, slang_operation *op)
367 {
368 slang_assembly_typeinfo ti;
369 GLuint size = 0;
370
371 /* get type info of the operation and calculate its size */
372 if (!slang_assembly_typeinfo_construct (&ti))
373 return GL_FALSE;
374 if (!_slang_typeof_operation (op, &A->space, &ti, A->atoms))
375 {
376 slang_assembly_typeinfo_destruct (&ti);
377 return GL_FALSE;
378 }
379 if (ti.spec.type != slang_spec_void)
380 if (A->ref == slang_ref_force)
381 size = 4;
382 else if (!sizeof_variable (A, &ti.spec, slang_qual_none, NULL, &size))
383 {
384 slang_assembly_typeinfo_destruct (&ti);
385 return GL_FALSE;
386 }
387 slang_assembly_typeinfo_destruct (&ti);
388
389 /* if nonzero, free it from the stack */
390 if (size != 0)
391 {
392 if (!PLAB (A->file, slang_asm_local_free, size))
393 return GL_FALSE;
394 }
395
396 return GL_TRUE;
397 }
398
399 /* _slang_assemble_operation() */
400
401 static GLboolean dereference_aggregate (slang_assemble_ctx *A, const slang_storage_aggregate *agg,
402 GLuint *size, slang_swizzle *swz, GLboolean is_swizzled)
403 {
404 GLuint i;
405
406 for (i = agg->count; i > 0; i--)
407 {
408 const slang_storage_array *arr = &agg->arrays[i - 1];
409 GLuint j;
410
411 for (j = arr->length; j > 0; j--)
412 {
413 if (arr->type == slang_stor_aggregate)
414 {
415 if (!dereference_aggregate (A, arr->aggregate, size, swz, is_swizzled))
416 return GL_FALSE;
417 }
418 else
419 {
420 GLuint src_offset;
421 slang_assembly_type ty;
422
423 *size -= 4;
424
425 /* calculate the offset within source variable to read */
426 if (is_swizzled)
427 {
428 /* swizzle the index to get the actual offset */
429 src_offset = swz->swizzle[*size / 4] * 4;
430 }
431 else
432 {
433 /* no swizzling - read sequentially */
434 src_offset = *size;
435 }
436
437 /* dereference data slot of a basic type */
438 if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4))
439 return GL_FALSE;
440 if (!PUSH (A->file, slang_asm_addr_deref))
441 return GL_FALSE;
442 if (!PLAB (A->file, slang_asm_addr_push, src_offset))
443 return GL_FALSE;
444 if (!PUSH (A->file, slang_asm_addr_add))
445 return GL_FALSE;
446
447 switch (arr->type)
448 {
449 case slang_stor_bool:
450 ty = slang_asm_bool_deref;
451 break;
452 case slang_stor_int:
453 ty = slang_asm_int_deref;
454 break;
455 case slang_stor_float:
456 ty = slang_asm_float_deref;
457 break;
458 default:
459 _mesa_problem(NULL, "Unexpected arr->type in dereference_aggregate");
460 ty = slang_asm_none;
461 }
462 if (!PUSH (A->file, ty))
463 return GL_FALSE;
464 }
465 }
466 }
467
468 return GL_TRUE;
469 }
470
471 GLboolean _slang_dereference (slang_assemble_ctx *A, slang_operation *op)
472 {
473 slang_assembly_typeinfo ti;
474 GLboolean result = GL_FALSE;
475 slang_storage_aggregate agg;
476 GLuint size;
477
478 /* get type information of the given operation */
479 if (!slang_assembly_typeinfo_construct (&ti))
480 return GL_FALSE;
481 if (!_slang_typeof_operation (op, &A->space, &ti, A->atoms))
482 goto end1;
483
484 /* construct aggregate from the type info */
485 if (!slang_storage_aggregate_construct (&agg))
486 goto end1;
487 if (!_slang_aggregate_variable (&agg, &ti.spec, ti.array_size, A->space.funcs, A->space.structs,
488 A->space.vars, A->mach, A->file, A->atoms))
489 goto end;
490
491 /* dereference the resulting aggregate */
492 size = _slang_sizeof_aggregate (&agg);
493 result = dereference_aggregate (A, &agg, &size, &ti.swz, ti.is_swizzled);
494
495 end:
496 slang_storage_aggregate_destruct (&agg);
497 end1:
498 slang_assembly_typeinfo_destruct (&ti);
499 return result;
500 }
501
502 GLboolean _slang_assemble_function_call (slang_assemble_ctx *A, slang_function *fun,
503 slang_operation *params, GLuint param_count, GLboolean assignment)
504 {
505 GLuint i;
506 slang_swizzle p_swz[64];
507 slang_ref_type p_ref[64];
508
509 /* TODO: fix this, allocate dynamically */
510 if (param_count > 64)
511 return GL_FALSE;
512
513 /* make room for the return value, if any */
514 if (fun->header.type.specifier.type != slang_spec_void)
515 {
516 GLuint ret_size = 0;
517
518 if (!sizeof_variable (A, &fun->header.type.specifier, slang_qual_none, NULL, &ret_size))
519 return GL_FALSE;
520 if (!PLAB (A->file, slang_asm_local_alloc, ret_size))
521 return GL_FALSE;
522 }
523
524 /* push the actual parameters on the stack */
525 for (i = 0; i < param_count; i++)
526 {
527 if (fun->parameters->variables[i].type.qualifier == slang_qual_inout ||
528 fun->parameters->variables[i].type.qualifier == slang_qual_out)
529 {
530 if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4))
531 return GL_FALSE;
532 /* TODO: optimize the "out" parameter case */
533 if (!_slang_assemble_operation_ (A, &params[i], slang_ref_force))
534 return GL_FALSE;
535 p_swz[i] = A->swz;
536 p_ref[i] = A->ref;
537 if (!PUSH (A->file, slang_asm_addr_copy))
538 return GL_FALSE;
539 if (!PUSH (A->file, slang_asm_addr_deref))
540 return GL_FALSE;
541 if (i == 0 && assignment)
542 {
543 /* duplicate the resulting address */
544 if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4))
545 return GL_FALSE;
546 if (!PUSH (A->file, slang_asm_addr_deref))
547 return GL_FALSE;
548 }
549 if (!_slang_dereference (A, &params[i]))
550 return GL_FALSE;
551 }
552 else
553 {
554 if (!_slang_assemble_operation_ (A, &params[i], slang_ref_forbid))
555 return GL_FALSE;
556 p_swz[i] = A->swz;
557 p_ref[i] = A->ref;
558 }
559 }
560
561 /* call the function */
562 if (!PLAB (A->file, slang_asm_call, fun->address))
563 return GL_FALSE;
564
565 /* pop the parameters from the stack */
566 for (i = param_count; i > 0; i--)
567 {
568 GLuint j = i - 1;
569
570 A->swz = p_swz[j];
571 A->ref = p_ref[j];
572 if (fun->parameters->variables[j].type.qualifier == slang_qual_inout ||
573 fun->parameters->variables[j].type.qualifier == slang_qual_out)
574 {
575 /* for output parameter copy the contents of the formal parameter
576 * back to the original actual parameter */
577 if (!_slang_assemble_assignment (A, &params[j]))
578 return GL_FALSE;
579 /* pop the actual parameter's address */
580 if (!PLAB (A->file, slang_asm_local_free, 4))
581 return GL_FALSE;
582 }
583 else
584 {
585 /* pop the value of the parameter */
586 if (!_slang_cleanup_stack_ (A, &params[j]))
587 return GL_FALSE;
588 }
589 }
590
591 return GL_TRUE;
592 }
593
594 GLboolean _slang_assemble_function_call_name (slang_assemble_ctx *A, const char *name,
595 slang_operation *params, GLuint param_count, GLboolean assignment)
596 {
597 slang_atom atom;
598 slang_function *fun;
599
600 atom = slang_atom_pool_atom (A->atoms, name);
601 if (atom == SLANG_ATOM_NULL)
602 return GL_FALSE;
603 fun = _slang_locate_function (A->space.funcs, atom, params, param_count, &A->space, A->atoms);
604 if (fun == NULL)
605 return GL_FALSE;
606 return _slang_assemble_function_call (A, fun, params, param_count, assignment);
607 }
608
609 static GLboolean assemble_function_call_name_dummyint (slang_assemble_ctx *A, const char *name,
610 slang_operation *params)
611 {
612 slang_operation p[2];
613 GLboolean result;
614
615 p[0] = params[0];
616 if (!slang_operation_construct (&p[1]))
617 return GL_FALSE;
618 p[1].type = slang_oper_literal_int;
619 result = _slang_assemble_function_call_name (A, name, p, 2, GL_FALSE);
620 slang_operation_destruct (&p[1]);
621 return result;
622 }
623
624 static const struct
625 {
626 const char *name;
627 slang_assembly_type code1, code2;
628 } inst[] = {
629 /* core */
630 { "float_add", slang_asm_float_add, slang_asm_float_copy },
631 { "float_multiply", slang_asm_float_multiply, slang_asm_float_copy },
632 { "float_divide", slang_asm_float_divide, slang_asm_float_copy },
633 { "float_negate", slang_asm_float_negate, slang_asm_float_copy },
634 { "float_less", slang_asm_float_less, slang_asm_bool_copy },
635 { "float_equal", slang_asm_float_equal_exp,slang_asm_bool_copy },
636 { "float_to_int", slang_asm_float_to_int, slang_asm_int_copy },
637 { "float_sine", slang_asm_float_sine, slang_asm_float_copy },
638 { "float_arcsine", slang_asm_float_arcsine, slang_asm_float_copy },
639 { "float_arctan", slang_asm_float_arctan, slang_asm_float_copy },
640 { "float_power", slang_asm_float_power, slang_asm_float_copy },
641 { "float_log2", slang_asm_float_log2, slang_asm_float_copy },
642 { "float_floor", slang_asm_float_floor, slang_asm_float_copy },
643 { "float_ceil", slang_asm_float_ceil, slang_asm_float_copy },
644 { "float_noise1", slang_asm_float_noise1, slang_asm_float_copy },
645 { "float_noise2", slang_asm_float_noise2, slang_asm_float_copy },
646 { "float_noise3", slang_asm_float_noise3, slang_asm_float_copy },
647 { "float_noise4", slang_asm_float_noise4, slang_asm_float_copy },
648 { "int_to_float", slang_asm_int_to_float, slang_asm_float_copy },
649 /* mesa-specific extensions */
650 { "float_print", slang_asm_float_deref, slang_asm_float_print },
651 { "int_print", slang_asm_int_deref, slang_asm_int_print },
652 { "bool_print", slang_asm_bool_deref, slang_asm_bool_print },
653 { NULL, slang_asm_none, slang_asm_none }
654 };
655
656 static GLboolean call_asm_instruction (slang_assemble_ctx *A, slang_atom a_name)
657 {
658 const char *id;
659 GLuint i;
660
661 id = slang_atom_pool_id (A->atoms, a_name);
662
663 for (i = 0; inst[i].name != NULL; i++)
664 if (slang_string_compare (id, inst[i].name) == 0)
665 break;
666 if (inst[i].name == NULL)
667 return GL_FALSE;
668
669 if (!PLAB2 (A->file, inst[i].code1, 4, 0))
670 return GL_FALSE;
671 if (inst[i].code2 != slang_asm_none)
672 if (!PLAB2 (A->file, inst[i].code2, 4, 0))
673 return GL_FALSE;
674
675 /* clean-up the stack from the remaining dst address */
676 if (!PLAB (A->file, slang_asm_local_free, 4))
677 return GL_FALSE;
678
679 return GL_TRUE;
680 }
681
682 static GLboolean equality_aggregate (slang_assemble_ctx *A, const slang_storage_aggregate *agg,
683 GLuint *index, GLuint size, GLuint z_label)
684 {
685 GLuint i;
686
687 for (i = 0; i < agg->count; i++)
688 {
689 const slang_storage_array *arr = &agg->arrays[i];
690 GLuint j;
691
692 for (j = 0; j < arr->length; j++)
693 {
694 if (arr->type == slang_stor_aggregate)
695 {
696 if (!equality_aggregate (A, arr->aggregate, index, size, z_label))
697 return GL_FALSE;
698 }
699 else
700 {
701 if (!PLAB2 (A->file, slang_asm_float_equal_int, size + *index, *index))
702 return GL_FALSE;
703 *index += 4;
704 if (!PLAB (A->file, slang_asm_jump_if_zero, z_label))
705 return GL_FALSE;
706 }
707 }
708 }
709
710 return GL_TRUE;
711 }
712
713 static GLboolean equality (slang_assemble_ctx *A, slang_operation *op, GLboolean equal)
714 {
715 slang_assembly_typeinfo ti;
716 GLboolean result = GL_FALSE;
717 slang_storage_aggregate agg;
718 GLuint index, size;
719 GLuint skip_jump, true_label, true_jump, false_label, false_jump;
720
721 /* get type of operation */
722 if (!slang_assembly_typeinfo_construct (&ti))
723 return GL_FALSE;
724 if (!_slang_typeof_operation (op, &A->space, &ti, A->atoms))
725 goto end1;
726
727 /* convert it to an aggregate */
728 if (!slang_storage_aggregate_construct (&agg))
729 goto end1;
730 if (!_slang_aggregate_variable (&agg, &ti.spec, NULL, A->space.funcs, A->space.structs,
731 A->space.vars, A->mach, A->file, A->atoms))
732 goto end;
733
734 /* compute the size of the agregate - there are two such aggregates on the stack */
735 size = _slang_sizeof_aggregate (&agg);
736
737 /* jump to the actual data-comparison code */
738 skip_jump = A->file->count;
739 if (!PUSH (A->file, slang_asm_jump))
740 goto end;
741
742 /* pop off the stack the compared data and push 1 */
743 true_label = A->file->count;
744 if (!PLAB (A->file, slang_asm_local_free, size * 2))
745 goto end;
746 if (!PLIT (A->file, slang_asm_bool_push, (GLfloat) 1))
747 goto end;
748 true_jump = A->file->count;
749 if (!PUSH (A->file, slang_asm_jump))
750 goto end;
751
752 false_label = A->file->count;
753 if (!PLAB (A->file, slang_asm_local_free, size * 2))
754 goto end;
755 if (!PLIT (A->file, slang_asm_bool_push, (GLfloat) 0))
756 goto end;
757 false_jump = A->file->count;
758 if (!PUSH (A->file, slang_asm_jump))
759 goto end;
760
761 A->file->code[skip_jump].param[0] = A->file->count;
762
763 /* compare the data on stack, it will eventually jump either to true or false label */
764 index = 0;
765 if (!equality_aggregate (A, &agg, &index, size, equal ? false_label : true_label))
766 goto end;
767 if (!PLAB (A->file, slang_asm_jump, equal ? true_label : false_label))
768 goto end;
769
770 A->file->code[true_jump].param[0] = A->file->count;
771 A->file->code[false_jump].param[0] = A->file->count;
772
773 result = GL_TRUE;
774 end:
775 slang_storage_aggregate_destruct (&agg);
776 end1:
777 slang_assembly_typeinfo_destruct (&ti);
778 return result;
779 }
780
781 static GLboolean handle_subscript (slang_assemble_ctx *A, slang_assembly_typeinfo *tie,
782 slang_assembly_typeinfo *tia, slang_operation *op, slang_ref_type ref)
783 {
784 GLuint asize = 0, esize = 0;
785
786 /* get type info of the master expression (matrix, vector or an array */
787 if (!_slang_typeof_operation (&op->children[0], &A->space, tia, A->atoms))
788 return GL_FALSE;
789 if (!sizeof_variable (A, &tia->spec, slang_qual_none, tia->array_size, &asize))
790 return GL_FALSE;
791
792 /* get type info of the result (matrix column, vector row or array element) */
793 if (!_slang_typeof_operation (op, &A->space, tie, A->atoms))
794 return GL_FALSE;
795 if (!sizeof_variable (A, &tie->spec, slang_qual_none, NULL, &esize))
796 return GL_FALSE;
797
798 /* assemble the master expression */
799 if (!_slang_assemble_operation_ (A, &op->children[0], ref))
800 return GL_FALSE;
801
802 /* when indexing an l-value swizzle, push the swizzle_tmp */
803 if (ref == slang_ref_force && tia->is_swizzled)
804 if (!PLAB2 (A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16))
805 return GL_FALSE;
806
807 /* assemble the subscript expression */
808 if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid))
809 return GL_FALSE;
810
811 if (ref == slang_ref_force && tia->is_swizzled)
812 {
813 GLuint i;
814
815 /* copy the swizzle indexes to the swizzle_tmp */
816 for (i = 0; i < tia->swz.num_components; i++)
817 {
818 if (!PLAB2 (A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16))
819 return GL_FALSE;
820 if (!PLAB (A->file, slang_asm_addr_push, i * 4))
821 return GL_FALSE;
822 if (!PUSH (A->file, slang_asm_addr_add))
823 return GL_FALSE;
824 if (!PLAB (A->file, slang_asm_addr_push, tia->swz.swizzle[i]))
825 return GL_FALSE;
826 if (!PUSH (A->file, slang_asm_addr_copy))
827 return GL_FALSE;
828 if (!PLAB (A->file, slang_asm_local_free, 4))
829 return GL_FALSE;
830 }
831
832 /* offset the pushed swizzle_tmp address and dereference it */
833 if (!PUSH (A->file, slang_asm_int_to_addr))
834 return GL_FALSE;
835 if (!PLAB (A->file, slang_asm_addr_push, 4))
836 return GL_FALSE;
837 if (!PUSH (A->file, slang_asm_addr_multiply))
838 return GL_FALSE;
839 if (!PUSH (A->file, slang_asm_addr_add))
840 return GL_FALSE;
841 if (!PUSH (A->file, slang_asm_addr_deref))
842 return GL_FALSE;
843 }
844 else
845 {
846 /* convert the integer subscript to a relative address */
847 if (!PUSH (A->file, slang_asm_int_to_addr))
848 return GL_FALSE;
849 }
850
851 if (!PLAB (A->file, slang_asm_addr_push, esize))
852 return GL_FALSE;
853 if (!PUSH (A->file, slang_asm_addr_multiply))
854 return GL_FALSE;
855
856 if (ref == slang_ref_force)
857 {
858 /* offset the base address with the relative address */
859 if (!PUSH (A->file, slang_asm_addr_add))
860 return GL_FALSE;
861 }
862 else
863 {
864 GLuint i;
865
866 /* move the selected element to the beginning of the master expression */
867 for (i = 0; i < esize; i += 4)
868 if (!PLAB2 (A->file, slang_asm_float_move, asize - esize + i + 4, i + 4))
869 return GL_FALSE;
870 if (!PLAB (A->file, slang_asm_local_free, 4))
871 return GL_FALSE;
872
873 /* free the rest of the master expression */
874 if (!PLAB (A->file, slang_asm_local_free, asize - esize))
875 return GL_FALSE;
876 }
877
878 return GL_TRUE;
879 }
880
881 static GLboolean handle_field (slang_assemble_ctx *A, slang_assembly_typeinfo *tia,
882 slang_assembly_typeinfo *tib, slang_operation *op, slang_ref_type ref)
883 {
884 /* get type info of the result (field or swizzle) */
885 if (!_slang_typeof_operation (op, &A->space, tia, A->atoms))
886 return GL_FALSE;
887
888 /* get type info of the master expression being accessed (struct or vector) */
889 if (!_slang_typeof_operation (&op->children[0], &A->space, tib, A->atoms))
890 return GL_FALSE;
891
892 /* if swizzling a vector in-place, the swizzle temporary is needed */
893 if (ref == slang_ref_forbid && tia->is_swizzled)
894 if (!PLAB2 (A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16))
895 return GL_FALSE;
896
897 /* assemble the master expression */
898 if (!_slang_assemble_operation_ (A, &op->children[0], ref))
899 return GL_FALSE;
900
901 /* assemble the field expression */
902 if (tia->is_swizzled)
903 {
904 if (ref == slang_ref_force)
905 {
906 #if 0
907 if (tia->swz.num_components == 1)
908 {
909 /* simple case - adjust the vector's address to point to the selected component */
910 if (!PLAB (file, slang_asm_addr_push, tia->swz.swizzle[0] * 4))
911 return 0;
912 if (!PUSH (file, slang_asm_addr_add))
913 return 0;
914 }
915 else
916 #endif
917 {
918 /* two or more vector components are being referenced - the so-called write mask
919 * must be passed to the upper operations and applied when assigning value
920 * to this swizzle */
921 A->swz = tia->swz;
922 }
923 }
924 else
925 {
926 /* swizzle the vector in-place using the swizzle temporary */
927 if (!_slang_assemble_constructor_from_swizzle (A, &tia->swz, &tia->spec, &tib->spec))
928 return GL_FALSE;
929 }
930 }
931 else
932 {
933 GLuint i, struct_size = 0, field_offset = 0, field_size = 0;
934
935 for (i = 0; i < tib->spec._struct->fields->num_variables; i++)
936 {
937 slang_variable *field;
938 slang_storage_aggregate agg;
939 GLuint size;
940
941 field = &tib->spec._struct->fields->variables[i];
942 if (!slang_storage_aggregate_construct (&agg))
943 return GL_FALSE;
944 if (!_slang_aggregate_variable (&agg, &field->type.specifier, field->array_size,
945 A->space.funcs, A->space.structs, A->space.vars, A->mach, A->file, A->atoms))
946 {
947 slang_storage_aggregate_destruct (&agg);
948 return GL_FALSE;
949 }
950 size = _slang_sizeof_aggregate (&agg);
951 slang_storage_aggregate_destruct (&agg);
952
953 if (op->a_id == field->a_name)
954 {
955 field_size = size;
956 struct_size = field_offset + size;
957 }
958 else if (struct_size != 0)
959 struct_size += size;
960 else
961 field_offset += size;
962 }
963
964 if (!PLAB (A->file, slang_asm_addr_push, field_offset))
965 return GL_FALSE;
966
967 if (ref == slang_ref_force)
968 {
969 if (!PUSH (A->file, slang_asm_addr_add))
970 return GL_FALSE;
971 }
972 else
973 {
974 GLuint i;
975
976 /* move the selected element to the beginning of the master expression */
977 for (i = 0; i < field_size; i += 4)
978 if (!PLAB2 (A->file, slang_asm_float_move, struct_size - field_size + i + 4, i + 4))
979 return GL_FALSE;
980 if (!PLAB (A->file, slang_asm_local_free, 4))
981 return GL_FALSE;
982
983 /* free the rest of the master expression */
984 if (!PLAB (A->file, slang_asm_local_free, struct_size - field_size))
985 return GL_FALSE;
986 }
987 }
988
989 return GL_TRUE;
990 }
991
992 GLboolean _slang_assemble_operation_ (slang_assemble_ctx *A, slang_operation *op, slang_ref_type ref)
993 {
994 GLuint assem;
995
996 assem = A->file->count;
997 if (!push_new (A->file))
998 return GL_FALSE;
999
1000 /* set default results */
1001 A->ref = /*(ref == slang_ref_freelance) ? slang_ref_force : */ref;
1002 A->swz.num_components = 0;
1003
1004 switch (op->type)
1005 {
1006 case slang_oper_block_no_new_scope:
1007 case slang_oper_block_new_scope:
1008 {
1009 GLuint i;
1010
1011 for (i = 0; i < op->num_children; i++)
1012 {
1013 if (!_slang_assemble_operation_ (A, &op->children[i], slang_ref_forbid/*slang_ref_freelance*/))
1014 return GL_FALSE;
1015 if (!_slang_cleanup_stack_ (A, &op->children[i]))
1016 return GL_FALSE;
1017 }
1018 }
1019 break;
1020 case slang_oper_variable_decl:
1021 {
1022 GLuint i;
1023
1024 for (i = 0; i < op->num_children; i++)
1025 {
1026 /* TODO: perform initialization of op->children[i] */
1027 /* TODO: clean-up stack */
1028 }
1029 }
1030 break;
1031 case slang_oper_asm:
1032 {
1033 GLuint i;
1034
1035 if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_force))
1036 return GL_FALSE;
1037 for (i = 1; i < op->num_children; i++)
1038 if (!_slang_assemble_operation_ (A, &op->children[i], slang_ref_forbid))
1039 return GL_FALSE;
1040 if (!call_asm_instruction (A, op->a_id))
1041 return GL_FALSE;
1042 }
1043 break;
1044 case slang_oper_break:
1045 A->file->code[assem].type = slang_asm_jump;
1046 A->file->code[assem].param[0] = A->flow.loop_end;
1047 break;
1048 case slang_oper_continue:
1049 A->file->code[assem].type = slang_asm_jump;
1050 A->file->code[assem].param[0] = A->flow.loop_start;
1051 break;
1052 case slang_oper_discard:
1053 A->file->code[assem].type = slang_asm_discard;
1054 if (!PUSH (A->file, slang_asm_exit))
1055 return GL_FALSE;
1056 break;
1057 case slang_oper_return:
1058 if (A->local.ret_size != 0)
1059 {
1060 /* push the result's address */
1061 if (!PLAB2 (A->file, slang_asm_local_addr, 0, A->local.ret_size))
1062 return GL_FALSE;
1063 if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid))
1064 return GL_FALSE;
1065
1066 A->swz.num_components = 0;
1067 /* assign the operation to the function result (it was reserved on the stack) */
1068 if (!_slang_assemble_assignment (A, op->children))
1069 return GL_FALSE;
1070
1071 if (!PLAB (A->file, slang_asm_local_free, 4))
1072 return GL_FALSE;
1073 }
1074 if (!PLAB (A->file, slang_asm_jump, A->flow.function_end))
1075 return GL_FALSE;
1076 break;
1077 case slang_oper_expression:
1078 if (ref == slang_ref_force)
1079 return GL_FALSE;
1080 if (!_slang_assemble_operation_ (A, &op->children[0], ref))
1081 return GL_FALSE;
1082 break;
1083 case slang_oper_if:
1084 if (!_slang_assemble_if (A, op))
1085 return GL_FALSE;
1086 break;
1087 case slang_oper_while:
1088 if (!_slang_assemble_while (A, op))
1089 return GL_FALSE;
1090 break;
1091 case slang_oper_do:
1092 if (!_slang_assemble_do (A, op))
1093 return GL_FALSE;
1094 break;
1095 case slang_oper_for:
1096 if (!_slang_assemble_for (A, op))
1097 return GL_FALSE;
1098 break;
1099 case slang_oper_void:
1100 break;
1101 case slang_oper_literal_bool:
1102 if (ref == slang_ref_force)
1103 return GL_FALSE;
1104 A->file->code[assem].type = slang_asm_bool_push;
1105 A->file->code[assem].literal = op->literal;
1106 A->ref = slang_ref_forbid;
1107 break;
1108 case slang_oper_literal_int:
1109 if (ref == slang_ref_force)
1110 return GL_FALSE;
1111 A->file->code[assem].type = slang_asm_int_push;
1112 A->file->code[assem].literal = op->literal;
1113 A->ref = slang_ref_forbid;
1114 break;
1115 case slang_oper_literal_float:
1116 if (ref == slang_ref_force)
1117 return GL_FALSE;
1118 A->file->code[assem].type = slang_asm_float_push;
1119 A->file->code[assem].literal = op->literal;
1120 A->ref = slang_ref_forbid;
1121 break;
1122 case slang_oper_identifier:
1123 {
1124 slang_variable *var;
1125 GLuint size;
1126
1127 /* find the variable and calculate its size */
1128 var = _slang_locate_variable (op->locals, op->a_id, GL_TRUE);
1129 if (var == NULL)
1130 return GL_FALSE;
1131 size = 0;
1132 if (!sizeof_variable (A, &var->type.specifier, slang_qual_none, var->array_size, &size))
1133 return GL_FALSE;
1134
1135 /* prepare stack for dereferencing */
1136 if (ref == slang_ref_forbid)
1137 if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4))
1138 return GL_FALSE;
1139
1140 /* push the variable's address */
1141 if (var->global)
1142 {
1143 if (!PLAB (A->file, slang_asm_addr_push, var->address))
1144 return GL_FALSE;
1145 }
1146 else
1147 {
1148 if (!PLAB2 (A->file, slang_asm_local_addr, var->address, size))
1149 return GL_FALSE;
1150 }
1151
1152 /* perform the dereference */
1153 if (ref == slang_ref_forbid)
1154 {
1155 if (!PUSH (A->file, slang_asm_addr_copy))
1156 return GL_FALSE;
1157 if (!PLAB (A->file, slang_asm_local_free, 4))
1158 return GL_FALSE;
1159 if (!_slang_dereference (A, op))
1160 return GL_FALSE;
1161 }
1162 }
1163 break;
1164 case slang_oper_sequence:
1165 if (ref == slang_ref_force)
1166 return GL_FALSE;
1167 if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/))
1168 return GL_FALSE;
1169 if (!_slang_cleanup_stack_ (A, &op->children[0]))
1170 return GL_FALSE;
1171 if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid))
1172 return GL_FALSE;
1173 A->ref = slang_ref_forbid;
1174 break;
1175 case slang_oper_assign:
1176 if (!_slang_assemble_assign (A, op, "=", ref))
1177 return GL_FALSE;
1178 break;
1179 case slang_oper_addassign:
1180 if (!_slang_assemble_assign (A, op, "+=", ref))
1181 return GL_FALSE;
1182 break;
1183 case slang_oper_subassign:
1184 if (!_slang_assemble_assign (A, op, "-=", ref))
1185 return GL_FALSE;
1186 break;
1187 case slang_oper_mulassign:
1188 if (!_slang_assemble_assign (A, op, "*=", ref))
1189 return GL_FALSE;
1190 break;
1191 /*case slang_oper_modassign:*/
1192 /*case slang_oper_lshassign:*/
1193 /*case slang_oper_rshassign:*/
1194 /*case slang_oper_orassign:*/
1195 /*case slang_oper_xorassign:*/
1196 /*case slang_oper_andassign:*/
1197 case slang_oper_divassign:
1198 if (!_slang_assemble_assign (A, op, "/=", ref))
1199 return GL_FALSE;
1200 break;
1201 case slang_oper_select:
1202 if (!_slang_assemble_select (A, op))
1203 return GL_FALSE;
1204 A->ref = slang_ref_forbid;
1205 break;
1206 case slang_oper_logicalor:
1207 if (!_slang_assemble_logicalor (A, op))
1208 return GL_FALSE;
1209 A->ref = slang_ref_forbid;
1210 break;
1211 case slang_oper_logicaland:
1212 if (!_slang_assemble_logicaland (A, op))
1213 return GL_FALSE;
1214 A->ref = slang_ref_forbid;
1215 break;
1216 case slang_oper_logicalxor:
1217 if (!_slang_assemble_function_call_name (A, "^^", op->children, 2, GL_FALSE))
1218 return GL_FALSE;
1219 A->ref = slang_ref_forbid;
1220 break;
1221 /*case slang_oper_bitor:*/
1222 /*case slang_oper_bitxor:*/
1223 /*case slang_oper_bitand:*/
1224 case slang_oper_less:
1225 if (!_slang_assemble_function_call_name (A, "<", op->children, 2, GL_FALSE))
1226 return GL_FALSE;
1227 A->ref = slang_ref_forbid;
1228 break;
1229 case slang_oper_greater:
1230 if (!_slang_assemble_function_call_name (A, ">", op->children, 2, GL_FALSE))
1231 return GL_FALSE;
1232 A->ref = slang_ref_forbid;
1233 break;
1234 case slang_oper_lessequal:
1235 if (!_slang_assemble_function_call_name (A, "<=", op->children, 2, GL_FALSE))
1236 return GL_FALSE;
1237 A->ref = slang_ref_forbid;
1238 break;
1239 case slang_oper_greaterequal:
1240 if (!_slang_assemble_function_call_name (A, ">=", op->children, 2, GL_FALSE))
1241 return GL_FALSE;
1242 A->ref = slang_ref_forbid;
1243 break;
1244 /*case slang_oper_lshift:*/
1245 /*case slang_oper_rshift:*/
1246 case slang_oper_add:
1247 if (!_slang_assemble_function_call_name (A, "+", op->children, 2, GL_FALSE))
1248 return GL_FALSE;
1249 A->ref = slang_ref_forbid;
1250 break;
1251 case slang_oper_subtract:
1252 if (!_slang_assemble_function_call_name (A, "-", op->children, 2, GL_FALSE))
1253 return GL_FALSE;
1254 A->ref = slang_ref_forbid;
1255 break;
1256 case slang_oper_multiply:
1257 if (!_slang_assemble_function_call_name (A, "*", op->children, 2, GL_FALSE))
1258 return GL_FALSE;
1259 A->ref = slang_ref_forbid;
1260 break;
1261 /*case slang_oper_modulus:*/
1262 case slang_oper_divide:
1263 if (!_slang_assemble_function_call_name (A, "/", op->children, 2, GL_FALSE))
1264 return GL_FALSE;
1265 A->ref = slang_ref_forbid;
1266 break;
1267 case slang_oper_equal:
1268 if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid))
1269 return GL_FALSE;
1270 if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid))
1271 return GL_FALSE;
1272 if (!equality (A, op->children, GL_TRUE))
1273 return GL_FALSE;
1274 A->ref = slang_ref_forbid;
1275 break;
1276 case slang_oper_notequal:
1277 if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid))
1278 return GL_FALSE;
1279 if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid))
1280 return GL_FALSE;
1281 if (!equality (A, op->children, GL_FALSE))
1282 return GL_FALSE;
1283 A->ref = slang_ref_forbid;
1284 break;
1285 case slang_oper_preincrement:
1286 if (!_slang_assemble_assign (A, op, "++", ref))
1287 return GL_FALSE;
1288 break;
1289 case slang_oper_predecrement:
1290 if (!_slang_assemble_assign (A, op, "--", ref))
1291 return GL_FALSE;
1292 break;
1293 case slang_oper_plus:
1294 if (!_slang_dereference (A, op))
1295 return GL_FALSE;
1296 A->ref = slang_ref_forbid;
1297 break;
1298 case slang_oper_minus:
1299 if (!_slang_assemble_function_call_name (A, "-", op->children, 1, GL_FALSE))
1300 return GL_FALSE;
1301 A->ref = slang_ref_forbid;
1302 break;
1303 /*case slang_oper_complement:*/
1304 case slang_oper_not:
1305 if (!_slang_assemble_function_call_name (A, "!", op->children, 1, GL_FALSE))
1306 return GL_FALSE;
1307 A->ref = slang_ref_forbid;
1308 break;
1309 case slang_oper_subscript:
1310 {
1311 slang_assembly_typeinfo ti_arr, ti_elem;
1312
1313 if (!slang_assembly_typeinfo_construct (&ti_arr))
1314 return GL_FALSE;
1315 if (!slang_assembly_typeinfo_construct (&ti_elem))
1316 {
1317 slang_assembly_typeinfo_destruct (&ti_arr);
1318 return GL_FALSE;
1319 }
1320 if (!handle_subscript (A, &ti_elem, &ti_arr, op, ref))
1321 {
1322 slang_assembly_typeinfo_destruct (&ti_arr);
1323 slang_assembly_typeinfo_destruct (&ti_elem);
1324 return GL_FALSE;
1325 }
1326 slang_assembly_typeinfo_destruct (&ti_arr);
1327 slang_assembly_typeinfo_destruct (&ti_elem);
1328 }
1329 break;
1330 case slang_oper_call:
1331 {
1332 slang_function *fun;
1333
1334 fun = _slang_locate_function (A->space.funcs, op->a_id, op->children, op->num_children,
1335 &A->space, A->atoms);
1336 if (fun == NULL)
1337 {
1338 if (!_slang_assemble_constructor (A, op))
1339 return GL_FALSE;
1340 }
1341 else
1342 {
1343 if (!_slang_assemble_function_call (A, fun, op->children, op->num_children, GL_FALSE))
1344 return GL_FALSE;
1345 }
1346 A->ref = slang_ref_forbid;
1347 }
1348 break;
1349 case slang_oper_field:
1350 {
1351 slang_assembly_typeinfo ti_after, ti_before;
1352
1353 if (!slang_assembly_typeinfo_construct (&ti_after))
1354 return GL_FALSE;
1355 if (!slang_assembly_typeinfo_construct (&ti_before))
1356 {
1357 slang_assembly_typeinfo_destruct (&ti_after);
1358 return GL_FALSE;
1359 }
1360 if (!handle_field (A, &ti_after, &ti_before, op, ref))
1361 {
1362 slang_assembly_typeinfo_destruct (&ti_after);
1363 slang_assembly_typeinfo_destruct (&ti_before);
1364 return GL_FALSE;
1365 }
1366 slang_assembly_typeinfo_destruct (&ti_after);
1367 slang_assembly_typeinfo_destruct (&ti_before);
1368 }
1369 break;
1370 case slang_oper_postincrement:
1371 if (!assemble_function_call_name_dummyint (A, "++", op->children))
1372 return GL_FALSE;
1373 A->ref = slang_ref_forbid;
1374 break;
1375 case slang_oper_postdecrement:
1376 if (!assemble_function_call_name_dummyint (A, "--", op->children))
1377 return GL_FALSE;
1378 A->ref = slang_ref_forbid;
1379 break;
1380 default:
1381 return GL_FALSE;
1382 }
1383
1384 return GL_TRUE;
1385 }
1386