From 02168254a8bc269511093e20411c863979b2afac Mon Sep 17 00:00:00 2001 From: Michal Krol Date: Thu, 19 May 2005 11:50:53 +0000 Subject: [PATCH] intermediate code generator (not finished); generic back-end interpreter (interprets directly intermediate code) --- src/mesa/shader/slang/slang_assemble.c | 1385 +++++++++++++++++ src/mesa/shader/slang/slang_assemble.h | 145 ++ .../shader/slang/slang_assemble_conditional.c | 485 ++++++ .../shader/slang/slang_assemble_conditional.h | 66 + .../shader/slang/slang_assemble_constructor.c | 333 ++++ .../shader/slang/slang_assemble_constructor.h | 80 + .../shader/slang/slang_assemble_typeinfo.c | 428 +++++ .../shader/slang/slang_assemble_typeinfo.h | 67 + src/mesa/shader/slang/slang_compile.c | 338 +++- src/mesa/shader/slang/slang_compile.h | 35 +- src/mesa/shader/slang/slang_execute.c | 347 +++++ src/mesa/shader/slang/slang_execute.h | 57 + src/mesa/shader/slang/slang_storage.c | 255 +++ src/mesa/shader/slang/slang_storage.h | 109 ++ src/mesa/sources | 6 + 15 files changed, 4059 insertions(+), 77 deletions(-) create mode 100644 src/mesa/shader/slang/slang_assemble.c create mode 100644 src/mesa/shader/slang/slang_assemble.h create mode 100644 src/mesa/shader/slang/slang_assemble_conditional.c create mode 100644 src/mesa/shader/slang/slang_assemble_conditional.h create mode 100644 src/mesa/shader/slang/slang_assemble_constructor.c create mode 100644 src/mesa/shader/slang/slang_assemble_constructor.h create mode 100644 src/mesa/shader/slang/slang_assemble_typeinfo.c create mode 100644 src/mesa/shader/slang/slang_assemble_typeinfo.h create mode 100644 src/mesa/shader/slang/slang_execute.c create mode 100644 src/mesa/shader/slang/slang_execute.h create mode 100644 src/mesa/shader/slang/slang_storage.c create mode 100644 src/mesa/shader/slang/slang_storage.h diff --git a/src/mesa/shader/slang/slang_assemble.c b/src/mesa/shader/slang/slang_assemble.c new file mode 100644 index 00000000000..03672b2fca3 --- /dev/null +++ b/src/mesa/shader/slang/slang_assemble.c @@ -0,0 +1,1385 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 2005 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_utility.h" +#include "slang_assemble.h" +#include "slang_compile.h" +#include "slang_storage.h" +#include "slang_assemble_constructor.h" +#include "slang_assemble_typeinfo.h" +#include "slang_assemble_conditional.h" + +/* slang_assembly */ + +static void slang_assembly_construct (slang_assembly *asm) +{ + asm->type = slang_asm_none; +} + +static void slang_assembly_destruct (slang_assembly *asm) +{ +} + +/* slang_assembly_file */ + +void slang_assembly_file_construct (slang_assembly_file *file) +{ + file->code = NULL; + file->count = 0; +} + +void slang_assembly_file_destruct (slang_assembly_file *file) +{ + unsigned int i; + + for (i = 0; i < file->count; i++) + slang_assembly_destruct (file->code + i); + slang_alloc_free (file->code); +} + +static int slang_assembly_file_push_new (slang_assembly_file *file) +{ + file->code = (slang_assembly *) slang_alloc_realloc (file->code, file->count * sizeof ( + slang_assembly), (file->count + 1) * sizeof (slang_assembly)); + if (file->code != NULL) + { + slang_assembly_construct (file->code + file->count); + file->count++; + return 1; + } + return 0; +} + +static int slang_assembly_file_push_general (slang_assembly_file *file, slang_assembly_type type, + GLfloat literal, GLuint label, GLuint size) +{ + slang_assembly *asm; + if (!slang_assembly_file_push_new (file)) + return 0; + asm = file->code + file->count - 1; + asm->type = type; + asm->literal = literal; + asm->param[0] = label; + asm->param[1] = size; + return 1; +} + +int slang_assembly_file_push (slang_assembly_file *file, slang_assembly_type type) +{ + return slang_assembly_file_push_general (file, type, (GLfloat) 0, 0, 0); +} + +int slang_assembly_file_push_label (slang_assembly_file *file, slang_assembly_type type, + GLuint label) +{ + return slang_assembly_file_push_general (file, type, (GLfloat) 0, label, 0); +} + +int slang_assembly_file_push_label2 (slang_assembly_file *file, slang_assembly_type type, + GLuint label1, GLuint label2) +{ + return slang_assembly_file_push_general (file, type, (GLfloat) 0, label1, label2); +} + +int slang_assembly_file_push_literal (slang_assembly_file *file, slang_assembly_type type, + GLfloat literal) +{ + return slang_assembly_file_push_general (file, type, literal, 0, 0); +} + +/* utility functions */ + +static int sizeof_variable (slang_type_specifier *spec, slang_operation *array_size, + slang_assembly_name_space *space, unsigned int *size) +{ + slang_storage_aggregate agg; + + slang_storage_aggregate_construct (&agg); + if (!_slang_aggregate_variable (&agg, spec, array_size, space->funcs, space->structs)) + { + slang_storage_aggregate_destruct (&agg); + return 0; + } + *size += _slang_sizeof_aggregate (&agg); + slang_storage_aggregate_destruct (&agg); + return 1; +} + +static int sizeof_variable2 (slang_variable *var, slang_assembly_name_space *space, + unsigned int *size) +{ + var->address = *size; + return sizeof_variable (&var->type.specifier, var->array_size, space, size); +} + +static int sizeof_variables (slang_variable_scope *vars, unsigned int start, unsigned int stop, + slang_assembly_name_space *space, unsigned int *size) +{ + unsigned int i; + + for (i = start; i < stop; i++) + if (!sizeof_variable2 (vars->variables + i, space, size)) + return 0; + return 1; +} + +static int collect_locals (slang_operation *op, slang_assembly_name_space *space, + unsigned int *size) +{ + unsigned int i; + + if (!sizeof_variables (op->locals, 0, op->locals->num_variables, space, size)) + return 0; + for (i = 0; i < op->num_children; i++) + if (!collect_locals (op->children + i, space, size)) + return 0; + return 1; +} + +/* _slang_locate_function() */ + +slang_function *_slang_locate_function (const char *name, slang_operation *params, + unsigned int num_params, slang_assembly_name_space *space) +{ + unsigned int i; + + for (i = 0; i < space->funcs->num_functions; i++) + { + unsigned int j; + slang_function *f = space->funcs->functions + i; + + if (slang_string_compare (name, f->header.name) != 0) + continue; + if (f->param_count != num_params) + continue; + for (j = 0; j < num_params; j++) + { + slang_assembly_typeinfo ti; + slang_assembly_typeinfo_construct (&ti); + if (!_slang_typeof_operation (params + j, space, &ti)) + { + slang_assembly_typeinfo_destruct (&ti); + return 0; + } + if (!slang_type_specifier_equal (&ti.spec, &f->parameters->variables[j].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].type.qualifier != slang_qual_out && + f->parameters->variables[j].type.qualifier != slang_qual_inout) + break; + } + if (j == num_params) + return f; + } + if (space->funcs->outer_scope != NULL) + { + slang_assembly_name_space my_space = *space; + my_space.funcs = space->funcs->outer_scope; + return _slang_locate_function (name, params, num_params, &my_space); + } + return NULL; +} + +/* _slang_assemble_function() */ + +int _slang_assemble_function (slang_assembly_file *file, slang_function *fun, + slang_assembly_name_space *space) +{ + unsigned int param_size, local_size; + unsigned int skip, cleanup; + slang_assembly_flow_control flow; + slang_assembly_local_info info; + slang_assembly_stack_info stk; + + fun->address = file->count; + + if (fun->body == NULL) + { + /* TODO: jump to the actual function body */ + return 1; + } + + /* calculate return value and parameters size */ + param_size = 0; + if (fun->header.type.specifier.type != slang_spec_void) + if (!sizeof_variable (&fun->header.type.specifier, NULL, space, ¶m_size)) + return 0; + info.ret_size = param_size; + if (!sizeof_variables (fun->parameters, 0, fun->param_count, space, ¶m_size)) + return 0; + + /* calculate local variables size, take into account the four-byte return address and + temporaries for various tasks */ + info.addr_tmp = param_size + 4; + info.swizzle_tmp = param_size + 4 + 4; + local_size = param_size + 4 + 4 + 16; + if (!sizeof_variables (fun->parameters, fun->param_count, fun->parameters->num_variables, space, + &local_size)) + return 0; + if (!collect_locals (fun->body, space, &local_size)) + return 0; + + /* allocate local variable storage */ + if (!slang_assembly_file_push_label (file, slang_asm_local_alloc, local_size - param_size - 4)) + return 0; + + /* mark a new frame for function variable storage */ + if (!slang_assembly_file_push_label (file, slang_asm_enter, local_size)) + return 0; + + /* skip the cleanup jump */ + skip = file->count; + if (!slang_assembly_file_push_new (file)) + return 0; + file->code[skip].type = slang_asm_jump; + + /* all "return" statements will be directed here */ + flow.function_end = file->count; + cleanup = file->count; + if (!slang_assembly_file_push_new (file)) + return 0; + file->code[cleanup].type = slang_asm_jump; + + /* execute the function body */ + file->code[skip].param[0] = file->count; + if (!_slang_assemble_operation (file, fun->body, 0, &flow, space, &info, &stk)) + return 0; + + /* this is the end of the function - restore the old function frame */ + file->code[cleanup].param[0] = file->count; + if (!slang_assembly_file_push (file, slang_asm_leave)) + return 0; + + /* free local variable storage */ + if (!slang_assembly_file_push_label (file, slang_asm_local_free, local_size - param_size - 4)) + return 0; + + /* jump out of the function */ + if (!slang_assembly_file_push (file, slang_asm_return)) + return 0; + return 1; +} + +int _slang_cleanup_stack (slang_assembly_file *file, slang_operation *op, int ref, + slang_assembly_name_space *space) +{ + slang_assembly_typeinfo ti; + unsigned int size; + + slang_assembly_typeinfo_construct (&ti); + if (!_slang_typeof_operation (op, space, &ti)) + { + slang_assembly_typeinfo_destruct (&ti); + return 0; + } + if (ti.spec.type == slang_spec_void) + size = 0; + else if (ref) + size = 4; + else + { + size = 0; + if (!sizeof_variable (&ti.spec, NULL, space, &size)) + { + slang_assembly_typeinfo_destruct (&ti); + return 0; + } + } + slang_assembly_typeinfo_destruct (&ti); + if (size != 0) + { + if (!slang_assembly_file_push_label (file, slang_asm_local_free, size)) + return 0; + } + return 1; +} + +/* _slang_assemble_operation() */ + +/* XXX: general swizzle! */ +static int dereference_aggregate (slang_assembly_file *file, const slang_storage_aggregate *agg, + unsigned int index, unsigned int *size, slang_assembly_local_info *info) +{ + unsigned int i; + + for (i = agg->count; i > 0; i--) + { + const slang_storage_array *arr = agg->arrays + i - 1; + unsigned int j; + + for (j = arr->length; j > 0; j--) + { + if (arr->type == slang_stor_aggregate) + { + if (!dereference_aggregate (file, arr->aggregate, index, size, info)) + return 0; + } + else + { + *size -= 4; + if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, info->addr_tmp, + 4)) + return 0; + if (!slang_assembly_file_push (file, slang_asm_addr_deref)) + return 0; + if (!slang_assembly_file_push_label (file, slang_asm_addr_push, *size)) + return 0; + if (!slang_assembly_file_push (file, slang_asm_addr_add)) + return 0; + switch (arr->type) + { + case slang_stor_bool: + if (!slang_assembly_file_push (file, slang_asm_bool_deref)) + return 0; + break; + case slang_stor_int: + if (!slang_assembly_file_push (file, slang_asm_int_deref)) + return 0; + break; + case slang_stor_float: + if (!slang_assembly_file_push (file, slang_asm_float_deref)) + return 0; + break; + } + index += 4; + } + } + } + return 1; +} +/* XXX: general swizzle! */ +static int dereference (slang_assembly_file *file, slang_operation *op, + slang_assembly_name_space *space, slang_assembly_local_info *info) +{ + slang_assembly_typeinfo ti; + int result; + slang_storage_aggregate agg; + unsigned int size; + + slang_assembly_typeinfo_construct (&ti); + if (!_slang_typeof_operation (op, space, &ti)) + { + slang_assembly_typeinfo_destruct (&ti); + return 0; + } + + slang_storage_aggregate_construct (&agg); + if (!_slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs)) + { + slang_storage_aggregate_destruct (&agg); + slang_assembly_typeinfo_destruct (&ti); + return 0; + } + + size = _slang_sizeof_aggregate (&agg); + result = dereference_aggregate (file, &agg, 0, &size, info); + + slang_storage_aggregate_destruct (&agg); + slang_assembly_typeinfo_destruct (&ti); + return result; +} + +static int call_function (slang_assembly_file *file, slang_function *fun, slang_operation *params, + unsigned int param_count, int assignment, slang_assembly_name_space *space, + slang_assembly_local_info *info) +{ + unsigned int ret_size, i; + slang_assembly_stack_info stk; + + /* make room for the return value, if any */ + ret_size = 0; + if (!sizeof_variable (&fun->header.type.specifier, NULL, space, &ret_size)) + return 0; + if (ret_size > 0) + { + if (!slang_assembly_file_push_label (file, slang_asm_local_alloc, ret_size)) + return 0; + } + + /* push the actual parameters on the stack */ + for (i = 0; i < param_count; i++) + { + slang_assembly_flow_control flow; + + if (i == 0 && assignment) + { + if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, info->addr_tmp, 4)) + return 0; + /* TODO: optimize the "out" parameter case */ + /* TODO: inspect stk */ + if (!_slang_assemble_operation (file, params, 1, &flow, space, info, &stk)) + return 0; + if (!slang_assembly_file_push (file, slang_asm_addr_copy)) + return 0; + if (!slang_assembly_file_push (file, slang_asm_addr_deref)) + return 0; + if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, info->addr_tmp, 4)) + return 0; + if (!slang_assembly_file_push (file, slang_asm_addr_deref)) + return 0; + if (!dereference (file, params, space, info)) + return 0; + } + else + { + /* TODO: for "out" and "inout" parameters also push the address (first) */ + /* TODO: optimize the "out" parameter case */ + /* TODO: inspect stk */ + if (!_slang_assemble_operation (file, params + i, 0, &flow, space, info, &stk)) + return 0; + } + } + + /* call the function */ + if (!slang_assembly_file_push_label (file, slang_asm_call, fun->address)) + return 0; + + /* pop the parameters from the stack */ + for (i = param_count; i > 0; i--) + { + /* XXX: copy inout/out params back to the actual variables */ + if (!_slang_cleanup_stack (file, params + i - 1, 0, space)) + return 0; + } + + return 1; +} + +static int call_function_name (slang_assembly_file *file, const char *name, slang_operation *params, + unsigned int param_count, int assignment, slang_assembly_name_space *space, + slang_assembly_local_info *info) +{ + slang_function *fun = _slang_locate_function (name, params, param_count, space); + if (fun == NULL) + return 0; + return call_function (file, fun, params, param_count, assignment, space, info); +} + +static int call_function_name_dummyint (slang_assembly_file *file, const char *name, + slang_operation *params, slang_assembly_name_space *space, slang_assembly_local_info *info) +{ + slang_operation p2[2]; + int result; + + p2[0] = *params; + if (!slang_operation_construct_a (p2 + 1)) + return 0; + p2[1].type = slang_oper_literal_int; + result = call_function_name (file, name, p2, 2, 0, space, info); + slang_operation_destruct (p2 + 1); + return result; +} + +static int call_asm_instruction (slang_assembly_file *file, const char *name) +{ + const struct + { + const char *name; + slang_assembly_type code1, code2; + } inst[] = { + { "float_to_int", slang_asm_float_to_int, slang_asm_int_copy }, + { "int_to_float", slang_asm_int_to_float, slang_asm_float_copy }, + { "float_copy", slang_asm_float_copy, slang_asm_none }, + { "int_copy", slang_asm_int_copy, slang_asm_none }, + { "bool_copy", slang_asm_bool_copy, slang_asm_none }, + { "float_add", slang_asm_float_add, 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_less", slang_asm_float_less, slang_asm_bool_copy }, + { "float_equal", slang_asm_float_equal, slang_asm_bool_copy }, + { NULL, slang_asm_none, slang_asm_none } + }; + unsigned int i; + + for (i = 0; inst[i].name != NULL; i++) + if (slang_string_compare (name, inst[i].name) == 0) + break; + if (inst[i].name == NULL) + return 0; + + if (!slang_assembly_file_push_label2 (file, inst[i].code1, 4, 0)) + return 0; + if (inst[i].code2 != slang_asm_none) + if (!slang_assembly_file_push_label2 (file, inst[i].code2, 4, 0)) + return 0; + + /* clean-up the stack from the remaining dst address */ + if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4)) + return 0; + + return 1; +} +/* XXX: general swizzle! */ +static int assign_aggregate (slang_assembly_file *file, const slang_storage_aggregate *agg, + unsigned int *index, unsigned int size, slang_assembly_local_info *info) +{ + unsigned int i; + + for (i = 0; i < agg->count; i++) + { + const slang_storage_array *arr = agg->arrays + i; + unsigned int j; + + for (j = 0; j < arr->length; j++) + { + if (arr->type == slang_stor_aggregate) + { + if (!assign_aggregate (file, arr->aggregate, index, size, info)) + return 0; + } + else + { + switch (arr->type) + { + case slang_stor_bool: + if (!slang_assembly_file_push_label2 (file, slang_asm_bool_copy, + size - *index, *index)) + return 0; + break; + case slang_stor_int: + if (!slang_assembly_file_push_label2 (file, slang_asm_int_copy, + size - *index, *index)) + return 0; + break; + case slang_stor_float: + if (!slang_assembly_file_push_label2 (file, slang_asm_float_copy, + size - *index, *index)) + return 0; + break; + } + *index += 4; + } + } + } + return 1; +} +/* XXX: general swizzle! */ +static int assignment (slang_assembly_file *file, slang_operation *op, + slang_assembly_name_space *space, slang_assembly_local_info *info) +{ + slang_assembly_typeinfo ti; + int result; + slang_storage_aggregate agg; + unsigned int index, size; + + slang_assembly_typeinfo_construct (&ti); + if (!_slang_typeof_operation (op, space, &ti)) + { + slang_assembly_typeinfo_destruct (&ti); + return 0; + } + + slang_storage_aggregate_construct (&agg); + if (!_slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs)) + { + slang_storage_aggregate_destruct (&agg); + slang_assembly_typeinfo_destruct (&ti); + return 0; + } + + index = 0; + size = _slang_sizeof_aggregate (&agg); + result = assign_aggregate (file, &agg, &index, size, info); + + slang_storage_aggregate_destruct (&agg); + slang_assembly_typeinfo_destruct (&ti); + return result; +} +/* XXX: general swizzle! */ +static int equality_aggregate (slang_assembly_file *file, const slang_storage_aggregate *agg, + unsigned int *index, unsigned int size, slang_assembly_local_info *info, unsigned int z_label) +{ + unsigned int i; + + for (i = 0; i < agg->count; i++) + { + const slang_storage_array *arr = agg->arrays + i; + unsigned int j; + + for (j = 0; j < arr->length; j++) + { + if (arr->type == slang_stor_aggregate) + { + if (!equality_aggregate (file, arr->aggregate, index, size, info, z_label)) + return 0; + } + else + { + if (!slang_assembly_file_push_label2 (file, slang_asm_float_equal, size + *index, + *index)) + return 0; + *index += 4; + if (!slang_assembly_file_push_label (file, slang_asm_jump_if_zero, z_label)) + return 0; + } + } + } + return 1; +} +/* XXX: general swizzle! */ +static int equality (slang_assembly_file *file, slang_operation *op, + slang_assembly_name_space *space, slang_assembly_local_info *info, int equal) +{ + slang_assembly_typeinfo ti; + int result; + slang_storage_aggregate agg; + unsigned int index, size; + unsigned int skip_jump, true_label, true_jump, false_label, false_jump; + + /* get type of operation */ + slang_assembly_typeinfo_construct (&ti); + if (!_slang_typeof_operation (op, space, &ti)) + { + slang_assembly_typeinfo_destruct (&ti); + return 0; + } + + /* convert it to an aggregate */ + slang_storage_aggregate_construct (&agg); + if (!(result = _slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs))) + 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 = file->count; + if (!(result = slang_assembly_file_push (file, slang_asm_jump))) + goto end; + + /* pop off the stack the compared data and push 1 */ + true_label = file->count; + if (!(result = slang_assembly_file_push_label (file, slang_asm_local_free, size * 2))) + goto end; + if (!(result = slang_assembly_file_push_literal (file, slang_asm_bool_push, 1.0f))) + goto end; + true_jump = file->count; + if (!(result = slang_assembly_file_push (file, slang_asm_jump))) + goto end; + + false_label = file->count; + if (!(result = slang_assembly_file_push_label (file, slang_asm_local_free, size * 2))) + goto end; + if (!(result = slang_assembly_file_push_literal (file, slang_asm_bool_push, 0.0f))) + goto end; + false_jump = file->count; + if (!(result = slang_assembly_file_push (file, slang_asm_jump))) + goto end; + + file->code[skip_jump].param[0] = file->count; + + /* compare the data on stack, it will eventually jump either to true or false label */ + index = 0; + if (!(result = equality_aggregate (file, &agg, &index, size, info, + equal ? false_label : true_label))) + goto end; + if (!(result = slang_assembly_file_push_label (file, slang_asm_jump, + equal ? true_label : false_label))) + goto end; + + file->code[true_jump].param[0] = file->count; + file->code[false_jump].param[0] = file->count; + + result = 1; +end: + slang_storage_aggregate_destruct (&agg); + slang_assembly_typeinfo_destruct (&ti); + return result; +} + +int _slang_assemble_operation (slang_assembly_file *file, slang_operation *op, int reference, + slang_assembly_flow_control *flow, slang_assembly_name_space *space, + slang_assembly_local_info *info, slang_assembly_stack_info *stk) +{ + unsigned int asm; + + stk->swizzle_mask = 0; + + asm = file->count; + if (!slang_assembly_file_push_new (file)) + return 0; + + switch (op->type) + { + case slang_oper_block_no_new_scope: + case slang_oper_block_new_scope: + { + unsigned int i; + for (i = 0; i < op->num_children; i++) + { + slang_assembly_stack_info stk; + if (!_slang_assemble_operation (file, op->children + i, 0, flow, space, info, &stk)) + return 0; + /* TODO: pass-in stk to cleanup */ + if (!_slang_cleanup_stack (file, op->children + i, 0, space)) + return 0; + } + } + break; + case slang_oper_variable_decl: + { + unsigned int i; + + for (i = 0; i < op->num_children; i++) + { + /* TODO: perform initialization of op->children[i] */ + /* TODO: clean-up stack */ + } + } + break; + case slang_oper_asm: + { + unsigned int i; + for (i = 0; i < op->num_children; i++) + { + slang_assembly_stack_info stk; + if (!_slang_assemble_operation (file, op->children + i, i == 0, flow, space, info, + &stk)) + return 0; + /* TODO: inspect stk */ + } + if (!call_asm_instruction (file, op->identifier)) + return 0; + } + break; + case slang_oper_break: + file->code[asm].type = slang_asm_jump; + file->code[asm].param[0] = flow->loop_end; + break; + case slang_oper_continue: + file->code[asm].type = slang_asm_jump; + file->code[asm].param[0] = flow->loop_start; + break; + case slang_oper_discard: + file->code[asm].type = slang_asm_discard; + if (!slang_assembly_file_push (file, slang_asm_exit)) + return 0; + break; + case slang_oper_return: + if (info->ret_size != 0) + { + slang_assembly_stack_info stk; + if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, 0, info->ret_size)) + return 0; + if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + return 0; + /* TODO: inspect stk */ + if (!assignment (file, op->children, space, info)) + return 0; + if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4)) + return 0; + } + if (!slang_assembly_file_push_label (file, slang_asm_jump, flow->function_end)) + return 0; + break; + case slang_oper_expression: + { + slang_assembly_stack_info stk; + if (!_slang_assemble_operation (file, op->children, reference, flow, space, info, &stk)) + return 0; + /* TODO: inspect stk */ + } + break; + case slang_oper_if: + if (!_slang_assemble_if (file, op, flow, space, info)) + return 0; + break; + case slang_oper_while: + if (!_slang_assemble_while (file, op, flow, space, info)) + return 0; + break; + case slang_oper_do: + if (!_slang_assemble_do (file, op, flow, space, info)) + return 0; + break; + case slang_oper_for: + if (!_slang_assemble_for (file, op, flow, space, info)) + return 0; + break; + case slang_oper_void: + break; + case slang_oper_literal_bool: + file->code[asm].type = slang_asm_bool_push; + file->code[asm].literal = op->literal; + break; + case slang_oper_literal_int: + file->code[asm].type = slang_asm_int_push; + file->code[asm].literal = op->literal; + break; + case slang_oper_literal_float: + file->code[asm].type = slang_asm_float_push; + file->code[asm].literal = op->literal; + break; + case slang_oper_identifier: + { + slang_variable *var; + unsigned int size; + var = _slang_locate_variable (op->locals, op->identifier, 1); + if (var == NULL) + return 0; + size = 0; + if (!sizeof_variable (&var->type.specifier, var->array_size, space, &size)) + return 0; + if (var->initializer != NULL) + { + assert (!"var->initializer, oper_identifier"); + } + else + { + if (!reference) + { + if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, + info->addr_tmp, 4)) + return 0; + } + /* XXX: globals! */ + if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, var->address, + size)) + return 0; + if (!reference) + { + if (!slang_assembly_file_push (file, slang_asm_addr_copy)) + return 0; + if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4)) + return 0; + if (!dereference (file, op, space, info)) + return 0; + } + } + } + break; + case slang_oper_sequence: + { + slang_assembly_stack_info stk; + if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + return 0; + /* TODO: pass-in stk to cleanup */ + if (!_slang_cleanup_stack (file, op->children, 0, space)) + return 0; + if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, + &stk)) + return 0; + /* TODO: inspect stk */ + } + break; + case slang_oper_assign: + { + slang_assembly_stack_info stk; + if (!reference) + if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, info->addr_tmp, + 4)) + return 0; + if (!_slang_assemble_operation (file, op->children, 1, flow, space, info, &stk)) + return 0; + /* TODO: inspect stk */ + if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk)) + return 0; + /* TODO: inspect stk */ + if (!assignment (file, op->children, space, info)) + return 0; + if (!reference) + { + if (!slang_assembly_file_push (file, slang_asm_addr_copy)) + return 0; + if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4)) + return 0; + if (!dereference (file, op->children, space, info)) + return 0; + } + } + break; + case slang_oper_addassign: + /* TODO: posprawdzaj czy zadzia³a dereferencja */ + if (!call_function_name (file, "+=", op->children, 2, 1, space, info)) + return 0; + if (reference) + { + /* TODO: stack is address */ + } + else + { + if (!dereference (file, op->children, space, info)) + return 0; + /* TODO: stack is operation type */ + } + break; + case slang_oper_subassign: + /* TODO: posprawdzaj czy zadzia³a dereferencja */ + if (!call_function_name (file, "-=", op->children, 2, 1, space, info)) + return 0; + if (reference) + { + /* TODO: stack is address */ + } + else + { + if (!dereference (file, op->children, space, info)) + return 0; + /* TODO: stack is operation type */ + } + break; + case slang_oper_mulassign: + /* TODO: posprawdzaj czy zadzia³a dereferencja */ + if (!call_function_name (file, "*=", op->children, 2, 1, space, info)) + return 0; + if (reference) + { + /* TODO: stack is address */ + } + else + { + if (!dereference (file, op->children, space, info)) + return 0; + /* TODO: stack is operation type */ + } + 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: + /* TODO: posprawdzaj czy zadzia³a dereferencja */ + if (!call_function_name (file, "/=", op->children, 2, 1, space, info)) + return 0; + if (reference) + { + /* TODO: stack is address */ + } + else + { + if (!dereference (file, op->children, space, info)) + return 0; + /* TODO: stack is operation type */ + } + break; + case slang_oper_select: + if (!_slang_assemble_select (file, op, flow, space, info)) + return 0; + break; + case slang_oper_logicalor: + if (!_slang_assemble_logicalor (file, op, flow, space, info)) + return 0; + break; + case slang_oper_logicaland: + if (!_slang_assemble_logicaland (file, op, flow, space, info)) + return 0; + break; + case slang_oper_logicalxor: + if (!call_function_name (file, "^^", op->children, 2, 0, space, info)) + return 0; + break; + /*case slang_oper_bitor:*/ + /*case slang_oper_bitxor:*/ + /*case slang_oper_bitand:*/ + case slang_oper_less: + if (!call_function_name (file, "<", op->children, 2, 0, space, info)) + return 0; + break; + case slang_oper_greater: + if (!call_function_name (file, ">", op->children, 2, 0, space, info)) + return 0; + break; + case slang_oper_lessequal: + if (!call_function_name (file, "<=", op->children, 2, 0, space, info)) + return 0; + break; + case slang_oper_greaterequal: + if (!call_function_name (file, ">=", op->children, 2, 0, space, info)) + return 0; + break; + /*case slang_oper_lshift:*/ + /*case slang_oper_rshift:*/ + case slang_oper_add: + if (!call_function_name (file, "+", op->children, 2, 0, space, info)) + return 0; + break; + case slang_oper_subtract: + if (!call_function_name (file, "-", op->children, 2, 0, space, info)) + return 0; + break; + case slang_oper_multiply: + if (!call_function_name (file, "*", op->children, 2, 0, space, info)) + return 0; + break; + /*case slang_oper_modulus:*/ + case slang_oper_divide: + if (!call_function_name (file, "/", op->children, 2, 0, space, info)) + return 0; + break; + case slang_oper_equal: + { + slang_assembly_stack_info stk; + if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + return 0; + /* TODO: inspect stk */ + if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk)) + return 0; + /* TODO: inspect stk */ + if (!equality (file, op->children, space, info, 1)) + return 0; + } + break; + case slang_oper_notequal: + { + slang_assembly_stack_info stk; + if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + return 0; + /* TODO: inspect stk */ + if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk)) + return 0; + /* TODO: inspect stk */ + if (!equality (file, op->children, space, info, 0)) + return 0; + } + break; + case slang_oper_preincrement: + /* TODO: posprawdzaj czy zadzia³a dereferencja */ + if (!call_function_name (file, "++", op->children, 1, 1, space, info)) + return 0; + if (reference) + { + /* TODO: stack is address */ + } + else + { + /* TODO: dereference */ + /* TODO: stack is operation type */ + } + break; + case slang_oper_predecrement: + /* TODO: posprawdzaj czy zadzia³a dereferencja */ + if (!call_function_name (file, "--", op->children, 1, 1, space, info)) + return 0; + if (reference) + { + /* TODO: stack is address */ + } + else + { + /* TODO: dereference */ + /* TODO: stack is operation type */ + } + break; + case slang_oper_plus: + if (!call_function_name (file, "+", op->children, 1, 0, space, info)) + return 0; + break; + case slang_oper_minus: + if (!call_function_name (file, "-", op->children, 1, 0, space, info)) + return 0; + break; + /*case slang_oper_complement:*/ + case slang_oper_not: + if (!call_function_name (file, "!", op->children, 1, 0, space, info)) + return 0; + break; + case slang_oper_subscript: + { + slang_assembly_stack_info _stk; + slang_assembly_typeinfo ti_arr, ti_elem; + unsigned int arr_size = 0, elem_size = 0; + if (!_slang_assemble_operation (file, op->children, reference, flow, space, info, + &_stk)) + return 0; + if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &_stk)) + return 0; + slang_assembly_typeinfo_construct (&ti_arr); + if (!_slang_typeof_operation (op->children, space, &ti_arr)) + { + slang_assembly_typeinfo_destruct (&ti_arr); + return 0; + } + if (!sizeof_variable (&ti_arr.spec, NULL, space, &arr_size)) + { + slang_assembly_typeinfo_destruct (&ti_arr); + return 0; + } + slang_assembly_typeinfo_construct (&ti_elem); + if (!_slang_typeof_operation (op, space, &ti_elem)) + { + slang_assembly_typeinfo_destruct (&ti_arr); + slang_assembly_typeinfo_destruct (&ti_elem); + return 0; + } + if (!sizeof_variable (&ti_elem.spec, NULL, space, &elem_size)) + { + slang_assembly_typeinfo_destruct (&ti_arr); + slang_assembly_typeinfo_destruct (&ti_elem); + return 0; + } + if (!slang_assembly_file_push (file, slang_asm_int_to_addr)) + { + slang_assembly_typeinfo_destruct (&ti_arr); + slang_assembly_typeinfo_destruct (&ti_elem); + return 0; + } + if (!slang_assembly_file_push_label (file, slang_asm_addr_push, elem_size)) + { + slang_assembly_typeinfo_destruct (&ti_arr); + slang_assembly_typeinfo_destruct (&ti_elem); + return 0; + } + if (!slang_assembly_file_push (file, slang_asm_addr_multiply)) + { + slang_assembly_typeinfo_destruct (&ti_arr); + slang_assembly_typeinfo_destruct (&ti_elem); + return 0; + } + if (reference) + { + if (!slang_assembly_file_push (file, slang_asm_addr_add)) + { + slang_assembly_typeinfo_destruct (&ti_arr); + slang_assembly_typeinfo_destruct (&ti_elem); + return 0; + } + } + else + { + unsigned int i; + for (i = 0; i < elem_size; i += 4) + { + if (!slang_assembly_file_push_label2 (file, slang_asm_float_move, + arr_size - elem_size + i + 4, i + 4)) + { + slang_assembly_typeinfo_destruct (&ti_arr); + slang_assembly_typeinfo_destruct (&ti_elem); + return 0; + } + } + if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4)) + { + slang_assembly_typeinfo_destruct (&ti_arr); + slang_assembly_typeinfo_destruct (&ti_elem); + return 0; + } + if (!slang_assembly_file_push_label (file, slang_asm_local_free, + arr_size - elem_size)) + { + slang_assembly_typeinfo_destruct (&ti_arr); + slang_assembly_typeinfo_destruct (&ti_elem); + return 0; + } + } + slang_assembly_typeinfo_destruct (&ti_arr); + slang_assembly_typeinfo_destruct (&ti_elem); + } + break; + case slang_oper_call: + { + slang_function *fun = _slang_locate_function (op->identifier, op->children, + op->num_children, space); + if (fun == NULL) + { + if (!_slang_assemble_constructor (file, op, flow, space, info)) + return 0; + } + else + { + if (!call_function (file, fun, op->children, op->num_children, 0, space, info)) + return 0; + } + } + break; + case slang_oper_field: + { + slang_assembly_typeinfo ti_after, ti_before; + slang_assembly_stack_info _stk; + slang_assembly_typeinfo_construct (&ti_after); + if (!_slang_typeof_operation (op, space, &ti_after)) + { + slang_assembly_typeinfo_destruct (&ti_after); + return 0; + } + slang_assembly_typeinfo_construct (&ti_before); + if (!_slang_typeof_operation (op->children, space, &ti_before)) + { + slang_assembly_typeinfo_destruct (&ti_after); + slang_assembly_typeinfo_destruct (&ti_before); + return 0; + } + if (!reference && ti_after.is_swizzled) + { + if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, + info->swizzle_tmp, 16)) + { + slang_assembly_typeinfo_destruct (&ti_after); + slang_assembly_typeinfo_destruct (&ti_before); + return 0; + } + } + if (!_slang_assemble_operation (file, op->children, reference, flow, space, info, + &_stk)) + { + slang_assembly_typeinfo_destruct (&ti_after); + slang_assembly_typeinfo_destruct (&ti_before); + return 0; + } + /* TODO: inspect stk */ + if (ti_after.is_swizzled) + { + if (reference) + { + if (ti_after.swz.num_components == 1) + { + if (!slang_assembly_file_push_label (file, slang_asm_addr_push, + ti_after.swz.swizzle[0] * 4)) + { + slang_assembly_typeinfo_destruct (&ti_after); + slang_assembly_typeinfo_destruct (&ti_before); + return 0; + } + if (!slang_assembly_file_push (file, slang_asm_addr_add)) + { + slang_assembly_typeinfo_destruct (&ti_after); + slang_assembly_typeinfo_destruct (&ti_before); + return 0; + } + } + else + { + unsigned int i; + for (i = 0; i < ti_after.swz.num_components; i++) + stk->swizzle_mask |= 1 << ti_after.swz.swizzle[i]; + } + } + else + { + if (!_slang_assemble_constructor_from_swizzle (file, &ti_after.swz, + &ti_after.spec, &ti_before.spec, info)) + { + slang_assembly_typeinfo_destruct (&ti_after); + slang_assembly_typeinfo_destruct (&ti_before); + return 0; + } + } + } + else + { + if (reference) + { + /* TODO: struct field address */ + } + else + { + /* TODO: struct field value */ + } + } + slang_assembly_typeinfo_destruct (&ti_after); + slang_assembly_typeinfo_destruct (&ti_before); + } + break; + case slang_oper_postincrement: + if (!call_function_name_dummyint (file, "++", op->children, space, info)) + return 0; + if (!dereference (file, op, space, info)) + return 0; + break; + case slang_oper_postdecrement: + if (!call_function_name_dummyint (file, "--", op->children, space, info)) + return 0; + if (!dereference (file, op, space, info)) + return 0; + break; + default: + return 0; + } + return 1; +} + + + + + + + + + +void xxx_first (slang_assembly_file *file) +{ + slang_assembly_file_push (file, slang_asm_jump); +} + +void xxx_prolog (slang_assembly_file *file) +{ + file->code[0].param[0] = file->count; + + /* allocate local storage for inout/out params */ + slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f); + slang_assembly_file_push_label (file, slang_asm_enter, 4); + +/* slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f); + slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f); + slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f); + slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f); + slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f); + slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f); + slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f); + slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f); + slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f); + slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f); + slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f); + slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f); + slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f); + slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f); + slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f);*/ + slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f); +/* slang_assembly_file_push_literal (file, slang_asm_float_push, 16.16f); + slang_assembly_file_push_literal (file, slang_asm_float_push, 15.15f); + slang_assembly_file_push_literal (file, slang_asm_float_push, 14.14f); + slang_assembly_file_push_literal (file, slang_asm_float_push, 13.13f); + slang_assembly_file_push_literal (file, slang_asm_float_push, 12.12f); + slang_assembly_file_push_literal (file, slang_asm_float_push, 11.11f); + slang_assembly_file_push_literal (file, slang_asm_float_push, 10.10f); + slang_assembly_file_push_literal (file, slang_asm_float_push, 9.9f); + slang_assembly_file_push_literal (file, slang_asm_float_push, 8.8f); + slang_assembly_file_push_literal (file, slang_asm_float_push, 7.7f); + slang_assembly_file_push_literal (file, slang_asm_float_push, 6.6f); + slang_assembly_file_push_literal (file, slang_asm_float_push, 5.5f); + slang_assembly_file_push_literal (file, slang_asm_float_push, 4.4f); + slang_assembly_file_push_literal (file, slang_asm_float_push, 3.3f); + slang_assembly_file_push_literal (file, slang_asm_float_push, 2.2f);*/ + slang_assembly_file_push_literal (file, slang_asm_float_push, 1.1f); + + slang_assembly_file_push_label (file, slang_asm_call, file->count + 3); + slang_assembly_file_push_label (file, slang_asm_local_free, 4); + + slang_assembly_file_push (file, slang_asm_exit); +} + diff --git a/src/mesa/shader/slang/slang_assemble.h b/src/mesa/shader/slang/slang_assemble.h new file mode 100644 index 00000000000..21721c42732 --- /dev/null +++ b/src/mesa/shader/slang/slang_assemble.h @@ -0,0 +1,145 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 2005 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. + */ + +#if !defined SLANG_ASSEMBLE_H +#define SLANG_ASSEMBLE_H + +#include "slang_compile.h" + +#if defined __cplusplus +extern "C" { +#endif + +typedef enum slang_assembly_type_ +{ + /* core */ + slang_asm_none, + slang_asm_float_copy, + slang_asm_float_move, + slang_asm_float_push, + slang_asm_float_deref, + slang_asm_float_add, + slang_asm_float_multiply, + slang_asm_float_divide, + slang_asm_float_negate, + slang_asm_float_less, + slang_asm_float_equal, + slang_asm_float_to_int, + slang_asm_int_copy, + slang_asm_int_move, + slang_asm_int_push, + slang_asm_int_deref, + slang_asm_int_to_float, + slang_asm_int_to_addr, + slang_asm_bool_copy, + slang_asm_bool_move, + slang_asm_bool_push, + slang_asm_bool_deref, + slang_asm_addr_copy, + slang_asm_addr_push, + slang_asm_addr_deref, + slang_asm_addr_add, + slang_asm_addr_multiply, + slang_asm_jump, + slang_asm_jump_if_zero, + slang_asm_enter, + slang_asm_leave, + slang_asm_local_alloc, + slang_asm_local_free, + slang_asm_local_addr, + slang_asm_call, + slang_asm_return, + slang_asm_discard, + slang_asm_exit, + slang_asm__last +} slang_assembly_type; + +typedef struct slang_assembly_ +{ + slang_assembly_type type; + GLfloat literal; + GLuint param[2]; +} slang_assembly; + +typedef struct slang_assembly_file_ +{ + slang_assembly *code; + unsigned int count; +} slang_assembly_file; + +void slang_assembly_file_construct (slang_assembly_file *); +void slang_assembly_file_destruct (slang_assembly_file *); +int slang_assembly_file_push (slang_assembly_file *, slang_assembly_type); +int slang_assembly_file_push_label (slang_assembly_file *, slang_assembly_type, GLuint); +int slang_assembly_file_push_label2 (slang_assembly_file *, slang_assembly_type, GLuint, GLuint); +int slang_assembly_file_push_literal (slang_assembly_file *, slang_assembly_type, GLfloat); + +typedef struct slang_assembly_flow_control_ +{ + unsigned int loop_start; /* for "continue" statement */ + unsigned int loop_end; /* for "break" statement */ + unsigned int function_end; /* for "return" statement */ +} slang_assembly_flow_control; + +typedef struct slang_assembly_name_space_ +{ + struct slang_function_scope_ *funcs; + struct slang_struct_scope_ *structs; + struct slang_variable_scope_ *vars; +} slang_assembly_name_space; + +slang_function *_slang_locate_function (const char *name, slang_operation *params, + unsigned int num_params, slang_assembly_name_space *space); + +int _slang_assemble_function (slang_assembly_file *, struct slang_function_ *, + slang_assembly_name_space *); + +typedef struct slang_assembly_stack_info_ +{ + unsigned int swizzle_mask; +} slang_assembly_stack_info; + +int _slang_cleanup_stack (slang_assembly_file *, slang_operation *, int ref, + slang_assembly_name_space *); + +typedef struct slang_assembly_local_info_ +{ + unsigned int ret_size; + unsigned int addr_tmp; + unsigned int swizzle_tmp; +} slang_assembly_local_info; + +int _slang_assemble_operation (slang_assembly_file *, struct slang_operation_ *, int reference, + slang_assembly_flow_control *, slang_assembly_name_space *, slang_assembly_local_info *, + slang_assembly_stack_info *); + +void xxx_first (slang_assembly_file *); +void xxx_prolog (slang_assembly_file *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/shader/slang/slang_assemble_conditional.c b/src/mesa/shader/slang/slang_assemble_conditional.c new file mode 100644 index 00000000000..498938bdd55 --- /dev/null +++ b/src/mesa/shader/slang/slang_assemble_conditional.c @@ -0,0 +1,485 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 2005 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_conditional.c + * slang condtional expressions assembler + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_utility.h" +#include "slang_assemble_conditional.h" +#include "slang_assemble.h" + +/* _slang_assemble_logicaland() */ + +int _slang_assemble_logicaland (slang_assembly_file *file, slang_operation *op, + slang_assembly_flow_control *flow, slang_assembly_name_space *space, + slang_assembly_local_info *info) +{ + /* + and: + + jumpz zero + + jump end + zero: + push 0 + end: + */ + + unsigned int zero_jump, end_jump; + slang_assembly_stack_info stk; + + /* evaluate left expression */ + if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + return 0; + /* TODO: inspect stk */ + + /* jump to pushing 0 if not true */ + zero_jump = file->count; + if (!slang_assembly_file_push (file, slang_asm_jump_if_zero)) + return 0; + + /* evaluate right expression */ + if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk)) + return 0; + /* TODO: inspect stk */ + + /* jump to the end of the expression */ + end_jump = file->count; + if (!slang_assembly_file_push (file, slang_asm_jump)) + return 0; + + /* push 0 on stack */ + file->code[zero_jump].param[0] = file->count; + if (!slang_assembly_file_push (file, slang_asm_bool_push)) + return 0; + + /* the end of the expression */ + file->code[end_jump].param[0] = file->count; + + return 1; +} + +/* _slang_assemble_logicalor() */ + +int _slang_assemble_logicalor (slang_assembly_file *file, slang_operation *op, + slang_assembly_flow_control *flow, slang_assembly_name_space *space, + slang_assembly_local_info *info) +{ + /* + or: + + jumpz right + push 1 + jump end + right: + + end: + */ + + unsigned int right_jump, end_jump; + slang_assembly_stack_info stk; + + /* evaluate left expression */ + if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + return 0; + /* TODO: inspect stk */ + + /* jump to evaluation of right expression if not true */ + right_jump = file->count; + if (!slang_assembly_file_push (file, slang_asm_jump_if_zero)) + return 0; + + /* push 1 on stack */ + if (!slang_assembly_file_push_literal (file, slang_asm_bool_push, 1.0f)) + return 0; + + /* jump to the end of the expression */ + end_jump = file->count; + if (!slang_assembly_file_push (file, slang_asm_jump)) + return 0; + + /* evaluate right expression */ + file->code[right_jump].param[0] = file->count; + if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk)) + return 0; + /* TODO: inspect stk */ + + /* the end of the expression */ + file->code[end_jump].param[0] = file->count; + + return 1; +} + +/* _slang_assemble_select() */ + +int _slang_assemble_select (slang_assembly_file *file, slang_operation *op, + slang_assembly_flow_control *flow, slang_assembly_name_space *space, + slang_assembly_local_info *info) +{ + /* + select: + + jumpz false + + jump end + false: + + end: + */ + + unsigned int cond_jump, end_jump; + slang_assembly_stack_info stk; + + /* execute condition expression */ + if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + return 0; + /* TODO: inspect stk */ + + /* jump to false expression if not true */ + cond_jump = file->count; + if (!slang_assembly_file_push (file, slang_asm_jump_if_zero)) + return 0; + + /* execute true expression */ + if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk)) + return 0; + /* TODO: inspect stk */ + + /* jump to the end of the expression */ + end_jump = file->count; + if (!slang_assembly_file_push (file, slang_asm_jump)) + return 0; + + /* resolve false point */ + file->code[cond_jump].param[0] = file->count; + + /* execute false expression */ + if (!_slang_assemble_operation (file, op->children + 2, 0, flow, space, info, &stk)) + return 0; + /* TODO: inspect stk */ + + /* resolve the end of the expression */ + file->code[end_jump].param[0] = file->count; + + return 1; +} + +/* _slang_assemble_for() */ + +int _slang_assemble_for (slang_assembly_file *file, slang_operation *op, + slang_assembly_flow_control *flow, slang_assembly_name_space *space, + slang_assembly_local_info *info) +{ + /* + for: + + jump start + break: + jump end + continue: + + start: + + jumpz end + + jump continue + end: + */ + + unsigned int start_jump, end_jump, cond_jump; + unsigned int break_label, cont_label; + slang_assembly_flow_control loop_flow = *flow; + slang_assembly_stack_info stk; + + /* execute initialization statement */ + if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + return 0; + /* TODO: pass-in stk to cleanup */ + if (!_slang_cleanup_stack (file, op->children, 0, space)) + return 0; + + /* skip the "go to the end of the loop" and loop-increment statements */ + start_jump = file->count; + if (!slang_assembly_file_push (file, slang_asm_jump)) + return 0; + + /* go to the end of the loop - break statements are directed here */ + break_label = file->count; + end_jump = file->count; + if (!slang_assembly_file_push (file, slang_asm_jump)) + return 0; + + /* resolve the beginning of the loop - continue statements are directed here */ + cont_label = file->count; + + /* execute loop-increment statement */ + if (!_slang_assemble_operation (file, op->children + 2, 0, flow, space, info, &stk)) + return 0; + /* TODO: pass-in stk to cleanup */ + if (!_slang_cleanup_stack (file, op->children + 2, 0, space)) + return 0; + + /* resolve the condition point */ + file->code[start_jump].param[0] = file->count; + + /* execute condition statement */ + if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk)) + return 0; + /* TODO: inspect stk */ + + /* jump to the end of the loop if not true */ + cond_jump = file->count; + if (!slang_assembly_file_push (file, slang_asm_jump_if_zero)) + return 0; + + /* execute loop body */ + loop_flow.loop_start = cont_label; + loop_flow.loop_end = break_label; + if (!_slang_assemble_operation (file, op->children + 3, 0, &loop_flow, space, info, &stk)) + return 0; + /* TODO: pass-in stk to cleanup */ + if (!_slang_cleanup_stack (file, op->children + 3, 0, space)) + return 0; + + /* go to the beginning of the loop */ + if (!slang_assembly_file_push_label (file, slang_asm_jump, cont_label)) + return 0; + + /* resolve the end of the loop */ + file->code[end_jump].param[0] = file->count; + file->code[cond_jump].param[0] = file->count; + + return 1; +} + +/* _slang_assemble_do() */ + +int _slang_assemble_do (slang_assembly_file *file, slang_operation *op, + slang_assembly_flow_control *flow, slang_assembly_name_space *space, + slang_assembly_local_info *info) +{ + /* + do: + jump start + break: + jump end + continue: + jump condition + start: + + condition: + + jumpz end + jump start + end: + */ + + unsigned int skip_jump, end_jump, cont_jump, cond_jump; + unsigned int break_label, cont_label; + slang_assembly_flow_control loop_flow = *flow; + slang_assembly_stack_info stk; + + /* skip the "go to the end of the loop" and "go to condition" statements */ + skip_jump = file->count; + if (!slang_assembly_file_push (file, slang_asm_jump)) + return 0; + + /* go to the end of the loop - break statements are directed here */ + break_label = file->count; + end_jump = file->count; + if (!slang_assembly_file_push (file, slang_asm_jump)) + return 0; + + /* go to condition - continue statements are directed here */ + cont_label = file->count; + cont_jump = file->count; + if (!slang_assembly_file_push (file, slang_asm_jump)) + return 0; + + /* resolve the beginning of the loop */ + file->code[skip_jump].param[0] = file->count; + + /* execute loop body */ + loop_flow.loop_start = cont_label; + loop_flow.loop_end = break_label; + if (!_slang_assemble_operation (file, op->children, 0, &loop_flow, space, info, &stk)) + return 0; + /* TODO: pass-in stk to cleanup */ + if (!_slang_cleanup_stack (file, op->children, 0, space)) + return 0; + + /* resolve condition point */ + file->code[cont_jump].param[0] = file->count; + + /* execute condition statement */ + if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk)) + return 0; + /* TODO: pass-in stk to cleanup */ + + /* jump to the end of the loop if not true */ + cond_jump = file->count; + if (!slang_assembly_file_push (file, slang_asm_jump_if_zero)) + return 0; + + /* jump to the beginning of the loop */ + if (!slang_assembly_file_push_label (file, slang_asm_jump, file->code[skip_jump].param[0])) + return 0; + + /* resolve the end of the loop */ + file->code[end_jump].param[0] = file->count; + file->code[cond_jump].param[0] = file->count; + + return 1; +} + +/* _slang_assemble_while() */ + +int _slang_assemble_while (slang_assembly_file *file, slang_operation *op, + slang_assembly_flow_control *flow, slang_assembly_name_space *space, + slang_assembly_local_info *info) +{ + /* + while: + jump continue + break: + jump end + continue: + + jumpz end + + jump continue + end: + */ + + unsigned int skip_jump, end_jump, cond_jump; + unsigned int break_label; + slang_assembly_flow_control loop_flow = *flow; + slang_assembly_stack_info stk; + + /* skip the "go to the end of the loop" statement */ + skip_jump = file->count; + if (!slang_assembly_file_push (file, slang_asm_jump)) + return 0; + + /* go to the end of the loop - break statements are directed here */ + break_label = file->count; + end_jump = file->count; + if (!slang_assembly_file_push (file, slang_asm_jump)) + return 0; + + /* resolve the beginning of the loop - continue statements are directed here */ + file->code[skip_jump].param[0] = file->count; + + /* execute condition statement */ + if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + return 0; + /* TODO: pass-in stk to cleanup */ + + /* jump to the end of the loop if not true */ + cond_jump = file->count; + if (!slang_assembly_file_push (file, slang_asm_jump_if_zero)) + return 0; + + /* execute loop body */ + loop_flow.loop_start = file->code[skip_jump].param[0]; + loop_flow.loop_end = break_label; + if (!_slang_assemble_operation (file, op->children + 1, 0, &loop_flow, space, info, &stk)) + return 0; + /* TODO: pass-in stk to cleanup */ + if (!_slang_cleanup_stack (file, op->children + 1, 0, space)) + return 0; + + /* jump to the beginning of the loop */ + if (!slang_assembly_file_push_label (file, slang_asm_jump, file->code[skip_jump].param[0])) + return 0; + + /* resolve the end of the loop */ + file->code[end_jump].param[0] = file->count; + file->code[cond_jump].param[0] = file->count; + + return 1; +} + +/* _slang_assemble_if() */ + +int _slang_assemble_if (slang_assembly_file *file, slang_operation *op, + slang_assembly_flow_control *flow, slang_assembly_name_space *space, + slang_assembly_local_info *info) +{ + /* + if: + + jumpz else + + jump end + else: + + end: + */ + + unsigned int cond_jump, else_jump; + slang_assembly_stack_info stk; + + /* execute condition statement */ + if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + return 0; + /* TODO: pass-in stk to cleanup */ + + /* jump to false-statement if not true */ + cond_jump = file->count; + if (!slang_assembly_file_push (file, slang_asm_jump_if_zero)) + return 0; + + /* execute true-statement */ + if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk)) + return 0; + /* TODO: pass-in stk to cleanup */ + if (!_slang_cleanup_stack (file, op->children + 1, 0, space)) + return 0; + + /* skip if-false statement */ + else_jump = file->count; + if (!slang_assembly_file_push (file, slang_asm_jump)) + return 0; + + /* resolve start of false-statement */ + file->code[cond_jump].param[0] = file->count; + + /* execute false-statement */ + if (!_slang_assemble_operation (file, op->children + 2, 0, flow, space, info, &stk)) + return 0; + /* TODO: pass-in stk to cleanup */ + if (!_slang_cleanup_stack (file, op->children + 2, 0, space)) + return 0; + + /* resolve end of if-false statement */ + file->code[else_jump].param[0] = file->count; + + return 1; +} + diff --git a/src/mesa/shader/slang/slang_assemble_conditional.h b/src/mesa/shader/slang/slang_assemble_conditional.h new file mode 100644 index 00000000000..9ae2c62a21f --- /dev/null +++ b/src/mesa/shader/slang/slang_assemble_conditional.h @@ -0,0 +1,66 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 2005 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. + */ + +#if !defined SLANG_ASSEMBLE_CONDITIONAL_H +#define SLANG_ASSEMBLE_CONDITIONAL_H + +#include "slang_assemble.h" + +#if defined __cplusplus +extern "C" { +#endif + +int _slang_assemble_logicaland (slang_assembly_file *file, slang_operation *op, + slang_assembly_flow_control *flow, slang_assembly_name_space *space, + slang_assembly_local_info *info); + +int _slang_assemble_logicalor (slang_assembly_file *file, slang_operation *op, + slang_assembly_flow_control *flow, slang_assembly_name_space *space, + slang_assembly_local_info *info); + +int _slang_assemble_select (slang_assembly_file *file, slang_operation *op, + slang_assembly_flow_control *flow, slang_assembly_name_space *space, + slang_assembly_local_info *info); + +int _slang_assemble_for (slang_assembly_file *file, slang_operation *op, + slang_assembly_flow_control *flow, slang_assembly_name_space *space, + slang_assembly_local_info *info); + +int _slang_assemble_do (slang_assembly_file *file, slang_operation *op, + slang_assembly_flow_control *flow, slang_assembly_name_space *space, + slang_assembly_local_info *info); + +int _slang_assemble_while (slang_assembly_file *file, slang_operation *op, + slang_assembly_flow_control *flow, slang_assembly_name_space *space, + slang_assembly_local_info *info); + +int _slang_assemble_if (slang_assembly_file *file, slang_operation *op, + slang_assembly_flow_control *flow, slang_assembly_name_space *space, + slang_assembly_local_info *info); +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/shader/slang/slang_assemble_constructor.c b/src/mesa/shader/slang/slang_assemble_constructor.c new file mode 100644 index 00000000000..976e2a02a5e --- /dev/null +++ b/src/mesa/shader/slang/slang_assemble_constructor.c @@ -0,0 +1,333 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 2005 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_constructor.c + * slang constructor and vector swizzle assembler + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_utility.h" +#include "slang_assemble_constructor.h" +#include "slang_assemble_typeinfo.h" +#include "slang_storage.h" + +/* _slang_is_swizzle() */ + +int _slang_is_swizzle (const char *field, unsigned int rows, slang_swizzle *swz) +{ + unsigned int i; + int xyzw = 0, rgba = 0, stpq = 0; + + /* the swizzle can be at most 4-component long */ + swz->num_components = slang_string_length (field); + if (swz->num_components > 4) + return 0; + + for (i = 0; i < swz->num_components; i++) + { + /* mark which swizzle group is used */ + switch (field[i]) + { + case 'x': + case 'y': + case 'z': + case 'w': + xyzw = 1; + break; + case 'r': + case 'g': + case 'b': + case 'a': + rgba = 1; + break; + case 's': + case 't': + case 'p': + case 'q': + stpq = 1; + break; + default: + return 0; + } + + /* collect swizzle component */ + switch (field[i]) + { + case 'x': + case 'r': + case 's': + swz->swizzle[i] = 0; + break; + case 'y': + case 'g': + case 't': + if (rows < 2) + return 0; + swz->swizzle[i] = 1; + break; + case 'z': + case 'b': + case 'p': + if (rows < 3) + return 0; + swz->swizzle[i] = 2; + break; + case 'w': + case 'a': + case 'q': + if (rows < 4) + return 0; + swz->swizzle[i] = 3; + break; + } + } + + /* only one swizzle group can be used */ + if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq)) + return 0; + + return 1; +} + +/* _slang_is_swizzle_mask() */ + +int _slang_is_swizzle_mask (const slang_swizzle *swz, unsigned int rows) +{ + unsigned int c, i; + + if (swz->num_components > rows) + return 0; + c = swz->swizzle[0]; + for (i = 1; i < swz->num_components; i++) + { + if (swz->swizzle[i] <= c) + return 0; + c = swz->swizzle[i]; + } + return 1; +} + +/* _slang_multiply_swizzles() */ + +void _slang_multiply_swizzles (slang_swizzle *dst, const slang_swizzle *left, + const slang_swizzle *right) +{ + unsigned int i; + dst->num_components = right->num_components; + for (i = 0; i < right->num_components; i++) + dst->swizzle[i] = left->swizzle[right->swizzle[i]]; +} + +/* _slang_assemble_constructor() */ + +static int constructor_aggregate (slang_assembly_file *file, const slang_storage_aggregate *flat, + unsigned int *index, slang_operation *op, unsigned int size, slang_assembly_flow_control *flow, + slang_assembly_name_space *space, slang_assembly_local_info *info) +{ + slang_assembly_typeinfo ti; + int result; + slang_storage_aggregate agg, flat_agg; + slang_assembly_stack_info stk; + unsigned int i; + + slang_assembly_typeinfo_construct (&ti); + if (!(result = _slang_typeof_operation (op, space, &ti))) + goto end1; + + slang_storage_aggregate_construct (&agg); + if (!(result = _slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs))) + goto end2; + + slang_storage_aggregate_construct (&flat_agg); + if (!(result = _slang_flatten_aggregate (&flat_agg, &agg))) + goto end; + + if (!(result = _slang_assemble_operation (file, op, 0, flow, space, info, &stk))) + goto end; + + for (i = 0; i < flat_agg.count; i++) + { + const slang_storage_array *arr1 = flat_agg.arrays + i; + const slang_storage_array *arr2 = flat->arrays + *index; + + if (arr1->type != arr2->type) + { + /* TODO: convert (generic) from arr1 to arr2 */ + } + (*index)++; + /* TODO: watch the index, if it reaches the size, pop off the stack subsequent values */ + } + + result = 1; +end: + slang_storage_aggregate_destruct (&flat_agg); +end2: + slang_storage_aggregate_destruct (&agg); +end1: + slang_assembly_typeinfo_destruct (&ti); + return result; +} +/* XXX: general swizzle! */ +int _slang_assemble_constructor (slang_assembly_file *file, slang_operation *op, + slang_assembly_flow_control *flow, slang_assembly_name_space *space, + slang_assembly_local_info *info) +{ + slang_assembly_typeinfo ti; + int result; + slang_storage_aggregate agg, flat; + unsigned int size, index, i; + + slang_assembly_typeinfo_construct (&ti); + if (!(result = _slang_typeof_operation (op, space, &ti))) + goto end1; + + slang_storage_aggregate_construct (&agg); + if (!(result = _slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs))) + goto end2; + + size = _slang_sizeof_aggregate (&agg); + + slang_storage_aggregate_construct (&flat); + if (!(result = _slang_flatten_aggregate (&flat, &agg))) + goto end; + + index = 0; + for (i = 0; i < op->num_children; i++) + { + if (!(result = constructor_aggregate (file, &flat, &index, op->children + i, size, flow, + space, info))) + goto end; + /* TODO: watch the index, if it reaches the size, raise an error */ + } + + result = 1; +end: + slang_storage_aggregate_destruct (&flat); +end2: + slang_storage_aggregate_destruct (&agg); +end1: + slang_assembly_typeinfo_destruct (&ti); + return result; +} + +/* _slang_assemble_constructor_from_swizzle() */ +/* XXX: wrong */ +int _slang_assemble_constructor_from_swizzle (slang_assembly_file *file, const slang_swizzle *swz, + slang_type_specifier *spec, slang_type_specifier *master_spec, slang_assembly_local_info *info) +{ + unsigned int master_rows, i; + switch (master_spec->type) + { + case slang_spec_bool: + case slang_spec_int: + case slang_spec_float: + master_rows = 1; + break; + case slang_spec_bvec2: + case slang_spec_ivec2: + case slang_spec_vec2: + master_rows = 2; + break; + case slang_spec_bvec3: + case slang_spec_ivec3: + case slang_spec_vec3: + master_rows = 3; + break; + case slang_spec_bvec4: + case slang_spec_ivec4: + case slang_spec_vec4: + master_rows = 4; + break; + } + for (i = 0; i < master_rows; i++) + { + switch (master_spec->type) + { + case slang_spec_bool: + case slang_spec_bvec2: + case slang_spec_bvec3: + case slang_spec_bvec4: + if (!slang_assembly_file_push_label2 (file, slang_asm_bool_copy, (master_rows - i) * 4, + i * 4)) + return 0; + break; + case slang_spec_int: + case slang_spec_ivec2: + case slang_spec_ivec3: + case slang_spec_ivec4: + if (!slang_assembly_file_push_label2 (file, slang_asm_int_copy, (master_rows - i) * 4, + i * 4)) + return 0; + break; + case slang_spec_float: + case slang_spec_vec2: + case slang_spec_vec3: + case slang_spec_vec4: + if (!slang_assembly_file_push_label2 (file, slang_asm_float_copy, + (master_rows - i) * 4, i * 4)) + return 0; + break; + } + } + if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4)) + return 0; + for (i = swz->num_components; i > 0; i--) + { + unsigned int n = i - 1; + if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, info->swizzle_tmp, 16)) + return 0; + if (!slang_assembly_file_push_label (file, slang_asm_addr_push, swz->swizzle[n] * 4)) + return 0; + if (!slang_assembly_file_push (file, slang_asm_addr_add)) + return 0; + switch (master_spec->type) + { + case slang_spec_bool: + case slang_spec_bvec2: + case slang_spec_bvec3: + case slang_spec_bvec4: + if (!slang_assembly_file_push (file, slang_asm_bool_deref)) + return 0; + break; + case slang_spec_int: + case slang_spec_ivec2: + case slang_spec_ivec3: + case slang_spec_ivec4: + if (!slang_assembly_file_push (file, slang_asm_int_deref)) + return 0; + break; + case slang_spec_float: + case slang_spec_vec2: + case slang_spec_vec3: + case slang_spec_vec4: + if (!slang_assembly_file_push (file, slang_asm_float_deref)) + return 0; + break; + } + } + return 1; +} + diff --git a/src/mesa/shader/slang/slang_assemble_constructor.h b/src/mesa/shader/slang/slang_assemble_constructor.h new file mode 100644 index 00000000000..f8a0fead3ca --- /dev/null +++ b/src/mesa/shader/slang/slang_assemble_constructor.h @@ -0,0 +1,80 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 2005 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. + */ + +#if !defined SLANG_ASSEMBLE_CONSTRUCTOR_H +#define SLANG_ASSEMBLE_CONSTRUCTOR_H + +#include "slang_assemble.h" +#include "slang_compile.h" + +#if defined __cplusplus +extern "C" { +#endif + +/* + holds a complete information about vector swizzle - the array contains + vector component sources indices, where 0 is "x", 1 is "y", ... + example: "xwz" --> { 3, { 0, 3, 2, n/u } } +*/ +typedef struct slang_swizzle_ +{ + unsigned int num_components; + unsigned int swizzle[4]; +} slang_swizzle; + +/* + checks if a field selector is a general swizzle (an r-value swizzle with replicated + components or an l-value swizzle mask) for a vector + returns 1 if this is the case, is filled with swizzle information + returns 0 otherwise +*/ +int _slang_is_swizzle (const char *field, unsigned int rows, slang_swizzle *swz); + +/* + checks if a general swizzle is an l-value swizzle - these swizzles do not have + duplicated fields and they are specified in order + returns 1 if this is a swizzle mask + returns 0 otherwise +*/ +int _slang_is_swizzle_mask (const slang_swizzle *swz, unsigned int rows); + +/* + combines two swizzles to form single swizzle + example: "wzyx.yx" --> "zw" +*/ +void _slang_multiply_swizzles (slang_swizzle *, const slang_swizzle *, const slang_swizzle *); + +int _slang_assemble_constructor (slang_assembly_file *file, slang_operation *op, + slang_assembly_flow_control *flow, slang_assembly_name_space *space, + slang_assembly_local_info *info); + +int _slang_assemble_constructor_from_swizzle (slang_assembly_file *file, const slang_swizzle *swz, + slang_type_specifier *spec, slang_type_specifier *master_spec, slang_assembly_local_info *info); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/shader/slang/slang_assemble_typeinfo.c b/src/mesa/shader/slang/slang_assemble_typeinfo.c new file mode 100644 index 00000000000..92af52a0e65 --- /dev/null +++ b/src/mesa/shader/slang/slang_assemble_typeinfo.c @@ -0,0 +1,428 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 2005 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_typeinfo.c + * slang type info + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_utility.h" +#include "slang_assemble_typeinfo.h" + +/* slang_assembly_typeinfo */ + +void slang_assembly_typeinfo_construct (slang_assembly_typeinfo *ti) +{ + slang_type_specifier_construct (&ti->spec); +} + +void slang_assembly_typeinfo_destruct (slang_assembly_typeinfo *ti) +{ + slang_type_specifier_destruct (&ti->spec); +} + +/* _slang_typeof_operation() */ + +int _slang_typeof_operation (slang_operation *op, slang_assembly_name_space *space, + slang_assembly_typeinfo *ti) +{ + ti->can_be_referenced = 0; + ti->is_swizzled = 0; + + switch (op->type) + { + case slang_oper_block_no_new_scope: + case slang_oper_block_new_scope: + case slang_oper_variable_decl: + case slang_oper_asm: + case slang_oper_break: + case slang_oper_continue: + case slang_oper_discard: + case slang_oper_return: + case slang_oper_if: + case slang_oper_while: + case slang_oper_do: + case slang_oper_for: + case slang_oper_void: + ti->spec.type = slang_spec_void; + break; + case slang_oper_expression: + case slang_oper_assign: + case slang_oper_addassign: + case slang_oper_subassign: + case slang_oper_mulassign: + case slang_oper_divassign: + case slang_oper_preincrement: + case slang_oper_predecrement: + if (!_slang_typeof_operation (op->children, space, ti)) + return 0; + break; + case slang_oper_literal_bool: + case slang_oper_logicalor: + case slang_oper_logicalxor: + case slang_oper_logicaland: + case slang_oper_equal: + case slang_oper_notequal: + case slang_oper_less: + case slang_oper_greater: + case slang_oper_lessequal: + case slang_oper_greaterequal: + case slang_oper_not: + ti->spec.type = slang_spec_bool; + break; + case slang_oper_literal_int: + ti->spec.type = slang_spec_int; + break; + case slang_oper_literal_float: + ti->spec.type = slang_spec_float; + break; + case slang_oper_identifier: + { + slang_variable *var; + + var = _slang_locate_variable (op->locals, op->identifier, 1); + if (var == NULL) + return 0; + if (!slang_type_specifier_copy (&ti->spec, &var->type.specifier)) + return 0; + ti->can_be_referenced = 1; + } + break; + case slang_oper_sequence: + /* TODO: check [0] and [1] if they match */ + if (!_slang_typeof_operation (op->children + 1, space, ti)) + return 0; + ti->can_be_referenced = 0; + ti->is_swizzled = 0; + 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_select: + /* TODO: check [1] and [2] if they match */ + if (!_slang_typeof_operation (op->children + 1, space, ti)) + return 0; + ti->can_be_referenced = 0; + ti->is_swizzled = 0; + break; + /*case slang_oper_bitor:*/ + /*case slang_oper_bitxor:*/ + /*case slang_oper_bitand:*/ + /*case slang_oper_lshift:*/ + /*case slang_oper_rshift:*/ + case slang_oper_add: + { + int exists; + if (!_slang_typeof_function ("+", op->children, 2, space, &ti->spec, &exists)) + return 0; + if (!exists) + return 0; + } + break; + case slang_oper_subtract: + { + int exists; + if (!_slang_typeof_function ("-", op->children, 2, space, &ti->spec, &exists)) + return 0; + if (!exists) + return 0; + } + break; + case slang_oper_multiply: + { + int exists; + if (!_slang_typeof_function ("*", op->children, 2, space, &ti->spec, &exists)) + return 0; + if (!exists) + return 0; + } + break; + case slang_oper_divide: + { + int exists; + if (!_slang_typeof_function ("/", op->children, 2, space, &ti->spec, &exists)) + return 0; + if (!exists) + return 0; + } + break; + /*case slang_oper_modulus:*/ + case slang_oper_plus: + { + int exists; + if (!_slang_typeof_function ("+", op->children, 1, space, &ti->spec, &exists)) + return 0; + if (!exists) + return 0; + } + break; + case slang_oper_minus: + { + int exists; + if (!_slang_typeof_function ("-", op->children, 1, space, &ti->spec, &exists)) + return 0; + if (!exists) + return 0; + } + break; + /*case slang_oper_complement:*/ + case slang_oper_subscript: + { + slang_assembly_typeinfo _ti; + slang_assembly_typeinfo_construct (&_ti); + if (!_slang_typeof_operation (op->children, space, &_ti)) + { + slang_assembly_typeinfo_destruct (&_ti); + return 0; + } + ti->can_be_referenced = _ti.can_be_referenced; + switch (_ti.spec.type) + { + case slang_spec_bvec2: + case slang_spec_bvec3: + case slang_spec_bvec4: + ti->spec.type = slang_spec_bool; + break; + case slang_spec_ivec2: + case slang_spec_ivec3: + case slang_spec_ivec4: + ti->spec.type = slang_spec_int; + break; + case slang_spec_vec2: + case slang_spec_vec3: + case slang_spec_vec4: + ti->spec.type = slang_spec_float; + break; + case slang_spec_mat2: + ti->spec.type = slang_spec_vec2; + break; + case slang_spec_mat3: + ti->spec.type = slang_spec_vec3; + break; + case slang_spec_mat4: + ti->spec.type = slang_spec_vec4; + break; + case slang_spec_array: + if (!slang_type_specifier_copy (&ti->spec, _ti.spec._array)) + { + slang_assembly_typeinfo_destruct (&_ti); + return 0; + } + break; + default: + slang_assembly_typeinfo_destruct (&_ti); + return 0; + } + slang_assembly_typeinfo_destruct (&_ti); + } + break; + case slang_oper_call: + { + int exists; + if (!_slang_typeof_function (op->identifier, op->children, op->num_children, space, + &ti->spec, &exists)) + return 0; + if (!exists) + { + slang_struct *s = slang_struct_scope_find (space->structs, op->identifier, 1); + if (s != NULL) + { + ti->spec.type = slang_spec_struct; + ti->spec._struct = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct)); + if (ti->spec._struct == NULL) + return 0; + if (!slang_struct_construct_a (ti->spec._struct)) + { + slang_alloc_free (ti->spec._struct); + ti->spec._struct = NULL; + return 0; + } + if (!slang_struct_copy (ti->spec._struct, s)) + return 0; + } + else + { + slang_type_specifier_type type = slang_type_specifier_type_from_string ( + op->identifier); + if (type == slang_spec_void) + return 0; + ti->spec.type = type; + } + } + } + break; + case slang_oper_field: + { + slang_assembly_typeinfo _ti; + slang_assembly_typeinfo_construct (&_ti); + if (!_slang_typeof_operation (op->children, space, &_ti)) + { + slang_assembly_typeinfo_destruct (&_ti); + return 0; + } + if (_ti.spec.type == slang_spec_struct) + { + slang_variable *field = _slang_locate_variable (_ti.spec._struct->fields, + op->identifier, 0); + if (field == NULL) + { + slang_assembly_typeinfo_destruct (&_ti); + return 0; + } + if (!slang_type_specifier_copy (&ti->spec, &field->type.specifier)) + { + slang_assembly_typeinfo_destruct (&_ti); + return 0; + } + } + else + { + unsigned int rows; + switch (_ti.spec.type) + { + case slang_spec_vec2: + case slang_spec_ivec2: + case slang_spec_bvec2: + rows = 2; + break; + case slang_spec_vec3: + case slang_spec_ivec3: + case slang_spec_bvec3: + rows = 3; + break; + case slang_spec_vec4: + case slang_spec_ivec4: + case slang_spec_bvec4: + rows = 4; + break; + default: + slang_assembly_typeinfo_destruct (&_ti); + return 0; + } + if (!_slang_is_swizzle (op->identifier, rows, &ti->swz)) + return 0; + ti->is_swizzled = 1; + ti->can_be_referenced = _ti.can_be_referenced && _slang_is_swizzle_mask (&ti->swz, + rows); + if (_ti.is_swizzled) + { + slang_swizzle swz; + _slang_multiply_swizzles (&swz, &_ti.swz, &ti->swz); + ti->swz = swz; + } + switch (_ti.spec.type) + { + case slang_spec_vec2: + case slang_spec_vec3: + case slang_spec_vec4: + switch (ti->swz.num_components) + { + case 1: + ti->spec.type = slang_spec_float; + break; + case 2: + ti->spec.type = slang_spec_vec2; + break; + case 3: + ti->spec.type = slang_spec_vec3; + break; + case 4: + ti->spec.type = slang_spec_vec4; + break; + } + break; + case slang_spec_ivec2: + case slang_spec_ivec3: + case slang_spec_ivec4: + switch (ti->swz.num_components) + { + case 1: + ti->spec.type = slang_spec_int; + break; + case 2: + ti->spec.type = slang_spec_ivec2; + break; + case 3: + ti->spec.type = slang_spec_ivec3; + break; + case 4: + ti->spec.type = slang_spec_ivec4; + break; + } + break; + case slang_spec_bvec2: + case slang_spec_bvec3: + case slang_spec_bvec4: + switch (ti->swz.num_components) + { + case 1: + ti->spec.type = slang_spec_bool; + break; + case 2: + ti->spec.type = slang_spec_bvec2; + break; + case 3: + ti->spec.type = slang_spec_bvec3; + break; + case 4: + ti->spec.type = slang_spec_bvec4; + break; + } + break; + } + } + slang_assembly_typeinfo_destruct (&_ti); + return 1; + } + break; + case slang_oper_postincrement: + case slang_oper_postdecrement: + if (!_slang_typeof_operation (op->children, space, ti)) + return 0; + ti->can_be_referenced = 0; + ti->is_swizzled = 0; + break; + default: + return 0; + } + return 1; +} + +/* _slang_typeof_function() */ + +int _slang_typeof_function (const char *name, slang_operation *params, unsigned int num_params, + slang_assembly_name_space *space, slang_type_specifier *spec, int *exists) +{ + slang_function *fun = _slang_locate_function (name, params, num_params, space); + *exists = fun != NULL; + if (fun == NULL) + return 1; + return slang_type_specifier_copy (spec, &fun->header.type.specifier); +} + diff --git a/src/mesa/shader/slang/slang_assemble_typeinfo.h b/src/mesa/shader/slang/slang_assemble_typeinfo.h new file mode 100644 index 00000000000..1c1839457eb --- /dev/null +++ b/src/mesa/shader/slang/slang_assemble_typeinfo.h @@ -0,0 +1,67 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 2005 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. + */ + +#if !defined SLANG_ASSEMBLE_TYPEINFO_H +#define SLANG_ASSEMBLE_TYPEINFO_H + +#include "slang_assemble_constructor.h" +#include "slang_compile.h" + +#if defined __cplusplus +extern "C" { +#endif + +typedef struct slang_assembly_typeinfo_ +{ + int can_be_referenced; + int is_swizzled; + slang_swizzle swz; + slang_type_specifier spec; +} slang_assembly_typeinfo; + +void slang_assembly_typeinfo_construct (slang_assembly_typeinfo *); +void slang_assembly_typeinfo_destruct (slang_assembly_typeinfo *); + +/* + retrieves type information about an operation + returns 1 on success + returns 0 otherwise +*/ +int _slang_typeof_operation (slang_operation *, slang_assembly_name_space *, + slang_assembly_typeinfo *); + +/* + retrieves type of a function prototype, if one exists + returns 1 on success, even if the function was not found + returns 0 otherwise +*/ +int _slang_typeof_function (const char *name, slang_operation *params, unsigned int num_params, + slang_assembly_name_space *space, slang_type_specifier *spec, int *exists); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c index 06dc7df9536..6835adea6d8 100644 --- a/src/mesa/shader/slang/slang_compile.c +++ b/src/mesa/shader/slang/slang_compile.c @@ -33,6 +33,9 @@ #include "slang_utility.h" #include "slang_compile.h" #include "slang_preprocess.h" +#include "slang_storage.h" +#include "slang_assemble.h" +#include "slang_execute.h" /* This is a straightforward implementation of the slang front-end compiler. @@ -43,22 +46,61 @@ static void slang_variable_construct (slang_variable *); static int slang_variable_copy (slang_variable *, const slang_variable *); -static void slang_struct_construct (slang_struct *); static void slang_struct_destruct (slang_struct *); -static int slang_struct_copy (slang_struct *, const slang_struct *); static int slang_struct_equal (const slang_struct *, const slang_struct *); static void slang_variable_destruct (slang_variable *); +/* slang_type_specifier_type */ + +/* these must match with slang_type_specifier_type enum */ +static const char *type_specifier_type_names[] = { + "void", + "bool", + "bvec2", + "bvec3", + "bvec4", + "int", + "ivec2", + "ivec3", + "ivec4", + "float", + "vec2", + "vec3", + "vec4", + "mat2", + "mat3", + "mat4", + "sampler1D", + "sampler2D", + "sampler3D", + "samplerCube", + "sampler1DShadow", + "sampler2DShadow", + NULL +}; + +slang_type_specifier_type slang_type_specifier_type_from_string (const char *name) +{ + const char **p = type_specifier_type_names; + while (*p != NULL) + { + if (slang_string_compare (*p, name) == 0) + return (slang_type_specifier_type) (p - type_specifier_type_names); + p++; + } + return slang_spec_void; +} + /* slang_type_specifier */ -static void slang_type_specifier_construct (slang_type_specifier *spec) +void slang_type_specifier_construct (slang_type_specifier *spec) { spec->type = slang_spec_void; spec->_struct = NULL; spec->_array = NULL; } -static void slang_type_specifier_destruct (slang_type_specifier *spec) +void slang_type_specifier_destruct (slang_type_specifier *spec) { if (spec->_struct != NULL) { @@ -72,7 +114,7 @@ static void slang_type_specifier_destruct (slang_type_specifier *spec) } } -static int slang_type_specifier_copy (slang_type_specifier *x, const slang_type_specifier *y) +int slang_type_specifier_copy (slang_type_specifier *x, const slang_type_specifier *y) { slang_type_specifier_destruct (x); slang_type_specifier_construct (x); @@ -80,19 +122,28 @@ static int slang_type_specifier_copy (slang_type_specifier *x, const slang_type_ if (x->type == slang_spec_struct) { x->_struct = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct)); - slang_struct_construct (x->_struct); + if (x->_struct == NULL) + return 0; + if (!slang_struct_construct_a (x->_struct)) + { + slang_alloc_free (x->_struct); + x->_struct = NULL; + return 0; + } return slang_struct_copy (x->_struct, y->_struct); } if (x->type == slang_spec_array) { x->_array = (slang_type_specifier *) slang_alloc_malloc (sizeof (slang_type_specifier)); + if (x->_array == NULL) + return 0; slang_type_specifier_construct (x->_array); return slang_type_specifier_copy (x->_array, y->_array); } return 1; } -static int slang_type_specifier_equal (const slang_type_specifier *x, const slang_type_specifier *y) +int slang_type_specifier_equal (const slang_type_specifier *x, const slang_type_specifier *y) { if (x->type != y->type) return 0; @@ -162,8 +213,8 @@ static int slang_variable_scope_copy (slang_variable_scope *x, const slang_varia } /* slang_operation */ -/* XXX mem! */ -static void slang_operation_construct (slang_operation *oper) + +int slang_operation_construct_a (slang_operation *oper) { oper->type = slang_oper_none; oper->children = NULL; @@ -171,10 +222,13 @@ static void slang_operation_construct (slang_operation *oper) oper->literal = (float) 0; oper->identifier = NULL; oper->locals = (slang_variable_scope *) slang_alloc_malloc (sizeof (slang_variable_scope)); + if (oper->locals == NULL) + return 0; slang_variable_scope_construct (oper->locals); + return 1; } -static void slang_operation_destruct (slang_operation *oper) +void slang_operation_destruct (slang_operation *oper) { unsigned int i; for (i = 0; i < oper->num_children; i++) @@ -188,16 +242,31 @@ static void slang_operation_destruct (slang_operation *oper) static int slang_operation_copy (slang_operation *x, const slang_operation *y) { unsigned int i; - slang_operation_destruct (x); - slang_operation_construct (x); + for (i = 0; i < x->num_children; i++) + slang_operation_destruct (x->children + i); + slang_alloc_free (x->children); + x->num_children = 0; + slang_alloc_free (x->identifier); + x->identifier = NULL; + slang_variable_scope_destruct (x->locals); + slang_variable_scope_construct (x->locals); + x->type = y->type; x->children = (slang_operation *) slang_alloc_malloc (y->num_children * sizeof ( slang_operation)); if (x->children == NULL) return 0; + for (i = 0; i < y->num_children; i++) + if (!slang_operation_construct_a (x->children + i)) + { + unsigned int j; + for (j = 0; j < i; j++) + slang_operation_destruct (x->children + j); + slang_alloc_free (x->children); + x->children = NULL; + return 0; + } x->num_children = y->num_children; - for (i = 0; i < x->num_children; i++) - slang_operation_construct (x->children + i); for (i = 0; i < x->num_children; i++) if (!slang_operation_copy (x->children + i, y->children + i)) return 0; @@ -221,6 +290,7 @@ static void slang_variable_construct (slang_variable *var) var->name = NULL; var->array_size = NULL; var->initializer = NULL; + var->address = ~0; } static void slang_variable_destruct (slang_variable *var) @@ -256,7 +326,12 @@ static int slang_variable_copy (slang_variable *x, const slang_variable *y) x->array_size = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation)); if (x->array_size == NULL) return 0; - slang_operation_construct (x->array_size); + if (!slang_operation_construct_a (x->array_size)) + { + slang_alloc_free (x->array_size); + x->array_size = NULL; + return 0; + } if (!slang_operation_copy (x->array_size, y->array_size)) return 0; } @@ -265,13 +340,29 @@ static int slang_variable_copy (slang_variable *x, const slang_variable *y) x->initializer = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation)); if (x->initializer == NULL) return 0; - slang_operation_construct (x->initializer); + if (!slang_operation_construct_a (x->initializer)) + { + slang_alloc_free (x->initializer); + x->initializer = NULL; + return 0; + } if (!slang_operation_copy (x->initializer, y->initializer)) return 0; } return 1; } +slang_variable *_slang_locate_variable (slang_variable_scope *scope, const char *name, int all) +{ + unsigned int i; + for (i = 0; i < scope->num_variables; i++) + if (slang_string_compare (name, scope->variables[i].name) == 0) + return scope->variables + i; + if (all && scope->outer_scope != NULL) + return _slang_locate_variable (scope->outer_scope, name, 1); + return NULL; +} + /* slang_struct_scope */ static void slang_struct_scope_construct (slang_struct_scope *scope) @@ -299,7 +390,17 @@ static int slang_struct_scope_copy (slang_struct_scope *x, const slang_struct_sc return 0; x->num_structs = y->num_structs; for (i = 0; i < x->num_structs; i++) - slang_struct_construct (x->structs + i); + { + unsigned int j; + if (!slang_struct_construct_a (x->structs + i)) + { + for (j = 0; j < i; j++) + slang_struct_destruct (x->structs + j); + slang_alloc_free (x->structs); + x->structs = NULL; + return 0; + } + } for (i = 0; i < x->num_structs; i++) if (!slang_struct_copy (x->structs + i, y->structs + i)) return 0; @@ -307,8 +408,7 @@ static int slang_struct_scope_copy (slang_struct_scope *x, const slang_struct_sc return 1; } -static slang_struct *slang_struct_scope_find (slang_struct_scope *stru, const char *name, - int all_scopes) +slang_struct *slang_struct_scope_find (slang_struct_scope *stru, const char *name, int all_scopes) { unsigned int i; for (i = 0; i < stru->num_structs; i++) @@ -320,14 +420,23 @@ static slang_struct *slang_struct_scope_find (slang_struct_scope *stru, const ch } /* slang_struct */ -/* XXX mem! */ -static void slang_struct_construct (slang_struct *stru) + +int slang_struct_construct_a (slang_struct *stru) { stru->name = NULL; stru->fields = (slang_variable_scope *) slang_alloc_malloc (sizeof (slang_variable_scope)); + if (stru->fields == NULL) + return 0; slang_variable_scope_construct (stru->fields); stru->structs = (slang_struct_scope *) slang_alloc_malloc (sizeof (slang_struct_scope)); + if (stru->structs == NULL) + { + slang_variable_scope_destruct (stru->fields); + slang_alloc_free (stru->fields); + return 0; + } slang_struct_scope_construct (stru->structs); + return 1; } static void slang_struct_destruct (slang_struct *stru) @@ -339,10 +448,14 @@ static void slang_struct_destruct (slang_struct *stru) slang_alloc_free (stru->structs); } -static int slang_struct_copy (slang_struct *x, const slang_struct *y) +int slang_struct_copy (slang_struct *x, const slang_struct *y) { - slang_struct_destruct (x); - slang_struct_construct (x); + slang_alloc_free (x->name); + x->name = NULL; + slang_variable_scope_destruct (x->fields); + slang_variable_scope_construct (x->fields); + slang_struct_scope_destruct (x->structs); + slang_struct_scope_construct (x->structs); if (y->name != NULL) { x->name = slang_string_duplicate (y->name); @@ -386,6 +499,7 @@ static void slang_function_construct (slang_function *func) func->parameters = (slang_variable_scope *) slang_alloc_malloc (sizeof (slang_variable_scope)); slang_variable_scope_construct (func->parameters); func->body = NULL; + func->address = ~0; } static void slang_function_destruct (slang_function *func) @@ -561,7 +675,7 @@ typedef struct slang_parse_ctx_ int parsing_builtin; } slang_parse_ctx; -/* --- */ +/* _slang_compile() */ static int parse_identifier (slang_parse_ctx *C, char **id) { @@ -826,7 +940,14 @@ static int parse_type_specifier (slang_parse_ctx *C, slang_type_specifier *spec, slang_info_log_memory (C->L); return 0; } - slang_struct_construct (spec->_struct); + if (!slang_struct_construct_a (spec->_struct)) + { + slang_alloc_free (spec->_struct); + spec->_struct = NULL; + slang_alloc_free (name); + slang_info_log_memory (C->L); + return 0; + } spec->_struct->name = name; spec->_struct->structs->outer_scope = structs; } @@ -878,7 +999,14 @@ static int parse_type_specifier (slang_parse_ctx *C, slang_type_specifier *spec, slang_info_log_memory (C->L); return 0; } - slang_operation_construct (var->array_size); + if (!slang_operation_construct_a (var->array_size)) + { + slang_alloc_free (var->array_size); + var->array_size = NULL; + slang_type_specifier_destruct (&sp); + slang_info_log_memory (C->L); + return 0; + } if (!parse_expression (C, var->array_size, scope, structs, funcs)) { slang_type_specifier_destruct (&sp); @@ -904,8 +1032,9 @@ static int parse_type_specifier (slang_parse_ctx *C, slang_type_specifier *spec, return 0; } s = structs->structs + structs->num_structs; + if (!slang_struct_construct_a (s)) + return 0; structs->num_structs++; - slang_struct_construct (s); if (!slang_struct_copy (s, spec->_struct)) return 0; } @@ -931,7 +1060,12 @@ static int parse_type_specifier (slang_parse_ctx *C, slang_type_specifier *spec, slang_info_log_memory (C->L); return 0; } - slang_struct_construct (spec->_struct); + if (!slang_struct_construct_a (spec->_struct)) + { + slang_alloc_free (spec->_struct); + spec->_struct = NULL; + return 0; + } if (!slang_struct_copy (spec->_struct, stru)) return 0; } @@ -1025,7 +1159,11 @@ static int parse_child_operation (slang_parse_ctx *C, slang_operation *oper, int slang_info_log_memory (C->L); return 0; } - slang_operation_construct (oper->children + oper->num_children); + if (!slang_operation_construct_a (oper->children + oper->num_children)) + { + slang_info_log_memory (C->L); + return 0; + } oper->num_children++; if (statement) return parse_statement (C, oper->children + oper->num_children - 1, scope, structs, funcs); @@ -1073,7 +1211,16 @@ static int parse_statement (slang_parse_ctx *C, slang_operation *oper, slang_var return 0; } for (i = 0; i < num_vars; i++) - slang_operation_construct (oper->children + i); + if (!slang_operation_construct_a (oper->children + i)) + { + unsigned int j; + for (j = 0; j < i; j++) + slang_operation_destruct (oper->children + j); + slang_alloc_free (oper->children); + oper->children = NULL; + slang_info_log_memory (C->L); + return 0; + } oper->num_children = num_vars; for (i = first_var; i < scope->num_variables; i++) { @@ -1230,39 +1377,10 @@ static int handle_unary_expression (slang_parse_ctx *C, slang_operation *op, return 1; } -/* these must match with slang_type_specifier_type enum */ -static const char *builtin_constructor_names[] = { - "void", - "bool", - "bvec2", - "bvec3", - "bvec4", - "int", - "ivec2", - "ivec3", - "ivec4", - "float", - "vec2", - "vec3", - "vec4", - "mat2", - "mat3", - "mat4", - "sampler1D", - "sampler2D", - "sampler3D", - "samplerCube", - "sampler1DShadow", - "sampler2DShadow", - NULL -}; - static int is_constructor_name (const char *name, slang_struct_scope *structs) { - const char **p = &builtin_constructor_names[1]; - while (*p != NULL) - if (slang_string_compare (*p++, name) == 0) - return 1; + if (slang_type_specifier_type_from_string (name) != slang_spec_void) + return 1; return slang_struct_scope_find (structs, name, 1) != NULL; } @@ -1285,8 +1403,12 @@ static int parse_expression (slang_parse_ctx *C, slang_operation *oper, slang_va return 0; } op = ops + num_ops; + if (!slang_operation_construct_a (op)) + { + slang_info_log_memory (C->L); + return 0; + } num_ops++; - slang_operation_construct (op); op->locals->outer_scope = scope; switch (op_code) { @@ -1513,6 +1635,7 @@ static int parse_expression (slang_parse_ctx *C, slang_operation *oper, slang_va static int parse_parameter_declaration (slang_parse_ctx *C, slang_variable *param, slang_struct_scope *structs, slang_variable_scope *scope, slang_function_scope *funcs) { + slang_storage_aggregate agg; if (!parse_type_qualifier (C, ¶m->type.qualifier)) return 0; switch (*C->I++) @@ -1557,10 +1680,24 @@ static int parse_parameter_declaration (slang_parse_ctx *C, slang_variable *para slang_info_log_memory (C->L); return 0; } - slang_operation_construct (param->array_size); + if (!slang_operation_construct_a (param->array_size)) + { + slang_alloc_free (param->array_size); + param->array_size = NULL; + slang_info_log_memory (C->L); + return 0; + } if (!parse_expression (C, param->array_size, scope, structs, funcs)) return 0; } + slang_storage_aggregate_construct (&agg); + if (!_slang_aggregate_variable (&agg, ¶m->type.specifier, param->array_size, funcs, + structs)) + { + slang_storage_aggregate_destruct (&agg); + return 0; + } + slang_storage_aggregate_destruct (&agg); return 1; } @@ -1680,7 +1817,7 @@ static int parse_function_prototype (slang_parse_ctx *C, slang_function *func, if (func->header.type.specifier.type == slang_spec_struct) return 0; func->header.name = slang_string_duplicate ( - builtin_constructor_names[func->header.type.specifier.type]); + type_specifier_type_names[func->header.type.specifier.type]); if (func->header.name == NULL) { slang_info_log_memory (C->L); @@ -1728,7 +1865,13 @@ static int parse_function_definition (slang_parse_ctx *C, slang_function *func, slang_info_log_memory (C->L); return 0; } - slang_operation_construct (func->body); + if (!slang_operation_construct_a (func->body)) + { + slang_alloc_free (func->body); + func->body = NULL; + slang_info_log_memory (C->L); + return 0; + } if (!parse_statement (C, func->body, func->parameters, structs, funcs)) return 0; return 1; @@ -1781,7 +1924,13 @@ static int parse_init_declarator (slang_parse_ctx *C, const slang_fully_specifie slang_info_log_memory (C->L); return 0; } - slang_operation_construct (var->initializer); + if (!slang_operation_construct_a (var->initializer)) + { + slang_alloc_free (var->initializer); + var->initializer = NULL; + slang_info_log_memory (C->L); + return 0; + } if (!parse_expression (C, var->initializer, vars, structs, funcs)) return 0; break; @@ -1816,13 +1965,32 @@ static int parse_init_declarator (slang_parse_ctx *C, const slang_fully_specifie slang_info_log_memory (C->L); return 0; } - slang_operation_construct (var->array_size); + if (!slang_operation_construct_a (var->array_size)) + { + slang_alloc_free (var->array_size); + var->array_size = NULL; + slang_info_log_memory (C->L); + return 0; + } if (!parse_expression (C, var->array_size, vars, structs, funcs)) return 0; break; default: return 0; } + if (!(var->type.specifier.type == slang_spec_array && var->array_size == NULL)) + { + slang_storage_aggregate agg; + + slang_storage_aggregate_construct (&agg); + if (!_slang_aggregate_variable (&agg, &var->type.specifier, var->array_size, funcs, + structs)) + { + slang_storage_aggregate_destruct (&agg); + return 0; + } + slang_storage_aggregate_destruct (&agg); + } return 1; } @@ -1874,7 +2042,8 @@ static int parse_function (slang_parse_ctx *C, int definition, slang_struct_scop } } - /* find a function with a prototype matching the parsed one */ + /* find a function with a prototype matching the parsed one - only the current scope + is being searched to allow built-in function overriding */ found_func = slang_function_scope_find (funcs, &parsed_func, 0); if (found_func == NULL) { @@ -1919,6 +2088,37 @@ static int parse_function (slang_parse_ctx *C, int definition, slang_struct_scop /* return the found function */ *parsed_func_ret = found_func; } + + /* assemble the parsed function */ + if (definition) + { +static int x = 0; +const int y = 61; /* core 437 */ +static + slang_assembly_file file; + slang_assembly_name_space space; +x++; +if (x == 1) + slang_assembly_file_construct (&file); + space.funcs = funcs; + space.structs = structs; + space.vars = scope; +if (x == 1) + xxx_first (&file); +if (x == y) + xxx_prolog (&file); + if (!_slang_assemble_function (&file, *parsed_func_ret, &space)) + { + slang_assembly_file_destruct (&file); + return 0; + } +if (x == y) +{ +_slang_execute (&file); +slang_assembly_file_destruct (&file); +exit (0); +} + } return 1; } diff --git a/src/mesa/shader/slang/slang_compile.h b/src/mesa/shader/slang/slang_compile.h index 25a0ef8ad81..a9a075c37f2 100644 --- a/src/mesa/shader/slang/slang_compile.h +++ b/src/mesa/shader/slang/slang_compile.h @@ -68,14 +68,21 @@ typedef enum slang_type_specifier_type_ slang_spec_sampler2DShadow, slang_spec_struct, slang_spec_array -} slang_type_specifier_type; +} slang_type_specifier_type; + +slang_type_specifier_type slang_type_specifier_type_from_string (const char *); typedef struct slang_type_specifier_ { slang_type_specifier_type type; struct slang_struct_ *_struct; /* spec_struct */ struct slang_type_specifier_ *_array; /* spec_array */ -} slang_type_specifier; +} slang_type_specifier; + +void slang_type_specifier_construct (slang_type_specifier *); +void slang_type_specifier_destruct (slang_type_specifier *); +int slang_type_specifier_copy (slang_type_specifier *, const slang_type_specifier *); +int slang_type_specifier_equal (const slang_type_specifier *, const slang_type_specifier *); typedef struct slang_fully_specified_type_ { @@ -164,29 +171,40 @@ typedef struct slang_operation_ float literal; /* bool, literal_int, literal_float */ char *identifier; /* asm, identifier, call, field */ slang_variable_scope *locals; -} slang_operation; +} slang_operation; + +int slang_operation_construct_a (slang_operation *); +void slang_operation_destruct (slang_operation *); typedef struct slang_variable_ { slang_fully_specified_type type; char *name; slang_operation *array_size; /* spec_array */ - slang_operation *initializer; -} slang_variable; + slang_operation *initializer; + unsigned int address; +} slang_variable; + +slang_variable *_slang_locate_variable (slang_variable_scope *scope, const char *name, int all); typedef struct slang_struct_scope_ { struct slang_struct_ *structs; unsigned int num_structs; struct slang_struct_scope_ *outer_scope; -} slang_struct_scope; +} slang_struct_scope; + +struct slang_struct_ *slang_struct_scope_find (slang_struct_scope *, const char *, int); typedef struct slang_struct_ { char *name; slang_variable_scope *fields; slang_struct_scope *structs; -} slang_struct; +} slang_struct; + +int slang_struct_construct_a (slang_struct *); +int slang_struct_copy (slang_struct *, const slang_struct *); typedef enum slang_function_kind_ { @@ -201,7 +219,8 @@ typedef struct slang_function_ slang_variable header; slang_variable_scope *parameters; unsigned int param_count; - slang_operation *body; + slang_operation *body; + unsigned int address; } slang_function; typedef struct slang_function_scope_ diff --git a/src/mesa/shader/slang/slang_execute.c b/src/mesa/shader/slang/slang_execute.c new file mode 100644 index 00000000000..1bcc4188a84 --- /dev/null +++ b/src/mesa/shader/slang/slang_execute.c @@ -0,0 +1,347 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 2005 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_execute.c + * intermediate code interpreter + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_utility.h" +#include "slang_assemble.h" +#include "slang_storage.h" +#include "slang_execute.h" + +static void dump_instruction (FILE *f, slang_assembly *a, unsigned int i) +{ + fprintf (f, "%.5u:\t", i); + + switch (a->type) + { + case slang_asm_none: + fprintf (f, "none"); + break; + case slang_asm_float_copy: + fprintf (f, "float_copy\t%d, %d", a->param[0], a->param[1]); + break; + case slang_asm_float_move: + fprintf (f, "float_move\t%d, %d", a->param[0], a->param[1]); + break; + case slang_asm_float_push: + fprintf (f, "float_push\t%f", a->literal); + break; + case slang_asm_float_deref: + fprintf (f, "float_deref"); + break; + case slang_asm_float_add: + fprintf (f, "float_add"); + break; + case slang_asm_float_multiply: + fprintf (f, "float_multiply"); + break; + case slang_asm_float_divide: + fprintf (f, "float_divide"); + break; + case slang_asm_float_negate: + fprintf (f, "float_negate"); + break; + case slang_asm_float_less: + fprintf (f, "float_less"); + break; + case slang_asm_float_equal: + fprintf (f, "float_equal\t%d, %d", a->param[0], a->param[1]); + break; + case slang_asm_float_to_int: + fprintf (f, "float_to_int"); + break; + case slang_asm_int_copy: + fprintf (f, "int_copy\t%d, %d", a->param[0], a->param[1]); + break; + case slang_asm_int_move: + fprintf (f, "int_move\t%d, %d", a->param[0], a->param[1]); + break; + case slang_asm_int_push: + fprintf (f, "int_push\t%d", (GLint) a->literal); + break; + case slang_asm_int_deref: + fprintf (f, "int_deref"); + break; + case slang_asm_int_to_float: + fprintf (f, "int_to_float"); + break; + case slang_asm_int_to_addr: + fprintf (f, "int_to_addr"); + break; + case slang_asm_bool_copy: + fprintf (f, "bool_copy\t%d, %d", a->param[0], a->param[1]); + break; + case slang_asm_bool_move: + fprintf (f, "bool_move\t%d, %d", a->param[0], a->param[1]); + break; + case slang_asm_bool_push: + fprintf (f, "bool_push\t%d", a->literal != 0.0f); + break; + case slang_asm_bool_deref: + fprintf (f, "bool_deref"); + break; + case slang_asm_addr_copy: + fprintf (f, "addr_copy"); + break; + case slang_asm_addr_push: + fprintf (f, "addr_push\t%u", a->param[0]); + break; + case slang_asm_addr_deref: + fprintf (f, "addr_deref"); + break; + case slang_asm_addr_add: + fprintf (f, "address_add"); + break; + case slang_asm_addr_multiply: + fprintf (f, "address_multiply"); + break; + case slang_asm_jump: + fprintf (f, "jump\t%u", a->param[0]); + break; + case slang_asm_jump_if_zero: + fprintf (f, "jump_if_zero\t%u", a->param[0]); + break; + case slang_asm_enter: + fprintf (f, "enter\t%u", a->param[0]); + break; + case slang_asm_leave: + fprintf (f, "leave"); + break; + case slang_asm_local_alloc: + fprintf (f, "local_alloc\t%u", a->param[0]); + break; + case slang_asm_local_free: + fprintf (f, "local_free\t%u", a->param[0]); + break; + case slang_asm_local_addr: + fprintf (f, "local_addr\t%u, %u", a->param[0], a->param[1]); + break; + case slang_asm_call: + fprintf (f, "call\t%u", a->param[0]); + break; + case slang_asm_return: + fprintf (f, "return"); + break; + case slang_asm_discard: + fprintf (f, "discard"); + break; + case slang_asm_exit: + fprintf (f, "exit"); + break; + } + + fprintf (f, "\n"); +} + +static void dump (const slang_assembly_file *file) +{ + unsigned int i; + static unsigned int counter = 0; + FILE *f; + char filename[256]; + + counter++; + sprintf (filename, "~mesa-slang-assembly-dump-(%u).txt", counter); + f = fopen (filename, "w"); + if (f == NULL) + return; + + for (i = 0; i < file->count; i++) + dump_instruction (f, file->code + i, i); + + fclose (f); +} + +int _slang_execute (const slang_assembly_file *file) +{ + slang_machine mach; +FILE *f; + + mach.ip = 0; + mach.sp = SLANG_MACHINE_STACK_SIZE; + mach.bp = 0; + mach.kill = 0; + mach.exit = 0; + + /* assume 32-bit machine */ + static_assert(sizeof (GLfloat) == 4); + static_assert(sizeof (GLfloat *) == 4); + static_assert(sizeof (GLuint) == 4); + static_assert(sizeof (GLuint *) == 4); + +dump (file); + +f = fopen ("~mesa-slang-assembly-execution.txt", "w"); + + while (!mach.exit) + { + slang_assembly *a = file->code + mach.ip; +if (f != NULL) +{ +unsigned int i; +dump_instruction (f, a, mach.ip); +fprintf (f, "\t\tsp=%u bp=%u\n", mach.sp, mach.bp); +for (i = mach.sp; i < SLANG_MACHINE_STACK_SIZE; i++) +fprintf (f, "\t%.5u\t%6f\t%u\n", i, mach.stack._float[i], mach.stack._addr[i]); +fflush (f); +} + mach.ip++; + + switch (a->type) + { + case slang_asm_none: + break; + case slang_asm_float_copy: + case slang_asm_int_copy: + case slang_asm_bool_copy: + *(mach.stack._floatp[mach.sp + a->param[0] / 4] + a->param[1] / 4) = + mach.stack._float[mach.sp]; + mach.sp++; + break; + case slang_asm_float_move: + case slang_asm_int_move: + case slang_asm_bool_move: + mach.stack._float[mach.sp + a->param[0] / 4] = + mach.stack._float[mach.sp + (mach.stack._addr[mach.sp] + a->param[1]) / 4]; + break; + case slang_asm_float_push: + case slang_asm_int_push: + case slang_asm_bool_push: + mach.sp--; + mach.stack._float[mach.sp] = a->literal; + break; + case slang_asm_float_deref: + case slang_asm_int_deref: + case slang_asm_bool_deref: + mach.stack._float[mach.sp] = *mach.stack._floatp[mach.sp]; + break; + case slang_asm_float_add: + mach.stack._float[mach.sp + 1] += mach.stack._float[mach.sp]; + mach.sp++; + break; + case slang_asm_float_multiply: + mach.stack._float[mach.sp + 1] *= mach.stack._float[mach.sp]; + mach.sp++; + break; + case slang_asm_float_divide: + mach.stack._float[mach.sp + 1] /= mach.stack._float[mach.sp]; + mach.sp++; + break; + case slang_asm_float_negate: + mach.stack._float[mach.sp] = -mach.stack._float[mach.sp]; + break; + case slang_asm_float_less: + mach.stack._float[mach.sp + 1] = + mach.stack._float[mach.sp + 1] < mach.stack._float[mach.sp] ? 1.0f : 0.0f; + mach.sp++; + break; + case slang_asm_float_equal: + mach.sp--; + mach.stack._float[mach.sp] = mach.stack._float[mach.sp + 1 + a->param[0] / 4] == + mach.stack._float[mach.sp + 1 + a->param[1] / 4] ? 1.0f : 0.0f; + break; + case slang_asm_float_to_int: + mach.stack._float[mach.sp] = (GLfloat) (GLint) mach.stack._float[mach.sp]; + break; + case slang_asm_int_to_float: + break; + case slang_asm_int_to_addr: + mach.stack._addr[mach.sp] = (GLuint) (GLint) mach.stack._float[mach.sp]; + break; + case slang_asm_addr_copy: + *mach.stack._addrp[mach.sp + 1] = mach.stack._addr[mach.sp]; + mach.sp++; + break; + case slang_asm_addr_push: + mach.sp--; + mach.stack._addr[mach.sp] = a->param[0]; + break; + case slang_asm_addr_deref: + mach.stack._addr[mach.sp] = *mach.stack._addrp[mach.sp]; + break; + case slang_asm_addr_add: + mach.stack._addr[mach.sp + 1] += mach.stack._addr[mach.sp]; + mach.sp++; + break; + case slang_asm_addr_multiply: + mach.stack._addr[mach.sp + 1] *= mach.stack._addr[mach.sp]; + mach.sp++; + break; + case slang_asm_jump: + mach.ip = a->param[0]; + break; + case slang_asm_jump_if_zero: + if (mach.stack._float[mach.sp] == 0.0f) + mach.ip = a->param[0]; + mach.sp++; + break; + case slang_asm_enter: + mach.sp--; + mach.stack._addr[mach.sp] = mach.bp; + mach.bp = mach.sp + a->param[0] / 4 + 1; + break; + case slang_asm_leave: + mach.bp = mach.stack._addr[mach.sp]; + mach.sp++; + break; + case slang_asm_local_alloc: + mach.sp -= a->param[0] / 4; + break; + case slang_asm_local_free: + mach.sp += a->param[0] / 4; + break; + case slang_asm_local_addr: + mach.sp--; + mach.stack._addr[mach.sp] = (GLuint) mach.stack._addr + mach.bp * 4 - + (a->param[0] + a->param[1]); + break; + case slang_asm_call: + mach.sp--; + mach.stack._addr[mach.sp] = mach.ip; + mach.ip = a->param[0]; + break; + case slang_asm_return: + mach.ip = mach.stack._addr[mach.sp]; + mach.sp++; + break; + case slang_asm_discard: + mach.kill = 1; + break; + case slang_asm_exit: + mach.exit = 1; + break; + } + } + +if (f != NULL) +fclose (f); + + return 0; +} + diff --git a/src/mesa/shader/slang/slang_execute.h b/src/mesa/shader/slang/slang_execute.h new file mode 100644 index 00000000000..119fd5135cb --- /dev/null +++ b/src/mesa/shader/slang/slang_execute.h @@ -0,0 +1,57 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 2005 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. + */ + +#if !defined SLANG_EXECUTE_H +#define SLANG_EXECUTE_H + +#if defined __cplusplus +extern "C" { +#endif + +#define SLANG_MACHINE_STACK_SIZE 64 + +typedef struct slang_machine_ +{ + GLuint ip; /* instruction pointer, for flow control */ + GLuint sp; /* stack pointer, for stack access */ + GLuint bp; /* base pointer, for local variable access */ + GLuint kill; /* discard the fragment */ + GLuint exit; /* terminate the shader */ + union stack_ + { + GLfloat _float[SLANG_MACHINE_STACK_SIZE]; + GLfloat *_floatp[SLANG_MACHINE_STACK_SIZE]; + GLuint _addr[SLANG_MACHINE_STACK_SIZE]; + GLuint *_addrp[SLANG_MACHINE_STACK_SIZE]; + } stack; +} slang_machine; + +int _slang_execute (const slang_assembly_file *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/shader/slang/slang_storage.c b/src/mesa/shader/slang/slang_storage.c new file mode 100644 index 00000000000..84af8d575c8 --- /dev/null +++ b/src/mesa/shader/slang/slang_storage.c @@ -0,0 +1,255 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 2005 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_storage.c + * slang variable storage + * \author Michal Krol + */ + +#include "imports.h" +#include "slang_utility.h" +#include "slang_storage.h" +#include "slang_assemble.h" + +/* slang_storage_array */ + +void slang_storage_array_construct (slang_storage_array *arr) +{ + arr->type = slang_stor_aggregate; + arr->aggregate = NULL; + arr->length = 0; +} + +void slang_storage_array_destruct (slang_storage_array *arr) +{ + if (arr->aggregate != NULL) + { + slang_storage_aggregate_destruct (arr->aggregate); + slang_alloc_free (arr->aggregate); + } +} + +/* slang_storage_aggregate */ + +void slang_storage_aggregate_construct (slang_storage_aggregate *agg) +{ + agg->arrays = NULL; + agg->count = 0; +} + +void slang_storage_aggregate_destruct (slang_storage_aggregate *agg) +{ + unsigned int i; + for (i = 0; i < agg->count; i++) + slang_storage_array_destruct (agg->arrays + i); + slang_alloc_free (agg->arrays); +} + +static slang_storage_array *slang_storage_aggregate_push_new (slang_storage_aggregate *agg) +{ + slang_storage_array *arr = NULL; + agg->arrays = (slang_storage_array *) slang_alloc_realloc (agg->arrays, agg->count * sizeof ( + slang_storage_array), (agg->count + 1) * sizeof (slang_storage_array)); + if (agg->arrays != NULL) + { + arr = agg->arrays + agg->count; + slang_storage_array_construct (arr); + agg->count++; + } + return arr; +} + +/* _slang_aggregate_variable() */ + +static int aggregate_vector (slang_storage_aggregate *agg, slang_storage_type basic_type, + unsigned int row_count) +{ + slang_storage_array *arr = slang_storage_aggregate_push_new (agg); + if (arr == NULL) + return 0; + arr->type = basic_type; + arr->length = row_count; + return 1; +} + +static int aggregate_matrix (slang_storage_aggregate *agg, slang_storage_type basic_type, + unsigned int order) +{ + slang_storage_array *arr = slang_storage_aggregate_push_new (agg); + if (arr == NULL) + return 0; + arr->type = slang_stor_aggregate; + arr->length = order; + arr->aggregate = (slang_storage_aggregate *) slang_alloc_malloc (sizeof ( + slang_storage_aggregate)); + if (arr->aggregate == NULL) + return 0; + slang_storage_aggregate_construct (arr->aggregate); + if (!aggregate_vector (arr->aggregate, basic_type, order)) + return 0; + return 1; +} + +static int aggregate_variables (slang_storage_aggregate *agg, const slang_variable_scope *vars, + slang_function_scope *funcs, slang_struct_scope *structs) +{ + unsigned int i; + for (i = 0; i < vars->num_variables; i++) + if (!_slang_aggregate_variable (agg, &vars->variables[i].type.specifier, + vars->variables[i].array_size, funcs, structs)) + return 0; + return 1; +} + +int _slang_aggregate_variable (slang_storage_aggregate *agg, slang_type_specifier *spec, + slang_operation *array_size, slang_function_scope *funcs, slang_struct_scope *structs) +{ + switch (spec->type) + { + case slang_spec_bool: + return aggregate_vector (agg, slang_stor_bool, 1); + case slang_spec_bvec2: + return aggregate_vector (agg, slang_stor_bool, 2); + case slang_spec_bvec3: + return aggregate_vector (agg, slang_stor_bool, 3); + case slang_spec_bvec4: + return aggregate_vector (agg, slang_stor_bool, 4); + case slang_spec_int: + return aggregate_vector (agg, slang_stor_int, 1); + case slang_spec_ivec2: + return aggregate_vector (agg, slang_stor_int, 2); + case slang_spec_ivec3: + return aggregate_vector (agg, slang_stor_int, 3); + case slang_spec_ivec4: + return aggregate_vector (agg, slang_stor_int, 4); + case slang_spec_float: + return aggregate_vector (agg, slang_stor_float, 1); + case slang_spec_vec2: + return aggregate_vector (agg, slang_stor_float, 2); + case slang_spec_vec3: + return aggregate_vector (agg, slang_stor_float, 3); + case slang_spec_vec4: + return aggregate_vector (agg, slang_stor_float, 4); + case slang_spec_mat2: + return aggregate_matrix (agg, slang_stor_float, 2); + case slang_spec_mat3: + return aggregate_matrix (agg, slang_stor_float, 3); + case slang_spec_mat4: + return aggregate_matrix (agg, slang_stor_float, 4); + case slang_spec_sampler1D: + case slang_spec_sampler2D: + case slang_spec_sampler3D: + case slang_spec_samplerCube: + case slang_spec_sampler1DShadow: + case slang_spec_sampler2DShadow: + return aggregate_vector (agg, slang_stor_int, 1); + case slang_spec_struct: + return aggregate_variables (agg, spec->_struct->fields, funcs, structs); + case slang_spec_array: + { + slang_storage_array *arr; + slang_assembly_file file; + slang_assembly_flow_control flow; + slang_assembly_name_space space; + slang_assembly_local_info info; + slang_assembly_stack_info stk; + + arr = slang_storage_aggregate_push_new (agg); + if (arr == NULL) + return 0; + arr->type = slang_stor_aggregate; + arr->aggregate = (slang_storage_aggregate *) slang_alloc_malloc (sizeof ( + slang_storage_aggregate)); + if (arr->aggregate == NULL) + return 0; + slang_storage_aggregate_construct (arr->aggregate); + if (!_slang_aggregate_variable (arr->aggregate, spec->_array, NULL, funcs, structs)) + return 0; + slang_assembly_file_construct (&file); + space.funcs = funcs; + space.structs = structs; + /* XXX: vars! */ + space.vars = NULL; + if (!_slang_assemble_operation (&file, array_size, 0, &flow, &space, &info, &stk)) + { + slang_assembly_file_destruct (&file); + return 0; + } + /* TODO: evaluate array size */ + slang_assembly_file_destruct (&file); + arr->length = 256; + } + return 1; + default: + return 0; + } +} + +/* _slang_sizeof_aggregate() */ + +unsigned int _slang_sizeof_aggregate (const slang_storage_aggregate *agg) +{ + unsigned int i, size = 0; + for (i = 0; i < agg->count; i++) + { + unsigned int element_size; + if (agg->arrays[i].type == slang_stor_aggregate) + element_size = _slang_sizeof_aggregate (agg->arrays[i].aggregate); + else + element_size = sizeof (GLfloat); + size += element_size * agg->arrays[i].length; + } + return size; +} + +/* _slang_flatten_aggregate () */ + +int _slang_flatten_aggregate (slang_storage_aggregate *flat, const slang_storage_aggregate *agg) +{ + unsigned int i; + for (i = 0; i < agg->count; i++) + { + unsigned int j; + for (j = 0; j < agg->arrays[i].length; j++) + { + if (agg->arrays[i].type == slang_stor_aggregate) + { + if (!_slang_flatten_aggregate (flat, agg->arrays[i].aggregate)) + return 0; + } + else + { + slang_storage_array *arr; + arr = slang_storage_aggregate_push_new (flat); + if (arr == NULL) + return 0; + arr->type = agg->arrays[i].type; + arr->length = 1; + } + } + } + return 1; +} + diff --git a/src/mesa/shader/slang/slang_storage.h b/src/mesa/shader/slang/slang_storage.h new file mode 100644 index 00000000000..c1b123f2a0a --- /dev/null +++ b/src/mesa/shader/slang/slang_storage.h @@ -0,0 +1,109 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 2005 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. + */ + +#if !defined SLANG_STORAGE_H +#define SLANG_STORAGE_H + +#include "slang_compile.h" + +#if defined __cplusplus +extern "C" { +#endif + +/* + Program variable data storage is kept completely transparent to the front-end compiler. It is + up to the back-end how the data is actually allocated. The slang_storage_type enum + provides the basic information about how the memory is interpreted. This abstract piece + of memory is called a data slot. A data slot of a particular type has a fixed size. + + For now, only the three basic types are supported, that is bool, int and float. Other built-in + types like vector or matrix can easily be decomposed into a series of basic types. +*/ +typedef enum slang_storage_type_ +{ + slang_stor_aggregate, + slang_stor_bool, + slang_stor_int, + slang_stor_float +} slang_storage_type; + +/* + The slang_storage_array structure groups data slots of the same type into an array. This + array has a fixed length. Arrays are required to have a size equal to the sum of sizes of its + elements. They are also required to support indirect addressing. That is, if B references + first data slot in the array, S is the size of the data slot and I is the integral index that + is not known at compile time, B+I*S references I-th data slot. + + This structure is also used to break down built-in data types that are not supported directly. + Vectors, like vec3, are constructed from arrays of their basic types. Matrices are formed of + an array of column vectors, which are in turn processed as other vectors. +*/ +typedef struct slang_storage_array_ +{ + slang_storage_type type; + struct slang_storage_aggregate_ *aggregate; /* slang_stor_aggregate */ + unsigned int length; +} slang_storage_array; + +void slang_storage_array_construct (slang_storage_array *); +void slang_storage_array_destruct (slang_storage_array *); + +/* + The slang_storage_aggregate structure relaxes the indirect addressing requirement for + slang_storage_array structure. Aggregates are always accessed statically - its member + addresses are well-known at compile time. For example, user-defined types are implemented as + aggregates. Aggregates can collect data of a different type. +*/ +typedef struct slang_storage_aggregate_ +{ + slang_storage_array *arrays; + unsigned int count; +} slang_storage_aggregate; + +void slang_storage_aggregate_construct (slang_storage_aggregate *); +void slang_storage_aggregate_destruct (slang_storage_aggregate *); + +int _slang_aggregate_variable (slang_storage_aggregate *, struct slang_type_specifier_ *, + struct slang_operation_ *, struct slang_function_scope_ *, slang_struct_scope *); + +/* + returns total size (in machine units) of the given aggregate + returns 0 on error +*/ +unsigned int _slang_sizeof_aggregate (const slang_storage_aggregate *); + +/* + converts structured aggregate to a flat one, with arrays of generic type being + one-element long + returns 1 on success + returns 0 otherwise +*/ +int _slang_flatten_aggregate (slang_storage_aggregate *, const slang_storage_aggregate *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/mesa/sources b/src/mesa/sources index c3165594bc6..ab0ae480889 100644 --- a/src/mesa/sources +++ b/src/mesa/sources @@ -187,8 +187,14 @@ SLANG_CPP_SOURCES = \ shader/slang/OSDependent/Linux/ossource.cpp SLANG_SOURCES = \ + shader/slang/slang_assemble.c \ + shader/slang/slang_assemble_conditional.c \ + shader/slang/slang_assemble_constructor.c \ + shader/slang/slang_assemble_typeinfo.c \ shader/slang/slang_compile.c \ + shader/slang/slang_execute.c \ shader/slang/slang_preprocess.c \ + shader/slang/slang_storage.c \ shader/slang/slang_utility.c ASM_C_SOURCES = \ -- 2.30.2