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