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