updated some printfs, added comment about sched_yield
[mesa.git] / src / mesa / shader / slang / slang_assemble.c
index b8f9d78b7af6d5cac5e6184be0beeef356969d35..faa13b33e69336bd0ac60b37686fce2cc6c27a59 100644 (file)
  */\r
 \r
 #include "imports.h"\r
-#include "slang_utility.h"\r
 #include "slang_assemble.h"\r
+#include "slang_compile.h"\r
 #include "slang_storage.h"\r
-#include "slang_assemble_typeinfo.h"\r
-#include "slang_assemble_conditional.h"\r
-#include "slang_assemble_assignment.h"\r
-#include "slang_execute.h"\r
 \r
 /* slang_assembly */\r
 \r
@@ -156,14 +152,14 @@ GLboolean slang_assembly_file_restore_point_load (slang_assembly_file *file,
 /* utility functions */\r
 \r
 static GLboolean sizeof_variable (slang_assemble_ctx *A, slang_type_specifier *spec,\r
-       slang_type_qualifier qual, slang_operation *array_size, GLuint *size)\r
+       slang_type_qualifier qual, GLuint array_len, GLuint *size)\r
 {\r
        slang_storage_aggregate agg;\r
 \r
        /* calculate the size of the variable's aggregate */\r
        if (!slang_storage_aggregate_construct (&agg))\r
                return GL_FALSE;\r
-       if (!_slang_aggregate_variable (&agg, spec, array_size, A->space.funcs, A->space.structs,\r
+       if (!_slang_aggregate_variable (&agg, spec, array_len, A->space.funcs, A->space.structs,\r
                        A->space.vars, A->mach, A->file, A->atoms))\r
        {\r
                slang_storage_aggregate_destruct (&agg);\r
@@ -184,7 +180,7 @@ static GLboolean sizeof_variable2 (slang_assemble_ctx *A, slang_variable *var, G
        var->address = *size;\r
        if (var->type.qualifier == slang_qual_out || var->type.qualifier == slang_qual_inout)\r
                var->address += 4;\r
-       return sizeof_variable (A, &var->type.specifier, var->type.qualifier, var->array_size, size);\r
+       return sizeof_variable (A, &var->type.specifier, var->type.qualifier, var->array_len, size);\r
 }\r
 \r
 static GLboolean sizeof_variables (slang_assemble_ctx *A, slang_variable_scope *vars, GLuint start,\r
@@ -233,7 +229,7 @@ slang_function *_slang_locate_function (slang_function_scope *funcs, slang_atom
 \r
                        if (!slang_assembly_typeinfo_construct (&ti))\r
                                return NULL;\r
-                       if (!_slang_typeof_operation (&params[j], space, &ti, atoms))\r
+                       if (!_slang_typeof_operation_ (&params[j], space, &ti, atoms))\r
                        {\r
                                slang_assembly_typeinfo_destruct (&ti);\r
                                return NULL;\r
@@ -301,7 +297,7 @@ GLboolean _slang_assemble_function (slang_assemble_ctx *A, slang_function *fun)
        /* calculate return value size */\r
        param_size = 0;\r
        if (fun->header.type.specifier.type != slang_spec_void)\r
-               if (!sizeof_variable (A, &fun->header.type.specifier, slang_qual_none, NULL, &param_size))\r
+               if (!sizeof_variable (A, &fun->header.type.specifier, slang_qual_none, 0, &param_size))\r
                        return GL_FALSE;\r
        A->local.ret_size = param_size;\r
 \r
@@ -344,7 +340,7 @@ GLboolean _slang_assemble_function (slang_assemble_ctx *A, slang_function *fun)
 \r
        /* execute the function body */\r
        A->file->code[skip].param[0] = A->file->count;\r
-       if (!_slang_assemble_operation_ (A, fun->body, /*slang_ref_freelance*/slang_ref_forbid))\r
+       if (!_slang_assemble_operation (A, fun->body, /*slang_ref_freelance*/slang_ref_forbid))\r
                return GL_FALSE;\r
 \r
        /* this is the end of the function - restore the old function frame */\r
@@ -363,7 +359,7 @@ GLboolean _slang_assemble_function (slang_assemble_ctx *A, slang_function *fun)
        return GL_TRUE;\r
 }\r
 \r
-GLboolean _slang_cleanup_stack_ (slang_assemble_ctx *A, slang_operation *op)\r
+GLboolean _slang_cleanup_stack (slang_assemble_ctx *A, slang_operation *op)\r
 {\r
        slang_assembly_typeinfo ti;\r
        GLuint size = 0;\r
@@ -371,19 +367,21 @@ GLboolean _slang_cleanup_stack_ (slang_assemble_ctx *A, slang_operation *op)
        /* get type info of the operation and calculate its size */\r
        if (!slang_assembly_typeinfo_construct (&ti))\r
                return GL_FALSE;\r
-       if (!_slang_typeof_operation (op, &A->space, &ti, A->atoms))\r
+       if (!_slang_typeof_operation (A, op, &ti))\r
        {\r
                slang_assembly_typeinfo_destruct (&ti);\r
                return GL_FALSE;\r
        }\r
-       if (ti.spec.type != slang_spec_void)\r
-               if (A->ref == slang_ref_force)\r
+       if (ti.spec.type != slang_spec_void) {\r
+               if (A->ref == slang_ref_force) {\r
                        size = 4;\r
-               else if (!sizeof_variable (A, &ti.spec, slang_qual_none, NULL, &size))\r
+               }\r
+               else if (!sizeof_variable (A, &ti.spec, slang_qual_none, 0, &size))\r
                {\r
                        slang_assembly_typeinfo_destruct (&ti);\r
                        return GL_FALSE;\r
                }\r
+       }\r
        slang_assembly_typeinfo_destruct (&ti);\r
 \r
        /* if nonzero, free it from the stack */\r
@@ -478,13 +476,13 @@ GLboolean _slang_dereference (slang_assemble_ctx *A, slang_operation *op)
        /* get type information of the given operation */\r
        if (!slang_assembly_typeinfo_construct (&ti))\r
                return GL_FALSE;\r
-       if (!_slang_typeof_operation (op, &A->space, &ti, A->atoms))\r
+       if (!_slang_typeof_operation (A, op, &ti))\r
                goto end1;\r
 \r
        /* construct aggregate from the type info */\r
        if (!slang_storage_aggregate_construct (&agg))\r
                goto end1;\r
-       if (!_slang_aggregate_variable (&agg, &ti.spec, ti.array_size, A->space.funcs, A->space.structs,\r
+       if (!_slang_aggregate_variable (&agg, &ti.spec, ti.array_len, A->space.funcs, A->space.structs,\r
                        A->space.vars, A->mach, A->file, A->atoms))\r
                goto end;\r
 \r
@@ -515,7 +513,7 @@ GLboolean _slang_assemble_function_call (slang_assemble_ctx *A, slang_function *
        {\r
                GLuint ret_size = 0;\r
 \r
-               if (!sizeof_variable (A, &fun->header.type.specifier, slang_qual_none, NULL, &ret_size))\r
+               if (!sizeof_variable (A, &fun->header.type.specifier, slang_qual_none, 0, &ret_size))\r
                        return GL_FALSE;\r
                if (!PLAB (A->file, slang_asm_local_alloc, ret_size))\r
                        return GL_FALSE;\r
@@ -530,7 +528,7 @@ GLboolean _slang_assemble_function_call (slang_assemble_ctx *A, slang_function *
                        if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4))\r
                                return GL_FALSE;\r
                        /* TODO: optimize the "out" parameter case */\r
-                       if (!_slang_assemble_operation_ (A, &params[i], slang_ref_force))\r
+                       if (!_slang_assemble_operation (A, &params[i], slang_ref_force))\r
                                return GL_FALSE;\r
                        p_swz[i] = A->swz;\r
                        p_ref[i] = A->ref;\r
@@ -551,7 +549,7 @@ GLboolean _slang_assemble_function_call (slang_assemble_ctx *A, slang_function *
                }\r
                else\r
                {\r
-                       if (!_slang_assemble_operation_ (A, &params[i], slang_ref_forbid))\r
+                       if (!_slang_assemble_operation (A, &params[i], slang_ref_forbid))\r
                                return GL_FALSE;\r
                        p_swz[i] = A->swz;\r
                        p_ref[i] = A->ref;\r
@@ -583,7 +581,7 @@ GLboolean _slang_assemble_function_call (slang_assemble_ctx *A, slang_function *
                else\r
                {\r
                        /* pop the value of the parameter */\r
-                       if (!_slang_cleanup_stack_ (A, &params[j]))\r
+                       if (!_slang_cleanup_stack (A, &params[j]))\r
                                return GL_FALSE;\r
                }\r
        }\r
@@ -646,6 +644,12 @@ static const struct
        { "float_noise3",   slang_asm_float_noise3,   slang_asm_float_copy },\r
        { "float_noise4",   slang_asm_float_noise4,   slang_asm_float_copy },\r
        { "int_to_float",   slang_asm_int_to_float,   slang_asm_float_copy },\r
+       { "vec4_tex1d",     slang_asm_vec4_tex1d,     slang_asm_none },\r
+       { "vec4_tex2d",     slang_asm_vec4_tex2d,     slang_asm_none },\r
+       { "vec4_tex3d",     slang_asm_vec4_tex3d,     slang_asm_none },\r
+       { "vec4_texcube",   slang_asm_vec4_texcube,   slang_asm_none },\r
+       { "vec4_shad1d",    slang_asm_vec4_shad1d,    slang_asm_none },\r
+       { "vec4_shad2d",    slang_asm_vec4_shad2d,    slang_asm_none },\r
        /* mesa-specific extensions */\r
        { "float_print",    slang_asm_float_deref,    slang_asm_float_print },\r
        { "int_print",      slang_asm_int_deref,      slang_asm_int_print },\r
@@ -721,13 +725,13 @@ static GLboolean equality (slang_assemble_ctx *A, slang_operation *op, GLboolean
        /* get type of operation */\r
        if (!slang_assembly_typeinfo_construct (&ti))\r
                return GL_FALSE;\r
-       if (!_slang_typeof_operation (op, &A->space, &ti, A->atoms))\r
+       if (!_slang_typeof_operation (A, op, &ti))\r
                goto end1;\r
 \r
        /* convert it to an aggregate */\r
        if (!slang_storage_aggregate_construct (&agg))\r
                goto end1;\r
-       if (!_slang_aggregate_variable (&agg, &ti.spec, NULL, A->space.funcs, A->space.structs,\r
+       if (!_slang_aggregate_variable (&agg, &ti.spec, 0, A->space.funcs, A->space.structs,\r
                        A->space.vars, A->mach, A->file, A->atoms))\r
                goto end;\r
 \r
@@ -784,19 +788,19 @@ static GLboolean handle_subscript (slang_assemble_ctx *A, slang_assembly_typeinf
        GLuint asize = 0, esize = 0;\r
 \r
        /* get type info of the master expression (matrix, vector or an array */\r
-       if (!_slang_typeof_operation (&op->children[0], &A->space, tia, A->atoms))\r
+       if (!_slang_typeof_operation (A, &op->children[0], tia))\r
                return GL_FALSE;\r
-       if (!sizeof_variable (A, &tia->spec, slang_qual_none, tia->array_size, &asize))\r
+       if (!sizeof_variable (A, &tia->spec, slang_qual_none, tia->array_len, &asize))\r
                return GL_FALSE;\r
 \r
        /* get type info of the result (matrix column, vector row or array element) */\r
-       if (!_slang_typeof_operation (op, &A->space, tie, A->atoms))\r
+       if (!_slang_typeof_operation (A, op, tie))\r
                return GL_FALSE;\r
-       if (!sizeof_variable (A, &tie->spec, slang_qual_none, NULL, &esize))\r
+       if (!sizeof_variable (A, &tie->spec, slang_qual_none, 0, &esize))\r
                return GL_FALSE;\r
 \r
        /* assemble the master expression */\r
-       if (!_slang_assemble_operation_ (A, &op->children[0], ref))\r
+       if (!_slang_assemble_operation (A, &op->children[0], ref))\r
                return GL_FALSE;\r
 \r
        /* when indexing an l-value swizzle, push the swizzle_tmp */\r
@@ -805,7 +809,7 @@ static GLboolean handle_subscript (slang_assemble_ctx *A, slang_assembly_typeinf
                        return GL_FALSE;\r
 \r
        /* assemble the subscript expression */\r
-       if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid))\r
+       if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))\r
                return GL_FALSE;\r
 \r
        if (ref == slang_ref_force && tia->is_swizzled)\r
@@ -882,11 +886,11 @@ static GLboolean handle_field (slang_assemble_ctx *A, slang_assembly_typeinfo *t
        slang_assembly_typeinfo *tib, slang_operation *op, slang_ref_type ref)\r
 {\r
        /* get type info of the result (field or swizzle) */\r
-       if (!_slang_typeof_operation (op, &A->space, tia, A->atoms))\r
+       if (!_slang_typeof_operation (A, op, tia))\r
                return GL_FALSE;\r
 \r
        /* get type info of the master expression being accessed (struct or vector) */\r
-       if (!_slang_typeof_operation (&op->children[0], &A->space, tib, A->atoms))\r
+       if (!_slang_typeof_operation (A, &op->children[0], tib))\r
                return GL_FALSE;\r
 \r
        /* if swizzling a vector in-place, the swizzle temporary is needed */\r
@@ -895,7 +899,7 @@ static GLboolean handle_field (slang_assemble_ctx *A, slang_assembly_typeinfo *t
                        return GL_FALSE;\r
 \r
        /* assemble the master expression */\r
-       if (!_slang_assemble_operation_ (A, &op->children[0], ref))\r
+       if (!_slang_assemble_operation (A, &op->children[0], ref))\r
                return GL_FALSE;\r
 \r
        /* assemble the field expression */\r
@@ -931,7 +935,9 @@ static GLboolean handle_field (slang_assemble_ctx *A, slang_assembly_typeinfo *t
        else\r
        {\r
                GLuint i, struct_size = 0, field_offset = 0, field_size = 0;\r
+               GLboolean relocate, shrink;\r
 \r
+               /* calculate struct size, field offset and field size */\r
                for (i = 0; i < tib->spec._struct->fields->num_variables; i++)\r
                {\r
                        slang_variable *field;\r
@@ -941,7 +947,7 @@ static GLboolean handle_field (slang_assemble_ctx *A, slang_assembly_typeinfo *t
                        field = &tib->spec._struct->fields->variables[i];\r
                        if (!slang_storage_aggregate_construct (&agg))\r
                                return GL_FALSE;\r
-                       if (!_slang_aggregate_variable (&agg, &field->type.specifier, field->array_size,\r
+                       if (!_slang_aggregate_variable (&agg, &field->type.specifier, field->array_len,\r
                                        A->space.funcs, A->space.structs, A->space.vars, A->mach, A->file, A->atoms))\r
                        {\r
                                slang_storage_aggregate_destruct (&agg);\r
@@ -961,42 +967,64 @@ static GLboolean handle_field (slang_assemble_ctx *A, slang_assembly_typeinfo *t
                                field_offset += size;\r
                }\r
 \r
-               if (!PLAB (A->file, slang_asm_addr_push, field_offset))\r
-                       return GL_FALSE;\r
+               /*\r
+                * OPTIMIZATION: If selecting the last field, no relocation is needed.\r
+                */\r
+               relocate = field_offset != struct_size - field_size;\r
 \r
-               if (ref == slang_ref_force)\r
+               /*\r
+                * OPTIMIZATION: If field and struct sizes are equal, no partial free is needed.\r
+                */\r
+               shrink = field_size != struct_size;\r
+\r
+               if (relocate)\r
                {\r
-                       if (!PUSH (A->file, slang_asm_addr_add))\r
+                       if (!PLAB (A->file, slang_asm_addr_push, field_offset))\r
                                return GL_FALSE;\r
                }\r
+\r
+               if (ref == slang_ref_force)\r
+               {\r
+                       if (relocate)\r
+                       {\r
+                               if (!PUSH (A->file, slang_asm_addr_add))\r
+                                       return GL_FALSE;\r
+                       }\r
+               }\r
                else\r
                {\r
-                       GLuint i;\r
+                       GLuint free_b = 0;\r
 \r
-                       /* move the selected element to the beginning of the master expression */\r
-                       for (i = 0; i < field_size; i += 4)\r
-                               if (!PLAB2 (A->file, slang_asm_float_move, struct_size - field_size + i + 4, i + 4))\r
-                                       return GL_FALSE;\r
-                       if (!PLAB (A->file, slang_asm_local_free, 4))\r
-                               return GL_FALSE;\r
+                       if (relocate)\r
+                       {\r
+                               GLuint i;\r
 \r
-                       /* free the rest of the master expression */\r
-                       if (!PLAB (A->file, slang_asm_local_free, struct_size - field_size))\r
-                               return GL_FALSE;\r
+                               /* move the selected element to the beginning of the master expression */\r
+                               for (i = 0; i < field_size; i += 4)\r
+                                       if (!PLAB2 (A->file, slang_asm_float_move, struct_size - field_size + i + 4, i + 4))\r
+                                               return GL_FALSE;\r
+                               free_b += 4;\r
+                       }\r
+\r
+                       if (shrink)\r
+                       {\r
+                               /* free the rest of the master expression */\r
+                               free_b += struct_size - field_size;\r
+                       }\r
+\r
+                       if (free_b)\r
+                       {\r
+                               if (!PLAB (A->file, slang_asm_local_free, free_b))\r
+                                       return GL_FALSE;\r
+                       }\r
                }\r
        }\r
 \r
        return GL_TRUE;\r
 }\r
 \r
-GLboolean _slang_assemble_operation_ (slang_assemble_ctx *A, slang_operation *op, slang_ref_type ref)\r
+GLboolean _slang_assemble_operation (slang_assemble_ctx *A, slang_operation *op, slang_ref_type ref)\r
 {\r
-       GLuint assem;\r
-\r
-       assem = A->file->count;\r
-       if (!push_new (A->file))\r
-               return GL_FALSE;\r
-\r
        /* set default results */\r
        A->ref = /*(ref == slang_ref_freelance) ? slang_ref_force : */ref;\r
        A->swz.num_components = 0;\r
@@ -1010,9 +1038,9 @@ GLboolean _slang_assemble_operation_ (slang_assemble_ctx *A, slang_operation *op
 \r
                        for (i = 0; i < op->num_children; i++)\r
                        {\r
-                               if (!_slang_assemble_operation_ (A, &op->children[i], slang_ref_forbid/*slang_ref_freelance*/))\r
+                               if (!_slang_assemble_operation (A, &op->children[i], slang_ref_forbid/*slang_ref_freelance*/))\r
                                        return GL_FALSE;\r
-                               if (!_slang_cleanup_stack_ (A, &op->children[i]))\r
+                               if (!_slang_cleanup_stack (A, &op->children[i]))\r
                                        return GL_FALSE;\r
                        }\r
                }\r
@@ -1032,25 +1060,26 @@ GLboolean _slang_assemble_operation_ (slang_assemble_ctx *A, slang_operation *op
                {\r
                        GLuint i;\r
 \r
-                       if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_force))\r
+                       if (!_slang_assemble_operation (A, &op->children[0], slang_ref_force))\r
                                return GL_FALSE;\r
                        for (i = 1; i < op->num_children; i++)\r
-                               if (!_slang_assemble_operation_ (A, &op->children[i], slang_ref_forbid))\r
+                               if (!_slang_assemble_operation (A, &op->children[i], slang_ref_forbid))\r
                                        return GL_FALSE;\r
                        if (!call_asm_instruction (A, op->a_id))\r
                                return GL_FALSE;\r
                }\r
                break;\r
        case slang_oper_break:\r
-               A->file->code[assem].type = slang_asm_jump;\r
-               A->file->code[assem].param[0] = A->flow.loop_end;\r
+               if (!PLAB (A->file, slang_asm_jump, A->flow.loop_end))\r
+                       return GL_FALSE;\r
                break;\r
        case slang_oper_continue:\r
-               A->file->code[assem].type = slang_asm_jump;\r
-               A->file->code[assem].param[0] = A->flow.loop_start;\r
+               if (!PLAB (A->file, slang_asm_jump, A->flow.loop_start))\r
+                       return GL_FALSE;\r
                break;\r
        case slang_oper_discard:\r
-               A->file->code[assem].type = slang_asm_discard;\r
+               if (!PUSH (A->file, slang_asm_discard))\r
+                       return GL_FALSE;\r
                if (!PUSH (A->file, slang_asm_exit))\r
                        return GL_FALSE;\r
                break;\r
@@ -1060,7 +1089,7 @@ GLboolean _slang_assemble_operation_ (slang_assemble_ctx *A, slang_operation *op
                        /* push the result's address */\r
                        if (!PLAB2 (A->file, slang_asm_local_addr, 0, A->local.ret_size))\r
                                return GL_FALSE;\r
-                       if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid))\r
+                       if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))\r
                                return GL_FALSE;\r
 \r
                        A->swz.num_components = 0;\r
@@ -1077,7 +1106,7 @@ GLboolean _slang_assemble_operation_ (slang_assemble_ctx *A, slang_operation *op
        case slang_oper_expression:\r
                if (ref == slang_ref_force)\r
                        return GL_FALSE;\r
-               if (!_slang_assemble_operation_ (A, &op->children[0], ref))\r
+               if (!_slang_assemble_operation (A, &op->children[0], ref))\r
                        return GL_FALSE;\r
                break;\r
        case slang_oper_if:\r
@@ -1101,22 +1130,22 @@ GLboolean _slang_assemble_operation_ (slang_assemble_ctx *A, slang_operation *op
        case slang_oper_literal_bool:\r
                if (ref == slang_ref_force)\r
                        return GL_FALSE;\r
-               A->file->code[assem].type = slang_asm_bool_push;\r
-               A->file->code[assem].literal = op->literal;\r
+               if (!PLIT (A->file, slang_asm_bool_push, op->literal))\r
+                       return GL_FALSE;\r
                A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_literal_int:\r
                if (ref == slang_ref_force)\r
                        return GL_FALSE;\r
-               A->file->code[assem].type = slang_asm_int_push;\r
-               A->file->code[assem].literal = op->literal;\r
+               if (!PLIT (A->file, slang_asm_int_push, op->literal))\r
+                       return GL_FALSE;\r
                A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_literal_float:\r
                if (ref == slang_ref_force)\r
                        return GL_FALSE;\r
-               A->file->code[assem].type = slang_asm_float_push;\r
-               A->file->code[assem].literal = op->literal;\r
+               if (!PLIT (A->file, slang_asm_float_push, op->literal))\r
+                       return GL_FALSE;\r
                A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_identifier:\r
@@ -1129,7 +1158,7 @@ GLboolean _slang_assemble_operation_ (slang_assemble_ctx *A, slang_operation *op
                        if (var == NULL)\r
                                return GL_FALSE;\r
                        size = 0;\r
-                       if (!sizeof_variable (A, &var->type.specifier, slang_qual_none, var->array_size, &size))\r
+                       if (!sizeof_variable (A, &var->type.specifier, slang_qual_none, var->array_len, &size))\r
                                return GL_FALSE;\r
 \r
                        /* prepare stack for dereferencing */\r
@@ -1140,7 +1169,7 @@ GLboolean _slang_assemble_operation_ (slang_assemble_ctx *A, slang_operation *op
                        /* push the variable's address */\r
                        if (var->global)\r
                        {\r
-                               if (!PLAB (A->file, slang_asm_addr_push, var->address))\r
+                               if (!PLAB (A->file, slang_asm_global_addr, var->address))\r
                                        return GL_FALSE;\r
                        }\r
                        else\r
@@ -1164,11 +1193,11 @@ GLboolean _slang_assemble_operation_ (slang_assemble_ctx *A, slang_operation *op
        case slang_oper_sequence:\r
                if (ref == slang_ref_force)\r
                        return GL_FALSE;\r
-               if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/))\r
+               if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/))\r
                        return GL_FALSE;\r
-               if (!_slang_cleanup_stack_ (A, &op->children[0]))\r
+               if (!_slang_cleanup_stack (A, &op->children[0]))\r
                        return GL_FALSE;\r
-               if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid))\r
+               if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))\r
                        return GL_FALSE;\r
                A->ref = slang_ref_forbid;\r
                break;\r
@@ -1179,14 +1208,17 @@ GLboolean _slang_assemble_operation_ (slang_assemble_ctx *A, slang_operation *op
        case slang_oper_addassign:\r
                if (!_slang_assemble_assign (A, op, "+=", ref))\r
                        return GL_FALSE;\r
+               A->ref = ref;\r
                break;\r
        case slang_oper_subassign:\r
                if (!_slang_assemble_assign (A, op, "-=", ref))\r
                        return GL_FALSE;\r
+               A->ref = ref;\r
                break;\r
        case slang_oper_mulassign:\r
                if (!_slang_assemble_assign (A, op, "*=", ref))\r
                        return GL_FALSE;\r
+               A->ref = ref;\r
                break;\r
        /*case slang_oper_modassign:*/\r
        /*case slang_oper_lshassign:*/\r
@@ -1197,6 +1229,7 @@ GLboolean _slang_assemble_operation_ (slang_assemble_ctx *A, slang_operation *op
        case slang_oper_divassign:\r
                if (!_slang_assemble_assign (A, op, "/=", ref))\r
                        return GL_FALSE;\r
+               A->ref = ref;\r
                break;\r
        case slang_oper_select:\r
                if (!_slang_assemble_select (A, op))\r
@@ -1265,18 +1298,18 @@ GLboolean _slang_assemble_operation_ (slang_assemble_ctx *A, slang_operation *op
                A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_equal:\r
-               if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid))\r
+               if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))\r
                        return GL_FALSE;\r
-               if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid))\r
+               if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))\r
                        return GL_FALSE;\r
                if (!equality (A, op->children, GL_TRUE))\r
                        return GL_FALSE;\r
                A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_notequal:\r
-               if (!_slang_assemble_operation_ (A, &op->children[0], slang_ref_forbid))\r
+               if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))\r
                        return GL_FALSE;\r
-               if (!_slang_assemble_operation_ (A, &op->children[1], slang_ref_forbid))\r
+               if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))\r
                        return GL_FALSE;\r
                if (!equality (A, op->children, GL_FALSE))\r
                        return GL_FALSE;\r
@@ -1285,10 +1318,12 @@ GLboolean _slang_assemble_operation_ (slang_assemble_ctx *A, slang_operation *op
        case slang_oper_preincrement:\r
                if (!_slang_assemble_assign (A, op, "++", ref))\r
                        return GL_FALSE;\r
+               A->ref = ref;\r
                break;\r
        case slang_oper_predecrement:\r
                if (!_slang_assemble_assign (A, op, "--", ref))\r
                        return GL_FALSE;\r
+               A->ref = ref;\r
                break;\r
        case slang_oper_plus:\r
                if (!_slang_dereference (A, op))\r