* \author Michal Krol
*/
-#include "imports.h"
-#include "slang_assemble_typeinfo.h"
+#include "main/imports.h"
+#include "shader/prog_instruction.h"
+#include "slang_typeinfo.h"
#include "slang_compile.h"
-#include "slang_error.h"
-#include "prog_instruction.h"
-
-
+#include "slang_log.h"
+#include "slang_mem.h"
/**
}
+/**
+ * Combines (multiplies) two swizzles to form single swizzle.
+ * Example: "vec.wzyx.yx" --> "vec.zw".
+ */
+GLvoid
+_slang_multiply_swizzles(slang_swizzle * dst, const slang_swizzle * left,
+ const slang_swizzle * right)
+{
+ GLuint i;
+
+ dst->num_components = right->num_components;
+ for (i = 0; i < right->num_components; i++)
+ dst->swizzle[i] = left->swizzle[right->swizzle[i]];
+}
+
+
GLvoid
slang_type_specifier_ctr(slang_type_specifier * self)
{
- self->type = slang_spec_void;
+ self->type = SLANG_SPEC_VOID;
self->_struct = NULL;
self->_array = NULL;
}
{
if (self->_struct != NULL) {
slang_struct_destruct(self->_struct);
- slang_alloc_free(self->_struct);
+ _slang_free(self->_struct);
}
if (self->_array != NULL) {
slang_type_specifier_dtr(self->_array);
- slang_alloc_free(self->_array);
+ _slang_free(self->_array);
}
}
slang_type_specifier_ctr(&z);
z.type = y->type;
- if (z.type == slang_spec_struct) {
- z._struct = (slang_struct *) slang_alloc_malloc(sizeof(slang_struct));
+ if (z.type == SLANG_SPEC_STRUCT) {
+ z._struct = (slang_struct *) _slang_alloc(sizeof(slang_struct));
if (z._struct == NULL) {
slang_type_specifier_dtr(&z);
return GL_FALSE;
}
if (!slang_struct_construct(z._struct)) {
- slang_alloc_free(z._struct);
+ _slang_free(z._struct);
slang_type_specifier_dtr(&z);
return GL_FALSE;
}
return GL_FALSE;
}
}
- else if (z.type == slang_spec_array) {
- z._array =
- (slang_type_specifier *)
- slang_alloc_malloc(sizeof(slang_type_specifier));
+ else if (z.type == SLANG_SPEC_ARRAY) {
+ z._array = (slang_type_specifier *)
+ _slang_alloc(sizeof(slang_type_specifier));
if (z._array == NULL) {
slang_type_specifier_dtr(&z);
return GL_FALSE;
return GL_TRUE;
}
+
+/**
+ * Test if two types are equal.
+ */
GLboolean
slang_type_specifier_equal(const slang_type_specifier * x,
const slang_type_specifier * y)
{
if (x->type != y->type)
- return 0;
- if (x->type == slang_spec_struct)
+ return GL_FALSE;
+ if (x->type == SLANG_SPEC_STRUCT)
return slang_struct_equal(x->_struct, y->_struct);
- if (x->type == slang_spec_array)
+ if (x->type == SLANG_SPEC_ARRAY)
return slang_type_specifier_equal(x->_array, y->_array);
- return 1;
+ return GL_TRUE;
+}
+
+
+/**
+ * As above, but allow float/int casting.
+ */
+static GLboolean
+slang_type_specifier_compatible(const slang_type_specifier * x,
+ const slang_type_specifier * y)
+{
+ /* special case: float == int */
+ if (x->type == SLANG_SPEC_INT && y->type == SLANG_SPEC_FLOAT) {
+ return GL_TRUE;
+ }
+ /* XXX may need to add bool/int compatibility, etc */
+
+ if (x->type != y->type)
+ return GL_FALSE;
+ if (x->type == SLANG_SPEC_STRUCT)
+ return slang_struct_equal(x->_struct, y->_struct);
+ if (x->type == SLANG_SPEC_ARRAY)
+ return slang_type_specifier_compatible(x->_array, y->_array);
+ return GL_TRUE;
}
GLboolean
-slang_assembly_typeinfo_construct(slang_assembly_typeinfo * ti)
+slang_typeinfo_construct(slang_typeinfo * ti)
{
+ _mesa_bzero(ti, sizeof(*ti));
slang_type_specifier_ctr(&ti->spec);
ti->array_len = 0;
return GL_TRUE;
}
GLvoid
-slang_assembly_typeinfo_destruct(slang_assembly_typeinfo * ti)
+slang_typeinfo_destruct(slang_typeinfo * ti)
{
slang_type_specifier_dtr(&ti->spec);
}
+
/**
* Determine the return type of a function.
- * \param name name of the function
+ * \param a_name the function name
+ * \param param function parameters (overloading)
+ * \param num_params number of parameters to function
+ * \param space namespace to search
+ * \param spec returns the type
+ * \param funFound returns pointer to the function, or NULL if not found.
+ * \return GL_TRUE for success, GL_FALSE if failure (bad function name)
+ */
+static GLboolean
+_slang_typeof_function(slang_atom a_name,
+ slang_operation * params, GLuint num_params,
+ const slang_name_space * space,
+ slang_type_specifier * spec,
+ 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, &error);
+ if (error)
+ return GL_FALSE;
+
+ if (!*funFound)
+ return GL_TRUE; /* yes, not false */
+
+ return slang_type_specifier_copy(spec, &(*funFound)->header.type.specifier);
+}
+
+
+/**
+ * Determine the type of a math function.
+ * \param name name of the operator, one of +,-,*,/ or unary -
* \param params array of function parameters
* \param num_params number of parameters
* \param space namespace to use
* \return GL_TRUE for success, GL_FALSE if failure
*/
static GLboolean
-typeof_existing_function(const char *name, const slang_operation * params,
- GLuint num_params,
- const slang_assembly_name_space * space,
- slang_type_specifier * spec,
- slang_atom_pool * atoms)
+typeof_math_call(const char *name, slang_operation *call,
+ const slang_name_space * space,
+ slang_type_specifier * spec,
+ slang_atom_pool * atoms,
+ slang_info_log *log)
{
- slang_atom atom;
- GLboolean exists;
+ if (call->fun) {
+ /* we've previously resolved this function call */
+ slang_type_specifier_copy(spec, &call->fun->header.type.specifier);
+ return GL_TRUE;
+ }
+ else {
+ slang_atom atom;
+ slang_function *fun;
- atom = slang_atom_pool_atom(atoms, name);
- if (!_slang_typeof_function(atom, params, num_params, space, spec,
- &exists, atoms))
+ /* number of params: */
+ assert(call->num_children == 1 || call->num_children == 2);
+
+ atom = slang_atom_pool_atom(atoms, name);
+ if (!_slang_typeof_function(atom, call->children, call->num_children,
+ space, spec, &fun, atoms, log))
+ return GL_FALSE;
+
+ if (fun) {
+ /* Save pointer to save time in future */
+ call->fun = fun;
+ return GL_TRUE;
+ }
return GL_FALSE;
- return exists;
+ }
}
GLboolean
_slang_typeof_operation(const slang_assemble_ctx * A,
- const slang_operation * op,
- slang_assembly_typeinfo * ti)
+ slang_operation * op,
+ slang_typeinfo * ti)
{
- return _slang_typeof_operation_(op, &A->space, ti, A->atoms);
+ return _slang_typeof_operation_(op, &A->space, ti, A->atoms, A->log);
}
* \return GL_TRUE for success, GL_FALSE if failure
*/
GLboolean
-_slang_typeof_operation_(const slang_operation * op,
- const slang_assembly_name_space * space,
- slang_assembly_typeinfo * ti,
- slang_atom_pool * atoms)
+_slang_typeof_operation_(slang_operation * op,
+ const slang_name_space * space,
+ slang_typeinfo * ti,
+ slang_atom_pool * atoms,
+ slang_info_log *log)
{
ti->can_be_referenced = GL_FALSE;
ti->is_swizzled = GL_FALSE;
switch (op->type) {
- case slang_oper_block_no_new_scope:
- case slang_oper_block_new_scope:
- case slang_oper_variable_decl:
- case slang_oper_asm:
- case slang_oper_break:
- case slang_oper_continue:
- case slang_oper_discard:
- case slang_oper_return:
- case slang_oper_if:
- case slang_oper_while:
- case slang_oper_do:
- case slang_oper_for:
- case slang_oper_void:
- ti->spec.type = slang_spec_void;
+ case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
+ case SLANG_OPER_BLOCK_NEW_SCOPE:
+ case SLANG_OPER_ASM:
+ case SLANG_OPER_BREAK:
+ case SLANG_OPER_CONTINUE:
+ case SLANG_OPER_DISCARD:
+ case SLANG_OPER_RETURN:
+ case SLANG_OPER_IF:
+ case SLANG_OPER_WHILE:
+ case SLANG_OPER_DO:
+ case SLANG_OPER_FOR:
+ case SLANG_OPER_VOID:
+ ti->spec.type = SLANG_SPEC_VOID;
break;
- case slang_oper_expression:
- case slang_oper_assign:
- case slang_oper_addassign:
- case slang_oper_subassign:
- case slang_oper_mulassign:
- case slang_oper_divassign:
- case slang_oper_preincrement:
- case slang_oper_predecrement:
- if (!_slang_typeof_operation_(op->children, space, ti, atoms))
+ case SLANG_OPER_EXPRESSION:
+ case SLANG_OPER_ASSIGN:
+ case SLANG_OPER_ADDASSIGN:
+ case SLANG_OPER_SUBASSIGN:
+ case SLANG_OPER_MULASSIGN:
+ case SLANG_OPER_DIVASSIGN:
+ case SLANG_OPER_PREINCREMENT:
+ case SLANG_OPER_PREDECREMENT:
+ if (!_slang_typeof_operation_(op->children, space, ti, atoms, log))
return GL_FALSE;
break;
- case slang_oper_literal_bool:
- case slang_oper_logicalor:
- case slang_oper_logicalxor:
- case slang_oper_logicaland:
- case slang_oper_equal:
- case slang_oper_notequal:
- case slang_oper_less:
- case slang_oper_greater:
- case slang_oper_lessequal:
- case slang_oper_greaterequal:
- case slang_oper_not:
- ti->spec.type = slang_spec_bool;
+ case SLANG_OPER_LITERAL_BOOL:
+ if (op->literal_size == 1)
+ ti->spec.type = SLANG_SPEC_BOOL;
+ else if (op->literal_size == 2)
+ ti->spec.type = SLANG_SPEC_BVEC2;
+ else if (op->literal_size == 3)
+ ti->spec.type = SLANG_SPEC_BVEC3;
+ else if (op->literal_size == 4)
+ ti->spec.type = SLANG_SPEC_BVEC4;
+ else {
+ _mesa_problem(NULL,
+ "Unexpected bool literal_size %d in _slang_typeof_operation()",
+ op->literal_size);
+ ti->spec.type = SLANG_SPEC_BOOL;
+ }
break;
- case slang_oper_literal_int:
- ti->spec.type = slang_spec_int;
+ case SLANG_OPER_LOGICALOR:
+ case SLANG_OPER_LOGICALXOR:
+ case SLANG_OPER_LOGICALAND:
+ case SLANG_OPER_EQUAL:
+ case SLANG_OPER_NOTEQUAL:
+ case SLANG_OPER_LESS:
+ case SLANG_OPER_GREATER:
+ case SLANG_OPER_LESSEQUAL:
+ case SLANG_OPER_GREATEREQUAL:
+ case SLANG_OPER_NOT:
+ ti->spec.type = SLANG_SPEC_BOOL;
break;
- case slang_oper_literal_float:
- ti->spec.type = slang_spec_float;
+ case SLANG_OPER_LITERAL_INT:
+ if (op->literal_size == 1)
+ ti->spec.type = SLANG_SPEC_INT;
+ else if (op->literal_size == 2)
+ ti->spec.type = SLANG_SPEC_IVEC2;
+ else if (op->literal_size == 3)
+ ti->spec.type = SLANG_SPEC_IVEC3;
+ else if (op->literal_size == 4)
+ ti->spec.type = SLANG_SPEC_IVEC4;
+ else {
+ _mesa_problem(NULL,
+ "Unexpected int literal_size %d in _slang_typeof_operation()",
+ op->literal_size);
+ ti->spec.type = SLANG_SPEC_INT;
+ }
break;
- case slang_oper_identifier:
+ case SLANG_OPER_LITERAL_FLOAT:
+ if (op->literal_size == 1)
+ ti->spec.type = SLANG_SPEC_FLOAT;
+ else if (op->literal_size == 2)
+ ti->spec.type = SLANG_SPEC_VEC2;
+ else if (op->literal_size == 3)
+ ti->spec.type = SLANG_SPEC_VEC3;
+ else if (op->literal_size == 4)
+ ti->spec.type = SLANG_SPEC_VEC4;
+ else {
+ _mesa_problem(NULL,
+ "Unexpected float literal_size %d in _slang_typeof_operation()",
+ op->literal_size);
+ ti->spec.type = SLANG_SPEC_FLOAT;
+ }
+ break;
+ case SLANG_OPER_IDENTIFIER:
+ case SLANG_OPER_VARIABLE_DECL:
{
slang_variable *var;
var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE);
- if (var == NULL)
- RETURN_ERROR2("undefined variable", (char *) op->a_id, 0);
- if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier))
- RETURN_OUT_OF_MEMORY();
+ if (!var) {
+ slang_info_log_error(log, "undefined variable '%s'",
+ (char *) op->a_id);
+ return GL_FALSE;
+ }
+ if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier)) {
+ slang_info_log_memory(log);
+ return GL_FALSE;
+ }
ti->can_be_referenced = GL_TRUE;
ti->array_len = var->array_len;
}
break;
- case slang_oper_sequence:
+ case SLANG_OPER_SEQUENCE:
/* TODO: check [0] and [1] if they match */
- if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms))
- RETURN_NIL();
+ if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms, log)) {
+ return GL_FALSE;
+ }
ti->can_be_referenced = GL_FALSE;
ti->is_swizzled = GL_FALSE;
break;
- /*case slang_oper_modassign: */
- /*case slang_oper_lshassign: */
- /*case slang_oper_rshassign: */
- /*case slang_oper_orassign: */
- /*case slang_oper_xorassign: */
- /*case slang_oper_andassign: */
- case slang_oper_select:
+ /*case SLANG_OPER_MODASSIGN: */
+ /*case SLANG_OPER_LSHASSIGN: */
+ /*case SLANG_OPER_RSHASSIGN: */
+ /*case SLANG_OPER_ORASSIGN: */
+ /*case SLANG_OPER_XORASSIGN: */
+ /*case SLANG_OPER_ANDASSIGN: */
+ case SLANG_OPER_SELECT:
/* TODO: check [1] and [2] if they match */
- if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms))
- RETURN_NIL();
+ if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms, log)) {
+ return GL_FALSE;
+ }
ti->can_be_referenced = GL_FALSE;
ti->is_swizzled = GL_FALSE;
break;
- /*case slang_oper_bitor: */
- /*case slang_oper_bitxor: */
- /*case slang_oper_bitand: */
- /*case slang_oper_lshift: */
- /*case slang_oper_rshift: */
- case slang_oper_add:
- if (!typeof_existing_function("+", op->children, 2, space,
- &ti->spec, atoms))
- RETURN_NIL();
+ /*case SLANG_OPER_BITOR: */
+ /*case SLANG_OPER_BITXOR: */
+ /*case SLANG_OPER_BITAND: */
+ /*case SLANG_OPER_LSHIFT: */
+ /*case SLANG_OPER_RSHIFT: */
+ case SLANG_OPER_ADD:
+ assert(op->num_children == 2);
+ if (!typeof_math_call("+", op, space, &ti->spec, atoms, log))
+ return GL_FALSE;
break;
- case slang_oper_subtract:
- if (!typeof_existing_function("-", op->children, 2, space,
- &ti->spec, atoms))
- RETURN_NIL();
+ case SLANG_OPER_SUBTRACT:
+ assert(op->num_children == 2);
+ if (!typeof_math_call("-", op, space, &ti->spec, atoms, log))
+ return GL_FALSE;
break;
- case slang_oper_multiply:
- if (!typeof_existing_function("*", op->children, 2, space,
- &ti->spec, atoms))
- RETURN_NIL();
+ case SLANG_OPER_MULTIPLY:
+ assert(op->num_children == 2);
+ if (!typeof_math_call("*", op, space, &ti->spec, atoms, log))
+ return GL_FALSE;
break;
- case slang_oper_divide:
- if (!typeof_existing_function("/", op->children, 2, space,
- &ti->spec, atoms))
- RETURN_NIL();
+ case SLANG_OPER_DIVIDE:
+ assert(op->num_children == 2);
+ if (!typeof_math_call("/", op, space, &ti->spec, atoms, log))
+ return GL_FALSE;
break;
- /*case slang_oper_modulus: */
- case slang_oper_plus:
- if (!_slang_typeof_operation_(op->children, space, ti, atoms))
- RETURN_NIL();
+ /*case SLANG_OPER_MODULUS: */
+ case SLANG_OPER_PLUS:
+ if (!_slang_typeof_operation_(op->children, space, ti, atoms, log))
+ return GL_FALSE;
ti->can_be_referenced = GL_FALSE;
ti->is_swizzled = GL_FALSE;
break;
- case slang_oper_minus:
- if (!typeof_existing_function("-", op->children, 1, space,
- &ti->spec, atoms))
- RETURN_NIL();
+ case SLANG_OPER_MINUS:
+ assert(op->num_children == 1);
+ if (!typeof_math_call("-", op, space, &ti->spec, atoms, log))
+ return GL_FALSE;
break;
- /*case slang_oper_complement: */
- case slang_oper_subscript:
+ /*case SLANG_OPER_COMPLEMENT: */
+ case SLANG_OPER_SUBSCRIPT:
{
- slang_assembly_typeinfo _ti;
+ slang_typeinfo _ti;
- if (!slang_assembly_typeinfo_construct(&_ti))
- RETURN_NIL();
- if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) {
- slang_assembly_typeinfo_destruct(&_ti);
- RETURN_NIL();
+ if (!slang_typeinfo_construct(&_ti))
+ return GL_FALSE;
+ if (!_slang_typeof_operation_(op->children, space, &_ti, atoms, log)) {
+ slang_typeinfo_destruct(&_ti);
+ return GL_FALSE;
}
ti->can_be_referenced = _ti.can_be_referenced;
- if (_ti.spec.type == slang_spec_array) {
+ if (_ti.spec.type == SLANG_SPEC_ARRAY) {
if (!slang_type_specifier_copy(&ti->spec, _ti.spec._array)) {
- slang_assembly_typeinfo_destruct(&_ti);
- RETURN_NIL();
+ slang_typeinfo_destruct(&_ti);
+ return GL_FALSE;
}
}
else {
if (!_slang_type_is_vector(_ti.spec.type)
&& !_slang_type_is_matrix(_ti.spec.type)) {
- slang_assembly_typeinfo_destruct(&_ti);
- RETURN_ERROR("cannot index a non-array type", 0);
+ slang_typeinfo_destruct(&_ti);
+ slang_info_log_error(log, "cannot index a non-array type");
+ return GL_FALSE;
}
ti->spec.type = _slang_type_base(_ti.spec.type);
}
- slang_assembly_typeinfo_destruct(&_ti);
+ slang_typeinfo_destruct(&_ti);
}
break;
- case slang_oper_call:
- {
- GLboolean exists;
-
+ case SLANG_OPER_CALL:
+ if (op->fun) {
+ /* we've resolved this call before */
+ slang_type_specifier_copy(&ti->spec, &op->fun->header.type.specifier);
+ }
+ else {
+ slang_function *fun;
if (!_slang_typeof_function(op->a_id, op->children, op->num_children,
- space, &ti->spec, &exists, atoms))
- RETURN_NIL();
- if (!exists) {
+ space, &ti->spec, &fun, atoms, log))
+ return GL_FALSE;
+ if (fun) {
+ /* save result for future use */
+ op->fun = fun;
+ }
+ else {
slang_struct *s =
slang_struct_scope_find(space->structs, op->a_id, GL_TRUE);
- if (s != NULL) {
- ti->spec.type = slang_spec_struct;
+ if (s) {
+ /* struct initializer */
+ ti->spec.type = SLANG_SPEC_STRUCT;
ti->spec._struct =
- (slang_struct *) slang_alloc_malloc(sizeof(slang_struct));
+ (slang_struct *) _slang_alloc(sizeof(slang_struct));
if (ti->spec._struct == NULL)
- RETURN_NIL();
+ return GL_FALSE;
if (!slang_struct_construct(ti->spec._struct)) {
- slang_alloc_free(ti->spec._struct);
+ _slang_free(ti->spec._struct);
ti->spec._struct = NULL;
- RETURN_NIL();
+ return GL_FALSE;
}
if (!slang_struct_copy(ti->spec._struct, s))
- RETURN_NIL();
+ return GL_FALSE;
}
else {
+ /* float, int, vec4, mat3, etc. constructor? */
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_ERROR2("function not found", name, 0);
+ if (type == SLANG_SPEC_VOID) {
+ slang_info_log_error(log, "undefined function '%s'", name);
+ return GL_FALSE;
+ }
ti->spec.type = type;
}
}
}
break;
- case slang_oper_field:
+ case SLANG_OPER_FIELD:
{
- slang_assembly_typeinfo _ti;
+ slang_typeinfo _ti;
- if (!slang_assembly_typeinfo_construct(&_ti))
- RETURN_NIL();
- if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) {
- slang_assembly_typeinfo_destruct(&_ti);
- RETURN_NIL();
+ if (!slang_typeinfo_construct(&_ti))
+ return GL_FALSE;
+ if (!_slang_typeof_operation_(op->children, space, &_ti, atoms, log)) {
+ slang_typeinfo_destruct(&_ti);
+ return GL_FALSE;
}
- if (_ti.spec.type == slang_spec_struct) {
+ if (_ti.spec.type == SLANG_SPEC_STRUCT) {
slang_variable *field;
field = _slang_locate_variable(_ti.spec._struct->fields, op->a_id,
GL_FALSE);
if (field == NULL) {
- slang_assembly_typeinfo_destruct(&_ti);
- RETURN_NIL();
+ slang_typeinfo_destruct(&_ti);
+ return GL_FALSE;
}
if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) {
- slang_assembly_typeinfo_destruct(&_ti);
- RETURN_NIL();
+ slang_typeinfo_destruct(&_ti);
+ return GL_FALSE;
}
ti->can_be_referenced = _ti.can_be_referenced;
}
slang_type_specifier_type base;
/* determine the swizzle of the field expression */
-#if 000
if (!_slang_type_is_vector(_ti.spec.type)) {
- slang_assembly_typeinfo_destruct(&_ti);
- RETURN_ERROR("Can't swizzle scalar expression", 0);
+ slang_typeinfo_destruct(&_ti);
+ slang_info_log_error(log, "Can't swizzle scalar expression");
+ return GL_FALSE;
}
-#endif
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_ERROR("Bad swizzle", 0);
+ slang_typeinfo_destruct(&_ti);
+ slang_info_log_error(log, "bad swizzle '%s'", swizzle);
+ return GL_FALSE;
}
ti->is_swizzled = GL_TRUE;
ti->can_be_referenced = _ti.can_be_referenced
break;
case 2:
switch (base) {
- case slang_spec_float:
- ti->spec.type = slang_spec_vec2;
+ case SLANG_SPEC_FLOAT:
+ ti->spec.type = SLANG_SPEC_VEC2;
break;
- case slang_spec_int:
- ti->spec.type = slang_spec_ivec2;
+ case SLANG_SPEC_INT:
+ ti->spec.type = SLANG_SPEC_IVEC2;
break;
- case slang_spec_bool:
- ti->spec.type = slang_spec_bvec2;
+ case SLANG_SPEC_BOOL:
+ ti->spec.type = SLANG_SPEC_BVEC2;
break;
default:
break;
break;
case 3:
switch (base) {
- case slang_spec_float:
- ti->spec.type = slang_spec_vec3;
+ case SLANG_SPEC_FLOAT:
+ ti->spec.type = SLANG_SPEC_VEC3;
break;
- case slang_spec_int:
- ti->spec.type = slang_spec_ivec3;
+ case SLANG_SPEC_INT:
+ ti->spec.type = SLANG_SPEC_IVEC3;
break;
- case slang_spec_bool:
- ti->spec.type = slang_spec_bvec3;
+ case SLANG_SPEC_BOOL:
+ ti->spec.type = SLANG_SPEC_BVEC3;
break;
default:
break;
break;
case 4:
switch (base) {
- case slang_spec_float:
- ti->spec.type = slang_spec_vec4;
+ case SLANG_SPEC_FLOAT:
+ ti->spec.type = SLANG_SPEC_VEC4;
break;
- case slang_spec_int:
- ti->spec.type = slang_spec_ivec4;
+ case SLANG_SPEC_INT:
+ ti->spec.type = SLANG_SPEC_IVEC4;
break;
- case slang_spec_bool:
- ti->spec.type = slang_spec_bvec4;
+ case SLANG_SPEC_BOOL:
+ ti->spec.type = SLANG_SPEC_BVEC4;
break;
default:
break;
break;
}
}
- slang_assembly_typeinfo_destruct(&_ti);
+ slang_typeinfo_destruct(&_ti);
}
break;
- case slang_oper_postincrement:
- case slang_oper_postdecrement:
- if (!_slang_typeof_operation_(op->children, space, ti, atoms))
- RETURN_NIL();
+ case SLANG_OPER_POSTINCREMENT:
+ case SLANG_OPER_POSTDECREMENT:
+ if (!_slang_typeof_operation_(op->children, space, ti, atoms, log))
+ return GL_FALSE;
ti->can_be_referenced = GL_FALSE;
ti->is_swizzled = GL_FALSE;
break;
default:
- RETURN_NIL();
+ return GL_FALSE;
}
return GL_TRUE;
}
-
/**
- * Determine the return type of a function.
- * \param a_name the function name
- * \param param function parameters (overloading)
- * \param num_params number of parameters to function
- * \param space namespace to search
- * \param exists returns GL_TRUE or GL_FALSE to indicate existance of function
- * \return GL_TRUE for success, GL_FALSE if failure (bad function name)
+ * Lookup a function according to name and parameter count/types.
*/
-GLboolean
-_slang_typeof_function(slang_atom a_name, const slang_operation * params,
- GLuint num_params,
- const slang_assembly_name_space * space,
- slang_type_specifier * spec, GLboolean * exists,
- slang_atom_pool * atoms)
+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, GLboolean *error)
{
- slang_function *fun = _slang_locate_function(space->funcs, a_name, params,
- num_params, space, atoms);
- *exists = fun != NULL;
- if (!fun)
- return GL_TRUE; /* yes, not false */
- return slang_type_specifier_copy(spec, &fun->header.type.specifier);
-}
+ slang_typeinfo arg_ti[100];
+ GLuint i;
+
+ *error = GL_FALSE;
+
+ /* 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;
+ }
+ }
+
+ /* 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;
+}
/**
_slang_type_is_matrix(slang_type_specifier_type ty)
{
switch (ty) {
- case slang_spec_mat2:
- case slang_spec_mat3:
- case slang_spec_mat4:
+ case SLANG_SPEC_MAT2:
+ case SLANG_SPEC_MAT3:
+ case SLANG_SPEC_MAT4:
+ case SLANG_SPEC_MAT23:
+ case SLANG_SPEC_MAT32:
+ case SLANG_SPEC_MAT24:
+ case SLANG_SPEC_MAT42:
+ case SLANG_SPEC_MAT34:
+ case SLANG_SPEC_MAT43:
return GL_TRUE;
default:
return GL_FALSE;
_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:
+ 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 GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+}
+
+
+/**
+ * Determine if a type is a float, float vector or float matrix.
+ * \return GL_TRUE if so, GL_FALSE otherwise
+ */
+GLboolean
+_slang_type_is_float_vec_mat(slang_type_specifier_type ty)
+{
+ switch (ty) {
+ case SLANG_SPEC_FLOAT:
+ case SLANG_SPEC_VEC2:
+ case SLANG_SPEC_VEC3:
+ case SLANG_SPEC_VEC4:
+ case SLANG_SPEC_MAT2:
+ case SLANG_SPEC_MAT3:
+ case SLANG_SPEC_MAT4:
+ case SLANG_SPEC_MAT23:
+ case SLANG_SPEC_MAT32:
+ case SLANG_SPEC_MAT24:
+ case SLANG_SPEC_MAT42:
+ case SLANG_SPEC_MAT34:
+ case SLANG_SPEC_MAT43:
return GL_TRUE;
default:
return GL_FALSE;
/**
- * Given a vector type, return the type of the vector's elements
+ * Given a vector type, return the type of the vector's elements.
+ * For a matrix, return the type of the columns.
*/
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;
+ 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;
+ case SLANG_SPEC_MAT23:
+ return SLANG_SPEC_VEC3;
+ case SLANG_SPEC_MAT32:
+ return SLANG_SPEC_VEC2;
+ case SLANG_SPEC_MAT24:
+ return SLANG_SPEC_VEC4;
+ case SLANG_SPEC_MAT42:
+ return SLANG_SPEC_VEC2;
+ case SLANG_SPEC_MAT34:
+ return SLANG_SPEC_VEC4;
+ case SLANG_SPEC_MAT43:
+ return SLANG_SPEC_VEC3;
default:
- return slang_spec_void;
+ return SLANG_SPEC_VOID;
}
}
/**
- * Return the dimensionality of a vector or matrix type.
+ * Return the dimensionality of a vector, or for a matrix, return number
+ * of columns.
*/
GLuint
_slang_type_dim(slang_type_specifier_type ty)
{
switch (ty) {
- case slang_spec_float:
- case slang_spec_int:
- case slang_spec_bool:
+ 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:
+ 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:
+ 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:
+ case SLANG_SPEC_VEC4:
+ case SLANG_SPEC_IVEC4:
+ case SLANG_SPEC_BVEC4:
+ case SLANG_SPEC_MAT4:
return 4;
+
+ case SLANG_SPEC_MAT23:
+ return 2;
+ case SLANG_SPEC_MAT32:
+ return 3;
+ case SLANG_SPEC_MAT24:
+ return 2;
+ case SLANG_SPEC_MAT42:
+ return 4;
+ case SLANG_SPEC_MAT34:
+ return 3;
+ case SLANG_SPEC_MAT43:
+ return 4;
+
default:
return 0;
}
}
+
+
+/**
+ * Return the GL_* type that corresponds to a SLANG_SPEC_* type.
+ */
+GLenum
+_slang_gltype_from_specifier(const slang_type_specifier *type)
+{
+ switch (type->type) {
+ case SLANG_SPEC_BOOL:
+ return GL_BOOL;
+ case SLANG_SPEC_BVEC2:
+ return GL_BOOL_VEC2;
+ case SLANG_SPEC_BVEC3:
+ return GL_BOOL_VEC3;
+ case SLANG_SPEC_BVEC4:
+ return GL_BOOL_VEC4;
+ case SLANG_SPEC_INT:
+ return GL_INT;
+ case SLANG_SPEC_IVEC2:
+ return GL_INT_VEC2;
+ case SLANG_SPEC_IVEC3:
+ return GL_INT_VEC3;
+ case SLANG_SPEC_IVEC4:
+ return GL_INT_VEC4;
+ case SLANG_SPEC_FLOAT:
+ return GL_FLOAT;
+ case SLANG_SPEC_VEC2:
+ return GL_FLOAT_VEC2;
+ case SLANG_SPEC_VEC3:
+ return GL_FLOAT_VEC3;
+ case SLANG_SPEC_VEC4:
+ return GL_FLOAT_VEC4;
+ case SLANG_SPEC_MAT2:
+ return GL_FLOAT_MAT2;
+ case SLANG_SPEC_MAT3:
+ return GL_FLOAT_MAT3;
+ case SLANG_SPEC_MAT4:
+ return GL_FLOAT_MAT4;
+ case SLANG_SPEC_MAT23:
+ return GL_FLOAT_MAT2x3;
+ case SLANG_SPEC_MAT32:
+ return GL_FLOAT_MAT3x2;
+ case SLANG_SPEC_MAT24:
+ return GL_FLOAT_MAT2x4;
+ case SLANG_SPEC_MAT42:
+ return GL_FLOAT_MAT4x2;
+ case SLANG_SPEC_MAT34:
+ return GL_FLOAT_MAT3x4;
+ case SLANG_SPEC_MAT43:
+ return GL_FLOAT_MAT4x3;
+ case SLANG_SPEC_SAMPLER1D:
+ return GL_SAMPLER_1D;
+ case SLANG_SPEC_SAMPLER2D:
+ return GL_SAMPLER_2D;
+ case SLANG_SPEC_SAMPLER3D:
+ return GL_SAMPLER_3D;
+ case SLANG_SPEC_SAMPLERCUBE:
+ return GL_SAMPLER_CUBE;
+ case SLANG_SPEC_SAMPLER1DSHADOW:
+ return GL_SAMPLER_1D_SHADOW;
+ case SLANG_SPEC_SAMPLER2DSHADOW:
+ return GL_SAMPLER_2D_SHADOW;
+ case SLANG_SPEC_SAMPLER2DRECT:
+ return GL_SAMPLER_2D_RECT_ARB;
+ case SLANG_SPEC_SAMPLER2DRECTSHADOW:
+ return GL_SAMPLER_2D_RECT_SHADOW_ARB;
+ case SLANG_SPEC_ARRAY:
+ return _slang_gltype_from_specifier(type->_array);
+ case SLANG_SPEC_STRUCT:
+ /* fall-through */
+ default:
+ return GL_NONE;
+ }
+}
+