summaryrefslogtreecommitdiff
path: root/src/mesa/shader/slang/slang_codegen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/shader/slang/slang_codegen.c')
-rw-r--r--src/mesa/shader/slang/slang_codegen.c249
1 files changed, 186 insertions, 63 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index d4bf99f78f..ad9cf06e27 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -1178,7 +1178,8 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
slang_operation_copy(inlined, fun->body);
/*** XXX review this */
- assert(inlined->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE);
+ assert(inlined->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE ||
+ inlined->type == SLANG_OPER_BLOCK_NEW_SCOPE);
inlined->type = SLANG_OPER_BLOCK_NEW_SCOPE;
#if 0
@@ -1702,7 +1703,7 @@ print_funcs(struct slang_function_scope_ *scope, const char *name)
/**
- * Return first function in the scope that has the given name.
+ * Find a function of the given name, taking 'numArgs' arguments.
* This is the function we'll try to call when there is no exact match
* between function parameters and call arguments.
*
@@ -1710,20 +1711,51 @@ print_funcs(struct slang_function_scope_ *scope, const char *name)
* all of them...
*/
static slang_function *
-_slang_first_function(struct slang_function_scope_ *scope, const char *name)
-{
- GLuint i;
- for (i = 0; i < scope->num_functions; i++) {
- slang_function *f = &scope->functions[i];
- if (strcmp(name, (char*) f->header.a_name) == 0)
- return f;
+_slang_find_function_by_argc(slang_function_scope *scope,
+ const char *name, int numArgs)
+{
+ while (scope) {
+ GLuint i;
+ for (i = 0; i < scope->num_functions; i++) {
+ slang_function *f = &scope->functions[i];
+ if (strcmp(name, (char*) f->header.a_name) == 0) {
+ int haveRetValue = _slang_function_has_return_value(f);
+ if (numArgs == f->param_count - haveRetValue)
+ return f;
+ }
+ }
+ scope = scope->outer_scope;
}
- if (scope->outer_scope)
- return _slang_first_function(scope->outer_scope, name);
+
return NULL;
}
+static slang_function *
+_slang_find_function_by_max_argc(slang_function_scope *scope,
+ const char *name)
+{
+ slang_function *maxFunc = NULL;
+ GLuint maxArgs = 0;
+
+ while (scope) {
+ GLuint i;
+ for (i = 0; i < scope->num_functions; i++) {
+ slang_function *f = &scope->functions[i];
+ if (strcmp(name, (char*) f->header.a_name) == 0) {
+ if (f->param_count > maxArgs) {
+ maxArgs = f->param_count;
+ maxFunc = f;
+ }
+ }
+ }
+ scope = scope->outer_scope;
+ }
+
+ return maxFunc;
+}
+
+
/**
* Generate a new slang_function which is a constructor for a user-defined
* struct type.
@@ -1754,7 +1786,8 @@ _slang_make_constructor(slang_assemble_ctx *A, slang_struct *str)
printf("Field %d: %s\n", i, (char*) str->fields->variables[i]->a_name);
*/
slang_variable *p = slang_variable_scope_grow(fun->parameters);
- *p = *str->fields->variables[i];
+ *p = *str->fields->variables[i]; /* copy the type */
+ p->type.qualifier = SLANG_QUAL_CONST;
}
fun->param_count = fun->parameters->num_variables;
}
@@ -1780,16 +1813,20 @@ _slang_make_constructor(slang_assemble_ctx *A, slang_struct *str)
* return T;
*/
{
+ slang_variable_scope *scope;
slang_variable *var;
GLint i;
fun->body = slang_operation_new(1);
- fun->body->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
+ fun->body->type = SLANG_OPER_BLOCK_NEW_SCOPE;
fun->body->num_children = numFields + 2;
fun->body->children = slang_operation_new(numFields + 2);
+ scope = fun->body->locals;
+ scope->outer_scope = fun->parameters;
+
/* create local var 't' */
- var = slang_variable_scope_grow(fun->parameters);
+ var = slang_variable_scope_grow(scope);
var->a_name = slang_atom_pool_atom(A->atoms, "t");
var->type = fun->header.type;
@@ -1799,7 +1836,7 @@ _slang_make_constructor(slang_assemble_ctx *A, slang_struct *str)
decl = &fun->body->children[0];
decl->type = SLANG_OPER_VARIABLE_DECL;
- decl->locals = _slang_variable_scope_new(fun->parameters);
+ decl->locals = _slang_variable_scope_new(scope);
decl->a_id = var->a_name;
}
@@ -1808,7 +1845,7 @@ _slang_make_constructor(slang_assemble_ctx *A, slang_struct *str)
slang_operation *assign = &fun->body->children[1 + i];
assign->type = SLANG_OPER_ASSIGN;
- assign->locals = _slang_variable_scope_new(fun->parameters);
+ assign->locals = _slang_variable_scope_new(scope);
assign->num_children = 2;
assign->children = slang_operation_new(2);
@@ -1816,21 +1853,21 @@ _slang_make_constructor(slang_assemble_ctx *A, slang_struct *str)
slang_operation *lhs = &assign->children[0];
lhs->type = SLANG_OPER_FIELD;
- lhs->locals = _slang_variable_scope_new(fun->parameters);
+ lhs->locals = _slang_variable_scope_new(scope);
lhs->num_children = 1;
lhs->children = slang_operation_new(1);
lhs->a_id = str->fields->variables[i]->a_name;
lhs->children[0].type = SLANG_OPER_IDENTIFIER;
lhs->children[0].a_id = var->a_name;
- lhs->children[0].locals = _slang_variable_scope_new(fun->parameters);
+ lhs->children[0].locals = _slang_variable_scope_new(scope);
#if 0
lhs->children[1].num_children = 1;
lhs->children[1].children = slang_operation_new(1);
lhs->children[1].children[0].type = SLANG_OPER_IDENTIFIER;
lhs->children[1].children[0].a_id = str->fields->variables[i]->a_name;
- lhs->children[1].children->locals = _slang_variable_scope_new(fun->parameters);
+ lhs->children[1].children->locals = _slang_variable_scope_new(scope);
#endif
}
@@ -1838,7 +1875,7 @@ _slang_make_constructor(slang_assemble_ctx *A, slang_struct *str)
slang_operation *rhs = &assign->children[1];
rhs->type = SLANG_OPER_IDENTIFIER;
- rhs->locals = _slang_variable_scope_new(fun->parameters);
+ rhs->locals = _slang_variable_scope_new(scope);
rhs->a_id = str->fields->variables[i]->a_name;
}
}
@@ -1848,12 +1885,12 @@ _slang_make_constructor(slang_assemble_ctx *A, slang_struct *str)
slang_operation *ret = &fun->body->children[numFields + 1];
ret->type = SLANG_OPER_RETURN;
- ret->locals = _slang_variable_scope_new(fun->parameters);
+ ret->locals = _slang_variable_scope_new(scope);
ret->num_children = 1;
ret->children = slang_operation_new(1);
ret->children[0].type = SLANG_OPER_IDENTIFIER;
ret->children[0].a_id = var->a_name;
- ret->children[0].locals = _slang_variable_scope_new(fun->parameters);
+ ret->children[0].locals = _slang_variable_scope_new(scope);
}
}
@@ -1870,7 +1907,7 @@ _slang_make_constructor(slang_assemble_ctx *A, slang_struct *str)
static slang_function *
_slang_locate_struct_constructor(slang_assemble_ctx *A, const char *name)
{
- int i;
+ unsigned int i;
for (i = 0; i < A->space.structs->num_structs; i++) {
slang_struct *str = &A->space.structs->structs[i];
if (strcmp(name, (const char *) str->a_name) == 0) {
@@ -1886,6 +1923,27 @@ _slang_locate_struct_constructor(slang_assemble_ctx *A, const char *name)
}
+
+static GLboolean
+_slang_is_vec_mat_type(const char *name)
+{
+ static const char *vecmat_types[] = {
+ "float", "int", "bool",
+ "vec2", "vec3", "vec4",
+ "ivec2", "ivec3", "ivec4",
+ "bvec2", "bvec3", "bvec4",
+ "mat2", "mat3", "mat4",
+ "mat2x3", "mat2x4", "mat3x2", "mat3x4", "mat4x2", "mat4x3",
+ NULL
+ };
+ int i;
+ for (i = 0; vecmat_types[i]; i++)
+ if (_mesa_strcmp(name, vecmat_types[i]) == 0)
+ return GL_TRUE;
+ return GL_FALSE;
+}
+
+
/**
* Assemble a function call, given a particular function name.
* \param name the function's name (operators like '*' are possible).
@@ -1898,28 +1956,53 @@ _slang_gen_function_call_name(slang_assemble_ctx *A, const char *name,
const GLuint param_count = oper->num_children;
slang_atom atom;
slang_function *fun;
+ GLboolean error;
atom = slang_atom_pool_atom(A->atoms, name);
if (atom == SLANG_ATOM_NULL)
return NULL;
/*
- * Use 'name' to find the function to call
+ * First, try to find function by name and exact argument type matching.
*/
fun = _slang_locate_function(A->space.funcs, atom, params, param_count,
- &A->space, A->atoms, A->log);
+ &A->space, A->atoms, A->log, &error);
+
+ if (error) {
+ slang_info_log_error(A->log,
+ "Function '%s' not found (check argument types)",
+ name);
+ return NULL;
+ }
if (!fun) {
+ /* Next, try locating a constructor function for a user-defined type */
fun = _slang_locate_struct_constructor(A, name);
}
- if (!fun) {
- /* A function with exactly the right parameters/types was not found.
- * Try adapting the parameters.
+ if (!fun && _slang_is_vec_mat_type(name)) {
+ /* Next, if this call looks like a vec() or mat() constructor call,
+ * try "unwinding" the args to satisfy a constructor.
*/
- fun = _slang_first_function(A->space.funcs, name);
- if (!fun || !_slang_adapt_call(oper, fun, &A->space, A->atoms, A->log)) {
- slang_info_log_error(A->log, "Function '%s' not found (check argument types)", name);
+ fun = _slang_find_function_by_max_argc(A->space.funcs, name);
+ if (fun) {
+ if (!_slang_adapt_call(oper, fun, &A->space, A->atoms, A->log)) {
+ slang_info_log_error(A->log,
+ "Function '%s' not found (check argument types)",
+ name);
+ return NULL;
+ }
+ }
+ }
+
+ if (!fun) {
+ /* Next, try casting args to the types of the formal parameters */
+ int numArgs = oper->num_children;
+ fun = _slang_find_function_by_argc(A->space.funcs, name, numArgs);
+ if (!fun || !_slang_cast_func_params(oper, fun, &A->space, A->atoms, A->log)) {
+ slang_info_log_error(A->log,
+ "Function '%s' not found (check argument types)",
+ name);
return NULL;
}
assert(fun);
@@ -2193,22 +2276,16 @@ _slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper)
cond = _slang_gen_operation(A, &oper->children[0]);
cond = new_cond(cond);
- if (is_operation_type(&oper->children[1], SLANG_OPER_BREAK)) {
+ if (is_operation_type(&oper->children[1], SLANG_OPER_BREAK)
+ && !haveElseClause) {
/* Special case: generate a conditional break */
ifBody = new_break_if_true(A->CurLoop, cond);
- if (haveElseClause) {
- elseBody = _slang_gen_operation(A, &oper->children[2]);
- return new_seq(ifBody, elseBody);
- }
return ifBody;
}
- else if (is_operation_type(&oper->children[1], SLANG_OPER_CONTINUE)) {
+ else if (is_operation_type(&oper->children[1], SLANG_OPER_CONTINUE)
+ && !haveElseClause) {
/* Special case: generate a conditional break */
ifBody = new_cont_if_true(A->CurLoop, cond);
- if (haveElseClause) {
- elseBody = _slang_gen_operation(A, &oper->children[2]);
- return new_seq(ifBody, elseBody);
- }
return ifBody;
}
else {
@@ -2318,6 +2395,11 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var)
n->Store->File = PROGRAM_TEMPORARY;
n->Store->Size = _slang_sizeof_type_specifier(&n->Var->type.specifier);
+ if (n->Store->Size <= 0) {
+ slang_info_log_error(A->log, "invalid declaration for '%s'",
+ (char*) var->a_name);
+ return NULL;
+ }
#if 0
printf("%s var %p %s store=%p index=%d size=%d\n",
__FUNCTION__, (void *) var, (char *) var->a_name,
@@ -2553,8 +2635,16 @@ _slang_gen_declaration(slang_assemble_ctx *A, slang_operation *oper)
assert(oper->num_children == 0 || oper->num_children == 1);
v = _slang_locate_variable(oper->locals, oper->a_id, GL_TRUE);
+ /*printf("Declare %s at %p\n", varName, v);*/
assert(v);
+#if 0
+ if (v->declared) {
+ slang_info_log_error(A->log, "variable '%s' redeclared", varName);
+ return NULL;
+ }
+#endif
+
varDecl = _slang_gen_var_decl(A, v);
if (oper->num_children > 0) {
@@ -2711,6 +2801,11 @@ _slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper)
lhs = _slang_gen_operation(A, &oper->children[0]);
if (lhs) {
+ if (!lhs->Store) {
+ slang_info_log_error(A->log,
+ "invalid left hand side for assignment");
+ return NULL;
+ }
if (!(lhs->Store->File == PROGRAM_OUTPUT ||
lhs->Store->File == PROGRAM_TEMPORARY ||
(lhs->Store->File == PROGRAM_VARYING &&
@@ -2764,6 +2859,7 @@ _slang_gen_struct_field(slang_assemble_ctx * A, slang_operation *oper)
GLuint swizzle;
if (!_slang_is_swizzle((char *) oper->a_id, rows, &swz)) {
slang_info_log_error(A->log, "Bad swizzle");
+ return NULL;
}
swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
swz.swizzle[1],
@@ -2812,10 +2908,14 @@ _slang_gen_struct_field(slang_assemble_ctx * A, slang_operation *oper)
fieldOffset = _slang_field_offset(&ti.spec, oper->a_id);
if (fieldSize == 0 || fieldOffset < 0) {
+ const char *structName;
+ if (ti.spec._struct)
+ structName = (char *) ti.spec._struct->a_name;
+ else
+ structName = "unknown";
slang_info_log_error(A->log,
"\"%s\" is not a member of struct \"%s\"",
- (char *) oper->a_id,
- (char *) ti.spec._struct->a_name);
+ (char *) oper->a_id, structName);
return NULL;
}
assert(fieldSize >= 0);
@@ -2889,6 +2989,7 @@ _slang_gen_array_element(slang_assemble_ctx * A, slang_operation *oper)
/*n->Store = _slang_clone_ir_storage_swz(n->Store, */
n->Writemask = WRITEMASK_X << index;
}
+ assert(n->Store);
return n;
}
else {
@@ -2933,11 +3034,17 @@ _slang_gen_array_element(slang_assemble_ctx * A, slang_operation *oper)
}
}
+ if (!array->Store) {
+ slang_info_log_error(A->log, "Invalid array");
+ return NULL;
+ }
+
elem = new_node2(IR_ELEMENT, array, index);
elem->Store = _slang_new_ir_storage_relative(constIndex,
elemSize,
array->Store);
+ assert(elem->Store->Parent);
/* XXX try to do some array bounds checking here */
return elem;
}
@@ -2950,6 +3057,39 @@ _slang_gen_array_element(slang_assemble_ctx * A, slang_operation *oper)
}
+#if 0
+static void
+print_vars(slang_variable_scope *s)
+{
+ int i;
+ printf("vars: ");
+ for (i = 0; i < s->num_variables; i++) {
+ printf("%s %d, \n",
+ (char*) s->variables[i]->a_name,
+ s->variables[i]->declared);
+ }
+
+ printf("\n");
+}
+#endif
+
+
+#if 0
+static void
+_slang_undeclare_vars(slang_variable_scope *locals)
+{
+ if (locals->num_variables > 0) {
+ int i;
+ for (i = 0; i < locals->num_variables; i++) {
+ slang_variable *v = locals->variables[i];
+ printf("undeclare %s at %p\n", (char*) v->a_name, v);
+ v->declared = GL_FALSE;
+ }
+ }
+}
+#endif
+
+
/**
* Generate IR tree for a slang_operation (AST node)
*/
@@ -2969,6 +3109,9 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
_slang_pop_var_table(A->vartable);
+ /*_slang_undeclare_vars(oper->locals);*/
+ /*print_vars(oper->locals);*/
+
if (n)
n = new_node1(IR_SCOPE, n);
return n;
@@ -2991,26 +3134,6 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
tree = new_seq(tree, n);
}
-#if 00
- if (oper->locals->num_variables > 0) {
- int i;
- /*
- printf("\n****** Deallocate vars in scope!\n");
- */
- for (i = 0; i < oper->locals->num_variables; i++) {
- slang_variable *v = oper->locals->variables + i;
- if (v->aux) {
- slang_ir_storage *store = (slang_ir_storage *) v->aux;
- /*
- printf(" Deallocate var %s\n", (char*) v->a_name);
- */
- assert(store->File == PROGRAM_TEMPORARY);
- assert(store->Index >= 0);
- _slang_free_temp(A->vartable, store->Index, store->Size);
- }
- }
- }
-#endif
return tree;
}
else {