mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-01 08:08:06 +02:00
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:
parent
6225e51a73
commit
1638edb325
8 changed files with 400 additions and 212 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
¶mVar->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(¶mVar->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(¶mVar->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(¶mVar->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,
|
||||
¶mVar->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) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue