2 * Mesa 3-D graphics library
5 * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
26 * \file slang_assemble.c
27 * slang intermediate code assembler
32 #include "slang_assemble.h"
33 #include "slang_compile.h"
34 #include "slang_storage.h"
35 #include "slang_error.h"
37 #include "slang_print.h"
38 /*#include "assemble2.c"*/
43 slang_assembly_construct(slang_assembly
* assem
)
45 assem
->type
= slang_asm_none
;
50 slang_assembly_destruct(slang_assembly
* assem
)
59 _slang_assembly_file_ctr(slang_assembly_file
* self
)
67 slang_assembly_file_destruct(slang_assembly_file
* file
)
71 for (i
= 0; i
< file
->count
; i
++)
72 slang_assembly_destruct(&file
->code
[i
]);
73 slang_alloc_free(file
->code
);
77 push_new(slang_assembly_file
* file
)
79 if (file
->count
== file
->capacity
) {
82 if (file
->capacity
== 0)
85 n
= file
->capacity
* 2;
86 file
->code
= (slang_assembly
*)
87 slang_alloc_realloc(file
->code
,
88 file
->capacity
* sizeof(slang_assembly
),
89 n
* sizeof(slang_assembly
));
90 if (file
->code
== NULL
)
94 if (!slang_assembly_construct(&file
->code
[file
->count
]))
101 push_gen(slang_assembly_file
* file
, slang_assembly_type type
,
102 GLfloat literal
, GLuint label
, GLuint size
)
104 slang_assembly
*assem
;
107 printf("Gen %s %f %d %d\n", slang_asm_string(type
), literal
, label
, size
);
111 assem
= &file
->code
[file
->count
- 1];
113 assem
->literal
= literal
;
114 assem
->param
[0] = label
;
115 assem
->param
[1] = size
;
120 slang_assembly_file_push(slang_assembly_file
* file
, slang_assembly_type type
)
122 return push_gen(file
, type
, (GLfloat
) 0, 0, 0);
126 slang_assembly_file_push_label(slang_assembly_file
* file
,
127 slang_assembly_type type
, GLuint label
)
129 return push_gen(file
, type
, (GLfloat
) 0, label
, 0);
133 slang_assembly_file_push_label2(slang_assembly_file
* file
,
134 slang_assembly_type type
, GLuint label1
,
137 return push_gen(file
, type
, (GLfloat
) 0, label1
, label2
);
141 slang_assembly_file_push_literal(slang_assembly_file
* file
,
142 slang_assembly_type type
, GLfloat literal
)
144 return push_gen(file
, type
, literal
, 0, 0);
147 #define PUSH slang_assembly_file_push
148 #define PLAB slang_assembly_file_push_label
149 #define PLAB2 slang_assembly_file_push_label2
150 #define PLIT slang_assembly_file_push_literal
152 /* slang_assembly_file_restore_point */
155 slang_assembly_file_restore_point_save(slang_assembly_file
* file
,
156 slang_assembly_file_restore_point
*
159 point
->count
= file
->count
;
164 slang_assembly_file_restore_point_load(slang_assembly_file
* file
,
165 slang_assembly_file_restore_point
*
170 for (i
= point
->count
; i
< file
->count
; i
++)
171 slang_assembly_destruct(&file
->code
[i
]);
172 file
->count
= point
->count
;
176 /* utility functions */
179 sizeof_variable(const slang_assemble_ctx
* A
, slang_type_specifier
* spec
,
180 slang_type_qualifier qual
, GLuint array_len
, GLuint
* size
)
182 slang_storage_aggregate agg
;
184 /* calculate the size of the variable's aggregate */
185 if (!slang_storage_aggregate_construct(&agg
))
187 if (!_slang_aggregate_variable(&agg
, spec
, array_len
, A
->space
.funcs
,
188 A
->space
.structs
, A
->space
.vars
, A
->mach
,
189 A
->file
, A
->atoms
)) {
190 slang_storage_aggregate_destruct(&agg
);
193 *size
+= _slang_sizeof_aggregate(&agg
);
194 slang_storage_aggregate_destruct(&agg
);
196 /* for reference variables consider the additional address overhead */
197 if (qual
== slang_qual_out
|| qual
== slang_qual_inout
)
204 sizeof_variable2(slang_assemble_ctx
* A
, slang_variable
* var
, GLuint
* size
)
206 var
->address
= *size
;
207 if (var
->type
.qualifier
== slang_qual_out
208 || var
->type
.qualifier
== slang_qual_inout
)
210 return sizeof_variable(A
, &var
->type
.specifier
, var
->type
.qualifier
,
211 var
->array_len
, size
);
215 sizeof_variables(slang_assemble_ctx
* A
, slang_variable_scope
* vars
,
216 GLuint start
, GLuint stop
, GLuint
* size
)
220 for (i
= start
; i
< stop
; i
++)
221 if (!sizeof_variable2(A
, &vars
->variables
[i
], size
))
227 collect_locals(slang_assemble_ctx
* A
, slang_operation
* op
, GLuint
* size
)
231 if (!sizeof_variables(A
, op
->locals
, 0, op
->locals
->num_variables
, size
))
233 for (i
= 0; i
< op
->num_children
; i
++)
234 if (!collect_locals(A
, &op
->children
[i
], size
))
239 /* _slang_locate_function() */
242 * Locate a function by comparing actual arguments against formal parameters.
245 _slang_locate_function(const slang_function_scope
* funcs
, slang_atom a_name
,
246 const slang_operation
* args
, GLuint num_args
,
247 const slang_assembly_name_space
* space
,
248 slang_atom_pool
* atoms
)
252 for (i
= 0; i
< funcs
->num_functions
; i
++) {
253 slang_function
*f
= &funcs
->functions
[i
];
254 const GLuint haveRetValue
= _slang_function_has_return_value(f
);
257 if (a_name
!= f
->header
.a_name
)
259 if (f
->param_count
- haveRetValue
!= num_args
)
262 /* compare parameter / argument types */
263 for (j
= 0; j
< num_args
; j
++) {
264 slang_assembly_typeinfo ti
;
266 if (!slang_assembly_typeinfo_construct(&ti
))
268 if (!_slang_typeof_operation_(&args
[j
], space
, &ti
, atoms
)) {
269 slang_assembly_typeinfo_destruct(&ti
);
272 if (!slang_type_specifier_equal(&ti
.spec
,
273 &f
->parameters
->variables
[j
/* + haveRetValue*/].type
.specifier
)) {
274 slang_assembly_typeinfo_destruct(&ti
);
277 slang_assembly_typeinfo_destruct(&ti
);
279 /* "out" and "inout" formal parameter requires the actual parameter to be l-value */
280 if (!ti
.can_be_referenced
&&
281 (f
->parameters
->variables
[j
/* + haveRetValue*/].type
.qualifier
== slang_qual_out
||
282 f
->parameters
->variables
[j
/* + haveRetValue*/].type
.qualifier
== slang_qual_inout
))
288 if (funcs
->outer_scope
!= NULL
)
289 return _slang_locate_function(funcs
->outer_scope
, a_name
, args
,
290 num_args
, space
, atoms
);
297 * Generate assembly for a parsed function.
300 _slang_assemble_function(slang_assemble_ctx
* A
, slang_function
* fun
)
302 GLuint param_size
, local_size
;
303 GLuint skip
, cleanup
;
304 const GLuint haveRetValue
= _slang_function_has_return_value(fun
);
306 fun
->address
= A
->file
->count
;
308 if (fun
->body
== NULL
) {
309 /* jump to the actual function body - we do not know it, so add
310 * the instruction to fixup table
312 if (!slang_fixup_save(&fun
->fixups
, fun
->address
))
314 if (!PUSH(A
->file
, slang_asm_jump
))
315 RETURN_OUT_OF_MEMORY();
319 /* resolve all fixup table entries and delete it */
321 for (i
= 0; i
< fun
->fixups
.count
; i
++)
322 A
->file
->code
[fun
->fixups
.table
[i
]].param
[0] = fun
->address
;
323 slang_fixup_table_free(&fun
->fixups
);
326 /* At this point traverse function formal parameters and code to calculate
327 * total memory size to be allocated on the stack.
328 * During this process the variables will be assigned local addresses to
329 * reference them in the code.
330 * No storage optimizations are performed so exclusive scopes are not
331 * detected and shared.
334 /* calculate return value size */
336 if (fun
->header
.type
.specifier
.type
!= slang_spec_void
) {
337 if (!sizeof_variable(A
, &fun
->header
.type
.specifier
,
338 slang_qual_none
, 0, ¶m_size
))
341 A
->local
.ret_size
= param_size
;
343 /* calculate formal parameter list size */
344 if (!sizeof_variables(A
, fun
->parameters
,
346 fun
->param_count
- haveRetValue
, ¶m_size
))
349 /* calculate local variables size - take into account the four-byte
350 * return address and temporaries for various tasks (4 for addr and
351 * 16 for swizzle temporaries). these include variables from the
352 * formal parameter scope and from the code
354 A
->local
.addr_tmp
= param_size
+ 4;
355 A
->local
.swizzle_tmp
= param_size
+ 4 + 4;
356 local_size
= param_size
+ 4 + 4 + 16;
357 if (!sizeof_variables(A
, fun
->parameters
, fun
->param_count
,
358 fun
->parameters
->num_variables
, &local_size
)) {
359 RETURN_OUT_OF_MEMORY();
361 if (!collect_locals(A
, fun
->body
, &local_size
))
364 /* allocate local variable storage */
365 if (!PLAB(A
->file
, slang_asm_local_alloc
, local_size
- param_size
- 4))
366 RETURN_OUT_OF_MEMORY();
368 /* mark a new frame for function variable storage */
369 if (!PLAB(A
->file
, slang_asm_enter
, local_size
))
370 RETURN_OUT_OF_MEMORY();
372 /* jump directly to the actual code */
373 skip
= A
->file
->count
;
374 if (!push_new(A
->file
))
375 RETURN_OUT_OF_MEMORY();
376 A
->file
->code
[skip
].type
= slang_asm_jump
;
378 /* all "return" statements will be directed here */
379 A
->flow
.function_end
= A
->file
->count
;
380 cleanup
= A
->file
->count
;
381 if (!push_new(A
->file
))
382 RETURN_OUT_OF_MEMORY();
383 A
->file
->code
[cleanup
].type
= slang_asm_jump
;
385 /* execute the function body */
386 A
->file
->code
[skip
].param
[0] = A
->file
->count
;
387 if (!_slang_assemble_operation(A
, fun
->body
,
388 /*slang_ref_freelance */ slang_ref_forbid
))
391 /* this is the end of the function - restore the old function frame */
392 A
->file
->code
[cleanup
].param
[0] = A
->file
->count
;
393 if (!PUSH(A
->file
, slang_asm_leave
))
394 RETURN_OUT_OF_MEMORY();
396 /* free local variable storage */
397 if (!PLAB(A
->file
, slang_asm_local_free
, local_size
- param_size
- 4))
398 RETURN_OUT_OF_MEMORY();
400 /* return from the function */
401 if (!PUSH(A
->file
, slang_asm_return
))
402 RETURN_OUT_OF_MEMORY();
408 _slang_cleanup_stack(slang_assemble_ctx
* A
, slang_operation
* op
)
410 slang_assembly_typeinfo ti
;
413 /* get type info of the operation and calculate its size */
414 if (!slang_assembly_typeinfo_construct(&ti
))
416 if (!_slang_typeof_operation(A
, op
, &ti
)) {
417 slang_assembly_typeinfo_destruct(&ti
);
420 if (ti
.spec
.type
!= slang_spec_void
) {
421 if (A
->ref
== slang_ref_force
) {
424 else if (!sizeof_variable(A
, &ti
.spec
, slang_qual_none
, 0, &size
)) {
425 slang_assembly_typeinfo_destruct(&ti
);
429 slang_assembly_typeinfo_destruct(&ti
);
431 /* if nonzero, free it from the stack */
433 if (!PLAB(A
->file
, slang_asm_local_free
, size
))
440 /* _slang_assemble_operation() */
443 dereference_basic(slang_assemble_ctx
* A
, slang_storage_type type
,
444 GLuint
* size
, slang_swizzle
* swz
, GLboolean is_swizzled
)
447 slang_assembly_type ty
;
449 *size
-= _slang_sizeof_type(type
);
451 /* If swizzling is taking place, we are forced to use scalar
452 * operations, even if we have vec4 instructions enabled (this
453 * should be actually done with special vec4 shuffle instructions).
454 * Adjust the size and calculate the offset within source variable
458 src_offset
= swz
->swizzle
[*size
/ 4] * 4;
462 /* dereference data slot of a basic type */
463 if (!PLAB2(A
->file
, slang_asm_local_addr
, A
->local
.addr_tmp
, 4))
465 if (!PUSH(A
->file
, slang_asm_addr_deref
))
467 if (src_offset
!= 0) {
468 if (!PLAB(A
->file
, slang_asm_addr_push
, src_offset
))
470 if (!PUSH(A
->file
, slang_asm_addr_add
))
475 case slang_stor_bool
:
476 ty
= slang_asm_bool_deref
;
479 ty
= slang_asm_int_deref
;
481 case slang_stor_float
:
482 ty
= slang_asm_float_deref
;
484 #if defined(USE_X86_ASM) || defined(SLANG_X86)
485 case slang_stor_vec4
:
486 ty
= slang_asm_vec4_deref
;
490 _mesa_problem(NULL
, "Unexpected arr->type in dereference_basic");
494 return PUSH(A
->file
, ty
);
498 dereference_aggregate(slang_assemble_ctx
* A
,
499 const slang_storage_aggregate
* agg
, GLuint
* size
,
500 slang_swizzle
* swz
, GLboolean is_swizzled
)
504 for (i
= agg
->count
; i
> 0; i
--) {
505 const slang_storage_array
*arr
= &agg
->arrays
[i
- 1];
508 for (j
= arr
->length
; j
> 0; j
--) {
509 if (arr
->type
== slang_stor_aggregate
) {
510 if (!dereference_aggregate(A
, arr
->aggregate
, size
,
515 if (is_swizzled
&& arr
->type
== slang_stor_vec4
) {
516 if (!dereference_basic(A
, slang_stor_float
, size
, swz
, is_swizzled
))
518 if (!dereference_basic(A
, slang_stor_float
, size
, swz
, is_swizzled
))
520 if (!dereference_basic(A
, slang_stor_float
, size
, swz
, is_swizzled
))
522 if (!dereference_basic(A
, slang_stor_float
, size
, swz
, is_swizzled
))
526 if (!dereference_basic(A
, arr
->type
, size
, swz
, is_swizzled
))
537 _slang_dereference(slang_assemble_ctx
* A
, slang_operation
* op
)
539 slang_assembly_typeinfo ti
;
540 GLboolean result
= GL_FALSE
;
541 slang_storage_aggregate agg
;
544 /* get type information of the given operation */
545 if (!slang_assembly_typeinfo_construct(&ti
))
547 if (!_slang_typeof_operation(A
, op
, &ti
))
550 /* construct aggregate from the type info */
551 if (!slang_storage_aggregate_construct(&agg
))
553 if (!_slang_aggregate_variable(&agg
, &ti
.spec
, ti
.array_len
, A
->space
.funcs
,
554 A
->space
.structs
, A
->space
.vars
, A
->mach
,
558 /* dereference the resulting aggregate */
559 size
= _slang_sizeof_aggregate(&agg
);
560 result
= dereference_aggregate(A
, &agg
, &size
, &ti
.swz
, ti
.is_swizzled
);
563 slang_storage_aggregate_destruct(&agg
);
565 slang_assembly_typeinfo_destruct(&ti
);
571 * Assemble a function call, given a pointer to the actual function to call.
574 _slang_assemble_function_call(slang_assemble_ctx
* A
, slang_function
* fun
,
575 slang_operation
* params
, GLuint param_count
,
576 GLboolean assignment
)
579 slang_swizzle p_swz
[64];
580 slang_ref_type p_ref
[64];
582 const GLuint haveRetValue = _slang_function_has_return_value(fun);
585 /* TODO: fix this, allocate dynamically */
586 if (param_count
> 64)
589 /* make room for the return value, if any */
590 if (fun
->header
.type
.specifier
.type
!= slang_spec_void
) {
593 if (!sizeof_variable(A
, &fun
->header
.type
.specifier
,
594 slang_qual_none
, 0, &ret_size
))
596 if (!PLAB(A
->file
, slang_asm_local_alloc
, ret_size
))
600 /* push the actual parameters on the stack */
601 for (i
= 0; i
< param_count
; i
++) {
602 if (fun
->parameters
->variables
[i
/*+ haveRetValue*/].type
.qualifier
== slang_qual_inout
||
603 fun
->parameters
->variables
[i
/*+ haveRetValue*/].type
.qualifier
== slang_qual_out
) {
604 if (!PLAB2(A
->file
, slang_asm_local_addr
, A
->local
.addr_tmp
, 4))
606 /* TODO: optimize the "out" parameter case */
607 if (!_slang_assemble_operation(A
, ¶ms
[i
], slang_ref_force
))
611 if (!PUSH(A
->file
, slang_asm_addr_copy
))
613 if (!PUSH(A
->file
, slang_asm_addr_deref
))
615 if (i
== 0 && assignment
) {
616 /* duplicate the resulting address */
617 if (!PLAB2(A
->file
, slang_asm_local_addr
, A
->local
.addr_tmp
, 4))
619 if (!PUSH(A
->file
, slang_asm_addr_deref
))
622 if (!_slang_dereference(A
, ¶ms
[i
]))
626 if (!_slang_assemble_operation(A
, ¶ms
[i
], slang_ref_forbid
))
633 /* call the function */
635 printf("CALL FUNCTION %s\n", (char*) fun
->header
.a_name
);
636 slang_print_var_scope(fun
->parameters
, fun
->param_count
);
638 if (!PLAB(A
->file
, slang_asm_call
, fun
->address
))
641 /* pop the parameters from the stack */
642 for (i
= param_count
; i
> 0; i
--) {
647 if (fun
->parameters
->variables
[j
/*+ haveRetValue*/].type
.qualifier
== slang_qual_inout
||
648 fun
->parameters
->variables
[j
/* + haveRetValue*/].type
.qualifier
== slang_qual_out
) {
649 /* for output parameter copy the contents of the formal parameter
650 * back to the original actual parameter
652 if (!_slang_assemble_assignment(A
, ¶ms
[j
]))
654 /* pop the actual parameter's address */
655 if (!PLAB(A
->file
, slang_asm_local_free
, 4))
659 /* pop the value of the parameter */
660 if (!_slang_cleanup_stack(A
, ¶ms
[j
]))
670 * Assemble a function call, given the name of the function to call and a
671 * list of parameters.
674 _slang_assemble_function_call_name(slang_assemble_ctx
* A
, const char *name
,
675 slang_operation
* params
,
676 GLuint param_count
, GLboolean assignment
)
681 atom
= slang_atom_pool_atom(A
->atoms
, name
);
682 if (atom
== SLANG_ATOM_NULL
)
685 _slang_locate_function(A
->space
.funcs
, atom
, params
, param_count
,
686 &A
->space
, A
->atoms
);
688 char *s
= (char *) name
;
689 if (strcmp(name
, "vec4") == 0)
690 printf("LLLLLLLLLLLLLLL locate %s %p\n", s
, (void*) fun
);
695 return _slang_assemble_function_call(A
, fun
, params
, param_count
,
700 assemble_function_call_name_dummyint(slang_assemble_ctx
* A
, const char *name
,
701 slang_operation
* params
)
703 slang_operation p
[2];
707 if (!slang_operation_construct(&p
[1]))
709 p
[1].type
= slang_oper_literal_int
;
710 result
= _slang_assemble_function_call_name(A
, name
, p
, 2, GL_FALSE
);
711 slang_operation_destruct(&p
[1]);
718 slang_assembly_type code1
, code2
;
721 {"float_add", slang_asm_float_add
, slang_asm_float_copy
},
722 {"float_subtract", slang_asm_float_subtract
, slang_asm_float_copy
},
723 {"float_multiply", slang_asm_float_multiply
, slang_asm_float_copy
},
724 {"float_divide", slang_asm_float_divide
, slang_asm_float_copy
},
725 {"float_negate", slang_asm_float_negate
, slang_asm_float_copy
},
726 {"float_min", slang_asm_float_min
, slang_asm_float_copy
},
727 {"float_max", slang_asm_float_max
, slang_asm_float_copy
},
728 {"float_less", slang_asm_float_less
, slang_asm_bool_copy
},
729 {"float_equal", slang_asm_float_equal_exp
, slang_asm_bool_copy
},
730 {"float_to_int", slang_asm_float_to_int
, slang_asm_int_copy
},
731 {"float_sine", slang_asm_float_sine
, slang_asm_float_copy
},
732 {"float_cosine", slang_asm_float_cosine
, slang_asm_float_copy
},
733 {"float_arcsine", slang_asm_float_arcsine
, slang_asm_float_copy
},
734 {"float_arctan", slang_asm_float_arctan
, slang_asm_float_copy
},
735 {"float_power", slang_asm_float_power
, slang_asm_float_copy
},
736 {"float_exp", slang_asm_float_exp
, slang_asm_float_copy
},
737 {"float_exp2", slang_asm_float_exp2
, slang_asm_float_copy
},
738 {"float_rsq", slang_asm_float_rsq
, slang_asm_float_copy
},
739 {"float_rcp", slang_asm_float_rcp
, slang_asm_float_copy
},
740 {"float_log2", slang_asm_float_log2
, slang_asm_float_copy
},
741 {"float_ceil", slang_asm_float_ceil
, slang_asm_float_copy
},
742 {"float_noise1", slang_asm_float_noise1
, slang_asm_float_copy
},
743 {"float_noise2", slang_asm_float_noise2
, slang_asm_float_copy
},
744 {"float_noise3", slang_asm_float_noise3
, slang_asm_float_copy
},
745 {"float_noise4", slang_asm_float_noise4
, slang_asm_float_copy
},
746 {"int_to_float", slang_asm_int_to_float
, slang_asm_float_copy
},
747 {"vec4_tex1d", slang_asm_vec4_tex1d
, slang_asm_none
},
748 {"vec4_texb1d", slang_asm_vec4_tex1d
, slang_asm_none
},
749 {"vec4_texp1d", slang_asm_vec4_tex1d
, slang_asm_none
},
750 {"vec4_tex2d", slang_asm_vec4_tex2d
, slang_asm_none
},
751 {"vec4_texb2d", slang_asm_vec4_tex2d
, slang_asm_none
},
752 {"vec4_texp2d", slang_asm_vec4_tex2d
, slang_asm_none
},
753 {"vec4_tex3d", slang_asm_vec4_tex3d
, slang_asm_none
},
754 {"vec4_texb3d", slang_asm_vec4_tex3d
, slang_asm_none
},
755 {"vec4_texp3d", slang_asm_vec4_tex3d
, slang_asm_none
},
756 {"vec4_texcube", slang_asm_vec4_texcube
, slang_asm_none
},
757 {"vec4_shad1d", slang_asm_vec4_shad1d
, slang_asm_none
},
758 {"vec4_shad2d", slang_asm_vec4_shad2d
, slang_asm_none
},
759 /* GL_MESA_shader_debug */
760 {"float_print", slang_asm_float_deref
, slang_asm_float_print
},
761 {"int_print", slang_asm_int_deref
, slang_asm_int_print
},
762 {"bool_print", slang_asm_bool_deref
, slang_asm_bool_print
},
764 {"float_to_vec4", slang_asm_float_to_vec4
, slang_asm_none
},
765 {"vec4_add", slang_asm_vec4_add
, slang_asm_float_copy
},
766 {"vec4_subtract", slang_asm_vec4_subtract
, slang_asm_float_copy
},
767 {"vec4_multiply", slang_asm_vec4_multiply
, slang_asm_float_copy
},
768 {"vec4_min", slang_asm_vec4_min
, slang_asm_float_copy
},
769 {"vec4_max", slang_asm_vec4_max
, slang_asm_float_copy
},
770 {"vec4_seq", slang_asm_vec4_seq
, slang_asm_float_copy
},
771 {"vec4_sne", slang_asm_vec4_sne
, slang_asm_float_copy
},
772 {"vec4_sge", slang_asm_vec4_sge
, slang_asm_float_copy
},
773 {"vec4_sgt", slang_asm_vec4_sgt
, slang_asm_float_copy
},
774 {"vec4_floor", slang_asm_vec4_floor
, slang_asm_float_copy
},
775 {"vec4_frac", slang_asm_vec4_frac
, slang_asm_float_copy
},
776 {"vec4_abs", slang_asm_vec4_abs
, slang_asm_float_copy
},
778 {"vec4_divide", slang_asm_vec4_divide
, slang_asm_none
},
779 {"vec4_negate", slang_asm_vec4_negate
, slang_asm_none
},
780 {"vec4_dot", slang_asm_vec4_dot
, slang_asm_float_copy
},
781 {"vec3_dot", slang_asm_vec3_dot
, slang_asm_float_copy
},
782 {"vec3_cross", slang_asm_vec3_cross
, slang_asm_float_copy
},
783 {NULL
, slang_asm_none
, slang_asm_none
}
787 call_asm_instruction(slang_assemble_ctx
* A
, slang_atom a_name
)
792 id
= slang_atom_pool_id(A
->atoms
, a_name
);
794 for (i
= 0; inst
[i
].name
!= NULL
; i
++)
795 if (slang_string_compare(id
, inst
[i
].name
) == 0)
797 if (inst
[i
].name
== NULL
)
800 if (!PLAB2(A
->file
, inst
[i
].code1
, 4, 0))
802 if (inst
[i
].code2
!= slang_asm_none
)
803 if (!PLAB2(A
->file
, inst
[i
].code2
, 4, 0))
806 /* clean-up the stack from the remaining dst address */
807 if (!PLAB(A
->file
, slang_asm_local_free
, 4))
814 equality_aggregate(slang_assemble_ctx
* A
,
815 const slang_storage_aggregate
* agg
, GLuint
* index
,
816 GLuint size
, GLuint z_label
)
820 for (i
= 0; i
< agg
->count
; i
++) {
821 const slang_storage_array
*arr
= &agg
->arrays
[i
];
824 for (j
= 0; j
< arr
->length
; j
++) {
825 if (arr
->type
== slang_stor_aggregate
) {
826 if (!equality_aggregate(A
, arr
->aggregate
, index
, size
, z_label
))
830 #if defined(USE_X86_ASM) || defined(SLANG_X86)
831 if (arr
->type
== slang_stor_vec4
) {
832 if (!PLAB2(A
->file
, slang_asm_vec4_equal_int
,
833 size
+ *index
, *index
))
838 if (!PLAB2(A
->file
, slang_asm_float_equal_int
,
839 size
+ *index
, *index
))
842 *index
+= _slang_sizeof_type(arr
->type
);
843 if (!PLAB(A
->file
, slang_asm_jump_if_zero
, z_label
))
853 equality(slang_assemble_ctx
* A
, slang_operation
* op
, GLboolean equal
)
855 slang_assembly_typeinfo ti
;
856 GLboolean result
= GL_FALSE
;
857 slang_storage_aggregate agg
;
859 GLuint skip_jump
, true_label
, true_jump
, false_label
, false_jump
;
861 /* get type of operation */
862 if (!slang_assembly_typeinfo_construct(&ti
))
863 RETURN_OUT_OF_MEMORY();
864 if (!_slang_typeof_operation(A
, op
, &ti
))
867 /* convert it to an aggregate */
868 if (!slang_storage_aggregate_construct(&agg
))
870 if (!_slang_aggregate_variable(&agg
, &ti
.spec
, 0, A
->space
.funcs
,
871 A
->space
.structs
, A
->space
.vars
,
872 A
->mach
, A
->file
, A
->atoms
))
875 /* compute the size of the agregate - there are two such aggregates
878 size
= _slang_sizeof_aggregate(&agg
);
880 /* jump to the actual data-comparison code */
881 skip_jump
= A
->file
->count
;
882 if (!PUSH(A
->file
, slang_asm_jump
))
885 /* pop off the stack the compared data and push 1 */
886 true_label
= A
->file
->count
;
887 if (!PLAB(A
->file
, slang_asm_local_free
, size
* 2))
889 if (!PLIT(A
->file
, slang_asm_bool_push
, (GLfloat
) 1))
891 true_jump
= A
->file
->count
;
892 if (!PUSH(A
->file
, slang_asm_jump
))
895 false_label
= A
->file
->count
;
896 if (!PLAB(A
->file
, slang_asm_local_free
, size
* 2))
898 if (!PLIT(A
->file
, slang_asm_bool_push
, (GLfloat
) 0))
900 false_jump
= A
->file
->count
;
901 if (!PUSH(A
->file
, slang_asm_jump
))
904 A
->file
->code
[skip_jump
].param
[0] = A
->file
->count
;
906 /* compare the data on stack, it will eventually jump either to
907 * true or false label
910 if (!equality_aggregate(A
, &agg
, &index
, size
,
911 equal
? false_label
: true_label
))
913 if (!PLAB(A
->file
, slang_asm_jump
, equal
? true_label
: false_label
))
916 A
->file
->code
[true_jump
].param
[0] = A
->file
->count
;
917 A
->file
->code
[false_jump
].param
[0] = A
->file
->count
;
921 slang_storage_aggregate_destruct(&agg
);
923 slang_assembly_typeinfo_destruct(&ti
);
928 handle_subscript(slang_assemble_ctx
* A
, slang_assembly_typeinfo
* tie
,
929 slang_assembly_typeinfo
* tia
, slang_operation
* op
,
932 GLuint asize
= 0, esize
= 0;
934 /* get type info of the master expression (matrix, vector or an array */
935 if (!_slang_typeof_operation(A
, &op
->children
[0], tia
))
937 if (!sizeof_variable(A
, &tia
->spec
, slang_qual_none
,
938 tia
->array_len
, &asize
))
941 /* get type info of the result (matrix column, vector row or array element) */
942 if (!_slang_typeof_operation(A
, op
, tie
))
944 if (!sizeof_variable(A
, &tie
->spec
, slang_qual_none
, 0, &esize
))
947 /* assemble the master expression */
948 if (!_slang_assemble_operation(A
, &op
->children
[0], ref
))
951 /* when indexing an l-value swizzle, push the swizzle_tmp */
952 if (ref
== slang_ref_force
&& tia
->is_swizzled
)
953 if (!PLAB2(A
->file
, slang_asm_local_addr
, A
->local
.swizzle_tmp
, 16))
956 /* assemble the subscript expression */
957 if (!_slang_assemble_operation(A
, &op
->children
[1], slang_ref_forbid
))
960 if (ref
== slang_ref_force
&& tia
->is_swizzled
) {
963 /* copy the swizzle indexes to the swizzle_tmp */
964 for (i
= 0; i
< tia
->swz
.num_components
; i
++) {
965 if (!PLAB2(A
->file
, slang_asm_local_addr
, A
->local
.swizzle_tmp
, 16))
967 if (!PLAB(A
->file
, slang_asm_addr_push
, i
* 4))
969 if (!PUSH(A
->file
, slang_asm_addr_add
))
971 if (!PLAB(A
->file
, slang_asm_addr_push
, tia
->swz
.swizzle
[i
]))
973 if (!PUSH(A
->file
, slang_asm_addr_copy
))
975 if (!PLAB(A
->file
, slang_asm_local_free
, 4))
979 /* offset the pushed swizzle_tmp address and dereference it */
980 if (!PUSH(A
->file
, slang_asm_int_to_addr
))
982 if (!PLAB(A
->file
, slang_asm_addr_push
, 4))
984 if (!PUSH(A
->file
, slang_asm_addr_multiply
))
986 if (!PUSH(A
->file
, slang_asm_addr_add
))
988 if (!PUSH(A
->file
, slang_asm_addr_deref
))
992 /* convert the integer subscript to a relative address */
993 if (!PUSH(A
->file
, slang_asm_int_to_addr
))
997 if (!PLAB(A
->file
, slang_asm_addr_push
, esize
))
999 if (!PUSH(A
->file
, slang_asm_addr_multiply
))
1002 if (ref
== slang_ref_force
) {
1003 /* offset the base address with the relative address */
1004 if (!PUSH(A
->file
, slang_asm_addr_add
))
1010 /* move the selected element to the beginning of the master expression */
1011 for (i
= 0; i
< esize
; i
+= 4)
1012 if (!PLAB2(A
->file
, slang_asm_float_move
,
1013 asize
- esize
+ i
+ 4, i
+ 4))
1015 if (!PLAB(A
->file
, slang_asm_local_free
, 4))
1018 /* free the rest of the master expression */
1019 if (!PLAB(A
->file
, slang_asm_local_free
, asize
- esize
))
1027 handle_field(slang_assemble_ctx
* A
, slang_assembly_typeinfo
* tia
,
1028 slang_assembly_typeinfo
* tib
, slang_operation
* op
,
1031 /* get type info of the result (field or swizzle) */
1032 if (!_slang_typeof_operation(A
, op
, tia
))
1035 /* get type info of the master expression being accessed (struct or vector) */
1036 if (!_slang_typeof_operation(A
, &op
->children
[0], tib
))
1039 /* if swizzling a vector in-place, the swizzle temporary is needed */
1040 if (ref
== slang_ref_forbid
&& tia
->is_swizzled
)
1041 if (!PLAB2(A
->file
, slang_asm_local_addr
, A
->local
.swizzle_tmp
, 16))
1042 RETURN_OUT_OF_MEMORY();
1044 /* assemble the master expression */
1045 if (!_slang_assemble_operation(A
, &op
->children
[0], ref
))
1048 /* assemble the field expression */
1049 if (tia
->is_swizzled
) {
1050 if (ref
== slang_ref_force
) {
1052 if (tia
->swz
.num_components
== 1) {
1053 /* simple case - adjust the vector's address to point to
1054 * the selected component
1056 if (!PLAB(file
, slang_asm_addr_push
, tia
->swz
.swizzle
[0] * 4))
1057 RETURN_OUT_OF_MEMORY();
1058 if (!PUSH(file
, slang_asm_addr_add
))
1059 RETURN_OUT_OF_MEMORY();
1064 /* two or more vector components are being referenced -
1065 * the so-called write mask must be passed to the upper
1066 * operations and applied when assigning value to this swizzle
1072 /* swizzle the vector in-place using the swizzle temporary */
1073 if (!_slang_assemble_constructor_from_swizzle(A
, &tia
->swz
,
1074 &tia
->spec
, &tib
->spec
))
1079 GLuint i
, struct_size
= 0, field_offset
= 0, field_size
= 0;
1082 * Calculate struct size, field offset and field size.
1084 for (i
= 0; i
< tib
->spec
._struct
->fields
->num_variables
; i
++) {
1085 slang_variable
*field
;
1086 slang_storage_aggregate agg
;
1089 field
= &tib
->spec
._struct
->fields
->variables
[i
];
1090 if (!slang_storage_aggregate_construct(&agg
))
1092 if (!_slang_aggregate_variable(&agg
, &field
->type
.specifier
,
1093 field
->array_len
, A
->space
.funcs
,
1094 A
->space
.structs
, A
->space
.vars
,
1095 A
->mach
, A
->file
, A
->atoms
)) {
1096 slang_storage_aggregate_destruct(&agg
);
1099 size
= _slang_sizeof_aggregate(&agg
);
1100 slang_storage_aggregate_destruct(&agg
);
1102 if (op
->a_id
== field
->a_name
) {
1104 field_offset
= struct_size
;
1106 struct_size
+= size
;
1109 if (ref
== slang_ref_force
) {
1113 * OPTIMIZATION: If selecting first field, no address shifting
1116 shift
= (field_offset
!= 0);
1119 if (!PLAB(A
->file
, slang_asm_addr_push
, field_offset
))
1120 RETURN_OUT_OF_MEMORY();
1121 if (!PUSH(A
->file
, slang_asm_addr_add
))
1122 RETURN_OUT_OF_MEMORY();
1126 GLboolean relocate
, shrink
;
1130 * OPTIMIZATION: If selecting last field, no relocation is needed.
1132 relocate
= (field_offset
!= (struct_size
- field_size
));
1135 * OPTIMIZATION: If field and struct sizes are equal, no partial
1138 shrink
= (field_size
!= struct_size
);
1144 * Move the selected element to the end of the master expression.
1145 * Do it in reverse order to avoid overwriting itself.
1147 if (!PLAB(A
->file
, slang_asm_addr_push
, field_offset
))
1148 RETURN_OUT_OF_MEMORY();
1149 for (i
= field_size
; i
> 0; i
-= 4)
1150 if (!PLAB2(A
->file
, slang_asm_float_move
,
1151 struct_size
- field_size
+ i
, i
))
1152 RETURN_OUT_OF_MEMORY();
1157 /* free the rest of the master expression */
1158 free_b
+= struct_size
- field_size
;
1162 if (!PLAB(A
->file
, slang_asm_local_free
, free_b
))
1163 RETURN_OUT_OF_MEMORY();
1172 _slang_assemble_operation(slang_assemble_ctx
* A
, slang_operation
* op
,
1175 /* set default results */
1176 A
->ref
= /*(ref == slang_ref_freelance) ? slang_ref_force : */ ref
;
1177 A
->swz
.num_components
= 0;
1180 case slang_oper_block_no_new_scope
:
1181 case slang_oper_block_new_scope
:
1185 for (i
= 0; i
< op
->num_children
; i
++) {
1186 if (!_slang_assemble_operation(A
, &op
->children
[i
],
1187 slang_ref_forbid
/*slang_ref_freelance */ ))
1189 if (!_slang_cleanup_stack(A
, &op
->children
[i
]))
1194 case slang_oper_variable_decl
:
1197 slang_operation assign
;
1200 /* Construct assignment expression placeholder. */
1201 if (!slang_operation_construct(&assign
))
1203 assign
.type
= slang_oper_assign
;
1204 assign
.children
= slang_operation_new(2);
1205 if (assign
.children
== NULL
) {
1206 slang_operation_destruct(&assign
);
1209 for (assign
.num_children
= 0; assign
.num_children
< 2;
1210 assign
.num_children
++)
1211 if (!slang_operation_construct(&assign
.children
1212 [assign
.num_children
])) {
1213 slang_operation_destruct(&assign
);
1214 RETURN_OUT_OF_MEMORY();
1218 for (i
= 0; i
< op
->num_children
; i
++) {
1219 slang_variable
*var
;
1222 _slang_locate_variable(op
->children
[i
].locals
,
1223 op
->children
[i
].a_id
, GL_TRUE
);
1228 if (var
->initializer
== NULL
)
1231 if (!slang_operation_copy(&assign
.children
[0], &op
->children
[i
])
1232 || !slang_operation_copy(&assign
.children
[1],
1234 || !_slang_assemble_assign(A
, &assign
, "=", slang_ref_forbid
)
1235 || !_slang_cleanup_stack(A
, &assign
)) {
1240 slang_operation_destruct(&assign
);
1245 case slang_oper_asm
:
1248 if (!_slang_assemble_operation(A
, &op
->children
[0], slang_ref_force
))
1250 for (i
= 1; i
< op
->num_children
; i
++)
1251 if (!_slang_assemble_operation(A
, &op
->children
[i
],
1254 if (!call_asm_instruction(A
, op
->a_id
))
1255 RETURN_ERROR2("Unknown __asm call", (char*) op
->a_id
, 0);
1258 case slang_oper_break
:
1259 if (!PLAB(A
->file
, slang_asm_jump
, A
->flow
.loop_end
))
1260 RETURN_OUT_OF_MEMORY();
1262 case slang_oper_continue
:
1263 if (!PLAB(A
->file
, slang_asm_jump
, A
->flow
.loop_start
))
1264 RETURN_OUT_OF_MEMORY();
1266 case slang_oper_discard
:
1267 if (!PUSH(A
->file
, slang_asm_discard
))
1268 RETURN_OUT_OF_MEMORY();
1269 if (!PUSH(A
->file
, slang_asm_exit
))
1270 RETURN_OUT_OF_MEMORY();
1272 case slang_oper_return
:
1273 if (A
->local
.ret_size
!= 0) {
1274 /* push the result's address */
1275 if (!PLAB2(A
->file
, slang_asm_local_addr
, 0, A
->local
.ret_size
))
1276 RETURN_OUT_OF_MEMORY();
1277 if (!_slang_assemble_operation(A
, &op
->children
[0], slang_ref_forbid
))
1280 A
->swz
.num_components
= 0;
1281 /* assign the operation to the function result (it was reserved on the stack) */
1282 if (!_slang_assemble_assignment(A
, op
->children
))
1285 if (!PLAB(A
->file
, slang_asm_local_free
, 4))
1286 RETURN_OUT_OF_MEMORY();
1288 if (!PLAB(A
->file
, slang_asm_jump
, A
->flow
.function_end
))
1289 RETURN_OUT_OF_MEMORY();
1291 case slang_oper_expression
:
1292 if (ref
== slang_ref_force
)
1294 if (!_slang_assemble_operation(A
, &op
->children
[0], ref
))
1298 if (!_slang_assemble_if(A
, op
))
1301 case slang_oper_while
:
1302 if (!_slang_assemble_while(A
, op
))
1306 if (!_slang_assemble_do(A
, op
))
1309 case slang_oper_for
:
1310 if (!_slang_assemble_for(A
, op
))
1313 case slang_oper_void
:
1315 case slang_oper_literal_bool
:
1316 if (ref
== slang_ref_force
)
1318 if (!PLIT(A
->file
, slang_asm_bool_push
, op
->literal
[0]))
1319 RETURN_OUT_OF_MEMORY();
1320 A
->ref
= slang_ref_forbid
;
1322 case slang_oper_literal_int
:
1323 if (ref
== slang_ref_force
)
1325 if (!PLIT(A
->file
, slang_asm_int_push
, op
->literal
[0]))
1326 RETURN_OUT_OF_MEMORY();
1327 A
->ref
= slang_ref_forbid
;
1329 case slang_oper_literal_float
:
1330 if (ref
== slang_ref_force
)
1332 if (!PLIT(A
->file
, slang_asm_float_push
, op
->literal
[0]))
1333 RETURN_OUT_OF_MEMORY();
1334 A
->ref
= slang_ref_forbid
;
1336 case slang_oper_identifier
:
1338 slang_variable
*var
;
1341 /* find the variable and calculate its size */
1342 var
= _slang_locate_variable(op
->locals
, op
->a_id
, GL_TRUE
);
1344 RETURN_ERROR2("undefined variable", (char *) op
->a_id
, 0);
1346 if (!sizeof_variable(A
, &var
->type
.specifier
, slang_qual_none
,
1347 var
->array_len
, &size
))
1348 RETURN_OUT_OF_MEMORY();
1350 /* prepare stack for dereferencing */
1351 if (ref
== slang_ref_forbid
)
1352 if (!PLAB2(A
->file
, slang_asm_local_addr
, A
->local
.addr_tmp
, 4))
1353 RETURN_OUT_OF_MEMORY();
1355 /* push the variable's address */
1357 if (!PLAB(A
->file
, slang_asm_global_addr
, var
->address
))
1358 RETURN_OUT_OF_MEMORY();
1361 if (!PLAB2(A
->file
, slang_asm_local_addr
, var
->address
, size
))
1362 RETURN_OUT_OF_MEMORY();
1365 /* perform the dereference */
1366 if (ref
== slang_ref_forbid
) {
1367 if (!PUSH(A
->file
, slang_asm_addr_copy
))
1368 RETURN_OUT_OF_MEMORY();
1369 if (!PLAB(A
->file
, slang_asm_local_free
, 4))
1370 RETURN_OUT_OF_MEMORY();
1371 if (!_slang_dereference(A
, op
))
1376 case slang_oper_sequence
:
1377 if (ref
== slang_ref_force
)
1379 if (!_slang_assemble_operation(A
, &op
->children
[0],
1380 slang_ref_forbid
/*slang_ref_freelance */ ))
1382 if (!_slang_cleanup_stack(A
, &op
->children
[0]))
1384 if (!_slang_assemble_operation(A
, &op
->children
[1], slang_ref_forbid
))
1386 A
->ref
= slang_ref_forbid
;
1388 case slang_oper_assign
:
1389 if (!_slang_assemble_assign(A
, op
, "=", ref
))
1392 case slang_oper_addassign
:
1393 if (!_slang_assemble_assign(A
, op
, "+=", ref
))
1397 case slang_oper_subassign
:
1398 if (!_slang_assemble_assign(A
, op
, "-=", ref
))
1402 case slang_oper_mulassign
:
1403 if (!_slang_assemble_assign(A
, op
, "*=", ref
))
1407 /*case slang_oper_modassign: */
1408 /*case slang_oper_lshassign: */
1409 /*case slang_oper_rshassign: */
1410 /*case slang_oper_orassign: */
1411 /*case slang_oper_xorassign: */
1412 /*case slang_oper_andassign: */
1413 case slang_oper_divassign
:
1414 if (!_slang_assemble_assign(A
, op
, "/=", ref
))
1418 case slang_oper_select
:
1419 if (!_slang_assemble_select(A
, op
))
1421 A
->ref
= slang_ref_forbid
;
1423 case slang_oper_logicalor
:
1424 if (!_slang_assemble_logicalor(A
, op
))
1426 A
->ref
= slang_ref_forbid
;
1428 case slang_oper_logicaland
:
1429 if (!_slang_assemble_logicaland(A
, op
))
1431 A
->ref
= slang_ref_forbid
;
1433 case slang_oper_logicalxor
:
1434 if (!_slang_assemble_function_call_name(A
, "^^", op
->children
, 2, GL_FALSE
))
1436 A
->ref
= slang_ref_forbid
;
1438 /*case slang_oper_bitor: */
1439 /*case slang_oper_bitxor: */
1440 /*case slang_oper_bitand: */
1441 case slang_oper_less
:
1442 if (!_slang_assemble_function_call_name(A
, "<", op
->children
, 2, GL_FALSE
))
1444 A
->ref
= slang_ref_forbid
;
1446 case slang_oper_greater
:
1447 if (!_slang_assemble_function_call_name(A
, ">", op
->children
, 2, GL_FALSE
))
1449 A
->ref
= slang_ref_forbid
;
1451 case slang_oper_lessequal
:
1452 if (!_slang_assemble_function_call_name(A
, "<=", op
->children
, 2, GL_FALSE
))
1454 A
->ref
= slang_ref_forbid
;
1456 case slang_oper_greaterequal
:
1457 if (!_slang_assemble_function_call_name(A
, ">=", op
->children
, 2, GL_FALSE
))
1459 A
->ref
= slang_ref_forbid
;
1461 /*case slang_oper_lshift: */
1462 /*case slang_oper_rshift: */
1463 case slang_oper_add
:
1464 if (!_slang_assemble_function_call_name(A
, "+", op
->children
, 2, GL_FALSE
))
1466 A
->ref
= slang_ref_forbid
;
1468 case slang_oper_subtract
:
1469 if (!_slang_assemble_function_call_name(A
, "-", op
->children
, 2, GL_FALSE
))
1471 A
->ref
= slang_ref_forbid
;
1473 case slang_oper_multiply
:
1474 if (!_slang_assemble_function_call_name(A
, "*", op
->children
, 2, GL_FALSE
))
1476 A
->ref
= slang_ref_forbid
;
1478 /*case slang_oper_modulus: */
1479 case slang_oper_divide
:
1480 if (!_slang_assemble_function_call_name(A
, "/", op
->children
, 2, GL_FALSE
))
1482 A
->ref
= slang_ref_forbid
;
1484 case slang_oper_equal
:
1485 if (!_slang_assemble_operation(A
, &op
->children
[0], slang_ref_forbid
))
1487 if (!_slang_assemble_operation(A
, &op
->children
[1], slang_ref_forbid
))
1489 if (!equality(A
, op
->children
, GL_TRUE
))
1491 A
->ref
= slang_ref_forbid
;
1493 case slang_oper_notequal
:
1494 if (!_slang_assemble_operation(A
, &op
->children
[0], slang_ref_forbid
))
1496 if (!_slang_assemble_operation(A
, &op
->children
[1], slang_ref_forbid
))
1498 if (!equality(A
, op
->children
, GL_FALSE
))
1500 A
->ref
= slang_ref_forbid
;
1502 case slang_oper_preincrement
:
1503 if (!_slang_assemble_assign(A
, op
, "++", ref
))
1507 case slang_oper_predecrement
:
1508 if (!_slang_assemble_assign(A
, op
, "--", ref
))
1512 case slang_oper_plus
:
1513 if (!_slang_dereference(A
, op
))
1515 A
->ref
= slang_ref_forbid
;
1517 case slang_oper_minus
:
1518 if (!_slang_assemble_function_call_name(A
, "-", op
->children
, 1, GL_FALSE
))
1520 A
->ref
= slang_ref_forbid
;
1522 /*case slang_oper_complement: */
1523 case slang_oper_not
:
1524 if (!_slang_assemble_function_call_name(A
, "!", op
->children
, 1, GL_FALSE
))
1526 A
->ref
= slang_ref_forbid
;
1528 case slang_oper_subscript
:
1530 slang_assembly_typeinfo ti_arr
, ti_elem
;
1532 if (!slang_assembly_typeinfo_construct(&ti_arr
))
1533 RETURN_OUT_OF_MEMORY();
1534 if (!slang_assembly_typeinfo_construct(&ti_elem
)) {
1535 slang_assembly_typeinfo_destruct(&ti_arr
);
1536 RETURN_OUT_OF_MEMORY();
1538 if (!handle_subscript(A
, &ti_elem
, &ti_arr
, op
, ref
)) {
1539 slang_assembly_typeinfo_destruct(&ti_arr
);
1540 slang_assembly_typeinfo_destruct(&ti_elem
);
1543 slang_assembly_typeinfo_destruct(&ti_arr
);
1544 slang_assembly_typeinfo_destruct(&ti_elem
);
1547 case slang_oper_call
:
1550 = _slang_locate_function(A
->space
.funcs
, op
->a_id
, op
->children
,
1551 op
->num_children
, &A
->space
, A
->atoms
);
1553 if (!_slang_assemble_constructor(A
, op
))
1554 RETURN_OUT_OF_MEMORY();
1557 if (!_slang_assemble_function_call(A
, fun
, op
->children
,
1558 op
->num_children
, GL_FALSE
))
1561 A
->ref
= slang_ref_forbid
;
1564 case slang_oper_field
:
1566 slang_assembly_typeinfo ti_after
, ti_before
;
1568 if (!slang_assembly_typeinfo_construct(&ti_after
))
1569 RETURN_OUT_OF_MEMORY();
1570 if (!slang_assembly_typeinfo_construct(&ti_before
)) {
1571 slang_assembly_typeinfo_destruct(&ti_after
);
1572 RETURN_OUT_OF_MEMORY();
1574 if (!handle_field(A
, &ti_after
, &ti_before
, op
, ref
)) {
1575 slang_assembly_typeinfo_destruct(&ti_after
);
1576 slang_assembly_typeinfo_destruct(&ti_before
);
1579 slang_assembly_typeinfo_destruct(&ti_after
);
1580 slang_assembly_typeinfo_destruct(&ti_before
);
1583 case slang_oper_postincrement
:
1584 if (!assemble_function_call_name_dummyint(A
, "++", op
->children
))
1586 A
->ref
= slang_ref_forbid
;
1588 case slang_oper_postdecrement
:
1589 if (!assemble_function_call_name_dummyint(A
, "--", op
->children
))
1591 A
->ref
= slang_ref_forbid
;