mesa: glsl: assorted fixes for resolving polymorphic functions

Plus,
- fix some issues in casting function arguments to format param types.
- fix some vec/mat constructor bugs
- find/report more syntax/semantic errors
This commit is contained in:
Brian Paul 2008-07-29 17:29:30 -06:00
parent 6225e51a73
commit 1638edb325
8 changed files with 400 additions and 212 deletions

View file

@ -1170,7 +1170,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
@ -1688,22 +1689,51 @@ print_funcs(struct slang_function_scope_ *scope, const char *name)
* all of them...
*/
static slang_function *
_slang_find_function_by_argc(struct slang_function_scope_ *scope,
_slang_find_function_by_argc(slang_function_scope *scope,
const char *name, int numArgs)
{
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
/*&& numArgs == f->param_count*/)
return f;
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_find_function_by_argc(scope->outer_scope, name, numArgs);
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.
@ -1761,16 +1791,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;
@ -1780,7 +1814,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;
}
@ -1789,7 +1823,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);
@ -1797,21 +1831,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
}
@ -1819,7 +1853,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;
}
}
@ -1829,12 +1863,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);
}
}
@ -1867,6 +1901,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).
@ -1879,29 +1934,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 (!fun) {
fun = _slang_locate_struct_constructor(A, name);
if (error) {
slang_info_log_error(A->log,
"Function '%s' not found (check argument types)",
name);
return NULL;
}
if (!fun) {
/* A function with exactly the right parameters/types was not found.
* Try adapting the parameters.
/* Next, try locating a constructor function for a user-defined type */
fun = _slang_locate_struct_constructor(A, name);
}
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_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_adapt_call(oper, fun, &A->space, A->atoms, A->log)) {
slang_info_log_error(A->log, "Function '%s' not found (check argument types)", name);
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);
@ -2888,6 +2967,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 {
@ -2932,11 +3012,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;
}
@ -2966,6 +3052,22 @@ print_vars(slang_variable_scope *s)
#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)
*/
@ -2985,6 +3087,7 @@ _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)
@ -3009,27 +3112,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
/*print_vars(oper->locals);*/
return tree;
}
else {

View file

@ -337,9 +337,10 @@ convert_to_array(slang_parse_ctx * C, slang_variable * var,
static GLboolean
parse_struct_field_var(slang_parse_ctx * C, slang_output_ctx * O,
slang_variable * var, const slang_type_specifier * sp)
slang_variable * var, slang_atom a_name,
const slang_type_specifier * sp)
{
var->a_name = parse_identifier(C);
var->a_name = a_name;
if (var->a_name == SLANG_ATOM_NULL)
return GL_FALSE;
@ -372,12 +373,19 @@ parse_struct_field(slang_parse_ctx * C, slang_output_ctx * O,
return 0;
do {
slang_atom a_name;
slang_variable *var = slang_variable_scope_grow(st->fields);
if (!var) {
slang_info_log_memory(C->L);
return 0;
}
if (!parse_struct_field_var(C, &o, var, sp))
a_name = parse_identifier(C);
if (_slang_locate_variable(st->fields, a_name, GL_FALSE)) {
slang_info_log_error(C->L, "duplicate field '%s'", (char *) a_name);
return 0;
}
if (!parse_struct_field_var(C, &o, var, a_name, sp))
return 0;
}
while (*C->I++ != FIELD_NONE);
@ -1579,11 +1587,22 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
const slang_fully_specified_type * type)
{
slang_variable *var;
slang_atom a_name;
/* empty init declatator (without name, e.g. "float ;") */
if (*C->I++ == VARIABLE_NONE)
return 1;
a_name = parse_identifier(C);
/* check if name is already in this scope */
if (_slang_locate_variable(O->vars, a_name, GL_FALSE)) {
slang_info_log_error(C->L,
"declaration of '%s' conflicts with previous declaration",
(char *) a_name);
return 0;
}
/* make room for the new variable and initialize it */
var = slang_variable_scope_grow(O->vars);
if (!var) {
@ -1593,7 +1612,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
/* copy the declarator qualifier type, parse the identifier */
var->type.qualifier = type->qualifier;
var->a_name = parse_identifier(C);
var->a_name = a_name;
if (var->a_name == SLANG_ATOM_NULL)
return 0;
@ -1657,6 +1676,7 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
A.space.vars = O->vars;
A.program = O->program;
A.vartable = O->vartable;
A.log = C->L;
A.curFuncEndLabel = NULL;
if (!_slang_codegen_global_variable(&A, var, C->type))
return 0;
@ -2265,7 +2285,7 @@ compile_shader(GLcontext *ctx, slang_code_object * object,
GLboolean success;
grammar id = 0;
#if 0 /* for debug */
#if 1 /* for debug */
_mesa_printf("********* COMPILE SHADER ***********\n");
_mesa_printf("%s\n", shader->Source);
_mesa_printf("************************************\n");

View file

@ -267,6 +267,7 @@ slang_variable_construct(slang_variable * var)
var->size = 0;
var->isTemp = GL_FALSE;
var->aux = NULL;
var->declared = 0;
return 1;
}
@ -325,16 +326,23 @@ slang_variable_copy(slang_variable * x, const slang_variable * y)
}
/**
* Search for named variable in given scope.
* \param all if true, search parent scopes too.
*/
slang_variable *
_slang_locate_variable(const slang_variable_scope * scope,
const slang_atom a_name, GLboolean all)
{
GLuint i;
for (i = 0; i < scope->num_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, a_name, 1);
while (scope) {
GLuint i;
for (i = 0; i < scope->num_variables; i++)
if (a_name == scope->variables[i]->a_name)
return scope->variables[i];
if (all)
scope = scope->outer_scope;
else
scope = NULL;
}
return NULL;
}

View file

@ -256,6 +256,12 @@ storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st)
}
assert(st->File >= 0);
#if 1 /* XXX temporary */
if (st->File == PROGRAM_UNDEFINED) {
slang_ir_storage *st0 = (slang_ir_storage *) st;
st0->File = PROGRAM_TEMPORARY;
}
#endif
assert(st->File < PROGRAM_UNDEFINED);
src->File = st->File;

View file

@ -1,8 +1,8 @@
/*
* Mesa 3-D graphics library
* Version: 6.5.2
* Version: 7.1
*
* Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
* Copyright (C) 2005-2008 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"),
@ -23,14 +23,13 @@
*/
/**
* \file slang_assemble_typeinfo.c
* slang type info
* \author Michal Krol
* Functions for constant folding, built-in constant lookup, and function
* call casting.
*/
#include "imports.h"
#include "macros.h"
#include "get.h"
#include "main/imports.h"
#include "main/macros.h"
#include "main/get.h"
#include "slang_compile.h"
#include "slang_codegen.h"
#include "slang_simplify.h"
@ -299,6 +298,81 @@ _slang_simplify(slang_operation *oper,
/**
* Insert casts to try to adapt actual parameters to formal parameters for a
* function call when an exact match for the parameter types is not found.
* Example:
* void foo(int i, bool b) {}
* x = foo(3.15, 9);
* Gets translated into:
* x = foo(int(3.15), bool(9))
*/
GLboolean
_slang_cast_func_params(slang_operation *callOper, const slang_function *fun,
const slang_name_space * space,
slang_atom_pool * atoms, slang_info_log *log)
{
const GLboolean haveRetValue = _slang_function_has_return_value(fun);
const int numParams = fun->param_count - haveRetValue;
int i;
int dbg = 0;
if (dbg)
printf("Adapt call of %d args to func %s (%d params)\n",
callOper->num_children, (char*) fun->header.a_name, numParams);
for (i = 0; i < numParams; i++) {
slang_typeinfo argType;
slang_variable *paramVar = fun->parameters->variables[i];
/* Get type of arg[i] */
if (!slang_typeinfo_construct(&argType))
return GL_FALSE;
if (!_slang_typeof_operation_(&callOper->children[i], space,
&argType, atoms, log)) {
slang_typeinfo_destruct(&argType);
return GL_FALSE;
}
/* see if arg type matches parameter type */
if (!slang_type_specifier_equal(&argType.spec,
&paramVar->type.specifier)) {
/* need to adapt arg type to match param type */
const char *constructorName =
slang_type_specifier_type_to_string(paramVar->type.specifier.type);
slang_operation *child = slang_operation_new(1);
if (dbg)
printf("Need to adapt types of arg %d\n", i);
slang_operation_copy(child, &callOper->children[i]);
child->locals->outer_scope = callOper->children[i].locals;
#if 0
if (_slang_sizeof_type_specifier(&argType.spec) >
_slang_sizeof_type_specifier(&paramVar->type.specifier)) {
}
#endif
callOper->children[i].type = SLANG_OPER_CALL;
callOper->children[i].a_id = slang_atom_pool_atom(atoms, constructorName);
callOper->children[i].num_children = 1;
callOper->children[i].children = child;
}
slang_typeinfo_destruct(&argType);
}
if (dbg) {
printf("===== New call to %s with cast arguments ===============\n",
(char*) fun->header.a_name);
slang_print_tree(callOper, 5);
}
return GL_TRUE;
}
/**
* Adapt the arguments for a function call to match the parameters of
* the given function.
@ -328,119 +402,66 @@ _slang_adapt_call(slang_operation *callOper, const slang_function *fun,
if (callOper->num_children != numParams) {
/* number of arguments doesn't match number of parameters */
if (fun->kind == SLANG_FUNC_CONSTRUCTOR) {
/* For constructor calls, we can try to unroll vector/matrix args
* into individual floats/ints and try to match the function params.
*/
for (i = 0; i < numParams; i++) {
slang_typeinfo argType;
GLint argSz, j;
/* For constructor calls, we can try to unroll vector/matrix args
* into individual floats/ints and try to match the function params.
*/
for (i = 0; i < numParams; i++) {
slang_typeinfo argType;
GLint argSz, j;
/* Get type of arg[i] */
if (!slang_typeinfo_construct(&argType))
return GL_FALSE;
if (!_slang_typeof_operation_(&callOper->children[i], space,
&argType, atoms, log)) {
slang_typeinfo_destruct(&argType);
return GL_FALSE;
/* Get type of arg[i] */
if (!slang_typeinfo_construct(&argType))
return GL_FALSE;
if (!_slang_typeof_operation_(&callOper->children[i], space,
&argType, atoms, log)) {
slang_typeinfo_destruct(&argType);
return GL_FALSE;
}
/*
paramSz = _slang_sizeof_type_specifier(&paramVar->type.specifier);
assert(paramSz == 1);
*/
argSz = _slang_sizeof_type_specifier(&argType.spec);
if (argSz > 1) {
slang_operation origArg;
/* break up arg[i] into components */
if (dbg)
printf("Break up arg %d from 1 to %d elements\n", i, argSz);
slang_operation_construct(&origArg);
slang_operation_copy(&origArg, &callOper->children[i]);
/* insert argSz-1 new children/args */
for (j = 0; j < argSz - 1; j++) {
(void) slang_operation_insert(&callOper->num_children,
&callOper->children, i);
}
/*
paramSz = _slang_sizeof_type_specifier(&paramVar->type.specifier);
assert(paramSz == 1);
*/
argSz = _slang_sizeof_type_specifier(&argType.spec);
if (argSz > 1) {
slang_operation origArg;
/* break up arg[i] into components */
if (dbg)
printf("Break up arg %d from 1 to %d elements\n", i, argSz);
slang_operation_construct(&origArg);
slang_operation_copy(&origArg,
&callOper->children[i]);
/* insert argSz-1 new children/args */
for (j = 0; j < argSz - 1; j++) {
(void) slang_operation_insert(&callOper->num_children,
&callOper->children, i);
}
/* replace arg[i+j] with subscript/index oper */
for (j = 0; j < argSz; j++) {
callOper->children[i + j].type = SLANG_OPER_SUBSCRIPT;
callOper->children[i + j].num_children = 2;
callOper->children[i + j].children = slang_operation_new(2);
slang_operation_copy(&callOper->children[i + j].children[0],
&origArg);
callOper->children[i + j].children[1].type
= SLANG_OPER_LITERAL_INT;
callOper->children[i + j].children[1].literal[0] = j;
}
/* replace arg[i+j] with subscript/index oper */
for (j = 0; j < argSz; j++) {
callOper->children[i + j].type = SLANG_OPER_SUBSCRIPT;
callOper->children[i + j].locals = _slang_variable_scope_new(callOper->locals);
callOper->children[i + j].num_children = 2;
callOper->children[i + j].children = slang_operation_new(2);
slang_operation_copy(&callOper->children[i + j].children[0],
&origArg);
callOper->children[i + j].children[1].type
= SLANG_OPER_LITERAL_INT;
callOper->children[i + j].children[1].literal[0] = (GLfloat) j;
}
} /* for i */
}
else {
/* non-constructor function: number of args must match number
* of function params.
*/
return GL_FALSE; /* caller will record an error msg */
}
}
}
if (callOper->num_children < numParams) {
if (callOper->num_children < (GLuint) numParams) {
/* still not enough args for all params */
return GL_FALSE;
}
else if (callOper->num_children > numParams) {
else if (callOper->num_children > (GLuint) numParams) {
/* now too many arguments */
/* XXX this isn't always an error, see spec */
return GL_FALSE;
}
/*
* Second phase, argument casting.
* Example:
* void foo(int i, bool b) {}
* x = foo(3.15, 9);
* Gets translated into:
* x = foo(int(3.15), bool(9))
*/
for (i = 0; i < numParams; i++) {
slang_typeinfo argType;
slang_variable *paramVar = fun->parameters->variables[i];
/* Get type of arg[i] */
if (!slang_typeinfo_construct(&argType))
return GL_FALSE;
if (!_slang_typeof_operation_(&callOper->children[i], space,
&argType, atoms, log)) {
slang_typeinfo_destruct(&argType);
return GL_FALSE;
}
/* see if arg type matches parameter type */
if (!slang_type_specifier_equal(&argType.spec,
&paramVar->type.specifier)) {
/* need to adapt arg type to match param type */
const char *constructorName =
slang_type_specifier_type_to_string(paramVar->type.specifier.type);
slang_operation *child = slang_operation_new(1);
if (dbg)
printf("Need to adapt types of arg %d\n", i);
slang_operation_copy(child, &callOper->children[i]);
child->locals->outer_scope = callOper->children[i].locals;
callOper->children[i].type = SLANG_OPER_CALL;
callOper->children[i].a_id = slang_atom_pool_atom(atoms, constructorName);
callOper->children[i].num_children = 1;
callOper->children[i].children = child;
}
slang_typeinfo_destruct(&argType);
/* just truncate */
callOper->num_children = (GLuint) numParams;
}
if (dbg) {

View file

@ -1,3 +1,26 @@
/*
* Mesa 3-D graphics library
* Version: 7.1
*
* Copyright (C) 2005-2008 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SLANG_SIMPLIFY_H
#define SLANG_SIMPLIFY_H
@ -13,6 +36,11 @@ _slang_simplify(slang_operation *oper,
slang_atom_pool * atoms);
extern GLboolean
_slang_cast_func_params(slang_operation *callOper, const slang_function *fun,
const slang_name_space * space,
slang_atom_pool * atoms, slang_info_log *log);
extern GLboolean
_slang_adapt_call(slang_operation *callOper, const slang_function *fun,
const slang_name_space * space,

View file

@ -273,6 +273,7 @@ slang_type_specifier_compatible(const slang_type_specifier * x,
GLboolean
slang_typeinfo_construct(slang_typeinfo * ti)
{
/*_mesa_bzero(ti, sizeof(*ti));*/
slang_type_specifier_ctr(&ti->spec);
ti->array_len = 0;
return GL_TRUE;
@ -304,10 +305,16 @@ _slang_typeof_function(slang_atom a_name,
slang_function **funFound,
slang_atom_pool *atoms, slang_info_log *log)
{
GLboolean error;
*funFound = _slang_locate_function(space->funcs, a_name, params,
num_params, space, atoms, log);
num_params, space, atoms, log, &error);
if (error)
return GL_FALSE;
if (!*funFound)
return GL_TRUE; /* yes, not false */
return slang_type_specifier_copy(spec, &(*funFound)->header.type.specifier);
}
@ -755,51 +762,66 @@ slang_function *
_slang_locate_function(const slang_function_scope * funcs, slang_atom a_name,
slang_operation * args, GLuint num_args,
const slang_name_space * space, slang_atom_pool * atoms,
slang_info_log *log)
slang_info_log *log, GLboolean *error)
{
slang_typeinfo arg_ti[100];
GLuint i;
for (i = 0; i < funcs->num_functions; i++) {
slang_function *f = &funcs->functions[i];
const GLuint haveRetValue = _slang_function_has_return_value(f);
GLuint j;
*error = GL_FALSE;
if (a_name != f->header.a_name)
continue;
if (f->param_count - haveRetValue != num_args)
continue;
/* compare parameter / argument types */
for (j = 0; j < num_args; j++) {
slang_typeinfo ti;
if (!slang_typeinfo_construct(&ti))
return NULL;
if (!_slang_typeof_operation_(&args[j], space, &ti, atoms, log)) {
slang_typeinfo_destruct(&ti);
return NULL;
}
if (!slang_type_specifier_compatible(&ti.spec,
&f->parameters->variables[j]->type.specifier)) {
slang_typeinfo_destruct(&ti);
break;
}
slang_typeinfo_destruct(&ti);
/* "out" and "inout" formal parameter requires the actual
* parameter to be l-value.
*/
if (!ti.can_be_referenced &&
(f->parameters->variables[j]->type.qualifier == SLANG_QUAL_OUT ||
f->parameters->variables[j]->type.qualifier == SLANG_QUAL_INOUT))
break;
/* determine type of each argument */
assert(num_args < 100);
for (i = 0; i < num_args; i++) {
if (!slang_typeinfo_construct(&arg_ti[i]))
return NULL;
if (!_slang_typeof_operation_(&args[i], space, &arg_ti[i], atoms, log)) {
return NULL;
}
if (j == num_args)
return f;
}
if (funcs->outer_scope != NULL)
return _slang_locate_function(funcs->outer_scope, a_name, args,
num_args, space, atoms, log);
/* loop over function scopes */
while (funcs) {
/* look for function with matching name and argument/param types */
for (i = 0; i < funcs->num_functions; i++) {
slang_function *f = &funcs->functions[i];
const GLuint haveRetValue = _slang_function_has_return_value(f);
GLuint j;
if (a_name != f->header.a_name)
continue;
if (f->param_count - haveRetValue != num_args)
continue;
/* compare parameter / argument types */
for (j = 0; j < num_args; j++) {
if (!slang_type_specifier_compatible(&arg_ti[j].spec,
&f->parameters->variables[j]->type.specifier)) {
/* param/arg types don't match */
break;
}
/* "out" and "inout" formal parameter requires the actual
* argument to be an l-value.
*/
if (!arg_ti[j].can_be_referenced &&
(f->parameters->variables[j]->type.qualifier == SLANG_QUAL_OUT ||
f->parameters->variables[j]->type.qualifier == SLANG_QUAL_INOUT)) {
/* param is not an lvalue! */
*error = GL_TRUE;
return NULL;
}
}
if (j == num_args) {
/* name and args match! */
return f;
}
}
funcs = funcs->outer_scope;
}
return NULL;
}

View file

@ -73,7 +73,8 @@ _slang_locate_function(const struct slang_function_scope_ *funcs,
slang_atom name, struct slang_operation_ *params,
GLuint num_params,
const slang_name_space *space,
slang_atom_pool *atoms, slang_info_log *log);
slang_atom_pool *atoms, slang_info_log *log,
GLboolean *error);
extern GLboolean