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