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