_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper);
+/**
+ * Retrieves type information about an operation.
+ * Returns GL_TRUE on success.
+ * Returns GL_FALSE otherwise.
+ */
+static GLboolean
+typeof_operation(const struct slang_assemble_ctx_ * A,
+ slang_operation * op,
+ slang_typeinfo * ti)
+{
+ return _slang_typeof_operation(op, &A->space, ti, A->atoms, A->log);
+}
+
+
static GLboolean
is_sampler_type(const slang_fully_specified_type *t)
{
if (!n->Store) {
/* need to setup storage */
- if (n->Var && n->Var->aux) {
+ if (n->Var && n->Var->store) {
/* node storage info = var storage info */
- n->Store = (slang_ir_storage *) n->Var->aux;
+ n->Store = n->Var->store;
}
else {
/* alloc new storage info */
(void*) n->Store, n->Store->Size);
#endif
if (n->Var)
- n->Var->aux = n->Store;
- assert(n->Var->aux);
+ n->Var->store = n->Store;
+ assert(n->Var->store);
}
}
}
{ "vec4_multiply", IR_MUL, 1, 2 },
{ "vec4_dot", IR_DOT4, 1, 2 },
{ "vec3_dot", IR_DOT3, 1, 2 },
+ { "vec2_dot", IR_DOT2, 1, 2 },
+ { "vec3_nrm", IR_NRM3, 1, 1 },
+ { "vec4_nrm", IR_NRM4, 1, 1 },
{ "vec3_cross", IR_CROSS, 1, 2 },
{ "vec4_lrp", IR_LRP, 1, 3 },
{ "vec4_min", IR_MIN, 1, 2 },
n->Children[0] = c0;
n->Children[1] = c1;
n->Children[2] = c2;
- n->Writemask = WRITEMASK_XYZW;
n->InstLocation = -1;
}
return n;
* New IR_VAR node - a reference to a previously declared variable.
*/
static slang_ir_node *
-new_var(slang_assemble_ctx *A, slang_operation *oper, slang_atom name)
+new_var(slang_assemble_ctx *A, slang_variable *var)
{
slang_ir_node *n;
- slang_variable *var = _slang_locate_variable(oper->locals, name, GL_TRUE);
if (!var)
return NULL;
assert(var->declared);
- assert(!oper->var || oper->var == var);
-
n = new_node0(IR_VAR);
if (n) {
_slang_attach_storage(n, var);
slang_resolve_variable(slang_operation *oper)
{
if (oper->type == SLANG_OPER_IDENTIFIER && !oper->var) {
- oper->var = _slang_locate_variable(oper->locals, oper->a_id, GL_TRUE);
+ oper->var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
}
}
switch (oper->type) {
case SLANG_OPER_VARIABLE_DECL:
{
- slang_variable *v = _slang_locate_variable(oper->locals,
+ slang_variable *v = _slang_variable_locate(oper->locals,
oper->a_id, GL_TRUE);
assert(v);
if (v->initializer && oper->num_children == 0) {
slang_atom id = oper->a_id;
slang_variable *v;
GLuint i;
- v = _slang_locate_variable(oper->locals, id, GL_TRUE);
+ v = _slang_variable_locate(oper->locals, id, GL_TRUE);
if (!v) {
_mesa_problem(NULL, "var %s not found!\n", (char *) oper->a_id);
return;
* Convert the given swizzle into a writemask. In some cases this
* is trivial, in other cases, we'll need to also swizzle the right
* hand side to put components in the right places.
+ * See comment above for more info.
+ * XXX this function could be simplified and should probably be renamed.
* \param swizzle the incoming swizzle
* \param writemaskOut returns the writemask
* \param swizzleOut swizzle to apply to the right-hand-side
}
-/**
- * As above, but produce a writemask.
- */
-static GLuint
-resolve_writemask(slang_assemble_ctx *A, const slang_operation *oper)
-{
- GLuint swizzle = resolve_swizzle(oper);
- GLuint writemask, swizzleOut;
- swizzle_to_writemask(A, swizzle, &writemask, &swizzleOut);
- return writemask;
-}
-
-
/**
* Recursively descend through swizzle nodes to find the node's storage info.
*/
/* Setup n->Store to be a particular location. Otherwise, storage
* for the result (a temporary) will be allocated later.
*/
- GLuint writemask = WRITEMASK_XYZW;
slang_operation *dest_oper;
slang_ir_node *n0;
dest_oper = &oper->children[0];
- writemask = resolve_writemask(A, dest_oper);
-
n0 = _slang_gen_operation(A, dest_oper);
if (!n0)
return NULL;
* struct type.
*/
static slang_function *
-_slang_make_constructor(slang_assemble_ctx *A, slang_struct *str)
+_slang_make_struct_constructor(slang_assemble_ctx *A, slang_struct *str)
{
const GLint numFields = str->fields->num_variables;
-
- slang_function *fun = (slang_function *) _mesa_malloc(sizeof(slang_function));
- if (!fun)
- return NULL;
-
- slang_function_construct(fun);
+ slang_function *fun = slang_function_new(SLANG_FUNC_CONSTRUCTOR);
/* function header (name, return type) */
- fun->kind = SLANG_FUNC_CONSTRUCTOR;
fun->header.a_name = str->a_name;
fun->header.type.qualifier = SLANG_QUAL_NONE;
fun->header.type.specifier.type = SLANG_SPEC_STRUCT;
ret->children[0].type = SLANG_OPER_IDENTIFIER;
ret->children[0].a_id = var->a_name;
ret->children[0].locals = _slang_variable_scope_new(scope);
-
}
}
/*
/* found a structure type that matches the function name */
if (!str->constructor) {
/* create the constructor function now */
- str->constructor = _slang_make_constructor(A, str);
+ str->constructor = _slang_make_struct_constructor(A, str);
}
return str->constructor;
}
}
+/**
+ * Generate a new slang_function to satisfy a call to an array constructor.
+ * Ex: float[3](1., 2., 3.)
+ */
+static slang_function *
+_slang_make_array_constructor(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_function *fun = slang_function_new(SLANG_FUNC_CONSTRUCTOR);
+ if (fun) {
+ slang_type_specifier_type baseType =
+ slang_type_specifier_type_from_string((char *) oper->a_id);
+
+ fun->header.a_name = oper->a_id;
+ fun->header.type.qualifier = SLANG_QUAL_NONE;
+ fun->header.type.specifier.type = SLANG_SPEC_ARRAY;
+ fun->header.type.specifier._array =
+ slang_type_specifier_new(baseType, NULL, NULL);
+
+
+ }
+ return fun;
+}
+
static GLboolean
_slang_is_vec_mat_type(const char *name)
if (atom == SLANG_ATOM_NULL)
return NULL;
- /*
- * 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, &error);
+ if (oper->array_constructor) {
+ /* this needs special handling */
+ fun = _slang_make_array_constructor(A, oper);
+ }
+ else {
+ /* Try to find function by name and exact argument type matching */
+ fun = _slang_function_locate(A->space.funcs, atom, params, param_count,
+ &A->space, A->atoms, A->log, &error);
+ }
if (error) {
slang_info_log_error(A->log,
name);
return NULL;
}
+ if (!fun->body) {
+ slang_info_log_error(A->log,
+ "Function '%s' prototyped but not defined. "
+ "Separate compilation units not supported.",
+ name);
+ return NULL;
+ }
+
+ /* type checking to be sure function's return type matches 'dest' type */
+ if (dest) {
+ slang_typeinfo t0;
+
+ slang_typeinfo_construct(&t0);
+ typeof_operation(A, dest, &t0);
+
+ if (!slang_type_specifier_equal(&t0.spec, &fun->header.type.specifier)) {
+ slang_info_log_error(A->log,
+ "Incompatible type returned by call to '%s'",
+ name);
+ return NULL;
+ }
+ }
n = _slang_gen_function_call(A, fun, oper, dest);
}
+static slang_ir_node *
+_slang_gen_method_call(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_atom *a_length = slang_atom_pool_atom(A->atoms, "length");
+ slang_ir_node *n;
+ slang_variable *var;
+
+ /* NOTE: In GLSL 1.20, there's only one kind of method
+ * call: array.length(). Anything else is an error.
+ */
+ if (oper->a_id != a_length) {
+ slang_info_log_error(A->log,
+ "Undefined method call '%s'", (char *) oper->a_id);
+ return NULL;
+ }
+
+ /* length() takes no arguments */
+ if (oper->num_children > 0) {
+ slang_info_log_error(A->log, "Invalid arguments to length() method");
+ return NULL;
+ }
+
+ /* lookup the object/variable */
+ var = _slang_variable_locate(oper->locals, oper->a_obj, GL_TRUE);
+ if (!var || var->type.specifier.type != SLANG_SPEC_ARRAY) {
+ slang_info_log_error(A->log,
+ "Undefined object '%s'", (char *) oper->a_obj);
+ return NULL;
+ }
+
+ /* Create a float/literal IR node encoding the array length */
+ n = new_node0(IR_FLOAT);
+ if (n) {
+ n->Value[0] = (float) var->array_len;
+ n->Store = _slang_new_ir_storage(PROGRAM_CONSTANT, -1, 1);
+ }
+ return n;
+}
+
+
static GLboolean
_slang_is_constant_cond(const slang_operation *oper, GLboolean *value)
{
GLint size;
slang_typeinfo_construct(&type);
- _slang_typeof_operation(A, oper, &type);
+ typeof_operation(A, oper, &type);
size = _slang_sizeof_type_specifier(&type.spec);
slang_typeinfo_destruct(&type);
return size == 1;
GLboolean isBool;
slang_typeinfo_construct(&type);
- _slang_typeof_operation(A, oper, &type);
+ typeof_operation(A, oper, &type);
isBool = (type.spec.type == SLANG_SPEC_BOOL);
slang_typeinfo_destruct(&type);
return isBool;
/* type-check expression */
if (!_slang_is_boolean(A, &oper->children[0])) {
- slang_info_log_error(A->log, "boolean expression expected for 'while'");
+ slang_info_log_error(A->log, "boolean expression expected for 'if'");
return NULL;
}
/**
* Generate IR node for allocating/declaring a variable.
+ * \param initializer Optional initializer expression for the variable.
*/
static slang_ir_node *
-_slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var)
+_slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var,
+ slang_operation *initializer)
{
- slang_ir_node *n;
+ slang_ir_node *varDecl, *n;
+ slang_ir_storage *store;
/*assert(!var->declared);*/
var->declared = GL_TRUE;
- assert(!is_sampler_type(&var->type));
+ varDecl = new_node0(IR_VAR_DECL);
+ if (!varDecl)
+ return NULL;
- n = new_node0(IR_VAR_DECL);
- if (n) {
- _slang_attach_storage(n, var);
- assert(var->aux);
- assert(n->Store == var->aux);
- assert(n->Store);
- assert(n->Store->Index < 0);
+ _slang_attach_storage(varDecl, var);
+ assert(var->store);
+ assert(varDecl->Store == var->store);
+ assert(varDecl->Store);
+ assert(varDecl->Store->Index < 0);
+ store = var->store;
- n->Store->File = PROGRAM_TEMPORARY;
- n->Store->Size = _slang_sizeof_type_specifier(&n->Var->type.specifier);
+ assert(store == varDecl->Store);
+
+ /* determine GPU storage file */
+ /* XXX if the variable is const, use PROGRAM_CONSTANT */
+ if (is_sampler_type(&var->type)) {
+ store->File = PROGRAM_SAMPLER;
+ }
+ else {
+ store->File = PROGRAM_TEMPORARY;
+ }
+
+ store->Size = _slang_sizeof_type_specifier(&varDecl->Var->type.specifier);
+
+ if (store->Size <= 0) {
+ slang_info_log_error(A->log, "invalid declaration for '%s'",
+ (char*) var->a_name);
+ return NULL;
+ }
- 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,
- (void *) n->Store, n->Store->Index, n->Store->Size);
+ printf("%s var %p %s store=%p index=%d size=%d\n",
+ __FUNCTION__, (void *) var, (char *) var->a_name,
+ (void *) store, store->Index, store->Size);
#endif
- if (var->array_len > 0) {
- /* this is an array */
- /* cannot be const-qualified */
- if (var->type.qualifier == SLANG_QUAL_CONST) {
- slang_info_log_error(A->log, "array '%s' cannot be const",
- (char*) var->a_name);
+ if (var->array_len > 0) {
+ /* this is an array */
+ /* round up the element size to a multiple of 4 */
+ GLint sz = (store->Size + 3) & ~3;
+ /* total size = element size * array length */
+ sz *= var->array_len;
+ store->Size = sz;
+ }
+
+ /* setup default swizzle for storing the variable */
+ /* XXX this may not be needed anymore - remove & test */
+ switch (store->Size) {
+ case 2:
+ store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
+ SWIZZLE_NIL, SWIZZLE_NIL);
+ break;
+ case 3:
+ store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
+ SWIZZLE_Z, SWIZZLE_NIL);
+ break;
+ default:
+ /* Note that float-sized vars may be allocated in any x/y/z/w
+ * slot, but that won't be determined until code emit time.
+ */
+ store->Swizzle = SWIZZLE_NOOP;
+ }
+
+ /* if there's an initializer, generate IR for the expression */
+ if (initializer) {
+ const char *varName = (const char *) var->a_name;
+ slang_ir_node *varRef, *init;
+
+ varRef = new_var(A, var);
+ if (!varRef) {
+ slang_info_log_error(A->log, "undefined variable '%s'", varName);
+ return NULL;
+ }
+
+ if (var->type.qualifier == SLANG_QUAL_CONST) {
+ /* if the variable is const, the initializer must be a const
+ * expression as well.
+ */
+#if 0
+ if (!_slang_is_constant_expr(initializer)) {
+ slang_info_log_error(A->log,
+ "initializer for %s not constant", varName);
return NULL;
}
- else {
- /* round up element size to mult of 4 */
- GLint sz = (n->Store->Size + 3) & ~3;
- /* mult by array size */
- sz *= var->array_len;
- n->Store->Size = sz;
- }
+#endif
}
- assert(n->Store->Size > 0);
+ /* constant-folding, etc here */
+ _slang_simplify(initializer, &A->space, A->atoms);
- /* setup default swizzle for storing the variable */
- switch (n->Store->Size) {
- case 2:
- n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
- SWIZZLE_NIL, SWIZZLE_NIL);
- break;
- case 3:
- n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
- SWIZZLE_Z, SWIZZLE_NIL);
- break;
- default:
- /* Note that float-sized vars may be allocated in any x/y/z/w
- * slot, but that won't be determined until code emit time.
- */
- n->Store->Swizzle = SWIZZLE_NOOP;
+ init = _slang_gen_operation(A, initializer);
+ if (!init)
+ return NULL;
+
+ /*assert(init->Store);*/
+
+ /* XXX remove this when type checking is added above */
+ if (init->Store && varRef->Store->Size != init->Store->Size) {
+ slang_info_log_error(A->log, "invalid assignment (wrong types)");
+ return NULL;
}
+
+ n = new_node2(IR_COPY, varRef, init);
+ n = new_seq(varDecl, n);
+ }
+ else {
+ /* no initializer */
+ n = varDecl;
}
+
return n;
}
/* type of children[0] must be boolean */
slang_typeinfo_construct(&type0);
- _slang_typeof_operation(A, &oper->children[0], &type0);
+ typeof_operation(A, &oper->children[0], &type0);
isBool = (type0.spec.type == SLANG_SPEC_BOOL);
slang_typeinfo_destruct(&type0);
if (!isBool) {
slang_typeinfo_construct(&type1);
slang_typeinfo_construct(&type2);
- _slang_typeof_operation(A, &oper->children[1], &type1);
- _slang_typeof_operation(A, &oper->children[2], &type2);
+ typeof_operation(A, &oper->children[1], &type1);
+ typeof_operation(A, &oper->children[2], &type2);
isEqual = slang_type_specifier_equal(&type1.spec, &type2.spec);
slang_typeinfo_destruct(&type1);
slang_typeinfo_destruct(&type2);
#if 1 /* DEBUG */
{
- slang_variable *v
- = _slang_locate_variable(oper->locals, a_retVal, GL_TRUE);
+ slang_variable *v =
+ _slang_variable_locate(oper->locals, a_retVal, GL_TRUE);
if (!v) {
/* trying to return a value in a void-valued function */
return NULL;
switch (oper->type) {
case SLANG_OPER_IDENTIFIER:
- var = _slang_locate_variable(oper->locals, oper->a_id, GL_TRUE);
+ var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
if (var && var->type.qualifier == SLANG_QUAL_CONST)
return GL_TRUE;
return GL_FALSE;
}
slang_typeinfo_construct(&t0);
- _slang_typeof_operation(A, op0, &t0);
+ typeof_operation(A, op0, &t0);
slang_typeinfo_construct(&t1);
- _slang_typeof_operation(A, op1, &t1);
+ typeof_operation(A, op1, &t1);
sz0 = _slang_sizeof_type_specifier(&t0.spec);
sz1 = _slang_sizeof_type_specifier(&t1.spec);
/**
- * Generate IR tree for a variable declaration.
+ * Generate IR tree for a local variable declaration.
*/
static slang_ir_node *
_slang_gen_declaration(slang_assemble_ctx *A, slang_operation *oper)
{
- slang_ir_node *n;
- slang_ir_node *varDecl;
- slang_variable *v;
const char *varName = (char *) oper->a_id;
+ slang_variable *var;
+ slang_ir_node *varDecl;
slang_operation *initializer;
assert(oper->type == SLANG_OPER_VARIABLE_DECL);
assert(oper->num_children <= 1);
- v = _slang_locate_variable(oper->locals, oper->a_id, GL_TRUE);
- if (!v)
+ /* lookup the variable by name */
+ var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
+ if (!var)
return NULL; /* "shouldn't happen" */
- if (v->type.qualifier == SLANG_QUAL_ATTRIBUTE ||
- v->type.qualifier == SLANG_QUAL_VARYING ||
- v->type.qualifier == SLANG_QUAL_UNIFORM) {
+ if (var->type.qualifier == SLANG_QUAL_ATTRIBUTE ||
+ var->type.qualifier == SLANG_QUAL_VARYING ||
+ var->type.qualifier == SLANG_QUAL_UNIFORM) {
/* can't declare attribute/uniform vars inside functions */
slang_info_log_error(A->log,
"local variable '%s' cannot be an attribute/uniform/varying",
}
#endif
- varDecl = _slang_gen_var_decl(A, v);
- if (!varDecl)
- return NULL;
-
/* check if the var has an initializer */
if (oper->num_children > 0) {
assert(oper->num_children == 1);
initializer = &oper->children[0];
}
- else if (v->initializer) {
- initializer = v->initializer;
+ else if (var->initializer) {
+ initializer = var->initializer;
}
else {
initializer = NULL;
}
- if (v->type.qualifier == SLANG_QUAL_CONST && !initializer) {
- slang_info_log_error(A->log,
- "const-qualified variable '%s' requires initializer",
- varName);
- return NULL;
- }
-
-
if (initializer) {
- slang_ir_node *var, *init;
-
- /* type check/compare var and initializer */
+ /* check/compare var type and initializer type */
if (!_slang_assignment_compatible(A, oper, initializer)) {
slang_info_log_error(A->log, "incompatible types in assignment");
return NULL;
}
+ }
- var = new_var(A, oper, oper->a_id);
- if (!var) {
- slang_info_log_error(A->log, "undefined variable '%s'", varName);
- return NULL;
- }
-
- if (v->type.qualifier == SLANG_QUAL_CONST) {
- /* if the variable is const, the initializer must be a const
- * expression as well.
- */
-#if 0
- if (!_slang_is_constant_expr(initializer)) {
- slang_info_log_error(A->log,
- "initializer for %s not constant", varName);
- return NULL;
- }
-#endif
- }
-
- _slang_simplify(initializer, &A->space, A->atoms);
-
- init = _slang_gen_operation(A, initializer);
- if (!init)
- return NULL;
-
- /*assert(init->Store);*/
-
- /* XXX remove this when type checking is added above */
- if (init->Store && var->Store->Size != init->Store->Size) {
- slang_info_log_error(A->log, "invalid assignment (wrong types)");
- return NULL;
- }
+ /* Generate IR node */
+ varDecl = _slang_gen_var_decl(A, var, initializer);
+ if (!varDecl)
+ return NULL;
- n = new_node2(IR_COPY, var, init);
- n = new_seq(varDecl, n);
- }
- else {
- n = varDecl;
+ if (var->type.qualifier == SLANG_QUAL_CONST && !initializer) {
+ slang_info_log_error(A->log,
+ "const-qualified variable '%s' requires initializer",
+ varName);
+ return NULL;
}
- return n;
+ return varDecl;
}
/* If there's a variable associated with this oper (from inlining)
* use it. Otherwise, use the oper's var id.
*/
- slang_atom aVar = oper->var ? oper->var->a_name : oper->a_id;
- slang_ir_node *n = new_var(A, oper, aVar);
+ slang_atom name = oper->var ? oper->var->a_name : oper->a_id;
+ slang_variable *var = _slang_variable_locate(oper->locals, name, GL_TRUE);
+ slang_ir_node *n = new_var(A, var);
if (!n) {
- slang_info_log_error(A->log, "undefined variable '%s'", (char *) aVar);
+ slang_info_log_error(A->log, "undefined variable '%s'", (char *) name);
return NULL;
}
return n;
if (oper->children[0].type == SLANG_OPER_IDENTIFIER) {
/* Check that var is writeable */
slang_variable *var
- = _slang_locate_variable(oper->children[0].locals,
+ = _slang_variable_locate(oper->children[0].locals,
oper->children[0].a_id, GL_TRUE);
if (!var) {
slang_info_log_error(A->log, "undefined variable '%s'",
rhs = _slang_gen_swizzle(rhs, newSwizzle);
}
n = new_node2(IR_COPY, lhs, rhs);
- n->Writemask = writemask;
return n;
}
else {
/* type of struct */
slang_typeinfo_construct(&ti);
- _slang_typeof_operation(A, &oper->children[0], &ti);
+ typeof_operation(A, &oper->children[0], &ti);
if (_slang_type_is_vector(ti.spec.type)) {
/* the field should be a swizzle */
/* oper->a_id is the field name */
slang_ir_node *base, *n;
slang_typeinfo field_ti;
- GLint fieldSize, fieldOffset = -1, swz;
+ GLint fieldSize, fieldOffset = -1;
/* type of field */
slang_typeinfo_construct(&field_ti);
- _slang_typeof_operation(A, oper, &field_ti);
+ typeof_operation(A, oper, &field_ti);
fieldSize = _slang_sizeof_type_specifier(&field_ti.spec);
if (fieldSize > 0)
if (!n)
return NULL;
-
- /* setup the storage info for this node */
- swz = fieldOffset % 4;
-
n->Field = (char *) oper->a_id;
- n->Store = _slang_new_ir_storage_relative(fieldOffset / 4,
- fieldSize,
- base->Store);
- if (fieldSize == 1)
- n->Store->Swizzle = MAKE_SWIZZLE4(swz, swz, swz, swz);
- else if (fieldSize == 2)
- n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
- SWIZZLE_NIL, SWIZZLE_NIL);
- else if (fieldSize == 3)
- n->Store->Swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y,
- SWIZZLE_Z, SWIZZLE_NIL);
+
+ /* Store the field's offset in storage->Index */
+ n->Store = _slang_new_ir_storage(base->Store->File,
+ fieldOffset,
+ fieldSize);
return n;
}
/* get array's type info */
slang_typeinfo_construct(&array_ti);
- _slang_typeof_operation(A, &oper->children[0], &array_ti);
+ typeof_operation(A, &oper->children[0], &array_ti);
if (_slang_type_is_vector(array_ti.spec.type)) {
/* indexing a simple vector type: "vec4 v; v[0]=p;" */
SWIZZLE_NIL,
SWIZZLE_NIL);
n = _slang_gen_swizzle(n, swizzle);
- /*n->Store = _slang_clone_ir_storage_swz(n->Store, */
- n->Writemask = WRITEMASK_X << index;
}
assert(n->Store);
return n;
/* size of array element */
slang_typeinfo_construct(&elem_ti);
- _slang_typeof_operation(A, oper, &elem_ti);
+ typeof_operation(A, oper, &elem_ti);
elemSize = _slang_sizeof_type_specifier(&elem_ti.spec);
if (_slang_type_is_matrix(array_ti.spec.type))
index = _slang_gen_operation(A, &oper->children[1]);
if (array && index) {
/* bounds check */
- GLint constIndex = 0;
+ GLint constIndex = -1;
if (index->Opcode == IR_FLOAT) {
constIndex = (int) index->Value[0];
if (constIndex < 0 || constIndex >= arrayLen) {
}
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 */
+ /* The storage info here will be updated during code emit */
+ elem->Store = _slang_new_ir_storage(array->Store->File,
+ array->Store->Index,
+ elemSize);
+
return elem;
}
else {
slang_ir_node *n;
slang_typeinfo_construct(&t0);
- _slang_typeof_operation(A, &oper->children[0], &t0);
+ typeof_operation(A, &oper->children[0], &t0);
slang_typeinfo_construct(&t1);
- _slang_typeof_operation(A, &oper->children[0], &t1);
+ typeof_operation(A, &oper->children[0], &t1);
if (t0.spec.type == SLANG_SPEC_ARRAY ||
t1.spec.type == SLANG_SPEC_ARRAY) {
case SLANG_OPER_CALL:
return _slang_gen_function_call_name(A, (const char *) oper->a_id,
oper, NULL);
+ case SLANG_OPER_METHOD:
+ return _slang_gen_method_call(A, oper);
case SLANG_OPER_RETURN:
return _slang_gen_return(A, oper);
case SLANG_OPER_LABEL:
const GLint totalSize = array_size(size, var->array_len);
const GLuint swizzle = _slang_var_swizzle(totalSize, 0);
- if (var->initializer) {
- slang_info_log_error(A->log, "illegal initializer for uniform '%s'", varName);
- return GL_FALSE;
- }
-
if (prog) {
/* user-defined uniform */
if (datatype == GL_NONE) {
/* temporary work-around */
GLenum datatype = GL_FLOAT;
GLint uniformLoc = _mesa_add_uniform(prog->Parameters, varName,
- totalSize, datatype);
+ totalSize, datatype, NULL);
store = _slang_new_ir_storage_swz(PROGRAM_UNIFORM, uniformLoc,
totalSize, swizzle);
* "f.a" (GL_FLOAT_VEC3)
* "f.b" (GL_FLOAT_VEC4)
*/
+
+ if (var->initializer) {
+ slang_info_log_error(A->log,
+ "unsupported initializer for uniform '%s'", varName);
+ return GL_FALSE;
+ }
}
else {
slang_info_log_error(A->log,
}
}
else {
- GLint uniformLoc = _mesa_add_uniform(prog->Parameters, varName,
- totalSize, datatype);
+ GLint uniformLoc;
+ const GLfloat *initialValues = NULL;
+ if (var->initializer) {
+ _slang_simplify(var->initializer, &A->space, A->atoms);
+ if (var->initializer->type == SLANG_OPER_LITERAL_FLOAT ||
+ var->initializer->type == SLANG_OPER_LITERAL_INT) {
+ /* simple float/vector initializer */
+ initialValues = var->initializer->literal;
+ }
+ else {
+ /* complex initializer */
+ slang_info_log_error(A->log,
+ "unsupported initializer for uniform '%s'", varName);
+ return GL_FALSE;
+ }
+ }
+
+ uniformLoc = _mesa_add_uniform(prog->Parameters, varName,
+ totalSize, datatype, initialValues);
store = _slang_new_ir_storage_swz(PROGRAM_UNIFORM, uniformLoc,
totalSize, swizzle);
}
if (prog) {
/* user-defined varying */
- GLint varyingLoc = _mesa_add_varying(prog->Varying, varName, totalSize);
- GLuint swizzle = _slang_var_swizzle(size, 0);
+ GLbitfield flags;
+ GLint varyingLoc;
+ GLuint swizzle;
+
+ flags = 0x0;
+ if (var->type.centroid == SLANG_CENTROID)
+ flags |= PROG_PARAM_BIT_CENTROID;
+ if (var->type.variant == SLANG_INVARIANT)
+ flags |= PROG_PARAM_BIT_INVARIANT;
+
+ varyingLoc = _mesa_add_varying(prog->Varying, varName,
+ totalSize, flags);
+ swizzle = _slang_var_swizzle(size, 0);
store = _slang_new_ir_storage_swz(PROGRAM_VARYING, varyingLoc,
totalSize, swizzle);
}
if (dbg) printf("VARYING ");
}
else if (var->type.qualifier == SLANG_QUAL_ATTRIBUTE) {
+ GLuint swizzle;
+ GLint index;
/* attributes must be float, vec or mat */
if (!_slang_type_is_float_vec_mat(var->type.specifier.type)) {
slang_info_log_error(A->log,
if (prog) {
/* user-defined vertex attribute */
const GLint attr = -1; /* unknown */
- GLint index = _mesa_add_attribute(prog->Attributes, varName,
- size, datatype, attr);
+ swizzle = _slang_var_swizzle(size, 0);
+ index = _mesa_add_attribute(prog->Attributes, varName,
+ size, datatype, attr);
assert(index >= 0);
- store = _slang_new_ir_storage(PROGRAM_INPUT,
- VERT_ATTRIB_GENERIC0 + index, size);
+ index = VERT_ATTRIB_GENERIC0 + index;
}
else {
/* pre-defined vertex attrib */
- GLuint swizzle;
- GLint index = _slang_input_index(varName, GL_VERTEX_PROGRAM_ARB,
- &swizzle);
+ index = _slang_input_index(varName, GL_VERTEX_PROGRAM_ARB, &swizzle);
assert(index >= 0);
- store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
}
+ store = _slang_new_ir_storage_swz(PROGRAM_INPUT, index, size, swizzle);
if (dbg) printf("ATTRIB ");
}
else if (var->type.qualifier == SLANG_QUAL_FIXEDINPUT) {
slang_ir_node *n;
/* IR node to declare the variable */
- n = _slang_gen_var_decl(A, var);
-
- /* IR code for the var's initializer, if present */
- if (var->initializer) {
- slang_ir_node *lhs, *rhs, *init;
-
- /* Generate IR_COPY instruction to initialize the variable */
- lhs = new_node0(IR_VAR);
- lhs->Var = var;
- lhs->Store = n->Store;
-
- /* constant folding, etc */
- _slang_simplify(var->initializer, &A->space, A->atoms);
-
- rhs = _slang_gen_operation(A, var->initializer);
- assert(rhs);
- init = new_node2(IR_COPY, lhs, rhs);
- n = new_seq(n, init);
- }
+ n = _slang_gen_var_decl(A, var, var->initializer);
+ /* emit GPU instructions */
success = _slang_emit_code(n, A->vartable, A->program, GL_FALSE, A->log);
_slang_free_ir_tree(n);
store ? store->Index : -2);
if (store)
- var->aux = store; /* save var's storage info */
+ var->store = store; /* save var's storage info */
var->declared = GL_TRUE;