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, GLuint array_len, 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_len, 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_len, 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, 0, &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 (A, op, &ti))
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, 0, &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 (A, op, &ti))
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_len, 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, 0, &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 { "vec4_tex2d", slang_asm_vec4_tex2d, slang_asm_none },
650 /* mesa-specific extensions */
651 { "float_print", slang_asm_float_deref, slang_asm_float_print },
652 { "int_print", slang_asm_int_deref, slang_asm_int_print },
653 { "bool_print", slang_asm_bool_deref, slang_asm_bool_print },
654 { NULL, slang_asm_none, slang_asm_none }
655 };
656
657 static GLboolean call_asm_instruction (slang_assemble_ctx *A, slang_atom a_name)
658 {
659 const char *id;
660 GLuint i;
661
662 id = slang_atom_pool_id (A->atoms, a_name);
663
664 for (i = 0; inst[i].name != NULL; i++)
665 if (slang_string_compare (id, inst[i].name) == 0)
666 break;
667 if (inst[i].name == NULL)
668 return GL_FALSE;
669
670 if (!PLAB2 (A->file, inst[i].code1, 4, 0))
671 return GL_FALSE;
672 if (inst[i].code2 != slang_asm_none)
673 if (!PLAB2 (A->file, inst[i].code2, 4, 0))
674 return GL_FALSE;
675
676 /* clean-up the stack from the remaining dst address */
677 if (!PLAB (A->file, slang_asm_local_free, 4))
678 return GL_FALSE;
679
680 return GL_TRUE;
681 }
682
683 static GLboolean equality_aggregate (slang_assemble_ctx *A, const slang_storage_aggregate *agg,
684 GLuint *index, GLuint size, GLuint z_label)
685 {
686 GLuint i;
687
688 for (i = 0; i < agg->count; i++)
689 {
690 const slang_storage_array *arr = &agg->arrays[i];
691 GLuint j;
692
693 for (j = 0; j < arr->length; j++)
694 {
695 if (arr->type == slang_stor_aggregate)
696 {
697 if (!equality_aggregate (A, arr->aggregate, index, size, z_label))
698 return GL_FALSE;
699 }
700 else
701 {
702 if (!PLAB2 (A->file, slang_asm_float_equal_int, size + *index, *index))
703 return GL_FALSE;
704 *index += 4;
705 if (!PLAB (A->file, slang_asm_jump_if_zero, z_label))
706 return GL_FALSE;
707 }
708 }
709 }
710
711 return GL_TRUE;
712 }
713
714 static GLboolean equality (slang_assemble_ctx *A, slang_operation *op, GLboolean equal)
715 {
716 slang_assembly_typeinfo ti;
717 GLboolean result = GL_FALSE;
718 slang_storage_aggregate agg;
719 GLuint index, size;
720 GLuint skip_jump, true_label, true_jump, false_label, false_jump;
721
722 /* get type of operation */
723 if (!slang_assembly_typeinfo_construct (&ti))
724 return GL_FALSE;
725 if (!_slang_typeof_operation (A, op, &ti))
726 goto end1;
727
728 /* convert it to an aggregate */
729 if (!slang_storage_aggregate_construct (&agg))
730 goto end1;
731 if (!_slang_aggregate_variable (&agg, &ti.spec, 0, A->space.funcs, A->space.structs,
732 A->space.vars, A->mach, A->file, A->atoms))
733 goto end;
734
735 /* compute the size of the agregate - there are two such aggregates on the stack */
736 size = _slang_sizeof_aggregate (&agg);
737
738 /* jump to the actual data-comparison code */
739 skip_jump = A->file->count;
740 if (!PUSH (A->file, slang_asm_jump))
741 goto end;
742
743 /* pop off the stack the compared data and push 1 */
744 true_label = A->file->count;
745 if (!PLAB (A->file, slang_asm_local_free, size * 2))
746 goto end;
747 if (!PLIT (A->file, slang_asm_bool_push, (GLfloat) 1))
748 goto end;
749 true_jump = A->file->count;
750 if (!PUSH (A->file, slang_asm_jump))
751 goto end;
752
753 false_label = A->file->count;
754 if (!PLAB (A->file, slang_asm_local_free, size * 2))
755 goto end;
756 if (!PLIT (A->file, slang_asm_bool_push, (GLfloat) 0))
757 goto end;
758 false_jump = A->file->count;
759 if (!PUSH (A->file, slang_asm_jump))
760 goto end;
761
762 A->file->code[skip_jump].param[0] = A->file->count;
763
764 /* compare the data on stack, it will eventually jump either to true or false label */
765 index = 0;
766 if (!equality_aggregate (A, &agg, &index, size, equal ? false_label : true_label))
767 goto end;
768 if (!PLAB (A->file, slang_asm_jump, equal ? true_label : false_label))
769 goto end;
770
771 A->file->code[true_jump].param[0] = A->file->count;
772 A->file->code[false_jump].param[0] = A->file->count;
773
774 result = GL_TRUE;
775 end:
776 slang_storage_aggregate_destruct (&agg);
777 end1:
778 slang_assembly_typeinfo_destruct (&ti);
779 return result;
780 }
781
782 static GLboolean handle_subscript (slang_assemble_ctx *A, slang_assembly_typeinfo *tie,
783 slang_assembly_typeinfo *tia, slang_operation *op, slang_ref_type ref)
784 {
785 GLuint asize = 0, esize = 0;
786
787 /* get type info of the master expression (matrix, vector or an array */
788 if (!_slang_typeof_operation (A, &op->children[0], tia))
789 return GL_FALSE;
790 if (!sizeof_variable (A, &tia->spec, slang_qual_none, tia->array_len, &asize))
791 return GL_FALSE;
792
793 /* get type info of the result (matrix column, vector row or array element) */
794 if (!_slang_typeof_operation (A, op, tie))
795 return GL_FALSE;
796 if (!sizeof_variable (A, &tie->spec, slang_qual_none, 0, &esize))
797 return GL_FALSE;
798
799 /* assemble the master expression */
800 if (!_slang_assemble_operation (A, &op->children[0], ref))
801 return GL_FALSE;
802
803 /* when indexing an l-value swizzle, push the swizzle_tmp */
804 if (ref == slang_ref_force && tia->is_swizzled)
805 if (!PLAB2 (A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16))
806 return GL_FALSE;
807
808 /* assemble the subscript expression */
809 if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
810 return GL_FALSE;
811
812 if (ref == slang_ref_force && tia->is_swizzled)
813 {
814 GLuint i;
815
816 /* copy the swizzle indexes to the swizzle_tmp */
817 for (i = 0; i < tia->swz.num_components; i++)
818 {
819 if (!PLAB2 (A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16))
820 return GL_FALSE;
821 if (!PLAB (A->file, slang_asm_addr_push, i * 4))
822 return GL_FALSE;
823 if (!PUSH (A->file, slang_asm_addr_add))
824 return GL_FALSE;
825 if (!PLAB (A->file, slang_asm_addr_push, tia->swz.swizzle[i]))
826 return GL_FALSE;
827 if (!PUSH (A->file, slang_asm_addr_copy))
828 return GL_FALSE;
829 if (!PLAB (A->file, slang_asm_local_free, 4))
830 return GL_FALSE;
831 }
832
833 /* offset the pushed swizzle_tmp address and dereference it */
834 if (!PUSH (A->file, slang_asm_int_to_addr))
835 return GL_FALSE;
836 if (!PLAB (A->file, slang_asm_addr_push, 4))
837 return GL_FALSE;
838 if (!PUSH (A->file, slang_asm_addr_multiply))
839 return GL_FALSE;
840 if (!PUSH (A->file, slang_asm_addr_add))
841 return GL_FALSE;
842 if (!PUSH (A->file, slang_asm_addr_deref))
843 return GL_FALSE;
844 }
845 else
846 {
847 /* convert the integer subscript to a relative address */
848 if (!PUSH (A->file, slang_asm_int_to_addr))
849 return GL_FALSE;
850 }
851
852 if (!PLAB (A->file, slang_asm_addr_push, esize))
853 return GL_FALSE;
854 if (!PUSH (A->file, slang_asm_addr_multiply))
855 return GL_FALSE;
856
857 if (ref == slang_ref_force)
858 {
859 /* offset the base address with the relative address */
860 if (!PUSH (A->file, slang_asm_addr_add))
861 return GL_FALSE;
862 }
863 else
864 {
865 GLuint i;
866
867 /* move the selected element to the beginning of the master expression */
868 for (i = 0; i < esize; i += 4)
869 if (!PLAB2 (A->file, slang_asm_float_move, asize - esize + i + 4, i + 4))
870 return GL_FALSE;
871 if (!PLAB (A->file, slang_asm_local_free, 4))
872 return GL_FALSE;
873
874 /* free the rest of the master expression */
875 if (!PLAB (A->file, slang_asm_local_free, asize - esize))
876 return GL_FALSE;
877 }
878
879 return GL_TRUE;
880 }
881
882 static GLboolean handle_field (slang_assemble_ctx *A, slang_assembly_typeinfo *tia,
883 slang_assembly_typeinfo *tib, slang_operation *op, slang_ref_type ref)
884 {
885 /* get type info of the result (field or swizzle) */
886 if (!_slang_typeof_operation (A, op, tia))
887 return GL_FALSE;
888
889 /* get type info of the master expression being accessed (struct or vector) */
890 if (!_slang_typeof_operation (A, &op->children[0], tib))
891 return GL_FALSE;
892
893 /* if swizzling a vector in-place, the swizzle temporary is needed */
894 if (ref == slang_ref_forbid && tia->is_swizzled)
895 if (!PLAB2 (A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16))
896 return GL_FALSE;
897
898 /* assemble the master expression */
899 if (!_slang_assemble_operation (A, &op->children[0], ref))
900 return GL_FALSE;
901
902 /* assemble the field expression */
903 if (tia->is_swizzled)
904 {
905 if (ref == slang_ref_force)
906 {
907 #if 0
908 if (tia->swz.num_components == 1)
909 {
910 /* simple case - adjust the vector's address to point to the selected component */
911 if (!PLAB (file, slang_asm_addr_push, tia->swz.swizzle[0] * 4))
912 return 0;
913 if (!PUSH (file, slang_asm_addr_add))
914 return 0;
915 }
916 else
917 #endif
918 {
919 /* two or more vector components are being referenced - the so-called write mask
920 * must be passed to the upper operations and applied when assigning value
921 * to this swizzle */
922 A->swz = tia->swz;
923 }
924 }
925 else
926 {
927 /* swizzle the vector in-place using the swizzle temporary */
928 if (!_slang_assemble_constructor_from_swizzle (A, &tia->swz, &tia->spec, &tib->spec))
929 return GL_FALSE;
930 }
931 }
932 else
933 {
934 GLuint i, struct_size = 0, field_offset = 0, field_size = 0;
935
936 for (i = 0; i < tib->spec._struct->fields->num_variables; i++)
937 {
938 slang_variable *field;
939 slang_storage_aggregate agg;
940 GLuint size;
941
942 field = &tib->spec._struct->fields->variables[i];
943 if (!slang_storage_aggregate_construct (&agg))
944 return GL_FALSE;
945 if (!_slang_aggregate_variable (&agg, &field->type.specifier, field->array_len,
946 A->space.funcs, A->space.structs, A->space.vars, A->mach, A->file, A->atoms))
947 {
948 slang_storage_aggregate_destruct (&agg);
949 return GL_FALSE;
950 }
951 size = _slang_sizeof_aggregate (&agg);
952 slang_storage_aggregate_destruct (&agg);
953
954 if (op->a_id == field->a_name)
955 {
956 field_size = size;
957 struct_size = field_offset + size;
958 }
959 else if (struct_size != 0)
960 struct_size += size;
961 else
962 field_offset += size;
963 }
964
965 if (!PLAB (A->file, slang_asm_addr_push, field_offset))
966 return GL_FALSE;
967
968 if (ref == slang_ref_force)
969 {
970 if (!PUSH (A->file, slang_asm_addr_add))
971 return GL_FALSE;
972 }
973 else
974 {
975 GLuint i;
976
977 /* move the selected element to the beginning of the master expression */
978 for (i = 0; i < field_size; i += 4)
979 if (!PLAB2 (A->file, slang_asm_float_move, struct_size - field_size + i + 4, i + 4))
980 return GL_FALSE;
981 if (!PLAB (A->file, slang_asm_local_free, 4))
982 return GL_FALSE;
983
984 /* free the rest of the master expression */
985 if (!PLAB (A->file, slang_asm_local_free, struct_size - field_size))
986 return GL_FALSE;
987 }
988 }
989
990 return GL_TRUE;
991 }
992
993 GLboolean _slang_assemble_operation (slang_assemble_ctx *A, slang_operation *op, slang_ref_type ref)
994 {
995 /* set default results */
996 A->ref = /*(ref == slang_ref_freelance) ? slang_ref_force : */ref;
997 A->swz.num_components = 0;
998
999 switch (op->type)
1000 {
1001 case slang_oper_block_no_new_scope:
1002 case slang_oper_block_new_scope:
1003 {
1004 GLuint i;
1005
1006 for (i = 0; i < op->num_children; i++)
1007 {
1008 if (!_slang_assemble_operation (A, &op->children[i], slang_ref_forbid/*slang_ref_freelance*/))
1009 return GL_FALSE;
1010 if (!_slang_cleanup_stack (A, &op->children[i]))
1011 return GL_FALSE;
1012 }
1013 }
1014 break;
1015 case slang_oper_variable_decl:
1016 {
1017 GLuint i;
1018
1019 for (i = 0; i < op->num_children; i++)
1020 {
1021 /* TODO: perform initialization of op->children[i] */
1022 /* TODO: clean-up stack */
1023 }
1024 }
1025 break;
1026 case slang_oper_asm:
1027 {
1028 GLuint i;
1029
1030 if (!_slang_assemble_operation (A, &op->children[0], slang_ref_force))
1031 return GL_FALSE;
1032 for (i = 1; i < op->num_children; i++)
1033 if (!_slang_assemble_operation (A, &op->children[i], slang_ref_forbid))
1034 return GL_FALSE;
1035 if (!call_asm_instruction (A, op->a_id))
1036 return GL_FALSE;
1037 }
1038 break;
1039 case slang_oper_break:
1040 if (!PLAB (A->file, slang_asm_jump, A->flow.loop_end))
1041 return GL_FALSE;
1042 break;
1043 case slang_oper_continue:
1044 if (!PLAB (A->file, slang_asm_jump, A->flow.loop_start))
1045 return GL_FALSE;
1046 break;
1047 case slang_oper_discard:
1048 if (!PUSH (A->file, slang_asm_discard))
1049 return GL_FALSE;
1050 if (!PUSH (A->file, slang_asm_exit))
1051 return GL_FALSE;
1052 break;
1053 case slang_oper_return:
1054 if (A->local.ret_size != 0)
1055 {
1056 /* push the result's address */
1057 if (!PLAB2 (A->file, slang_asm_local_addr, 0, A->local.ret_size))
1058 return GL_FALSE;
1059 if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
1060 return GL_FALSE;
1061
1062 A->swz.num_components = 0;
1063 /* assign the operation to the function result (it was reserved on the stack) */
1064 if (!_slang_assemble_assignment (A, op->children))
1065 return GL_FALSE;
1066
1067 if (!PLAB (A->file, slang_asm_local_free, 4))
1068 return GL_FALSE;
1069 }
1070 if (!PLAB (A->file, slang_asm_jump, A->flow.function_end))
1071 return GL_FALSE;
1072 break;
1073 case slang_oper_expression:
1074 if (ref == slang_ref_force)
1075 return GL_FALSE;
1076 if (!_slang_assemble_operation (A, &op->children[0], ref))
1077 return GL_FALSE;
1078 break;
1079 case slang_oper_if:
1080 if (!_slang_assemble_if (A, op))
1081 return GL_FALSE;
1082 break;
1083 case slang_oper_while:
1084 if (!_slang_assemble_while (A, op))
1085 return GL_FALSE;
1086 break;
1087 case slang_oper_do:
1088 if (!_slang_assemble_do (A, op))
1089 return GL_FALSE;
1090 break;
1091 case slang_oper_for:
1092 if (!_slang_assemble_for (A, op))
1093 return GL_FALSE;
1094 break;
1095 case slang_oper_void:
1096 break;
1097 case slang_oper_literal_bool:
1098 if (ref == slang_ref_force)
1099 return GL_FALSE;
1100 if (!PLIT (A->file, slang_asm_bool_push, op->literal))
1101 return GL_FALSE;
1102 A->ref = slang_ref_forbid;
1103 break;
1104 case slang_oper_literal_int:
1105 if (ref == slang_ref_force)
1106 return GL_FALSE;
1107 if (!PLIT (A->file, slang_asm_int_push, op->literal))
1108 return GL_FALSE;
1109 A->ref = slang_ref_forbid;
1110 break;
1111 case slang_oper_literal_float:
1112 if (ref == slang_ref_force)
1113 return GL_FALSE;
1114 if (!PLIT (A->file, slang_asm_float_push, op->literal))
1115 return GL_FALSE;
1116 A->ref = slang_ref_forbid;
1117 break;
1118 case slang_oper_identifier:
1119 {
1120 slang_variable *var;
1121 GLuint size;
1122
1123 /* find the variable and calculate its size */
1124 var = _slang_locate_variable (op->locals, op->a_id, GL_TRUE);
1125 if (var == NULL)
1126 return GL_FALSE;
1127 size = 0;
1128 if (!sizeof_variable (A, &var->type.specifier, slang_qual_none, var->array_len, &size))
1129 return GL_FALSE;
1130
1131 /* prepare stack for dereferencing */
1132 if (ref == slang_ref_forbid)
1133 if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4))
1134 return GL_FALSE;
1135
1136 /* push the variable's address */
1137 if (var->global)
1138 {
1139 if (!PLAB (A->file, slang_asm_addr_push, var->address))
1140 return GL_FALSE;
1141 }
1142 else
1143 {
1144 if (!PLAB2 (A->file, slang_asm_local_addr, var->address, size))
1145 return GL_FALSE;
1146 }
1147
1148 /* perform the dereference */
1149 if (ref == slang_ref_forbid)
1150 {
1151 if (!PUSH (A->file, slang_asm_addr_copy))
1152 return GL_FALSE;
1153 if (!PLAB (A->file, slang_asm_local_free, 4))
1154 return GL_FALSE;
1155 if (!_slang_dereference (A, op))
1156 return GL_FALSE;
1157 }
1158 }
1159 break;
1160 case slang_oper_sequence:
1161 if (ref == slang_ref_force)
1162 return GL_FALSE;
1163 if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/))
1164 return GL_FALSE;
1165 if (!_slang_cleanup_stack (A, &op->children[0]))
1166 return GL_FALSE;
1167 if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
1168 return GL_FALSE;
1169 A->ref = slang_ref_forbid;
1170 break;
1171 case slang_oper_assign:
1172 if (!_slang_assemble_assign (A, op, "=", ref))
1173 return GL_FALSE;
1174 break;
1175 case slang_oper_addassign:
1176 if (!_slang_assemble_assign (A, op, "+=", ref))
1177 return GL_FALSE;
1178 break;
1179 case slang_oper_subassign:
1180 if (!_slang_assemble_assign (A, op, "-=", ref))
1181 return GL_FALSE;
1182 break;
1183 case slang_oper_mulassign:
1184 if (!_slang_assemble_assign (A, op, "*=", ref))
1185 return GL_FALSE;
1186 break;
1187 /*case slang_oper_modassign:*/
1188 /*case slang_oper_lshassign:*/
1189 /*case slang_oper_rshassign:*/
1190 /*case slang_oper_orassign:*/
1191 /*case slang_oper_xorassign:*/
1192 /*case slang_oper_andassign:*/
1193 case slang_oper_divassign:
1194 if (!_slang_assemble_assign (A, op, "/=", ref))
1195 return GL_FALSE;
1196 break;
1197 case slang_oper_select:
1198 if (!_slang_assemble_select (A, op))
1199 return GL_FALSE;
1200 A->ref = slang_ref_forbid;
1201 break;
1202 case slang_oper_logicalor:
1203 if (!_slang_assemble_logicalor (A, op))
1204 return GL_FALSE;
1205 A->ref = slang_ref_forbid;
1206 break;
1207 case slang_oper_logicaland:
1208 if (!_slang_assemble_logicaland (A, op))
1209 return GL_FALSE;
1210 A->ref = slang_ref_forbid;
1211 break;
1212 case slang_oper_logicalxor:
1213 if (!_slang_assemble_function_call_name (A, "^^", op->children, 2, GL_FALSE))
1214 return GL_FALSE;
1215 A->ref = slang_ref_forbid;
1216 break;
1217 /*case slang_oper_bitor:*/
1218 /*case slang_oper_bitxor:*/
1219 /*case slang_oper_bitand:*/
1220 case slang_oper_less:
1221 if (!_slang_assemble_function_call_name (A, "<", op->children, 2, GL_FALSE))
1222 return GL_FALSE;
1223 A->ref = slang_ref_forbid;
1224 break;
1225 case slang_oper_greater:
1226 if (!_slang_assemble_function_call_name (A, ">", op->children, 2, GL_FALSE))
1227 return GL_FALSE;
1228 A->ref = slang_ref_forbid;
1229 break;
1230 case slang_oper_lessequal:
1231 if (!_slang_assemble_function_call_name (A, "<=", op->children, 2, GL_FALSE))
1232 return GL_FALSE;
1233 A->ref = slang_ref_forbid;
1234 break;
1235 case slang_oper_greaterequal:
1236 if (!_slang_assemble_function_call_name (A, ">=", op->children, 2, GL_FALSE))
1237 return GL_FALSE;
1238 A->ref = slang_ref_forbid;
1239 break;
1240 /*case slang_oper_lshift:*/
1241 /*case slang_oper_rshift:*/
1242 case slang_oper_add:
1243 if (!_slang_assemble_function_call_name (A, "+", op->children, 2, GL_FALSE))
1244 return GL_FALSE;
1245 A->ref = slang_ref_forbid;
1246 break;
1247 case slang_oper_subtract:
1248 if (!_slang_assemble_function_call_name (A, "-", op->children, 2, GL_FALSE))
1249 return GL_FALSE;
1250 A->ref = slang_ref_forbid;
1251 break;
1252 case slang_oper_multiply:
1253 if (!_slang_assemble_function_call_name (A, "*", op->children, 2, GL_FALSE))
1254 return GL_FALSE;
1255 A->ref = slang_ref_forbid;
1256 break;
1257 /*case slang_oper_modulus:*/
1258 case slang_oper_divide:
1259 if (!_slang_assemble_function_call_name (A, "/", op->children, 2, GL_FALSE))
1260 return GL_FALSE;
1261 A->ref = slang_ref_forbid;
1262 break;
1263 case slang_oper_equal:
1264 if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
1265 return GL_FALSE;
1266 if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
1267 return GL_FALSE;
1268 if (!equality (A, op->children, GL_TRUE))
1269 return GL_FALSE;
1270 A->ref = slang_ref_forbid;
1271 break;
1272 case slang_oper_notequal:
1273 if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
1274 return GL_FALSE;
1275 if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
1276 return GL_FALSE;
1277 if (!equality (A, op->children, GL_FALSE))
1278 return GL_FALSE;
1279 A->ref = slang_ref_forbid;
1280 break;
1281 case slang_oper_preincrement:
1282 if (!_slang_assemble_assign (A, op, "++", ref))
1283 return GL_FALSE;
1284 break;
1285 case slang_oper_predecrement:
1286 if (!_slang_assemble_assign (A, op, "--", ref))
1287 return GL_FALSE;
1288 break;
1289 case slang_oper_plus:
1290 if (!_slang_dereference (A, op))
1291 return GL_FALSE;
1292 A->ref = slang_ref_forbid;
1293 break;
1294 case slang_oper_minus:
1295 if (!_slang_assemble_function_call_name (A, "-", op->children, 1, GL_FALSE))
1296 return GL_FALSE;
1297 A->ref = slang_ref_forbid;
1298 break;
1299 /*case slang_oper_complement:*/
1300 case slang_oper_not:
1301 if (!_slang_assemble_function_call_name (A, "!", op->children, 1, GL_FALSE))
1302 return GL_FALSE;
1303 A->ref = slang_ref_forbid;
1304 break;
1305 case slang_oper_subscript:
1306 {
1307 slang_assembly_typeinfo ti_arr, ti_elem;
1308
1309 if (!slang_assembly_typeinfo_construct (&ti_arr))
1310 return GL_FALSE;
1311 if (!slang_assembly_typeinfo_construct (&ti_elem))
1312 {
1313 slang_assembly_typeinfo_destruct (&ti_arr);
1314 return GL_FALSE;
1315 }
1316 if (!handle_subscript (A, &ti_elem, &ti_arr, op, ref))
1317 {
1318 slang_assembly_typeinfo_destruct (&ti_arr);
1319 slang_assembly_typeinfo_destruct (&ti_elem);
1320 return GL_FALSE;
1321 }
1322 slang_assembly_typeinfo_destruct (&ti_arr);
1323 slang_assembly_typeinfo_destruct (&ti_elem);
1324 }
1325 break;
1326 case slang_oper_call:
1327 {
1328 slang_function *fun;
1329
1330 fun = _slang_locate_function (A->space.funcs, op->a_id, op->children, op->num_children,
1331 &A->space, A->atoms);
1332 if (fun == NULL)
1333 {
1334 if (!_slang_assemble_constructor (A, op))
1335 return GL_FALSE;
1336 }
1337 else
1338 {
1339 if (!_slang_assemble_function_call (A, fun, op->children, op->num_children, GL_FALSE))
1340 return GL_FALSE;
1341 }
1342 A->ref = slang_ref_forbid;
1343 }
1344 break;
1345 case slang_oper_field:
1346 {
1347 slang_assembly_typeinfo ti_after, ti_before;
1348
1349 if (!slang_assembly_typeinfo_construct (&ti_after))
1350 return GL_FALSE;
1351 if (!slang_assembly_typeinfo_construct (&ti_before))
1352 {
1353 slang_assembly_typeinfo_destruct (&ti_after);
1354 return GL_FALSE;
1355 }
1356 if (!handle_field (A, &ti_after, &ti_before, op, ref))
1357 {
1358 slang_assembly_typeinfo_destruct (&ti_after);
1359 slang_assembly_typeinfo_destruct (&ti_before);
1360 return GL_FALSE;
1361 }
1362 slang_assembly_typeinfo_destruct (&ti_after);
1363 slang_assembly_typeinfo_destruct (&ti_before);
1364 }
1365 break;
1366 case slang_oper_postincrement:
1367 if (!assemble_function_call_name_dummyint (A, "++", op->children))
1368 return GL_FALSE;
1369 A->ref = slang_ref_forbid;
1370 break;
1371 case slang_oper_postdecrement:
1372 if (!assemble_function_call_name_dummyint (A, "--", op->children))
1373 return GL_FALSE;
1374 A->ref = slang_ref_forbid;
1375 break;
1376 default:
1377 return GL_FALSE;
1378 }
1379
1380 return GL_TRUE;
1381 }
1382