updated some printfs, added comment about sched_yield
[mesa.git] / src / mesa / shader / slang / slang_assemble.c
index d4f635cd0fb1fad88489ea7e0e7e48cddd54edf4..faa13b33e69336bd0ac60b37686fce2cc6c27a59 100644 (file)
@@ -1,8 +1,8 @@
 /*\r
  * Mesa 3-D graphics library\r
- * Version:  6.3\r
+ * Version:  6.5\r
  *\r
- * Copyright (C) 2005  Brian Paul   All Rights Reserved.\r
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.\r
  *\r
  * Permission is hereby granted, free of charge, to any person obtaining a\r
  * copy of this software and associated documentation files (the "Software"),\r
  */\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_constructor.h"\r
-#include "slang_assemble_typeinfo.h"\r
-#include "slang_assemble_conditional.h"\r
-#include "slang_assemble_assignment.h"\r
 \r
 /* slang_assembly */\r
 \r
-static void slang_assembly_construct (slang_assembly *asm)\r
+static GLboolean slang_assembly_construct (slang_assembly *assem)\r
 {\r
-       asm->type = slang_asm_none;\r
+       assem->type = slang_asm_none;\r
+       return GL_TRUE;\r
 }\r
 \r
-static void slang_assembly_destruct (slang_assembly *asm)\r
+static GLvoid slang_assembly_destruct (slang_assembly *assem)\r
 {\r
 }\r
 \r
 /* slang_assembly_file */\r
 \r
-void slang_assembly_file_construct (slang_assembly_file *file)\r
+GLboolean slang_assembly_file_construct (slang_assembly_file *file)\r
 {\r
        file->code = NULL;\r
        file->count = 0;\r
+       file->capacity = 0;\r
+       return GL_TRUE;\r
 }\r
 \r
-void slang_assembly_file_destruct (slang_assembly_file *file)\r
+GLvoid slang_assembly_file_destruct (slang_assembly_file *file)\r
 {\r
-       unsigned int i;\r
+       GLuint i;\r
 \r
        for (i = 0; i < file->count; i++)\r
-               slang_assembly_destruct (file->code + i);\r
+               slang_assembly_destruct (&file->code[i]);\r
        slang_alloc_free (file->code);\r
 }\r
 \r
-static int slang_assembly_file_push_new (slang_assembly_file *file)\r
+static GLboolean push_new (slang_assembly_file *file)\r
 {\r
-       file->code = (slang_assembly *) slang_alloc_realloc (file->code, file->count * sizeof (\r
-               slang_assembly), (file->count + 1) * sizeof (slang_assembly));\r
-       if (file->code != NULL)\r
+       if (file->count == file->capacity)\r
        {\r
-               slang_assembly_construct (file->code + file->count);\r
-               file->count++;\r
-               return 1;\r
+               GLuint n;\r
+\r
+               if (file->capacity == 0)\r
+                       n = 256;\r
+               else\r
+                       n = file->capacity * 2;\r
+               file->code = (slang_assembly *) slang_alloc_realloc (file->code,\r
+                       file->capacity * sizeof (slang_assembly), n * sizeof (slang_assembly));\r
+               if (file->code == NULL)\r
+                       return GL_FALSE;\r
+               file->capacity = n;\r
        }\r
-       return 0;\r
+       if (!slang_assembly_construct (&file->code[file->count]))\r
+               return GL_FALSE;\r
+       file->count++;\r
+       return GL_TRUE;\r
 }\r
 \r
-static int slang_assembly_file_push_general (slang_assembly_file *file, slang_assembly_type type,\r
-       GLfloat literal, GLuint label, GLuint size)\r
+static GLboolean push_gen (slang_assembly_file *file, slang_assembly_type type, GLfloat literal,\r
+       GLuint label, GLuint size)\r
 {\r
-       slang_assembly *asm;\r
-       if (!slang_assembly_file_push_new (file))\r
-               return 0;\r
-       asm = file->code + file->count - 1;\r
-       asm->type = type;\r
-       asm->literal = literal;\r
-       asm->param[0] = label;\r
-       asm->param[1] = size;\r
-       return 1;\r
+       slang_assembly *assem;\r
+\r
+       if (!push_new (file))\r
+               return GL_FALSE;\r
+       assem = &file->code[file->count - 1];\r
+       assem->type = type;\r
+       assem->literal = literal;\r
+       assem->param[0] = label;\r
+       assem->param[1] = size;\r
+       return GL_TRUE;\r
 }\r
 \r
-int slang_assembly_file_push (slang_assembly_file *file, slang_assembly_type type)\r
+GLboolean slang_assembly_file_push (slang_assembly_file *file, slang_assembly_type type)\r
 {\r
-       return slang_assembly_file_push_general (file, type, (GLfloat) 0, 0, 0);\r
+       return push_gen (file, type, (GLfloat) 0, 0, 0);\r
 }\r
 \r
-int slang_assembly_file_push_label (slang_assembly_file *file, slang_assembly_type type,\r
+GLboolean slang_assembly_file_push_label (slang_assembly_file *file, slang_assembly_type type,\r
        GLuint label)\r
 {\r
-       return slang_assembly_file_push_general (file, type, (GLfloat) 0, label, 0);\r
+       return push_gen (file, type, (GLfloat) 0, label, 0);\r
 }\r
 \r
-int slang_assembly_file_push_label2 (slang_assembly_file *file, slang_assembly_type type,\r
+GLboolean slang_assembly_file_push_label2 (slang_assembly_file *file, slang_assembly_type type,\r
        GLuint label1, GLuint label2)\r
 {\r
-       return slang_assembly_file_push_general (file, type, (GLfloat) 0, label1, label2);\r
+       return push_gen (file, type, (GLfloat) 0, label1, label2);\r
 }\r
 \r
-int slang_assembly_file_push_literal (slang_assembly_file *file, slang_assembly_type type,\r
+GLboolean slang_assembly_file_push_literal (slang_assembly_file *file, slang_assembly_type type,\r
        GLfloat literal)\r
 {\r
-       return slang_assembly_file_push_general (file, type, literal, 0, 0);\r
+       return push_gen (file, type, literal, 0, 0);\r
+}\r
+\r
+#define PUSH slang_assembly_file_push\r
+#define PLAB slang_assembly_file_push_label\r
+#define PLAB2 slang_assembly_file_push_label2\r
+#define PLIT slang_assembly_file_push_literal\r
+\r
+/* slang_assembly_file_restore_point */\r
+\r
+GLboolean slang_assembly_file_restore_point_save (slang_assembly_file *file,\r
+       slang_assembly_file_restore_point *point)\r
+{\r
+       point->count = file->count;\r
+       return GL_TRUE;\r
+}\r
+\r
+GLboolean slang_assembly_file_restore_point_load (slang_assembly_file *file,\r
+       slang_assembly_file_restore_point *point)\r
+{\r
+       GLuint i;\r
+\r
+       for (i = point->count; i < file->count; i++)\r
+               slang_assembly_destruct (&file->code[i]);\r
+       file->count = point->count;\r
+       return GL_TRUE;\r
 }\r
 \r
 /* utility functions */\r
 \r
-static int sizeof_variable (slang_type_specifier *spec, slang_type_qualifier qual,\r
-       slang_operation *array_size, slang_assembly_name_space *space, unsigned int *size)\r
+static GLboolean sizeof_variable (slang_assemble_ctx *A, slang_type_specifier *spec,\r
+       slang_type_qualifier qual, GLuint array_len, GLuint *size)\r
 {\r
        slang_storage_aggregate agg;\r
 \r
-       slang_storage_aggregate_construct (&agg);\r
-       if (!_slang_aggregate_variable (&agg, spec, array_size, space->funcs, space->structs))\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_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
-               return 0;\r
+               return GL_FALSE;\r
        }\r
        *size += _slang_sizeof_aggregate (&agg);\r
+       slang_storage_aggregate_destruct (&agg);\r
+\r
+       /* for reference variables consider the additional address overhead */\r
        if (qual == slang_qual_out || qual == slang_qual_inout)\r
                *size += 4;\r
-       slang_storage_aggregate_destruct (&agg);\r
-       return 1;\r
+\r
+       return GL_TRUE;\r
 }\r
 \r
-static int sizeof_variable2 (slang_variable *var, slang_assembly_name_space *space,\r
-       unsigned int *size)\r
+static GLboolean sizeof_variable2 (slang_assemble_ctx *A, slang_variable *var, GLuint *size)\r
 {\r
        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 (&var->type.specifier, var->type.qualifier, var->array_size, space,\r
-               size);\r
+       return sizeof_variable (A, &var->type.specifier, var->type.qualifier, var->array_len, size);\r
 }\r
 \r
-static int sizeof_variables (slang_variable_scope *vars, unsigned int start, unsigned int stop,\r
-       slang_assembly_name_space *space, unsigned int *size)\r
+static GLboolean sizeof_variables (slang_assemble_ctx *A, slang_variable_scope *vars, GLuint start,\r
+       GLuint stop, GLuint *size)\r
 {\r
-       unsigned int i;\r
+       GLuint i;\r
 \r
        for (i = start; i < stop; i++)\r
-               if (!sizeof_variable2 (vars->variables + i, space, size))\r
-                       return 0;\r
-       return 1;\r
+               if (!sizeof_variable2 (A, &vars->variables[i], size))\r
+                       return GL_FALSE;\r
+       return GL_TRUE;\r
 }\r
 \r
-static int collect_locals (slang_operation *op, slang_assembly_name_space *space,\r
-       unsigned int *size)\r
+static GLboolean collect_locals (slang_assemble_ctx *A, slang_operation *op, GLuint *size)\r
 {\r
-       unsigned int i;\r
+       GLuint i;\r
 \r
-       if (!sizeof_variables (op->locals, 0, op->locals->num_variables, space, size))\r
-               return 0;\r
+       if (!sizeof_variables (A, op->locals, 0, op->locals->num_variables, size))\r
+               return GL_FALSE;\r
        for (i = 0; i < op->num_children; i++)\r
-               if (!collect_locals (op->children + i, space, size))\r
-                       return 0;\r
-       return 1;\r
+               if (!collect_locals (A, &op->children[i], size))\r
+                       return GL_FALSE;\r
+       return GL_TRUE;\r
 }\r
 \r
 /* _slang_locate_function() */\r
 \r
-slang_function *_slang_locate_function (const char *name, slang_operation *params,\r
-       unsigned int num_params, slang_assembly_name_space *space)\r
+slang_function *_slang_locate_function (slang_function_scope *funcs, slang_atom a_name,\r
+       slang_operation *params, GLuint num_params, slang_assembly_name_space *space,\r
+       slang_atom_pool *atoms)\r
 {\r
-       unsigned int i;\r
+       GLuint i;\r
 \r
-       for (i = 0; i < space->funcs->num_functions; i++)\r
+       for (i = 0; i < funcs->num_functions; i++)\r
        {\r
-               unsigned int j;\r
-               slang_function *f = space->funcs->functions + i;\r
+               GLuint j;\r
+               slang_function *f = &funcs->functions[i];\r
 \r
-               if (slang_string_compare (name, f->header.name) != 0)\r
+               if (a_name != f->header.a_name)\r
                        continue;\r
                if (f->param_count != num_params)\r
                        continue;\r
                for (j = 0; j < num_params; j++)\r
                {\r
                        slang_assembly_typeinfo ti;\r
-                       slang_assembly_typeinfo_construct (&ti);\r
-                       if (!_slang_typeof_operation (params + j, space, &ti))\r
+\r
+                       if (!slang_assembly_typeinfo_construct (&ti))\r
+                               return NULL;\r
+                       if (!_slang_typeof_operation_ (&params[j], space, &ti, atoms))\r
                        {\r
                                slang_assembly_typeinfo_destruct (&ti);\r
-                               return 0;\r
+                               return NULL;\r
                        }\r
                        if (!slang_type_specifier_equal (&ti.spec, &f->parameters->variables[j].type.specifier))\r
                        {\r
@@ -201,506 +240,814 @@ slang_function *_slang_locate_function (const char *name, slang_operation *param
                                break;\r
                        }\r
                        slang_assembly_typeinfo_destruct (&ti);\r
+\r
                        /* "out" and "inout" formal parameter requires the actual parameter to be l-value */\r
                        if (!ti.can_be_referenced &&\r
-                               (f->parameters->variables[j].type.qualifier == slang_qual_out ||\r
-                               f->parameters->variables[j].type.qualifier == slang_qual_inout))\r
+                                       (f->parameters->variables[j].type.qualifier == slang_qual_out ||\r
+                                       f->parameters->variables[j].type.qualifier == slang_qual_inout))\r
                                break;\r
                }\r
                if (j == num_params)\r
                        return f;\r
        }\r
-       if (space->funcs->outer_scope != NULL)\r
-       {\r
-               slang_assembly_name_space my_space = *space;\r
-               my_space.funcs = space->funcs->outer_scope;\r
-               return _slang_locate_function (name, params, num_params, &my_space);\r
-       }\r
+       if (funcs->outer_scope != NULL)\r
+               return _slang_locate_function (funcs->outer_scope, a_name, params, num_params, space, atoms);\r
        return NULL;\r
 }\r
 \r
 /* _slang_assemble_function() */\r
 \r
-int _slang_assemble_function (slang_assembly_file *file, slang_function *fun,\r
-       slang_assembly_name_space *space)\r
+GLboolean _slang_assemble_function (slang_assemble_ctx *A, slang_function *fun)\r
 {\r
-       unsigned int param_size, local_size;\r
-       unsigned int skip, cleanup;\r
-       slang_assembly_flow_control flow;\r
-       slang_assembly_local_info info;\r
-       slang_assembly_stack_info stk;\r
+       GLuint param_size, local_size;\r
+       GLuint skip, cleanup;\r
 \r
-       fun->address = file->count;\r
+       fun->address = A->file->count;\r
 \r
        if (fun->body == NULL)\r
        {\r
-               /* TODO: jump to the actual function body */\r
-               return 1;\r
+               /* jump to the actual function body - we do not know it, so add the instruction\r
+                * to fixup table */\r
+               fun->fixups.table = (GLuint *) slang_alloc_realloc (fun->fixups.table,\r
+                       fun->fixups.count * sizeof (GLuint), (fun->fixups.count + 1) * sizeof (GLuint));\r
+               if (fun->fixups.table == NULL)\r
+                       return GL_FALSE;\r
+               fun->fixups.table[fun->fixups.count] = fun->address;\r
+               fun->fixups.count++;\r
+               if (!PUSH (A->file, slang_asm_jump))\r
+                       return GL_FALSE;\r
+               return GL_TRUE;\r
+       }\r
+       else\r
+       {\r
+               GLuint i;\r
+\r
+               /* resolve all fixup table entries and delete it */\r
+               for (i = 0; i < fun->fixups.count; i++)\r
+                       A->file->code[fun->fixups.table[i]].param[0] = fun->address;\r
+               slang_fixup_table_free (&fun->fixups);\r
        }\r
 \r
-       /* calculate return value and parameters size */\r
+       /* At this point traverse function formal parameters and code to calculate\r
+        * total memory size to be allocated on the stack.\r
+        * During this process the variables will be assigned local addresses to\r
+        * reference them in the code.\r
+        * No storage optimizations are performed so exclusive scopes are not detected and shared. */\r
+\r
+       /* calculate return value size */\r
        param_size = 0;\r
        if (fun->header.type.specifier.type != slang_spec_void)\r
-               if (!sizeof_variable (&fun->header.type.specifier, slang_qual_none, NULL, space,\r
-                       &param_size))\r
-                       return 0;\r
-       info.ret_size = param_size;\r
-       if (!sizeof_variables (fun->parameters, 0, fun->param_count, space, &param_size))\r
-               return 0;\r
-\r
-       /* calculate local variables size, take into account the four-byte return address and\r
-       temporaries for various tasks */\r
-       info.addr_tmp = param_size + 4;\r
-       info.swizzle_tmp = param_size + 4 + 4;\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
+       /* calculate formal parameter list size */\r
+       if (!sizeof_variables (A, fun->parameters, 0, fun->param_count, &param_size))\r
+               return GL_FALSE;\r
+\r
+       /* calculate local variables size - take into account the four-byte return address and\r
+        * temporaries for various tasks (4 for addr and 16 for swizzle temporaries).\r
+        * these include variables from the formal parameter scope and from the code */\r
+       A->local.addr_tmp = param_size + 4;\r
+       A->local.swizzle_tmp = param_size + 4 + 4;\r
        local_size = param_size + 4 + 4 + 16;\r
-       if (!sizeof_variables (fun->parameters, fun->param_count, fun->parameters->num_variables, space,\r
-               &local_size))\r
-               return 0;\r
-       if (!collect_locals (fun->body, space, &local_size))\r
-               return 0;\r
+       if (!sizeof_variables (A, fun->parameters, fun->param_count, fun->parameters->num_variables,\r
+                       &local_size))\r
+               return GL_FALSE;\r
+       if (!collect_locals (A, fun->body, &local_size))\r
+               return GL_FALSE;\r
 \r
        /* allocate local variable storage */\r
-       if (!slang_assembly_file_push_label (file, slang_asm_local_alloc, local_size - param_size - 4))\r
-               return 0;\r
+       if (!PLAB (A->file, slang_asm_local_alloc, local_size - param_size - 4))\r
+               return GL_FALSE;\r
 \r
        /* mark a new frame for function variable storage */\r
-       if (!slang_assembly_file_push_label (file, slang_asm_enter, local_size))\r
-               return 0;\r
+       if (!PLAB (A->file, slang_asm_enter, local_size))\r
+               return GL_FALSE;\r
 \r
-       /* skip the cleanup jump */\r
-       skip = file->count;\r
-       if (!slang_assembly_file_push_new (file))\r
-               return 0;\r
-       file->code[skip].type = slang_asm_jump;\r
+       /* jump directly to the actual code */\r
+       skip = A->file->count;\r
+       if (!push_new (A->file))\r
+               return GL_FALSE;\r
+       A->file->code[skip].type = slang_asm_jump;\r
 \r
        /* all "return" statements will be directed here */\r
-       flow.function_end = file->count;\r
-       cleanup = file->count;\r
-       if (!slang_assembly_file_push_new (file))\r
-               return 0;\r
-       file->code[cleanup].type = slang_asm_jump;\r
+       A->flow.function_end = A->file->count;\r
+       cleanup = A->file->count;\r
+       if (!push_new (A->file))\r
+               return GL_FALSE;\r
+       A->file->code[cleanup].type = slang_asm_jump;\r
 \r
        /* execute the function body */\r
-       file->code[skip].param[0] = file->count;\r
-       if (!_slang_assemble_operation (file, fun->body, 0, &flow, space, &info, &stk))\r
-               return 0;\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
+               return GL_FALSE;\r
 \r
        /* this is the end of the function - restore the old function frame */\r
-       file->code[cleanup].param[0] = file->count;\r
-       if (!slang_assembly_file_push (file, slang_asm_leave))\r
-               return 0;\r
+       A->file->code[cleanup].param[0] = A->file->count;\r
+       if (!PUSH (A->file, slang_asm_leave))\r
+               return GL_FALSE;\r
 \r
        /* free local variable storage */\r
-       if (!slang_assembly_file_push_label (file, slang_asm_local_free, local_size - param_size - 4))\r
-               return 0;\r
+       if (!PLAB (A->file, slang_asm_local_free, local_size - param_size - 4))\r
+               return GL_FALSE;\r
 \r
-       /* jump out of the function */\r
-       if (!slang_assembly_file_push (file, slang_asm_return))\r
-               return 0;\r
-       return 1;\r
+       /* return from the function */\r
+       if (!PUSH (A->file, slang_asm_return))\r
+               return GL_FALSE;\r
+\r
+       return GL_TRUE;\r
 }\r
 \r
-int _slang_cleanup_stack (slang_assembly_file *file, slang_operation *op, int ref,\r
-       slang_assembly_name_space *space)\r
+GLboolean _slang_cleanup_stack (slang_assemble_ctx *A, slang_operation *op)\r
 {\r
        slang_assembly_typeinfo ti;\r
-       unsigned int size;\r
+       GLuint size = 0;\r
 \r
-       slang_assembly_typeinfo_construct (&ti);\r
-       if (!_slang_typeof_operation (op, space, &ti))\r
+       /* 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 (A, op, &ti))\r
        {\r
                slang_assembly_typeinfo_destruct (&ti);\r
-               return 0;\r
+               return GL_FALSE;\r
        }\r
-       if (ti.spec.type == slang_spec_void)\r
-               size = 0;\r
-       else if (ref)\r
-               size = 4;\r
-       else\r
-       {\r
-               size = 0;\r
-               if (!sizeof_variable (&ti.spec, slang_qual_none, NULL, space, &size))\r
+       if (ti.spec.type != slang_spec_void) {\r
+               if (A->ref == slang_ref_force) {\r
+                       size = 4;\r
+               }\r
+               else if (!sizeof_variable (A, &ti.spec, slang_qual_none, 0, &size))\r
                {\r
                        slang_assembly_typeinfo_destruct (&ti);\r
-                       return 0;\r
+                       return GL_FALSE;\r
                }\r
        }\r
        slang_assembly_typeinfo_destruct (&ti);\r
+\r
+       /* if nonzero, free it from the stack */\r
        if (size != 0)\r
        {\r
-               if (!slang_assembly_file_push_label (file, slang_asm_local_free, size))\r
-                       return 0;\r
+               if (!PLAB (A->file, slang_asm_local_free, size))\r
+                       return GL_FALSE;\r
        }\r
-       return 1;\r
+\r
+       return GL_TRUE;\r
 }\r
 \r
 /* _slang_assemble_operation() */\r
 \r
-/* XXX: general swizzle! */\r
-static int dereference_aggregate (slang_assembly_file *file, const slang_storage_aggregate *agg,\r
-       unsigned int index, unsigned int *size, slang_assembly_local_info *info)\r
+static GLboolean dereference_aggregate (slang_assemble_ctx *A, const slang_storage_aggregate *agg,\r
+       GLuint *size, slang_swizzle *swz, GLboolean is_swizzled)\r
 {\r
-       unsigned int i;\r
+       GLuint i;\r
 \r
        for (i = agg->count; i > 0; i--)\r
        {\r
-               const slang_storage_array *arr = agg->arrays + i - 1;\r
-               unsigned int j;\r
+               const slang_storage_array *arr = &agg->arrays[i - 1];\r
+               GLuint j;\r
 \r
                for (j = arr->length; j > 0; j--)\r
                {\r
                        if (arr->type == slang_stor_aggregate)\r
                        {\r
-                               if (!dereference_aggregate (file, arr->aggregate, index, size, info))\r
-                                       return 0;\r
+                               if (!dereference_aggregate (A, arr->aggregate, size, swz, is_swizzled))\r
+                                       return GL_FALSE;\r
                        }\r
                        else\r
                        {\r
+                               GLuint src_offset;\r
+                               slang_assembly_type ty;\r
+\r
                                *size -= 4;\r
-                               if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, info->addr_tmp,\r
-                                       4))\r
-                                       return 0;\r
-                               if (!slang_assembly_file_push (file, slang_asm_addr_deref))\r
-                                       return 0;\r
-                               if (!slang_assembly_file_push_label (file, slang_asm_addr_push, *size))\r
-                                       return 0;\r
-                               if (!slang_assembly_file_push (file, slang_asm_addr_add))\r
-                                       return 0;\r
+\r
+                               /* calculate the offset within source variable to read */\r
+                               if (is_swizzled)\r
+                               {\r
+                                       /* swizzle the index to get the actual offset */\r
+                                       src_offset = swz->swizzle[*size / 4] * 4;\r
+                               }\r
+                               else\r
+                               {\r
+                                       /* no swizzling - read sequentially */\r
+                                       src_offset = *size;\r
+                               }\r
+\r
+                               /* dereference data slot of a basic type */\r
+                               if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4))\r
+                                       return GL_FALSE;\r
+                               if (!PUSH (A->file, slang_asm_addr_deref))\r
+                                       return GL_FALSE;\r
+                               if (!PLAB (A->file, slang_asm_addr_push, src_offset))\r
+                                       return GL_FALSE;\r
+                               if (!PUSH (A->file, slang_asm_addr_add))\r
+                                       return GL_FALSE;\r
+\r
                                switch (arr->type)\r
                                {\r
                                case slang_stor_bool:\r
-                                       if (!slang_assembly_file_push (file, slang_asm_bool_deref))\r
-                                               return 0;\r
+                                       ty = slang_asm_bool_deref;\r
                                        break;\r
                                case slang_stor_int:\r
-                                       if (!slang_assembly_file_push (file, slang_asm_int_deref))\r
-                                               return 0;\r
+                                       ty = slang_asm_int_deref;\r
                                        break;\r
                                case slang_stor_float:\r
-                                       if (!slang_assembly_file_push (file, slang_asm_float_deref))\r
-                                               return 0;\r
+                                       ty = slang_asm_float_deref;\r
                                        break;\r
+                               default:\r
+                                       _mesa_problem(NULL, "Unexpected arr->type in dereference_aggregate");\r
+                                       ty = slang_asm_none;\r
                                }\r
-                               index += 4;\r
+                               if (!PUSH (A->file, ty))\r
+                                       return GL_FALSE;\r
                        }\r
                }\r
        }\r
-       return 1;\r
+\r
+       return GL_TRUE;\r
 }\r
-/* XXX: general swizzle! */\r
-int dereference (slang_assembly_file *file, slang_operation *op,\r
-       slang_assembly_name_space *space, slang_assembly_local_info *info)\r
+\r
+GLboolean _slang_dereference (slang_assemble_ctx *A, slang_operation *op)\r
 {\r
        slang_assembly_typeinfo ti;\r
-       int result;\r
+       GLboolean result = GL_FALSE;\r
        slang_storage_aggregate agg;\r
-       unsigned int size;\r
-\r
-       slang_assembly_typeinfo_construct (&ti);\r
-       if (!_slang_typeof_operation (op, space, &ti))\r
-       {\r
-               slang_assembly_typeinfo_destruct (&ti);\r
-               return 0;\r
-       }\r
-\r
-       slang_storage_aggregate_construct (&agg);\r
-       if (!_slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs))\r
-       {\r
-               slang_storage_aggregate_destruct (&agg);\r
-               slang_assembly_typeinfo_destruct (&ti);\r
-               return 0;\r
-       }\r
+       GLuint size;\r
+\r
+       /* get type information of the given operation */\r
+       if (!slang_assembly_typeinfo_construct (&ti))\r
+               return GL_FALSE;\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_len, A->space.funcs, A->space.structs,\r
+                       A->space.vars, A->mach, A->file, A->atoms))\r
+               goto end;\r
 \r
+       /* dereference the resulting aggregate */\r
        size = _slang_sizeof_aggregate (&agg);\r
-       result = dereference_aggregate (file, &agg, 0, &size, info);\r
+       result = dereference_aggregate (A, &agg, &size, &ti.swz, ti.is_swizzled);\r
 \r
+end:\r
        slang_storage_aggregate_destruct (&agg);\r
+end1:\r
        slang_assembly_typeinfo_destruct (&ti);\r
        return result;\r
 }\r
 \r
-static int call_function (slang_assembly_file *file, slang_function *fun, slang_operation *params,\r
-       unsigned int param_count, int assignment, slang_assembly_name_space *space,\r
-       slang_assembly_local_info *info)\r
+GLboolean _slang_assemble_function_call (slang_assemble_ctx *A, slang_function *fun,\r
+       slang_operation *params, GLuint param_count, GLboolean assignment)\r
 {\r
-       unsigned int i;\r
-       slang_assembly_stack_info stk;\r
+       GLuint i;\r
+       slang_swizzle p_swz[64];\r
+       slang_ref_type p_ref[64];\r
+\r
+       /* TODO: fix this, allocate dynamically */\r
+       if (param_count > 64)\r
+               return GL_FALSE;\r
 \r
        /* make room for the return value, if any */\r
        if (fun->header.type.specifier.type != slang_spec_void)\r
        {\r
-               unsigned int ret_size = 0;\r
-               if (!sizeof_variable (&fun->header.type.specifier, slang_qual_none, NULL, space, &ret_size))\r
-                       return 0;\r
-               if (!slang_assembly_file_push_label (file, slang_asm_local_alloc, ret_size))\r
-                       return 0;\r
+               GLuint ret_size = 0;\r
+\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
        }\r
 \r
        /* push the actual parameters on the stack */\r
        for (i = 0; i < param_count; i++)\r
        {\r
-               slang_assembly_flow_control flow;\r
-\r
                if (fun->parameters->variables[i].type.qualifier == slang_qual_inout ||\r
                        fun->parameters->variables[i].type.qualifier == slang_qual_out)\r
                {\r
-                       if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, info->addr_tmp, 4))\r
-                               return 0;\r
+                       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
-                       /* TODO: inspect stk */\r
-                       if (!_slang_assemble_operation (file, params + i, 1, &flow, space, info, &stk))\r
-                               return 0;\r
-                       if (!slang_assembly_file_push (file, slang_asm_addr_copy))\r
-                               return 0;\r
-                       if (!slang_assembly_file_push (file, slang_asm_addr_deref))\r
-                               return 0;\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
+                       if (!PUSH (A->file, slang_asm_addr_copy))\r
+                               return GL_FALSE;\r
+                       if (!PUSH (A->file, slang_asm_addr_deref))\r
+                               return GL_FALSE;\r
                        if (i == 0 && assignment)\r
                        {\r
-                               if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, info->addr_tmp,\r
-                                       4))\r
-                                       return 0;\r
-                               if (!slang_assembly_file_push (file, slang_asm_addr_deref))\r
-                                       return 0;\r
+                               /* duplicate the resulting address */\r
+                               if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4))\r
+                                       return GL_FALSE;\r
+                               if (!PUSH (A->file, slang_asm_addr_deref))\r
+                                       return GL_FALSE;\r
                        }\r
-                       if (!dereference (file, params, space, info))\r
-                               return 0;\r
+                       if (!_slang_dereference (A, &params[i]))\r
+                               return GL_FALSE;\r
                }\r
                else\r
                {\r
-                       /* TODO: for "out" and "inout" parameters also push the address (first) */\r
-                       /* TODO: optimize the "out" parameter case */\r
-                       /* TODO: inspect stk */\r
-                       if (!_slang_assemble_operation (file, params + i, 0, &flow, space, info, &stk))\r
-                               return 0;\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
                }\r
        }\r
 \r
        /* call the function */\r
-       if (!slang_assembly_file_push_label (file, slang_asm_call, fun->address))\r
-               return 0;\r
+       if (!PLAB (A->file, slang_asm_call, fun->address))\r
+               return GL_FALSE;\r
 \r
        /* pop the parameters from the stack */\r
        for (i = param_count; i > 0; i--)\r
        {\r
-               unsigned int j = i - 1;\r
+               GLuint j = i - 1;\r
+\r
+               A->swz = p_swz[j];\r
+               A->ref = p_ref[j];\r
                if (fun->parameters->variables[j].type.qualifier == slang_qual_inout ||\r
                        fun->parameters->variables[j].type.qualifier == slang_qual_out)\r
                {\r
-                       if (!_slang_assemble_assignment (file, params + j, space, info))\r
-                               return 0;\r
-                       if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4))\r
-                               return 0;\r
+                       /* for output parameter copy the contents of the formal parameter\r
+                        * back to the original actual parameter */\r
+                       if (!_slang_assemble_assignment (A, &params[j]))\r
+                               return GL_FALSE;\r
+                       /* pop the actual parameter's address */\r
+                       if (!PLAB (A->file, slang_asm_local_free, 4))\r
+                               return GL_FALSE;\r
                }\r
                else\r
                {\r
-                       if (!_slang_cleanup_stack (file, params + j, 0, space))\r
-                               return 0;\r
+                       /* pop the value of the parameter */\r
+                       if (!_slang_cleanup_stack (A, &params[j]))\r
+                               return GL_FALSE;\r
                }\r
        }\r
 \r
-       return 1;\r
+       return GL_TRUE;\r
 }\r
 \r
-int call_function_name (slang_assembly_file *file, const char *name, slang_operation *params,\r
-       unsigned int param_count, int assignment, slang_assembly_name_space *space,\r
-       slang_assembly_local_info *info)\r
+GLboolean _slang_assemble_function_call_name (slang_assemble_ctx *A, const char *name,\r
+       slang_operation *params, GLuint param_count, GLboolean assignment)\r
 {\r
-       slang_function *fun = _slang_locate_function (name, params, param_count, space);\r
+       slang_atom atom;\r
+       slang_function *fun;\r
+\r
+       atom = slang_atom_pool_atom (A->atoms, name);\r
+       if (atom == SLANG_ATOM_NULL)\r
+               return GL_FALSE;\r
+       fun = _slang_locate_function (A->space.funcs, atom, params, param_count, &A->space, A->atoms);\r
        if (fun == NULL)\r
-               return 0;\r
-       return call_function (file, fun, params, param_count, assignment, space, info);\r
+               return GL_FALSE;\r
+       return _slang_assemble_function_call (A, fun, params, param_count, assignment);\r
 }\r
 \r
-static int call_function_name_dummyint (slang_assembly_file *file, const char *name,\r
-       slang_operation *params, slang_assembly_name_space *space, slang_assembly_local_info *info)\r
+static GLboolean assemble_function_call_name_dummyint (slang_assemble_ctx *A, const char *name,\r
+       slang_operation *params)\r
 {\r
-       slang_operation p2[2];\r
-       int result;\r
-\r
-       p2[0] = *params;\r
-       if (!slang_operation_construct_a (p2 + 1))\r
-               return 0;\r
-       p2[1].type = slang_oper_literal_int;\r
-       result = call_function_name (file, name, p2, 2, 0, space, info);\r
-       slang_operation_destruct (p2 + 1);\r
+       slang_operation p[2];\r
+       GLboolean result;\r
+\r
+       p[0] = params[0];\r
+       if (!slang_operation_construct (&p[1]))\r
+               return GL_FALSE;\r
+       p[1].type = slang_oper_literal_int;\r
+       result = _slang_assemble_function_call_name (A, name, p, 2, GL_FALSE);\r
+       slang_operation_destruct (&p[1]);\r
        return result;\r
 }\r
 \r
-static int call_asm_instruction (slang_assembly_file *file, const char *name)\r
+static const struct\r
 {\r
-       const struct\r
-       {\r
-               const char *name;\r
-               slang_assembly_type code1, code2;\r
-       } inst[] = {\r
-               { "float_to_int",   slang_asm_float_to_int,   slang_asm_int_copy },\r
-               { "int_to_float",   slang_asm_int_to_float,   slang_asm_float_copy },\r
-               { "float_copy",     slang_asm_float_copy,     slang_asm_none },\r
-               { "int_copy",       slang_asm_int_copy,       slang_asm_none },\r
-               { "bool_copy",      slang_asm_bool_copy,      slang_asm_none },\r
-               { "float_add",      slang_asm_float_add,      slang_asm_float_copy },\r
-               { "float_multiply", slang_asm_float_multiply, slang_asm_float_copy },\r
-               { "float_divide",   slang_asm_float_divide,   slang_asm_float_copy },\r
-               { "float_negate",   slang_asm_float_negate,   slang_asm_float_copy },\r
-               { "float_less",     slang_asm_float_less,     slang_asm_bool_copy },\r
-               { "float_equal",    slang_asm_float_equal,    slang_asm_bool_copy },\r
-               { NULL,             slang_asm_none,           slang_asm_none }\r
-       };\r
-       unsigned int i;\r
+       const char *name;\r
+       slang_assembly_type code1, code2;\r
+} inst[] = {\r
+       /* core */\r
+       { "float_add",      slang_asm_float_add,      slang_asm_float_copy },\r
+       { "float_multiply", slang_asm_float_multiply, slang_asm_float_copy },\r
+       { "float_divide",   slang_asm_float_divide,   slang_asm_float_copy },\r
+       { "float_negate",   slang_asm_float_negate,   slang_asm_float_copy },\r
+       { "float_less",     slang_asm_float_less,     slang_asm_bool_copy },\r
+       { "float_equal",    slang_asm_float_equal_exp,slang_asm_bool_copy },\r
+       { "float_to_int",   slang_asm_float_to_int,   slang_asm_int_copy },\r
+       { "float_sine",     slang_asm_float_sine,     slang_asm_float_copy },\r
+       { "float_arcsine",  slang_asm_float_arcsine,  slang_asm_float_copy },\r
+       { "float_arctan",   slang_asm_float_arctan,   slang_asm_float_copy },\r
+       { "float_power",    slang_asm_float_power,    slang_asm_float_copy },\r
+       { "float_log2",     slang_asm_float_log2,     slang_asm_float_copy },\r
+       { "float_floor",    slang_asm_float_floor,    slang_asm_float_copy },\r
+       { "float_ceil",     slang_asm_float_ceil,     slang_asm_float_copy },\r
+       { "float_noise1",   slang_asm_float_noise1,   slang_asm_float_copy },\r
+       { "float_noise2",   slang_asm_float_noise2,   slang_asm_float_copy },\r
+       { "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
+       { "bool_print",     slang_asm_bool_deref,     slang_asm_bool_print },\r
+       { NULL,             slang_asm_none,           slang_asm_none }\r
+};\r
+\r
+static GLboolean call_asm_instruction (slang_assemble_ctx *A, slang_atom a_name)\r
+{\r
+       const char *id;\r
+       GLuint i;\r
+\r
+       id = slang_atom_pool_id (A->atoms, a_name);\r
 \r
        for (i = 0; inst[i].name != NULL; i++)\r
-               if (slang_string_compare (name, inst[i].name) == 0)\r
+               if (slang_string_compare (id, inst[i].name) == 0)\r
                        break;\r
        if (inst[i].name == NULL)\r
-               return 0;\r
+               return GL_FALSE;\r
 \r
-       if (!slang_assembly_file_push_label2 (file, inst[i].code1, 4, 0))\r
-               return 0;\r
+       if (!PLAB2 (A->file, inst[i].code1, 4, 0))\r
+               return GL_FALSE;\r
        if (inst[i].code2 != slang_asm_none)\r
-               if (!slang_assembly_file_push_label2 (file, inst[i].code2, 4, 0))\r
-                       return 0;\r
+               if (!PLAB2 (A->file, inst[i].code2, 4, 0))\r
+                       return GL_FALSE;\r
 \r
        /* clean-up the stack from the remaining dst address */\r
-       if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4))\r
-               return 0;\r
+       if (!PLAB (A->file, slang_asm_local_free, 4))\r
+               return GL_FALSE;\r
 \r
-       return 1;\r
+       return GL_TRUE;\r
 }\r
 \r
-/* XXX: general swizzle! */\r
-static int equality_aggregate (slang_assembly_file *file, const slang_storage_aggregate *agg,\r
-       unsigned int *index, unsigned int size, slang_assembly_local_info *info, unsigned int z_label)\r
+static GLboolean equality_aggregate (slang_assemble_ctx *A, const slang_storage_aggregate *agg,\r
+       GLuint *index, GLuint size, GLuint z_label)\r
 {\r
-       unsigned int i;\r
+       GLuint i;\r
 \r
        for (i = 0; i < agg->count; i++)\r
        {\r
-               const slang_storage_array *arr = agg->arrays + i;\r
-               unsigned int j;\r
+               const slang_storage_array *arr = &agg->arrays[i];\r
+               GLuint j;\r
 \r
                for (j = 0; j < arr->length; j++)\r
                {\r
                        if (arr->type == slang_stor_aggregate)\r
                        {\r
-                               if (!equality_aggregate (file, arr->aggregate, index, size, info, z_label))\r
-                                       return 0;\r
+                               if (!equality_aggregate (A, arr->aggregate, index, size, z_label))\r
+                                       return GL_FALSE;\r
                        }\r
                        else\r
                        {\r
-                               if (!slang_assembly_file_push_label2 (file, slang_asm_float_equal, size + *index,\r
-                                       *index))\r
-                                       return 0;\r
+                               if (!PLAB2 (A->file, slang_asm_float_equal_int, size + *index, *index))\r
+                                       return GL_FALSE;\r
                                *index += 4;\r
-                               if (!slang_assembly_file_push_label (file, slang_asm_jump_if_zero, z_label))\r
-                                       return 0;\r
+                               if (!PLAB (A->file, slang_asm_jump_if_zero, z_label))\r
+                                       return GL_FALSE;\r
                        }\r
                }\r
        }\r
-       return 1;\r
+\r
+       return GL_TRUE;\r
 }\r
-/* XXX: general swizzle! */\r
-static int equality (slang_assembly_file *file, slang_operation *op,\r
-       slang_assembly_name_space *space, slang_assembly_local_info *info, int equal)\r
+\r
+static GLboolean equality (slang_assemble_ctx *A, slang_operation *op, GLboolean equal)\r
 {\r
        slang_assembly_typeinfo ti;\r
-       int result;\r
+       GLboolean result = GL_FALSE;\r
        slang_storage_aggregate agg;\r
-       unsigned int index, size;\r
-       unsigned int skip_jump, true_label, true_jump, false_label, false_jump;\r
+       GLuint index, size;\r
+       GLuint skip_jump, true_label, true_jump, false_label, false_jump;\r
 \r
        /* get type of operation */\r
-       slang_assembly_typeinfo_construct (&ti);\r
-       if (!_slang_typeof_operation (op, space, &ti))\r
-       {\r
-               slang_assembly_typeinfo_destruct (&ti);\r
-               return 0;\r
-       }\r
+       if (!slang_assembly_typeinfo_construct (&ti))\r
+               return GL_FALSE;\r
+       if (!_slang_typeof_operation (A, op, &ti))\r
+               goto end1;\r
 \r
        /* convert it to an aggregate */\r
-       slang_storage_aggregate_construct (&agg);\r
-       if (!(result = _slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs)))\r
+       if (!slang_storage_aggregate_construct (&agg))\r
+               goto end1;\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
        /* compute the size of the agregate - there are two such aggregates on the stack */\r
        size = _slang_sizeof_aggregate (&agg);\r
 \r
        /* jump to the actual data-comparison code */\r
-       skip_jump = file->count;\r
-       if (!(result = slang_assembly_file_push (file, slang_asm_jump)))\r
+       skip_jump = A->file->count;\r
+       if (!PUSH (A->file, slang_asm_jump))\r
                goto end;\r
 \r
        /* pop off the stack the compared data and push 1 */\r
-       true_label = file->count;\r
-       if (!(result = slang_assembly_file_push_label (file, slang_asm_local_free, size * 2)))\r
+       true_label = A->file->count;\r
+       if (!PLAB (A->file, slang_asm_local_free, size * 2))\r
                goto end;\r
-       if (!(result = slang_assembly_file_push_literal (file, slang_asm_bool_push, 1.0f)))\r
+       if (!PLIT (A->file, slang_asm_bool_push, (GLfloat) 1))\r
                goto end;\r
-       true_jump = file->count;\r
-       if (!(result = slang_assembly_file_push (file, slang_asm_jump)))\r
+       true_jump = A->file->count;\r
+       if (!PUSH (A->file, slang_asm_jump))\r
                goto end;\r
 \r
-       false_label = file->count;\r
-       if (!(result = slang_assembly_file_push_label (file, slang_asm_local_free, size * 2)))\r
+       false_label = A->file->count;\r
+       if (!PLAB (A->file, slang_asm_local_free, size * 2))\r
                goto end;\r
-       if (!(result = slang_assembly_file_push_literal (file, slang_asm_bool_push, 0.0f)))\r
+       if (!PLIT (A->file, slang_asm_bool_push, (GLfloat) 0))\r
                goto end;\r
-       false_jump = file->count;\r
-       if (!(result = slang_assembly_file_push (file, slang_asm_jump)))\r
+       false_jump = A->file->count;\r
+       if (!PUSH (A->file, slang_asm_jump))\r
                goto end;\r
 \r
-       file->code[skip_jump].param[0] = file->count;\r
+       A->file->code[skip_jump].param[0] = A->file->count;\r
 \r
        /* compare the data on stack, it will eventually jump either to true or false label */\r
        index = 0;\r
-       if (!(result = equality_aggregate (file, &agg, &index, size, info,\r
-               equal ? false_label : true_label)))\r
+       if (!equality_aggregate (A, &agg, &index, size, equal ? false_label : true_label))\r
                goto end;\r
-       if (!(result = slang_assembly_file_push_label (file, slang_asm_jump,\r
-               equal ? true_label : false_label)))\r
+       if (!PLAB (A->file, slang_asm_jump, equal ? true_label : false_label))\r
                goto end;\r
 \r
-       file->code[true_jump].param[0] = file->count;\r
-       file->code[false_jump].param[0] = file->count;\r
+       A->file->code[true_jump].param[0] = A->file->count;\r
+       A->file->code[false_jump].param[0] = A->file->count;\r
 \r
-       result = 1;\r
+       result = GL_TRUE;\r
 end:\r
        slang_storage_aggregate_destruct (&agg);\r
+end1:\r
        slang_assembly_typeinfo_destruct (&ti);\r
        return result;\r
 }\r
 \r
-int _slang_assemble_operation (slang_assembly_file *file, slang_operation *op, int reference,\r
-       slang_assembly_flow_control *flow, slang_assembly_name_space *space,\r
-       slang_assembly_local_info *info, slang_assembly_stack_info *stk)\r
+static GLboolean handle_subscript (slang_assemble_ctx *A, slang_assembly_typeinfo *tie,\r
+       slang_assembly_typeinfo *tia, slang_operation *op, slang_ref_type ref)\r
+{\r
+       GLuint asize = 0, esize = 0;\r
+\r
+       /* get type info of the master expression (matrix, vector or an array */\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_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 (A, op, tie))\r
+               return GL_FALSE;\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
+               return GL_FALSE;\r
+\r
+       /* when indexing an l-value swizzle, push the swizzle_tmp */\r
+       if (ref == slang_ref_force && tia->is_swizzled)\r
+               if (!PLAB2 (A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16))\r
+                       return GL_FALSE;\r
+\r
+       /* assemble the subscript expression */\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
+       {\r
+               GLuint i;\r
+\r
+               /* copy the swizzle indexes to the swizzle_tmp */\r
+               for (i = 0; i < tia->swz.num_components; i++)\r
+               {\r
+                       if (!PLAB2 (A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16))\r
+                               return GL_FALSE;\r
+                       if (!PLAB (A->file, slang_asm_addr_push, i * 4))\r
+                               return GL_FALSE;\r
+                       if (!PUSH (A->file, slang_asm_addr_add))\r
+                               return GL_FALSE;\r
+                       if (!PLAB (A->file, slang_asm_addr_push, tia->swz.swizzle[i]))\r
+                               return GL_FALSE;\r
+                       if (!PUSH (A->file, slang_asm_addr_copy))\r
+                               return GL_FALSE;\r
+                       if (!PLAB (A->file, slang_asm_local_free, 4))\r
+                               return GL_FALSE;\r
+               }\r
+\r
+               /* offset the pushed swizzle_tmp address and dereference it */\r
+               if (!PUSH (A->file, slang_asm_int_to_addr))\r
+                       return GL_FALSE;\r
+               if (!PLAB (A->file, slang_asm_addr_push, 4))\r
+                       return GL_FALSE;\r
+               if (!PUSH (A->file, slang_asm_addr_multiply))\r
+                       return GL_FALSE;\r
+               if (!PUSH (A->file, slang_asm_addr_add))\r
+                       return GL_FALSE;\r
+               if (!PUSH (A->file, slang_asm_addr_deref))\r
+                       return GL_FALSE;\r
+       }\r
+       else\r
+       {\r
+               /* convert the integer subscript to a relative address */\r
+               if (!PUSH (A->file, slang_asm_int_to_addr))\r
+                       return GL_FALSE;\r
+       }\r
+\r
+       if (!PLAB (A->file, slang_asm_addr_push, esize))\r
+               return GL_FALSE;\r
+       if (!PUSH (A->file, slang_asm_addr_multiply))\r
+               return GL_FALSE;\r
+\r
+       if (ref == slang_ref_force)\r
+       {\r
+               /* offset the base address with the relative address */\r
+               if (!PUSH (A->file, slang_asm_addr_add))\r
+                       return GL_FALSE;\r
+       }\r
+       else\r
+       {\r
+               GLuint i;\r
+\r
+               /* move the selected element to the beginning of the master expression */\r
+               for (i = 0; i < esize; i += 4)\r
+                       if (!PLAB2 (A->file, slang_asm_float_move, asize - esize + i + 4, i + 4))\r
+                               return GL_FALSE;\r
+               if (!PLAB (A->file, slang_asm_local_free, 4))\r
+                       return GL_FALSE;\r
+\r
+               /* free the rest of the master expression */\r
+               if (!PLAB (A->file, slang_asm_local_free, asize - esize))\r
+                       return GL_FALSE;\r
+       }\r
+\r
+       return GL_TRUE;\r
+}\r
+\r
+static GLboolean handle_field (slang_assemble_ctx *A, slang_assembly_typeinfo *tia,\r
+       slang_assembly_typeinfo *tib, slang_operation *op, slang_ref_type ref)\r
 {\r
-       unsigned int asm;\r
+       /* get type info of the result (field or swizzle) */\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 (A, &op->children[0], tib))\r
+               return GL_FALSE;\r
+\r
+       /* if swizzling a vector in-place, the swizzle temporary is needed */\r
+       if (ref == slang_ref_forbid && tia->is_swizzled)\r
+               if (!PLAB2 (A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16))\r
+                       return GL_FALSE;\r
+\r
+       /* assemble the master expression */\r
+       if (!_slang_assemble_operation (A, &op->children[0], ref))\r
+               return GL_FALSE;\r
+\r
+       /* assemble the field expression */\r
+       if (tia->is_swizzled)\r
+       {\r
+               if (ref == slang_ref_force)\r
+               {\r
+#if 0\r
+                       if (tia->swz.num_components == 1)\r
+                       {\r
+                               /* simple case - adjust the vector's address to point to the selected component */\r
+                               if (!PLAB (file, slang_asm_addr_push, tia->swz.swizzle[0] * 4))\r
+                                       return 0;\r
+                               if (!PUSH (file, slang_asm_addr_add))\r
+                                       return 0;\r
+                       }\r
+                       else\r
+#endif\r
+                       {\r
+                               /* two or more vector components are being referenced - the so-called write mask\r
+                                * must be passed to the upper operations and applied when assigning value\r
+                                * to this swizzle */\r
+                               A->swz = tia->swz;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       /* swizzle the vector in-place using the swizzle temporary */\r
+                       if (!_slang_assemble_constructor_from_swizzle (A, &tia->swz, &tia->spec, &tib->spec))\r
+                               return GL_FALSE;\r
+               }\r
+       }\r
+       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
+                       slang_storage_aggregate agg;\r
+                       GLuint size;\r
+\r
+                       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_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
+                               return GL_FALSE;\r
+                       }\r
+                       size = _slang_sizeof_aggregate (&agg);\r
+                       slang_storage_aggregate_destruct (&agg);\r
+\r
+                       if (op->a_id == field->a_name)\r
+                       {\r
+                               field_size = size;\r
+                               struct_size = field_offset + size;\r
+                       }\r
+                       else if (struct_size != 0)\r
+                               struct_size += size;\r
+                       else\r
+                               field_offset += size;\r
+               }\r
+\r
+               /*\r
+                * OPTIMIZATION: If selecting the last field, no relocation is needed.\r
+                */\r
+               relocate = field_offset != struct_size - field_size;\r
+\r
+               /*\r
+                * OPTIMIZATION: If field and struct sizes are equal, no partial free is needed.\r
+                */\r
+               shrink = field_size != struct_size;\r
 \r
-       stk->swizzle_mask = 0;\r
+               if (relocate)\r
+               {\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 free_b = 0;\r
+\r
+                       if (relocate)\r
+                       {\r
+                               GLuint i;\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
+                               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
-       asm = file->count;\r
-       if (!slang_assembly_file_push_new (file))\r
-               return 0;\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
+{\r
+       /* set default results */\r
+       A->ref = /*(ref == slang_ref_freelance) ? slang_ref_force : */ref;\r
+       A->swz.num_components = 0;\r
 \r
        switch (op->type)\r
        {\r
        case slang_oper_block_no_new_scope:\r
        case slang_oper_block_new_scope:\r
                {\r
-                       unsigned int i;\r
+                       GLuint i;\r
+\r
                        for (i = 0; i < op->num_children; i++)\r
                        {\r
-                               slang_assembly_stack_info stk;\r
-                               if (!_slang_assemble_operation (file, op->children + i, 0, flow, space, info, &stk))\r
-                                       return 0;\r
-                               /* TODO: pass-in stk to cleanup */\r
-                               if (!_slang_cleanup_stack (file, op->children + i, 0, space))\r
-                                       return 0;\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
+                                       return GL_FALSE;\r
                        }\r
                }\r
                break;\r
        case slang_oper_variable_decl:\r
                {\r
-                       unsigned int i;\r
+                       GLuint i;\r
 \r
                        for (i = 0; i < op->num_children; i++)\r
                        {\r
@@ -711,155 +1058,167 @@ int _slang_assemble_operation (slang_assembly_file *file, slang_operation *op, i
                break;\r
        case slang_oper_asm:\r
                {\r
-                       unsigned int i;\r
-                       for (i = 0; i < op->num_children; i++)\r
-                       {\r
-                               slang_assembly_stack_info stk;\r
-                               if (!_slang_assemble_operation (file, op->children + i, i == 0, flow, space, info,\r
-                                       &stk))\r
-                                       return 0;\r
-                               /* TODO: inspect stk */\r
-                       }\r
-                       if (!call_asm_instruction (file, op->identifier))\r
-                               return 0;\r
+                       GLuint i;\r
+\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
+                                       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
-               file->code[asm].type = slang_asm_jump;\r
-               file->code[asm].param[0] = 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
-               file->code[asm].type = slang_asm_jump;\r
-               file->code[asm].param[0] = 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
-               file->code[asm].type = slang_asm_discard;\r
-               if (!slang_assembly_file_push (file, slang_asm_exit))\r
-                       return 0;\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
        case slang_oper_return:\r
-               if (info->ret_size != 0)\r
+               if (A->local.ret_size != 0)\r
                {\r
-                       slang_assembly_stack_info stk;\r
-                       if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, 0, info->ret_size))\r
-                               return 0;\r
-                       if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk))\r
-                               return 0;\r
-                       /* TODO: inspect stk */\r
-                       if (!_slang_assemble_assignment (file, op->children, space, info))\r
-                               return 0;\r
-                       if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4))\r
-                               return 0;\r
+                       /* 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
+                               return GL_FALSE;\r
+\r
+                       A->swz.num_components = 0;\r
+                       /* assign the operation to the function result (it was reserved on the stack) */\r
+                       if (!_slang_assemble_assignment (A, op->children))\r
+                               return GL_FALSE;\r
+\r
+                       if (!PLAB (A->file, slang_asm_local_free, 4))\r
+                               return GL_FALSE;\r
                }\r
-               if (!slang_assembly_file_push_label (file, slang_asm_jump, flow->function_end))\r
-                       return 0;\r
+               if (!PLAB (A->file, slang_asm_jump, A->flow.function_end))\r
+                       return GL_FALSE;\r
                break;\r
        case slang_oper_expression:\r
-               {\r
-                       slang_assembly_stack_info stk;\r
-                       if (!_slang_assemble_operation (file, op->children, reference, flow, space, info, &stk))\r
-                               return 0;\r
-                       /* TODO: inspect stk */\r
-               }\r
+               if (ref == slang_ref_force)\r
+                       return GL_FALSE;\r
+               if (!_slang_assemble_operation (A, &op->children[0], ref))\r
+                       return GL_FALSE;\r
                break;\r
        case slang_oper_if:\r
-               if (!_slang_assemble_if (file, op, flow, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_if (A, op))\r
+                       return GL_FALSE;\r
                break;\r
        case slang_oper_while:\r
-               if (!_slang_assemble_while (file, op, flow, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_while (A, op))\r
+                       return GL_FALSE;\r
                break;\r
        case slang_oper_do:\r
-               if (!_slang_assemble_do (file, op, flow, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_do (A, op))\r
+                       return GL_FALSE;\r
                break;\r
        case slang_oper_for:\r
-               if (!_slang_assemble_for (file, op, flow, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_for (A, op))\r
+                       return GL_FALSE;\r
                break;\r
        case slang_oper_void:\r
                break;\r
        case slang_oper_literal_bool:\r
-               file->code[asm].type = slang_asm_bool_push;\r
-               file->code[asm].literal = op->literal;\r
+               if (ref == slang_ref_force)\r
+                       return GL_FALSE;\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
-               file->code[asm].type = slang_asm_int_push;\r
-               file->code[asm].literal = op->literal;\r
+               if (ref == slang_ref_force)\r
+                       return GL_FALSE;\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
-               file->code[asm].type = slang_asm_float_push;\r
-               file->code[asm].literal = op->literal;\r
+               if (ref == slang_ref_force)\r
+                       return GL_FALSE;\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
                {\r
                        slang_variable *var;\r
-                       unsigned int size;\r
-                       var = _slang_locate_variable (op->locals, op->identifier, 1);\r
+                       GLuint size;\r
+\r
+                       /* find the variable and calculate its size */\r
+                       var = _slang_locate_variable (op->locals, op->a_id, GL_TRUE);\r
                        if (var == NULL)\r
-                               return 0;\r
+                               return GL_FALSE;\r
                        size = 0;\r
-                       if (!sizeof_variable (&var->type.specifier, slang_qual_none, var->array_size, space,\r
-                               &size))\r
-                               return 0;\r
-                       if (var->initializer != NULL)\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
+                       if (ref == slang_ref_forbid)\r
+                               if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4))\r
+                                       return GL_FALSE;\r
+\r
+                       /* push the variable's address */\r
+                       if (var->global)\r
                        {\r
-                               assert (!"var->initializer, oper_identifier");\r
+                               if (!PLAB (A->file, slang_asm_global_addr, var->address))\r
+                                       return GL_FALSE;\r
                        }\r
                        else\r
                        {\r
-                               if (!reference)\r
-                               {\r
-                                       if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr,\r
-                                               info->addr_tmp, 4))\r
-                                               return 0;\r
-                               }\r
-                               /* XXX: globals! */\r
-                               if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, var->address,\r
-                                       size))\r
-                                       return 0;\r
-                               if (!reference)\r
-                               {\r
-                                       if (!slang_assembly_file_push (file, slang_asm_addr_copy))\r
-                                               return 0;\r
-                                       if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4))\r
-                                               return 0;\r
-                                       if (!dereference (file, op, space, info))\r
-                                               return 0;\r
-                               }\r
+                               if (!PLAB2 (A->file, slang_asm_local_addr, var->address, size))\r
+                                       return GL_FALSE;\r
+                       }\r
+\r
+                       /* perform the dereference */\r
+                       if (ref == slang_ref_forbid)\r
+                       {\r
+                               if (!PUSH (A->file, slang_asm_addr_copy))\r
+                                       return GL_FALSE;\r
+                               if (!PLAB (A->file, slang_asm_local_free, 4))\r
+                                       return GL_FALSE;\r
+                               if (!_slang_dereference (A, op))\r
+                                       return GL_FALSE;\r
                        }\r
                }\r
                break;\r
        case slang_oper_sequence:\r
-               {\r
-                       slang_assembly_stack_info stk;\r
-                       if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk))\r
-                               return 0;\r
-                       /* TODO: pass-in stk to cleanup */\r
-                       if (!_slang_cleanup_stack (file, op->children, 0, space))\r
-                               return 0;\r
-                       if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info,\r
-                               &stk))\r
-                               return 0;\r
-                       /* TODO: inspect stk */\r
-               }\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
+                       return GL_FALSE;\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
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_assign:\r
-               if (!_slang_assemble_assign (file, op, "=", reference, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_assign (A, op, "=", ref))\r
+                       return GL_FALSE;\r
                break;\r
        case slang_oper_addassign:\r
-               if (!_slang_assemble_assign (file, op, "+=", reference, space, info))\r
-                       return 0;\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 (file, op, "-=", reference, space, info))\r
-                       return 0;\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 (file, op, "*=", reference, space, info))\r
-                       return 0;\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
@@ -868,197 +1227,136 @@ int _slang_assemble_operation (slang_assembly_file *file, slang_operation *op, i
        /*case slang_oper_xorassign:*/\r
        /*case slang_oper_andassign:*/\r
        case slang_oper_divassign:\r
-               if (!_slang_assemble_assign (file, op, "/=", reference, space, info))\r
-                       return 0;\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 (file, op, flow, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_select (A, op))\r
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_logicalor:\r
-               if (!_slang_assemble_logicalor (file, op, flow, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_logicalor (A, op))\r
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_logicaland:\r
-               if (!_slang_assemble_logicaland (file, op, flow, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_logicaland (A, op))\r
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_logicalxor:\r
-               if (!call_function_name (file, "^^", op->children, 2, 0, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_function_call_name (A, "^^", op->children, 2, GL_FALSE))\r
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        /*case slang_oper_bitor:*/\r
        /*case slang_oper_bitxor:*/\r
        /*case slang_oper_bitand:*/\r
        case slang_oper_less:\r
-               if (!call_function_name (file, "<", op->children, 2, 0, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_function_call_name (A, "<", op->children, 2, GL_FALSE))\r
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_greater:\r
-               if (!call_function_name (file, ">", op->children, 2, 0, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_function_call_name (A, ">", op->children, 2, GL_FALSE))\r
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_lessequal:\r
-               if (!call_function_name (file, "<=", op->children, 2, 0, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_function_call_name (A, "<=", op->children, 2, GL_FALSE))\r
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_greaterequal:\r
-               if (!call_function_name (file, ">=", op->children, 2, 0, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_function_call_name (A, ">=", op->children, 2, GL_FALSE))\r
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        /*case slang_oper_lshift:*/\r
        /*case slang_oper_rshift:*/\r
        case slang_oper_add:\r
-               if (!call_function_name (file, "+", op->children, 2, 0, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_function_call_name (A, "+", op->children, 2, GL_FALSE))\r
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_subtract:\r
-               if (!call_function_name (file, "-", op->children, 2, 0, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_function_call_name (A, "-", op->children, 2, GL_FALSE))\r
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_multiply:\r
-               if (!call_function_name (file, "*", op->children, 2, 0, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_function_call_name (A, "*", op->children, 2, GL_FALSE))\r
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        /*case slang_oper_modulus:*/\r
        case slang_oper_divide:\r
-               if (!call_function_name (file, "/", op->children, 2, 0, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_function_call_name (A, "/", op->children, 2, GL_FALSE))\r
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_equal:\r
-               {\r
-                       slang_assembly_stack_info stk;\r
-                       if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk))\r
-                               return 0;\r
-                       /* TODO: inspect stk */\r
-                       if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk))\r
-                               return 0;\r
-                       /* TODO: inspect stk */\r
-                       if (!equality (file, op->children, space, info, 1))\r
-                               return 0;\r
-               }\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
+                       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
-               {\r
-                       slang_assembly_stack_info stk;\r
-                       if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk))\r
-                               return 0;\r
-                       /* TODO: inspect stk */\r
-                       if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk))\r
-                               return 0;\r
-                       /* TODO: inspect stk */\r
-                       if (!equality (file, op->children, space, info, 0))\r
-                               return 0;\r
-               }\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
+                       return GL_FALSE;\r
+               if (!equality (A, op->children, GL_FALSE))\r
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_preincrement:\r
-               if (!_slang_assemble_assign (file, op, "++", reference, space, info))\r
-                       return 0;\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 (file, op, "--", reference, space, info))\r
-                       return 0;\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 (!call_function_name (file, "+", op->children, 1, 0, space, info))\r
-                       return 0;\r
+               if (!_slang_dereference (A, op))\r
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_minus:\r
-               if (!call_function_name (file, "-", op->children, 1, 0, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_function_call_name (A, "-", op->children, 1, GL_FALSE))\r
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        /*case slang_oper_complement:*/\r
        case slang_oper_not:\r
-               if (!call_function_name (file, "!", op->children, 1, 0, space, info))\r
-                       return 0;\r
+               if (!_slang_assemble_function_call_name (A, "!", op->children, 1, GL_FALSE))\r
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_subscript:\r
                {\r
-                       slang_assembly_stack_info _stk;\r
                        slang_assembly_typeinfo ti_arr, ti_elem;\r
-                       unsigned int arr_size = 0, elem_size = 0;\r
-                       if (!_slang_assemble_operation (file, op->children, reference, flow, space, info,\r
-                               &_stk))\r
-                               return 0;\r
-                       if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &_stk))\r
-                               return 0;\r
-                       slang_assembly_typeinfo_construct (&ti_arr);\r
-                       if (!_slang_typeof_operation (op->children, space, &ti_arr))\r
-                       {\r
-                               slang_assembly_typeinfo_destruct (&ti_arr);\r
-                               return 0;\r
-                       }\r
-                       if (!sizeof_variable (&ti_arr.spec, slang_qual_none, NULL, space, &arr_size))\r
-                       {\r
-                               slang_assembly_typeinfo_destruct (&ti_arr);\r
-                               return 0;\r
-                       }\r
-                       slang_assembly_typeinfo_construct (&ti_elem);\r
-                       if (!_slang_typeof_operation (op, space, &ti_elem))\r
-                       {\r
-                               slang_assembly_typeinfo_destruct (&ti_arr);\r
-                               slang_assembly_typeinfo_destruct (&ti_elem);\r
-                               return 0;\r
-                       }\r
-                       if (!sizeof_variable (&ti_elem.spec, slang_qual_none, NULL, space, &elem_size))\r
-                       {\r
-                               slang_assembly_typeinfo_destruct (&ti_arr);\r
-                               slang_assembly_typeinfo_destruct (&ti_elem);\r
-                               return 0;\r
-                       }\r
-                       if (!slang_assembly_file_push (file, slang_asm_int_to_addr))\r
-                       {\r
-                               slang_assembly_typeinfo_destruct (&ti_arr);\r
-                               slang_assembly_typeinfo_destruct (&ti_elem);\r
-                               return 0;\r
-                       }\r
-                       if (!slang_assembly_file_push_label (file, slang_asm_addr_push, elem_size))\r
+\r
+                       if (!slang_assembly_typeinfo_construct (&ti_arr))\r
+                               return GL_FALSE;\r
+                       if (!slang_assembly_typeinfo_construct (&ti_elem))\r
                        {\r
                                slang_assembly_typeinfo_destruct (&ti_arr);\r
-                               slang_assembly_typeinfo_destruct (&ti_elem);\r
-                               return 0;\r
+                               return GL_FALSE;\r
                        }\r
-                       if (!slang_assembly_file_push (file, slang_asm_addr_multiply))\r
+                       if (!handle_subscript (A, &ti_elem, &ti_arr, op, ref))\r
                        {\r
                                slang_assembly_typeinfo_destruct (&ti_arr);\r
                                slang_assembly_typeinfo_destruct (&ti_elem);\r
-                               return 0;\r
-                       }\r
-                       if (reference)\r
-                       {\r
-                               if (!slang_assembly_file_push (file, slang_asm_addr_add))\r
-                               {\r
-                                       slang_assembly_typeinfo_destruct (&ti_arr);\r
-                                       slang_assembly_typeinfo_destruct (&ti_elem);\r
-                                       return 0;\r
-                               }\r
-                       }\r
-                       else\r
-                       {\r
-                               unsigned int i;\r
-                               for (i = 0; i < elem_size; i += 4)\r
-                               {\r
-                                       if (!slang_assembly_file_push_label2 (file, slang_asm_float_move,\r
-                                               arr_size - elem_size + i + 4, i + 4))\r
-                                       {\r
-                                               slang_assembly_typeinfo_destruct (&ti_arr);\r
-                                               slang_assembly_typeinfo_destruct (&ti_elem);\r
-                                               return 0;\r
-                                       }\r
-                               }\r
-                               if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4))\r
-                               {\r
-                                       slang_assembly_typeinfo_destruct (&ti_arr);\r
-                                       slang_assembly_typeinfo_destruct (&ti_elem);\r
-                                       return 0;\r
-                               }\r
-                               if (!slang_assembly_file_push_label (file, slang_asm_local_free,\r
-                                       arr_size - elem_size))\r
-                               {\r
-                                       slang_assembly_typeinfo_destruct (&ti_arr);\r
-                                       slang_assembly_typeinfo_destruct (&ti_elem);\r
-                                       return 0;\r
-                               }\r
+                               return GL_FALSE;\r
                        }\r
                        slang_assembly_typeinfo_destruct (&ti_arr);\r
                        slang_assembly_typeinfo_destruct (&ti_elem);\r
@@ -1066,143 +1364,58 @@ int _slang_assemble_operation (slang_assembly_file *file, slang_operation *op, i
                break;\r
        case slang_oper_call:\r
                {\r
-                       slang_function *fun = _slang_locate_function (op->identifier, op->children,\r
-                               op->num_children, space);\r
+                       slang_function *fun;\r
+\r
+                       fun = _slang_locate_function (A->space.funcs, op->a_id, op->children, op->num_children,\r
+                               &A->space, A->atoms);\r
                        if (fun == NULL)\r
                        {\r
-                               if (!_slang_assemble_constructor (file, op, flow, space, info))\r
-                                       return 0;\r
+                               if (!_slang_assemble_constructor (A, op))\r
+                                       return GL_FALSE;\r
                        }\r
                        else\r
                        {\r
-                               if (!call_function (file, fun, op->children, op->num_children, 0, space, info))\r
-                                       return 0;\r
+                               if (!_slang_assemble_function_call (A, fun, op->children, op->num_children, GL_FALSE))\r
+                                       return GL_FALSE;\r
                        }\r
+                       A->ref = slang_ref_forbid;\r
                }\r
                break;\r
        case slang_oper_field:\r
                {\r
                        slang_assembly_typeinfo ti_after, ti_before;\r
-                       slang_assembly_stack_info _stk;\r
-                       slang_assembly_typeinfo_construct (&ti_after);\r
-                       if (!_slang_typeof_operation (op, space, &ti_after))\r
+\r
+                       if (!slang_assembly_typeinfo_construct (&ti_after))\r
+                               return GL_FALSE;\r
+                       if (!slang_assembly_typeinfo_construct (&ti_before))\r
                        {\r
                                slang_assembly_typeinfo_destruct (&ti_after);\r
-                               return 0;\r
+                               return GL_FALSE;\r
                        }\r
-                       slang_assembly_typeinfo_construct (&ti_before);\r
-                       if (!_slang_typeof_operation (op->children, space, &ti_before))\r
+                       if (!handle_field (A, &ti_after, &ti_before, op, ref))\r
                        {\r
                                slang_assembly_typeinfo_destruct (&ti_after);\r
                                slang_assembly_typeinfo_destruct (&ti_before);\r
-                               return 0;\r
-                       }\r
-                       if (!reference && ti_after.is_swizzled)\r
-                       {\r
-                               if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr,\r
-                                       info->swizzle_tmp, 16))\r
-                               {\r
-                                       slang_assembly_typeinfo_destruct (&ti_after);\r
-                                       slang_assembly_typeinfo_destruct (&ti_before);\r
-                                       return 0;\r
-                               }\r
-                       }\r
-                       if (!_slang_assemble_operation (file, op->children, reference, flow, space, info,\r
-                               &_stk))\r
-                       {\r
-                               slang_assembly_typeinfo_destruct (&ti_after);\r
-                               slang_assembly_typeinfo_destruct (&ti_before);\r
-                               return 0;\r
-                       }\r
-                       /* TODO: inspect stk */\r
-                       if (ti_after.is_swizzled)\r
-                       {\r
-                               if (reference)\r
-                               {\r
-                                       if (ti_after.swz.num_components == 1)\r
-                                       {\r
-                                               if (!slang_assembly_file_push_label (file, slang_asm_addr_push,\r
-                                                       ti_after.swz.swizzle[0] * 4))\r
-                                               {\r
-                                                       slang_assembly_typeinfo_destruct (&ti_after);\r
-                                                       slang_assembly_typeinfo_destruct (&ti_before);\r
-                                                       return 0;\r
-                                               }\r
-                                               if (!slang_assembly_file_push (file, slang_asm_addr_add))\r
-                                               {\r
-                                                       slang_assembly_typeinfo_destruct (&ti_after);\r
-                                                       slang_assembly_typeinfo_destruct (&ti_before);\r
-                                                       return 0;\r
-                                               }\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               unsigned int i;\r
-                                               for (i = 0; i < ti_after.swz.num_components; i++)\r
-                                                       stk->swizzle_mask |= 1 << ti_after.swz.swizzle[i];\r
-                                       }\r
-                               }\r
-                               else\r
-                               {\r
-                                       if (!_slang_assemble_constructor_from_swizzle (file, &ti_after.swz,\r
-                                               &ti_after.spec, &ti_before.spec, info))\r
-                                       {\r
-                                               slang_assembly_typeinfo_destruct (&ti_after);\r
-                                               slang_assembly_typeinfo_destruct (&ti_before);\r
-                                               return 0;\r
-                                       }\r
-                               }\r
-                       }\r
-                       else\r
-                       {\r
-                               if (reference)\r
-                               {\r
-                                       /* TODO: struct field address */\r
-                               }\r
-                               else\r
-                               {\r
-                                       /* TODO: struct field value */\r
-                               }\r
+                               return GL_FALSE;\r
                        }\r
                        slang_assembly_typeinfo_destruct (&ti_after);\r
                        slang_assembly_typeinfo_destruct (&ti_before);\r
                }\r
                break;\r
        case slang_oper_postincrement:\r
-               if (!call_function_name_dummyint (file, "++", op->children, space, info))\r
-                       return 0;\r
-               if (!dereference (file, op, space, info))\r
-                       return 0;\r
+               if (!assemble_function_call_name_dummyint (A, "++", op->children))\r
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        case slang_oper_postdecrement:\r
-               if (!call_function_name_dummyint (file, "--", op->children, space, info))\r
-                       return 0;\r
-               if (!dereference (file, op, space, info))\r
-                       return 0;\r
+               if (!assemble_function_call_name_dummyint (A, "--", op->children))\r
+                       return GL_FALSE;\r
+               A->ref = slang_ref_forbid;\r
                break;\r
        default:\r
-               return 0;\r
+               return GL_FALSE;\r
        }\r
-       return 1;\r
-}\r
-\r
-\r
-\r
-\r
-\r
 \r
-\r
-\r
-\r
-void xxx_first (slang_assembly_file *file)\r
-{\r
-       slang_assembly_file_push (file, slang_asm_jump);\r
-}\r
-\r
-void xxx_prolog (slang_assembly_file *file, unsigned int addr)\r
-{\r
-       file->code[0].param[0] = file->count;\r
-       slang_assembly_file_push_label (file, slang_asm_call, addr);\r
-       slang_assembly_file_push (file, slang_asm_exit);\r
+       return GL_TRUE;\r
 }\r
 \r