From 02eb9acc5e4307db09662592951ef44319a0cda5 Mon Sep 17 00:00:00 2001 From: Michal Krol Date: Mon, 13 Feb 2006 11:38:37 +0000 Subject: Get it running for ARB_vertex_shader. Add experimental print functions to builtin library. Some functionality missing: - automatic arrays; - general constructors; - local variable initialization; - texture sampling and noise; - semantic error checking; - function prototypes. --- src/mesa/shader/slang/slang_assemble.c | 1061 ++++++++++++-------- src/mesa/shader/slang/slang_assemble.h | 58 +- src/mesa/shader/slang/slang_assemble_assignment.c | 72 +- src/mesa/shader/slang/slang_assemble_assignment.h | 10 +- src/mesa/shader/slang/slang_assemble_conditional.c | 73 +- src/mesa/shader/slang/slang_assemble_conditional.h | 18 +- src/mesa/shader/slang/slang_assemble_constructor.c | 114 +-- src/mesa/shader/slang/slang_assemble_constructor.h | 17 +- src/mesa/shader/slang/slang_assemble_typeinfo.c | 367 ++++--- src/mesa/shader/slang/slang_assemble_typeinfo.h | 18 +- src/mesa/shader/slang/slang_compile.c | 958 +++++++++++------- src/mesa/shader/slang/slang_compile.h | 12 +- src/mesa/shader/slang/slang_compile_function.c | 11 +- src/mesa/shader/slang/slang_compile_function.h | 2 +- src/mesa/shader/slang/slang_compile_operation.c | 15 +- src/mesa/shader/slang/slang_compile_operation.h | 2 +- src/mesa/shader/slang/slang_compile_struct.c | 32 +- src/mesa/shader/slang/slang_compile_struct.h | 4 +- src/mesa/shader/slang/slang_compile_variable.c | 27 +- src/mesa/shader/slang/slang_compile_variable.h | 6 +- src/mesa/shader/slang/slang_execute.c | 246 +++-- src/mesa/shader/slang/slang_execute.h | 9 +- src/mesa/shader/slang/slang_preprocess.c | 5 +- src/mesa/shader/slang/slang_storage.c | 134 ++- src/mesa/shader/slang/slang_storage.h | 7 +- src/mesa/shader/slang/slang_utility.c | 87 +- src/mesa/shader/slang/slang_utility.h | 41 +- 27 files changed, 2060 insertions(+), 1346 deletions(-) (limited to 'src/mesa/shader') diff --git a/src/mesa/shader/slang/slang_assemble.c b/src/mesa/shader/slang/slang_assemble.c index a97da6b283..45b6b1961c 100644 --- a/src/mesa/shader/slang/slang_assemble.c +++ b/src/mesa/shader/slang/slang_assemble.c @@ -31,18 +31,20 @@ #include "imports.h" #include "slang_utility.h" #include "slang_assemble.h" -#include "slang_compile.h" +/*#include "slang_compile.h"*/ #include "slang_storage.h" -#include "slang_assemble_constructor.h" +/*#include "slang_assemble_constructor.h"*/ #include "slang_assemble_typeinfo.h" #include "slang_assemble_conditional.h" #include "slang_assemble_assignment.h" +#include "slang_execute.h" /* slang_assembly */ -static void slang_assembly_construct (slang_assembly *assem) +static int slang_assembly_construct (slang_assembly *assem) { assem->type = slang_asm_none; + return 1; } static void slang_assembly_destruct (slang_assembly *assem) @@ -51,10 +53,12 @@ static void slang_assembly_destruct (slang_assembly *assem) /* slang_assembly_file */ -void slang_assembly_file_construct (slang_assembly_file *file) +int slang_assembly_file_construct (slang_assembly_file *file) { file->code = NULL; file->count = 0; + file->capacity = 0; + return 1; } void slang_assembly_file_destruct (slang_assembly_file *file) @@ -62,30 +66,40 @@ 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_assembly_destruct (&file->code[i]); slang_alloc_free (file->code); } -static int slang_assembly_file_push_new (slang_assembly_file *file) +static int 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) + if (file->count == file->capacity) { - slang_assembly_construct (file->code + file->count); - file->count++; - return 1; + unsigned int n; + + if (file->capacity == 0) + n = 256; + else + n = file->capacity * 2; + file->code = (slang_assembly *) slang_alloc_realloc (file->code, + file->capacity * sizeof (slang_assembly), n * sizeof (slang_assembly)); + if (file->code == NULL) + return 0; + file->capacity = n; } - return 0; + if (!slang_assembly_construct (&file->code[file->count])) + return 0; + file->count++; + return 1; } -static int slang_assembly_file_push_general (slang_assembly_file *file, slang_assembly_type type, - GLfloat literal, GLuint label, GLuint size) +static int push_gen (slang_assembly_file *file, slang_assembly_type type, GLfloat literal, + GLuint label, GLuint size) { slang_assembly *assem; - if (!slang_assembly_file_push_new (file)) + + if (!push_new (file)) return 0; - assem = file->code + file->count - 1; + assem = &file->code[file->count - 1]; assem->type = type; assem->literal = literal; assem->param[0] = label; @@ -95,102 +109,138 @@ static int slang_assembly_file_push_general (slang_assembly_file *file, slang_as 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); + return push_gen (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); + return push_gen (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); + return push_gen (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); + return push_gen (file, type, literal, 0, 0); +} + +#define PUSH slang_assembly_file_push +#define PLAB slang_assembly_file_push_label +#define PLAB2 slang_assembly_file_push_label2 +#define PLIT slang_assembly_file_push_literal + +/* slang_assembly_file_restore_point */ + +int slang_assembly_file_restore_point_save (slang_assembly_file *file, + slang_assembly_file_restore_point *point) +{ + point->count = file->count; + return 1; +} + +int slang_assembly_file_restore_point_load (slang_assembly_file *file, + slang_assembly_file_restore_point *point) +{ + unsigned int i; + + for (i = point->count; i < file->count; i++) + slang_assembly_destruct (&file->code[i]); + file->count = point->count; + return 1; } /* utility functions */ static int sizeof_variable (slang_type_specifier *spec, slang_type_qualifier qual, - slang_operation *array_size, slang_assembly_name_space *space, unsigned int *size) + slang_operation *array_size, slang_assembly_name_space *space, unsigned int *size, + slang_machine *mach, slang_assembly_file *pfile, slang_atom_pool *atoms) { slang_storage_aggregate agg; - slang_storage_aggregate_construct (&agg); - if (!_slang_aggregate_variable (&agg, spec, array_size, space->funcs, space->structs, space->vars)) + /* calculate the size of the variable's aggregate */ + if (!slang_storage_aggregate_construct (&agg)) + return 0; + if (!_slang_aggregate_variable (&agg, spec, array_size, space->funcs, space->structs, + space->vars, mach, pfile, atoms)) { slang_storage_aggregate_destruct (&agg); return 0; } *size += _slang_sizeof_aggregate (&agg); + slang_storage_aggregate_destruct (&agg); + + /* for reference variables consider the additional address overhead */ if (qual == slang_qual_out || qual == slang_qual_inout) *size += 4; - slang_storage_aggregate_destruct (&agg); return 1; } static int sizeof_variable2 (slang_variable *var, slang_assembly_name_space *space, - unsigned int *size) + unsigned int *size, slang_machine *mach, slang_assembly_file *pfile, slang_atom_pool *atoms) { var->address = *size; if (var->type.qualifier == slang_qual_out || var->type.qualifier == slang_qual_inout) var->address += 4; return sizeof_variable (&var->type.specifier, var->type.qualifier, var->array_size, space, - size); + size, mach, pfile, atoms); } static int sizeof_variables (slang_variable_scope *vars, unsigned int start, unsigned int stop, - slang_assembly_name_space *space, unsigned int *size) + slang_assembly_name_space *space, unsigned int *size, slang_machine *mach, + slang_assembly_file *pfile, slang_atom_pool *atoms) { unsigned int i; for (i = start; i < stop; i++) - if (!sizeof_variable2 (vars->variables + i, space, size)) + if (!sizeof_variable2 (&vars->variables[i], space, size, mach, pfile, atoms)) return 0; return 1; } static int collect_locals (slang_operation *op, slang_assembly_name_space *space, - unsigned int *size) + unsigned int *size, slang_machine *mach, slang_assembly_file *pfile, slang_atom_pool *atoms) { unsigned int i; - if (!sizeof_variables (op->locals, 0, op->locals->num_variables, space, size)) + if (!sizeof_variables (op->locals, 0, op->locals->num_variables, space, size, mach, pfile, + atoms)) return 0; for (i = 0; i < op->num_children; i++) - if (!collect_locals (op->children + i, space, size)) + if (!collect_locals (&op->children[i], space, size, mach, pfile, atoms)) 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) +slang_function *_slang_locate_function (slang_function_scope *funcs, slang_atom a_name, + slang_operation *params, unsigned int num_params, slang_assembly_name_space *space, + slang_atom_pool *atoms) { unsigned int i; - for (i = 0; i < space->funcs->num_functions; i++) + for (i = 0; i < funcs->num_functions; i++) { unsigned int j; - slang_function *f = space->funcs->functions + i; + slang_function *f = &funcs->functions[i]; - if (slang_string_compare (name, f->header.name) != 0) + if (a_name != f->header.a_name) 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)) + + if (!slang_assembly_typeinfo_construct (&ti)) + return 0; + if (!_slang_typeof_operation (¶ms[j], space, &ti, atoms)) { slang_assembly_typeinfo_destruct (&ti); return 0; @@ -201,28 +251,25 @@ slang_function *_slang_locate_function (const char *name, slang_operation *param 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)) + (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); - } + if (funcs->outer_scope != NULL) + return _slang_locate_function (funcs->outer_scope, a_name, params, num_params, space, atoms); return NULL; } /* _slang_assemble_function() */ int _slang_assemble_function (slang_assembly_file *file, slang_function *fun, - slang_assembly_name_space *space) + slang_assembly_name_space *space, slang_machine *mach, slang_atom_pool *atoms) { unsigned int param_size, local_size; unsigned int skip, cleanup; @@ -238,97 +285,106 @@ int _slang_assemble_function (slang_assembly_file *file, slang_function *fun, return 1; } - /* calculate return value and parameters size */ + /* At this point traverse function formal parameters and code to calculate + * total memory size to be allocated on the stack. + * During this process the variables will be assigned local addresses to + * reference them in the code. + * No storage optimizations are performed so exclusive scopes are not detected and shared. */ + + /* calculate return value size */ param_size = 0; if (fun->header.type.specifier.type != slang_spec_void) if (!sizeof_variable (&fun->header.type.specifier, slang_qual_none, NULL, space, - ¶m_size)) + ¶m_size, mach, file, atoms)) return 0; info.ret_size = param_size; - if (!sizeof_variables (fun->parameters, 0, fun->param_count, space, ¶m_size)) + + /* calculate formal parameter list size */ + if (!sizeof_variables (fun->parameters, 0, fun->param_count, space, ¶m_size, mach, file, + atoms)) return 0; - /* calculate local variables size, take into account the four-byte return address and - temporaries for various tasks */ + /* calculate local variables size - take into account the four-byte return address and + * temporaries for various tasks (4 for addr and 16 for swizzle temporaries). + * these include variables from the formal parameter scope and from the code */ 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)) + &local_size, mach, file, atoms)) return 0; - if (!collect_locals (fun->body, space, &local_size)) + if (!collect_locals (fun->body, space, &local_size, mach, file, atoms)) return 0; /* allocate local variable storage */ - if (!slang_assembly_file_push_label (file, slang_asm_local_alloc, local_size - param_size - 4)) + if (!PLAB (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)) + if (!PLAB (file, slang_asm_enter, local_size)) return 0; - /* skip the cleanup jump */ + /* jump directly to the actual code */ skip = file->count; - if (!slang_assembly_file_push_new (file)) + if (!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)) + if (!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)) + if (!_slang_assemble_operation (file, fun->body, 0, &flow, space, &info, &stk, mach, atoms)) 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)) + if (!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)) + if (!PLAB (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 from the function */ + if (!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_name_space *space, slang_machine *mach, slang_atom_pool *atoms) { slang_assembly_typeinfo ti; - unsigned int size; + unsigned int size = 0; - slang_assembly_typeinfo_construct (&ti); - if (!_slang_typeof_operation (op, space, &ti)) + /* get type info of the operation and calculate its size */ + if (!slang_assembly_typeinfo_construct (&ti)) + return 0; + if (!_slang_typeof_operation (op, space, &ti, atoms)) { slang_assembly_typeinfo_destruct (&ti); return 0; } - if (ti.spec.type == slang_spec_void) - size = 0; - else if (ref) + if (ref) size = 4; - else - { - size = 0; - if (!sizeof_variable (&ti.spec, slang_qual_none, NULL, space, &size)) + else if (ti.spec.type != slang_spec_void) + if (!sizeof_variable (&ti.spec, slang_qual_none, NULL, space, &size, mach, file, atoms)) { slang_assembly_typeinfo_destruct (&ti); return 0; } - } slang_assembly_typeinfo_destruct (&ti); + + /* if nonzero, free it from the stack */ if (size != 0) { - if (!slang_assembly_file_push_label (file, slang_asm_local_free, size)) + if (!PLAB (file, slang_asm_local_free, size)) return 0; } return 1; @@ -336,103 +392,133 @@ int _slang_cleanup_stack (slang_assembly_file *file, slang_operation *op, int re /* _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 *size, slang_assembly_local_info *info, slang_swizzle *swz, int is_swizzled) { unsigned int i; for (i = agg->count; i > 0; i--) { - const slang_storage_array *arr = agg->arrays + i - 1; + 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)) + if (!dereference_aggregate (file, arr->aggregate, size, info, swz, is_swizzled)) return 0; } else { + unsigned int src_offset; + slang_assembly_type ty; + *size -= 4; - if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, info->addr_tmp, - 4)) + + /* calculate the offset within source variable to read */ + if (is_swizzled) + { + /* swizzle the index to get the actual offset */ + src_offset = swz->swizzle[*size / 4] * 4; + } + else + { + /* no swizzling - read sequentially */ + src_offset = *size; + } + + /* dereference data slot of a basic type */ + if (!PLAB2 (file, slang_asm_local_addr, info->addr_tmp, 4)) return 0; - if (!slang_assembly_file_push (file, slang_asm_addr_deref)) + if (!PUSH (file, slang_asm_addr_deref)) return 0; - if (!slang_assembly_file_push_label (file, slang_asm_addr_push, *size)) + if (!PLAB (file, slang_asm_addr_push, src_offset)) return 0; - if (!slang_assembly_file_push (file, slang_asm_addr_add)) + if (!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; + ty = slang_asm_bool_deref; break; case slang_stor_int: - if (!slang_assembly_file_push (file, slang_asm_int_deref)) - return 0; + ty = slang_asm_int_deref; break; case slang_stor_float: - if (!slang_assembly_file_push (file, slang_asm_float_deref)) - return 0; + ty = slang_asm_float_deref; break; } - index += 4; + if (!PUSH (file, ty)) + return 0; } } } return 1; } -/* XXX: general swizzle! */ -int dereference (slang_assembly_file *file, slang_operation *op, - slang_assembly_name_space *space, slang_assembly_local_info *info) + +int _slang_dereference (slang_assembly_file *file, slang_operation *op, + slang_assembly_name_space *space, slang_assembly_local_info *info, slang_machine *mach, + slang_atom_pool *atoms) { 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)) + /* get type information of the given operation */ + if (!slang_assembly_typeinfo_construct (&ti)) + return 0; + if (!_slang_typeof_operation (op, space, &ti, atoms)) { slang_assembly_typeinfo_destruct (&ti); return 0; } - slang_storage_aggregate_construct (&agg); - if (!_slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs, space->vars)) + /* construct aggregate from the type info */ + if (!slang_storage_aggregate_construct (&agg)) + { + slang_assembly_typeinfo_destruct (&ti); + return 0; + } + if (!_slang_aggregate_variable (&agg, &ti.spec, ti.array_size, space->funcs, space->structs, + space->vars, mach, file, atoms)) { slang_storage_aggregate_destruct (&agg); slang_assembly_typeinfo_destruct (&ti); return 0; } + /* dereference the resulting aggregate */ size = _slang_sizeof_aggregate (&agg); - result = dereference_aggregate (file, &agg, 0, &size, info); + result = dereference_aggregate (file, &agg, &size, info, &ti.swz, ti.is_swizzled); 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, +int _slang_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) + slang_assembly_local_info *info, slang_machine *mach, slang_atom_pool *atoms) { unsigned int i; - slang_assembly_stack_info stk; + slang_assembly_stack_info p_stk[64]; + + /* TODO: fix this, allocate dynamically */ + if (param_count > 64) + return 0; /* make room for the return value, if any */ if (fun->header.type.specifier.type != slang_spec_void) { unsigned int ret_size = 0; - if (!sizeof_variable (&fun->header.type.specifier, slang_qual_none, NULL, space, &ret_size)) + + if (!sizeof_variable (&fun->header.type.specifier, slang_qual_none, NULL, space, + &ret_size, mach, file, atoms)) return 0; - if (!slang_assembly_file_push_label (file, slang_asm_local_alloc, ret_size)) + if (!PLAB (file, slang_asm_local_alloc, ret_size)) return 0; } @@ -444,56 +530,59 @@ static int call_function (slang_assembly_file *file, slang_function *fun, slang_ if (fun->parameters->variables[i].type.qualifier == slang_qual_inout || fun->parameters->variables[i].type.qualifier == slang_qual_out) { - if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, info->addr_tmp, 4)) + if (!PLAB2 (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 + i, 1, &flow, space, info, &stk)) + if (!_slang_assemble_operation (file, ¶ms[i], 1, &flow, space, info, &p_stk[i], + mach, atoms)) return 0; - if (!slang_assembly_file_push (file, slang_asm_addr_copy)) + if (!PUSH (file, slang_asm_addr_copy)) return 0; - if (!slang_assembly_file_push (file, slang_asm_addr_deref)) + if (!PUSH (file, slang_asm_addr_deref)) return 0; if (i == 0 && assignment) { - if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, info->addr_tmp, - 4)) + /* duplicate the resulting address */ + if (!PLAB2 (file, slang_asm_local_addr, info->addr_tmp, 4)) return 0; - if (!slang_assembly_file_push (file, slang_asm_addr_deref)) + if (!PUSH (file, slang_asm_addr_deref)) return 0; } - if (!dereference (file, params, space, info)) + if (!_slang_dereference (file, ¶ms[i], space, info, mach, atoms)) 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)) + if (!_slang_assemble_operation (file, ¶ms[i], 0, &flow, space, info, &p_stk[i], + mach, atoms)) return 0; } } /* call the function */ - if (!slang_assembly_file_push_label (file, slang_asm_call, fun->address)) + if (!PLAB (file, slang_asm_call, fun->address)) return 0; /* pop the parameters from the stack */ for (i = param_count; i > 0; i--) { unsigned int j = i - 1; + if (fun->parameters->variables[j].type.qualifier == slang_qual_inout || fun->parameters->variables[j].type.qualifier == slang_qual_out) { - if (!_slang_assemble_assignment (file, params + j, space, info)) + /* for output parameter copy the contents of the formal parameter + * back to the original actual parameter */ + if (!_slang_assemble_assignment (file, ¶ms[j], space, info, &p_stk[j], mach, atoms)) return 0; - if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4)) + /* pop the actual parameter's address */ + if (!PLAB (file, slang_asm_local_free, 4)) return 0; } else { - if (!_slang_cleanup_stack (file, params + j, 0, space)) + /* pop the value of the parameter */ + if (!_slang_cleanup_stack (file, ¶ms[j], 0, space, mach, atoms)) return 0; } } @@ -501,73 +590,94 @@ static int call_function (slang_assembly_file *file, slang_function *fun, slang_ return 1; } +/* TODO: migrate to full-atom version */ 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_assembly_local_info *info, slang_machine *mach, slang_atom_pool *atoms) { - slang_function *fun = _slang_locate_function (name, params, param_count, space); + slang_atom atom; + slang_function *fun; + + atom = slang_atom_pool_atom (atoms, name); + if (atom == SLANG_ATOM_NULL) + return 0; + fun = _slang_locate_function (space->funcs, atom, params, param_count, space, atoms); if (fun == NULL) return 0; - return call_function (file, fun, params, param_count, assignment, space, info); + return _slang_call_function (file, fun, params, param_count, assignment, space, info, mach, + atoms); } 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 *params, slang_assembly_name_space *space, slang_assembly_local_info *info, + slang_machine *mach, slang_atom_pool *atoms) { - slang_operation p2[2]; + slang_operation p[2]; int result; - p2[0] = *params; - if (!slang_operation_construct (p2 + 1)) + p[0] = params[0]; + if (!slang_operation_construct (&p[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); + p[1].type = slang_oper_literal_int; + result = call_function_name (file, name, p, 2, 0, space, info, mach, atoms); + slang_operation_destruct (&p[1]); return result; } -static int call_asm_instruction (slang_assembly_file *file, const char *name) +static const struct { - 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 } - }; + const char *name; + slang_assembly_type code1, code2; +} inst[] = { + /* core */ + { "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_exp,slang_asm_bool_copy }, + { "float_to_int", slang_asm_float_to_int, slang_asm_int_copy }, + { "float_sine", slang_asm_float_sine, slang_asm_float_copy }, + { "float_arcsine", slang_asm_float_arcsine, slang_asm_float_copy }, + { "float_arctan", slang_asm_float_arctan, slang_asm_float_copy }, + { "float_power", slang_asm_float_power, slang_asm_float_copy }, + { "float_log2", slang_asm_float_log2, slang_asm_float_copy }, + { "float_floor", slang_asm_float_floor, slang_asm_float_copy }, + { "float_ceil", slang_asm_float_ceil, slang_asm_float_copy }, + { "int_to_float", slang_asm_int_to_float, slang_asm_float_copy }, + /* mesa-specific extensions */ + { "float_print", slang_asm_float_deref, slang_asm_float_print }, + { "int_print", slang_asm_int_deref, slang_asm_int_print }, + { "bool_print", slang_asm_bool_deref, slang_asm_bool_print }, + { NULL, slang_asm_none, slang_asm_none } +}; + +static int call_asm_instruction (slang_assembly_file *file, slang_atom a_name, slang_atom_pool *atoms) +{ + const char *id; unsigned int i; + id = slang_atom_pool_id (atoms, a_name); + for (i = 0; inst[i].name != NULL; i++) - if (slang_string_compare (name, inst[i].name) == 0) + if (slang_string_compare (id, inst[i].name) == 0) break; if (inst[i].name == NULL) return 0; - if (!slang_assembly_file_push_label2 (file, inst[i].code1, 4, 0)) + if (!PLAB2 (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)) + if (!PLAB2 (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)) + if (!PLAB (file, slang_asm_local_free, 4)) return 0; return 1; } -/* 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) { @@ -575,7 +685,7 @@ static int equality_aggregate (slang_assembly_file *file, const slang_storage_ag for (i = 0; i < agg->count; i++) { - const slang_storage_array *arr = agg->arrays + i; + const slang_storage_array *arr = &agg->arrays[i]; unsigned int j; for (j = 0; j < arr->length; j++) @@ -587,39 +697,38 @@ static int equality_aggregate (slang_assembly_file *file, const slang_storage_ag } else { - if (!slang_assembly_file_push_label2 (file, slang_asm_float_equal, size + *index, - *index)) + if (!PLAB2 (file, slang_asm_float_equal_int, size + *index, *index)) return 0; *index += 4; - if (!slang_assembly_file_push_label (file, slang_asm_jump_if_zero, z_label)) + if (!PLAB (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_name_space *space, slang_assembly_local_info *info, int equal, + slang_machine *mach, slang_atom_pool *atoms) { slang_assembly_typeinfo ti; - int result; + int result = 0; 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); + if (!slang_assembly_typeinfo_construct (&ti)) return 0; - } + if (!_slang_typeof_operation (op, space, &ti, atoms)) + goto end1; /* convert it to an aggregate */ - slang_storage_aggregate_construct (&agg); - if (!(result = _slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs, - space->vars))) + if (!slang_storage_aggregate_construct (&agg)) + goto end1; + if (!_slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs, + space->vars, mach, file, atoms)) goto end; /* compute the size of the agregate - there are two such aggregates on the stack */ @@ -627,37 +736,35 @@ static int equality (slang_assembly_file *file, slang_operation *op, /* jump to the actual data-comparison code */ skip_jump = file->count; - if (!(result = slang_assembly_file_push (file, slang_asm_jump))) + if (!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))) + if (!PLAB (file, slang_asm_local_free, size * 2)) goto end; - if (!(result = slang_assembly_file_push_literal (file, slang_asm_bool_push, 1.0f))) + if (!PLIT (file, slang_asm_bool_push, (GLfloat) 1)) goto end; true_jump = file->count; - if (!(result = slang_assembly_file_push (file, slang_asm_jump))) + if (!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))) + if (!PLAB (file, slang_asm_local_free, size * 2)) goto end; - if (!(result = slang_assembly_file_push_literal (file, slang_asm_bool_push, 0.0f))) + if (!PLIT (file, slang_asm_bool_push, (GLfloat) 0)) goto end; false_jump = file->count; - if (!(result = slang_assembly_file_push (file, slang_asm_jump))) + if (!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))) + if (!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))) + if (!PLAB (file, slang_asm_jump, equal ? true_label : false_label)) goto end; file->code[true_jump].param[0] = file->count; @@ -666,20 +773,245 @@ static int equality (slang_assembly_file *file, slang_operation *op, result = 1; end: slang_storage_aggregate_destruct (&agg); +end1: slang_assembly_typeinfo_destruct (&ti); return result; } +static int handle_subscript (slang_assembly_typeinfo *tie, slang_assembly_typeinfo *tia, + 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_machine *mach, + slang_atom_pool *atoms) +{ + unsigned int asize = 0, esize = 0; + slang_assembly_stack_info _stk; + + /* get type info of the master expression (matrix, vector or an array */ + if (!_slang_typeof_operation (&op->children[0], space, tia, atoms)) + return 0; + if (!sizeof_variable (&tia->spec, slang_qual_none, tia->array_size, space, &asize, mach, file, + atoms)) + return 0; + + /* get type info of the result (matrix column, vector row or array element) */ + if (!_slang_typeof_operation (op, space, tie, atoms)) + return 0; + if (!sizeof_variable (&tie->spec, slang_qual_none, NULL, space, &esize, mach, file, atoms)) + return 0; + + /* assemble the master expression */ + if (!_slang_assemble_operation (file, &op->children[0], reference, flow, space, info, &_stk, + mach, atoms)) + return 0; + /* ignre the _stk */ + + /* when indexing an l-value swizzle, push the swizzle_tmp */ + if (reference && tia->is_swizzled) + { + if (!PLAB2 (file, slang_asm_local_addr, info->swizzle_tmp, 16)) + return 0; + } + + /* assemble the subscript expression */ + if (!_slang_assemble_operation (file, &op->children[1], 0, flow, space, info, &_stk, mach, atoms)) + return 0; + /* ignore the _stk */ + + if (reference && tia->is_swizzled) + { + unsigned int i; + + /* copy the swizzle indexes to the swizzle_tmp */ + for (i = 0; i < tia->swz.num_components; i++) + { + if (!PLAB2 (file, slang_asm_local_addr, info->swizzle_tmp, 16)) + return 0; + if (!PLAB (file, slang_asm_addr_push, i * 4)) + return 0; + if (!PUSH (file, slang_asm_addr_add)) + return 0; + if (!PLAB (file, slang_asm_addr_push, tia->swz.swizzle[i])) + return 0; + if (!PUSH (file, slang_asm_addr_copy)) + return 0; + if (!PLAB (file, slang_asm_local_free, 4)) + return 0; + } + + /* offset the pushed swizzle_tmp address and dereference it */ + if (!PUSH (file, slang_asm_int_to_addr)) + return 0; + if (!PLAB (file, slang_asm_addr_push, 4)) + return 0; + if (!PUSH (file, slang_asm_addr_multiply)) + return 0; + if (!PUSH (file, slang_asm_addr_add)) + return 0; + if (!PUSH (file, slang_asm_addr_deref)) + return 0; + } + else + { + /* convert the integer subscript to a relative address */ + if (!PUSH (file, slang_asm_int_to_addr)) + return 0; + } + + if (!PLAB (file, slang_asm_addr_push, esize)) + return 0; + if (!PUSH (file, slang_asm_addr_multiply)) + return 0; + + if (reference) + { + /* offset the base address with the relative address */ + if (!PUSH (file, slang_asm_addr_add)) + return 0; + } + else + { + unsigned int i; + + /* move the selected element to the beginning of the master expression */ + for (i = 0; i < esize; i += 4) + if (!PLAB2 (file, slang_asm_float_move, asize - esize + i + 4, i + 4)) + return 0; + if (!PLAB (file, slang_asm_local_free, 4)) + return 0; + + /* free the rest of the master expression */ + if (!PLAB (file, slang_asm_local_free, asize - esize)) + return 0; + } + return 1; +} + +static int handle_field (slang_assembly_typeinfo *tia, slang_assembly_typeinfo *tib, + 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, + slang_machine *mach, slang_atom_pool *atoms) +{ + slang_assembly_stack_info _stk; + + /* get type info of the result (field or swizzle) */ + if (!_slang_typeof_operation (op, space, tia, atoms)) + return 0; + + /* get type info of the master expression being accessed (struct or vector) */ + if (!_slang_typeof_operation (&op->children[0], space, tib, atoms)) + return 0; + + /* if swizzling a vector in-place, the swizzle temporary is needed */ + if (!reference && tia->is_swizzled) + if (!PLAB2 (file, slang_asm_local_addr, info->swizzle_tmp, 16)) + return 0; + + /* assemble the master expression */ + if (!_slang_assemble_operation (file, &op->children[0], reference, flow, space, info, &_stk, + mach, atoms)) + return 0; + /* ignore _stk.swizzle - we'll have it in tia->swz */ + + /* assemble the field expression */ + if (tia->is_swizzled) + { + if (reference) + { + /*if (tia->swz.num_components == 1) + { + /* simple case - adjust the vector's address to point to the selected component */ + /* if (!PLAB (file, slang_asm_addr_push, tia->swz.swizzle[0] * 4)) + return 0; + if (!PUSH (file, slang_asm_addr_add)) + return 0; + } + else*/ + { + /* two or more vector components are being referenced - the so-called write mask + * must be passed to the upper operations and applied when assigning value + * to this swizzle */ + stk->swizzle = tia->swz; + } + } + else + { + /* swizzle the vector in-place using the swizzle temporary */ + if (!_slang_assemble_constructor_from_swizzle (file, &tia->swz, &tia->spec, &tib->spec, + info)) + return 0; + } + } + else + { + GLuint i, struct_size = 0, field_offset = 0, field_size = 0; + + for (i = 0; i < tib->spec._struct->fields->num_variables; i++) + { + slang_variable *field; + slang_storage_aggregate agg; + GLuint size; + + field = &tib->spec._struct->fields->variables[i]; + if (!slang_storage_aggregate_construct (&agg)) + return 0; + if (!_slang_aggregate_variable (&agg, &field->type.specifier, field->array_size, + space->funcs, space->structs, space->vars, mach, file, atoms)) + { + slang_storage_aggregate_destruct (&agg); + return 0; + } + size = _slang_sizeof_aggregate (&agg); + slang_storage_aggregate_destruct (&agg); + + if (op->a_id == field->a_name) + { + field_size = size; + struct_size = field_offset + size; + } + else if (struct_size != 0) + struct_size += size; + else + field_offset += size; + } + + if (!PLAB (file, slang_asm_addr_push, field_offset)) + return 0; + + if (reference) + { + if (!PUSH (file, slang_asm_addr_add)) + return 0; + } + else + { + unsigned int i; + + /* move the selected element to the beginning of the master expression */ + for (i = 0; i < field_size; i += 4) + if (!PLAB2 (file, slang_asm_float_move, struct_size - field_size + i + 4, i + 4)) + return 0; + if (!PLAB (file, slang_asm_local_free, 4)) + return 0; + + /* free the rest of the master expression */ + if (!PLAB (file, slang_asm_local_free, struct_size - field_size)) + return 0; + } + } + return 1; +} + 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) + slang_assembly_local_info *info, slang_assembly_stack_info *stk, slang_machine *mach, + slang_atom_pool *atoms) { unsigned int assem; - stk->swizzle_mask = 0; + stk->swizzle.num_components = 0; assem = file->count; - if (!slang_assembly_file_push_new (file)) + if (!push_new (file)) return 0; switch (op->type) @@ -688,13 +1020,16 @@ int _slang_assemble_operation (slang_assembly_file *file, slang_operation *op, i 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)) + + if (!_slang_assemble_operation (file, &op->children[i], 0, flow, space, info, &stk, + mach, atoms)) return 0; - /* TODO: pass-in stk to cleanup */ - if (!_slang_cleanup_stack (file, op->children + i, 0, space)) + /* ignore the stk */ + if (!_slang_cleanup_stack (file, &op->children[i], 0, space, mach, atoms)) return 0; } } @@ -713,15 +1048,17 @@ int _slang_assemble_operation (slang_assembly_file *file, slang_operation *op, i 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)) + + if (!_slang_assemble_operation (file, &op->children[i], i == 0, flow, space, info, + &stk, mach, atoms)) return 0; - /* TODO: inspect stk */ + /* __asm statement does not support any swizzles, so lets ignore stk for now */ } - if (!call_asm_instruction (file, op->identifier)) + if (!call_asm_instruction (file, op->a_id, atoms)) return 0; } break; @@ -735,48 +1072,57 @@ int _slang_assemble_operation (slang_assembly_file *file, slang_operation *op, i break; case slang_oper_discard: file->code[assem].type = slang_asm_discard; - if (!slang_assembly_file_push (file, slang_asm_exit)) + if (!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)) + + /* push the result's address */ + if (!PLAB2 (file, slang_asm_local_addr, 0, info->ret_size)) return 0; - if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + if (!_slang_assemble_operation (file, &op->children[0], 0, flow, space, info, &stk, + mach, atoms)) return 0; - /* TODO: inspect stk */ - if (!_slang_assemble_assignment (file, op->children, space, info)) + + /* ignore the stk from latest operation, reset swizzle to 0 for the assignment */ + stk.swizzle.num_components = 0; + /* assign the operation to the function result (it was reserved on the stack) */ + if (!_slang_assemble_assignment (file, op->children, space, info, &stk, mach, atoms)) return 0; - if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4)) + + if (!PLAB (file, slang_asm_local_free, 4)) return 0; } - if (!slang_assembly_file_push_label (file, slang_asm_jump, flow->function_end)) + if (!PLAB (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)) + + assert (!reference); + if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk, mach, atoms)) return 0; - /* TODO: inspect stk */ + /* ignore the stk info */ } break; case slang_oper_if: - if (!_slang_assemble_if (file, op, flow, space, info)) + if (!_slang_assemble_if (file, op, flow, space, info, mach, atoms)) return 0; break; case slang_oper_while: - if (!_slang_assemble_while (file, op, flow, space, info)) + if (!_slang_assemble_while (file, op, flow, space, info, mach, atoms)) return 0; break; case slang_oper_do: - if (!_slang_assemble_do (file, op, flow, space, info)) + if (!_slang_assemble_do (file, op, flow, space, info, mach, atoms)) return 0; break; case slang_oper_for: - if (!_slang_assemble_for (file, op, flow, space, info)) + if (!_slang_assemble_for (file, op, flow, space, info, mach, atoms)) return 0; break; case slang_oper_void: @@ -797,69 +1143,75 @@ int _slang_assemble_operation (slang_assembly_file *file, slang_operation *op, i { slang_variable *var; unsigned int size; - var = _slang_locate_variable (op->locals, op->identifier, 1); + + /* find the variable and calculate its size */ + var = _slang_locate_variable (op->locals, op->a_id, 1); if (var == NULL) return 0; size = 0; if (!sizeof_variable (&var->type.specifier, slang_qual_none, var->array_size, space, - &size)) + &size, mach, file, atoms)) return 0; - if (var->initializer != NULL) + + /* prepare stack for dereferencing */ + if (!reference) + if (!PLAB2 (file, slang_asm_local_addr, info->addr_tmp, 4)) + return 0; + + /* push the variable's address */ + if (var->global) { - assert (!"var->initializer, oper_identifier"); + if (!PLAB (file, slang_asm_addr_push, var->address)) + return 0; } 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)) + if (!PLAB2 (file, slang_asm_local_addr, var->address, size)) + return 0; + } + + /* perform the dereference */ + if (!reference) + { + if (!PUSH (file, slang_asm_addr_copy)) + return 0; + if (!PLAB (file, slang_asm_local_free, 4)) + return 0; + if (!_slang_dereference (file, op, space, info, mach, atoms)) 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)) + + if (!_slang_assemble_operation (file, &op->children[0], 0, flow, space, info, &stk, + mach, atoms)) return 0; /* TODO: pass-in stk to cleanup */ - if (!_slang_cleanup_stack (file, op->children, 0, space)) + if (!_slang_cleanup_stack (file, &op->children[0], 0, space, mach, atoms)) return 0; - if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, - &stk)) + if (!_slang_assemble_operation (file, &op->children[1], 0, flow, space, info, + &stk, mach, atoms)) return 0; /* TODO: inspect stk */ } break; case slang_oper_assign: - if (!_slang_assemble_assign (file, op, "=", reference, space, info)) + if (!_slang_assemble_assign (file, op, "=", reference, space, info, mach, atoms)) return 0; break; case slang_oper_addassign: - if (!_slang_assemble_assign (file, op, "+=", reference, space, info)) + if (!_slang_assemble_assign (file, op, "+=", reference, space, info, mach, atoms)) return 0; break; case slang_oper_subassign: - if (!_slang_assemble_assign (file, op, "-=", reference, space, info)) + if (!_slang_assemble_assign (file, op, "-=", reference, space, info, mach, atoms)) return 0; break; case slang_oper_mulassign: - if (!_slang_assemble_assign (file, op, "*=", reference, space, info)) + if (!_slang_assemble_assign (file, op, "*=", reference, space, info, mach, atoms)) return 0; break; /*case slang_oper_modassign:*/ @@ -869,214 +1221,149 @@ int _slang_assemble_operation (slang_assembly_file *file, slang_operation *op, i /*case slang_oper_xorassign:*/ /*case slang_oper_andassign:*/ case slang_oper_divassign: - if (!_slang_assemble_assign (file, op, "/=", reference, space, info)) + if (!_slang_assemble_assign (file, op, "/=", reference, space, info, mach, atoms)) return 0; break; case slang_oper_select: - if (!_slang_assemble_select (file, op, flow, space, info)) + if (!_slang_assemble_select (file, op, flow, space, info, mach, atoms)) return 0; break; case slang_oper_logicalor: - if (!_slang_assemble_logicalor (file, op, flow, space, info)) + if (!_slang_assemble_logicalor (file, op, flow, space, info, mach, atoms)) return 0; break; case slang_oper_logicaland: - if (!_slang_assemble_logicaland (file, op, flow, space, info)) + if (!_slang_assemble_logicaland (file, op, flow, space, info, mach, atoms)) return 0; break; case slang_oper_logicalxor: - if (!call_function_name (file, "^^", op->children, 2, 0, space, info)) + if (!call_function_name (file, "^^", op->children, 2, 0, space, info, mach, atoms)) 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)) + if (!call_function_name (file, "<", op->children, 2, 0, space, info, mach, atoms)) return 0; break; case slang_oper_greater: - if (!call_function_name (file, ">", op->children, 2, 0, space, info)) + if (!call_function_name (file, ">", op->children, 2, 0, space, info, mach, atoms)) return 0; break; case slang_oper_lessequal: - if (!call_function_name (file, "<=", op->children, 2, 0, space, info)) + if (!call_function_name (file, "<=", op->children, 2, 0, space, info, mach, atoms)) return 0; break; case slang_oper_greaterequal: - if (!call_function_name (file, ">=", op->children, 2, 0, space, info)) + if (!call_function_name (file, ">=", op->children, 2, 0, space, info, mach, atoms)) 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)) + if (!call_function_name (file, "+", op->children, 2, 0, space, info, mach, atoms)) return 0; break; case slang_oper_subtract: - if (!call_function_name (file, "-", op->children, 2, 0, space, info)) + if (!call_function_name (file, "-", op->children, 2, 0, space, info, mach, atoms)) return 0; break; case slang_oper_multiply: - if (!call_function_name (file, "*", op->children, 2, 0, space, info)) + if (!call_function_name (file, "*", op->children, 2, 0, space, info, mach, atoms)) return 0; break; /*case slang_oper_modulus:*/ case slang_oper_divide: - if (!call_function_name (file, "/", op->children, 2, 0, space, info)) + if (!call_function_name (file, "/", op->children, 2, 0, space, info, mach, atoms)) return 0; break; case slang_oper_equal: { slang_assembly_stack_info stk; - if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + + if (!_slang_assemble_operation (file, &op->children[0], 0, flow, space, info, &stk, + mach, atoms)) return 0; - /* TODO: inspect stk */ - if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk)) + if (!_slang_assemble_operation (file, &op->children[1], 0, flow, space, info, &stk, + mach, atoms)) return 0; - /* TODO: inspect stk */ - if (!equality (file, op->children, space, info, 1)) + if (!equality (file, op->children, space, info, 1, mach, atoms)) return 0; } break; case slang_oper_notequal: { slang_assembly_stack_info stk; - if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + + if (!_slang_assemble_operation (file, &op->children[0], 0, flow, space, info, &stk, + mach, atoms)) return 0; - /* TODO: inspect stk */ - if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk)) + if (!_slang_assemble_operation (file, &op->children[1], 0, flow, space, info, &stk, + mach, atoms)) return 0; - /* TODO: inspect stk */ - if (!equality (file, op->children, space, info, 0)) + if (!equality (file, op->children, space, info, 0, mach, atoms)) return 0; } break; case slang_oper_preincrement: - if (!_slang_assemble_assign (file, op, "++", reference, space, info)) + if (!_slang_assemble_assign (file, op, "++", reference, space, info, mach, atoms)) return 0; break; case slang_oper_predecrement: - if (!_slang_assemble_assign (file, op, "--", reference, space, info)) + if (!_slang_assemble_assign (file, op, "--", reference, space, info, mach, atoms)) return 0; break; case slang_oper_plus: - if (!call_function_name (file, "+", op->children, 1, 0, space, info)) + if (!_slang_dereference (file, op, space, info, mach, atoms)) return 0; break; case slang_oper_minus: - if (!call_function_name (file, "-", op->children, 1, 0, space, info)) + if (!call_function_name (file, "-", op->children, 1, 0, space, info, mach, atoms)) return 0; break; /*case slang_oper_complement:*/ case slang_oper_not: - if (!call_function_name (file, "!", op->children, 1, 0, space, info)) + if (!call_function_name (file, "!", op->children, 1, 0, space, info, mach, atoms)) 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, slang_qual_none, 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, slang_qual_none, 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); + + if (!slang_assembly_typeinfo_construct (&ti_arr)) return 0; - } - if (!slang_assembly_file_push_label (file, slang_asm_addr_push, elem_size)) + if (!slang_assembly_typeinfo_construct (&ti_elem)) { slang_assembly_typeinfo_destruct (&ti_arr); - slang_assembly_typeinfo_destruct (&ti_elem); return 0; } - if (!slang_assembly_file_push (file, slang_asm_addr_multiply)) + if (!handle_subscript (&ti_elem, &ti_arr, file, op, reference, flow, space, info, + mach, atoms)) { 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); + slang_function *fun; + + fun = _slang_locate_function (space->funcs, op->a_id, op->children, op->num_children, + space, atoms); if (fun == NULL) { - if (!_slang_assemble_constructor (file, op, flow, space, info)) - return 0; +/* if (!_slang_assemble_constructor (file, op, flow, space, info, mach)) +*/ return 0; } else { - if (!call_function (file, fun, op->children, op->num_children, 0, space, info)) + if (!_slang_call_function (file, fun, op->children, op->num_children, 0, space, + info, mach, atoms)) return 0; } } @@ -1084,101 +1371,31 @@ int _slang_assemble_operation (slang_assembly_file *file, slang_operation *op, i 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); + + if (!slang_assembly_typeinfo_construct (&ti_after)) return 0; - } - slang_assembly_typeinfo_construct (&ti_before); - if (!_slang_typeof_operation (op->children, space, &ti_before)) + if (!slang_assembly_typeinfo_construct (&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)) + if (!handle_field (&ti_after, &ti_before, file, op, reference, flow, space, info, stk, + mach, atoms)) { 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)) + if (!call_function_name_dummyint (file, "++", op->children, space, info, mach, atoms)) 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)) + if (!call_function_name_dummyint (file, "--", op->children, space, info, mach, atoms)) return 0; break; default: diff --git a/src/mesa/shader/slang/slang_assemble.h b/src/mesa/shader/slang/slang_assemble.h index d93755c7e7..c3af8d8fed 100644 --- a/src/mesa/shader/slang/slang_assemble.h +++ b/src/mesa/shader/slang/slang_assemble.h @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.3 + * Version: 6.5 * - * Copyright (C) 2005 Brian Paul All Rights Reserved. + * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -44,8 +44,16 @@ typedef enum slang_assembly_type_ slang_asm_float_divide, slang_asm_float_negate, slang_asm_float_less, - slang_asm_float_equal, + slang_asm_float_equal_exp, + slang_asm_float_equal_int, slang_asm_float_to_int, + slang_asm_float_sine, + slang_asm_float_arcsine, + slang_asm_float_arctan, + slang_asm_float_power, + slang_asm_float_log2, + slang_asm_float_floor, + slang_asm_float_ceil, slang_asm_int_copy, slang_asm_int_move, slang_asm_int_push, @@ -72,6 +80,10 @@ typedef enum slang_assembly_type_ slang_asm_return, slang_asm_discard, slang_asm_exit, + /* mesa-specific extensions */ + slang_asm_float_print, + slang_asm_int_print, + slang_asm_bool_print, slang_asm__last } slang_assembly_type; @@ -86,15 +98,26 @@ typedef struct slang_assembly_file_ { slang_assembly *code; unsigned int count; + unsigned int capacity; } slang_assembly_file; -void slang_assembly_file_construct (slang_assembly_file *); +int 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_file_restore_point_ +{ + unsigned int count; +} slang_assembly_file_restore_point; + +int slang_assembly_file_restore_point_save (slang_assembly_file *, + slang_assembly_file_restore_point *); +int slang_assembly_file_restore_point_load (slang_assembly_file *, + slang_assembly_file_restore_point *); + typedef struct slang_assembly_flow_control_ { unsigned int loop_start; /* for "continue" statement */ @@ -109,19 +132,31 @@ typedef struct slang_assembly_name_space_ 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); +slang_function *_slang_locate_function (slang_function_scope *funcs, slang_atom a_name, + slang_operation *params, unsigned int num_params, slang_assembly_name_space *space, + slang_atom_pool *); int _slang_assemble_function (slang_assembly_file *, struct slang_function_ *, - slang_assembly_name_space *); + slang_assembly_name_space *, struct slang_machine_ *, slang_atom_pool *); + +/* + 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; typedef struct slang_assembly_stack_info_ { - unsigned int swizzle_mask; + slang_swizzle swizzle; } slang_assembly_stack_info; int _slang_cleanup_stack (slang_assembly_file *, slang_operation *, int ref, - slang_assembly_name_space *); + slang_assembly_name_space *, struct slang_machine_ *, slang_atom_pool *); typedef struct slang_assembly_local_info_ { @@ -130,9 +165,12 @@ typedef struct slang_assembly_local_info_ unsigned int swizzle_tmp; } slang_assembly_local_info; +int _slang_dereference (slang_assembly_file *, slang_operation *, slang_assembly_name_space *, + slang_assembly_local_info *, struct slang_machine_ *, slang_atom_pool *); + 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 *); + slang_assembly_stack_info *, struct slang_machine_ *, slang_atom_pool *); #ifdef __cplusplus } diff --git a/src/mesa/shader/slang/slang_assemble_assignment.c b/src/mesa/shader/slang/slang_assemble_assignment.c index d8821f03bb..3c35e86256 100644 --- a/src/mesa/shader/slang/slang_assemble_assignment.c +++ b/src/mesa/shader/slang/slang_assemble_assignment.c @@ -29,10 +29,11 @@ */ #include "imports.h" +#include "slang_utility.h" #include "slang_assemble_assignment.h" #include "slang_assemble_typeinfo.h" #include "slang_storage.h" -#include "slang_utility.h" +#include "slang_execute.h" /* _slang_assemble_assignment() @@ -54,28 +55,45 @@ | addr of variable | +------------------+ */ -/* TODO: add support for swizzle mask */ + 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 *index, unsigned int size, slang_assembly_local_info *info, + slang_assembly_stack_info *stk) { unsigned int i; for (i = 0; i < agg->count; i++) { - const slang_storage_array *arr = agg->arrays + 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)) + if (!assign_aggregate (file, arr->aggregate, index, size, info, stk)) return 0; } else { + unsigned int dst_addr_loc, dst_offset; slang_assembly_type ty; + /* calculate the distance from top of the stack to the destination address */ + dst_addr_loc = size - *index; + + /* calculate the offset within destination variable to write */ + if (stk->swizzle.num_components != 0) + { + /* swizzle the index to get the actual offset */ + dst_offset = stk->swizzle.swizzle[*index / 4] * 4; + } + else + { + /* no swizzling - write sequentially */ + dst_offset = *index; + } + switch (arr->type) { case slang_stor_bool: @@ -90,7 +108,7 @@ static int assign_aggregate (slang_assembly_file *file, const slang_storage_aggr default: break; } - if (!slang_assembly_file_push_label2 (file, ty, size - *index, *index)) + if (!slang_assembly_file_push_label2 (file, ty, dst_addr_loc, dst_offset)) return 0; *index += 4; } @@ -100,22 +118,29 @@ static int assign_aggregate (slang_assembly_file *file, const slang_storage_aggr } int _slang_assemble_assignment (slang_assembly_file *file, slang_operation *op, - slang_assembly_name_space *space, slang_assembly_local_info *info) + slang_assembly_name_space *space, slang_assembly_local_info *info, slang_assembly_stack_info *stk, + struct slang_machine_ *mach, slang_atom_pool *atoms) { 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)) + if (!slang_assembly_typeinfo_construct (&ti)) + return 0; + if (!_slang_typeof_operation (op, space, &ti, atoms)) { slang_assembly_typeinfo_destruct (&ti); return 0; } - slang_storage_aggregate_construct (&agg); - if (!_slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs, space->vars)) + if (!slang_storage_aggregate_construct (&agg)) + { + slang_assembly_typeinfo_destruct (&ti); + return 0; + } + if (!_slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs, + space->vars, mach, file, atoms)) { slang_storage_aggregate_destruct (&agg); slang_assembly_typeinfo_destruct (&ti); @@ -124,7 +149,7 @@ int _slang_assemble_assignment (slang_assembly_file *file, slang_operation *op, index = 0; size = _slang_sizeof_aggregate (&agg); - result = assign_aggregate (file, &agg, &index, size, info); + result = assign_aggregate (file, &agg, &index, size, info, stk); slang_storage_aggregate_destruct (&agg); slang_assembly_typeinfo_destruct (&ti); @@ -138,17 +163,15 @@ int _slang_assemble_assignment (slang_assembly_file *file, slang_operation *op, children */ -int dereference (slang_assembly_file *file, slang_operation *op, - slang_assembly_name_space *space, slang_assembly_local_info *info); - 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_assembly_local_info *info, slang_machine *mach, slang_atom_pool *atoms); int _slang_assemble_assign (slang_assembly_file *file, slang_operation *op, const char *oper, - int ref, slang_assembly_name_space *space, slang_assembly_local_info *info) + int ref, slang_assembly_name_space *space, slang_assembly_local_info *info, + struct slang_machine_ *mach, slang_atom_pool *atoms) { - slang_assembly_stack_info stk; + slang_assembly_stack_info l_stk, r_stk; slang_assembly_flow_control flow; if (!ref) @@ -159,16 +182,19 @@ int _slang_assemble_assign (slang_assembly_file *file, slang_operation *op, cons if (slang_string_compare ("=", oper) == 0) { - if (!_slang_assemble_operation (file, op->children, 1, &flow, space, info, &stk)) + if (!_slang_assemble_operation (file, &op->children[0], 1, &flow, space, info, &l_stk, mach, + atoms)) return 0; - if (!_slang_assemble_operation (file, op->children + 1, 0, &flow, space, info, &stk)) + if (!_slang_assemble_operation (file, &op->children[1], 0, &flow, space, info, &r_stk, mach, + atoms)) return 0; - if (!_slang_assemble_assignment (file, op->children, space, info)) + if (!_slang_assemble_assignment (file, op->children, space, info, &l_stk, mach, atoms)) return 0; } else { - if (!call_function_name (file, oper, op->children, op->num_children, 1, space, info)) + if (!call_function_name (file, oper, op->children, op->num_children, 1, space, info, mach, + atoms)) return 0; } @@ -178,7 +204,7 @@ int _slang_assemble_assign (slang_assembly_file *file, slang_operation *op, cons return 0; if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4)) return 0; - if (!dereference (file, op->children, space, info)) + if (!_slang_dereference (file, op->children, space, info, mach, atoms)) return 0; } diff --git a/src/mesa/shader/slang/slang_assemble_assignment.h b/src/mesa/shader/slang/slang_assemble_assignment.h index 06972ad176..1dc48b16a7 100644 --- a/src/mesa/shader/slang/slang_assemble_assignment.h +++ b/src/mesa/shader/slang/slang_assemble_assignment.h @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.3 + * Version: 6.5 * - * Copyright (C) 2005 Brian Paul All Rights Reserved. + * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,10 +32,12 @@ extern "C" { #endif int _slang_assemble_assignment (slang_assembly_file *, slang_operation *, - slang_assembly_name_space *, slang_assembly_local_info *); + slang_assembly_name_space *, slang_assembly_local_info *, slang_assembly_stack_info *, + struct slang_machine_ *, slang_atom_pool *); int _slang_assemble_assign (slang_assembly_file *, slang_operation *, const char *, int ref, - slang_assembly_name_space *, slang_assembly_local_info *); + slang_assembly_name_space *, slang_assembly_local_info *, struct slang_machine_ *, + slang_atom_pool *); #ifdef __cplusplus } diff --git a/src/mesa/shader/slang/slang_assemble_conditional.c b/src/mesa/shader/slang/slang_assemble_conditional.c index 498938bdd5..74324cfe6c 100644 --- a/src/mesa/shader/slang/slang_assemble_conditional.c +++ b/src/mesa/shader/slang/slang_assemble_conditional.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.3 + * Version: 6.5 * - * Copyright (C) 2005 Brian Paul All Rights Reserved. + * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,12 +32,13 @@ #include "slang_utility.h" #include "slang_assemble_conditional.h" #include "slang_assemble.h" +#include "slang_execute.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) + slang_assembly_local_info *info, slang_machine *mach, slang_atom_pool *atoms) { /* and: @@ -54,7 +55,7 @@ int _slang_assemble_logicaland (slang_assembly_file *file, slang_operation *op, slang_assembly_stack_info stk; /* evaluate left expression */ - if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + if (!_slang_assemble_operation (file, &op->children[0], 0, flow, space, info, &stk, mach, atoms)) return 0; /* TODO: inspect stk */ @@ -64,7 +65,7 @@ int _slang_assemble_logicaland (slang_assembly_file *file, slang_operation *op, return 0; /* evaluate right expression */ - if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk)) + if (!_slang_assemble_operation (file, &op->children[1], 0, flow, space, info, &stk, mach, atoms)) return 0; /* TODO: inspect stk */ @@ -75,7 +76,7 @@ int _slang_assemble_logicaland (slang_assembly_file *file, slang_operation *op, /* push 0 on stack */ file->code[zero_jump].param[0] = file->count; - if (!slang_assembly_file_push (file, slang_asm_bool_push)) + if (!slang_assembly_file_push_literal (file, slang_asm_bool_push, (GLfloat) 0)) return 0; /* the end of the expression */ @@ -88,7 +89,7 @@ int _slang_assemble_logicaland (slang_assembly_file *file, slang_operation *op, 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) + slang_assembly_local_info *info, slang_machine *mach, slang_atom_pool *atoms) { /* or: @@ -105,7 +106,7 @@ int _slang_assemble_logicalor (slang_assembly_file *file, slang_operation *op, slang_assembly_stack_info stk; /* evaluate left expression */ - if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + if (!_slang_assemble_operation (file, &op->children[0], 0, flow, space, info, &stk, mach, atoms)) return 0; /* TODO: inspect stk */ @@ -115,7 +116,7 @@ int _slang_assemble_logicalor (slang_assembly_file *file, slang_operation *op, return 0; /* push 1 on stack */ - if (!slang_assembly_file_push_literal (file, slang_asm_bool_push, 1.0f)) + if (!slang_assembly_file_push_literal (file, slang_asm_bool_push, (GLfloat) 1)) return 0; /* jump to the end of the expression */ @@ -125,7 +126,7 @@ int _slang_assemble_logicalor (slang_assembly_file *file, slang_operation *op, /* evaluate right expression */ file->code[right_jump].param[0] = file->count; - if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk)) + if (!_slang_assemble_operation (file, &op->children[1], 0, flow, space, info, &stk, mach, atoms)) return 0; /* TODO: inspect stk */ @@ -139,7 +140,7 @@ int _slang_assemble_logicalor (slang_assembly_file *file, slang_operation *op, 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) + slang_assembly_local_info *info, slang_machine *mach, slang_atom_pool *atoms) { /* select: @@ -156,7 +157,7 @@ int _slang_assemble_select (slang_assembly_file *file, slang_operation *op, slang_assembly_stack_info stk; /* execute condition expression */ - if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + if (!_slang_assemble_operation (file, &op->children[0], 0, flow, space, info, &stk, mach, atoms)) return 0; /* TODO: inspect stk */ @@ -166,7 +167,7 @@ int _slang_assemble_select (slang_assembly_file *file, slang_operation *op, return 0; /* execute true expression */ - if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk)) + if (!_slang_assemble_operation (file, &op->children[1], 0, flow, space, info, &stk, mach, atoms)) return 0; /* TODO: inspect stk */ @@ -179,7 +180,7 @@ int _slang_assemble_select (slang_assembly_file *file, slang_operation *op, file->code[cond_jump].param[0] = file->count; /* execute false expression */ - if (!_slang_assemble_operation (file, op->children + 2, 0, flow, space, info, &stk)) + if (!_slang_assemble_operation (file, &op->children[2], 0, flow, space, info, &stk, mach, atoms)) return 0; /* TODO: inspect stk */ @@ -193,7 +194,7 @@ int _slang_assemble_select (slang_assembly_file *file, slang_operation *op, 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) + slang_assembly_local_info *info, slang_machine *mach, slang_atom_pool *atoms) { /* for: @@ -217,10 +218,10 @@ int _slang_assemble_for (slang_assembly_file *file, slang_operation *op, slang_assembly_stack_info stk; /* execute initialization statement */ - if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + if (!_slang_assemble_operation (file, &op->children[0], 0, flow, space, info, &stk, mach, atoms)) return 0; /* TODO: pass-in stk to cleanup */ - if (!_slang_cleanup_stack (file, op->children, 0, space)) + if (!_slang_cleanup_stack (file, &op->children[0], 0, space, mach, atoms)) return 0; /* skip the "go to the end of the loop" and loop-increment statements */ @@ -238,17 +239,17 @@ int _slang_assemble_for (slang_assembly_file *file, slang_operation *op, cont_label = file->count; /* execute loop-increment statement */ - if (!_slang_assemble_operation (file, op->children + 2, 0, flow, space, info, &stk)) + if (!_slang_assemble_operation (file, &op->children[2], 0, flow, space, info, &stk, mach, atoms)) return 0; /* TODO: pass-in stk to cleanup */ - if (!_slang_cleanup_stack (file, op->children + 2, 0, space)) + if (!_slang_cleanup_stack (file, &op->children[2], 0, space, mach, atoms)) 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)) + if (!_slang_assemble_operation (file, &op->children[1], 0, flow, space, info, &stk, mach, atoms)) return 0; /* TODO: inspect stk */ @@ -260,10 +261,10 @@ int _slang_assemble_for (slang_assembly_file *file, slang_operation *op, /* 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)) + if (!_slang_assemble_operation (file, &op->children[3], 0, &loop_flow, space, info, &stk, mach, atoms)) return 0; /* TODO: pass-in stk to cleanup */ - if (!_slang_cleanup_stack (file, op->children + 3, 0, space)) + if (!_slang_cleanup_stack (file, &op->children[3], 0, space, mach, atoms)) return 0; /* go to the beginning of the loop */ @@ -281,7 +282,7 @@ int _slang_assemble_for (slang_assembly_file *file, slang_operation *op, 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) + slang_assembly_local_info *info, slang_machine *mach, slang_atom_pool *atoms) { /* do: @@ -327,17 +328,17 @@ int _slang_assemble_do (slang_assembly_file *file, slang_operation *op, /* 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)) + if (!_slang_assemble_operation (file, &op->children[0], 0, &loop_flow, space, info, &stk, mach, atoms)) return 0; /* TODO: pass-in stk to cleanup */ - if (!_slang_cleanup_stack (file, op->children, 0, space)) + if (!_slang_cleanup_stack (file, &op->children[0], 0, space, mach, atoms)) 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)) + if (!_slang_assemble_operation (file, &op->children[1], 0, flow, space, info, &stk, mach, atoms)) return 0; /* TODO: pass-in stk to cleanup */ @@ -361,7 +362,7 @@ int _slang_assemble_do (slang_assembly_file *file, slang_operation *op, 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) + slang_assembly_local_info *info, slang_machine *mach, slang_atom_pool *atoms) { /* while: @@ -396,7 +397,7 @@ int _slang_assemble_while (slang_assembly_file *file, slang_operation *op, file->code[skip_jump].param[0] = file->count; /* execute condition statement */ - if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + if (!_slang_assemble_operation (file, &op->children[0], 0, flow, space, info, &stk, mach, atoms)) return 0; /* TODO: pass-in stk to cleanup */ @@ -408,10 +409,10 @@ int _slang_assemble_while (slang_assembly_file *file, slang_operation *op, /* 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)) + if (!_slang_assemble_operation (file, &op->children[1], 0, &loop_flow, space, info, &stk, mach, atoms)) return 0; /* TODO: pass-in stk to cleanup */ - if (!_slang_cleanup_stack (file, op->children + 1, 0, space)) + if (!_slang_cleanup_stack (file, &op->children[1], 0, space, mach, atoms)) return 0; /* jump to the beginning of the loop */ @@ -429,7 +430,7 @@ int _slang_assemble_while (slang_assembly_file *file, slang_operation *op, 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) + slang_assembly_local_info *info, slang_machine *mach, slang_atom_pool *atoms) { /* if: @@ -446,7 +447,7 @@ int _slang_assemble_if (slang_assembly_file *file, slang_operation *op, slang_assembly_stack_info stk; /* execute condition statement */ - if (!_slang_assemble_operation (file, op->children, 0, flow, space, info, &stk)) + if (!_slang_assemble_operation (file, &op->children[0], 0, flow, space, info, &stk, mach, atoms)) return 0; /* TODO: pass-in stk to cleanup */ @@ -456,10 +457,10 @@ int _slang_assemble_if (slang_assembly_file *file, slang_operation *op, return 0; /* execute true-statement */ - if (!_slang_assemble_operation (file, op->children + 1, 0, flow, space, info, &stk)) + if (!_slang_assemble_operation (file, &op->children[1], 0, flow, space, info, &stk, mach, atoms)) return 0; /* TODO: pass-in stk to cleanup */ - if (!_slang_cleanup_stack (file, op->children + 1, 0, space)) + if (!_slang_cleanup_stack (file, &op->children[1], 0, space, mach, atoms)) return 0; /* skip if-false statement */ @@ -471,10 +472,10 @@ int _slang_assemble_if (slang_assembly_file *file, slang_operation *op, file->code[cond_jump].param[0] = file->count; /* execute false-statement */ - if (!_slang_assemble_operation (file, op->children + 2, 0, flow, space, info, &stk)) + if (!_slang_assemble_operation (file, &op->children[2], 0, flow, space, info, &stk, mach, atoms)) return 0; /* TODO: pass-in stk to cleanup */ - if (!_slang_cleanup_stack (file, op->children + 2, 0, space)) + if (!_slang_cleanup_stack (file, &op->children[2], 0, space, mach, atoms)) return 0; /* resolve end of if-false statement */ diff --git a/src/mesa/shader/slang/slang_assemble_conditional.h b/src/mesa/shader/slang/slang_assemble_conditional.h index f52b4129d3..f5aa0d4826 100644 --- a/src/mesa/shader/slang/slang_assemble_conditional.h +++ b/src/mesa/shader/slang/slang_assemble_conditional.h @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.3 + * Version: 6.5 * - * Copyright (C) 2005 Brian Paul All Rights Reserved. + * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -33,31 +33,31 @@ extern "C" { 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); + slang_assembly_local_info *info, struct slang_machine_ *, slang_atom_pool *); 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); + slang_assembly_local_info *info, struct slang_machine_ *, slang_atom_pool *); 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); + slang_assembly_local_info *info, struct slang_machine_ *, slang_atom_pool *); 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); + slang_assembly_local_info *info, struct slang_machine_ *, slang_atom_pool *); 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); + slang_assembly_local_info *info, struct slang_machine_ *, slang_atom_pool *); 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); + slang_assembly_local_info *info, struct slang_machine_ *, slang_atom_pool *); 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); + slang_assembly_local_info *info, struct slang_machine_ *, slang_atom_pool *); #ifdef __cplusplus } diff --git a/src/mesa/shader/slang/slang_assemble_constructor.c b/src/mesa/shader/slang/slang_assemble_constructor.c index e62f88b591..aa2e019538 100644 --- a/src/mesa/shader/slang/slang_assemble_constructor.c +++ b/src/mesa/shader/slang/slang_assemble_constructor.c @@ -84,25 +84,23 @@ int _slang_is_swizzle (const char *field, unsigned int rows, slang_swizzle *swz) 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; } + + /* check if the component is valid for given vector's row count */ + if (rows <= swz->swizzle[i]) + return 0; } /* only one swizzle group can be used */ @@ -116,16 +114,18 @@ int _slang_is_swizzle (const char *field, unsigned int rows, slang_swizzle *swz) int _slang_is_swizzle_mask (const slang_swizzle *swz, unsigned int rows) { - unsigned int c, i; + unsigned int i, c = 0; + /* the swizzle may not be longer than the vector dim */ if (swz->num_components > rows) return 0; - c = swz->swizzle[0]; - for (i = 1; i < swz->num_components; i++) + + /* the swizzle components cannot be duplicated */ + for (i = 0; i < swz->num_components; i++) { - if (swz->swizzle[i] <= c) + if ((c & (1 << swz->swizzle[i])) != 0) return 0; - c = swz->swizzle[i]; + c |= 1 << swz->swizzle[i]; } return 1; } @@ -136,13 +136,14 @@ 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) @@ -177,10 +178,10 @@ static int constructor_aggregate (slang_assembly_file *file, const slang_storage 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: @@ -192,38 +193,41 @@ end1: return result; } /* XXX: general swizzle! */ -int _slang_assemble_constructor (slang_assembly_file *file, slang_operation *op, +/*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_local_info *info, struct slang_machine_ *pmach) { slang_assembly_typeinfo ti; int result; slang_storage_aggregate agg, flat; unsigned int size, index, i; - slang_assembly_typeinfo_construct (&ti); + if (!slang_assembly_typeinfo_construct (&ti)) + return 0; if (!(result = _slang_typeof_operation (op, space, &ti))) goto end1; - slang_storage_aggregate_construct (&agg); + if (!(result = slang_storage_aggregate_construct (&agg))) + goto end1; if (!(result = _slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs, - space->vars))) + space->vars, pmach, file))) goto end2; size = _slang_sizeof_aggregate (&agg); - slang_storage_aggregate_construct (&flat); + if (!(result = slang_storage_aggregate_construct (&flat))) + goto end2; 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, +/* 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: @@ -236,66 +240,34 @@ end1: } /* _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; - default: - break; - } + + master_rows = _slang_type_dim (master_spec->type); for (i = 0; i < master_rows; i++) { - switch (master_spec->type) + switch (_slang_type_base (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)) + 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)) + 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)) + (master_rows - i) * 4, i * 4)) return 0; break; default: - break; + break; } } if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4)) @@ -303,37 +275,29 @@ int _slang_assemble_constructor_from_swizzle (slang_assembly_file *file, const s 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) + switch (_slang_type_base (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; default: - break; + break; } } return 1; diff --git a/src/mesa/shader/slang/slang_assemble_constructor.h b/src/mesa/shader/slang/slang_assemble_constructor.h index f8a0fead3c..b87e9cce7d 100644 --- a/src/mesa/shader/slang/slang_assemble_constructor.h +++ b/src/mesa/shader/slang/slang_assemble_constructor.h @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.3 + * Version: 6.5 * - * Copyright (C) 2005 Brian Paul All Rights Reserved. + * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,17 +32,6 @@ 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 @@ -67,7 +56,7 @@ void _slang_multiply_swizzles (slang_swizzle *, const slang_swizzle *, const sla 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_local_info *info, struct slang_machine_ *); 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); diff --git a/src/mesa/shader/slang/slang_assemble_typeinfo.c b/src/mesa/shader/slang/slang_assemble_typeinfo.c index f550556763..778ba04ced 100644 --- a/src/mesa/shader/slang/slang_assemble_typeinfo.c +++ b/src/mesa/shader/slang/slang_assemble_typeinfo.c @@ -34,20 +34,37 @@ /* slang_assembly_typeinfo */ -void slang_assembly_typeinfo_construct (slang_assembly_typeinfo *ti) +int slang_assembly_typeinfo_construct (slang_assembly_typeinfo *ti) { - slang_type_specifier_construct (&ti->spec); + if (!slang_type_specifier_construct (&ti->spec)) + return 0; + ti->array_size = NULL; + return 1; } void slang_assembly_typeinfo_destruct (slang_assembly_typeinfo *ti) { slang_type_specifier_destruct (&ti->spec); + /* do not free ti->array_size */ } /* _slang_typeof_operation() */ +static int typeof_existing_function (const char *name, slang_operation *params, + unsigned int num_params, slang_assembly_name_space *space, slang_type_specifier *spec, + slang_atom_pool *atoms) +{ + slang_atom atom; + int exists; + + atom = slang_atom_pool_atom (atoms, name); + if (!_slang_typeof_function (atom, params, num_params, space, spec, &exists, atoms)) + return 0; + return exists; +} + int _slang_typeof_operation (slang_operation *op, slang_assembly_name_space *space, - slang_assembly_typeinfo *ti) + slang_assembly_typeinfo *ti, slang_atom_pool *atoms) { ti->can_be_referenced = 0; ti->is_swizzled = 0; @@ -77,7 +94,7 @@ int _slang_typeof_operation (slang_operation *op, slang_assembly_name_space *spa case slang_oper_divassign: case slang_oper_preincrement: case slang_oper_predecrement: - if (!_slang_typeof_operation (op->children, space, ti)) + if (!_slang_typeof_operation (op->children, space, ti, atoms)) return 0; break; case slang_oper_literal_bool: @@ -103,17 +120,18 @@ int _slang_typeof_operation (slang_operation *op, slang_assembly_name_space *spa { slang_variable *var; - var = _slang_locate_variable (op->locals, op->identifier, 1); + var = _slang_locate_variable (op->locals, op->a_id, 1); if (var == NULL) return 0; if (!slang_type_specifier_copy (&ti->spec, &var->type.specifier)) return 0; ti->can_be_referenced = 1; + ti->array_size = var->array_size; } break; case slang_oper_sequence: /* TODO: check [0] and [1] if they match */ - if (!_slang_typeof_operation (op->children + 1, space, ti)) + if (!_slang_typeof_operation (&op->children[1], space, ti, atoms)) return 0; ti->can_be_referenced = 0; ti->is_swizzled = 0; @@ -126,7 +144,7 @@ int _slang_typeof_operation (slang_operation *op, slang_assembly_name_space *spa /*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)) + if (!_slang_typeof_operation (&op->children[1], space, ti, atoms)) return 0; ti->can_be_referenced = 0; ti->is_swizzled = 0; @@ -137,107 +155,61 @@ int _slang_typeof_operation (slang_operation *op, slang_assembly_name_space *spa /*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; - } + if (!typeof_existing_function ("+", op->children, 2, space, &ti->spec, atoms)) + 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; - } + if (!typeof_existing_function ("-", op->children, 2, space, &ti->spec, atoms)) + 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; - } + if (!typeof_existing_function ("*", op->children, 2, space, &ti->spec, atoms)) + 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; - } + if (!typeof_existing_function ("/", op->children, 2, space, &ti->spec, atoms)) + 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; - } + if (!_slang_typeof_operation (op->children, space, ti, atoms)) + return 0; + ti->can_be_referenced = 0; + ti->is_swizzled = 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; - } + if (!typeof_existing_function ("-", op->children, 1, space, &ti->spec, atoms)) + 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)) + + if (!slang_assembly_typeinfo_construct (&_ti)) + return 0; + if (!_slang_typeof_operation (op->children, space, &_ti, atoms)) { slang_assembly_typeinfo_destruct (&_ti); return 0; } ti->can_be_referenced = _ti.can_be_referenced; - switch (_ti.spec.type) + if (_ti.spec.type == slang_spec_array) { - 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; + } + else + { + if (!_slang_type_is_vector (_ti.spec.type) && !_slang_type_is_matrix (_ti.spec.type)) + { + slang_assembly_typeinfo_destruct (&_ti); + return 0; + } + ti->spec.type = _slang_type_base (_ti.spec.type); } slang_assembly_typeinfo_destruct (&_ti); } @@ -245,12 +217,13 @@ int _slang_typeof_operation (slang_operation *op, slang_assembly_name_space *spa case slang_oper_call: { int exists; - if (!_slang_typeof_function (op->identifier, op->children, op->num_children, space, - &ti->spec, &exists)) + + if (!_slang_typeof_function (op->a_id, op->children, op->num_children, space, &ti->spec, + &exists, atoms)) return 0; if (!exists) { - slang_struct *s = slang_struct_scope_find (space->structs, op->identifier, 1); +/* slang_struct *s = slang_struct_scope_find (space->structs, op->identifier, 1); if (s != NULL) { ti->spec.type = slang_spec_struct; @@ -267,9 +240,12 @@ int _slang_typeof_operation (slang_operation *op, slang_assembly_name_space *spa return 0; } else - { - slang_type_specifier_type type = slang_type_specifier_type_from_string ( - op->identifier); +*/ { + const char *name; + slang_type_specifier_type type; + + name = slang_atom_pool_id (atoms, op->a_id); + type = slang_type_specifier_type_from_string (name); if (type == slang_spec_void) return 0; ti->spec.type = type; @@ -280,16 +256,19 @@ int _slang_typeof_operation (slang_operation *op, slang_assembly_name_space *spa case slang_oper_field: { slang_assembly_typeinfo _ti; - slang_assembly_typeinfo_construct (&_ti); - if (!_slang_typeof_operation (op->children, space, &_ti)) + + if (!slang_assembly_typeinfo_construct (&_ti)) + return 0; + if (!_slang_typeof_operation (op->children, space, &_ti, atoms)) { 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); + slang_variable *field; + + field = _slang_locate_variable (_ti.spec._struct->fields, op->a_id, 0); if (field == NULL) { slang_assembly_typeinfo_destruct (&_ti); @@ -300,112 +279,96 @@ int _slang_typeof_operation (slang_operation *op, slang_assembly_name_space *spa slang_assembly_typeinfo_destruct (&_ti); return 0; } + ti->can_be_referenced = _ti.can_be_referenced; } else { unsigned int rows; - switch (_ti.spec.type) + const char *swizzle; + slang_type_specifier_type base; + + /* determine the swizzle of the field expression */ + if (!_slang_type_is_vector (_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)) + rows = _slang_type_dim (_ti.spec.type); + swizzle = slang_atom_pool_id (atoms, op->a_id); + if (!_slang_is_swizzle (swizzle, rows, &ti->swz)) + { + slang_assembly_typeinfo_destruct (&_ti); 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; + + /* swizzle the swizzle */ _slang_multiply_swizzles (&swz, &_ti.swz, &ti->swz); ti->swz = swz; } - switch (_ti.spec.type) + base = _slang_type_base (_ti.spec.type); + switch (ti->swz.num_components) { - case slang_spec_vec2: - case slang_spec_vec3: - case slang_spec_vec4: - switch (ti->swz.num_components) + case 1: + ti->spec.type = base; + break; + case 2: + switch (base) { - case 1: - ti->spec.type = slang_spec_float; - break; - case 2: + case slang_spec_float: ti->spec.type = slang_spec_vec2; break; - case 3: - ti->spec.type = slang_spec_vec3; + case slang_spec_int: + ti->spec.type = slang_spec_ivec2; break; - case 4: - ti->spec.type = slang_spec_vec4; + case slang_spec_bool: + ti->spec.type = slang_spec_bvec2; break; } break; - case slang_spec_ivec2: - case slang_spec_ivec3: - case slang_spec_ivec4: - switch (ti->swz.num_components) + case 3: + switch (base) { - case 1: - ti->spec.type = slang_spec_int; - break; - case 2: - ti->spec.type = slang_spec_ivec2; + case slang_spec_float: + ti->spec.type = slang_spec_vec3; break; - case 3: + case slang_spec_int: ti->spec.type = slang_spec_ivec3; break; - case 4: - ti->spec.type = slang_spec_ivec4; + case slang_spec_bool: + ti->spec.type = slang_spec_bvec3; break; } break; - case slang_spec_bvec2: - case slang_spec_bvec3: - case slang_spec_bvec4: - switch (ti->swz.num_components) + case 4: + switch (base) { - case 1: - ti->spec.type = slang_spec_bool; - break; - case 2: - ti->spec.type = slang_spec_bvec2; + case slang_spec_float: + ti->spec.type = slang_spec_vec4; break; - case 3: - ti->spec.type = slang_spec_bvec3; + case slang_spec_int: + ti->spec.type = slang_spec_ivec4; break; - case 4: + case slang_spec_bool: ti->spec.type = slang_spec_bvec4; break; } break; default: - 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)) + if (!_slang_typeof_operation (op->children, space, ti, atoms)) return 0; ti->can_be_referenced = 0; ti->is_swizzled = 0; @@ -418,13 +381,113 @@ int _slang_typeof_operation (slang_operation *op, slang_assembly_name_space *spa /* _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) +int _slang_typeof_function (slang_atom a_name, slang_operation *params, unsigned int num_params, + slang_assembly_name_space *space, slang_type_specifier *spec, int *exists, slang_atom_pool *atoms) { - slang_function *fun = _slang_locate_function (name, params, num_params, space); + slang_function *fun; + + fun = _slang_locate_function (space->funcs, a_name, params, num_params, space, atoms); *exists = fun != NULL; if (fun == NULL) return 1; return slang_type_specifier_copy (spec, &fun->header.type.specifier); } +/* _slang_type_is_matrix() */ + +int _slang_type_is_matrix (slang_type_specifier_type ty) +{ + switch (ty) + { + case slang_spec_mat2: + case slang_spec_mat3: + case slang_spec_mat4: + return 1; + default: + return 0; + } +} + +/* _slang_type_is_vector() */ + +int _slang_type_is_vector (slang_type_specifier_type ty) +{ + switch (ty) + { + case slang_spec_vec2: + case slang_spec_vec3: + case slang_spec_vec4: + case slang_spec_ivec2: + case slang_spec_ivec3: + case slang_spec_ivec4: + case slang_spec_bvec2: + case slang_spec_bvec3: + case slang_spec_bvec4: + return 1; + default: + return 0; + } +} + +/* _slang_type_base_of_vector() */ + +slang_type_specifier_type _slang_type_base (slang_type_specifier_type ty) +{ + switch (ty) + { + case slang_spec_float: + case slang_spec_vec2: + case slang_spec_vec3: + case slang_spec_vec4: + return slang_spec_float; + case slang_spec_int: + case slang_spec_ivec2: + case slang_spec_ivec3: + case slang_spec_ivec4: + return slang_spec_int; + case slang_spec_bool: + case slang_spec_bvec2: + case slang_spec_bvec3: + case slang_spec_bvec4: + return slang_spec_bool; + case slang_spec_mat2: + return slang_spec_vec2; + case slang_spec_mat3: + return slang_spec_vec3; + case slang_spec_mat4: + return slang_spec_vec4; + default: + return slang_spec_void; + } +} + +/* _slang_type_dim */ + +unsigned int _slang_type_dim (slang_type_specifier_type ty) +{ + switch (ty) + { + case slang_spec_float: + case slang_spec_int: + case slang_spec_bool: + return 1; + case slang_spec_vec2: + case slang_spec_ivec2: + case slang_spec_bvec2: + case slang_spec_mat2: + return 2; + case slang_spec_vec3: + case slang_spec_ivec3: + case slang_spec_bvec3: + case slang_spec_mat3: + return 3; + case slang_spec_vec4: + case slang_spec_ivec4: + case slang_spec_bvec4: + case slang_spec_mat4: + return 4; + default: + return 0; + } +} + diff --git a/src/mesa/shader/slang/slang_assemble_typeinfo.h b/src/mesa/shader/slang/slang_assemble_typeinfo.h index 1c1839457e..cd16440e1a 100644 --- a/src/mesa/shader/slang/slang_assemble_typeinfo.h +++ b/src/mesa/shader/slang/slang_assemble_typeinfo.h @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.3 + * Version: 6.5 * - * Copyright (C) 2005 Brian Paul All Rights Reserved. + * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -38,9 +38,10 @@ typedef struct slang_assembly_typeinfo_ int is_swizzled; slang_swizzle swz; slang_type_specifier spec; + slang_operation *array_size; } slang_assembly_typeinfo; -void slang_assembly_typeinfo_construct (slang_assembly_typeinfo *); +int slang_assembly_typeinfo_construct (slang_assembly_typeinfo *); void slang_assembly_typeinfo_destruct (slang_assembly_typeinfo *); /* @@ -49,15 +50,20 @@ void slang_assembly_typeinfo_destruct (slang_assembly_typeinfo *); returns 0 otherwise */ int _slang_typeof_operation (slang_operation *, slang_assembly_name_space *, - slang_assembly_typeinfo *); + slang_assembly_typeinfo *, slang_atom_pool *); /* 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); +int _slang_typeof_function (slang_atom a_name, slang_operation *params, unsigned int num_params, + slang_assembly_name_space *space, slang_type_specifier *spec, int *exists, slang_atom_pool *); + +int _slang_type_is_matrix (slang_type_specifier_type); +int _slang_type_is_vector (slang_type_specifier_type); +slang_type_specifier_type _slang_type_base (slang_type_specifier_type); +unsigned int _slang_type_dim (slang_type_specifier_type); #ifdef __cplusplus } diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c index ce5653c6c5..11243202db 100644 --- a/src/mesa/shader/slang/slang_compile.c +++ b/src/mesa/shader/slang/slang_compile.c @@ -59,30 +59,83 @@ static GLuint slang_var_pool_alloc (slang_var_pool *pool, unsigned int size) int slang_translation_unit_construct (slang_translation_unit *unit) { - if (!slang_variable_scope_construct (&unit->globals)) + unit->assembly = (slang_assembly_file *) slang_alloc_malloc (sizeof (slang_assembly_file)); + if (unit->assembly == NULL) return 0; - if (!slang_function_scope_construct (&unit->functions)) + if (!slang_assembly_file_construct (unit->assembly)) { - slang_variable_scope_destruct (&unit->globals); + slang_alloc_free (unit->assembly); return 0; - } - if (!slang_struct_scope_construct (&unit->structs)) + } + unit->global_pool = (slang_var_pool *) slang_alloc_malloc (sizeof (slang_var_pool)); + if (unit->global_pool == NULL) + { + slang_assembly_file_destruct (unit->assembly); + slang_alloc_free (unit->assembly); + return 0; + } + unit->global_pool->next_addr = 0; + unit->machine = (slang_machine *) slang_alloc_malloc (sizeof (slang_machine)); + if (unit->machine == NULL) + { + slang_alloc_free (unit->global_pool); + slang_assembly_file_destruct (unit->assembly); + slang_alloc_free (unit->assembly); + return 0; + } + slang_machine_init (unit->machine); + unit->atom_pool = (slang_atom_pool *) slang_alloc_malloc (sizeof (slang_atom_pool)); + if (unit->atom_pool == NULL) + { + slang_alloc_free (unit->machine); + slang_alloc_free (unit->global_pool); + slang_assembly_file_destruct (unit->assembly); + slang_alloc_free (unit->assembly); + return 0; + } + slang_atom_pool_construct (unit->atom_pool); + if (!slang_translation_unit_construct2 (unit, unit->assembly, unit->global_pool, unit->machine, + unit->atom_pool)) + { + slang_alloc_free (unit->atom_pool); + slang_alloc_free (unit->machine); + slang_alloc_free (unit->global_pool); + slang_assembly_file_destruct (unit->assembly); + slang_alloc_free (unit->assembly); + return 0; + } + unit->free_assembly = 1; + unit->free_global_pool = 1; + unit->free_machine = 1; + unit->free_atom_pool = 1; + return 1; +} + +int slang_translation_unit_construct2 (slang_translation_unit *unit, slang_assembly_file *file, + slang_var_pool *pool, struct slang_machine_ *mach, slang_atom_pool *atoms) +{ + if (!slang_variable_scope_construct (&unit->globals)) + return 0; + if (!slang_function_scope_construct (&unit->functions)) { slang_variable_scope_destruct (&unit->globals); - slang_function_scope_destruct (&unit->functions); return 0; } - unit->assembly = (slang_assembly_file *) slang_alloc_malloc (sizeof (slang_assembly_file)); - if (unit->assembly == NULL) + if (!slang_struct_scope_construct (&unit->structs)) { slang_variable_scope_destruct (&unit->globals); slang_function_scope_destruct (&unit->functions); - slang_struct_scope_destruct (&unit->structs); return 0; } - slang_assembly_file_construct (unit->assembly); - unit->global_pool.next_addr = 0; - return 1; + unit->assembly = file; + unit->free_assembly = 0; + unit->global_pool = pool; + unit->free_global_pool = 0; + unit->machine = mach; + unit->free_machine = 0; + unit->atom_pool = atoms; + unit->free_atom_pool = 0; + return 1; } void slang_translation_unit_destruct (slang_translation_unit *unit) @@ -90,8 +143,20 @@ void slang_translation_unit_destruct (slang_translation_unit *unit) slang_variable_scope_destruct (&unit->globals); slang_function_scope_destruct (&unit->functions); slang_struct_scope_destruct (&unit->structs); - slang_assembly_file_destruct (unit->assembly); - slang_alloc_free (unit->assembly); + if (unit->free_assembly) + { + slang_assembly_file_destruct (unit->assembly); + slang_alloc_free (unit->assembly); + } + if (unit->free_global_pool) + slang_alloc_free (unit->global_pool); + if (unit->free_machine) + slang_alloc_free (unit->machine); + if (unit->free_atom_pool) + { + slang_atom_pool_destruct (unit->atom_pool); + slang_alloc_free (unit->atom_pool); + } } /* slang_info_log */ @@ -182,7 +247,8 @@ typedef struct slang_parse_ctx_ const byte *I; slang_info_log *L; int parsing_builtin; - int global_scope; + int global_scope; + slang_atom_pool *atoms; } slang_parse_ctx; /* slang_output_ctx */ @@ -194,20 +260,24 @@ typedef struct slang_output_ctx_ slang_struct_scope *structs; slang_assembly_file *assembly; slang_var_pool *global_pool; + slang_machine *machine; } slang_output_ctx; /* _slang_compile() */ -static int parse_identifier (slang_parse_ctx *C, char **id) +static void parse_identifier_str (slang_parse_ctx *C, char **id) { - *id = slang_string_duplicate ((const char *) C->I); - if (*id == NULL) - { - slang_info_log_memory (C->L); - return 0; - } - C->I += _mesa_strlen ((const char *) C->I) + 1; - return 1; + *id = (char *) C->I; + C->I += _mesa_strlen (*id) + 1; +} + +static slang_atom parse_identifier (slang_parse_ctx *C) +{ + const char *id; + + id = (const char *) C->I; + C->I += _mesa_strlen (id) + 1; + return slang_atom_pool_atom (C->atoms, id); } static int parse_number (slang_parse_ctx *C, int *number) @@ -239,30 +309,14 @@ static int parse_float (slang_parse_ctx *C, float *number) char *exponent = NULL; char *whole = NULL; - if (!parse_identifier (C, &integral)) - return 0; - - if (!parse_identifier (C, &fractional)) - { - slang_alloc_free (integral); - return 0; - } - - if (!parse_identifier (C, &exponent)) - { - slang_alloc_free (fractional); - slang_alloc_free (integral); - return 0; - } + parse_identifier_str (C, &integral); + parse_identifier_str (C, &fractional); + parse_identifier_str (C, &exponent); - whole = (char *) (slang_alloc_malloc ((_mesa_strlen (integral) + - _mesa_strlen (fractional) + _mesa_strlen (exponent) + 3) * - sizeof (char))); + whole = (char *) (slang_alloc_malloc ((_mesa_strlen (integral) + _mesa_strlen (fractional) + + _mesa_strlen (exponent) + 3) * sizeof (char))); if (whole == NULL) { - slang_alloc_free (exponent); - slang_alloc_free (fractional); - slang_alloc_free (integral); slang_info_log_memory (C->L); return 0; } @@ -276,14 +330,11 @@ static int parse_float (slang_parse_ctx *C, float *number) *number = (float) (_mesa_strtod(whole, (char **)NULL)); slang_alloc_free (whole); - slang_alloc_free (exponent); - slang_alloc_free (fractional); - slang_alloc_free (integral); return 1; } /* revision number - increment after each change affecting emitted output */ -#define REVISION 2 +#define REVISION 3 static int check_revision (slang_parse_ctx *C) { @@ -307,8 +358,10 @@ static int parse_type_specifier (slang_parse_ctx *, slang_output_ctx *, slang_ty static int parse_struct_field_var (slang_parse_ctx *C, slang_output_ctx *O, slang_variable *var) { - if (!parse_identifier (C, &var->name)) + var->a_name = parse_identifier (C); + if (var->a_name == SLANG_ATOM_NULL) return 0; + switch (*C->I++) { case FIELD_NONE: @@ -332,6 +385,7 @@ static int parse_struct_field_var (slang_parse_ctx *C, slang_output_ctx *O, slan default: return 0; } + return 1; } @@ -355,7 +409,7 @@ static int parse_struct_field (slang_parse_ctx *C, slang_output_ctx *O, slang_st slang_info_log_memory (C->L); return 0; } - var = st->fields->variables + st->fields->num_variables; + var = &st->fields->variables[st->fields->num_variables]; if (!slang_variable_construct (var)) return 0; st->fields->num_variables++; @@ -365,25 +419,30 @@ static int parse_struct_field (slang_parse_ctx *C, slang_output_ctx *O, slang_st return 0; } while (*C->I++ != FIELD_NONE); + return 1; } static int parse_struct (slang_parse_ctx *C, slang_output_ctx *O, slang_struct **st) { - char *name; + slang_atom a_name; + const char *name; - if (!parse_identifier (C, &name)) + /* parse struct name (if any) and make sure it is unique in current scope */ + a_name = parse_identifier (C); + if (a_name == SLANG_ATOM_NULL) return 0; - if (name[0] != '\0' && slang_struct_scope_find (O->structs, name, 0) != NULL) + name = slang_atom_pool_id (C->atoms, a_name); + if (name[0] != '\0' && slang_struct_scope_find (O->structs, a_name, 0) != NULL) { slang_info_log_error (C->L, "%s: duplicate type name", name); - slang_alloc_free (name); return 0; } + + /* set-up a new struct */ *st = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct)); if (*st == NULL) { - slang_alloc_free (name); slang_info_log_memory (C->L); return 0; } @@ -391,13 +450,13 @@ static int parse_struct (slang_parse_ctx *C, slang_output_ctx *O, slang_struct * { slang_alloc_free (*st); *st = NULL; - slang_alloc_free (name); slang_info_log_memory (C->L); return 0; } - (**st).name = name; + (**st).a_name = a_name; (**st).structs->outer_scope = O->structs; + /* parse individual struct fields */ do { slang_type_specifier sp; @@ -412,13 +471,14 @@ static int parse_struct (slang_parse_ctx *C, slang_output_ctx *O, slang_struct * } while (*C->I++ != FIELD_NONE); - if ((**st).name != '\0') + /* if named struct, copy it to current scope */ + if (name[0] != '\0') { slang_struct *s; O->structs->structs = (slang_struct *) slang_alloc_realloc (O->structs->structs, - O->structs->num_structs * sizeof (slang_struct), - (O->structs->num_structs + 1) * sizeof (slang_struct)); + O->structs->num_structs * sizeof (slang_struct), + (O->structs->num_structs + 1) * sizeof (slang_struct)); if (O->structs->structs == NULL) { slang_info_log_memory (C->L); @@ -576,21 +636,24 @@ static int parse_type_specifier (slang_parse_ctx *C, slang_output_ctx *O, slang_ if (!parse_struct (C, O, &spec->_struct)) return 0; break; - case TYPE_SPECIFIER_TYPENAME: + case TYPE_SPECIFIER_TYPENAME: spec->type = slang_spec_struct; { - char *name; - slang_struct *stru; - if (!parse_identifier (C, &name)) - return 0; - stru = slang_struct_scope_find (O->structs, name, 1); + slang_atom a_name; + slang_struct *stru; + + a_name = parse_identifier (C); + if (a_name == NULL) + return 0; + + stru = slang_struct_scope_find (O->structs, a_name, 1); if (stru == NULL) { - slang_info_log_error (C->L, "%s: undeclared type name", name); - slang_alloc_free (name); + slang_info_log_error (C->L, "%s: undeclared type name", + slang_atom_pool_id (C->atoms, a_name)); return 0; } - slang_alloc_free (name); + spec->_struct = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct)); if (spec->_struct == NULL) { @@ -687,7 +750,9 @@ static int parse_fully_specified_type (slang_parse_ctx *C, slang_output_ctx *O, static int parse_child_operation (slang_parse_ctx *C, slang_output_ctx *O, slang_operation *oper, int statement) -{ +{ + slang_operation *ch; + oper->children = (slang_operation *) slang_alloc_realloc (oper->children, oper->num_children * sizeof (slang_operation), (oper->num_children + 1) * sizeof (slang_operation)); @@ -695,16 +760,17 @@ static int parse_child_operation (slang_parse_ctx *C, slang_output_ctx *O, slang { slang_info_log_memory (C->L); return 0; - } - if (!slang_operation_construct (oper->children + oper->num_children)) + } + ch = &oper->children[oper->num_children]; + if (!slang_operation_construct (ch)) { slang_info_log_memory (C->L); return 0; } oper->num_children++; if (statement) - return parse_statement (C, O, &oper->children[oper->num_children - 1]); - return parse_expression (C, O, &oper->children[oper->num_children - 1]); + return parse_statement (C, O, ch); + return parse_expression (C, O, ch); } static int parse_declaration (slang_parse_ctx *C, slang_output_ctx *O); @@ -714,29 +780,34 @@ static int parse_statement (slang_parse_ctx *C, slang_output_ctx *O, slang_opera oper->locals->outer_scope = O->vars; switch (*C->I++) { - case OP_BLOCK_BEGIN_NO_NEW_SCOPE: + case OP_BLOCK_BEGIN_NO_NEW_SCOPE: + /* parse child statements, do not create new variable scope */ oper->type = slang_oper_block_no_new_scope; while (*C->I != OP_END) if (!parse_child_operation (C, O, oper, 1)) return 0; C->I++; break; - case OP_BLOCK_BEGIN_NEW_SCOPE: - oper->type = slang_oper_block_new_scope; - while (*C->I != OP_END) + case OP_BLOCK_BEGIN_NEW_SCOPE: + /* parse child statements, create new variable scope */ { slang_output_ctx o = *O; + + oper->type = slang_oper_block_new_scope; o.vars = oper->locals; - if (!parse_child_operation (C, &o, oper, 1)) - return 0; + while (*C->I != OP_END) + if (!parse_child_operation (C, &o, oper, 1)) + return 0; + C->I++; } - C->I++; break; - case OP_DECLARE: + case OP_DECLARE: + /* local variable declaration, individual declarators are stored as children identifiers */ oper->type = slang_oper_variable_decl; { const unsigned int first_var = O->vars->num_variables; - + + /* parse the declaration, note that there can be zero or more than one declarators */ if (!parse_declaration (C, O)) return 0; if (first_var < O->vars->num_variables) @@ -751,36 +822,28 @@ static int parse_statement (slang_parse_ctx *C, slang_output_ctx *O, slang_opera slang_info_log_memory (C->L); return 0; } - for (i = 0; i < num_vars; i++) - if (!slang_operation_construct (oper->children + i)) + for (oper->num_children = 0; oper->num_children < num_vars; oper->num_children++) + if (!slang_operation_construct (&oper->children[oper->num_children])) { - 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 < O->vars->num_variables; i++) { - slang_operation *o = oper->children + i - first_var; + slang_operation *o = &oper->children[i - first_var]; + o->type = slang_oper_identifier; o->locals->outer_scope = O->vars; - o->identifier = slang_string_duplicate (O->vars->variables[i].name); - if (o->identifier == NULL) - { - slang_info_log_memory (C->L); - return 0; - } + o->a_id = O->vars->variables[i].a_name; } } } break; - case OP_ASM: - oper->type = slang_oper_asm; - if (!parse_identifier (C, &oper->identifier)) + case OP_ASM: + /* the __asm statement, parse the mnemonic and all its arguments as expressions */ + oper->type = slang_oper_asm; + oper->a_id = parse_identifier (C); + if (oper->a_id == SLANG_ATOM_NULL) return 0; while (*C->I != OP_END) if (!parse_child_operation (C, O, oper, 0)) @@ -816,9 +879,10 @@ static int parse_statement (slang_parse_ctx *C, slang_output_ctx *O, slang_opera return 0; break; case OP_WHILE: - oper->type = slang_oper_while; { slang_output_ctx o = *O; + + oper->type = slang_oper_while; o.vars = oper->locals; if (!parse_child_operation (C, &o, oper, 1)) return 0; @@ -834,9 +898,10 @@ static int parse_statement (slang_parse_ctx *C, slang_output_ctx *O, slang_opera return 0; break; case OP_FOR: - oper->type = slang_oper_for; { slang_output_ctx o = *O; + + oper->type = slang_oper_for; o.vars = oper->locals; if (!parse_child_operation (C, &o, oper, 1)) return 0; @@ -852,85 +917,41 @@ static int parse_statement (slang_parse_ctx *C, slang_output_ctx *O, slang_opera return 0; } return 1; +} + +static int handle_nary_expression (slang_parse_ctx *C, slang_operation *op, slang_operation **ops, + unsigned int *total_ops, unsigned int n) +{ + unsigned int i; + + op->children = (slang_operation *) slang_alloc_malloc (n * sizeof (slang_operation)); + if (op->children == NULL) + { + slang_info_log_memory (C->L); + return 0; + } + op->num_children = n; + + for (i = 0; i < n; i++) + op->children[i] = (*ops)[*total_ops - (n + 1 - i)]; + (*ops)[*total_ops - (n + 1)] = (*ops)[*total_ops - 1]; + *total_ops -= n; + + *ops = (slang_operation *) slang_alloc_realloc (*ops, (*total_ops + n) * sizeof (slang_operation), + *total_ops * sizeof (slang_operation)); + if (*ops == NULL) + { + slang_info_log_memory (C->L); + return 0; + } + return 1; } -static int handle_trinary_expression (slang_parse_ctx *C, slang_operation *op, - slang_operation **ops, unsigned int *num_ops) -{ - op->num_children = 3; - op->children = (slang_operation *) slang_alloc_malloc (3 * sizeof (slang_operation)); - if (op->children == NULL) - { - slang_info_log_memory (C->L); - return 0; - } - op->children[0] = (*ops)[*num_ops - 4]; - op->children[1] = (*ops)[*num_ops - 3]; - op->children[2] = (*ops)[*num_ops - 2]; - (*ops)[*num_ops - 4] = (*ops)[*num_ops - 1]; - *num_ops -= 3; - *ops = (slang_operation *) slang_alloc_realloc (*ops, (*num_ops + 3) * sizeof (slang_operation), - *num_ops * sizeof (slang_operation)); - if (*ops == NULL) - { - slang_info_log_memory (C->L); - return 0; - } - return 1; -} - -static int handle_binary_expression (slang_parse_ctx *C, slang_operation *op, - slang_operation **ops, unsigned int *num_ops) -{ - op->num_children = 2; - op->children = (slang_operation *) slang_alloc_malloc (2 * sizeof (slang_operation)); - if (op->children == NULL) - { - slang_info_log_memory (C->L); - return 0; - } - op->children[0] = (*ops)[*num_ops - 3]; - op->children[1] = (*ops)[*num_ops - 2]; - (*ops)[*num_ops - 3] = (*ops)[*num_ops - 1]; - *num_ops -= 2; - *ops = (slang_operation *) slang_alloc_realloc (*ops, (*num_ops + 2) * sizeof (slang_operation), - *num_ops * sizeof (slang_operation)); - if (*ops == NULL) - { - slang_info_log_memory (C->L); - return 0; - } - return 1; -} - -static int handle_unary_expression (slang_parse_ctx *C, slang_operation *op, - slang_operation **ops, unsigned int *num_ops) -{ - op->num_children = 1; - op->children = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation)); - if (op->children == NULL) - { - slang_info_log_memory (C->L); - return 0; - } - op->children[0] = (*ops)[*num_ops - 2]; - (*ops)[*num_ops - 2] = (*ops)[*num_ops - 1]; - (*num_ops)--; - *ops = (slang_operation *) slang_alloc_realloc (*ops, (*num_ops + 1) * sizeof (slang_operation), - *num_ops * sizeof (slang_operation)); - if (*ops == NULL) - { - slang_info_log_memory (C->L); - return 0; - } - return 1; -} - -static int is_constructor_name (const char *name, slang_struct_scope *structs) +static int is_constructor_name (const char *name, slang_atom a_name, slang_struct_scope *structs) { if (slang_type_specifier_type_from_string (name) != slang_spec_void) return 1; - return slang_struct_scope_find (structs, name, 1) != NULL; + return slang_struct_scope_find (structs, a_name, 1) != NULL; } static int parse_expression (slang_parse_ctx *C, slang_output_ctx *O, slang_operation *oper) @@ -942,7 +963,9 @@ static int parse_expression (slang_parse_ctx *C, slang_output_ctx *O, slang_oper while (*C->I != OP_END) { slang_operation *op; - const unsigned int op_code = *C->I++; + const unsigned int op_code = *C->I++; + + /* allocate default operation, becomes a no-op if not used */ ops = (slang_operation *) slang_alloc_realloc (ops, num_ops * sizeof (slang_operation), (num_ops + 1) * sizeof (slang_operation)); if (ops == NULL) @@ -950,14 +973,15 @@ static int parse_expression (slang_parse_ctx *C, slang_output_ctx *O, slang_oper slang_info_log_memory (C->L); return 0; } - op = ops + num_ops; + op = &ops[num_ops]; if (!slang_operation_construct (op)) { slang_info_log_memory (C->L); return 0; } num_ops++; - op->locals->outer_scope = O->vars; + op->locals->outer_scope = O->vars; + switch (op_code) { case OP_PUSH_VOID: @@ -967,13 +991,13 @@ static int parse_expression (slang_parse_ctx *C, slang_output_ctx *O, slang_oper op->type = slang_oper_literal_bool; if (!parse_number (C, &number)) return 0; - op->literal = (float) number; + op->literal = (GLfloat) number; break; case OP_PUSH_INT: op->type = slang_oper_literal_int; if (!parse_number (C, &number)) return 0; - op->literal = (float) number; + op->literal = (GLfloat) number; break; case OP_PUSH_FLOAT: op->type = slang_oper_literal_float; @@ -982,37 +1006,38 @@ static int parse_expression (slang_parse_ctx *C, slang_output_ctx *O, slang_oper break; case OP_PUSH_IDENTIFIER: op->type = slang_oper_identifier; - if (!parse_identifier (C, &op->identifier)) + op->a_id = parse_identifier (C); + if (op->a_id == SLANG_ATOM_NULL) return 0; break; case OP_SEQUENCE: op->type = slang_oper_sequence; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_ASSIGN: op->type = slang_oper_assign; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_ADDASSIGN: op->type = slang_oper_addassign; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_SUBASSIGN: op->type = slang_oper_subassign; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_MULASSIGN: op->type = slang_oper_mulassign; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_DIVASSIGN: op->type = slang_oper_divassign; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; /*case OP_MODASSIGN:*/ @@ -1023,22 +1048,22 @@ static int parse_expression (slang_parse_ctx *C, slang_output_ctx *O, slang_oper /*case OP_ANDASSIGN:*/ case OP_SELECT: op->type = slang_oper_select; - if (!handle_trinary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 3)) return 0; break; case OP_LOGICALOR: op->type = slang_oper_logicalor; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_LOGICALXOR: op->type = slang_oper_logicalxor; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_LOGICALAND: op->type = slang_oper_logicaland; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; /*case OP_BITOR:*/ @@ -1046,126 +1071,133 @@ static int parse_expression (slang_parse_ctx *C, slang_output_ctx *O, slang_oper /*case OP_BITAND:*/ case OP_EQUAL: op->type = slang_oper_equal; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_NOTEQUAL: op->type = slang_oper_notequal; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_LESS: op->type = slang_oper_less; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_GREATER: op->type = slang_oper_greater; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_LESSEQUAL: op->type = slang_oper_lessequal; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_GREATEREQUAL: op->type = slang_oper_greaterequal; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; /*case OP_LSHIFT:*/ /*case OP_RSHIFT:*/ case OP_ADD: op->type = slang_oper_add; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_SUBTRACT: op->type = slang_oper_subtract; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_MULTIPLY: op->type = slang_oper_multiply; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_DIVIDE: op->type = slang_oper_divide; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; /*case OP_MODULUS:*/ case OP_PREINCREMENT: op->type = slang_oper_preincrement; - if (!handle_unary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 1)) return 0; break; case OP_PREDECREMENT: op->type = slang_oper_predecrement; - if (!handle_unary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 1)) return 0; break; case OP_PLUS: op->type = slang_oper_plus; - if (!handle_unary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 1)) return 0; break; case OP_MINUS: op->type = slang_oper_minus; - if (!handle_unary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 1)) return 0; break; case OP_NOT: op->type = slang_oper_not; - if (!handle_unary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 1)) return 0; break; /*case OP_COMPLEMENT:*/ case OP_SUBSCRIPT: op->type = slang_oper_subscript; - if (!handle_binary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 2)) return 0; break; case OP_CALL: op->type = slang_oper_call; - if (!parse_identifier (C, &op->identifier)) + op->a_id = parse_identifier (C); + if (op->a_id == SLANG_ATOM_NULL) return 0; while (*C->I != OP_END) if (!parse_child_operation (C, O, op, 0)) return 0; C->I++; - if (!C->parsing_builtin && - !slang_function_scope_find_by_name (O->funs, op->identifier, 1) && - !is_constructor_name (op->identifier, O->structs)) - { - slang_info_log_error (C->L, "%s: undeclared function name", op->identifier); - return 0; + if (!C->parsing_builtin && !slang_function_scope_find_by_name (O->funs, op->a_id, 1)) + { + const char *id; + + id = slang_atom_pool_id (C->atoms, op->a_id); + if (!is_constructor_name (id, op->a_id, O->structs)) + { + slang_info_log_error (C->L, "%s: undeclared function name", id); + return 0; + } } break; case OP_FIELD: op->type = slang_oper_field; - if (!parse_identifier (C, &op->identifier)) + op->a_id = parse_identifier (C); + if (op->a_id == SLANG_ATOM_NULL) return 0; - if (!handle_unary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 1)) return 0; break; case OP_POSTINCREMENT: op->type = slang_oper_postincrement; - if (!handle_unary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 1)) return 0; break; case OP_POSTDECREMENT: op->type = slang_oper_postdecrement; - if (!handle_unary_expression (C, op, &ops, &num_ops)) + if (!handle_nary_expression (C, op, &ops, &num_ops, 1)) return 0; break; default: return 0; } } - C->I++; + C->I++; + *oper = *ops; slang_alloc_free (ops); return 1; @@ -1183,7 +1215,10 @@ static int parse_expression (slang_parse_ctx *C, slang_output_ctx *O, slang_oper static int parse_parameter_declaration (slang_parse_ctx *C, slang_output_ctx *O, slang_variable *param) { - slang_storage_aggregate agg; + slang_storage_aggregate agg; + + /* parse and validate the parameter's type qualifiers (there can be two at most) because + * not all combinations are valid */ if (!parse_type_qualifier (C, ¶m->type.qualifier)) return 0; switch (*C->I++) @@ -1215,11 +1250,16 @@ static int parse_parameter_declaration (slang_parse_ctx *C, slang_output_ctx *O, break; default: return 0; - } + } + + /* parse parameter's type specifier and name */ if (!parse_type_specifier (C, O, ¶m->type.specifier)) - return 0; - if (!parse_identifier (C, ¶m->name)) - return 0; + return 0; + param->a_name = parse_identifier (C); + if (param->a_name == SLANG_ATOM_NULL) + return 0; + + /* if the parameter is an array, parse its size (the size must be explicitly defined */ if (*C->I++ == PARAMETER_ARRAY_PRESENT) { param->array_size = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation)); @@ -1236,16 +1276,22 @@ static int parse_parameter_declaration (slang_parse_ctx *C, slang_output_ctx *O, return 0; } if (!parse_expression (C, O, param->array_size)) - return 0; - } - slang_storage_aggregate_construct (&agg); - if (!_slang_aggregate_variable (&agg, ¶m->type.specifier, param->array_size, O->funs, - O->structs, O->vars)) - { - slang_storage_aggregate_destruct (&agg); - return 0; - } - slang_storage_aggregate_destruct (&agg); + return 0; + /* TODO: execute the array_size */ + } + + /* calculate the parameter size */ + if (!slang_storage_aggregate_construct (&agg)) + return 0; + if (!_slang_aggregate_variable (&agg, ¶m->type.specifier, param->array_size, O->funs, + O->structs, O->vars, O->machine, O->assembly, C->atoms)) + { + slang_storage_aggregate_destruct (&agg); + return 0; + } + param->size = _slang_sizeof_aggregate (&agg); + slang_storage_aggregate_destruct (&agg); + /* TODO: allocate the local address here? */ return 1; } @@ -1259,38 +1305,35 @@ static int parse_parameter_declaration (slang_parse_ctx *C, slang_output_ctx *O, #define PARAMETER_NEXT 1 /* operator type */ -#define OPERATOR_ASSIGN 1 -#define OPERATOR_ADDASSIGN 2 -#define OPERATOR_SUBASSIGN 3 -#define OPERATOR_MULASSIGN 4 -#define OPERATOR_DIVASSIGN 5 -/*#define OPERATOR_MODASSIGN 6*/ -/*#define OPERATOR_LSHASSIGN 7*/ -/*#define OPERATOR_RSHASSIGN 8*/ -/*#define OPERATOR_ANDASSIGN 9*/ -/*#define OPERATOR_XORASSIGN 10*/ -/*#define OPERATOR_ORASSIGN 11*/ -#define OPERATOR_LOGICALXOR 12 -/*#define OPERATOR_BITOR 13*/ -/*#define OPERATOR_BITXOR 14*/ -/*#define OPERATOR_BITAND 15*/ -#define OPERATOR_EQUAL 16 -#define OPERATOR_NOTEQUAL 17 -#define OPERATOR_LESS 18 -#define OPERATOR_GREATER 19 -#define OPERATOR_LESSEQUAL 20 -#define OPERATOR_GREATEREQUAL 21 -/*#define OPERATOR_LSHIFT 22*/ -/*#define OPERATOR_RSHIFT 23*/ -#define OPERATOR_MULTIPLY 24 -#define OPERATOR_DIVIDE 25 -/*#define OPERATOR_MODULUS 26*/ -#define OPERATOR_INCREMENT 27 -#define OPERATOR_DECREMENT 28 -#define OPERATOR_PLUS 29 -#define OPERATOR_MINUS 30 -/*#define OPERATOR_COMPLEMENT 31*/ -#define OPERATOR_NOT 32 +#define OPERATOR_ADDASSIGN 1 +#define OPERATOR_SUBASSIGN 2 +#define OPERATOR_MULASSIGN 3 +#define OPERATOR_DIVASSIGN 4 +/*#define OPERATOR_MODASSIGN 5*/ +/*#define OPERATOR_LSHASSIGN 6*/ +/*#define OPERATOR_RSHASSIGN 7*/ +/*#define OPERATOR_ANDASSIGN 8*/ +/*#define OPERATOR_XORASSIGN 9*/ +/*#define OPERATOR_ORASSIGN 10*/ +#define OPERATOR_LOGICALXOR 11 +/*#define OPERATOR_BITOR 12*/ +/*#define OPERATOR_BITXOR 13*/ +/*#define OPERATOR_BITAND 14*/ +#define OPERATOR_LESS 15 +#define OPERATOR_GREATER 16 +#define OPERATOR_LESSEQUAL 17 +#define OPERATOR_GREATEREQUAL 18 +/*#define OPERATOR_LSHIFT 19*/ +/*#define OPERATOR_RSHIFT 20*/ +#define OPERATOR_MULTIPLY 21 +#define OPERATOR_DIVIDE 22 +/*#define OPERATOR_MODULUS 23*/ +#define OPERATOR_INCREMENT 24 +#define OPERATOR_DECREMENT 25 +#define OPERATOR_PLUS 26 +#define OPERATOR_MINUS 27 +/*#define OPERATOR_COMPLEMENT 28*/ +#define OPERATOR_NOT 29 static const struct { unsigned int o_code; @@ -1302,7 +1345,6 @@ static const struct { { OPERATOR_DECREMENT, "--" }, { OPERATOR_SUBASSIGN, "-=" }, { OPERATOR_MINUS, "-" }, - { OPERATOR_NOTEQUAL, "!=" }, { OPERATOR_NOT, "!" }, { OPERATOR_MULASSIGN, "*=" }, { OPERATOR_MULTIPLY, "*" }, @@ -1316,8 +1358,6 @@ static const struct { /*{ OPERATOR_RSHASSIGN, ">>=" },*/ /*{ OPERATOR_RSHIFT, ">>" },*/ { OPERATOR_GREATER, ">" }, - { OPERATOR_EQUAL, "==" }, - { OPERATOR_ASSIGN, "=" }, /*{ OPERATOR_MODASSIGN, "%=" },*/ /*{ OPERATOR_MODULUS, "%" },*/ /*{ OPERATOR_ANDASSIGN, "&=" },*/ @@ -1326,46 +1366,51 @@ static const struct { /*{ OPERATOR_BITOR, "|" },*/ /*{ OPERATOR_COMPLEMENT, "~" },*/ /*{ OPERATOR_XORASSIGN, "^=" },*/ - { OPERATOR_LOGICALXOR, "^^" }/*,*/ + { OPERATOR_LOGICALXOR, "^^" }, /*{ OPERATOR_BITXOR, "^" }*/ }; -static int parse_operator_name (slang_parse_ctx *C, char **pname) +static slang_atom parse_operator_name (slang_parse_ctx *C) { - unsigned int i; - for (i = 0; i < sizeof (operator_names) / sizeof (*operator_names); i++) + unsigned int i; + + for (i = 0; i < sizeof (operator_names) / sizeof (*operator_names); i++) + { if (operator_names[i].o_code == (unsigned int) (*C->I)) { - *pname = slang_string_duplicate (operator_names[i].o_name); - if (*pname == NULL) + slang_atom atom = slang_atom_pool_atom (C->atoms, operator_names[i].o_name); + if (atom == SLANG_ATOM_NULL) { slang_info_log_memory (C->L); return 0; } C->I++; - return 1; - } + return atom; + } + } return 0; } static int parse_function_prototype (slang_parse_ctx *C, slang_output_ctx *O, slang_function *func) -{ +{ + /* parse function type and name */ if (!parse_fully_specified_type (C, O, &func->header.type)) return 0; switch (*C->I++) { - case FUNCTION_ORDINARY: + case FUNCTION_ORDINARY: func->kind = slang_func_ordinary; - if (!parse_identifier (C, &func->header.name)) - return 0; + func->header.a_name = parse_identifier (C); + if (func->header.a_name == SLANG_ATOM_NULL) + return 0; break; case FUNCTION_CONSTRUCTOR: func->kind = slang_func_constructor; if (func->header.type.specifier.type == slang_spec_struct) return 0; - func->header.name = slang_string_duplicate ( + func->header.a_name = slang_atom_pool_atom (C->atoms, slang_type_specifier_type_to_string (func->header.type.specifier.type)); - if (func->header.name == NULL) + if (func->header.a_name == SLANG_ATOM_NULL) { slang_info_log_memory (C->L); return 0; @@ -1373,15 +1418,19 @@ static int parse_function_prototype (slang_parse_ctx *C, slang_output_ctx *O, sl break; case FUNCTION_OPERATOR: func->kind = slang_func_operator; - if (!parse_operator_name (C, &func->header.name)) + func->header.a_name = parse_operator_name (C); + if (func->header.a_name == SLANG_ATOM_NULL) return 0; break; default: return 0; } - func->parameters->outer_scope = O->vars; + + /* parse function parameters */ while (*C->I++ == PARAMETER_NEXT) - { + { + slang_variable *p; + func->parameters->variables = (slang_variable *) slang_alloc_realloc ( func->parameters->variables, func->parameters->num_variables * sizeof (slang_variable), @@ -1390,14 +1439,21 @@ static int parse_function_prototype (slang_parse_ctx *C, slang_output_ctx *O, sl { slang_info_log_memory (C->L); return 0; - } - slang_variable_construct (func->parameters->variables + func->parameters->num_variables); + } + p = &func->parameters->variables[func->parameters->num_variables]; + if (!slang_variable_construct (p)) + return 0; func->parameters->num_variables++; - if (!parse_parameter_declaration (C, O, - &func->parameters->variables[func->parameters->num_variables - 1])) + if (!parse_parameter_declaration (C, O, p)) return 0; - } - func->param_count = func->parameters->num_variables; + } + + /* function formal parameters and local variables share the same scope, so save + * the information about param count in a seperate place + * also link the scope to the global variable scope so when a given identifier is not + * found here, the search process continues in the global space */ + func->param_count = func->parameters->num_variables; + func->parameters->outer_scope = O->vars; return 1; } @@ -1406,7 +1462,9 @@ static int parse_function_definition (slang_parse_ctx *C, slang_output_ctx *O, s slang_output_ctx o = *O; if (!parse_function_prototype (C, O, func)) - return 0; + return 0; + + /* create function's body operation */ func->body = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation)); if (func->body == NULL) { @@ -1420,12 +1478,110 @@ static int parse_function_definition (slang_parse_ctx *C, slang_output_ctx *O, s slang_info_log_memory (C->L); return 0; } + + /* to parse the body the parse context is modified in order to capture parsed variables + * into function's local variable scope */ C->global_scope = 0; o.vars = func->parameters; if (!parse_statement (C, &o, func->body)) return 0; C->global_scope = 1; return 1; +} + +static int initialize_global (slang_assembly_file *file, slang_machine *pmach, + slang_assembly_name_space *space, slang_variable *var, slang_atom_pool *atoms) +{ + slang_assembly_file_restore_point point; + slang_machine mach; + slang_assembly_local_info info; + slang_operation op_id, op_assign; + int result; + slang_assembly_flow_control flow; + slang_assembly_stack_info stk; + + /* save the current assembly */ + if (!slang_assembly_file_restore_point_save (file, &point)) + return 0; + + /* setup the machine */ + mach = *pmach; + mach.ip = file->count; + + /* allocate local storage for expression */ + info.ret_size = 0; + info.addr_tmp = 0; + info.swizzle_tmp = 4; + if (!slang_assembly_file_push_label (file, slang_asm_local_alloc, 20)) + return 0; + if (!slang_assembly_file_push_label (file, slang_asm_enter, 20)) + return 0; + + /* construct the left side of assignment */ + if (!slang_operation_construct (&op_id)) + return 0; + op_id.type = slang_oper_identifier; + op_id.a_id = var->a_name; + + /* put the variable into operation's scope */ + op_id.locals->variables = (slang_variable *) slang_alloc_malloc (sizeof (slang_variable)); + if (op_id.locals->variables == NULL) + { + slang_operation_destruct (&op_id); + return 0; + } + op_id.locals->num_variables = 1; + op_id.locals->variables[0] = *var; + + /* construct the assignment expression */ + if (!slang_operation_construct (&op_assign)) + { + op_id.locals->num_variables = 0; + slang_operation_destruct (&op_id); + return 0; + } + op_assign.type = slang_oper_assign; + op_assign.children = (slang_operation *) slang_alloc_malloc (2 * sizeof (slang_operation)); + if (op_assign.children == NULL) + { + slang_operation_destruct (&op_assign); + op_id.locals->num_variables = 0; + slang_operation_destruct (&op_id); + return 0; + } + op_assign.num_children = 2; + op_assign.children[0] = op_id; + op_assign.children[1] = *var->initializer; + + /* insert the actual expression */ + result = _slang_assemble_operation (file, &op_assign, 0, &flow, space, &info, &stk, pmach, atoms); + + /* carefully destroy the operations */ + op_assign.num_children = 0; + slang_alloc_free (op_assign.children); + op_assign.children = NULL; + slang_operation_destruct (&op_assign); + op_id.locals->num_variables = 0; + slang_operation_destruct (&op_id); + + if (!result) + return 0; + if (!slang_assembly_file_push (file, slang_asm_exit)) + return 0; + + /* execute the expression */ + if (!_slang_execute2 (file, &mach)) + return 0; + + /* restore the old assembly */ + if (!slang_assembly_file_restore_point_load (file, &point)) + return 0; + + /* now we copy the contents of the initialized variable back to the original machine */ + _mesa_memcpy ((GLubyte *) pmach->mem + var->address, (GLubyte *) mach.mem + var->address, + var->size); + + return 1; } /* init declarator list */ @@ -1442,9 +1598,9 @@ static int parse_function_definition (slang_parse_ctx *C, slang_output_ctx *O, s static int parse_init_declarator (slang_parse_ctx *C, slang_output_ctx *O, const slang_fully_specified_type *type) { - slang_variable *var; + slang_variable *var; - /* empty init declatator, e.g. "float ;" */ + /* empty init declatator (without name, e.g. "float ;") */ if (*C->I++ == VARIABLE_NONE) return 1; @@ -1458,12 +1614,15 @@ static int parse_init_declarator (slang_parse_ctx *C, slang_output_ctx *O, return 0; } var = &O->vars->variables[O->vars->num_variables]; - slang_variable_construct (var); + if (!slang_variable_construct (var)) + return 0; O->vars->num_variables++; - /* copy the declarator qualifier type, parse the identifier */ + /* copy the declarator qualifier type, parse the identifier */ + var->global = C->global_scope; var->type.qualifier = type->qualifier; - if (!parse_identifier (C, &var->name)) + var->a_name = parse_identifier (C); + if (var->a_name == SLANG_ATOM_NULL) return 0; switch (*C->I++) @@ -1491,11 +1650,12 @@ static int parse_init_declarator (slang_parse_ctx *C, slang_output_ctx *O, return 0; } if (!parse_expression (C, O, var->initializer)) - return 0; + return 0; + /* TODO: execute the initializer */ break; - case VARIABLE_ARRAY_UNKNOWN: +/* case VARIABLE_ARRAY_UNKNOWN: /* unsized array - mark it as array and copy the specifier to the array element */ - var->type.specifier.type = slang_spec_array; +/* var->type.specifier.type = slang_spec_array; var->type.specifier._array = (slang_type_specifier *) slang_alloc_malloc (sizeof ( slang_type_specifier)); if (var->type.specifier._array == NULL) @@ -1506,9 +1666,9 @@ static int parse_init_declarator (slang_parse_ctx *C, slang_output_ctx *O, slang_type_specifier_construct (var->type.specifier._array); if (!slang_type_specifier_copy (var->type.specifier._array, &type->specifier)) return 0; - break; + break;*/ case VARIABLE_ARRAY_EXPLICIT: - /* an array - mark it as array, copy the specifier to the array element and + /* sized array - mark it as array, copy the specifier to the array element and * parse the expression */ var->type.specifier.type = slang_spec_array; var->type.specifier._array = (slang_type_specifier *) slang_alloc_malloc (sizeof ( @@ -1518,7 +1678,13 @@ static int parse_init_declarator (slang_parse_ctx *C, slang_output_ctx *O, slang_info_log_memory (C->L); return 0; } - slang_type_specifier_construct (var->type.specifier._array); + if (!slang_type_specifier_construct (var->type.specifier._array)) + { + slang_alloc_free (var->type.specifier._array); + var->type.specifier._array = NULL; + slang_info_log_memory (C->L); + return 0; + } if (!slang_type_specifier_copy (var->type.specifier._array, &type->specifier)) return 0; var->array_size = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation)); @@ -1546,15 +1712,29 @@ static int parse_init_declarator (slang_parse_ctx *C, slang_output_ctx *O, { slang_storage_aggregate agg; - slang_storage_aggregate_construct (&agg); + if (!slang_storage_aggregate_construct (&agg)) + return 0; if (!_slang_aggregate_variable (&agg, &var->type.specifier, var->array_size, O->funs, - O->structs, O->vars)) + O->structs, O->vars, O->machine, O->assembly, C->atoms)) { slang_storage_aggregate_destruct (&agg); return 0; } - var->address = slang_var_pool_alloc (O->global_pool, _slang_sizeof_aggregate (&agg)); - slang_storage_aggregate_destruct (&agg); + var->size = _slang_sizeof_aggregate (&agg); + slang_storage_aggregate_destruct (&agg); + var->address = slang_var_pool_alloc (O->global_pool, var->size); + } + + /* initialize global variable */ + if (C->global_scope && var->initializer != NULL) + { + slang_assembly_name_space space; + + space.funcs = O->funs; + space.structs = O->structs; + space.vars = O->vars; + if (!initialize_global (O->assembly, O->machine, &space, var, C->atoms)) + return 0; } return 1; } @@ -1562,13 +1742,17 @@ static int parse_init_declarator (slang_parse_ctx *C, slang_output_ctx *O, static int parse_init_declarator_list (slang_parse_ctx *C, slang_output_ctx *O) { slang_fully_specified_type type; - - slang_fully_specified_type_construct (&type); + + /* parse the fully specified type, common to all declarators */ + if (!slang_fully_specified_type_construct (&type)) + return 0; if (!parse_fully_specified_type (C, O, &type)) { slang_fully_specified_type_destruct (&type); return 0; - } + } + + /* parse declarators, pass-in the parsed type */ do { if (!parse_init_declarator (C, O, &type)) @@ -1577,7 +1761,8 @@ static int parse_init_declarator_list (slang_parse_ctx *C, slang_output_ctx *O) return 0; } } - while (*C->I++ == DECLARATOR_NEXT); + while (*C->I++ == DECLARATOR_NEXT); + slang_fully_specified_type_destruct (&type); return 1; } @@ -1598,7 +1783,7 @@ static int parse_function (slang_parse_ctx *C, slang_output_ctx *O, int definiti return 0; } } - else +/* else { if (!parse_function_prototype (C, O, &parsed_func)) { @@ -1608,7 +1793,7 @@ static int parse_function (slang_parse_ctx *C, slang_output_ctx *O, int definiti } /* find a function with a prototype matching the parsed one - only the current scope - is being searched to allow built-in function overriding */ + * is being searched to allow built-in function overriding */ found_func = slang_function_scope_find (O->funs, &parsed_func, 0); if (found_func == NULL) { @@ -1628,13 +1813,13 @@ static int parse_function (slang_parse_ctx *C, slang_output_ctx *O, int definiti /* return the newly parsed function */ *parsed_func_ret = &O->funs->functions[O->funs->num_functions - 1]; } - else +/* else { /* TODO: check function return type qualifiers and specifiers */ - if (definition) +/* if (definition) { /* destroy the existing function declaration and replace it with the new one */ - if (found_func->body != NULL) +/* if (found_func->body != NULL) { slang_info_log_error (C->L, "%s: function already has a body", parsed_func.header.name); @@ -1647,11 +1832,11 @@ static int parse_function (slang_parse_ctx *C, slang_output_ctx *O, int definiti else { /* another declaration of the same function prototype - ignore it */ - slang_function_destruct (&parsed_func); +/* slang_function_destruct (&parsed_func); } /* return the found function */ - *parsed_func_ret = found_func; +/* *parsed_func_ret = found_func; } /* assemble the parsed function */ @@ -1661,11 +1846,12 @@ static int parse_function (slang_parse_ctx *C, slang_output_ctx *O, int definiti space.funcs = O->funs; space.structs = O->structs; - space.vars = O->vars; - - (**parsed_func_ret).address = O->assembly->count; - /*if (!_slang_assemble_function (O->assembly, *parsed_func_ret, &space)) - return 0;*/ + space.vars = O->vars; + if (!_slang_assemble_function (O->assembly, *parsed_func_ret, &space, O->machine, C->atoms)) + { + const char *name = slang_atom_pool_id (C->atoms, (**parsed_func_ret).header.a_name); + return 0; + } } return 1; } @@ -1676,17 +1862,19 @@ static int parse_function (slang_parse_ctx *C, slang_output_ctx *O, int definiti static int parse_declaration (slang_parse_ctx *C, slang_output_ctx *O) { - slang_function *dummy_func; - switch (*C->I++) { case DECLARATION_INIT_DECLARATOR_LIST: if (!parse_init_declarator_list (C, O)) return 0; break; - case DECLARATION_FUNCTION_PROTOTYPE: - if (!parse_function (C, O, 0, &dummy_func)) - return 0; + case DECLARATION_FUNCTION_PROTOTYPE: + { + slang_function *dummy_func; + + if (!parse_function (C, O, 0, &dummy_func)) + return 0; + } break; default: return 0; @@ -1703,21 +1891,26 @@ static int parse_translation_unit (slang_parse_ctx *C, slang_translation_unit *u { slang_output_ctx o; + /* setup output context */ o.funs = &unit->functions; o.structs = &unit->structs; o.vars = &unit->globals; o.assembly = unit->assembly; - o.global_pool = &unit->global_pool; - + o.global_pool = unit->global_pool; + o.machine = unit->machine; + + /* parse individual functions and declarations */ while (*C->I != EXTERNAL_NULL) - { - slang_function *func; - + { switch (*C->I++) { - case EXTERNAL_FUNCTION_DEFINITION: - if (!parse_function (C, &o, 1, &func)) - return 0; + case EXTERNAL_FUNCTION_DEFINITION: + { + slang_function *func; + + if (!parse_function (C, &o, 1, &func)) + return 0; + } break; case EXTERNAL_DECLARATION: if (!parse_declaration (C, &o)) @@ -1737,36 +1930,38 @@ static int parse_translation_unit (slang_parse_ctx *C, slang_translation_unit *u #define BUILTIN_TOTAL 3 static int compile_binary (const byte *prod, slang_translation_unit *unit, slang_unit_type type, - slang_info_log *log, slang_translation_unit *builtins) + slang_info_log *log, slang_translation_unit *builtins, slang_assembly_file *file, + slang_var_pool *pool, slang_machine *mach, slang_translation_unit *downlink, + slang_atom_pool *atoms) { - slang_parse_ctx C; + slang_parse_ctx C; + + /* create translation unit object */ + if (file != NULL) + { + if (!slang_translation_unit_construct2 (unit, file, pool, mach, atoms)) + return 0; + unit->type = type; + } /* set-up parse context */ C.I = prod; C.L = log; C.parsing_builtin = builtins == NULL; - C.global_scope = 1; + C.global_scope = 1; + C.atoms = unit->atom_pool; if (!check_revision (&C)) - return 0; - - /* create translation unit object */ - slang_translation_unit_construct (unit); - unit->type = type; + { + slang_translation_unit_destruct (unit); + return 0; + } - if (builtins != NULL) + if (downlink != NULL) { - /* link to built-in functions */ - builtins[BUILTIN_COMMON].functions.outer_scope = &builtins[BUILTIN_CORE].functions; - builtins[BUILTIN_TARGET].functions.outer_scope = &builtins[BUILTIN_COMMON].functions; - unit->functions.outer_scope = &builtins[BUILTIN_TARGET].functions; - - /* link to built-in variables - core unit does not define any */ - builtins[BUILTIN_TARGET].globals.outer_scope = &builtins[BUILTIN_COMMON].globals; - unit->globals.outer_scope = &builtins[BUILTIN_TARGET].globals; - - /* link to built-in structure typedefs - only in common unit */ - unit->structs.outer_scope = &builtins[BUILTIN_COMMON].structs; + unit->functions.outer_scope = &downlink->functions; + unit->globals.outer_scope = &downlink->globals; + unit->structs.outer_scope = &downlink->structs; } /* parse translation unit */ @@ -1789,7 +1984,7 @@ static int compile_with_grammar (grammar id, const char *source, slang_translati if (!_slang_preprocess_version (source, &version, &start, log)) return 0; - /* check the syntax */ + /* check the syntax and generate its binary representation */ if (!grammar_fast_check (id, (const byte *) source + start, &prod, &size, 65536)) { char buf[1024]; @@ -1798,8 +1993,10 @@ static int compile_with_grammar (grammar id, const char *source, slang_translati slang_info_log_error (log, buf); return 0; } - - if (!compile_binary (prod, unit, type, log, builtins)) + + /* syntax is okay - translate it to internal representation */ + if (!compile_binary (prod, unit, type, log, builtins, NULL, NULL, NULL, + &builtins[BUILTIN_TARGET], NULL)) { grammar_alloc_free (prod); return 0; @@ -1858,26 +2055,33 @@ static int compile (grammar *id, slang_translation_unit *builtin_units, int *com /* if parsing user-specified shader, load built-in library */ if (type == slang_unit_fragment_shader || type == slang_unit_vertex_shader) { + /* compile core functionality first */ if (!compile_binary (slang_core_gc, &builtin_units[BUILTIN_CORE], - slang_unit_fragment_builtin, log, NULL)) + slang_unit_fragment_builtin, log, NULL, unit->assembly, unit->global_pool, + unit->machine, NULL, unit->atom_pool)) return 0; compiled[BUILTIN_CORE] = 1; + /* compile common functions and variables, link to core */ if (!compile_binary (slang_common_builtin_gc, &builtin_units[BUILTIN_COMMON], - slang_unit_fragment_builtin, log, NULL)) + slang_unit_fragment_builtin, log, NULL, unit->assembly, unit->global_pool, + unit->machine, &builtin_units[BUILTIN_CORE], unit->atom_pool)) return 0; compiled[BUILTIN_COMMON] = 1; + /* compile target-specific functions and variables, link to common */ if (type == slang_unit_fragment_shader) { if (!compile_binary (slang_fragment_builtin_gc, &builtin_units[BUILTIN_TARGET], - slang_unit_fragment_builtin, log, NULL)) + slang_unit_fragment_builtin, log, NULL, unit->assembly, unit->global_pool, + unit->machine, &builtin_units[BUILTIN_COMMON], unit->atom_pool)) return 0; } else if (type == slang_unit_vertex_shader) { if (!compile_binary (slang_vertex_builtin_gc, &builtin_units[BUILTIN_TARGET], - slang_unit_vertex_builtin, log, NULL)) + slang_unit_vertex_builtin, log, NULL, unit->assembly, unit->global_pool, + unit->machine, &builtin_units[BUILTIN_COMMON], unit->atom_pool)) return 0; } compiled[BUILTIN_TARGET] = 1; @@ -1899,20 +2103,28 @@ int _slang_compile (const char *source, slang_translation_unit *unit, slang_unit { int success; grammar id = 0; - slang_translation_unit builtin_units[BUILTIN_TOTAL]; - int compiled[BUILTIN_TOTAL] = { 0 }; - +// slang_translation_unit builtin_units[BUILTIN_TOTAL]; + slang_translation_unit *builtin_units; + int compiled[BUILTIN_TOTAL] = { 0 }; + + /* create the main unit first */ + if (!slang_translation_unit_construct (unit)) + return 0; + unit->type = type; + + builtin_units = (slang_translation_unit *) slang_alloc_malloc (BUILTIN_TOTAL * sizeof (slang_translation_unit)); success = compile (&id, builtin_units, compiled, source, unit, type, log); - /* destroy built-in library */ - if (type == slang_unit_fragment_shader || type == slang_unit_vertex_shader) + /* destroy built-in library */ + /* XXX: free with the unit */ + /*if (type == slang_unit_fragment_shader || type == slang_unit_vertex_shader) { int i; for (i = 0; i < BUILTIN_TOTAL; i++) if (compiled[i] != 0) slang_translation_unit_destruct (&builtin_units[i]); - } + }*/ if (id != 0) grammar_destroy (id); diff --git a/src/mesa/shader/slang/slang_compile.h b/src/mesa/shader/slang/slang_compile.h index dd774dd35e..8c7b96c970 100644 --- a/src/mesa/shader/slang/slang_compile.h +++ b/src/mesa/shader/slang/slang_compile.h @@ -54,10 +54,18 @@ typedef struct slang_translation_unit_ slang_struct_scope structs; slang_unit_type type; struct slang_assembly_file_ *assembly; - slang_var_pool global_pool; + int free_assembly; + slang_var_pool *global_pool; + int free_global_pool; + struct slang_machine_ *machine; + int free_machine; + slang_atom_pool *atom_pool; + int free_atom_pool; } slang_translation_unit; -int slang_translation_unit_construct (slang_translation_unit *); +int slang_translation_unit_construct (slang_translation_unit *); +int slang_translation_unit_construct2 (slang_translation_unit *, struct slang_assembly_file_ *, + slang_var_pool *, struct slang_machine_ *, slang_atom_pool *); void slang_translation_unit_destruct (slang_translation_unit *); typedef struct slang_info_log_ diff --git a/src/mesa/shader/slang/slang_compile_function.c b/src/mesa/shader/slang/slang_compile_function.c index 970c6faef0..d62b009e66 100644 --- a/src/mesa/shader/slang/slang_compile_function.c +++ b/src/mesa/shader/slang/slang_compile_function.c @@ -31,7 +31,6 @@ #include "imports.h" #include "slang_utility.h" #include "slang_compile_variable.h" -#include "slang_compile_struct.h" #include "slang_compile_operation.h" #include "slang_compile_function.h" @@ -91,15 +90,15 @@ void slang_function_scope_destruct (slang_function_scope *scope) slang_alloc_free (scope->functions); } -int slang_function_scope_find_by_name (slang_function_scope *funcs, const char *name, int all_scopes) +int slang_function_scope_find_by_name (slang_function_scope *funcs, slang_atom a_name, int all_scopes) { unsigned int i; for (i = 0; i < funcs->num_functions; i++) - if (slang_string_compare (name, funcs->functions[i].header.name) == 0) + if (a_name == funcs->functions[i].header.a_name) return 1; if (all_scopes && funcs->outer_scope != NULL) - return slang_function_scope_find_by_name (funcs->outer_scope, name, 1); + return slang_function_scope_find_by_name (funcs->outer_scope, a_name, 1); return 0; } @@ -110,10 +109,10 @@ slang_function *slang_function_scope_find (slang_function_scope *funcs, slang_fu for (i = 0; i < funcs->num_functions; i++) { - slang_function *f = funcs->functions + i; + slang_function *f = &funcs->functions[i]; unsigned int j; - if (slang_string_compare (fun->header.name, f->header.name) != 0) + if (fun->header.a_name != f->header.a_name) continue; if (fun->param_count != f->param_count) continue; diff --git a/src/mesa/shader/slang/slang_compile_function.h b/src/mesa/shader/slang/slang_compile_function.h index 7f13bffa92..59743dfc29 100644 --- a/src/mesa/shader/slang/slang_compile_function.h +++ b/src/mesa/shader/slang/slang_compile_function.h @@ -58,7 +58,7 @@ typedef struct slang_function_scope_ int slang_function_scope_construct (slang_function_scope *); void slang_function_scope_destruct (slang_function_scope *); -int slang_function_scope_find_by_name (slang_function_scope *, const char *, int); +int slang_function_scope_find_by_name (slang_function_scope *, slang_atom, int); slang_function *slang_function_scope_find (slang_function_scope *, slang_function *, int); #ifdef __cplusplus diff --git a/src/mesa/shader/slang/slang_compile_operation.c b/src/mesa/shader/slang/slang_compile_operation.c index f6d371a44b..6783f1dc78 100644 --- a/src/mesa/shader/slang/slang_compile_operation.c +++ b/src/mesa/shader/slang/slang_compile_operation.c @@ -31,9 +31,7 @@ #include "imports.h" #include "slang_utility.h" #include "slang_compile_variable.h" -#include "slang_compile_struct.h" #include "slang_compile_operation.h" -#include "slang_compile_function.h" /* slang_operation */ @@ -43,7 +41,7 @@ int slang_operation_construct (slang_operation *oper) oper->children = NULL; oper->num_children = 0; oper->literal = (float) 0; - oper->identifier = NULL; + oper->a_id = SLANG_ATOM_NULL; oper->locals = (slang_variable_scope *) slang_alloc_malloc (sizeof (slang_variable_scope)); if (oper->locals == NULL) return 0; @@ -62,7 +60,6 @@ void slang_operation_destruct (slang_operation *oper) for (i = 0; i < oper->num_children; i++) slang_operation_destruct (oper->children + i); slang_alloc_free (oper->children); - slang_alloc_free (oper->identifier); slang_variable_scope_destruct (oper->locals); slang_alloc_free (oper->locals); } @@ -94,15 +91,7 @@ int slang_operation_copy (slang_operation *x, const slang_operation *y) return 0; } z.literal = y->literal; - if (y->identifier != NULL) - { - z.identifier = slang_string_duplicate (y->identifier); - if (z.identifier == NULL) - { - slang_operation_destruct (&z); - return 0; - } - } + z.a_id = y->a_id; if (!slang_variable_scope_copy (z.locals, y->locals)) { slang_operation_destruct (&z); diff --git a/src/mesa/shader/slang/slang_compile_operation.h b/src/mesa/shader/slang/slang_compile_operation.h index 54b2d17df6..9e64848a0a 100644 --- a/src/mesa/shader/slang/slang_compile_operation.h +++ b/src/mesa/shader/slang/slang_compile_operation.h @@ -101,7 +101,7 @@ typedef struct slang_operation_ struct slang_operation_ *children; unsigned int num_children; float literal; /* type: bool, literal_int, literal_float */ - char *identifier; /* type: asm, identifier, call, field */ + slang_atom a_id; /* type: asm, identifier, call, field */ slang_variable_scope *locals; } slang_operation; diff --git a/src/mesa/shader/slang/slang_compile_struct.c b/src/mesa/shader/slang/slang_compile_struct.c index bad58f4e5b..0828d23598 100644 --- a/src/mesa/shader/slang/slang_compile_struct.c +++ b/src/mesa/shader/slang/slang_compile_struct.c @@ -32,8 +32,6 @@ #include "slang_utility.h" #include "slang_compile_variable.h" #include "slang_compile_struct.h" -#include "slang_compile_operation.h" -#include "slang_compile_function.h" /* slang_struct_scope */ @@ -86,15 +84,15 @@ int slang_struct_scope_copy (slang_struct_scope *x, const slang_struct_scope *y) return 1; } -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, slang_atom a_name, int all_scopes) { unsigned int i; for (i = 0; i < stru->num_structs; i++) - if (slang_string_compare (name, stru->structs[i].name) == 0) - return stru->structs + i; + if (a_name == stru->structs[i].a_name) + return &stru->structs[i]; if (all_scopes && stru->outer_scope != NULL) - return slang_struct_scope_find (stru->outer_scope, name, 1); + return slang_struct_scope_find (stru->outer_scope, a_name, 1); return NULL; } @@ -102,7 +100,7 @@ slang_struct *slang_struct_scope_find (slang_struct_scope *stru, const char *nam int slang_struct_construct (slang_struct *stru) { - stru->name = NULL; + stru->a_name = SLANG_ATOM_NULL; stru->fields = (slang_variable_scope *) slang_alloc_malloc (sizeof (slang_variable_scope)); if (stru->fields == NULL) return 0; @@ -130,7 +128,6 @@ int slang_struct_construct (slang_struct *stru) void slang_struct_destruct (slang_struct *stru) { - slang_alloc_free (stru->name); slang_variable_scope_destruct (stru->fields); slang_alloc_free (stru->fields); slang_struct_scope_destruct (stru->structs); @@ -143,15 +140,7 @@ int slang_struct_copy (slang_struct *x, const slang_struct *y) if (!slang_struct_construct (&z)) return 0; - if (y->name != NULL) - { - z.name = slang_string_duplicate (y->name); - if (z.name == NULL) - { - slang_struct_destruct (&z); - return 0; - } - } + z.a_name = y->a_name; if (!slang_variable_scope_copy (z.fields, y->fields)) { slang_struct_destruct (&z); @@ -175,15 +164,16 @@ int slang_struct_equal (const slang_struct *x, const slang_struct *y) return 0; for (i = 0; i < x->fields->num_variables; i++) { - slang_variable *varx = x->fields->variables + i; - slang_variable *vary = y->fields->variables + i; - if (slang_string_compare (varx->name, vary->name) != 0) + slang_variable *varx = &x->fields->variables[i]; + slang_variable *vary = &y->fields->variables[i]; + + if (varx->a_name != vary->a_name) return 0; if (!slang_type_specifier_equal (&varx->type.specifier, &vary->type.specifier)) return 0; if (varx->type.specifier.type == slang_spec_array) { - /* TODO compare array sizes */ + /* TODO: compare array sizes */ } } return 1; diff --git a/src/mesa/shader/slang/slang_compile_struct.h b/src/mesa/shader/slang/slang_compile_struct.h index 10af980216..4798b6042f 100644 --- a/src/mesa/shader/slang/slang_compile_struct.h +++ b/src/mesa/shader/slang/slang_compile_struct.h @@ -39,11 +39,11 @@ typedef struct slang_struct_scope_ int slang_struct_scope_construct (slang_struct_scope *); void slang_struct_scope_destruct (slang_struct_scope *); int slang_struct_scope_copy (slang_struct_scope *, const slang_struct_scope *); -struct slang_struct_ *slang_struct_scope_find (slang_struct_scope *, const char *, int); +struct slang_struct_ *slang_struct_scope_find (slang_struct_scope *, slang_atom, int); typedef struct slang_struct_ { - char *name; + slang_atom a_name; struct slang_variable_scope_ *fields; slang_struct_scope *structs; } slang_struct; diff --git a/src/mesa/shader/slang/slang_compile_variable.c b/src/mesa/shader/slang/slang_compile_variable.c index 39aabd8312..da3b24fb7e 100644 --- a/src/mesa/shader/slang/slang_compile_variable.c +++ b/src/mesa/shader/slang/slang_compile_variable.c @@ -33,7 +33,6 @@ #include "slang_compile_variable.h" #include "slang_compile_struct.h" #include "slang_compile_operation.h" -#include "slang_compile_function.h" /* slang_type_specifier_type */ @@ -269,17 +268,18 @@ int slang_variable_construct (slang_variable *var) { if (!slang_fully_specified_type_construct (&var->type)) return 0; - var->name = NULL; + var->a_name = SLANG_ATOM_NULL; var->array_size = NULL; var->initializer = NULL; var->address = ~0; + var->size = 0; + var->global = 0; return 1; } void slang_variable_destruct (slang_variable *var) { slang_fully_specified_type_destruct (&var->type); - slang_alloc_free (var->name); if (var->array_size != NULL) { slang_operation_destruct (var->array_size); @@ -303,15 +303,7 @@ int slang_variable_copy (slang_variable *x, const slang_variable *y) slang_variable_destruct (&z); return 0; } - if (y->name != NULL) - { - z.name = slang_string_duplicate (y->name); - if (z.name == NULL) - { - slang_variable_destruct (&z); - return 0; - } - } + z.a_name = y->a_name; if (y->array_size != NULL) { z.array_size = (slang_operation *) slang_alloc_malloc (sizeof (slang_operation)); @@ -352,20 +344,23 @@ int slang_variable_copy (slang_variable *x, const slang_variable *y) return 0; } } + z.address = y->address; + z.size = y->size; + z.global = y->global; slang_variable_destruct (x); *x = z; return 1; } -slang_variable *_slang_locate_variable (slang_variable_scope *scope, const char *name, int all) +slang_variable *_slang_locate_variable (slang_variable_scope *scope, slang_atom a_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 (a_name == scope->variables[i].a_name) + return &scope->variables[i]; if (all && scope->outer_scope != NULL) - return _slang_locate_variable (scope->outer_scope, name, 1); + return _slang_locate_variable (scope->outer_scope, a_name, 1); return NULL; } diff --git a/src/mesa/shader/slang/slang_compile_variable.h b/src/mesa/shader/slang/slang_compile_variable.h index d82a661eda..fc42280ae5 100644 --- a/src/mesa/shader/slang/slang_compile_variable.h +++ b/src/mesa/shader/slang/slang_compile_variable.h @@ -109,17 +109,19 @@ int slang_variable_scope_copy (slang_variable_scope *, const slang_variable_scop typedef struct slang_variable_ { slang_fully_specified_type type; - char *name; + slang_atom a_name; struct slang_operation_ *array_size; /* type: spec_array */ struct slang_operation_ *initializer; unsigned int address; + unsigned int size; + int global; } slang_variable; int slang_variable_construct (slang_variable *); void slang_variable_destruct (slang_variable *); int slang_variable_copy (slang_variable *, const slang_variable *); -slang_variable *_slang_locate_variable (slang_variable_scope *scope, const char *name, int all); +slang_variable *_slang_locate_variable (slang_variable_scope *scope, slang_atom a_name, int all); #ifdef __cplusplus } diff --git a/src/mesa/shader/slang/slang_execute.c b/src/mesa/shader/slang/slang_execute.c index e4df832577..a40a35cd57 100644 --- a/src/mesa/shader/slang/slang_execute.c +++ b/src/mesa/shader/slang/slang_execute.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.3 + * Version: 6.5 * - * Copyright (C) 2005 Brian Paul All Rights Reserved. + * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -34,7 +34,24 @@ #include "slang_storage.h" #include "slang_execute.h" -#define DEBUG_SLANG 1 +#define DEBUG_SLANG 0 + +void slang_machine_init (slang_machine *mach) +{ + mach->ip = 0; + mach->sp = SLANG_MACHINE_STACK_SIZE; + mach->bp = 0; + mach->kill = 0; + mach->exit = 0; +} + +int _slang_execute (const slang_assembly_file *file) +{ + slang_machine mach; + + slang_machine_init (&mach); + return _slang_execute2 (file, &mach); +} #if DEBUG_SLANG @@ -44,6 +61,7 @@ static void dump_instruction (FILE *f, slang_assembly *a, unsigned int i) switch (a->type) { + /* core */ case slang_asm_none: fprintf (f, "none"); break; @@ -74,12 +92,36 @@ static void dump_instruction (FILE *f, slang_assembly *a, unsigned int i) case slang_asm_float_less: fprintf (f, "float_less"); break; - case slang_asm_float_equal: + case slang_asm_float_equal_exp: + fprintf (f, "float_equal"); + break; + case slang_asm_float_equal_int: 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_float_sine: + fprintf (f, "float_sine"); + break; + case slang_asm_float_arcsine: + fprintf (f, "float_arcsine"); + break; + case slang_asm_float_arctan: + fprintf (f, "float_arctan"); + break; + case slang_asm_float_power: + fprintf (f, "float_power"); + break; + case slang_asm_float_log2: + fprintf (f, "float_log2"); + break; + case slang_asm_float_floor: + fprintf (f, "float_floor"); + break; + case slang_asm_float_ceil: + fprintf (f, "float_ceil"); + break; case slang_asm_int_copy: fprintf (f, "int_copy\t%d, %d", a->param[0], a->param[1]); break; @@ -158,6 +200,16 @@ static void dump_instruction (FILE *f, slang_assembly *a, unsigned int i) case slang_asm_exit: fprintf (f, "exit"); break; + /* mesa-specific extensions */ + case slang_asm_float_print: + fprintf (f, "float_print"); + break; + case slang_asm_int_print: + fprintf (f, "int_print"); + break; + case slang_asm_bool_print: + fprintf (f, "bool_print"); + break; default: break; } @@ -186,11 +238,13 @@ static void dump (const slang_assembly_file *file) #endif -int _slang_execute (const slang_assembly_file *file) +int _slang_execute2 (const slang_assembly_file *file, slang_machine *mach) { - slang_machine mach; + slang_machine_slot *stack; -#ifdef DEBUG_SLANG +#if DEBUG_SLANG + static unsigned int counter = 0; + char filename[256]; FILE *f; #endif @@ -198,161 +252,195 @@ int _slang_execute (const slang_assembly_file *file) static_assert(sizeof (GLfloat) == 4); static_assert(sizeof (GLuint) == 4); - mach.ip = 0; - mach.sp = SLANG_MACHINE_STACK_SIZE; - mach.bp = 0; - mach.kill = 0; - mach.exit = 0; - mach.global = mach.mem; - mach.stack = mach.global + SLANG_MACHINE_GLOBAL_SIZE; - #if DEBUG_SLANG dump (file); - f = fopen ("~mesa-slang-assembly-execution.txt", "w"); + counter++; + _mesa_sprintf (filename, "~mesa-slang-assembly-exec-(%u).txt", counter); + f = fopen (filename, "w"); #endif - while (!mach.exit) + stack = mach->mem + SLANG_MACHINE_GLOBAL_SIZE; + + while (!mach->exit) { - slang_assembly *a; + slang_assembly *a = &file->code[mach->ip]; #if DEBUG_SLANG - if (f != NULL) + if (f != NULL && a->type != slang_asm_none) { unsigned int i; - dump_instruction (f, file->code + mach.ip, 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[i]._float, mach.stack[i]._addr); + dump_instruction (f, file->code + mach->ip, 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, stack[i]._float, stack[i]._addr); fflush (f); } #endif - a = file->code + mach.ip; - mach.ip++; + mach->ip++; switch (a->type) { + /* core */ case slang_asm_none: break; case slang_asm_float_copy: case slang_asm_int_copy: case slang_asm_bool_copy: - mach.mem[mach.stack[mach.sp + a->param[0] / 4]._addr + a->param[1] / 4]._float = - mach.stack[mach.sp]._float; - mach.sp++; + mach->mem[(stack[mach->sp + a->param[0] / 4]._addr + a->param[1]) / 4]._float = + stack[mach->sp]._float; + mach->sp++; break; case slang_asm_float_move: case slang_asm_int_move: case slang_asm_bool_move: - mach.stack[mach.sp + a->param[0] / 4]._float = - mach.stack[mach.sp + (mach.stack[mach.sp]._addr + a->param[1]) / 4]._float; + stack[mach->sp + a->param[0] / 4]._float = + stack[mach->sp + (stack[mach->sp]._addr + a->param[1]) / 4]._float; break; case slang_asm_float_push: case slang_asm_int_push: case slang_asm_bool_push: - mach.sp--; - mach.stack[mach.sp]._float = a->literal; + mach->sp--; + stack[mach->sp]._float = a->literal; break; case slang_asm_float_deref: case slang_asm_int_deref: case slang_asm_bool_deref: - mach.stack[mach.sp]._float = mach.mem[mach.stack[mach.sp]._addr]._float; + stack[mach->sp]._float = mach->mem[stack[mach->sp]._addr / 4]._float; break; case slang_asm_float_add: - mach.stack[mach.sp + 1]._float += mach.stack[mach.sp]._float; - mach.sp++; + stack[mach->sp + 1]._float += stack[mach->sp]._float; + mach->sp++; break; case slang_asm_float_multiply: - mach.stack[mach.sp + 1]._float *= mach.stack[mach.sp]._float; - mach.sp++; + stack[mach->sp + 1]._float *= stack[mach->sp]._float; + mach->sp++; break; case slang_asm_float_divide: - mach.stack[mach.sp + 1]._float /= mach.stack[mach.sp]._float; - mach.sp++; + stack[mach->sp + 1]._float /= stack[mach->sp]._float; + mach->sp++; break; case slang_asm_float_negate: - mach.stack[mach.sp]._float = -mach.stack[mach.sp]._float; + stack[mach->sp]._float = -stack[mach->sp]._float; break; case slang_asm_float_less: - mach.stack[mach.sp + 1]._float = - mach.stack[mach.sp + 1]._float < mach.stack[mach.sp]._float ? 1.0f : 0.0f; - mach.sp++; + stack[mach->sp + 1]._float = + stack[mach->sp + 1]._float < stack[mach->sp]._float ? (GLfloat) 1 : (GLfloat) 0; + mach->sp++; + break; + case slang_asm_float_equal_exp: + stack[mach->sp + 1]._float = + stack[mach->sp + 1]._float == stack[mach->sp]._float ? (GLfloat) 1 : (GLfloat) 0; + mach->sp++; break; - case slang_asm_float_equal: - mach.sp--; - mach.stack[mach.sp]._float = mach.stack[mach.sp + 1 + a->param[0] / 4]._float == - mach.stack[mach.sp + 1 + a->param[1] / 4]._float ? 1.0f : 0.0f; + case slang_asm_float_equal_int: + mach->sp--; + stack[mach->sp]._float = stack[mach->sp + 1 + a->param[0] / 4]._float == + stack[mach->sp + 1 + a->param[1] / 4]._float ? (GLfloat) 1 : (GLfloat) 0; break; case slang_asm_float_to_int: - mach.stack[mach.sp]._float = (GLfloat) (GLint) mach.stack[mach.sp]._float; + stack[mach->sp]._float = (GLfloat) (GLint) stack[mach->sp]._float; + break; + case slang_asm_float_sine: + stack[mach->sp]._float = (GLfloat) _mesa_sin (stack[mach->sp]._float); + break; + case slang_asm_float_arcsine: + stack[mach->sp]._float = _mesa_asinf (stack[mach->sp]._float); + break; + case slang_asm_float_arctan: + stack[mach->sp]._float = _mesa_atanf (stack[mach->sp]._float); + break; + case slang_asm_float_power: + stack[mach->sp + 1]._float = + (GLfloat) _mesa_pow (stack[mach->sp + 1]._float, stack[mach->sp]._float); + mach->sp++; + break; + case slang_asm_float_log2: + stack[mach->sp]._float = LOG2 (stack[mach->sp]._float); + break; + case slang_asm_float_floor: + stack[mach->sp]._float = FLOORF (stack[mach->sp]._float); + break; + case slang_asm_float_ceil: + stack[mach->sp]._float = CEILF (stack[mach->sp]._float); break; case slang_asm_int_to_float: break; case slang_asm_int_to_addr: - mach.stack[mach.sp]._addr = (GLuint) (GLint) mach.stack[mach.sp]._float; + stack[mach->sp]._addr = (GLuint) (GLint) stack[mach->sp]._float; break; case slang_asm_addr_copy: - mach.mem[mach.stack[mach.sp + 1]._addr]._addr = mach.stack[mach.sp]._addr; - mach.sp++; + mach->mem[stack[mach->sp + 1]._addr / 4]._addr = stack[mach->sp]._addr; + mach->sp++; break; case slang_asm_addr_push: - mach.sp--; - mach.stack[mach.sp]._addr = a->param[0]; + mach->sp--; + stack[mach->sp]._addr = a->param[0]; break; case slang_asm_addr_deref: - mach.stack[mach.sp]._addr = mach.mem[mach.stack[mach.sp]._addr]._addr; + stack[mach->sp]._addr = mach->mem[stack[mach->sp]._addr / 4]._addr; break; case slang_asm_addr_add: - mach.stack[mach.sp + 1]._addr += mach.stack[mach.sp]._addr; - mach.sp++; + stack[mach->sp + 1]._addr += stack[mach->sp]._addr; + mach->sp++; break; case slang_asm_addr_multiply: - mach.stack[mach.sp + 1]._addr *= mach.stack[mach.sp]._addr; - mach.sp++; + stack[mach->sp + 1]._addr *= stack[mach->sp]._addr; + mach->sp++; break; case slang_asm_jump: - mach.ip = a->param[0]; + mach->ip = a->param[0]; break; case slang_asm_jump_if_zero: - if (mach.stack[mach.sp]._float == 0.0f) - mach.ip = a->param[0]; - mach.sp++; + if (stack[mach->sp]._float == 0.0f) + mach->ip = a->param[0]; + mach->sp++; break; case slang_asm_enter: - mach.sp--; - mach.stack[mach.sp]._addr = mach.bp; - mach.bp = mach.sp + a->param[0] / 4; + mach->sp--; + stack[mach->sp]._addr = mach->bp; + mach->bp = mach->sp + a->param[0] / 4; break; case slang_asm_leave: - mach.bp = mach.stack[mach.sp]._addr; - mach.sp++; + mach->bp = stack[mach->sp]._addr; + mach->sp++; break; case slang_asm_local_alloc: - mach.sp -= a->param[0] / 4; + mach->sp -= a->param[0] / 4; break; case slang_asm_local_free: - mach.sp += a->param[0] / 4; + mach->sp += a->param[0] / 4; break; case slang_asm_local_addr: - mach.sp--; - mach.stack[mach.sp]._addr = SLANG_MACHINE_GLOBAL_SIZE * 4 + mach.bp * 4 - + mach->sp--; + stack[mach->sp]._addr = SLANG_MACHINE_GLOBAL_SIZE * 4 + mach->bp * 4 - (a->param[0] + a->param[1]) + 4; break; case slang_asm_call: - mach.sp--; - mach.stack[mach.sp]._addr = mach.ip; - mach.ip = a->param[0]; + mach->sp--; + stack[mach->sp]._addr = mach->ip; + mach->ip = a->param[0]; break; case slang_asm_return: - mach.ip = mach.stack[mach.sp]._addr; - mach.sp++; + mach->ip = stack[mach->sp]._addr; + mach->sp++; break; case slang_asm_discard: - mach.kill = 1; + mach->kill = 1; break; case slang_asm_exit: - mach.exit = 1; + mach->exit = 1; + break; + /* mesa-specific extensions */ + case slang_asm_float_print: + _mesa_printf ("slang print: %f\n", stack[mach->sp]._float); + break; + case slang_asm_int_print: + _mesa_printf ("slang print: %d\n", (GLint) stack[mach->sp]._float); + break; + case slang_asm_bool_print: + _mesa_printf ("slang print: %s\n", (GLint) stack[mach->sp]._float ? "true" : "false"); break; } } @@ -362,6 +450,6 @@ int _slang_execute (const slang_assembly_file *file) fclose (f); #endif - return 0; + return 1; } diff --git a/src/mesa/shader/slang/slang_execute.h b/src/mesa/shader/slang/slang_execute.h index f911574b15..a3b326f315 100644 --- a/src/mesa/shader/slang/slang_execute.h +++ b/src/mesa/shader/slang/slang_execute.h @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.3 + * Version: 6.5 * - * Copyright (C) 2005 Brian Paul All Rights Reserved. + * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -47,11 +47,12 @@ typedef struct slang_machine_ GLuint kill; /* discard the fragment */ GLuint exit; /* terminate the shader */ slang_machine_slot mem[SLANG_MACHINE_MEMORY_SIZE]; - slang_machine_slot *global; - slang_machine_slot *stack; } slang_machine; +void slang_machine_init (slang_machine *); + int _slang_execute (const slang_assembly_file *); +int _slang_execute2 (const slang_assembly_file *, slang_machine *); #ifdef __cplusplus } diff --git a/src/mesa/shader/slang/slang_preprocess.c b/src/mesa/shader/slang/slang_preprocess.c index b1f62ded3d..3601a384f7 100644 --- a/src/mesa/shader/slang/slang_preprocess.c +++ b/src/mesa/shader/slang/slang_preprocess.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.3 + * Version: 6.5 * - * Copyright (C) 2005 Brian Paul All Rights Reserved. + * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -30,6 +30,7 @@ #include "imports.h" #include "grammar_mesa.h" +#include "slang_utility.h" #include "slang_compile.h" #include "slang_preprocess.h" diff --git a/src/mesa/shader/slang/slang_storage.c b/src/mesa/shader/slang/slang_storage.c index 8a608c4902..a2d1ab9314 100644 --- a/src/mesa/shader/slang/slang_storage.c +++ b/src/mesa/shader/slang/slang_storage.c @@ -31,15 +31,17 @@ #include "imports.h" #include "slang_utility.h" #include "slang_storage.h" -#include "slang_assemble.h" +#include "slang_assemble.h" +#include "slang_execute.h" /* slang_storage_array */ -void slang_storage_array_construct (slang_storage_array *arr) +int slang_storage_array_construct (slang_storage_array *arr) { arr->type = slang_stor_aggregate; arr->aggregate = NULL; - arr->length = 0; + arr->length = 0; + return 1; } void slang_storage_array_destruct (slang_storage_array *arr) @@ -53,15 +55,17 @@ void slang_storage_array_destruct (slang_storage_array *arr) /* slang_storage_aggregate */ -void slang_storage_aggregate_construct (slang_storage_aggregate *agg) +int slang_storage_aggregate_construct (slang_storage_aggregate *agg) { agg->arrays = NULL; - agg->count = 0; + agg->count = 0; + return 1; } void slang_storage_aggregate_destruct (slang_storage_aggregate *agg) { - unsigned int i; + unsigned int i; + for (i = 0; i < agg->count; i++) slang_storage_array_destruct (agg->arrays + i); slang_alloc_free (agg->arrays); @@ -75,7 +79,8 @@ static slang_storage_array *slang_storage_aggregate_push_new (slang_storage_aggr if (agg->arrays != NULL) { arr = agg->arrays + agg->count; - slang_storage_array_construct (arr); + if (!slang_storage_array_construct (arr)) + return NULL; agg->count++; } return arr; @@ -97,7 +102,7 @@ static int aggregate_vector (slang_storage_aggregate *agg, slang_storage_type ba static int aggregate_matrix (slang_storage_aggregate *agg, slang_storage_type basic_type, unsigned int dimension) { - slang_storage_array *arr = slang_storage_aggregate_push_new (agg); + slang_storage_array *arr = slang_storage_aggregate_push_new (agg); if (arr == NULL) return 0; arr->type = slang_stor_aggregate; @@ -106,26 +111,80 @@ static int aggregate_matrix (slang_storage_aggregate *agg, slang_storage_type ba slang_storage_aggregate)); if (arr->aggregate == NULL) return 0; - slang_storage_aggregate_construct (arr->aggregate); + if (!slang_storage_aggregate_construct (arr->aggregate)) + { + slang_alloc_free (arr->aggregate); + arr->aggregate = NULL; + return 0; + } if (!aggregate_vector (arr->aggregate, basic_type, dimension)) return 0; return 1; } static int aggregate_variables (slang_storage_aggregate *agg, slang_variable_scope *vars, - slang_function_scope *funcs, slang_struct_scope *structs, slang_variable_scope *globals) + slang_function_scope *funcs, slang_struct_scope *structs, slang_variable_scope *globals, + slang_machine *mach, slang_assembly_file *file, slang_atom_pool *atoms) { 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, globals)) + vars->variables[i].array_size, funcs, structs, globals, mach, file, atoms)) return 0; return 1; } + +static int eval_array_size (slang_assembly_file *file, slang_machine *pmach, + slang_assembly_name_space *space, slang_operation *array_size, GLuint *plength, + slang_atom_pool *atoms) +{ + slang_assembly_file_restore_point point; + slang_assembly_local_info info; + slang_assembly_flow_control flow; + slang_assembly_stack_info stk; + slang_machine mach; + + /* save the current assembly */ + if (!slang_assembly_file_restore_point_save (file, &point)) + return 0; + + /* setup the machine */ + mach = *pmach; + mach.ip = file->count; + + /* allocate local storage for expression */ + info.ret_size = 0; + info.addr_tmp = 0; + info.swizzle_tmp = 4; + if (!slang_assembly_file_push_label (file, slang_asm_local_alloc, 20)) + return 0; + if (!slang_assembly_file_push_label (file, slang_asm_enter, 20)) + return 0; + + /* insert the actual expression */ + if (!_slang_assemble_operation (file, array_size, 0, &flow, space, &info, &stk, pmach, atoms)) + return 0; + if (!slang_assembly_file_push (file, slang_asm_exit)) + return 0; + + /* execute the expression */ + if (!_slang_execute2 (file, &mach)) + return 0; + + /* the evaluated expression is on top of the stack */ + *plength = (GLuint) mach.mem[mach.sp + SLANG_MACHINE_GLOBAL_SIZE]._float; + /* TODO: check if 0 < arr->length <= 65535 */ + + /* restore the old assembly */ + if (!slang_assembly_file_restore_point_load (file, &point)) + 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, - slang_variable_scope *vars) + slang_variable_scope *vars, slang_machine *mach, slang_assembly_file *file, + slang_atom_pool *atoms) { switch (spec->type) { @@ -167,15 +226,12 @@ int _slang_aggregate_variable (slang_storage_aggregate *agg, slang_type_specifie 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, vars); + return aggregate_variables (agg, spec->_struct->fields, funcs, structs, vars, mach, + file, atoms); case slang_spec_array: { - slang_storage_array *arr; - slang_assembly_file file; - slang_assembly_flow_control flow; + slang_storage_array *arr; 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) @@ -185,21 +241,20 @@ int _slang_aggregate_variable (slang_storage_aggregate *agg, slang_type_specifie 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, vars)) - return 0; - slang_assembly_file_construct (&file); - space.funcs = funcs; - space.structs = structs; - space.vars = vars; - if (!_slang_assemble_operation (&file, array_size, 0, &flow, &space, &info, &stk)) - { - slang_assembly_file_destruct (&file); - return 0; + if (!slang_storage_aggregate_construct (arr->aggregate)) + { + slang_alloc_free (arr->aggregate); + arr->aggregate = NULL; + return 0; } - /* TODO: evaluate array size */ - slang_assembly_file_destruct (&file); - arr->length = 256; + if (!_slang_aggregate_variable (arr->aggregate, spec->_array, NULL, funcs, structs, + vars, mach, file, atoms)) + return 0; + space.funcs = funcs; + space.structs = structs; + space.vars = vars; + if (!eval_array_size (file, mach, &space, array_size, &arr->length, atoms)) + return 0; } return 1; default: @@ -211,10 +266,12 @@ int _slang_aggregate_variable (slang_storage_aggregate *agg, slang_type_specifie unsigned int _slang_sizeof_aggregate (const slang_storage_aggregate *agg) { - unsigned int i, size = 0; + unsigned int i, size = 0; + for (i = 0; i < agg->count; i++) { - unsigned int element_size; + unsigned int element_size; + if (agg->arrays[i].type == slang_stor_aggregate) element_size = _slang_sizeof_aggregate (agg->arrays[i].aggregate); else @@ -228,10 +285,12 @@ unsigned int _slang_sizeof_aggregate (const slang_storage_aggregate *agg) int _slang_flatten_aggregate (slang_storage_aggregate *flat, const slang_storage_aggregate *agg) { - unsigned int i; + unsigned int i; + for (i = 0; i < agg->count; i++) { - unsigned int j; + unsigned int j; + for (j = 0; j < agg->arrays[i].length; j++) { if (agg->arrays[i].type == slang_stor_aggregate) @@ -241,7 +300,8 @@ int _slang_flatten_aggregate (slang_storage_aggregate *flat, const slang_storage } else { - slang_storage_array *arr; + slang_storage_array *arr; + arr = slang_storage_aggregate_push_new (flat); if (arr == NULL) return 0; diff --git a/src/mesa/shader/slang/slang_storage.h b/src/mesa/shader/slang/slang_storage.h index b875ce6745..a99f38f65c 100644 --- a/src/mesa/shader/slang/slang_storage.h +++ b/src/mesa/shader/slang/slang_storage.h @@ -66,7 +66,7 @@ typedef struct slang_storage_array_ unsigned int length; } slang_storage_array; -void slang_storage_array_construct (slang_storage_array *); +int slang_storage_array_construct (slang_storage_array *); void slang_storage_array_destruct (slang_storage_array *); /* @@ -81,12 +81,13 @@ typedef struct slang_storage_aggregate_ unsigned int count; } slang_storage_aggregate; -void slang_storage_aggregate_construct (slang_storage_aggregate *); +int 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 *, - slang_variable_scope *); + slang_variable_scope *, struct slang_machine_ *, struct slang_assembly_file_ *, + slang_atom_pool *); /* returns total size (in machine units) of the given aggregate diff --git a/src/mesa/shader/slang/slang_utility.c b/src/mesa/shader/slang/slang_utility.c index c07e161c8d..5075832a92 100644 --- a/src/mesa/shader/slang/slang_utility.c +++ b/src/mesa/shader/slang/slang_utility.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.3 + * Version: 6.5 * - * Copyright (C) 2005 Brian Paul All Rights Reserved. + * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -31,43 +31,82 @@ #include "imports.h" #include "slang_utility.h" -void slang_alloc_free (void *ptr) +char *slang_string_concat (char *dst, const char *src) { - _mesa_free (ptr); + return _mesa_strcpy (dst + _mesa_strlen (dst), src); } -void *slang_alloc_malloc (unsigned int size) -{ - return _mesa_malloc (size); -} +/* slang_atom_pool */ -void *slang_alloc_realloc (void *ptr, unsigned int old_size, unsigned int size) +void slang_atom_pool_construct (slang_atom_pool *pool) { - return _mesa_realloc (ptr, old_size, size); -} + GLuint i; -int slang_string_compare (const char *str1, const char *str2) -{ - return _mesa_strcmp (str1, str2); + for (i = 0; i < SLANG_ATOM_POOL_SIZE; i++) + pool->entries[i] = NULL; } -char *slang_string_copy (char *dst, const char *src) +void slang_atom_pool_destruct (slang_atom_pool *pool) { - return _mesa_strcpy (dst, src); -} + GLuint i; -char *slang_string_concat (char *dst, const char *src) -{ - return _mesa_strcpy (dst + _mesa_strlen (dst), src); + for (i = 0; i < SLANG_ATOM_POOL_SIZE; i++) + { + slang_atom_entry *entry; + + entry = pool->entries[i]; + while (entry != NULL) + { + slang_atom_entry *next; + + next = entry->next; + slang_alloc_free (entry->id); + slang_alloc_free (entry); + entry = next; + } + } } -char *slang_string_duplicate (const char *src) +slang_atom slang_atom_pool_atom (slang_atom_pool *pool, const char *id) { - return _mesa_strdup (src); + GLuint hash; + const char *p = id; + slang_atom_entry **entry; + + hash = 0; + while (*p != '\0') + { + GLuint g; + + hash = (hash << 4) + (GLuint) *p++; + g = hash & 0xf0000000; + if (g != 0) + hash ^= g >> 24; + hash &= ~g; + } + hash %= SLANG_ATOM_POOL_SIZE; + + entry = &pool->entries[hash]; + while (*entry != NULL) + { + if (slang_string_compare ((**entry).id, id) == 0) + return (slang_atom) (**entry).id; + entry = &(**entry).next; + } + + *entry = (slang_atom_entry *) slang_alloc_malloc (sizeof (slang_atom_entry)); + if (*entry == NULL) + return SLANG_ATOM_NULL; + + (**entry).next = NULL; + (**entry).id = slang_string_duplicate (id); + if ((**entry).id == NULL) + return SLANG_ATOM_NULL; + return (slang_atom) (**entry).id; } -unsigned int slang_string_length (const char *str) +const char *slang_atom_pool_id (slang_atom_pool *pool, slang_atom atom) { - return _mesa_strlen (str); + return (const char *) atom; } diff --git a/src/mesa/shader/slang/slang_utility.h b/src/mesa/shader/slang/slang_utility.h index 2b040a4446..2d2ac8e42e 100644 --- a/src/mesa/shader/slang/slang_utility.h +++ b/src/mesa/shader/slang/slang_utility.h @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.3 + * Version: 6.5 * - * Copyright (C) 2005 Brian Paul All Rights Reserved. + * Copyright (C) 2005-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -34,14 +34,37 @@ extern "C" { */ #define static_assert(expr) do { int _array[(expr) ? 1 : -1]; _array[0]; } while (0) -void slang_alloc_free (void *); -void *slang_alloc_malloc (unsigned int); -void *slang_alloc_realloc (void *, unsigned int, unsigned int); -int slang_string_compare (const char *, const char *); -char *slang_string_copy (char *, const char *); +#define slang_alloc_free(ptr) _mesa_free (ptr) +#define slang_alloc_malloc(size) _mesa_malloc (size) +#define slang_alloc_realloc(ptr, old_size, size) _mesa_realloc (ptr, old_size, size) +#define slang_string_compare(str1, str2) _mesa_strcmp (str1, str2) +#define slang_string_copy(dst, src) _mesa_strcpy (dst, src) +#define slang_string_duplicate(src) _mesa_strdup (src) +#define slang_string_length(str) _mesa_strlen (str) + char *slang_string_concat (char *, const char *); -char *slang_string_duplicate (const char *); -unsigned int slang_string_length (const char *); + +typedef GLvoid *slang_atom; + +#define SLANG_ATOM_NULL ((slang_atom) 0) + +typedef struct slang_atom_entry_ +{ + char *id; + struct slang_atom_entry_ *next; +} slang_atom_entry; + +#define SLANG_ATOM_POOL_SIZE 1023 + +typedef struct slang_atom_pool_ +{ + slang_atom_entry *entries[SLANG_ATOM_POOL_SIZE]; +} slang_atom_pool; + +void slang_atom_pool_construct (slang_atom_pool *); +void slang_atom_pool_destruct (slang_atom_pool *); +slang_atom slang_atom_pool_atom (slang_atom_pool *, const char *); +const char *slang_atom_pool_id (slang_atom_pool *, slang_atom); #ifdef __cplusplus } -- cgit v1.2.3