diff options
Diffstat (limited to 'src/mesa/shader/slang/slang_assemble.c')
-rw-r--r-- | src/mesa/shader/slang/slang_assemble.c | 1588 |
1 files changed, 0 insertions, 1588 deletions
diff --git a/src/mesa/shader/slang/slang_assemble.c b/src/mesa/shader/slang/slang_assemble.c deleted file mode 100644 index e65bf38ad5..0000000000 --- a/src/mesa/shader/slang/slang_assemble.c +++ /dev/null @@ -1,1588 +0,0 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5.2 - * - * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/** - * \file slang_assemble.c - * slang intermediate code assembler - * \author Michal Krol - */ - -#include "imports.h" -#include "slang_assemble.h" -#include "slang_compile.h" -#include "slang_storage.h" -#include "slang_error.h" -#include "slang_print.h" - - -/* slang_assembly */ - -static GLboolean -slang_assembly_construct(slang_assembly * assem) -{ - assem->type = slang_asm_none; - return GL_TRUE; -} - -static GLvoid -slang_assembly_destruct(slang_assembly * assem) -{ -} - -/* - * slang_assembly_file - */ - -GLvoid -_slang_assembly_file_ctr(slang_assembly_file * self) -{ - self->code = NULL; - self->count = 0; - self->capacity = 0; -} - -GLvoid -slang_assembly_file_destruct(slang_assembly_file * file) -{ - GLuint i; - - for (i = 0; i < file->count; i++) - slang_assembly_destruct(&file->code[i]); - slang_alloc_free(file->code); -} - -static GLboolean -push_new(slang_assembly_file * file) -{ - if (file->count == file->capacity) { - GLuint n; - - if (file->capacity == 0) - n = 256; - else - n = file->capacity * 2; - file->code = (slang_assembly *) - slang_alloc_realloc(file->code, - file->capacity * sizeof(slang_assembly), - n * sizeof(slang_assembly)); - if (file->code == NULL) - return GL_FALSE; - file->capacity = n; - } - if (!slang_assembly_construct(&file->code[file->count])) - return GL_FALSE; - file->count++; - return GL_TRUE; -} - -static GLboolean -push_gen(slang_assembly_file * file, slang_assembly_type type, - GLfloat literal, GLuint label, GLuint size) -{ - slang_assembly *assem; - -#if 0 - printf("Gen %s %f %d %d\n", slang_asm_string(type), literal, label, size); -#endif - if (!push_new(file)) - return GL_FALSE; - assem = &file->code[file->count - 1]; - assem->type = type; - assem->literal = literal; - assem->param[0] = label; - assem->param[1] = size; - return GL_TRUE; -} - -GLboolean -slang_assembly_file_push(slang_assembly_file * file, slang_assembly_type type) -{ - return push_gen(file, type, (GLfloat) 0, 0, 0); -} - -GLboolean -slang_assembly_file_push_label(slang_assembly_file * file, - slang_assembly_type type, GLuint label) -{ - return push_gen(file, type, (GLfloat) 0, label, 0); -} - -GLboolean -slang_assembly_file_push_label2(slang_assembly_file * file, - slang_assembly_type type, GLuint label1, - GLuint label2) -{ - return push_gen(file, type, (GLfloat) 0, label1, label2); -} - -GLboolean -slang_assembly_file_push_literal(slang_assembly_file * file, - slang_assembly_type type, GLfloat literal) -{ - return push_gen(file, type, literal, 0, 0); -} - -#define PUSH slang_assembly_file_push -#define PLAB slang_assembly_file_push_label -#define PLAB2 slang_assembly_file_push_label2 -#define PLIT slang_assembly_file_push_literal - -/* slang_assembly_file_restore_point */ - -GLboolean -slang_assembly_file_restore_point_save(slang_assembly_file * file, - slang_assembly_file_restore_point * - point) -{ - point->count = file->count; - return GL_TRUE; -} - -GLboolean -slang_assembly_file_restore_point_load(slang_assembly_file * file, - slang_assembly_file_restore_point * - point) -{ - GLuint i; - - for (i = point->count; i < file->count; i++) - slang_assembly_destruct(&file->code[i]); - file->count = point->count; - return GL_TRUE; -} - -/* utility functions */ - -static GLboolean -sizeof_variable(const slang_assemble_ctx * A, slang_type_specifier * spec, - slang_type_qualifier qual, GLuint array_len, GLuint * size) -{ - slang_storage_aggregate agg; - - /* calculate the size of the variable's aggregate */ - if (!slang_storage_aggregate_construct(&agg)) - return GL_FALSE; - if (!_slang_aggregate_variable(&agg, spec, array_len, A->space.funcs, - A->space.structs, A->space.vars, - A->file, A->atoms)) { - slang_storage_aggregate_destruct(&agg); - return GL_FALSE; - } - *size += _slang_sizeof_aggregate(&agg); - slang_storage_aggregate_destruct(&agg); - - /* for reference variables consider the additional address overhead */ - if (qual == slang_qual_out || qual == slang_qual_inout) - *size += 4; - - return GL_TRUE; -} - -static GLboolean -sizeof_variable2(slang_assemble_ctx * A, slang_variable * var, GLuint * size) -{ - var->address = *size; - if (var->type.qualifier == slang_qual_out - || var->type.qualifier == slang_qual_inout) - var->address += 4; - return sizeof_variable(A, &var->type.specifier, var->type.qualifier, - var->array_len, size); -} - -static GLboolean -sizeof_variables(slang_assemble_ctx * A, slang_variable_scope * vars, - GLuint start, GLuint stop, GLuint * size) -{ - GLuint i; - - for (i = start; i < stop; i++) - if (!sizeof_variable2(A, vars->variables[i], size)) - return GL_FALSE; - return GL_TRUE; -} - -static GLboolean -collect_locals(slang_assemble_ctx * A, slang_operation * op, GLuint * size) -{ - GLuint i; - - if (!sizeof_variables(A, op->locals, 0, op->locals->num_variables, size)) - return GL_FALSE; - for (i = 0; i < op->num_children; i++) - if (!collect_locals(A, &op->children[i], size)) - return GL_FALSE; - return GL_TRUE; -} - -/* _slang_locate_function() */ - -/** - * Locate a function by comparing actual arguments against formal parameters. - */ -slang_function * -_slang_locate_function(const slang_function_scope * funcs, slang_atom a_name, - const slang_operation * args, GLuint num_args, - const slang_assembly_name_space * space, - slang_atom_pool * atoms) -{ - GLuint i; - - for (i = 0; i < funcs->num_functions; i++) { - slang_function *f = &funcs->functions[i]; - const GLuint haveRetValue = _slang_function_has_return_value(f); - GLuint j; - - if (a_name != f->header.a_name) - continue; - if (f->param_count - haveRetValue != num_args) - continue; - - /* compare parameter / argument types */ - for (j = 0; j < num_args; j++) { - slang_assembly_typeinfo ti; - - if (!slang_assembly_typeinfo_construct(&ti)) - return NULL; - if (!_slang_typeof_operation_(&args[j], space, &ti, atoms)) { - slang_assembly_typeinfo_destruct(&ti); - return NULL; - } - if (!slang_type_specifier_equal(&ti.spec, - &f->parameters->variables[j/* + haveRetValue*/]->type.specifier)) { - slang_assembly_typeinfo_destruct(&ti); - break; - } - slang_assembly_typeinfo_destruct(&ti); - - /* "out" and "inout" formal parameter requires the actual parameter to be l-value */ - if (!ti.can_be_referenced && - (f->parameters->variables[j/* + haveRetValue*/]->type.qualifier == slang_qual_out || - f->parameters->variables[j/* + haveRetValue*/]->type.qualifier == slang_qual_inout)) - break; - } - if (j == num_args) - return f; - } - if (funcs->outer_scope != NULL) - return _slang_locate_function(funcs->outer_scope, a_name, args, - num_args, space, atoms); - return NULL; -} - - - -/** - * Generate assembly for a parsed function. - */ -GLboolean -_slang_assemble_function(slang_assemble_ctx * A, slang_function * fun) -{ - GLuint param_size, local_size; - GLuint skip, cleanup; - const GLuint haveRetValue = _slang_function_has_return_value(fun); - - fun->address = A->file->count; - - if (fun->body == NULL) { - /* jump to the actual function body - we do not know it, so add - * the instruction to fixup table - */ - if (!slang_fixup_save(&fun->fixups, fun->address)) - RETURN_NIL(); - if (!PUSH(A->file, slang_asm_jump)) - RETURN_OUT_OF_MEMORY(); - return GL_TRUE; - } - else { - /* resolve all fixup table entries and delete it */ - GLuint i; - for (i = 0; i < fun->fixups.count; i++) - A->file->code[fun->fixups.table[i]].param[0] = fun->address; - slang_fixup_table_free(&fun->fixups); - } - - /* At this point traverse function formal parameters and code to calculate - * total memory size to be allocated on the stack. - * During this process the variables will be assigned local addresses to - * reference them in the code. - * No storage optimizations are performed so exclusive scopes are not - * detected and shared. - */ - - /* calculate return value size */ - param_size = 0; - if (fun->header.type.specifier.type != slang_spec_void) { - if (!sizeof_variable(A, &fun->header.type.specifier, - slang_qual_none, 0, ¶m_size)) - RETURN_NIL(); - } - A->local.ret_size = param_size; - - /* calculate formal parameter list size */ - if (!sizeof_variables(A, fun->parameters, - 0, - fun->param_count - haveRetValue, ¶m_size)) - RETURN_NIL(); - - /* calculate local variables size - take into account the four-byte - * return address and temporaries for various tasks (4 for addr and - * 16 for swizzle temporaries). these include variables from the - * formal parameter scope and from the code - */ - A->local.addr_tmp = param_size + 4; - A->local.swizzle_tmp = param_size + 4 + 4; - local_size = param_size + 4 + 4 + 16; - if (!sizeof_variables(A, fun->parameters, fun->param_count, - fun->parameters->num_variables, &local_size)) { - RETURN_OUT_OF_MEMORY(); - } - if (!collect_locals(A, fun->body, &local_size)) - RETURN_NIL(); - - /* allocate local variable storage */ - if (!PLAB(A->file, slang_asm_local_alloc, local_size - param_size - 4)) - RETURN_OUT_OF_MEMORY(); - - /* mark a new frame for function variable storage */ - if (!PLAB(A->file, slang_asm_enter, local_size)) - RETURN_OUT_OF_MEMORY(); - - /* jump directly to the actual code */ - skip = A->file->count; - if (!push_new(A->file)) - RETURN_OUT_OF_MEMORY(); - A->file->code[skip].type = slang_asm_jump; - - /* all "return" statements will be directed here */ - A->flow.function_end = A->file->count; - cleanup = A->file->count; - if (!push_new(A->file)) - RETURN_OUT_OF_MEMORY(); - A->file->code[cleanup].type = slang_asm_jump; - - /* execute the function body */ - A->file->code[skip].param[0] = A->file->count; - if (!_slang_assemble_operation(A, fun->body, - /*slang_ref_freelance */ slang_ref_forbid)) - RETURN_NIL(); - - /* this is the end of the function - restore the old function frame */ - A->file->code[cleanup].param[0] = A->file->count; - if (!PUSH(A->file, slang_asm_leave)) - RETURN_OUT_OF_MEMORY(); - - /* free local variable storage */ - if (!PLAB(A->file, slang_asm_local_free, local_size - param_size - 4)) - RETURN_OUT_OF_MEMORY(); - - /* return from the function */ - if (!PUSH(A->file, slang_asm_return)) - RETURN_OUT_OF_MEMORY(); - - return GL_TRUE; -} - -GLboolean -_slang_cleanup_stack(slang_assemble_ctx * A, slang_operation * op) -{ - slang_assembly_typeinfo ti; - GLuint size = 0; - - /* get type info of the operation and calculate its size */ - if (!slang_assembly_typeinfo_construct(&ti)) - return GL_FALSE; - if (!_slang_typeof_operation(A, op, &ti)) { - slang_assembly_typeinfo_destruct(&ti); - return GL_FALSE; - } - if (ti.spec.type != slang_spec_void) { - if (A->ref == slang_ref_force) { - size = 4; - } - else if (!sizeof_variable(A, &ti.spec, slang_qual_none, 0, &size)) { - slang_assembly_typeinfo_destruct(&ti); - return GL_FALSE; - } - } - slang_assembly_typeinfo_destruct(&ti); - - /* if nonzero, free it from the stack */ - if (size != 0) { - if (!PLAB(A->file, slang_asm_local_free, size)) - return GL_FALSE; - } - - return GL_TRUE; -} - -/* _slang_assemble_operation() */ - -static GLboolean -dereference_basic(slang_assemble_ctx * A, slang_storage_type type, - GLuint * size, slang_swizzle * swz, GLboolean is_swizzled) -{ - GLuint src_offset; - slang_assembly_type ty; - - *size -= _slang_sizeof_type(type); - - /* If swizzling is taking place, we are forced to use scalar - * operations, even if we have vec4 instructions enabled (this - * should be actually done with special vec4 shuffle instructions). - * Adjust the size and calculate the offset within source variable - * to read. - */ - if (is_swizzled) - src_offset = swz->swizzle[*size / 4] * 4; - else - src_offset = *size; - - /* dereference data slot of a basic type */ - if (!PLAB2(A->file, slang_asm_local_addr, A->local.addr_tmp, 4)) - return GL_FALSE; - if (!PUSH(A->file, slang_asm_addr_deref)) - return GL_FALSE; - if (src_offset != 0) { - if (!PLAB(A->file, slang_asm_addr_push, src_offset)) - return GL_FALSE; - if (!PUSH(A->file, slang_asm_addr_add)) - return GL_FALSE; - } - - switch (type) { - case slang_stor_bool: - ty = slang_asm_bool_deref; - break; - case slang_stor_int: - ty = slang_asm_int_deref; - break; - case slang_stor_float: - ty = slang_asm_float_deref; - break; - default: - _mesa_problem(NULL, "Unexpected arr->type in dereference_basic"); - ty = slang_asm_none; - } - - return PUSH(A->file, ty); -} - -static GLboolean -dereference_aggregate(slang_assemble_ctx * A, - const slang_storage_aggregate * agg, GLuint * size, - slang_swizzle * swz, GLboolean is_swizzled) -{ - GLuint i; - - for (i = agg->count; i > 0; i--) { - const slang_storage_array *arr = &agg->arrays[i - 1]; - GLuint j; - - for (j = arr->length; j > 0; j--) { - if (arr->type == slang_stor_aggregate) { - if (!dereference_aggregate(A, arr->aggregate, size, - swz, is_swizzled)) - return GL_FALSE; - } - else { - if (is_swizzled && arr->type == slang_stor_vec4) { - if (!dereference_basic(A, slang_stor_float, size, swz, is_swizzled)) - return GL_FALSE; - if (!dereference_basic(A, slang_stor_float, size, swz, is_swizzled)) - return GL_FALSE; - if (!dereference_basic(A, slang_stor_float, size, swz, is_swizzled)) - return GL_FALSE; - if (!dereference_basic(A, slang_stor_float, size, swz, is_swizzled)) - return GL_FALSE; - } - else { - if (!dereference_basic(A, arr->type, size, swz, is_swizzled)) - return GL_FALSE; - } - } - } - } - - return GL_TRUE; -} - -GLboolean -_slang_dereference(slang_assemble_ctx * A, slang_operation * op) -{ - slang_assembly_typeinfo ti; - GLboolean result = GL_FALSE; - slang_storage_aggregate agg; - GLuint size; - - /* get type information of the given operation */ - if (!slang_assembly_typeinfo_construct(&ti)) - return GL_FALSE; - if (!_slang_typeof_operation(A, op, &ti)) - goto end1; - - /* construct aggregate from the type info */ - if (!slang_storage_aggregate_construct(&agg)) - goto end1; - if (!_slang_aggregate_variable(&agg, &ti.spec, ti.array_len, A->space.funcs, - A->space.structs, A->space.vars, - A->file, A->atoms)) - goto end; - - /* dereference the resulting aggregate */ - size = _slang_sizeof_aggregate(&agg); - result = dereference_aggregate(A, &agg, &size, &ti.swz, ti.is_swizzled); - - end: - slang_storage_aggregate_destruct(&agg); - end1: - slang_assembly_typeinfo_destruct(&ti); - return result; -} - - -/** - * Assemble a function call, given a pointer to the actual function to call. - */ -GLboolean -_slang_assemble_function_call(slang_assemble_ctx * A, slang_function * fun, - slang_operation * params, GLuint param_count, - GLboolean assignment) -{ - GLuint i; - slang_swizzle p_swz[64]; - slang_ref_type p_ref[64]; - /* - const GLuint haveRetValue = _slang_function_has_return_value(fun); - */ - - /* TODO: fix this, allocate dynamically */ - if (param_count > 64) - return GL_FALSE; - - /* make room for the return value, if any */ - if (fun->header.type.specifier.type != slang_spec_void) { - GLuint ret_size = 0; - - if (!sizeof_variable(A, &fun->header.type.specifier, - slang_qual_none, 0, &ret_size)) - return GL_FALSE; - if (!PLAB(A->file, slang_asm_local_alloc, ret_size)) - return GL_FALSE; - } - - /* push the actual parameters on the stack */ - for (i = 0; i < param_count; i++) { - if (fun->parameters->variables[i /*+ haveRetValue*/]->type.qualifier == slang_qual_inout || - fun->parameters->variables[i /*+ haveRetValue*/]->type.qualifier == slang_qual_out) { - if (!PLAB2(A->file, slang_asm_local_addr, A->local.addr_tmp, 4)) - return GL_FALSE; - /* TODO: optimize the "out" parameter case */ - if (!_slang_assemble_operation(A, ¶ms[i], slang_ref_force)) - return GL_FALSE; - p_swz[i] = A->swz; - p_ref[i] = A->ref; - if (!PUSH(A->file, slang_asm_addr_copy)) - return GL_FALSE; - if (!PUSH(A->file, slang_asm_addr_deref)) - return GL_FALSE; - if (i == 0 && assignment) { - /* duplicate the resulting address */ - if (!PLAB2(A->file, slang_asm_local_addr, A->local.addr_tmp, 4)) - return GL_FALSE; - if (!PUSH(A->file, slang_asm_addr_deref)) - return GL_FALSE; - } - if (!_slang_dereference(A, ¶ms[i])) - return GL_FALSE; - } - else { - if (!_slang_assemble_operation(A, ¶ms[i], slang_ref_forbid)) - return GL_FALSE; - p_swz[i] = A->swz; - p_ref[i] = A->ref; - } - } - - /* call the function */ -#if 0 - printf("CALL FUNCTION %s\n", (char*) fun->header.a_name); - slang_print_var_scope(fun->parameters, fun->param_count); -#endif - if (!PLAB(A->file, slang_asm_call, fun->address)) - return GL_FALSE; - - /* pop the parameters from the stack */ - for (i = param_count; i > 0; i--) { - GLuint j = i - 1; - - A->swz = p_swz[j]; - A->ref = p_ref[j]; - if (fun->parameters->variables[j /*+ haveRetValue*/]->type.qualifier == slang_qual_inout || - fun->parameters->variables[j/* + haveRetValue*/]->type.qualifier == slang_qual_out) { - /* for output parameter copy the contents of the formal parameter - * back to the original actual parameter - */ - if (!_slang_assemble_assignment(A, ¶ms[j])) - return GL_FALSE; - /* pop the actual parameter's address */ - if (!PLAB(A->file, slang_asm_local_free, 4)) - return GL_FALSE; - } - else { - /* pop the value of the parameter */ - if (!_slang_cleanup_stack(A, ¶ms[j])) - return GL_FALSE; - } - } - - return GL_TRUE; -} - - -/** - * Assemble a function call, given the name of the function to call and a - * list of parameters. - */ -GLboolean -_slang_assemble_function_call_name(slang_assemble_ctx * A, const char *name, - slang_operation * params, - GLuint param_count, GLboolean assignment) -{ - slang_atom atom; - slang_function *fun; - - atom = slang_atom_pool_atom(A->atoms, name); - if (atom == SLANG_ATOM_NULL) - return GL_FALSE; - fun = - _slang_locate_function(A->space.funcs, atom, params, param_count, - &A->space, A->atoms); - { - char *s = (char *) name; - if (strcmp(name, "vec4") == 0) - printf("LLLLLLLLLLLLLLL locate %s %p\n", s, (void*) fun); - } - - if (fun == NULL) - return GL_FALSE; - return _slang_assemble_function_call(A, fun, params, param_count, - assignment); -} - -static GLboolean -assemble_function_call_name_dummyint(slang_assemble_ctx * A, const char *name, - slang_operation * params) -{ - slang_operation p[2]; - GLboolean result; - - p[0] = params[0]; - if (!slang_operation_construct(&p[1])) - return GL_FALSE; - p[1].type = slang_oper_literal_int; - result = _slang_assemble_function_call_name(A, name, p, 2, GL_FALSE); - slang_operation_destruct(&p[1]); - return result; -} - -static const struct -{ - const char *name; - slang_assembly_type code1, code2; -} inst[] = { - /* core */ - {"float_add", slang_asm_float_add, slang_asm_float_copy}, - {"float_subtract", slang_asm_float_subtract, slang_asm_float_copy}, - {"float_multiply", slang_asm_float_multiply, slang_asm_float_copy}, - {"float_divide", slang_asm_float_divide, slang_asm_float_copy}, - {"float_negate", slang_asm_float_negate, slang_asm_float_copy}, - {"float_min", slang_asm_float_min, slang_asm_float_copy}, - {"float_max", slang_asm_float_max, slang_asm_float_copy}, - {"float_less", slang_asm_float_less, slang_asm_bool_copy}, - {"float_equal", slang_asm_float_equal_exp, slang_asm_bool_copy}, - {"float_to_int", slang_asm_float_to_int, slang_asm_int_copy}, - {"float_sine", slang_asm_float_sine, slang_asm_float_copy}, - {"float_cosine", slang_asm_float_cosine, slang_asm_float_copy}, - {"float_arcsine", slang_asm_float_arcsine, slang_asm_float_copy}, - {"float_arctan", slang_asm_float_arctan, slang_asm_float_copy}, - {"float_power", slang_asm_float_power, slang_asm_float_copy}, - {"float_exp", slang_asm_float_exp, slang_asm_float_copy}, - {"float_exp2", slang_asm_float_exp2, slang_asm_float_copy}, - {"float_rsq", slang_asm_float_rsq, slang_asm_float_copy}, - {"float_rcp", slang_asm_float_rcp, slang_asm_float_copy}, - {"float_log2", slang_asm_float_log2, slang_asm_float_copy}, - {"float_ceil", slang_asm_float_ceil, slang_asm_float_copy}, - {"float_noise1", slang_asm_float_noise1, slang_asm_float_copy}, - {"float_noise2", slang_asm_float_noise2, slang_asm_float_copy}, - {"float_noise3", slang_asm_float_noise3, slang_asm_float_copy}, - {"float_noise4", slang_asm_float_noise4, slang_asm_float_copy}, - {"int_to_float", slang_asm_int_to_float, slang_asm_float_copy}, - {"vec4_tex1d", slang_asm_vec4_tex1d, slang_asm_none}, - {"vec4_texb1d", slang_asm_vec4_tex1d, slang_asm_none}, - {"vec4_texp1d", slang_asm_vec4_tex1d, slang_asm_none}, - {"vec4_tex2d", slang_asm_vec4_tex2d, slang_asm_none}, - {"vec4_texb2d", slang_asm_vec4_tex2d, slang_asm_none}, - {"vec4_texp2d", slang_asm_vec4_tex2d, slang_asm_none}, - {"vec4_tex3d", slang_asm_vec4_tex3d, slang_asm_none}, - {"vec4_texb3d", slang_asm_vec4_tex3d, slang_asm_none}, - {"vec4_texp3d", slang_asm_vec4_tex3d, slang_asm_none}, - {"vec4_texcube", slang_asm_vec4_texcube, slang_asm_none}, - {"vec4_shad1d", slang_asm_vec4_shad1d, slang_asm_none}, - {"vec4_shad2d", slang_asm_vec4_shad2d, slang_asm_none}, - {"vec4_ddx", 0, slang_asm_none}, - {"vec4_ddy", 0, slang_asm_none}, - /* GL_MESA_shader_debug */ - {"float_print", slang_asm_float_deref, slang_asm_float_print}, - {"int_print", slang_asm_int_deref, slang_asm_int_print}, - {"bool_print", slang_asm_bool_deref, slang_asm_bool_print}, - /* vec4 */ - {"float_to_vec4", slang_asm_float_to_vec4, slang_asm_none}, - {"vec4_add", slang_asm_vec4_add, slang_asm_float_copy}, - {"vec4_subtract", slang_asm_vec4_subtract, slang_asm_float_copy}, - {"vec4_multiply", slang_asm_vec4_multiply, slang_asm_float_copy}, - {"vec4_min", slang_asm_vec4_min, slang_asm_float_copy}, - {"vec4_max", slang_asm_vec4_max, slang_asm_float_copy}, - {"vec4_seq", slang_asm_vec4_seq, slang_asm_float_copy}, - {"vec4_sne", slang_asm_vec4_sne, slang_asm_float_copy}, - {"vec4_sge", slang_asm_vec4_sge, slang_asm_float_copy}, - {"vec4_sgt", slang_asm_vec4_sgt, slang_asm_float_copy}, - {"vec4_floor", slang_asm_vec4_floor, slang_asm_float_copy}, - {"vec4_frac", slang_asm_vec4_frac, slang_asm_float_copy}, - {"vec4_abs", slang_asm_vec4_abs, slang_asm_float_copy}, - - {"vec4_divide", slang_asm_vec4_divide, slang_asm_none}, - {"vec4_negate", slang_asm_vec4_negate, slang_asm_none}, - {"vec4_dot", slang_asm_vec4_dot, slang_asm_float_copy}, - {"vec3_dot", slang_asm_vec3_dot, slang_asm_float_copy}, - {"vec3_cross", slang_asm_vec3_cross, slang_asm_float_copy}, - {NULL, slang_asm_none, slang_asm_none} -}; - -static GLboolean -call_asm_instruction(slang_assemble_ctx * A, slang_atom a_name) -{ - const char *id; - GLuint i; - - id = slang_atom_pool_id(A->atoms, a_name); - - for (i = 0; inst[i].name != NULL; i++) - if (slang_string_compare(id, inst[i].name) == 0) - break; - if (inst[i].name == NULL) - return GL_FALSE; - - if (!PLAB2(A->file, inst[i].code1, 4, 0)) - return GL_FALSE; - if (inst[i].code2 != slang_asm_none) - if (!PLAB2(A->file, inst[i].code2, 4, 0)) - return GL_FALSE; - - /* clean-up the stack from the remaining dst address */ - if (!PLAB(A->file, slang_asm_local_free, 4)) - return GL_FALSE; - - return GL_TRUE; -} - -static GLboolean -equality_aggregate(slang_assemble_ctx * A, - const slang_storage_aggregate * agg, GLuint * index, - GLuint size, GLuint z_label) -{ - GLuint i; - - for (i = 0; i < agg->count; i++) { - const slang_storage_array *arr = &agg->arrays[i]; - GLuint j; - - for (j = 0; j < arr->length; j++) { - if (arr->type == slang_stor_aggregate) { - if (!equality_aggregate(A, arr->aggregate, index, size, z_label)) - return GL_FALSE; - } - else { - if (!PLAB2(A->file, slang_asm_float_equal_int, - size + *index, *index)) - return GL_FALSE; - - *index += _slang_sizeof_type(arr->type); - if (!PLAB(A->file, slang_asm_jump_if_zero, z_label)) - return GL_FALSE; - } - } - } - - return GL_TRUE; -} - -static GLboolean -equality(slang_assemble_ctx * A, slang_operation * op, GLboolean equal) -{ - slang_assembly_typeinfo ti; - GLboolean result = GL_FALSE; - slang_storage_aggregate agg; - GLuint index, size; - GLuint skip_jump, true_label, true_jump, false_label, false_jump; - - /* get type of operation */ - if (!slang_assembly_typeinfo_construct(&ti)) - RETURN_OUT_OF_MEMORY(); - if (!_slang_typeof_operation(A, op, &ti)) - goto end1; - - /* convert it to an aggregate */ - if (!slang_storage_aggregate_construct(&agg)) - goto end1; - if (!_slang_aggregate_variable(&agg, &ti.spec, 0, A->space.funcs, - A->space.structs, A->space.vars, - A->file, A->atoms)) - goto end; - - /* compute the size of the agregate - there are two such aggregates - * on the stack - */ - size = _slang_sizeof_aggregate(&agg); - - /* jump to the actual data-comparison code */ - skip_jump = A->file->count; - if (!PUSH(A->file, slang_asm_jump)) - goto end; - - /* pop off the stack the compared data and push 1 */ - true_label = A->file->count; - if (!PLAB(A->file, slang_asm_local_free, size * 2)) - goto end; - if (!PLIT(A->file, slang_asm_bool_push, (GLfloat) 1)) - goto end; - true_jump = A->file->count; - if (!PUSH(A->file, slang_asm_jump)) - goto end; - - false_label = A->file->count; - if (!PLAB(A->file, slang_asm_local_free, size * 2)) - goto end; - if (!PLIT(A->file, slang_asm_bool_push, (GLfloat) 0)) - goto end; - false_jump = A->file->count; - if (!PUSH(A->file, slang_asm_jump)) - goto end; - - A->file->code[skip_jump].param[0] = A->file->count; - - /* compare the data on stack, it will eventually jump either to - * true or false label - */ - index = 0; - if (!equality_aggregate(A, &agg, &index, size, - equal ? false_label : true_label)) - goto end; - if (!PLAB(A->file, slang_asm_jump, equal ? true_label : false_label)) - goto end; - - A->file->code[true_jump].param[0] = A->file->count; - A->file->code[false_jump].param[0] = A->file->count; - - result = GL_TRUE; - end: - slang_storage_aggregate_destruct(&agg); - end1: - slang_assembly_typeinfo_destruct(&ti); - return result; -} - -static GLboolean -handle_subscript(slang_assemble_ctx * A, slang_assembly_typeinfo * tie, - slang_assembly_typeinfo * tia, slang_operation * op, - slang_ref_type ref) -{ - GLuint asize = 0, esize = 0; - - /* get type info of the master expression (matrix, vector or an array */ - if (!_slang_typeof_operation(A, &op->children[0], tia)) - return GL_FALSE; - if (!sizeof_variable(A, &tia->spec, slang_qual_none, - tia->array_len, &asize)) - return GL_FALSE; - - /* get type info of the result (matrix column, vector row or array element) */ - if (!_slang_typeof_operation(A, op, tie)) - return GL_FALSE; - if (!sizeof_variable(A, &tie->spec, slang_qual_none, 0, &esize)) - return GL_FALSE; - - /* assemble the master expression */ - if (!_slang_assemble_operation(A, &op->children[0], ref)) - return GL_FALSE; - - /* when indexing an l-value swizzle, push the swizzle_tmp */ - if (ref == slang_ref_force && tia->is_swizzled) - if (!PLAB2(A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16)) - return GL_FALSE; - - /* assemble the subscript expression */ - if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid)) - return GL_FALSE; - - if (ref == slang_ref_force && tia->is_swizzled) { - GLuint i; - - /* copy the swizzle indexes to the swizzle_tmp */ - for (i = 0; i < tia->swz.num_components; i++) { - if (!PLAB2(A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16)) - return GL_FALSE; - if (!PLAB(A->file, slang_asm_addr_push, i * 4)) - return GL_FALSE; - if (!PUSH(A->file, slang_asm_addr_add)) - return GL_FALSE; - if (!PLAB(A->file, slang_asm_addr_push, tia->swz.swizzle[i])) - return GL_FALSE; - if (!PUSH(A->file, slang_asm_addr_copy)) - return GL_FALSE; - if (!PLAB(A->file, slang_asm_local_free, 4)) - return GL_FALSE; - } - - /* offset the pushed swizzle_tmp address and dereference it */ - if (!PUSH(A->file, slang_asm_int_to_addr)) - return GL_FALSE; - if (!PLAB(A->file, slang_asm_addr_push, 4)) - return GL_FALSE; - if (!PUSH(A->file, slang_asm_addr_multiply)) - return GL_FALSE; - if (!PUSH(A->file, slang_asm_addr_add)) - return GL_FALSE; - if (!PUSH(A->file, slang_asm_addr_deref)) - return GL_FALSE; - } - else { - /* convert the integer subscript to a relative address */ - if (!PUSH(A->file, slang_asm_int_to_addr)) - return GL_FALSE; - } - - if (!PLAB(A->file, slang_asm_addr_push, esize)) - return GL_FALSE; - if (!PUSH(A->file, slang_asm_addr_multiply)) - return GL_FALSE; - - if (ref == slang_ref_force) { - /* offset the base address with the relative address */ - if (!PUSH(A->file, slang_asm_addr_add)) - return GL_FALSE; - } - else { - GLuint i; - - /* move the selected element to the beginning of the master expression */ - for (i = 0; i < esize; i += 4) - if (!PLAB2(A->file, slang_asm_float_move, - asize - esize + i + 4, i + 4)) - return GL_FALSE; - if (!PLAB(A->file, slang_asm_local_free, 4)) - return GL_FALSE; - - /* free the rest of the master expression */ - if (!PLAB(A->file, slang_asm_local_free, asize - esize)) - return GL_FALSE; - } - - return GL_TRUE; -} - -static GLboolean -handle_field(slang_assemble_ctx * A, slang_assembly_typeinfo * tia, - slang_assembly_typeinfo * tib, slang_operation * op, - slang_ref_type ref) -{ - /* get type info of the result (field or swizzle) */ - if (!_slang_typeof_operation(A, op, tia)) - RETURN_NIL(); - - /* get type info of the master expression being accessed (struct or vector) */ - if (!_slang_typeof_operation(A, &op->children[0], tib)) - RETURN_NIL(); - - /* if swizzling a vector in-place, the swizzle temporary is needed */ - if (ref == slang_ref_forbid && tia->is_swizzled) - if (!PLAB2(A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16)) - RETURN_OUT_OF_MEMORY(); - - /* assemble the master expression */ - if (!_slang_assemble_operation(A, &op->children[0], ref)) - RETURN_NIL(); - - /* assemble the field expression */ - if (tia->is_swizzled) { - if (ref == slang_ref_force) { -#if 0 - if (tia->swz.num_components == 1) { - /* simple case - adjust the vector's address to point to - * the selected component - */ - if (!PLAB(file, slang_asm_addr_push, tia->swz.swizzle[0] * 4)) - RETURN_OUT_OF_MEMORY(); - if (!PUSH(file, slang_asm_addr_add)) - RETURN_OUT_OF_MEMORY(); - } - else -#endif - { - /* two or more vector components are being referenced - - * the so-called write mask must be passed to the upper - * operations and applied when assigning value to this swizzle - */ - A->swz = tia->swz; - } - } - else { - /* swizzle the vector in-place using the swizzle temporary */ - if (!_slang_assemble_constructor_from_swizzle(A, &tia->swz, - &tia->spec, &tib->spec)) - RETURN_NIL(); - } - } - else { - GLuint i, struct_size = 0, field_offset = 0, field_size = 0; - - /* - * Calculate struct size, field offset and field size. - */ - for (i = 0; i < tib->spec._struct->fields->num_variables; i++) { - slang_variable *field; - slang_storage_aggregate agg; - GLuint size; - - field = tib->spec._struct->fields->variables[i]; - if (!slang_storage_aggregate_construct(&agg)) - RETURN_NIL(); - if (!_slang_aggregate_variable(&agg, &field->type.specifier, - field->array_len, A->space.funcs, - A->space.structs, A->space.vars, - A->file, A->atoms)) { - slang_storage_aggregate_destruct(&agg); - RETURN_NIL(); - } - size = _slang_sizeof_aggregate(&agg); - slang_storage_aggregate_destruct(&agg); - - if (op->a_id == field->a_name) { - field_size = size; - field_offset = struct_size; - } - struct_size += size; - } - - if (ref == slang_ref_force) { - GLboolean shift; - - /* - * OPTIMIZATION: If selecting first field, no address shifting - * is needed. - */ - shift = (field_offset != 0); - - if (shift) { - if (!PLAB(A->file, slang_asm_addr_push, field_offset)) - RETURN_OUT_OF_MEMORY(); - if (!PUSH(A->file, slang_asm_addr_add)) - RETURN_OUT_OF_MEMORY(); - } - } - else { - GLboolean relocate, shrink; - GLuint free_b = 0; - - /* - * OPTIMIZATION: If selecting last field, no relocation is needed. - */ - relocate = (field_offset != (struct_size - field_size)); - - /* - * OPTIMIZATION: If field and struct sizes are equal, no partial - * free is needed. - */ - shrink = (field_size != struct_size); - - if (relocate) { - GLuint i; - - /* - * Move the selected element to the end of the master expression. - * Do it in reverse order to avoid overwriting itself. - */ - if (!PLAB(A->file, slang_asm_addr_push, field_offset)) - RETURN_OUT_OF_MEMORY(); - for (i = field_size; i > 0; i -= 4) - if (!PLAB2(A->file, slang_asm_float_move, - struct_size - field_size + i, i)) - RETURN_OUT_OF_MEMORY(); - free_b += 4; - } - - if (shrink) { - /* free the rest of the master expression */ - free_b += struct_size - field_size; - } - - if (free_b) { - if (!PLAB(A->file, slang_asm_local_free, free_b)) - RETURN_OUT_OF_MEMORY(); - } - } - } - - return GL_TRUE; -} - -GLboolean -_slang_assemble_operation(slang_assemble_ctx * A, slang_operation * op, - slang_ref_type ref) -{ - /* set default results */ - A->ref = /*(ref == slang_ref_freelance) ? slang_ref_force : */ ref; - A->swz.num_components = 0; - - switch (op->type) { - case slang_oper_block_no_new_scope: - case slang_oper_block_new_scope: - { - GLuint i; - - for (i = 0; i < op->num_children; i++) { - if (!_slang_assemble_operation(A, &op->children[i], - slang_ref_forbid /*slang_ref_freelance */ )) - RETURN_NIL(); - if (!_slang_cleanup_stack(A, &op->children[i])) - RETURN_NIL(); - } - } - break; - case slang_oper_variable_decl: - { - GLuint i; - slang_operation assign; - GLboolean result; - - /* Construct assignment expression placeholder. */ - if (!slang_operation_construct(&assign)) - RETURN_NIL(); - assign.type = slang_oper_assign; - assign.children = slang_operation_new(2); - if (assign.children == NULL) { - slang_operation_destruct(&assign); - RETURN_NIL(); - } - for (assign.num_children = 0; assign.num_children < 2; - assign.num_children++) - if (!slang_operation_construct(&assign.children - [assign.num_children])) { - slang_operation_destruct(&assign); - RETURN_OUT_OF_MEMORY(); - } - - result = GL_TRUE; - for (i = 0; i < op->num_children; i++) { - slang_variable *var; - - var = - _slang_locate_variable(op->children[i].locals, - op->children[i].a_id, GL_TRUE); - if (var == NULL) { - result = GL_FALSE; - break; - } - if (var->initializer == NULL) - continue; - - if (!slang_operation_copy(&assign.children[0], &op->children[i]) - || !slang_operation_copy(&assign.children[1], - var->initializer) - || !_slang_assemble_assign(A, &assign, "=", slang_ref_forbid) - || !_slang_cleanup_stack(A, &assign)) { - result = GL_FALSE; - break; - } - } - slang_operation_destruct(&assign); - if (!result) - RETURN_NIL(); - } - break; - case slang_oper_asm: - { - GLuint i; - if (!_slang_assemble_operation(A, &op->children[0], slang_ref_force)) - RETURN_NIL(); - for (i = 1; i < op->num_children; i++) - if (!_slang_assemble_operation(A, &op->children[i], - slang_ref_forbid)) - RETURN_NIL(); - if (!call_asm_instruction(A, op->a_id)) - RETURN_ERROR2("Unknown __asm call", (char*) op->a_id, 0); - } - break; - case slang_oper_break: - if (!PLAB(A->file, slang_asm_jump, A->flow.loop_end)) - RETURN_OUT_OF_MEMORY(); - break; - case slang_oper_continue: - if (!PLAB(A->file, slang_asm_jump, A->flow.loop_start)) - RETURN_OUT_OF_MEMORY(); - break; - case slang_oper_discard: - if (!PUSH(A->file, slang_asm_discard)) - RETURN_OUT_OF_MEMORY(); - if (!PUSH(A->file, slang_asm_exit)) - RETURN_OUT_OF_MEMORY(); - break; - case slang_oper_return: - if (A->local.ret_size != 0) { - /* push the result's address */ - if (!PLAB2(A->file, slang_asm_local_addr, 0, A->local.ret_size)) - RETURN_OUT_OF_MEMORY(); - if (!_slang_assemble_operation(A, &op->children[0], slang_ref_forbid)) - RETURN_NIL(); - - A->swz.num_components = 0; - /* assign the operation to the function result (it was reserved on the stack) */ - if (!_slang_assemble_assignment(A, op->children)) - RETURN_NIL(); - - if (!PLAB(A->file, slang_asm_local_free, 4)) - RETURN_OUT_OF_MEMORY(); - } - if (!PLAB(A->file, slang_asm_jump, A->flow.function_end)) - RETURN_OUT_OF_MEMORY(); - break; - case slang_oper_expression: - if (ref == slang_ref_force) - RETURN_NIL(); - if (!_slang_assemble_operation(A, &op->children[0], ref)) - RETURN_NIL(); - break; - case slang_oper_if: - if (!_slang_assemble_if(A, op)) - RETURN_NIL(); - break; - case slang_oper_while: - if (!_slang_assemble_while(A, op)) - RETURN_NIL(); - break; - case slang_oper_do: - if (!_slang_assemble_do(A, op)) - RETURN_NIL(); - break; - case slang_oper_for: - if (!_slang_assemble_for(A, op)) - RETURN_NIL(); - break; - case slang_oper_void: - break; - case slang_oper_literal_bool: - if (ref == slang_ref_force) - RETURN_NIL(); - if (!PLIT(A->file, slang_asm_bool_push, op->literal[0])) - RETURN_OUT_OF_MEMORY(); - A->ref = slang_ref_forbid; - break; - case slang_oper_literal_int: - if (ref == slang_ref_force) - RETURN_NIL(); - if (!PLIT(A->file, slang_asm_int_push, op->literal[0])) - RETURN_OUT_OF_MEMORY(); - A->ref = slang_ref_forbid; - break; - case slang_oper_literal_float: -#if 0 - if (ref == slang_ref_force) - RETURN_NIL(); -#endif - if (!PLIT(A->file, slang_asm_float_push, op->literal[0])) - RETURN_OUT_OF_MEMORY(); - A->ref = slang_ref_forbid; - break; - case slang_oper_identifier: - { - slang_variable *var; - GLuint size; - - /* find the variable and calculate its size */ - var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE); - if (var == NULL) - RETURN_ERROR2("undefined variable", (char *) op->a_id, 0); - size = 0; - if (!sizeof_variable(A, &var->type.specifier, slang_qual_none, - var->array_len, &size)) - RETURN_OUT_OF_MEMORY(); - - /* prepare stack for dereferencing */ - if (ref == slang_ref_forbid) - if (!PLAB2(A->file, slang_asm_local_addr, A->local.addr_tmp, 4)) - RETURN_OUT_OF_MEMORY(); - - /* push the variable's address */ - if (var->global) { - if (!PLAB(A->file, slang_asm_global_addr, var->address)) - RETURN_OUT_OF_MEMORY(); - } - else { - if (!PLAB2(A->file, slang_asm_local_addr, var->address, size)) - RETURN_OUT_OF_MEMORY(); - } - - /* perform the dereference */ - if (ref == slang_ref_forbid) { - if (!PUSH(A->file, slang_asm_addr_copy)) - RETURN_OUT_OF_MEMORY(); - if (!PLAB(A->file, slang_asm_local_free, 4)) - RETURN_OUT_OF_MEMORY(); - if (!_slang_dereference(A, op)) - RETURN_NIL(); - } - } - break; - case slang_oper_sequence: - if (ref == slang_ref_force) - RETURN_NIL(); - if (!_slang_assemble_operation(A, &op->children[0], - slang_ref_forbid /*slang_ref_freelance */ )) - RETURN_NIL(); - if (!_slang_cleanup_stack(A, &op->children[0])) - RETURN_NIL(); - if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - case slang_oper_assign: - if (!_slang_assemble_assign(A, op, "=", ref)) - RETURN_NIL(); - break; - case slang_oper_addassign: - if (!_slang_assemble_assign(A, op, "+=", ref)) - RETURN_NIL(); - A->ref = ref; - break; - case slang_oper_subassign: - if (!_slang_assemble_assign(A, op, "-=", ref)) - RETURN_NIL(); - A->ref = ref; - break; - case slang_oper_mulassign: - if (!_slang_assemble_assign(A, op, "*=", ref)) - RETURN_NIL(); - A->ref = ref; - break; - /*case slang_oper_modassign: */ - /*case slang_oper_lshassign: */ - /*case slang_oper_rshassign: */ - /*case slang_oper_orassign: */ - /*case slang_oper_xorassign: */ - /*case slang_oper_andassign: */ - case slang_oper_divassign: - if (!_slang_assemble_assign(A, op, "/=", ref)) - RETURN_NIL(); - A->ref = ref; - break; - case slang_oper_select: - if (!_slang_assemble_select(A, op)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - case slang_oper_logicalor: - if (!_slang_assemble_logicalor(A, op)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - case slang_oper_logicaland: - if (!_slang_assemble_logicaland(A, op)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - case slang_oper_logicalxor: - if (!_slang_assemble_function_call_name(A, "^^", op->children, 2, GL_FALSE)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - /*case slang_oper_bitor: */ - /*case slang_oper_bitxor: */ - /*case slang_oper_bitand: */ - case slang_oper_less: - if (!_slang_assemble_function_call_name(A, "<", op->children, 2, GL_FALSE)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - case slang_oper_greater: - if (!_slang_assemble_function_call_name(A, ">", op->children, 2, GL_FALSE)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - case slang_oper_lessequal: - if (!_slang_assemble_function_call_name(A, "<=", op->children, 2, GL_FALSE)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - case slang_oper_greaterequal: - if (!_slang_assemble_function_call_name(A, ">=", op->children, 2, GL_FALSE)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - /*case slang_oper_lshift: */ - /*case slang_oper_rshift: */ - case slang_oper_add: - if (!_slang_assemble_function_call_name(A, "+", op->children, 2, GL_FALSE)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - case slang_oper_subtract: - if (!_slang_assemble_function_call_name(A, "-", op->children, 2, GL_FALSE)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - case slang_oper_multiply: - if (!_slang_assemble_function_call_name(A, "*", op->children, 2, GL_FALSE)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - /*case slang_oper_modulus: */ - case slang_oper_divide: - if (!_slang_assemble_function_call_name(A, "/", op->children, 2, GL_FALSE)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - case slang_oper_equal: - if (!_slang_assemble_operation(A, &op->children[0], slang_ref_forbid)) - RETURN_NIL(); - if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid)) - RETURN_NIL(); - if (!equality(A, op->children, GL_TRUE)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - case slang_oper_notequal: - if (!_slang_assemble_operation(A, &op->children[0], slang_ref_forbid)) - RETURN_NIL(); - if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid)) - RETURN_NIL(); - if (!equality(A, op->children, GL_FALSE)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - case slang_oper_preincrement: - if (!_slang_assemble_assign(A, op, "++", ref)) - RETURN_NIL(); - A->ref = ref; - break; - case slang_oper_predecrement: - if (!_slang_assemble_assign(A, op, "--", ref)) - RETURN_NIL(); - A->ref = ref; - break; - case slang_oper_plus: - if (!_slang_dereference(A, op)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - case slang_oper_minus: - if (!_slang_assemble_function_call_name(A, "-", op->children, 1, GL_FALSE)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - /*case slang_oper_complement: */ - case slang_oper_not: - if (!_slang_assemble_function_call_name(A, "!", op->children, 1, GL_FALSE)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - case slang_oper_subscript: - { - slang_assembly_typeinfo ti_arr, ti_elem; - - if (!slang_assembly_typeinfo_construct(&ti_arr)) - RETURN_OUT_OF_MEMORY(); - if (!slang_assembly_typeinfo_construct(&ti_elem)) { - slang_assembly_typeinfo_destruct(&ti_arr); - RETURN_OUT_OF_MEMORY(); - } - if (!handle_subscript(A, &ti_elem, &ti_arr, op, ref)) { - slang_assembly_typeinfo_destruct(&ti_arr); - slang_assembly_typeinfo_destruct(&ti_elem); - RETURN_NIL(); - } - slang_assembly_typeinfo_destruct(&ti_arr); - slang_assembly_typeinfo_destruct(&ti_elem); - } - break; - case slang_oper_call: - { - slang_function *fun - = _slang_locate_function(A->space.funcs, op->a_id, op->children, - op->num_children, &A->space, A->atoms); - if (fun == NULL) { - if (!_slang_assemble_constructor(A, op)) - RETURN_OUT_OF_MEMORY(); - } - else { - if (!_slang_assemble_function_call(A, fun, op->children, - op->num_children, GL_FALSE)) - RETURN_NIL(); - } - A->ref = slang_ref_forbid; - } - break; - case slang_oper_field: - { - slang_assembly_typeinfo ti_after, ti_before; - - if (!slang_assembly_typeinfo_construct(&ti_after)) - RETURN_OUT_OF_MEMORY(); - if (!slang_assembly_typeinfo_construct(&ti_before)) { - slang_assembly_typeinfo_destruct(&ti_after); - RETURN_OUT_OF_MEMORY(); - } - if (!handle_field(A, &ti_after, &ti_before, op, ref)) { - slang_assembly_typeinfo_destruct(&ti_after); - slang_assembly_typeinfo_destruct(&ti_before); - RETURN_NIL(); - } - slang_assembly_typeinfo_destruct(&ti_after); - slang_assembly_typeinfo_destruct(&ti_before); - } - break; - case slang_oper_postincrement: - if (!assemble_function_call_name_dummyint(A, "++", op->children)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - case slang_oper_postdecrement: - if (!assemble_function_call_name_dummyint(A, "--", op->children)) - RETURN_NIL(); - A->ref = slang_ref_forbid; - break; - default: - RETURN_NIL(); - } - - return GL_TRUE; -} |