/*
* Mesa 3-D graphics library
- * Version: 6.5
+ * Version: 6.5.2
*
* Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
*
#include "slang_assemble.h"
#include "slang_compile.h"
#include "slang_storage.h"
+#include "slang_error.h"
+
+#include "slang_print.h"
+/*#include "assemble2.c"*/
/* slang_assembly */
{
slang_assembly *assem;
+#if 0
+ printf("Gen %s %f %d %d\n", slang_asm_string(type), literal, label, size);
+#endif
if (!push_new(file))
return GL_FALSE;
assem = &file->code[file->count - 1];
/* utility functions */
static GLboolean
-sizeof_variable(slang_assemble_ctx * A, slang_type_specifier * spec,
+sizeof_variable(const slang_assemble_ctx * A, slang_type_specifier * spec,
slang_type_qualifier qual, GLuint array_len, GLuint * size)
{
slang_storage_aggregate agg;
/* calculate the size of the variable's aggregate */
if (!slang_storage_aggregate_construct(&agg))
return GL_FALSE;
- if (!_slang_aggregate_variable
- (&agg, spec, array_len, A->space.funcs, A->space.structs,
- A->space.vars, A->mach, A->file, A->atoms)) {
+ if (!_slang_aggregate_variable(&agg, spec, array_len, A->space.funcs,
+ A->space.structs, A->space.vars, A->mach,
+ A->file, A->atoms)) {
slang_storage_aggregate_destruct(&agg);
return GL_FALSE;
}
/* _slang_locate_function() */
+/**
+ * Locate a function by comparing actual arguments against formal parameters.
+ */
slang_function *
_slang_locate_function(const slang_function_scope * funcs, slang_atom a_name,
- const slang_operation * params, GLuint num_params,
+ const slang_operation * args, GLuint num_args,
const slang_assembly_name_space * space,
slang_atom_pool * atoms)
{
GLuint i;
for (i = 0; i < funcs->num_functions; i++) {
- GLuint j;
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 != num_params)
+ if (f->param_count - haveRetValue != num_args)
continue;
- for (j = 0; j < num_params; j++) {
+
+ /* compare parameter / argument types */
+ for (j = 0; j < num_args; j++) {
slang_assembly_typeinfo ti;
if (!slang_assembly_typeinfo_construct(&ti))
return NULL;
- if (!_slang_typeof_operation_(¶ms[j], space, &ti, atoms)) {
+ if (!_slang_typeof_operation_(&args[j], space, &ti, atoms)) {
slang_assembly_typeinfo_destruct(&ti);
return NULL;
}
- if (!slang_type_specifier_equal
- (&ti.spec, &f->parameters->variables[j].type.specifier)) {
+ if (!slang_type_specifier_equal(&ti.spec,
+ &f->parameters->variables[j/* + haveRetValue*/].type.specifier)) {
slang_assembly_typeinfo_destruct(&ti);
break;
}
/* "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))
+ (f->parameters->variables[j/* + haveRetValue*/].type.qualifier == slang_qual_out ||
+ f->parameters->variables[j/* + haveRetValue*/].type.qualifier == slang_qual_inout))
break;
}
- if (j == num_params)
+ if (j == num_args)
return f;
}
if (funcs->outer_scope != NULL)
- return _slang_locate_function(funcs->outer_scope, a_name, params,
- num_params, space, atoms);
+ return _slang_locate_function(funcs->outer_scope, a_name, args,
+ num_args, space, atoms);
return NULL;
}
-/* _slang_assemble_function() */
+
+/**
+ * Generate assembly for a parsed function.
+ */
GLboolean
_slang_assemble_function(slang_assemble_ctx * A, slang_function * fun)
{
GLuint param_size, local_size;
GLuint skip, cleanup;
+ const GLuint haveRetValue = _slang_function_has_return_value(fun);
fun->address = A->file->count;
* the instruction to fixup table
*/
if (!slang_fixup_save(&fun->fixups, fun->address))
- return GL_FALSE;
+ RETURN_NIL();
if (!PUSH(A->file, slang_asm_jump))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
return GL_TRUE;
}
else {
/* calculate return value size */
param_size = 0;
- if (fun->header.type.specifier.type != slang_spec_void)
- if (!sizeof_variable
- (A, &fun->header.type.specifier, slang_qual_none, 0, ¶m_size))
- return GL_FALSE;
+ if (fun->header.type.specifier.type != slang_spec_void) {
+ if (!sizeof_variable(A, &fun->header.type.specifier,
+ slang_qual_none, 0, ¶m_size))
+ RETURN_NIL();
+ }
A->local.ret_size = param_size;
/* calculate formal parameter list size */
- if (!sizeof_variables
- (A, fun->parameters, 0, fun->param_count, ¶m_size))
- return GL_FALSE;
+ if (!sizeof_variables(A, fun->parameters,
+ 0,
+ fun->param_count - haveRetValue, ¶m_size))
+ RETURN_NIL();
/* calculate local variables size - take into account the four-byte
* return address and temporaries for various tasks (4 for addr and
A->local.addr_tmp = param_size + 4;
A->local.swizzle_tmp = param_size + 4 + 4;
local_size = param_size + 4 + 4 + 16;
- if (!sizeof_variables
- (A, fun->parameters, fun->param_count, fun->parameters->num_variables,
- &local_size))
- return GL_FALSE;
+ if (!sizeof_variables(A, fun->parameters, fun->param_count,
+ fun->parameters->num_variables, &local_size)) {
+ RETURN_OUT_OF_MEMORY();
+ }
if (!collect_locals(A, fun->body, &local_size))
- return GL_FALSE;
+ RETURN_NIL();
/* allocate local variable storage */
if (!PLAB(A->file, slang_asm_local_alloc, local_size - param_size - 4))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
/* mark a new frame for function variable storage */
if (!PLAB(A->file, slang_asm_enter, local_size))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
/* jump directly to the actual code */
skip = A->file->count;
if (!push_new(A->file))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
A->file->code[skip].type = slang_asm_jump;
/* all "return" statements will be directed here */
A->flow.function_end = A->file->count;
cleanup = A->file->count;
if (!push_new(A->file))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
A->file->code[cleanup].type = slang_asm_jump;
/* execute the function body */
A->file->code[skip].param[0] = A->file->count;
- if (!_slang_assemble_operation
- (A, fun->body, /*slang_ref_freelance */ slang_ref_forbid))
- return GL_FALSE;
+ if (!_slang_assemble_operation(A, fun->body,
+ /*slang_ref_freelance */ slang_ref_forbid))
+ RETURN_NIL();
/* this is the end of the function - restore the old function frame */
A->file->code[cleanup].param[0] = A->file->count;
if (!PUSH(A->file, slang_asm_leave))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
/* free local variable storage */
if (!PLAB(A->file, slang_asm_local_free, local_size - param_size - 4))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
/* return from the function */
if (!PUSH(A->file, slang_asm_return))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
return GL_TRUE;
}
for (j = arr->length; j > 0; j--) {
if (arr->type == slang_stor_aggregate) {
- if (!dereference_aggregate
- (A, arr->aggregate, size, swz, is_swizzled))
+ if (!dereference_aggregate(A, arr->aggregate, size,
+ swz, is_swizzled))
return GL_FALSE;
}
else {
if (is_swizzled && arr->type == slang_stor_vec4) {
- if (!dereference_basic
- (A, slang_stor_float, size, swz, is_swizzled))
+ if (!dereference_basic(A, slang_stor_float, size, swz, is_swizzled))
return GL_FALSE;
- if (!dereference_basic
- (A, slang_stor_float, size, swz, is_swizzled))
+ if (!dereference_basic(A, slang_stor_float, size, swz, is_swizzled))
return GL_FALSE;
- if (!dereference_basic
- (A, slang_stor_float, size, swz, is_swizzled))
+ if (!dereference_basic(A, slang_stor_float, size, swz, is_swizzled))
return GL_FALSE;
- if (!dereference_basic
- (A, slang_stor_float, size, swz, is_swizzled))
+ if (!dereference_basic(A, slang_stor_float, size, swz, is_swizzled))
return GL_FALSE;
}
else {
/* construct aggregate from the type info */
if (!slang_storage_aggregate_construct(&agg))
goto end1;
- if (!_slang_aggregate_variable
- (&agg, &ti.spec, ti.array_len, A->space.funcs, A->space.structs,
- A->space.vars, A->mach, A->file, A->atoms))
+ if (!_slang_aggregate_variable(&agg, &ti.spec, ti.array_len, A->space.funcs,
+ A->space.structs, A->space.vars, A->mach,
+ A->file, A->atoms))
goto end;
/* dereference the resulting aggregate */
return result;
}
+
+/**
+ * Assemble a function call, given a pointer to the actual function to call.
+ */
GLboolean
_slang_assemble_function_call(slang_assemble_ctx * A, slang_function * fun,
slang_operation * params, GLuint param_count,
GLuint i;
slang_swizzle p_swz[64];
slang_ref_type p_ref[64];
+ /*
+ const GLuint haveRetValue = _slang_function_has_return_value(fun);
+ */
/* TODO: fix this, allocate dynamically */
if (param_count > 64)
if (fun->header.type.specifier.type != slang_spec_void) {
GLuint ret_size = 0;
- if (!sizeof_variable
- (A, &fun->header.type.specifier, slang_qual_none, 0, &ret_size))
+ if (!sizeof_variable(A, &fun->header.type.specifier,
+ slang_qual_none, 0, &ret_size))
return GL_FALSE;
if (!PLAB(A->file, slang_asm_local_alloc, ret_size))
return GL_FALSE;
/* push the actual parameters on the stack */
for (i = 0; i < param_count; i++) {
- if (fun->parameters->variables[i].type.qualifier == slang_qual_inout ||
- fun->parameters->variables[i].type.qualifier == slang_qual_out) {
+ if (fun->parameters->variables[i /*+ haveRetValue*/].type.qualifier == slang_qual_inout ||
+ fun->parameters->variables[i /*+ haveRetValue*/].type.qualifier == slang_qual_out) {
if (!PLAB2(A->file, slang_asm_local_addr, A->local.addr_tmp, 4))
return GL_FALSE;
/* TODO: optimize the "out" parameter case */
}
/* call the function */
+#if 0
+ printf("CALL FUNCTION %s\n", (char*) fun->header.a_name);
+ slang_print_var_scope(fun->parameters, fun->param_count);
+#endif
if (!PLAB(A->file, slang_asm_call, fun->address))
return GL_FALSE;
A->swz = p_swz[j];
A->ref = p_ref[j];
- if (fun->parameters->variables[j].type.qualifier == slang_qual_inout ||
- fun->parameters->variables[j].type.qualifier == slang_qual_out) {
+ if (fun->parameters->variables[j /*+ haveRetValue*/].type.qualifier == slang_qual_inout ||
+ fun->parameters->variables[j/* + haveRetValue*/].type.qualifier == slang_qual_out) {
/* for output parameter copy the contents of the formal parameter
* back to the original actual parameter
*/
return GL_TRUE;
}
+
+/**
+ * Assemble a function call, given the name of the function to call and a
+ * list of parameters.
+ */
GLboolean
_slang_assemble_function_call_name(slang_assemble_ctx * A, const char *name,
slang_operation * params,
fun =
_slang_locate_function(A->space.funcs, atom, params, param_count,
&A->space, A->atoms);
+ {
+ char *s = (char *) name;
+ if (strcmp(name, "vec4") == 0)
+ printf("LLLLLLLLLLLLLLL locate %s %p\n", s, (void*) fun);
+ }
+
if (fun == NULL)
return GL_FALSE;
return _slang_assemble_function_call(A, fun, params, param_count,
} inst[] = {
/* core */
{"float_add", slang_asm_float_add, slang_asm_float_copy},
+ {"float_subtract", slang_asm_float_subtract, slang_asm_float_copy},
{"float_multiply", slang_asm_float_multiply, slang_asm_float_copy},
{"float_divide", slang_asm_float_divide, slang_asm_float_copy},
{"float_negate", slang_asm_float_negate, slang_asm_float_copy},
+ {"float_min", slang_asm_float_min, slang_asm_float_copy},
+ {"float_max", slang_asm_float_max, slang_asm_float_copy},
{"float_less", slang_asm_float_less, slang_asm_bool_copy},
{"float_equal", slang_asm_float_equal_exp, slang_asm_bool_copy},
{"float_to_int", slang_asm_float_to_int, slang_asm_int_copy},
{"float_sine", slang_asm_float_sine, slang_asm_float_copy},
+ {"float_cosine", slang_asm_float_cosine, slang_asm_float_copy},
{"float_arcsine", slang_asm_float_arcsine, slang_asm_float_copy},
{"float_arctan", slang_asm_float_arctan, slang_asm_float_copy},
{"float_power", slang_asm_float_power, slang_asm_float_copy},
+ {"float_exp", slang_asm_float_exp, slang_asm_float_copy},
+ {"float_exp2", slang_asm_float_exp2, slang_asm_float_copy},
+ {"float_rsq", slang_asm_float_rsq, slang_asm_float_copy},
+ {"float_rcp", slang_asm_float_rcp, slang_asm_float_copy},
{"float_log2", slang_asm_float_log2, slang_asm_float_copy},
- {"float_floor", slang_asm_float_floor, slang_asm_float_copy},
{"float_ceil", slang_asm_float_ceil, slang_asm_float_copy},
{"float_noise1", slang_asm_float_noise1, slang_asm_float_copy},
{"float_noise2", slang_asm_float_noise2, slang_asm_float_copy},
{"bool_print", slang_asm_bool_deref, slang_asm_bool_print},
/* vec4 */
{"float_to_vec4", slang_asm_float_to_vec4, slang_asm_none},
- {"vec4_add", slang_asm_vec4_add, slang_asm_none},
- {"vec4_subtract", slang_asm_vec4_subtract, slang_asm_none},
- {"vec4_multiply", slang_asm_vec4_multiply, slang_asm_none},
+ {"vec4_add", slang_asm_vec4_add, slang_asm_float_copy},
+ {"vec4_subtract", slang_asm_vec4_subtract, slang_asm_float_copy},
+ {"vec4_multiply", slang_asm_vec4_multiply, slang_asm_float_copy},
+ {"vec4_min", slang_asm_vec4_min, slang_asm_float_copy},
+ {"vec4_max", slang_asm_vec4_max, slang_asm_float_copy},
+ {"vec4_seq", slang_asm_vec4_seq, slang_asm_float_copy},
+ {"vec4_sne", slang_asm_vec4_sne, slang_asm_float_copy},
+ {"vec4_sge", slang_asm_vec4_sge, slang_asm_float_copy},
+ {"vec4_sgt", slang_asm_vec4_sgt, slang_asm_float_copy},
+ {"vec4_floor", slang_asm_vec4_floor, slang_asm_float_copy},
+ {"vec4_frac", slang_asm_vec4_frac, slang_asm_float_copy},
+ {"vec4_abs", slang_asm_vec4_abs, slang_asm_float_copy},
+
{"vec4_divide", slang_asm_vec4_divide, slang_asm_none},
{"vec4_negate", slang_asm_vec4_negate, slang_asm_none},
- {"vec4_dot", slang_asm_vec4_dot, slang_asm_none},
+ {"vec4_dot", slang_asm_vec4_dot, slang_asm_float_copy},
+ {"vec3_dot", slang_asm_vec3_dot, slang_asm_float_copy},
+ {"vec3_cross", slang_asm_vec3_cross, slang_asm_float_copy},
{NULL, slang_asm_none, slang_asm_none}
};
else {
#if defined(USE_X86_ASM) || defined(SLANG_X86)
if (arr->type == slang_stor_vec4) {
- if (!PLAB2
- (A->file, slang_asm_vec4_equal_int, size + *index, *index))
+ if (!PLAB2(A->file, slang_asm_vec4_equal_int,
+ size + *index, *index))
return GL_FALSE;
}
else
#endif
- if (!PLAB2
- (A->file, slang_asm_float_equal_int, size + *index,
- *index))
+ if (!PLAB2(A->file, slang_asm_float_equal_int,
+ size + *index, *index))
return GL_FALSE;
*index += _slang_sizeof_type(arr->type);
/* get type of operation */
if (!slang_assembly_typeinfo_construct(&ti))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
if (!_slang_typeof_operation(A, op, &ti))
goto end1;
/* convert it to an aggregate */
if (!slang_storage_aggregate_construct(&agg))
goto end1;
- if (!_slang_aggregate_variable
- (&agg, &ti.spec, 0, A->space.funcs, A->space.structs, A->space.vars,
- A->mach, A->file, A->atoms))
+ if (!_slang_aggregate_variable(&agg, &ti.spec, 0, A->space.funcs,
+ A->space.structs, A->space.vars,
+ A->mach, A->file, A->atoms))
goto end;
- /* compute the size of the agregate - there are two such aggregates on the stack */
+ /* compute the size of the agregate - there are two such aggregates
+ * on the stack
+ */
size = _slang_sizeof_aggregate(&agg);
/* jump to the actual data-comparison code */
A->file->code[skip_jump].param[0] = A->file->count;
- /* compare the data on stack, it will eventually jump either to true or false label */
+ /* compare the data on stack, it will eventually jump either to
+ * true or false label
+ */
index = 0;
- if (!equality_aggregate
- (A, &agg, &index, size, equal ? false_label : true_label))
+ if (!equality_aggregate(A, &agg, &index, size,
+ equal ? false_label : true_label))
goto end;
if (!PLAB(A->file, slang_asm_jump, equal ? true_label : false_label))
goto end;
/* get type info of the master expression (matrix, vector or an array */
if (!_slang_typeof_operation(A, &op->children[0], tia))
return GL_FALSE;
- if (!sizeof_variable
- (A, &tia->spec, slang_qual_none, tia->array_len, &asize))
+ if (!sizeof_variable(A, &tia->spec, slang_qual_none,
+ tia->array_len, &asize))
return GL_FALSE;
/* get type info of the result (matrix column, vector row or array element) */
/* move the selected element to the beginning of the master expression */
for (i = 0; i < esize; i += 4)
- if (!PLAB2
- (A->file, slang_asm_float_move, asize - esize + i + 4, i + 4))
+ if (!PLAB2(A->file, slang_asm_float_move,
+ asize - esize + i + 4, i + 4))
return GL_FALSE;
if (!PLAB(A->file, slang_asm_local_free, 4))
return GL_FALSE;
{
/* get type info of the result (field or swizzle) */
if (!_slang_typeof_operation(A, op, tia))
- return GL_FALSE;
+ RETURN_NIL();
/* get type info of the master expression being accessed (struct or vector) */
if (!_slang_typeof_operation(A, &op->children[0], tib))
- return GL_FALSE;
+ RETURN_NIL();
/* if swizzling a vector in-place, the swizzle temporary is needed */
if (ref == slang_ref_forbid && tia->is_swizzled)
if (!PLAB2(A->file, slang_asm_local_addr, A->local.swizzle_tmp, 16))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
/* assemble the master expression */
if (!_slang_assemble_operation(A, &op->children[0], ref))
- return GL_FALSE;
+ RETURN_NIL();
/* assemble the field expression */
if (tia->is_swizzled) {
* the selected component
*/
if (!PLAB(file, slang_asm_addr_push, tia->swz.swizzle[0] * 4))
- return 0;
+ RETURN_OUT_OF_MEMORY();
if (!PUSH(file, slang_asm_addr_add))
- return 0;
+ RETURN_OUT_OF_MEMORY();
}
else
#endif
}
else {
/* swizzle the vector in-place using the swizzle temporary */
- if (!_slang_assemble_constructor_from_swizzle
- (A, &tia->swz, &tia->spec, &tib->spec))
- return GL_FALSE;
+ if (!_slang_assemble_constructor_from_swizzle(A, &tia->swz,
+ &tia->spec, &tib->spec))
+ RETURN_NIL();
}
}
else {
field = &tib->spec._struct->fields->variables[i];
if (!slang_storage_aggregate_construct(&agg))
- return GL_FALSE;
- if (!_slang_aggregate_variable
- (&agg, &field->type.specifier, field->array_len, A->space.funcs,
- A->space.structs, A->space.vars, A->mach, A->file, A->atoms)) {
+ RETURN_NIL();
+ if (!_slang_aggregate_variable(&agg, &field->type.specifier,
+ field->array_len, A->space.funcs,
+ A->space.structs, A->space.vars,
+ A->mach, A->file, A->atoms)) {
slang_storage_aggregate_destruct(&agg);
- return GL_FALSE;
+ RETURN_NIL();
}
size = _slang_sizeof_aggregate(&agg);
slang_storage_aggregate_destruct(&agg);
if (shift) {
if (!PLAB(A->file, slang_asm_addr_push, field_offset))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
if (!PUSH(A->file, slang_asm_addr_add))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
}
}
else {
* Do it in reverse order to avoid overwriting itself.
*/
if (!PLAB(A->file, slang_asm_addr_push, field_offset))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
for (i = field_size; i > 0; i -= 4)
- if (!PLAB2
- (A->file, slang_asm_float_move,
- struct_size - field_size + i, i))
- return GL_FALSE;
+ if (!PLAB2(A->file, slang_asm_float_move,
+ struct_size - field_size + i, i))
+ RETURN_OUT_OF_MEMORY();
free_b += 4;
}
if (free_b) {
if (!PLAB(A->file, slang_asm_local_free, free_b))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
}
}
}
GLuint i;
for (i = 0; i < op->num_children; i++) {
- if (!_slang_assemble_operation
- (A, &op->children[i],
- slang_ref_forbid /*slang_ref_freelance */ ))
- return GL_FALSE;
+ if (!_slang_assemble_operation(A, &op->children[i],
+ slang_ref_forbid /*slang_ref_freelance */ ))
+ RETURN_NIL();
if (!_slang_cleanup_stack(A, &op->children[i]))
- return GL_FALSE;
+ RETURN_NIL();
}
}
break;
/* Construct assignment expression placeholder. */
if (!slang_operation_construct(&assign))
- return GL_FALSE;
+ RETURN_NIL();
assign.type = slang_oper_assign;
- assign.children =
- (slang_operation *) slang_alloc_malloc(2 *
- sizeof(slang_operation));
+ assign.children = slang_operation_new(2);
if (assign.children == NULL) {
slang_operation_destruct(&assign);
- return GL_FALSE;
+ RETURN_NIL();
}
for (assign.num_children = 0; assign.num_children < 2;
assign.num_children++)
- if (!slang_operation_construct
- (&assign.children[assign.num_children])) {
+ if (!slang_operation_construct(&assign.children
+ [assign.num_children])) {
slang_operation_destruct(&assign);
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
}
result = GL_TRUE;
}
slang_operation_destruct(&assign);
if (!result)
- return GL_FALSE;
+ RETURN_NIL();
}
break;
case slang_oper_asm:
{
GLuint i;
if (!_slang_assemble_operation(A, &op->children[0], slang_ref_force))
- return GL_FALSE;
+ RETURN_NIL();
for (i = 1; i < op->num_children; i++)
- if (!_slang_assemble_operation
- (A, &op->children[i], slang_ref_forbid))
- return GL_FALSE;
+ if (!_slang_assemble_operation(A, &op->children[i],
+ slang_ref_forbid))
+ RETURN_NIL();
if (!call_asm_instruction(A, op->a_id))
- return GL_FALSE;
+ RETURN_ERROR2("Unknown __asm call", (char*) op->a_id, 0);
}
break;
case slang_oper_break:
if (!PLAB(A->file, slang_asm_jump, A->flow.loop_end))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
break;
case slang_oper_continue:
if (!PLAB(A->file, slang_asm_jump, A->flow.loop_start))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
break;
case slang_oper_discard:
if (!PUSH(A->file, slang_asm_discard))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
if (!PUSH(A->file, slang_asm_exit))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
break;
case slang_oper_return:
if (A->local.ret_size != 0) {
/* push the result's address */
if (!PLAB2(A->file, slang_asm_local_addr, 0, A->local.ret_size))
- return GL_FALSE;
- if (!_slang_assemble_operation
- (A, &op->children[0], slang_ref_forbid))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
+ if (!_slang_assemble_operation(A, &op->children[0], slang_ref_forbid))
+ RETURN_NIL();
A->swz.num_components = 0;
/* assign the operation to the function result (it was reserved on the stack) */
if (!_slang_assemble_assignment(A, op->children))
- return GL_FALSE;
+ RETURN_NIL();
if (!PLAB(A->file, slang_asm_local_free, 4))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
}
if (!PLAB(A->file, slang_asm_jump, A->flow.function_end))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
break;
case slang_oper_expression:
if (ref == slang_ref_force)
- return GL_FALSE;
+ RETURN_NIL();
if (!_slang_assemble_operation(A, &op->children[0], ref))
- return GL_FALSE;
+ RETURN_NIL();
break;
case slang_oper_if:
if (!_slang_assemble_if(A, op))
- return GL_FALSE;
+ RETURN_NIL();
break;
case slang_oper_while:
if (!_slang_assemble_while(A, op))
- return GL_FALSE;
+ RETURN_NIL();
break;
case slang_oper_do:
if (!_slang_assemble_do(A, op))
- return GL_FALSE;
+ RETURN_NIL();
break;
case slang_oper_for:
if (!_slang_assemble_for(A, op))
- return GL_FALSE;
+ RETURN_NIL();
break;
case slang_oper_void:
break;
case slang_oper_literal_bool:
if (ref == slang_ref_force)
- return GL_FALSE;
- if (!PLIT(A->file, slang_asm_bool_push, op->literal))
- return GL_FALSE;
+ RETURN_NIL();
+ if (!PLIT(A->file, slang_asm_bool_push, op->literal[0]))
+ RETURN_OUT_OF_MEMORY();
A->ref = slang_ref_forbid;
break;
case slang_oper_literal_int:
if (ref == slang_ref_force)
- return GL_FALSE;
- if (!PLIT(A->file, slang_asm_int_push, op->literal))
- return GL_FALSE;
+ RETURN_NIL();
+ if (!PLIT(A->file, slang_asm_int_push, op->literal[0]))
+ RETURN_OUT_OF_MEMORY();
A->ref = slang_ref_forbid;
break;
case slang_oper_literal_float:
if (ref == slang_ref_force)
- return GL_FALSE;
- if (!PLIT(A->file, slang_asm_float_push, op->literal))
- return GL_FALSE;
+ RETURN_NIL();
+ if (!PLIT(A->file, slang_asm_float_push, op->literal[0]))
+ RETURN_OUT_OF_MEMORY();
A->ref = slang_ref_forbid;
break;
case slang_oper_identifier:
/* find the variable and calculate its size */
var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE);
if (var == NULL)
- return GL_FALSE;
+ RETURN_ERROR2("undefined variable", (char *) op->a_id, 0);
size = 0;
- if (!sizeof_variable
- (A, &var->type.specifier, slang_qual_none, var->array_len,
- &size))
- return GL_FALSE;
+ if (!sizeof_variable(A, &var->type.specifier, slang_qual_none,
+ var->array_len, &size))
+ RETURN_OUT_OF_MEMORY();
/* prepare stack for dereferencing */
if (ref == slang_ref_forbid)
if (!PLAB2(A->file, slang_asm_local_addr, A->local.addr_tmp, 4))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
/* push the variable's address */
if (var->global) {
if (!PLAB(A->file, slang_asm_global_addr, var->address))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
}
else {
if (!PLAB2(A->file, slang_asm_local_addr, var->address, size))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
}
/* perform the dereference */
if (ref == slang_ref_forbid) {
if (!PUSH(A->file, slang_asm_addr_copy))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
if (!PLAB(A->file, slang_asm_local_free, 4))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
if (!_slang_dereference(A, op))
- return GL_FALSE;
+ RETURN_NIL();
}
}
break;
case slang_oper_sequence:
if (ref == slang_ref_force)
- return GL_FALSE;
+ RETURN_NIL();
if (!_slang_assemble_operation(A, &op->children[0],
slang_ref_forbid /*slang_ref_freelance */ ))
- return GL_FALSE;
+ RETURN_NIL();
if (!_slang_cleanup_stack(A, &op->children[0]))
- return GL_FALSE;
+ RETURN_NIL();
if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
case slang_oper_assign:
if (!_slang_assemble_assign(A, op, "=", ref))
- return GL_FALSE;
+ RETURN_NIL();
break;
case slang_oper_addassign:
if (!_slang_assemble_assign(A, op, "+=", ref))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = ref;
break;
case slang_oper_subassign:
if (!_slang_assemble_assign(A, op, "-=", ref))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = ref;
break;
case slang_oper_mulassign:
if (!_slang_assemble_assign(A, op, "*=", ref))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = ref;
break;
/*case slang_oper_modassign: */
/*case slang_oper_andassign: */
case slang_oper_divassign:
if (!_slang_assemble_assign(A, op, "/=", ref))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = ref;
break;
case slang_oper_select:
if (!_slang_assemble_select(A, op))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
case slang_oper_logicalor:
if (!_slang_assemble_logicalor(A, op))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
case slang_oper_logicaland:
if (!_slang_assemble_logicaland(A, op))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
case slang_oper_logicalxor:
if (!_slang_assemble_function_call_name(A, "^^", op->children, 2, GL_FALSE))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
/*case slang_oper_bitor: */
/*case slang_oper_bitand: */
case slang_oper_less:
if (!_slang_assemble_function_call_name(A, "<", op->children, 2, GL_FALSE))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
case slang_oper_greater:
if (!_slang_assemble_function_call_name(A, ">", op->children, 2, GL_FALSE))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
case slang_oper_lessequal:
if (!_slang_assemble_function_call_name(A, "<=", op->children, 2, GL_FALSE))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
case slang_oper_greaterequal:
if (!_slang_assemble_function_call_name(A, ">=", op->children, 2, GL_FALSE))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
/*case slang_oper_lshift: */
/*case slang_oper_rshift: */
case slang_oper_add:
if (!_slang_assemble_function_call_name(A, "+", op->children, 2, GL_FALSE))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
case slang_oper_subtract:
if (!_slang_assemble_function_call_name(A, "-", op->children, 2, GL_FALSE))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
case slang_oper_multiply:
if (!_slang_assemble_function_call_name(A, "*", op->children, 2, GL_FALSE))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
/*case slang_oper_modulus: */
case slang_oper_divide:
if (!_slang_assemble_function_call_name(A, "/", op->children, 2, GL_FALSE))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
case slang_oper_equal:
if (!_slang_assemble_operation(A, &op->children[0], slang_ref_forbid))
- return GL_FALSE;
+ RETURN_NIL();
if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid))
- return GL_FALSE;
+ RETURN_NIL();
if (!equality(A, op->children, GL_TRUE))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
case slang_oper_notequal:
if (!_slang_assemble_operation(A, &op->children[0], slang_ref_forbid))
- return GL_FALSE;
+ RETURN_NIL();
if (!_slang_assemble_operation(A, &op->children[1], slang_ref_forbid))
- return GL_FALSE;
+ RETURN_NIL();
if (!equality(A, op->children, GL_FALSE))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
case slang_oper_preincrement:
if (!_slang_assemble_assign(A, op, "++", ref))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = ref;
break;
case slang_oper_predecrement:
if (!_slang_assemble_assign(A, op, "--", ref))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = ref;
break;
case slang_oper_plus:
if (!_slang_dereference(A, op))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
case slang_oper_minus:
- if (!_slang_assemble_function_call_name
- (A, "-", op->children, 1, GL_FALSE))
- return GL_FALSE;
+ if (!_slang_assemble_function_call_name(A, "-", op->children, 1, GL_FALSE))
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
/*case slang_oper_complement: */
case slang_oper_not:
- if (!_slang_assemble_function_call_name
- (A, "!", op->children, 1, GL_FALSE))
- return GL_FALSE;
+ if (!_slang_assemble_function_call_name(A, "!", op->children, 1, GL_FALSE))
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
case slang_oper_subscript:
slang_assembly_typeinfo ti_arr, ti_elem;
if (!slang_assembly_typeinfo_construct(&ti_arr))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
if (!slang_assembly_typeinfo_construct(&ti_elem)) {
slang_assembly_typeinfo_destruct(&ti_arr);
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
}
if (!handle_subscript(A, &ti_elem, &ti_arr, op, ref)) {
slang_assembly_typeinfo_destruct(&ti_arr);
slang_assembly_typeinfo_destruct(&ti_elem);
- return GL_FALSE;
+ RETURN_NIL();
}
slang_assembly_typeinfo_destruct(&ti_arr);
slang_assembly_typeinfo_destruct(&ti_elem);
break;
case slang_oper_call:
{
- slang_function *fun;
-
- fun =
- _slang_locate_function(A->space.funcs, op->a_id, op->children,
- op->num_children, &A->space, A->atoms);
+ slang_function *fun
+ = _slang_locate_function(A->space.funcs, op->a_id, op->children,
+ op->num_children, &A->space, A->atoms);
if (fun == NULL) {
if (!_slang_assemble_constructor(A, op))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
}
else {
- if (!_slang_assemble_function_call
- (A, fun, op->children, op->num_children, GL_FALSE))
- return GL_FALSE;
+ if (!_slang_assemble_function_call(A, fun, op->children,
+ op->num_children, GL_FALSE))
+ RETURN_NIL();
}
A->ref = slang_ref_forbid;
}
slang_assembly_typeinfo ti_after, ti_before;
if (!slang_assembly_typeinfo_construct(&ti_after))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
if (!slang_assembly_typeinfo_construct(&ti_before)) {
slang_assembly_typeinfo_destruct(&ti_after);
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
}
if (!handle_field(A, &ti_after, &ti_before, op, ref)) {
slang_assembly_typeinfo_destruct(&ti_after);
slang_assembly_typeinfo_destruct(&ti_before);
- return GL_FALSE;
+ RETURN_NIL();
}
slang_assembly_typeinfo_destruct(&ti_after);
slang_assembly_typeinfo_destruct(&ti_before);
break;
case slang_oper_postincrement:
if (!assemble_function_call_name_dummyint(A, "++", op->children))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
case slang_oper_postdecrement:
if (!assemble_function_call_name_dummyint(A, "--", op->children))
- return GL_FALSE;
+ RETURN_NIL();
A->ref = slang_ref_forbid;
break;
default:
- return GL_FALSE;
+ RETURN_NIL();
}
return GL_TRUE;
#ifndef SLANG_ASSEMBLE_H
#define SLANG_ASSEMBLE_H
+#include "imports.h"
+#include "mtypes.h"
#include "slang_utility.h"
#if defined __cplusplus
slang_asm_float_push,
slang_asm_float_deref,
slang_asm_float_add, /* a = pop(); b = pop(); push(a + b); */
+ slang_asm_float_subtract,
slang_asm_float_multiply,
slang_asm_float_divide,
slang_asm_float_negate, /* push(-pop()) */
slang_asm_float_equal_int,
slang_asm_float_to_int, /* push(floatToInt(pop())) */
slang_asm_float_sine, /* push(sin(pop()) */
+ slang_asm_float_cosine,
slang_asm_float_arcsine,
slang_asm_float_arctan,
slang_asm_float_power, /* push(pow(pop(), pop())) */
+ slang_asm_float_exp,
+ slang_asm_float_exp2,
+ slang_asm_float_rsq,
+ slang_asm_float_rcp,
slang_asm_float_log2,
- slang_asm_float_floor,
+ slang_asm_float_min,
+ slang_asm_float_max,
slang_asm_float_ceil,
slang_asm_float_noise1, /* push(noise1(pop()) */
slang_asm_float_noise2, /* push(noise2(pop(), pop())) */
slang_asm_vec4_multiply,
slang_asm_vec4_divide,
slang_asm_vec4_negate,
+ slang_asm_vec4_min,
+ slang_asm_vec4_max,
+ slang_asm_vec4_seq,
+ slang_asm_vec4_sne,
+ slang_asm_vec4_sge,
+ slang_asm_vec4_sgt,
slang_asm_vec4_dot,
+ slang_asm_vec3_dot,
+ slang_asm_vec3_cross,
+ slang_asm_vec4_floor,
+ slang_asm_vec4_frac,
+ slang_asm_vec4_abs,
+
slang_asm_vec4_copy,
slang_asm_vec4_deref,
slang_asm_vec4_equal_int,
slang_assembly_local_info local;
slang_ref_type ref;
slang_swizzle swz;
+ struct gl_program *program;
} slang_assemble_ctx;
extern struct slang_function_ *
extern GLboolean
_slang_assemble_function(slang_assemble_ctx *, struct slang_function_ *);
-extern GLboolean
-_slang_assemble_function2(slang_assemble_ctx * , struct slang_function_ *);
-
extern GLboolean
_slang_cleanup_stack(slang_assemble_ctx *, struct slang_operation_ *);
#include "imports.h"
#include "slang_assemble.h"
#include "slang_storage.h"
+#include "slang_error.h"
/*
* _slang_assemble_assignment()
*/
dst_addr_loc = size - *index;
- if (!slang_assembly_file_push_label2
- (A->file, ty, dst_addr_loc, dst_offset))
- return GL_FALSE;
+ if (!slang_assembly_file_push_label2(A->file, ty, dst_addr_loc, dst_offset))
+ RETURN_NIL();
+
*index += _slang_sizeof_type(type);
return GL_TRUE;
GLuint index, size;
if (!slang_assembly_typeinfo_construct(&ti))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
if (!_slang_typeof_operation(A, op, &ti))
goto end1;
slang_storage_aggregate_destruct(&agg);
end:
slang_assembly_typeinfo_destruct(&ti);
+ if (!result)
+ RETURN_NIL();
return result;
}
GLuint i;
GLboolean xyzw = GL_FALSE, rgba = GL_FALSE, stpq = GL_FALSE;
+ /* init to default */
+ for (i = 0; i < 4; i++)
+ swz->swizzle[i] = i;
+
/* the swizzle can be at most 4-component long */
swz->num_components = slang_string_length(field);
if (swz->num_components > 4)
if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq))
return GL_FALSE;
+ if (swz->num_components == 1) {
+ /* smear */
+ swz->swizzle[3] =
+ swz->swizzle[2] =
+ swz->swizzle[1] = swz->swizzle[0];
+ }
return GL_TRUE;
}
/* check if there are too few arguments */
if (arg_sums[1] < size) {
/* TODO: info log: too few arguments in constructor list */
+ /* DEBUG */
+ {
+ if (!slang_storage_aggregate_construct(&agg))
+ goto end1;
+ if (!_slang_aggregate_variable(&agg, &ti.spec, 0, A->space.funcs,
+ A->space.structs, A->space.vars,
+ A->mach, A->file, A->atoms))
+ goto end2;
+
+ /* calculate size of the constructor */
+ size = _slang_sizeof_aggregate(&agg);
+ }
goto end;
}
else
garbage_size = 0;
- if (!constructor_aggregate
- (A, &flat, &op->children[i - 1], garbage_size))
+ if (!constructor_aggregate(A, &flat, &op->children[i - 1], garbage_size))
goto end;
}
#include "imports.h"
#include "slang_assemble.h"
#include "slang_compile.h"
+#include "slang_error.h"
-/*
- * slang_type_specifier
- */
GLvoid
slang_type_specifier_ctr(slang_type_specifier * self)
return 1;
}
-/* slang_assembly_typeinfo */
GLboolean
slang_assembly_typeinfo_construct(slang_assembly_typeinfo * ti)
slang_type_specifier_dtr(&ti->spec);
}
-/* _slang_typeof_operation() */
/**
* Determine the return type of a function.
case slang_oper_preincrement:
case slang_oper_predecrement:
if (!_slang_typeof_operation_(op->children, space, ti, atoms))
- return 0;
+ return GL_FALSE;
break;
case slang_oper_literal_bool:
case slang_oper_logicalor:
case slang_oper_identifier:
{
slang_variable *var;
-
var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE);
if (var == NULL)
- return GL_FALSE;
+ RETURN_ERROR2("undefined variable", (char *) op->a_id, 0);
if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier))
- return GL_FALSE;
+ RETURN_OUT_OF_MEMORY();
ti->can_be_referenced = GL_TRUE;
ti->array_len = var->array_len;
}
case slang_oper_sequence:
/* TODO: check [0] and [1] if they match */
if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms))
- return GL_FALSE;
+ RETURN_NIL();
ti->can_be_referenced = GL_FALSE;
ti->is_swizzled = GL_FALSE;
break;
case slang_oper_select:
/* TODO: check [1] and [2] if they match */
if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms))
- return GL_FALSE;
+ RETURN_NIL();
ti->can_be_referenced = GL_FALSE;
ti->is_swizzled = GL_FALSE;
break;
case slang_oper_add:
if (!typeof_existing_function("+", op->children, 2, space,
&ti->spec, atoms))
- return GL_FALSE;
+ RETURN_NIL();
break;
case slang_oper_subtract:
if (!typeof_existing_function("-", op->children, 2, space,
&ti->spec, atoms))
- return GL_FALSE;
+ RETURN_NIL();
break;
case slang_oper_multiply:
if (!typeof_existing_function("*", op->children, 2, space,
&ti->spec, atoms))
- return GL_FALSE;
+ RETURN_NIL();
break;
case slang_oper_divide:
if (!typeof_existing_function("/", op->children, 2, space,
&ti->spec, atoms))
- return GL_FALSE;
+ RETURN_NIL();
break;
/*case slang_oper_modulus: */
case slang_oper_plus:
if (!_slang_typeof_operation_(op->children, space, ti, atoms))
- return GL_FALSE;
+ RETURN_NIL();
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 GL_FALSE;
+ if (!typeof_existing_function("-", op->children, 1, space,
+ &ti->spec, atoms))
+ RETURN_NIL();
break;
/*case slang_oper_complement: */
case slang_oper_subscript:
slang_assembly_typeinfo _ti;
if (!slang_assembly_typeinfo_construct(&_ti))
- return GL_FALSE;
+ RETURN_NIL();
if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) {
slang_assembly_typeinfo_destruct(&_ti);
- return GL_FALSE;
+ RETURN_NIL();
}
ti->can_be_referenced = _ti.can_be_referenced;
if (_ti.spec.type == slang_spec_array) {
if (!slang_type_specifier_copy(&ti->spec, _ti.spec._array)) {
slang_assembly_typeinfo_destruct(&_ti);
- return GL_FALSE;
+ RETURN_NIL();
}
}
else {
if (!_slang_type_is_vector(_ti.spec.type)
&& !_slang_type_is_matrix(_ti.spec.type)) {
slang_assembly_typeinfo_destruct(&_ti);
- return GL_FALSE;
+ RETURN_ERROR("cannot index a non-array type", 0);
}
ti->spec.type = _slang_type_base(_ti.spec.type);
}
if (!_slang_typeof_function(op->a_id, op->children, op->num_children,
space, &ti->spec, &exists, atoms))
- return GL_FALSE;
+ RETURN_NIL();
if (!exists) {
slang_struct *s =
slang_struct_scope_find(space->structs, op->a_id, GL_TRUE);
ti->spec._struct =
(slang_struct *) slang_alloc_malloc(sizeof(slang_struct));
if (ti->spec._struct == NULL)
- return GL_FALSE;
+ RETURN_NIL();
if (!slang_struct_construct(ti->spec._struct)) {
slang_alloc_free(ti->spec._struct);
ti->spec._struct = NULL;
- return GL_FALSE;
+ RETURN_NIL();
}
if (!slang_struct_copy(ti->spec._struct, s))
- return GL_FALSE;
+ RETURN_NIL();
}
else {
const char *name;
name = slang_atom_pool_id(atoms, op->a_id);
type = slang_type_specifier_type_from_string(name);
if (type == slang_spec_void)
- return GL_FALSE;
+ RETURN_ERROR2("function not found", name, 0);
ti->spec.type = type;
}
}
slang_assembly_typeinfo _ti;
if (!slang_assembly_typeinfo_construct(&_ti))
- return GL_FALSE;
+ RETURN_NIL();
if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) {
slang_assembly_typeinfo_destruct(&_ti);
- return GL_FALSE;
+ RETURN_NIL();
}
if (_ti.spec.type == slang_spec_struct) {
slang_variable *field;
- field =
- _slang_locate_variable(_ti.spec._struct->fields, op->a_id,
- GL_FALSE);
+ field = _slang_locate_variable(_ti.spec._struct->fields, op->a_id,
+ GL_FALSE);
if (field == NULL) {
slang_assembly_typeinfo_destruct(&_ti);
- return GL_FALSE;
+ RETURN_NIL();
}
if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) {
slang_assembly_typeinfo_destruct(&_ti);
- return GL_FALSE;
+ RETURN_NIL();
}
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 GL_FALSE;
+ RETURN_ERROR("Can't swizzle scalar expression", 0);
}
+#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 GL_FALSE;
+ RETURN_ERROR("Bad swizzle", 0);
}
ti->is_swizzled = GL_TRUE;
ti->can_be_referenced = _ti.can_be_referenced
case slang_oper_postincrement:
case slang_oper_postdecrement:
if (!_slang_typeof_operation_(op->children, space, ti, atoms))
- return GL_FALSE;
+ RETURN_NIL();
ti->can_be_referenced = GL_FALSE;
ti->is_swizzled = GL_FALSE;
break;
default:
- return GL_FALSE;
+ RETURN_NIL();
}
return GL_TRUE;
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 2005-2007 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.
+ */
+
+/**
+ * \file slang_codegen.c
+ * Mesa GLSL code generator. Convert AST to IR tree.
+ * \author Brian Paul
+ */
+
+#include "imports.h"
+#include "macros.h"
+#include "slang_assemble.h"
+#include "slang_codegen.h"
+#include "slang_compile.h"
+#include "slang_storage.h"
+#include "slang_error.h"
+#include "slang_simplify.h"
+#include "slang_emit.h"
+#include "slang_ir.h"
+#include "mtypes.h"
+#include "program.h"
+#include "slang_print.h"
+
+
+static slang_function *CurFunction = NULL;
+
+
+static slang_ir_node *
+slang_assemble_operation(slang_assemble_ctx * A, slang_operation *oper);
+
+
+
+/**
+ * Allocate storage for given variable, attach it to 'ir'.
+ */
+static GLboolean
+slang_alloc_var_storage(slang_variable *variable, slang_ir_node *ir)
+{
+ slang_ir_storage *store;
+
+ assert(variable);
+
+ /*assert(!variable->aux);*/
+
+ if (variable->aux) {
+ store = (slang_ir_storage *) variable->aux;
+ ir->Store = store;
+ if (store)
+ store->Size = -12;
+ }
+ else {
+ /* alloc storage */
+ store = (slang_ir_storage *) _mesa_calloc(sizeof(*store));
+ store->File = PROGRAM_TEMPORARY;
+ store->Index = -1;
+ store->Size = -10;
+ variable->aux = store;
+ ir->Store = store;
+ }
+ return GL_TRUE;
+}
+
+
+static slang_ir_node *
+new_node(slang_ir_opcode op, slang_ir_node *left, slang_ir_node *right)
+{
+ slang_ir_node *n = (slang_ir_node *) calloc(1, sizeof(slang_ir_node));
+ if (n) {
+ n->Opcode = op;
+ n->Children[0] = left;
+ n->Children[1] = right;
+ n->Swizzle = SWIZZLE_NOOP;
+ n->Writemask = WRITEMASK_XYZW;
+ }
+ return n;
+}
+
+static slang_ir_node *
+new_seq(slang_ir_node *left, slang_ir_node *right)
+{
+ assert(left);
+ assert(right);
+ return new_node(IR_SEQ, left, right);
+}
+
+static slang_ir_node *
+new_label(const char *name)
+{
+ slang_ir_node *n = new_node(IR_LABEL, NULL, NULL);
+ n->Target = _mesa_strdup(name);
+ return n;
+}
+
+static slang_ir_node *
+new_float_literal(float x, float y, float z, float w)
+{
+ slang_ir_node *n = new_node(IR_FLOAT, NULL, NULL);
+ n->Value[0] = x;
+ n->Value[1] = y;
+ n->Value[2] = z;
+ n->Value[3] = w;
+ return n;
+}
+
+static slang_ir_node *
+new_cjump(slang_ir_node *cond, const char *target)
+{
+ slang_ir_node *n = new_node(IR_CJUMP, cond, NULL);
+ n->Target = _mesa_strdup(target);
+ return n;
+}
+
+static slang_ir_node *
+new_jump(const char *target)
+{
+ slang_ir_node *n = new_node(IR_JUMP, NULL, NULL);
+ if (n) {
+ n->Target = _mesa_strdup(target);
+ }
+ return n;
+}
+
+
+/**
+ * New IR_VAR_DECL node - allocate storage for a new variable.
+ */
+static slang_ir_node *
+new_var_decl(slang_assemble_ctx *A, slang_variable *v)
+{
+ slang_ir_node *n = new_node(IR_VAR_DECL, NULL, NULL);
+ if (n) {
+ n->Var = v;
+ v->declared = GL_TRUE;
+ }
+ 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, GLuint swizzle)
+{
+ slang_variable *v = _slang_locate_variable(oper->locals, name, GL_TRUE);
+ slang_ir_node *n = new_node(IR_VAR, NULL, NULL);
+ if (!v) {
+ printf("VAR NOT FOUND %s\n", (char *) name);
+ assert(v);
+ }
+ /**
+ assert(v->declared);
+ **/
+ assert(!oper->var || oper->var == v);
+ v->used = GL_TRUE;
+ oper->var = v;
+ n->Swizzle = swizzle;
+ n->Var = v;
+ slang_resolve_storage(NULL, n, A->program);
+ return n;
+}
+
+
+static GLboolean
+slang_is_writemask(const char *field, GLuint *mask)
+{
+ const GLuint n = 4;
+ GLuint i, bit, c = 0;
+
+ for (i = 0; i < n && field[i]; i++) {
+ switch (field[i]) {
+ case 'x':
+ case 'r':
+ bit = WRITEMASK_X;
+ break;
+ case 'y':
+ case 'g':
+ bit = WRITEMASK_Y;
+ break;
+ case 'z':
+ case 'b':
+ bit = WRITEMASK_Z;
+ break;
+ case 'w':
+ case 'a':
+ bit = WRITEMASK_W;
+ break;
+ default:
+ return GL_FALSE;
+ }
+ if (c & bit)
+ return GL_FALSE;
+ c |= bit;
+ }
+ *mask = c;
+ return GL_TRUE;
+}
+
+
+static slang_ir_node *
+slang_assemble_return(slang_assemble_ctx * A, slang_operation *oper)
+{
+ if (oper->num_children == 0) {
+ /* Convert to:
+ * goto __endOfFunction;
+ */
+ oper->type = slang_oper_goto;
+ oper->a_id = slang_atom_pool_atom(A->atoms, CurFunction->end_label);
+ }
+ else {
+ /*
+ * Convert from:
+ * return expr;
+ * To:
+ * __retVal = expr;
+ * goto __endOfFunction;
+ */
+ slang_operation *block, *assign, *jump;
+ slang_atom a_retVal;
+
+ a_retVal = slang_atom_pool_atom(A->atoms, "__retVal");
+ assert(a_retVal);
+
+#if 1
+ {
+ slang_variable *v
+ = _slang_locate_variable(oper->locals, a_retVal, GL_TRUE);
+ assert(v);
+ }
+#endif
+
+ block = slang_operation_new(1);
+ block->type = slang_oper_block_no_new_scope;
+ block->num_children = 2;
+ block->children = slang_operation_new(2);
+ assert(block->locals);
+ block->locals->outer_scope = oper->locals->outer_scope;
+
+ /* child[0]: __retVal = expr; */
+ assign = &block->children[0];
+ assign->type = slang_oper_assign;
+ assign->locals->outer_scope = block->locals;
+ assign->num_children = 2;
+ assign->children = slang_operation_new(2);
+ /* lhs */
+ assign->children[0].type = slang_oper_identifier;
+ assign->children[0].a_id = a_retVal;
+ assign->children[0].locals->outer_scope = assign->locals;
+ /* rhs */
+#if 0
+ assign->children[1] = oper->children[0]; /* XXX copy */
+#else
+ slang_operation_copy(&assign->children[1], &oper->children[0]);
+#endif
+
+
+ /* child[1]: goto __endOfFunction */
+ jump = &block->children[1];
+ jump->type = slang_oper_goto;
+ assert(CurFunction->end_label);
+ jump->a_id = slang_atom_pool_atom(A->atoms, CurFunction->end_label);
+
+#if 00
+ printf("NEW RETURN:\n");
+ slang_print_tree(block, 0);
+#endif
+
+ slang_operation_copy(oper, block);
+ /* XXX destruct block */
+ }
+
+ /* assemble the new code */
+ return slang_assemble_operation(A, oper);
+}
+
+
+
+/**
+ * Check if the given function is really just a wrapper for an
+ * basic assembly instruction.
+ */
+static GLboolean
+slang_is_asm_function(const slang_function *fun)
+{
+ if (fun->body->type == slang_oper_block_no_new_scope &&
+ fun->body->num_children == 1 &&
+ fun->body->children[0].type == slang_oper_asm) {
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+}
+
+
+/**
+ * Produce inline code for a call to an assembly instruction.
+ */
+static slang_operation *
+slang_inline_asm_function(slang_assemble_ctx *A,
+ slang_function *fun, slang_operation *oper)
+{
+ const int numArgs = oper->num_children;
+ const slang_operation *args = oper->children;
+ GLuint i;
+ slang_operation *inlined = slang_operation_new(1);
+
+ /*assert(oper->type == slang_oper_call); or vec4_add, etc */
+
+ inlined->type = fun->body->children[0].type;
+ inlined->a_id = fun->body->children[0].a_id;
+ inlined->num_children = numArgs;
+ inlined->children = slang_operation_new(numArgs);
+#if 0
+ inlined->locals = slang_variable_scope_copy(oper->locals);
+#else
+ assert(inlined->locals);
+ inlined->locals->outer_scope = oper->locals->outer_scope;
+#endif
+
+ for (i = 0; i < numArgs; i++) {
+ slang_operation_copy(inlined->children + i, args + i);
+ }
+
+ return inlined;
+}
+
+
+static void
+slang_resolve_variable(slang_operation *oper)
+{
+ if (oper->type != slang_oper_identifier)
+ return;
+ if (!oper->var) {
+ oper->var = _slang_locate_variable(oper->locals,
+ (const slang_atom) oper->a_id,
+ GL_TRUE);
+ if (oper->var)
+ oper->var->used = GL_TRUE;
+ }
+}
+
+
+/**
+ * Replace particular variables (slang_oper_identifier) with new expressions.
+ */
+static void
+slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
+ GLuint substCount, slang_variable **substOld,
+ slang_operation **substNew, GLboolean isLHS)
+{
+ switch (oper->type) {
+ case slang_oper_variable_decl:
+ {
+ slang_variable *v = _slang_locate_variable(oper->locals,
+ oper->a_id, GL_TRUE);
+ assert(v);
+ if (v->initializer && oper->num_children == 0) {
+ /* set child of oper to copy of initializer */
+ oper->num_children = 1;
+ oper->children = slang_operation_new(1);
+ slang_operation_copy(&oper->children[0], v->initializer);
+ }
+ if (oper->num_children == 1) {
+ /* the initializer */
+ slang_substitute(A, &oper->children[0], substCount, substOld, substNew, GL_FALSE);
+ }
+ }
+ break;
+ case slang_oper_identifier:
+ assert(oper->num_children == 0);
+ if (1/**!isLHS XXX FIX */) {
+ slang_atom id = oper->a_id;
+ slang_variable *v;
+ GLuint i;
+ v = _slang_locate_variable(oper->locals, id, GL_TRUE);
+ if (!v) {
+ printf("var %s not found!\n", (char *) oper->a_id);
+ break;
+ }
+
+ /* look for a substitution */
+ for (i = 0; i < substCount; i++) {
+ if (v == substOld[i]) {
+ /* OK, replace this slang_oper_identifier with a new expr */
+ assert(substNew[i]->type == slang_oper_identifier ||
+ substNew[i]->type == slang_oper_literal_float);
+#if 1 /* DEBUG only */
+ if (substNew[i]->type == slang_oper_identifier) {
+ assert(substNew[i]->var);
+ assert(substNew[i]->var->a_name);
+ printf("Substitute %s with %s in id node %p\n",
+ (char*)v->a_name, (char*) substNew[i]->var->a_name,
+ (void*) oper);
+ }
+ else
+ printf("Substitute %s with %f in id node %p\n",
+ (char*)v->a_name, substNew[i]->literal[0],
+ (void*) oper);
+#endif
+ slang_operation_copy(oper, substNew[i]);
+ break;
+ }
+ }
+ }
+ break;
+ case slang_oper_return:
+ /* do return replacement here too */
+ slang_assemble_return(A, oper);
+ slang_substitute(A, oper, substCount, substOld, substNew, GL_FALSE);
+ break;
+ case slang_oper_assign:
+ case slang_oper_subscript:
+ /* special case:
+ * child[0] can't have substitutions but child[1] can.
+ */
+ slang_substitute(A, &oper->children[0], substCount, substOld, substNew, GL_TRUE);
+ slang_substitute(A, &oper->children[1], substCount, substOld, substNew, GL_FALSE);
+ break;
+ case slang_oper_field:
+ /* XXX NEW - test */
+ slang_substitute(A, &oper->children[0], substCount, substOld, substNew, GL_TRUE);
+ break;
+ default:
+ {
+ GLuint i;
+ for (i = 0; i < oper->num_children; i++)
+ slang_substitute(A, &oper->children[i], substCount, substOld, substNew, GL_FALSE);
+ }
+ }
+}
+
+
+
+/**
+ * Inline the given function call operation.
+ * Return a new slang_operation that corresponds to the inlined code.
+ */
+static slang_operation *
+slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
+ slang_operation *oper, slang_operation *returnOper)
+{
+ typedef enum {
+ SUBST = 1,
+ COPY_IN,
+ COPY_OUT
+ } ParamMode;
+ ParamMode *paramMode;
+ const GLboolean haveRetValue = _slang_function_has_return_value(fun);
+ const GLuint numArgs = oper->num_children;
+ const GLuint totalArgs = numArgs + haveRetValue;
+ slang_operation *args = oper->children;
+ slang_operation *inlined, *top;
+ slang_variable **substOld;
+ slang_operation **substNew;
+ GLuint substCount, numCopyIn, i;
+
+ /*assert(oper->type == slang_oper_call); (or (matrix) multiply, etc) */
+ assert(fun->param_count == totalArgs);
+
+ /* allocate temporary arrays */
+ paramMode = (ParamMode *)
+ _mesa_calloc(totalArgs * sizeof(ParamMode));
+ substOld = (slang_variable **)
+ _mesa_calloc(totalArgs * sizeof(slang_variable *));
+ substNew = (slang_operation **)
+ _mesa_calloc(totalArgs * sizeof(slang_operation *));
+
+ printf("\nInline call to %s (total vars=%d nparams=%d)\n",
+ (char *) fun->header.a_name,
+ fun->parameters->num_variables, numArgs);
+
+
+ if (haveRetValue && !returnOper) {
+ /* Create comma sequence for inlined code, the left child will be the
+ * function body and the right child will be a variable (__retVal)
+ * that will get the return value.
+ */
+ slang_operation *commaSeq;
+ slang_operation *declOper = NULL;
+ slang_variable *resultVar;
+
+ commaSeq = slang_operation_new(1);
+ commaSeq->type = slang_oper_sequence;
+ assert(commaSeq->locals);
+ commaSeq->locals->outer_scope = oper->locals->outer_scope;
+ commaSeq->num_children = 3;
+ commaSeq->children = slang_operation_new(3);
+ /* allocate the return var */
+ resultVar = slang_variable_scope_grow(commaSeq->locals);
+ /*
+ printf("ALLOC __retVal from scope %p\n", (void*) commaSeq->locals);
+ */
+ printf("Alloc __resultTemp in scope %p for retval of calling %s\n",
+ (void*)commaSeq->locals, (char *) fun->header.a_name);
+
+ resultVar->a_name = slang_atom_pool_atom(A->atoms, "__resultTmp");
+ resultVar->type = fun->header.type; /* XXX copy? */
+ /*resultVar->type.qualifier = slang_qual_out;*/
+
+ /* child[0] = __resultTmp declaration */
+ declOper = &commaSeq->children[0];
+ declOper->type = slang_oper_variable_decl;
+ declOper->a_id = resultVar->a_name;
+ declOper->locals->outer_scope = commaSeq->locals; /*** ??? **/
+
+ /* child[1] = function body */
+ inlined = &commaSeq->children[1];
+ /* XXXX this may be inappropriate!!!!: */
+ inlined->locals->outer_scope = commaSeq->locals;
+
+ /* child[2] = __resultTmp reference */
+ returnOper = &commaSeq->children[2];
+ returnOper->type = slang_oper_identifier;
+ returnOper->a_id = resultVar->a_name;
+ returnOper->locals->outer_scope = commaSeq->locals;
+ declOper->locals->outer_scope = commaSeq->locals;
+
+ top = commaSeq;
+ }
+ else {
+ top = inlined = slang_operation_new(1);
+ /* XXXX this may be inappropriate!!!! */
+ inlined->locals->outer_scope = oper->locals->outer_scope;
+ }
+
+
+ assert(inlined->locals);
+
+ /* Examine the parameters, look for inout/out params, look for possible
+ * substitutions, etc:
+ * param type behaviour
+ * in copy actual to local
+ * const in substitute param with actual
+ * out copy out
+ */
+ substCount = 0;
+ for (i = 0; i < totalArgs; i++) {
+ slang_variable *p = &fun->parameters->variables[i];
+ printf("Param %d: %s %s \n", i,
+ slang_type_qual_string(p->type.qualifier),
+ (char *) p->a_name);
+ if (p->type.qualifier == slang_qual_inout ||
+ p->type.qualifier == slang_qual_out) {
+ /* an output param */
+ slang_operation *arg;
+ if (i < numArgs)
+ arg = &args[i];
+ else
+ arg = returnOper;
+ paramMode[i] = SUBST;
+ assert(arg->type == slang_oper_identifier
+ /*||arg->type == slang_oper_variable_decl*/);
+ slang_resolve_variable(arg);
+ /* replace parameter 'p' with argument 'arg' */
+ substOld[substCount] = p;
+ substNew[substCount] = arg; /* will get copied */
+ substCount++;
+ }
+ else if (p->type.qualifier == slang_qual_const) {
+ /* a constant input param */
+ if (args[i].type == slang_oper_identifier ||
+ args[i].type == slang_oper_literal_float) {
+ /* replace all occurances of this parameter variable with the
+ * actual argument variable or a literal.
+ */
+ paramMode[i] = SUBST;
+ slang_resolve_variable(&args[i]);
+ substOld[substCount] = p;
+ substNew[substCount] = &args[i]; /* will get copied */
+ substCount++;
+ }
+ else {
+ paramMode[i] = COPY_IN;
+ }
+ }
+ else {
+ paramMode[i] = COPY_IN;
+ }
+ assert(paramMode[i]);
+ }
+
+#if 00
+ printf("ABOUT to inline body %p with checksum %d\n",
+ (char *) fun->body, slang_checksum_tree(fun->body));
+#endif
+
+ /* actual code inlining: */
+ slang_operation_copy(inlined, fun->body);
+
+#if 000
+ printf("======================= orig body code ======================\n");
+ printf("=== params scope = %p\n", (void*) fun->parameters);
+ slang_print_tree(fun->body, 8);
+ printf("======================= copied code =========================\n");
+ slang_print_tree(inlined, 8);
+#endif
+
+ /* do parameter substitution in inlined code: */
+ slang_substitute(A, inlined, substCount, substOld, substNew, GL_FALSE);
+
+#if 000
+ printf("======================= subst code ==========================\n");
+ slang_print_tree(inlined, 8);
+ printf("=============================================================\n");
+#endif
+
+ /* New prolog statements: (inserted before the inlined code)
+ * Copy the 'in' arguments.
+ */
+ numCopyIn = 0;
+ for (i = 0; i < numArgs; i++) {
+ if (paramMode[i] == COPY_IN) {
+ slang_variable *p = &fun->parameters->variables[i];
+ /* declare parameter 'p' */
+ slang_operation *decl = slang_operation_insert(&inlined->num_children,
+ &inlined->children,
+ numCopyIn);
+ printf("COPY_IN %s from expr\n", (char*)p->a_name);
+ decl->type = slang_oper_variable_decl;
+ assert(decl->locals);
+ decl->locals = fun->parameters;
+ decl->a_id = p->a_name;
+ decl->num_children = 1;
+ decl->children = slang_operation_new(1);
+
+ /* child[0] is the var's initializer */
+ slang_operation_copy(&decl->children[0], args + i);
+
+ numCopyIn++;
+ }
+ }
+
+ /* New epilog statements:
+ * 1. Create end of function label to jump to from return statements.
+ * 2. Copy the 'out' parameter vars
+ */
+ {
+ slang_operation *lab = slang_operation_insert(&inlined->num_children,
+ &inlined->children,
+ inlined->num_children);
+ lab->type = slang_oper_label;
+ lab->a_id = slang_atom_pool_atom(A->atoms, CurFunction->end_label);
+ }
+
+ for (i = 0; i < totalArgs; i++) {
+ if (paramMode[i] == COPY_OUT) {
+ const slang_variable *p = &fun->parameters->variables[i];
+ /* actualCallVar = outParam */
+ /*if (i > 0 || !haveRetValue)*/
+ slang_operation *ass = slang_operation_insert(&inlined->num_children,
+ &inlined->children,
+ inlined->num_children);
+ ass->type = slang_oper_assign;
+ ass->num_children = 2;
+ ass->locals = _slang_variable_scope_new(inlined->locals);
+ assert(ass->locals);
+ ass->children = slang_operation_new(2);
+ ass->children[0] = args[i]; /*XXX copy */
+ ass->children[1].type = slang_oper_identifier;
+ ass->children[1].a_id = p->a_name;
+ ass->children[1].locals = _slang_variable_scope_new(ass->locals);
+ }
+ }
+
+ _mesa_free(paramMode);
+ _mesa_free(substOld);
+ _mesa_free(substNew);
+
+ printf("Done Inline call to %s (total vars=%d nparams=%d)\n",
+ (char *) fun->header.a_name,
+ fun->parameters->num_variables, numArgs);
+
+ return top;
+}
+
+
+static slang_ir_node *
+slang_assemble_function_call(slang_assemble_ctx *A, slang_function *fun,
+ slang_operation *oper, slang_operation *dest)
+{
+ slang_ir_node *n;
+ slang_operation *inlined;
+ slang_function *prevFunc;
+
+ prevFunc = CurFunction;
+ CurFunction = fun;
+
+ if (!CurFunction->end_label) {
+ char name[200];
+ sprintf(name, "__endOfFunc_%s_", (char *) CurFunction->header.a_name);
+ CurFunction->end_label = slang_atom_pool_gen(A->atoms, name);
+ }
+
+ if (slang_is_asm_function(fun) && !dest) {
+ /* assemble assembly function - tree style */
+ inlined = slang_inline_asm_function(A, fun, oper);
+ }
+ else {
+ /* non-assembly function */
+ inlined = slang_inline_function_call(A, fun, oper, dest);
+ }
+
+ /* Replace the function call with the inlined block */
+#if 0
+ slang_operation_construct(oper);
+ slang_operation_copy(oper, inlined);
+#else
+ *oper = *inlined;
+#endif
+
+
+#if 1
+ assert(inlined->locals);
+ printf("*** Inlined code for call to %s:\n",
+ (char*) fun->header.a_name);
+
+ slang_print_tree(oper, 10);
+ printf("\n");
+#endif
+
+ /* assemble what we just made XXX here??? */
+ n = slang_assemble_operation(A, oper);
+
+ CurFunction = prevFunc;
+
+ return n;
+}
+
+
+/**
+ * Map "_asm foo" to IR_FOO, etc.
+ */
+typedef struct
+{
+ const char *Name;
+ slang_ir_opcode Opcode;
+ GLuint HaveRetValue, NumParams;
+} slang_asm_info;
+
+
+static slang_asm_info AsmInfo[] = {
+ /* vec4 binary op */
+ { "vec4_add", IR_ADD, 1, 2 },
+ { "vec4_multiply", IR_MUL, 1, 2 },
+ { "vec4_dot", IR_DOT4, 1, 2 },
+ { "vec3_dot", IR_DOT3, 1, 2 },
+ { "vec3_cross", IR_CROSS, 1, 2 },
+ { "vec4_min", IR_MIN, 1, 2 },
+ { "vec4_max", IR_MAX, 1, 2 },
+ { "vec4_seq", IR_SEQ, 1, 2 },
+ { "vec4_sge", IR_SGE, 1, 2 },
+ { "vec4_sgt", IR_SGT, 1, 2 },
+ /* vec4 unary */
+ { "vec4_floor", IR_FLOOR, 1, 1 },
+ { "vec4_frac", IR_FRAC, 1, 1 },
+ { "vec4_abs", IR_ABS, 1, 1 },
+ /* float binary op */
+ { "float_add", IR_ADD, 1, 2 },
+ { "float_subtract", IR_SUB, 1, 2 },
+ { "float_multiply", IR_MUL, 1, 2 },
+ { "float_divide", IR_DIV, 1, 2 },
+ { "float_power", IR_POW, 1, 2 },
+ /* unary op */
+ { "int_to_float", IR_I_TO_F, 1, 1 },
+ { "float_exp", IR_EXP, 1, 1 },
+ { "float_exp2", IR_EXP2, 1, 1 },
+ { "float_log2", IR_LOG2, 1, 1 },
+ { "float_rsq", IR_RSQ, 1, 1 },
+ { "float_rcp", IR_RCP, 1, 1 },
+ { "float_sine", IR_SIN, 1, 1 },
+ { "float_cosine", IR_COS, 1, 1 },
+ { NULL, IR_NOP, 0, 0 }
+};
+
+
+static slang_asm_info *
+slang_find_asm_info(const char *name)
+{
+ GLuint i;
+ for (i = 0; AsmInfo[i].Name; i++) {
+ if (_mesa_strcmp(AsmInfo[i].Name, name) == 0) {
+ return AsmInfo + i;
+ }
+ }
+ return NULL;
+}
+
+
+static GLuint
+make_writemask(char *field)
+{
+ GLuint mask = 0x0;
+ while (*field) {
+ switch (*field) {
+ case 'x':
+ mask |= WRITEMASK_X;
+ break;
+ case 'y':
+ mask |= WRITEMASK_Y;
+ break;
+ case 'z':
+ mask |= WRITEMASK_Z;
+ break;
+ case 'w':
+ mask |= WRITEMASK_W;
+ break;
+ default:
+ abort();
+ }
+ field++;
+ }
+ if (mask == 0x0)
+ return WRITEMASK_XYZW;
+ else
+ return mask;
+}
+
+
+/**
+ * Generate IR code for an instruction/operation such as:
+ * __asm vec4_dot __retVal.x, v1, v2;
+ */
+static slang_ir_node *
+slang_assemble_asm(slang_assemble_ctx *A, slang_operation *oper,
+ slang_operation *dest)
+{
+ const slang_asm_info *info;
+ slang_ir_node *kids[2], *n;
+ GLuint j, firstOperand;
+
+ assert(oper->type == slang_oper_asm);
+
+ info = slang_find_asm_info((char *) oper->a_id);
+ assert(info);
+ assert(info->NumParams <= 2);
+
+ if (info->NumParams == oper->num_children) {
+ /* storage for result not specified */
+ firstOperand = 0;
+ }
+ else {
+ /* storage for result (child[0]) is specified */
+ firstOperand = 1;
+ }
+
+ /* assemble child(ren) */
+ kids[0] = kids[1] = NULL;
+ for (j = 0; j < info->NumParams; j++) {
+ kids[j] = slang_assemble_operation(A, &oper->children[firstOperand + j]);
+ }
+
+ n = new_node(info->Opcode, kids[0], kids[1]);
+
+ if (firstOperand) {
+ /* 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];
+ if (dest_oper->type == slang_oper_field) {
+ /* writemask */
+ writemask = make_writemask((char*) dest_oper->a_id);
+ dest_oper = &dest_oper->children[0];
+ }
+
+ assert(dest_oper->type == slang_oper_identifier);
+ n0 = slang_assemble_operation(A, dest_oper);
+ assert(n0->Var);
+ assert(n0->Store);
+ free(n0);
+
+ n->Store = n0->Store;
+ n->Writemask = writemask;
+ }
+
+ return n;
+}
+
+
+
+
+
+/**
+ * Assemble a function call, given a particular function name.
+ * \param name the function's name (operators like '*' are possible).
+ */
+static slang_ir_node *
+slang_assemble_function_call_name(slang_assemble_ctx *A, const char *name,
+ slang_operation *oper, slang_operation *dest)
+{
+ slang_operation *params = oper->children;
+ const GLuint param_count = oper->num_children;
+ slang_atom atom;
+ slang_function *fun;
+
+ atom = slang_atom_pool_atom(A->atoms, name);
+ if (atom == SLANG_ATOM_NULL)
+ return NULL;
+
+ fun = _slang_locate_function(A->space.funcs, atom, params, param_count,
+ &A->space, A->atoms);
+ if (!fun) {
+ RETURN_ERROR2("Undefined function", name, 0);
+ }
+
+ return slang_assemble_function_call(A, fun, oper, dest);
+}
+
+
+static slang_ir_node *
+slang_assemble_operation(slang_assemble_ctx * A, slang_operation *oper)
+{
+ switch (oper->type) {
+ case slang_oper_block_no_new_scope:
+ case slang_oper_block_new_scope:
+ /* list of operations */
+ assert(oper->num_children > 0);
+ {
+ slang_ir_node *n, *first = NULL;
+ GLuint i;
+ for (i = 0; i < oper->num_children; i++) {
+ n = slang_assemble_operation(A, &oper->children[i]);
+ first = first ? new_seq(first, n) : n;
+ }
+ return first;
+ }
+ break;
+ case slang_oper_expression:
+ return slang_assemble_operation(A, &oper->children[0]);
+ break;
+ case slang_oper_while:
+ {
+ slang_ir_node *nStartLabel = new_label("while-start");
+ slang_ir_node *nCond = slang_assemble_operation(A, &oper->children[0]);
+ slang_ir_node *nNotCond = new_node(IR_NOT, nCond, NULL);
+ slang_ir_node *nBody = slang_assemble_operation(A, &oper->children[1]);
+ slang_ir_node *nEndLabel = new_label("while-end");
+ slang_ir_node *nCJump = new_cjump(nNotCond, "while-end");
+ slang_ir_node *nJump = new_jump("while-start");
+
+ return new_seq(nStartLabel,
+ new_seq(nCJump,
+ new_seq(nBody,
+ new_seq(nJump,
+ nEndLabel)
+ )
+ )
+ );
+ }
+ break;
+ case slang_oper_less:
+ return new_node(IR_LESS,
+ slang_assemble_operation(A, &oper->children[0]),
+ slang_assemble_operation(A, &oper->children[1]));
+ case slang_oper_add:
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 2);
+ n = slang_assemble_function_call_name(A, "+", oper, NULL);
+ return n;
+ }
+ case slang_oper_subtract:
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 2);
+ n = slang_assemble_function_call_name(A, "-", oper, NULL);
+ return n;
+ }
+ case slang_oper_multiply:
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 2);
+ n = slang_assemble_function_call_name(A, "*", oper, NULL);
+ return n;
+ }
+ case slang_oper_divide:
+ {
+ slang_ir_node *n;
+ assert(oper->num_children == 2);
+ n = slang_assemble_function_call_name(A, "/", oper, NULL);
+ return n;
+ }
+
+ case slang_oper_variable_decl:
+ {
+ slang_ir_node *n;
+ slang_ir_node *varDecl;
+ slang_variable *v;
+
+ assert(oper->num_children == 0 || oper->num_children == 1);
+
+ v = _slang_locate_variable(oper->locals,
+ oper->a_id, GL_TRUE);
+ assert(v);
+ varDecl = new_var_decl(A, v);
+ slang_alloc_var_storage(v, varDecl);
+
+ if (oper->num_children > 0) {
+ /* child is initializer */
+ slang_ir_node *var, *init, *rhs;
+ assert(oper->num_children == 1);
+ var = new_var(A, oper, oper->a_id, SWIZZLE_NOOP);
+ /* XXX make copy of this initializer? */
+ printf("\n*** ASSEMBLE INITIALIZER %p\n", (void*) v->initializer);
+ rhs = slang_assemble_operation(A, &oper->children[0]);
+ init = new_node(IR_MOVE, var, rhs);
+ n = new_seq(varDecl, init);
+ }
+ else if (v->initializer) {
+ slang_ir_node *var, *init, *rhs;
+ var = new_var(A, oper, oper->a_id, SWIZZLE_NOOP);
+ /* XXX make copy of this initializer? */
+ printf("\n*** ASSEMBLE INITIALIZER %p\n", (void*) v->initializer);
+ rhs = slang_assemble_operation(A, v->initializer);
+ init = new_node(IR_MOVE, var, rhs);
+ n = new_seq(varDecl, init);
+ }
+ else {
+ n = varDecl;
+ }
+ return n;
+ }
+ break;
+ case slang_oper_assign:
+ /* assignment */
+ /* XXX look for special case of: x = f(a, b)
+ * and replace with f(a, b, x) (where x == hidden __retVal out param)
+ */
+ if (oper->children[0].type == slang_oper_identifier &&
+ oper->children[1].type == slang_oper_call) {
+ /* special case */
+ slang_ir_node *n;
+ printf(">>>>>>>>>>>>>> Assign function call\n");
+ n = slang_assemble_function_call_name(A,
+ (const char *) oper->children[1].a_id,
+ &oper->children[1], &oper->children[0]);
+ return n;
+ }
+ else
+ {
+ slang_operation *lhs = &oper->children[0];
+ slang_ir_node *n, *c0, *c1;
+ GLuint mask = WRITEMASK_XYZW;
+ if (lhs->type == slang_oper_field) {
+ /* writemask */
+ if (!slang_is_writemask((char *) lhs->a_id, &mask))
+ mask = WRITEMASK_XYZW;
+ lhs = &lhs->children[0];
+ }
+ c0 = slang_assemble_operation(A, lhs);
+ c1 = slang_assemble_operation(A, &oper->children[1]);
+
+ n = new_node(IR_MOVE, c0, c1);
+ n->Writemask = mask;
+ return n;
+ }
+ break;
+ case slang_oper_asm:
+ return slang_assemble_asm(A, oper, NULL);
+ case slang_oper_call:
+ return slang_assemble_function_call_name(A, (const char *) oper->a_id,
+ oper, NULL);
+ break;
+ case slang_oper_return:
+ return slang_assemble_return(A, oper);
+ case slang_oper_goto:
+ return new_jump((char*) oper->a_id);
+ case slang_oper_label:
+ return new_label((char*) oper->a_id);
+ case slang_oper_identifier:
+ {
+ /* 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, SWIZZLE_NOOP);
+ assert(oper->var);
+ return n;
+ }
+ break;
+ case slang_oper_field:
+ {
+ slang_assembly_typeinfo ti;
+ slang_assembly_typeinfo_construct(&ti);
+ _slang_typeof_operation(A, &oper->children[0], &ti);
+ if (_slang_type_is_vector(ti.spec.type)) {
+ /* the field should be a swizzle */
+ const GLuint rows = _slang_type_dim(ti.spec.type);
+ slang_swizzle swz;
+ slang_ir_node *n;
+ if (!_slang_is_swizzle((char *) oper->a_id, rows, &swz)) {
+ RETURN_ERROR("Bad swizzle", 0);
+ }
+ n = slang_assemble_operation(A, &oper->children[0]);
+ n->Swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
+ swz.swizzle[1],
+ swz.swizzle[2],
+ swz.swizzle[3]);
+ return n;
+ }
+ else if (ti.spec.type == slang_spec_float) {
+ const GLuint rows = 1;
+ slang_swizzle swz;
+ slang_ir_node *n;
+ if (!_slang_is_swizzle((char *) oper->a_id, rows, &swz)) {
+ RETURN_ERROR("Bad swizzle", 0);
+ }
+ n = slang_assemble_operation(A, &oper->children[0]);
+ n->Swizzle = MAKE_SWIZZLE4(swz.swizzle[0],
+ swz.swizzle[1],
+ swz.swizzle[2],
+ swz.swizzle[3]);
+ return n;
+ }
+ else {
+ /* the field is a structure member */
+ abort();
+ }
+ }
+ break;
+ case slang_oper_subscript:
+ /* array dereference */
+ if (oper->children[1].type == slang_oper_literal_int) {
+ /* compile-time constant index - OK */
+ slang_assembly_typeinfo ti;
+ slang_ir_node *base;
+ slang_ir_storage *store2;
+ GLint index;
+ slang_assembly_typeinfo_construct(&ti);
+ _slang_typeof_operation(A, &oper->children[0], &ti);
+
+ base = slang_assemble_operation(A, &oper->children[0]);
+ assert(base->Opcode == IR_VAR);
+
+ index = (GLint) oper->children[1].literal[0];
+ /*
+ printf("element[%d]\n", index);
+ */
+#if 1
+ store2 = (slang_ir_storage *) _mesa_calloc(sizeof(*store2));
+ *store2 = *base->Store;
+ base->Store = store2;
+ base->Store->Size = -15;
+#endif
+ assert(base->Store);
+ base->Store->Index += index;
+ base->Store->Size = 1;
+ return base;
+ }
+ else {
+ /* run-time index - TBD */
+ abort();
+ }
+ return NULL;
+ case slang_oper_literal_float:
+ return new_float_literal(oper->literal[0], oper->literal[1],
+ oper->literal[2], oper->literal[3]);
+ case slang_oper_literal_int:
+ return new_float_literal(oper->literal[0], 0, 0, 0);
+ case slang_oper_literal_bool:
+ return new_float_literal(oper->literal[0], 0, 0, 0);
+ case slang_oper_postincrement:
+ /* XXX not 100% about this */
+ {
+ slang_ir_node *var = slang_assemble_operation(A, &oper->children[0]);
+ slang_ir_node *one = new_float_literal(1.0, 1.0, 1.0, 1.0);
+ slang_ir_node *sum = new_node(IR_ADD, var, one);
+ slang_ir_node *assign = new_node(IR_MOVE, var, sum);
+ return assign;
+ }
+ break;
+ case slang_oper_sequence:
+ {
+ slang_ir_node *top = NULL;
+ GLuint i;
+ for (i = 0; i < oper->num_children; i++) {
+ slang_ir_node *n = slang_assemble_operation(A, &oper->children[i]);
+ top = top ? new_seq(top, n) : n;
+ }
+ return top;
+ }
+ break;
+ case slang_oper_none:
+ return NULL;
+ default:
+ printf("Unhandled node type %d\n", oper->type);
+ abort();
+ return new_node(IR_NOP, NULL, NULL);
+ }
+ abort();
+ return NULL;
+}
+
+
+/**
+ * Produce an IR tree from a function AST.
+ * Then call the code emitter to convert the IR tree into a gl_program.
+ */
+struct slang_ir_node_ *
+_slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
+{
+ slang_ir_node *n, *endLabel;
+
+ if (_mesa_strcmp((char *) fun->header.a_name, "main") != 0 &&
+ _mesa_strcmp((char *) fun->header.a_name, "foo") != 0 &&
+ _mesa_strcmp((char *) fun->header.a_name, "bar") != 0)
+ return 0;
+
+ printf("\n*********** Assemble function2(%s)\n", (char*)fun->header.a_name);
+
+ slang_print_function(fun, 1);
+
+ A->program->Parameters = _mesa_new_parameter_list();
+ A->program->Varying = _mesa_new_parameter_list();
+
+ /*printf("** Begin Simplify\n");*/
+ slang_simplify(fun->body, &A->space, A->atoms);
+ /*printf("** End Simplify\n");*/
+
+ CurFunction = fun;
+
+ n = slang_assemble_operation(A, fun->body);
+
+ if (!CurFunction->end_label)
+ CurFunction->end_label = slang_atom_pool_gen(A->atoms, "__endOfFunction_Main");
+
+ endLabel = new_label(fun->end_label);
+ n = new_seq(n, endLabel);
+
+ CurFunction = NULL;
+
+
+ printf("************* New body for %s *****\n", (char*)fun->header.a_name);
+ slang_print_function(fun, 1);
+
+ printf("************* IR for %s *******\n", (char*)fun->header.a_name);
+ slang_print_ir(n, 0);
+
+ if (_mesa_strcmp((char*) fun->header.a_name, "main") == 0) {
+ _slang_emit_code(n, A->program);
+ }
+
+ printf("************* End assemble function2 ************\n\n");
+
+ return n;
+}
+
+
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 2005-2007 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_CODEGEN_H
+#define SLANG_CODEGEN_H
+
+
+#include "imports.h"
+#include "slang_compile.h"
+#include "slang_ir.h"
+
+
+extern struct slang_ir_node_ *
+_slang_codegen_function(slang_assemble_ctx *A , struct slang_function_ *fun);
+
+
+#endif /* SLANG_CODEGEN_H */
*/
#include "imports.h"
+#include "context.h"
+#include "program.h"
#include "grammar_mesa.h"
+#include "slang_codegen.h"
#include "slang_compile.h"
#include "slang_preprocess.h"
#include "slang_storage.h"
+#include "slang_error.h"
+
+#include "slang_print.h"
/*
* This is a straightforward implementation of the slang front-end
log->dont_free_text = 1;
log->text = out_of_memory;
}
+ abort();
}
/* slang_parse_ctx */
slang_assembly_file *assembly;
slang_var_pool *global_pool;
slang_machine *machine;
+ struct gl_program *program;
} slang_output_ctx;
/* _slang_compile() */
* \param C the parsing context
* \param O the output context
* \param oper the operation we're parsing
- * \param statment which child of the operation is being parsed
+ * \param statement indicates whether parsing a statement, or expression
* \return 1 if success, 0 if error
*/
static int
parse_child_operation(slang_parse_ctx * C, slang_output_ctx * O,
- slang_operation * oper, unsigned int statement)
+ slang_operation * oper, GLboolean statement)
{
slang_operation *ch;
/* grow child array */
+#if 000
oper->children = (slang_operation *)
slang_alloc_realloc(oper->children,
oper->num_children * sizeof(slang_operation),
return 0;
}
oper->num_children++;
- /* XXX I guess the 0th "statement" is not really a statement? */
+#else
+ ch = slang_operation_grow(&oper->num_children, &oper->children);
+#endif
if (statement)
return parse_statement(C, O, ch);
return parse_expression(C, O, ch);
/* local variable declaration, individual declarators are stored as
* children identifiers
*/
+#if 000
oper->type = slang_oper_variable_decl;
{
const unsigned int first_var = O->vars->num_variables;
}
}
}
+#else
+
+ oper->type = slang_oper_block_no_new_scope;
+ {
+ const unsigned int first_var = O->vars->num_variables;
+
+ /* parse the declaration, note that there can be zero or more
+ * than one declarators
+ */
+ if (!parse_declaration(C, O))
+ return 0;
+ if (first_var < O->vars->num_variables) {
+ const unsigned int num_vars = O->vars->num_variables - first_var;
+ unsigned int i;
+
+ oper->num_children = num_vars;
+ oper->children = slang_operation_new(num_vars);
+ if (oper->children == NULL) {
+ slang_info_log_memory(C->L);
+ return 0;
+ }
+ for (i = first_var; i < O->vars->num_variables; i++) {
+ slang_operation *o = &oper->children[i - first_var];
+ o->type = slang_oper_variable_decl;
+ o->locals->outer_scope = O->vars;
+ o->a_id = O->vars->variables[i].a_name;
+ }
+ }
+ }
+
+
+#endif
break;
case OP_ASM:
/* the __asm statement, parse the mnemonic and all its arguments
*/
oper->type = slang_oper_asm;
oper->a_id = parse_identifier(C);
+ if (strcmp((char*)oper->a_id, "dot") == 0) {
+ printf("Assemble dot! **************************\n");
+ }
if (oper->a_id == SLANG_ATOM_NULL)
return 0;
while (*C->I != OP_END) {
op->type = slang_oper_literal_bool;
if (!parse_number(C, &number))
return 0;
- op->literal = (GLfloat) number;
+ op->literal[0] =
+ op->literal[1] =
+ op->literal[2] =
+ op->literal[3] = (GLfloat) number;
break;
case OP_PUSH_INT:
op->type = slang_oper_literal_int;
if (!parse_number(C, &number))
return 0;
- op->literal = (GLfloat) number;
+ op->literal[0] =
+ op->literal[1] =
+ op->literal[2] =
+ op->literal[3] = (GLfloat) number;
break;
case OP_PUSH_FLOAT:
op->type = slang_oper_literal_float;
- if (!parse_float(C, &op->literal))
+ if (!parse_float(C, &op->literal[0]))
return 0;
+ op->literal[1] =
+ op->literal[2] =
+ op->literal[3] = op->literal[0];
break;
case OP_PUSH_IDENTIFIER:
op->type = slang_oper_identifier;
return 0;
}
+#if 111
+ /* if the function returns a value, append a hidden __retVal 'out'
+ * parameter that corresponds to the return value.
+ */
+ if (_slang_function_has_return_value(func)) {
+ slang_variable *p = slang_variable_scope_grow(func->parameters);
+ slang_atom a_retVal = slang_atom_pool_atom(C->atoms, "__retVal");
+ assert(a_retVal);
+ p->a_name = a_retVal;
+ p->type = func->header.type;
+ p->type.qualifier = slang_qual_out;
+ }
+#endif
+
/* function formal parameters and local variables share the same
* scope, so save the information about param count in a seperate
* place also link the scope to the global variable scope so when a
*/
func->param_count = func->parameters->num_variables;
func->parameters->outer_scope = O->vars;
+
return 1;
}
* \param O output context
* \param definition if non-zero expect a definition, else a declaration
* \param parsed_func_ret returns the parsed function
- * \return 1 if success, 0 if failure
+ * \return GL_TRUE if success, GL_FALSE if failure
*/
-static int
+static GLboolean
parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
slang_function ** parsed_func_ret)
{
/* parse function definition/declaration */
if (!slang_function_construct(&parsed_func))
- return 0;
+ return GL_FALSE;
if (definition) {
if (!parse_function_definition(C, O, &parsed_func)) {
slang_function_destruct(&parsed_func);
- return 0;
+ return GL_FALSE;
}
}
else {
if (!parse_function_prototype(C, O, &parsed_func)) {
slang_function_destruct(&parsed_func);
- return 0;
+ return GL_FALSE;
}
}
*/
found_func = slang_function_scope_find(O->funs, &parsed_func, 0);
if (found_func == NULL) {
- /* add the parsed function to the function list */
+ /* New function, add it to the function list */
O->funs->functions =
(slang_function *) slang_alloc_realloc(O->funs->functions,
O->funs->num_functions *
if (O->funs->functions == NULL) {
slang_info_log_memory(C->L);
slang_function_destruct(&parsed_func);
- return 0;
+ return GL_FALSE;
}
O->funs->functions[O->funs->num_functions] = parsed_func;
O->funs->num_functions++;
*parsed_func_ret = &O->funs->functions[O->funs->num_functions - 1];
}
else {
+ /* previously defined or declared */
/* TODO: check function return type qualifiers and specifiers */
if (definition) {
if (found_func->body != NULL) {
parsed_func.header.
a_name));
slang_function_destruct(&parsed_func);
- return 0;
+ return GL_FALSE;
}
/* destroy the existing function declaration and replace it
A.space.funcs = O->funs;
A.space.structs = O->structs;
A.space.vars = O->vars;
- if (!_slang_assemble_function(&A, *parsed_func_ret))
- return 0;
+ A.program = O->program;
+
+ _slang_reset_error();
+
+#if 0
+ printf("*************** Assemble function %s ****\n", (char *) (*parsed_func_ret)->header.a_name);
+ slang_print_var_scope((*parsed_func_ret)->parameters,
+ (*parsed_func_ret)->param_count);
+#endif
+
+
+ if (!_slang_assemble_function(&A, *parsed_func_ret)) {
+ /* propogate the error message back through the info log */
+ C->L->text = _mesa_strdup(_slang_error_text());
+ C->L->dont_free_text = GL_FALSE;
+ return GL_FALSE;
+ }
+
+
+#if 0
+ printf("**************************************\n");
+#endif
+#if 1
+ _slang_codegen_function(&A, *parsed_func_ret);
+#endif
}
- return 1;
+ return GL_TRUE;
}
/* declaration */
#define EXTERNAL_DECLARATION 2
static GLboolean
-parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit)
+parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
+ struct gl_program *program)
{
slang_output_ctx o;
o.assembly = &unit->object->assembly;
o.global_pool = &unit->object->varpool;
o.machine = &unit->object->machine;
+ o.program = program;
/* parse individual functions and declarations */
while (*C->I != EXTERNAL_NULL) {
slang_function *func;
if (!parse_function(C, &o, 1, &func))
- return 0;
+ return GL_FALSE;
}
break;
case EXTERNAL_DECLARATION:
if (!parse_declaration(C, &o))
- return 0;
+ return GL_FALSE;
break;
default:
- return 0;
+ return GL_FALSE;
}
}
C->I++;
- return 1;
+ return GL_TRUE;
}
static GLboolean
compile_binary(const byte * prod, slang_code_unit * unit,
slang_unit_type type, slang_info_log * infolog,
- slang_code_unit * builtin, slang_code_unit * downlink)
+ slang_code_unit * builtin, slang_code_unit * downlink,
+ struct gl_program *program)
{
slang_parse_ctx C;
}
/* parse translation unit */
- return parse_code_unit(&C, unit);
+ return parse_code_unit(&C, unit, program);
}
static GLboolean
compile_with_grammar(grammar id, const char *source, slang_code_unit * unit,
slang_unit_type type, slang_info_log * infolog,
- slang_code_unit * builtin)
+ slang_code_unit * builtin,
+ struct gl_program *program)
{
byte *prod;
GLuint size, start, version;
}
/* Finally check the syntax and generate its binary representation. */
- if (!grammar_fast_check
- (id, (const byte *) (slang_string_cstr(&preprocessed)), &prod, &size,
+ if (!grammar_fast_check(id,
+ (const byte *) (slang_string_cstr(&preprocessed)),
+ &prod, &size,
65536)) {
char buf[1024];
GLint pos;
slang_string_free(&preprocessed);
grammar_get_last_error((byte *) (buf), sizeof(buf), &pos);
slang_info_log_error(infolog, buf);
- return GL_FALSE;
+ RETURN_ERROR("syntax error", 0);
}
slang_string_free(&preprocessed);
/* Syntax is okay - translate it to internal representation. */
- if (!compile_binary
- (prod, unit, type, infolog, builtin,
- &builtin[SLANG_BUILTIN_TOTAL - 1])) {
+ if (!compile_binary(prod, unit, type, infolog, builtin,
+ &builtin[SLANG_BUILTIN_TOTAL - 1],
+ program)) {
grammar_alloc_free(prod);
return GL_FALSE;
}
};
#if defined(USE_X86_ASM) || defined(SLANG_X86)
+foo
static const byte slang_builtin_vec4_gc[] = {
#include "library/slang_builtin_vec4_gc.h"
};
static GLboolean
compile_object(grammar * id, const char *source, slang_code_object * object,
- slang_unit_type type, slang_info_log * infolog)
+ slang_unit_type type, slang_info_log * infolog,
+ struct gl_program *program)
{
slang_code_unit *builtins = NULL;
/* if parsing user-specified shader, load built-in library */
if (type == slang_unit_fragment_shader || type == slang_unit_vertex_shader) {
/* compile core functionality first */
- if (!compile_binary(slang_core_gc, &object->builtin[SLANG_BUILTIN_CORE],
- slang_unit_fragment_builtin, infolog, NULL, NULL))
+ if (!compile_binary(slang_core_gc,
+ &object->builtin[SLANG_BUILTIN_CORE],
+ slang_unit_fragment_builtin, infolog,
+ NULL, NULL, NULL))
return GL_FALSE;
/* compile common functions and variables, link to core */
- if (!compile_binary
- (slang_common_builtin_gc, &object->builtin[SLANG_BUILTIN_COMMON],
- slang_unit_fragment_builtin, infolog, NULL,
- &object->builtin[SLANG_BUILTIN_CORE]))
+ if (!compile_binary(slang_common_builtin_gc,
+ &object->builtin[SLANG_BUILTIN_COMMON],
+ slang_unit_fragment_builtin, infolog, NULL,
+ &object->builtin[SLANG_BUILTIN_CORE], NULL))
return GL_FALSE;
/* compile target-specific functions and variables, link to common */
if (type == slang_unit_fragment_shader) {
- if (!compile_binary
- (slang_fragment_builtin_gc,
- &object->builtin[SLANG_BUILTIN_TARGET],
- slang_unit_fragment_builtin, infolog, NULL,
- &object->builtin[SLANG_BUILTIN_COMMON]))
+ if (!compile_binary(slang_fragment_builtin_gc,
+ &object->builtin[SLANG_BUILTIN_TARGET],
+ slang_unit_fragment_builtin, infolog, NULL,
+ &object->builtin[SLANG_BUILTIN_COMMON], NULL))
return GL_FALSE;
}
else if (type == slang_unit_vertex_shader) {
- if (!compile_binary
- (slang_vertex_builtin_gc, &object->builtin[SLANG_BUILTIN_TARGET],
- slang_unit_vertex_builtin, infolog, NULL,
- &object->builtin[SLANG_BUILTIN_COMMON]))
+ if (!compile_binary(slang_vertex_builtin_gc,
+ &object->builtin[SLANG_BUILTIN_TARGET],
+ slang_unit_vertex_builtin, infolog, NULL,
+ &object->builtin[SLANG_BUILTIN_COMMON], NULL))
return GL_FALSE;
}
#if defined(USE_X86_ASM) || defined(SLANG_X86)
/* compile x86 4-component vector overrides, link to target */
- if (!compile_binary
- (slang_builtin_vec4_gc, &object->builtin[SLANG_BUILTIN_VEC4],
- slang_unit_fragment_builtin, infolog, NULL,
- &object->builtin[SLANG_BUILTIN_TARGET]))
+ if (!compile_binary(slang_builtin_vec4_gc,
+ &object->builtin[SLANG_BUILTIN_VEC4],
+ slang_unit_fragment_builtin, infolog, NULL,
+ &object->builtin[SLANG_BUILTIN_TARGET]))
return GL_FALSE;
#endif
/* disable language extensions */
+#if NEW_SLANG /* allow-built-ins */
+ grammar_set_reg8(*id, (const byte *) "parsing_builtin", 1);
+#else
grammar_set_reg8(*id, (const byte *) "parsing_builtin", 0);
+#endif
builtins = object->builtin;
}
/* compile the actual shader - pass-in built-in library for external shader */
return compile_with_grammar(*id, source, &object->unit, type, infolog,
- builtins);
+ builtins, program);
+}
+
+
+static void
+slang_create_uniforms(const slang_export_data_table *exports,
+ struct gl_program *program)
+{
+ /* XXX only add uniforms that are actually going to get used */
+ GLuint i;
+ for (i = 0; i < exports->count; i++) {
+ if (exports->entries[i].access == slang_exp_uniform) {
+ const char *name = (char *) exports->entries[i].quant.name;
+ GLint j = _mesa_add_uniform(program->Parameters, name, 4);
+ assert(j >= 0);
+ }
+ }
}
+
GLboolean
_slang_compile(const char *source, slang_code_object * object,
- slang_unit_type type, slang_info_log * infolog)
+ slang_unit_type type, slang_info_log * infolog,
+ struct gl_program *program)
{
GLboolean success;
grammar id = 0;
_slang_code_object_dtr(object);
_slang_code_object_ctr(object);
- success = compile_object(&id, source, object, type, infolog);
+ success = compile_object(&id, source, object, type, infolog, program);
if (id != 0)
grammar_destroy(id);
if (!success)
if (!_slang_build_export_data_table(&object->expdata, &object->unit.vars))
return GL_FALSE;
- if (!_slang_build_export_code_table
- (&object->expcode, &object->unit.funs, &object->unit))
+ if (!_slang_build_export_code_table(&object->expcode, &object->unit.funs,
+ &object->unit))
return GL_FALSE;
+#if NEW_SLANG
+ {
+ GET_CURRENT_CONTEXT(ctx);
+ slang_create_uniforms(&object->expdata, program);
+ _mesa_print_program(program);
+ _mesa_print_program_parameters(ctx, program);
+ }
+#endif
+
+
#if defined(USE_X86_ASM) || defined(SLANG_X86)
/* XXX: lookup the @main label */
if (!_slang_x86_codegen
return GL_TRUE;
}
+
#if !defined SLANG_COMPILE_H
#define SLANG_COMPILE_H
+#include "imports.h"
+#include "mtypes.h"
#include "slang_export.h"
#include "slang_execute.h"
#include "slang_compile_variable.h"
void slang_info_log_memory (slang_info_log *);
extern GLboolean
-_slang_compile (const char *, slang_code_object *, slang_unit_type, slang_info_log *);
+_slang_compile (const char *, slang_code_object *, slang_unit_type, slang_info_log *, struct gl_program *program);
#ifdef __cplusplus
}
func->param_count = 0;
func->body = NULL;
func->address = ~0;
+ func->end_label = 0;
slang_fixup_table_init(&func->fixups);
return 1;
}
}
+/**
+ * Does this function have a non-void return value?
+ */
+GLboolean
+_slang_function_has_return_value(const slang_function *fun)
+{
+ return fun->header.type.specifier.type != slang_spec_void;
+}
+
+
/**
* Search a list of functions for a particular function by name.
* \param funcs the list of functions to search
for (i = 0; i < funcs->num_functions; i++) {
slang_function *f = &funcs->functions[i];
+ const GLuint haveRetValue = 0;
+#if 0
+ = (f->header.type.specifier.type != slang_spec_void);
+#endif
unsigned int j;
+ /*
+ printf("Compare name %s to %s (ret %u, %d, %d)\n",
+ (char *) fun->header.a_name, (char *) f->header.a_name,
+ haveRetValue,
+ fun->param_count, f->param_count);
+ */
+
if (fun->header.a_name != f->header.a_name)
continue;
if (fun->param_count != f->param_count)
continue;
- for (j = 0; j < fun->param_count; j++) {
+ for (j = haveRetValue; j < fun->param_count; j++) {
if (!slang_type_specifier_equal
(&fun->parameters->variables[j].type.specifier,
&f->parameters->variables[j].type.specifier))
break;
}
- if (j == fun->param_count)
+ if (j == fun->param_count) {
+ /*
+ printf("Found match\n");
+ */
return f;
+ }
}
+ /*
+ printf("Not found\n");
+ */
if (all_scopes && funcs->outer_scope != NULL)
return slang_function_scope_find(funcs->outer_scope, fun, 1);
return NULL;
slang_operation *body; /**< The instruction tree */
unsigned int address; /**< Address of this func in memory */
slang_fixup_table fixups; /**< Mem locations which need func's address */
+ slang_atom end_label; /**< The end-of-function label */
} slang_function;
extern int slang_function_construct(slang_function *);
extern void
slang_function_scope_destruct(slang_function_scope *);
+extern GLboolean
+_slang_function_has_return_value(const slang_function *fun);
+
extern int
slang_function_scope_find_by_name(slang_function_scope *, slang_atom, int);
oper->type = slang_oper_none;
oper->children = NULL;
oper->num_children = 0;
- oper->literal = (float) 0;
+ oper->literal[0] = 0.0;
oper->a_id = SLANG_ATOM_NULL;
- oper->locals =
- (slang_variable_scope *)
- slang_alloc_malloc(sizeof(slang_variable_scope));
+ oper->locals = _slang_variable_scope_new(NULL);
if (oper->locals == NULL)
return GL_FALSE;
_slang_variable_scope_ctr(oper->locals);
+ oper->fun = NULL;
+ oper->var = NULL;
return GL_TRUE;
}
slang_alloc_free(oper->children);
slang_variable_scope_destruct(oper->locals);
slang_alloc_free(oper->locals);
+ oper->children = NULL;
+ oper->num_children = 0;
+ oper->locals = NULL;
}
/**
return GL_FALSE;
}
}
- z.literal = y->literal;
+ z.literal[0] = y->literal[0];
+ z.literal[1] = y->literal[1];
+ z.literal[2] = y->literal[2];
+ z.literal[3] = y->literal[3];
z.a_id = y->a_id;
- if (!slang_variable_scope_copy(z.locals, y->locals)) {
- slang_operation_destruct(&z);
- return GL_FALSE;
+ if (y->locals) {
+ if (!slang_variable_scope_copy(z.locals, y->locals)) {
+ slang_operation_destruct(&z);
+ return GL_FALSE;
+ }
}
+#if 0
+ z.var = y->var;
+ z.fun = y->fun;
+#endif
slang_operation_destruct(x);
*x = z;
return GL_TRUE;
slang_operation *
slang_operation_new(GLuint count)
{
- return (slang_operation *) _mesa_calloc(count * sizeof(slang_operation));
+ slang_operation *ops
+ = (slang_operation *) _mesa_malloc(count * sizeof(slang_operation));
+ assert(count > 0);
+ if (ops) {
+ GLuint i;
+ for (i = 0; i < count; i++)
+ slang_operation_construct(ops + i);
+ }
+ return ops;
+}
+
+
+slang_operation *
+slang_operation_grow(GLuint *numChildren, slang_operation **children)
+{
+ slang_operation *ops;
+
+ ops = (slang_operation *)
+ slang_alloc_realloc(*children,
+ *numChildren * sizeof(slang_operation),
+ (*numChildren + 1) * sizeof(slang_operation));
+ if (ops) {
+ slang_operation *newOp = ops + *numChildren;
+ if (!slang_operation_construct(newOp)) {
+ _mesa_free(ops);
+ *children = NULL;
+ return NULL;
+ }
+ *children = ops;
+ (*numChildren)++;
+ return newOp;
+ }
+ return NULL;
+}
+
+/**
+ * Insert a new slang_operation into an array.
+ * \param numChildren pointer to current number of children (in/out)
+ * \param children address of array (in/out)
+ * \param pos position to insert
+ * \return pointer to the new operation
+ */
+slang_operation *
+slang_operation_insert(GLuint *numChildren, slang_operation **children,
+ GLuint pos)
+{
+ slang_operation *ops;
+
+ assert(pos <= *numChildren);
+
+ ops = (slang_operation *)
+ _mesa_malloc((*numChildren + 1) * sizeof(slang_operation));
+ if (ops) {
+ slang_operation *newOp;
+ newOp = ops + pos;
+ if (pos > 0)
+ _mesa_memcpy(ops, *children, pos * sizeof(slang_operation));
+ if (pos < *numChildren)
+ _mesa_memcpy(newOp + 1, (*children) + pos,
+ (*numChildren - pos) * sizeof(slang_operation));
+
+ if (!slang_operation_construct(newOp)) {
+ _mesa_free(ops);
+ *numChildren = 0;
+ *children = NULL;
+ return NULL;
+ }
+ *children = ops;
+ (*numChildren)++;
+ return newOp;
+ }
+ return NULL;
}
+
slang_oper_continue, /* "continue" statement */
slang_oper_discard, /* "discard" (kill fragment) statement */
slang_oper_return, /* "return" [expr] */
+ slang_oper_goto, /* jump to label */
+ slang_oper_label, /* a jump target */
slang_oper_expression, /* [expr] */
slang_oper_if, /* "if" [0] then [1] else [2] */
slang_oper_while, /* "while" [cond] [body] */
slang_operation_type type;
struct slang_operation_ *children;
GLuint num_children;
- GLfloat literal; /**< Used for float, int and bool values */
- slang_atom a_id; /**< type: asm, identifier, call, field */
- slang_variable_scope *locals; /**< local vars for scope */
+ GLfloat literal[4]; /**< Used for float, int and bool values */
+ slang_atom a_id; /**< type: asm, identifier, call, field */
+ slang_variable_scope *locals; /**< local vars for scope */
+ struct slang_function_ *fun; /**< If type == slang_oper_call */
+ struct slang_variable_ *var; /**< If type == slang_oper_identier */
+ slang_fully_specified_type *datatype; /**< Type of this operation */
+ slang_assembly_typeinfo ti;
} slang_operation;
extern slang_operation *
slang_operation_new(GLuint count);
+extern slang_operation *
+slang_operation_grow(GLuint *numChildren, slang_operation **children);
+
+extern slang_operation *
+slang_operation_insert(GLuint *numChildren, slang_operation **children,
+ GLuint pos);
+
#ifdef __cplusplus
}
* slang_variable_scope
*/
+slang_variable_scope *
+_slang_variable_scope_new(slang_variable_scope *parent)
+{
+ slang_variable_scope *s;
+ s = (slang_variable_scope *) _mesa_calloc(sizeof(slang_variable_scope));
+ s->outer_scope = parent;
+ return s;
+}
+
+
GLvoid
_slang_variable_scope_ctr(slang_variable_scope * self)
{
var->array_len = 0;
var->initializer = NULL;
var->address = ~0;
- var->address2 = 0;
var->size = 0;
var->global = GL_FALSE;
+ var->declared = GL_FALSE;
+ var->used = GL_FALSE;
+ var->aux = NULL;
return 1;
}
z.a_name = y->a_name;
z.array_len = y->array_len;
if (y->initializer != NULL) {
- z.initializer =
- (slang_operation *) slang_alloc_malloc(sizeof(slang_operation));
+ z.initializer
+ = (slang_operation *) slang_alloc_malloc(sizeof(slang_operation));
if (z.initializer == NULL) {
slang_variable_destruct(&z);
return 0;
GLuint array_len; /**< only if type == slang_spec_array */
struct slang_operation_ *initializer; /**< Optional initializer code */
GLuint address; /**< Storage location */
- GLuint address2; /**< Storage location */
GLuint size; /**< Variable's size in bytes */
GLboolean global; /**< A global var? */
+ GLboolean used; /**< Ever referenced by code? */
+ GLboolean declared; /**< Declared by slang_variable_decl? */
void *aux; /**< Used during code gen */
} slang_variable;
struct slang_variable_scope_ *outer_scope;
} slang_variable_scope;
+
+extern slang_variable_scope *
+_slang_variable_scope_new(slang_variable_scope *parent);
+
extern GLvoid
_slang_variable_scope_ctr(slang_variable_scope *);
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 2005-2007 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.
+ */
+
+/**
+ * \file slang_emit.c
+ * Emit program instructions (PI code) from IR trees.
+ * \author Brian Paul
+ */
+
+#include "imports.h"
+#include "context.h"
+#include "get.h"
+#include "macros.h"
+#include "program.h"
+#include "program_instruction.h"
+#include "slang_emit.h"
+
+
+/**
+ * Assembly and IR info
+ */
+typedef struct
+{
+ slang_ir_opcode IrOpcode;
+ const char *IrName;
+ gl_inst_opcode InstOpcode;
+ GLuint ResultSize, NumParams;
+} slang_ir_info;
+
+
+
+static slang_ir_info IrInfo[] = {
+ /* binary ops */
+ { IR_ADD, "IR_ADD", OPCODE_ADD, 4, 2 },
+ { IR_SUB, "IR_SUB", OPCODE_SUB, 4, 2 },
+ { IR_MUL, "IR_MUL", OPCODE_MUL, 4, 2 },
+ { IR_DIV, "IR_DIV", OPCODE_NOP, 0, 2 }, /* XXX broke */
+ { IR_DOT4, "IR_DOT_4", OPCODE_DP4, 1, 2 },
+ { IR_DOT3, "IR_DOT_3", OPCODE_DP3, 1, 2 },
+ { IR_CROSS, "IR_CROSS", OPCODE_XPD, 3, 2 },
+ { IR_MIN, "IR_MIN", OPCODE_MIN, 4, 2 },
+ { IR_MAX, "IR_MAX", OPCODE_MAX, 4, 2 },
+ { IR_SEQUAL, "IR_SEQUAL", OPCODE_SEQ, 4, 2 },
+ { IR_SNEQUAL, "IR_SNEQUAL", OPCODE_SNE, 4, 2 },
+ { IR_SGE, "IR_SGE", OPCODE_SGE, 4, 2 },
+ { IR_SGT, "IR_SGT", OPCODE_SGT, 4, 2 },
+ { IR_POW, "IR_POW", OPCODE_POW, 1, 2 },
+ /* unary ops */
+ { IR_I_TO_F, "IR_I_TO_F", OPCODE_NOP, 1, 1 },
+ { IR_EXP, "IR_EXP", OPCODE_EXP, 1, 1 },
+ { IR_EXP2, "IR_EXP2", OPCODE_EX2, 1, 1 },
+ { IR_LOG2, "IR_LOG2", OPCODE_LG2, 1, 1 },
+ { IR_RSQ, "IR_RSQ", OPCODE_RSQ, 1, 1 },
+ { IR_RCP, "IR_RCP", OPCODE_RCP, 1, 1 },
+ { IR_FLOOR, "IR_FLOOR", OPCODE_FLR, 4, 1 },
+ { IR_FRAC, "IR_FRAC", OPCODE_FRC, 4, 1 },
+ { IR_ABS, "IR_ABS", OPCODE_ABS, 4, 1 },
+ { IR_SIN, "IR_SIN", OPCODE_SIN, 1, 1 },
+ { IR_COS, "IR_COS", OPCODE_COS, 1, 1 },
+ /* other */
+ { IR_SEQ, "IR_SEQ", 0, 0, 0 },
+ { IR_LABEL, "IR_LABEL", 0, 0, 0 },
+ { IR_JUMP, "IR_JUMP", 0, 0, 0 },
+ { IR_CJUMP, "IR_CJUMP", 0, 0, 0 },
+ { IR_CALL, "IR_CALL", 0, 0, 0 },
+ { IR_MOVE, "IR_MOVE", 0, 0, 1 },
+ { IR_LESS, "IR_LESS", 0, 1, 2 },
+ { IR_NOT, "IR_NOT", 0, 1, 1 },
+ { IR_VAR, "IR_VAR", 0, 0, 0 },
+ { IR_VAR_DECL, "IR_VAR_DECL", 0, 0, 0 },
+ { IR_FLOAT, "IR_FLOAT", 0, 0, 0 },
+ { IR_FIELD, "IR_FIELD", 0, 0, 0 },
+ { IR_NOP, NULL, OPCODE_NOP, 0, 0 }
+};
+
+
+static slang_ir_info *
+slang_find_ir_info(slang_ir_opcode opcode)
+{
+ GLuint i;
+ for (i = 0; IrInfo[i].IrName; i++) {
+ if (IrInfo[i].IrOpcode == opcode) {
+ return IrInfo + i;
+ }
+ }
+ return NULL;
+}
+
+static const char *
+slang_ir_name(slang_ir_opcode opcode)
+{
+ return slang_find_ir_info(opcode)->IrName;
+}
+
+
+slang_ir_storage *
+_slang_new_ir_storage(enum register_file file, GLint index, GLint size)
+{
+ slang_ir_storage *st;
+ st = (slang_ir_storage *) _mesa_calloc(sizeof(slang_ir_storage));
+ if (st) {
+ st->File = file;
+ st->Index = index;
+ st->Size = size;
+ }
+ return st;
+}
+
+
+static const char *
+swizzle_string(GLuint swizzle)
+{
+ static char s[6];
+ GLuint i;
+ s[0] = '.';
+ for (i = 1; i < 5; i++) {
+ s[i] = "xyzw"[GET_SWZ(swizzle, i-1)];
+ }
+ s[i] = 0;
+ return s;
+}
+
+static const char *
+writemask_string(GLuint writemask)
+{
+ static char s[6];
+ GLuint i, j = 0;
+ s[j++] = '.';
+ for (i = 0; i < 4; i++) {
+ if (writemask & (1 << i))
+ s[j++] = "xyzw"[i];
+ }
+ s[j] = 0;
+ return s;
+}
+
+static const char *
+storage_string(const slang_ir_storage *st)
+{
+ static const char *files[] = {
+ "TEMP",
+ "LOCAL_PARAM",
+ "ENV_PARAM",
+ "STATE",
+ "INPUT",
+ "OUTPUT",
+ "NAMED_PARAM",
+ "CONSTANT",
+ "UNIFORM",
+ "WRITE_ONLY",
+ "ADDRESS",
+ "UNDEFINED"
+ };
+ static char s[100];
+#if 0
+ if (st->Size == 1)
+ sprintf(s, "%s[%d]", files[st->File], st->Index);
+ else
+ sprintf(s, "%s[%d..%d]", files[st->File], st->Index,
+ st->Index + st->Size - 1);
+#endif
+ sprintf(s, "%s", files[st->File]);
+ return s;
+}
+
+
+static GLuint
+sizeof_struct(const slang_struct *s)
+{
+ return 0;
+}
+
+
+static GLuint
+sizeof_type(const slang_fully_specified_type *t)
+{
+ switch (t->specifier.type) {
+ case slang_spec_void:
+ abort();
+ return 0;
+ case slang_spec_bool:
+ return 1;
+ case slang_spec_bvec2:
+ return 2;
+ case slang_spec_bvec3:
+ return 3;
+ case slang_spec_bvec4:
+ return 4;
+ case slang_spec_int:
+ return 1;
+ case slang_spec_ivec2:
+ return 2;
+ case slang_spec_ivec3:
+ return 3;
+ case slang_spec_ivec4:
+ return 4;
+ case slang_spec_float:
+ return 1;
+ case slang_spec_vec2:
+ return 2;
+ case slang_spec_vec3:
+ return 3;
+ case slang_spec_vec4:
+ return 4;
+ case slang_spec_mat2:
+ return 2 * 2;
+ case slang_spec_mat3:
+ return 3 * 3;
+ case slang_spec_mat4:
+ return 4 * 4;
+ case slang_spec_sampler1D:
+ case slang_spec_sampler2D:
+ case slang_spec_sampler3D:
+ case slang_spec_samplerCube:
+ case slang_spec_sampler1DShadow:
+ case slang_spec_sampler2DShadow:
+ abort();
+ return 0;
+ case slang_spec_struct:
+ return sizeof_struct(t->specifier._struct);
+ case slang_spec_array:
+ return 1; /* XXX */
+ default:
+ abort();
+ return 0;
+ }
+ return 0;
+}
+
+
+#define IND 0
+void
+slang_print_ir(const slang_ir_node *n, int indent)
+{
+ int i;
+ if (!n)
+ return;
+#if !IND
+ if (n->Opcode != IR_SEQ)
+#else
+ printf("%3d:", indent);
+#endif
+ for (i = 0; i < indent; i++)
+ printf(" ");
+
+ switch (n->Opcode) {
+ case IR_SEQ:
+#if IND
+ printf("SEQ store %p\n", (void*) n->Store);
+#endif
+ assert(n->Children[0]);
+ assert(n->Children[1]);
+ slang_print_ir(n->Children[0], indent + IND);
+ slang_print_ir(n->Children[1], indent + IND);
+ break;
+ case IR_MOVE:
+ printf("MOVE (writemask = %s)\n", writemask_string(n->Writemask));
+ slang_print_ir(n->Children[0], indent+3);
+ slang_print_ir(n->Children[1], indent+3);
+ break;
+ case IR_LABEL:
+ printf("LABEL: %s\n", n->Target);
+ break;
+ case IR_JUMP:
+ printf("JUMP %s\n", n->Target);
+ break;
+ case IR_CJUMP:
+ printf("CJUMP %s\n", n->Target);
+ slang_print_ir(n->Children[0], indent+3);
+ break;
+ case IR_VAR:
+ printf("VAR %s%s at %s store %p\n",
+ (char *) n->Var->a_name, swizzle_string(n->Swizzle),
+ storage_string(n->Store), (void*) n->Store);
+ break;
+ case IR_VAR_DECL:
+ printf("VAR_DECL %s (%p) at %s store %p\n",
+ (char *) n->Var->a_name, (void*) n->Var, storage_string(n->Store),
+ (void*) n->Store);
+ break;
+ case IR_FIELD:
+ printf("FIELD %s of\n", n->Target);
+ slang_print_ir(n->Children[0], indent+3);
+ break;
+ case IR_CALL:
+ printf("ASMCALL %s(%d args)\n", n->Target, n->Swizzle);
+ break;
+ case IR_FLOAT:
+ printf("FLOAT %f %f %f %f\n",
+ n->Value[0], n->Value[1], n->Value[2], n->Value[3]);
+ break;
+ case IR_I_TO_F:
+ printf("INT_TO_FLOAT %d\n", (int) n->Value[0]);
+ break;
+ default:
+ printf("%s (%p, %p)\n", slang_ir_name(n->Opcode),
+ (void*) n->Children[0], (void*) n->Children[1]);
+ slang_print_ir(n->Children[0], indent+3);
+ slang_print_ir(n->Children[1], indent+3);
+ }
+}
+
+
+static GLint
+alloc_temporary(slang_gen_context *gc)
+{
+ GLuint i;
+ for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
+ if (!gc->TempUsed[i]) {
+ gc->TempUsed[i] = GL_TRUE;
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+static GLboolean
+is_temporary(const slang_gen_context *gc, const slang_ir_storage *st)
+{
+ if (st->File == PROGRAM_TEMPORARY && gc->TempUsed[st->Index])
+ return gc->TempUsed[st->Index];
+ else
+ return GL_FALSE;
+}
+
+
+static void
+free_temporary(slang_gen_context *gc, GLuint r)
+{
+ if (gc->TempUsed[r])
+ gc->TempUsed[r] = GL_FALSE;
+}
+
+
+
+static GLint
+slang_find_input(GLenum target, const char *name, GLint index)
+{
+ struct input_info {
+ const char *Name;
+ GLuint Attrib;
+ };
+ static const struct input_info vertInputs[] = {
+ { "gl_Vertex", VERT_ATTRIB_POS },
+ { "gl_Normal", VERT_ATTRIB_NORMAL },
+ { "gl_Color", VERT_ATTRIB_COLOR0 },
+ { "gl_SecondaryColor", VERT_ATTRIB_COLOR1 },
+ { NULL, 0 }
+ };
+ static const struct input_info fragInputs[] = {
+ { NULL, 0 }
+ };
+ const struct input_info *inputs;
+ GLuint i;
+
+ if (target == GL_VERTEX_PROGRAM_ARB) {
+ inputs = vertInputs;
+ }
+ else {
+ assert(target == GL_FRAGMENT_PROGRAM_ARB);
+ inputs = fragInputs;
+ }
+
+ for (i = 0; inputs[i].Name; i++) {
+ if (strcmp(inputs[i].Name, name) == 0) {
+ /* found */
+ return inputs[i].Attrib;
+ }
+ }
+ return -1;
+}
+
+
+static GLint
+slang_find_output(GLenum target, const char *name, GLint index)
+{
+ struct output_info {
+ const char *Name;
+ GLuint Attrib;
+ };
+ static const struct output_info vertOutputs[] = {
+ { "gl_Position", VERT_RESULT_HPOS },
+ { "gl_FrontColor", VERT_RESULT_COL0 },
+ { "gl_BackColor", VERT_RESULT_BFC0 },
+ { "gl_FrontSecondaryColor", VERT_RESULT_COL1 },
+ { "gl_BackSecondaryColor", VERT_RESULT_BFC1 },
+ { "gl_TexCoord", VERT_RESULT_TEX0 }, /* XXX indexed */
+ { "gl_FogFragCoord", VERT_RESULT_FOGC },
+ { NULL, 0 }
+ };
+ static const struct output_info fragOutputs[] = {
+ { "gl_FragColor", FRAG_RESULT_COLR },
+ { NULL, 0 }
+ };
+ const struct output_info *outputs;
+ GLuint i;
+
+ if (target == GL_VERTEX_PROGRAM_ARB) {
+ outputs = vertOutputs;
+ }
+ else {
+ assert(target == GL_FRAGMENT_PROGRAM_ARB);
+ outputs = fragOutputs;
+ }
+
+ for (i = 0; outputs[i].Name; i++) {
+ if (strcmp(outputs[i].Name, name) == 0) {
+ /* found */
+ return outputs[i].Attrib;
+ }
+ }
+ return -1;
+}
+
+
+/**
+ * Lookup a named constant and allocate storage for the parameter in
+ * the given parameter list.
+ * \return position of the constant in the paramList.
+ */
+static GLint
+slang_lookup_constant(const char *name, GLint index,
+ struct gl_program_parameter_list *paramList)
+{
+ struct constant_info {
+ const char *Name;
+ const GLenum Token;
+ };
+ static const struct constant_info info[] = {
+ { "gl_MaxLights", GL_MAX_LIGHTS },
+ { "gl_MaxClipPlanes", GL_MAX_CLIP_PLANES },
+ { "gl_MaxTextureUnits", GL_MAX_TEXTURE_UNITS },
+ { "gl_MaxTextureCoords", GL_MAX_TEXTURE_COORDS },
+ { "gl_MaxVertexAttribs", GL_MAX_VERTEX_ATTRIBS },
+ { "gl_MaxVertexUniformComponents", GL_MAX_VERTEX_UNIFORM_COMPONENTS },
+ { "gl_MaxVaryingFloats", GL_MAX_VARYING_FLOATS },
+ { "gl_MaxVertexTextureImageUnits", GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS },
+ { "gl_MaxTextureImageUnits", GL_MAX_TEXTURE_IMAGE_UNITS },
+ { "gl_MaxFragmentUniformComponents", GL_MAX_FRAGMENT_UNIFORM_COMPONENTS },
+ { "gl_MaxCombinedTextureImageUnits", GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS },
+ { NULL, 0 }
+ };
+ GLuint i;
+ GLuint swizzle; /* XXX use this */
+
+ for (i = 0; info[i].Name; i++) {
+ if (strcmp(info[i].Name, name) == 0) {
+ /* found */
+ GLfloat value = -1.0;
+ GLint pos;
+ _mesa_GetFloatv(info[i].Token, &value);
+ ASSERT(value >= 0.0); /* sanity check that glGetFloatv worked */
+ pos = _mesa_add_unnamed_constant(paramList, &value, 1, &swizzle);
+ return pos;
+ }
+ }
+ return -1;
+}
+
+
+/**
+ * Determine if 'name' is a state variable. If so, create a new program
+ * parameter for it, and return the param's index. Else, return -1.
+ */
+static GLint
+slang_lookup_statevar(const char *name, GLint index,
+ struct gl_program_parameter_list *paramList)
+{
+ struct state_info {
+ const char *Name;
+ const GLuint NumRows; /** for matrices */
+ const GLuint Swizzle;
+ const GLint Indexes[6];
+ };
+ static const struct state_info state[] = {
+ { "gl_ModelViewMatrix", 4, SWIZZLE_NOOP,
+ { STATE_MATRIX, STATE_MODELVIEW, 0, 0, 0, STATE_MATRIX_TRANSPOSE } },
+ { "gl_NormalMatrix", 3, SWIZZLE_NOOP,
+ { STATE_MATRIX, STATE_MODELVIEW, 0, 0, 0, STATE_MATRIX_INVTRANS } },
+ { "gl_ProjectionMatrix", 4, SWIZZLE_NOOP,
+ { STATE_MATRIX, STATE_PROJECTION, 0, 0, 0, STATE_MATRIX_TRANSPOSE } },
+ { "gl_ModelViewProjectionMatrix", 4, SWIZZLE_NOOP,
+ { STATE_MATRIX, STATE_MVP, 0, 0, 0, STATE_MATRIX_TRANSPOSE } },
+ { "gl_TextureMatrix", 4, SWIZZLE_NOOP,
+ { STATE_MATRIX, STATE_TEXTURE, 0, 0, 0, STATE_MATRIX_TRANSPOSE } },
+ { NULL, 0, 0, {0, 0, 0, 0, 0, 0} }
+ };
+ GLuint i;
+
+ for (i = 0; state[i].Name; i++) {
+ if (strcmp(state[i].Name, name) == 0) {
+ /* found */
+ if (paramList) {
+ if (state[i].NumRows > 1) {
+ /* a matrix */
+ GLuint j;
+ GLint pos[4], indexesCopy[6];
+ /* make copy of state tokens */
+ for (j = 0; j < 6; j++)
+ indexesCopy[j] = state[i].Indexes[j];
+ /* load rows */
+ for (j = 0; j < state[i].NumRows; j++) {
+ indexesCopy[3] = indexesCopy[4] = j; /* jth row of matrix */
+ pos[j] = _mesa_add_state_reference(paramList, indexesCopy);
+ assert(pos[j] >= 0);
+ }
+ return pos[0];
+ }
+ else {
+ /* non-matrix state */
+ GLint pos
+ = _mesa_add_state_reference(paramList, state[i].Indexes);
+ assert(pos >= 0);
+ return pos;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+
+static GLint
+slang_alloc_uniform(struct gl_program *prog, const char *name)
+{
+ GLint i = _mesa_add_uniform(prog->Parameters, name, 4);
+ return i;
+}
+
+
+static GLint
+slang_alloc_varying(struct gl_program *prog, const char *name)
+{
+ GLint i = _mesa_add_varying(prog->Varying, name, 4); /* XXX fix size */
+ if (prog->Target == GL_VERTEX_PROGRAM_ARB) {
+ i += VERT_RESULT_VAR0;
+ prog->OutputsWritten |= (1 << i);
+ }
+ else {
+ i += FRAG_ATTRIB_VAR0;
+ prog->InputsRead |= (1 << i);
+ }
+ return i;
+}
+
+
+/**
+ * Allocate temporary storage for an intermediate result (such as for
+ * a multiply or add, etc.
+ */
+static void
+slang_alloc_temp_storage(slang_gen_context *gc, slang_ir_node *n, GLint size)
+{
+ GLint indx;
+ assert(!n->Var);
+ assert(!n->Store);
+ assert(size > 0);
+ indx = alloc_temporary(gc);
+ n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, indx, size);
+}
+
+
+/**
+ * Allocate storage info for an IR node (n->Store).
+ * We may do any of the following:
+ * 1. Compute Store->File/Index for program inputs/outputs/uniforms/etc.
+ * 2. Allocate storage for user-declared variables.
+ * 3. Allocate intermediate/unnamed storage for complex expressions.
+ * 4. other?
+ *
+ * If gc or prog is NULL, we may only be able to determine the Store->File
+ * but not an Index (register).
+ */
+void
+slang_resolve_storage(slang_gen_context *gc, slang_ir_node *n,
+ struct gl_program *prog)
+{
+ int k = 0;
+ if (!n->Store) {
+ /**assert(n->Var);**/
+ if (n->Var && n->Var->aux) {
+ /* node storage info = var storage info */
+ n->Store = (slang_ir_storage *) n->Var->aux;
+ }
+ else {
+ /* alloc new storage info */
+ n->Store = _slang_new_ir_storage(PROGRAM_UNDEFINED, -1, -5);
+ k = 1;
+ /*XXX n->Store->Size = sizeof(var's type) */
+ if (n->Var)
+ n->Var->aux = n->Store;
+ }
+ }
+
+ if (n->Opcode == IR_VAR_DECL) {
+ /* allocate storage for a user's variable */
+ assert(n->Var);
+ if (n->Store->Index < 0) {
+ assert(gc);
+ n->Store->File = PROGRAM_TEMPORARY;
+ n->Store->Index = alloc_temporary(gc);
+ n->Store->Size = sizeof_type(&n->Var->type);
+ printf("alloc var %s storage at %d (size %d)\n",
+ (char *) n->Var->a_name,
+ n->Store->Index,
+ n->Store->Size);
+ assert(n->Store->Size > 0);
+ n->Var->declared = GL_TRUE;
+ }
+ return;
+ }
+
+ if (n->Opcode == IR_VAR && n->Store->File == PROGRAM_UNDEFINED) {
+ /* try to determine the storage for this variable */
+ GLint i;
+
+ assert(n->Var);
+ assert(prog);
+
+#if 0
+ assert(n->Var->declared ||
+ n->Var->type.qualifier == slang_qual_uniform ||
+ n->Var->type.qualifier == slang_qual_varying ||
+ n->Var->type.qualifier == slang_qual_fixedoutput ||
+ n->Var->type.qualifier == slang_qual_attribute ||
+ n->Var->type.qualifier == slang_qual_out ||
+ n->Var->type.qualifier == slang_qual_const);
+#endif
+
+ i = slang_find_input(prog->Target, (char *) n->Var->a_name, 0);
+ if (i >= 0) {
+ n->Store->File = PROGRAM_INPUT;
+ n->Store->Index = i;
+ n->Store->Size = sizeof_type(&n->Var->type);
+ assert(n->Store->Size > 0);
+ prog->InputsRead |= (1 << i);
+ return;
+ }
+
+ i = slang_find_output(prog->Target, (char *) n->Var->a_name, 0);
+ if (i >= 0) {
+ n->Store->File = PROGRAM_OUTPUT;
+ n->Store->Index = i;
+ n->Store->Size = sizeof_type(&n->Var->type);
+ prog->OutputsWritten |= (1 << i);
+ return;
+ }
+
+ i = slang_lookup_statevar((char *) n->Var->a_name, 0, prog->Parameters);
+ if (i >= 0) {
+ n->Store->File = PROGRAM_STATE_VAR;
+ n->Store->Index = i;
+ n->Store->Size = sizeof_type(&n->Var->type);
+ return;
+ }
+
+ i = slang_lookup_constant((char *) n->Var->a_name, 0, prog->Parameters);
+ if (i >= 0) {
+ n->Store->File = PROGRAM_CONSTANT;
+ n->Store->Index = i;
+ n->Store->Size = sizeof_type(&n->Var->type);
+ return;
+ }
+
+ /* probably a uniform or varying */
+ if (n->Var->type.qualifier == slang_qual_uniform) {
+ i = slang_alloc_uniform(prog, (char *) n->Var->a_name);
+ if (i >= 0) {
+ n->Store->File = PROGRAM_UNIFORM;
+ n->Store->Index = i;
+ n->Store->Size = sizeof_type(&n->Var->type);
+ return;
+ }
+ }
+ else if (n->Var->type.qualifier == slang_qual_varying) {
+ i = slang_alloc_varying(prog, (char *) n->Var->a_name);
+ if (i >= 0) {
+ if (prog->Target == GL_VERTEX_PROGRAM_ARB)
+ n->Store->File = PROGRAM_OUTPUT;
+ else
+ n->Store->File = PROGRAM_INPUT;
+ n->Store->Size = sizeof_type(&n->Var->type);
+ n->Store->Index = i;
+ return;
+ }
+ }
+
+ /* what is this?!? */
+ /*
+ abort();
+ */
+ }
+
+ if (n->Store->File == PROGRAM_TEMPORARY && n->Store->Index < 0) {
+ /* unnamed intermediate temporary */
+ if (gc)
+ n->Store->Index = alloc_temporary(gc);
+ return;
+ }
+
+ if (gc && n->Store->File == PROGRAM_UNDEFINED && n->Store->Size < 0) {
+ abort();
+ }
+}
+
+
+static slang_ir_storage *
+alloc_constant(const GLfloat v[], GLuint size, struct gl_program *prog)
+{
+ GLuint swizzle;
+ GLint ind = _mesa_add_unnamed_constant(prog->Parameters, v, size, &swizzle);
+ slang_ir_storage *st = _slang_new_ir_storage(PROGRAM_CONSTANT, ind, size);
+ return st;
+}
+
+
+/**
+ * Swizzle a swizzle.
+ */
+static GLuint
+swizzle_compose(GLuint swz1, GLuint swz2)
+{
+ GLuint i, swz, s[4];
+ for (i = 0; i < 4; i++) {
+ GLuint c = GET_SWZ(swz1, i);
+ s[i] = GET_SWZ(swz2, c);
+ }
+ swz = MAKE_SWIZZLE4(s[0], s[1], s[2], s[3]);
+ return swz;
+}
+
+
+/**
+ * Convert IR storage to an instruction dst register.
+ */
+static void
+storage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st,
+ GLuint writemask)
+{
+ static const GLuint defaultWritemask[4] = {
+ WRITEMASK_X,
+ WRITEMASK_X | WRITEMASK_Y,
+ WRITEMASK_X | WRITEMASK_Y | WRITEMASK_Z,
+ WRITEMASK_X | WRITEMASK_Y | WRITEMASK_Z | WRITEMASK_W
+ };
+ dst->File = st->File;
+ dst->Index = st->Index;
+ assert(st->Size >= 1);
+ assert(st->Size <= 4);
+ dst->WriteMask = defaultWritemask[st->Size - 1] & writemask;
+}
+
+
+/**
+ * Convert IR storage to an instruction src register.
+ */
+static void
+storage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st,
+ GLuint swizzle)
+{
+ static const GLuint defaultSwizzle[4] = {
+ MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X),
+ MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W),
+ MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W),
+ MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W)
+ };
+
+ src->File = st->File;
+ src->Index = st->Index;
+ assert(st->Size >= 1);
+ assert(st->Size <= 4);
+ /* XXX swizzling logic here may need some work */
+ /*src->Swizzle = swizzle_compose(swizzle, defaultSwizzle[st->Size - 1]);*/
+ if (swizzle != SWIZZLE_NOOP)
+ src->Swizzle = swizzle;
+ else
+ src->Swizzle = defaultSwizzle[st->Size - 1];
+}
+
+
+
+/**
+ * Add new instruction at end of given program.
+ * \param prog the program to append instruction onto
+ * \param opcode opcode for the new instruction
+ * \return pointer to the new instruction
+ */
+static struct prog_instruction *
+new_instruction(struct gl_program *prog, gl_inst_opcode opcode)
+{
+ struct prog_instruction *inst;
+ prog->Instructions = _mesa_realloc_instructions(prog->Instructions,
+ prog->NumInstructions,
+ prog->NumInstructions + 1);
+ inst = prog->Instructions + prog->NumInstructions;
+ prog->NumInstructions++;
+ _mesa_init_instructions(inst, 1);
+ inst->Opcode = opcode;
+ return inst;
+}
+
+
+static struct prog_instruction *
+gen(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog);
+
+
+/**
+ * Generate code for a simple binary-op instruction.
+ */
+static struct prog_instruction *
+gen_binop(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
+{
+ struct prog_instruction *inst;
+ const slang_ir_info *info = slang_find_ir_info(n->Opcode);
+ assert(info);
+
+ gen(gc, n->Children[0], prog);
+ gen(gc, n->Children[1], prog);
+ inst = new_instruction(prog, info->InstOpcode);
+ /* alloc temp storage for the result: */
+ if (!n->Store || n->Store->File == PROGRAM_UNDEFINED) {
+#if 1
+ slang_alloc_temp_storage(gc, n, info->ResultSize);
+#else
+ slang_resolve_storage(gc, n, prog);
+#endif
+ }
+ storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+ storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store,
+ n->Children[0]->Swizzle);
+ storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store,
+ n->Children[1]->Swizzle);
+ inst->Comment = n->Comment;
+ return inst;
+}
+
+
+static struct prog_instruction *
+gen_unop(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
+{
+ struct prog_instruction *inst;
+ const slang_ir_info *info = slang_find_ir_info(n->Opcode);
+ assert(info);
+
+ assert(info->NumParams == 1);
+
+ gen(gc, n->Children[0], prog);
+
+ inst = new_instruction(prog, info->InstOpcode);
+ /*slang_resolve_storage(gc, n, prog);*/
+
+ if (!n->Store)
+ slang_alloc_temp_storage(gc, n, info->ResultSize);
+
+ storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+
+ storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store,
+ n->Children[0]->Swizzle);
+
+ inst->Comment = n->Comment;
+
+ return inst;
+}
+
+
+static struct prog_instruction *
+gen(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
+{
+ struct prog_instruction *inst;
+ if (!n)
+ return NULL;
+
+ switch (n->Opcode) {
+ case IR_SEQ:
+ assert(n->Children[0]);
+ assert(n->Children[1]);
+ gen(gc, n->Children[0], prog);
+ inst = gen(gc, n->Children[1], prog);
+ n->Store = n->Children[1]->Store;
+ return inst;
+ break;
+ case IR_VAR_DECL:
+ slang_resolve_storage(gc, n, prog);
+ assert(n->Store->Index >= 0);
+ assert(n->Store->Size > 0);
+ break;
+ case IR_VAR:
+ /*printf("Gen: var ref\n");*/
+ {
+ int b = !n->Store || n->Store->Index < 0;
+ if (b)
+ slang_resolve_storage(gc, n, prog);
+ /*assert(n->Store->Index >= 0);*/
+ assert(n->Store->Size > 0);
+ }
+ break;
+ case IR_MOVE:
+ /* rhs */
+ assert(n->Children[1]);
+ inst = gen(gc, n->Children[1], prog);
+ /* lhs */
+ gen(gc, n->Children[0], prog);
+
+#if 1
+ if (inst && is_temporary(gc, n->Children[1]->Store)) {
+ /* Peephole optimization:
+ * Just modify the RHS to put its result into the dest of this
+ * MOVE operation. Then, this MOVE is a no-op.
+ */
+ free_temporary(gc, n->Children[1]->Store->Index);
+ *n->Children[1]->Store = *n->Children[0]->Store;
+ /* fixup the prev (RHS) instruction */
+ storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask);
+ return inst;
+ }
+ else
+#endif
+ {
+ inst = new_instruction(prog, OPCODE_MOV);
+ storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask);
+ storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store,
+ n->Children[1]->Swizzle);
+ if (n->Children[1]->Store->File == PROGRAM_TEMPORARY) {
+ free_temporary(gc, n->Children[1]->Store->Index);
+ }
+ inst->Comment = n->Comment;
+ n->Store = n->Children[0]->Store; /*XXX new */
+ return inst;
+ }
+ break;
+ case IR_ADD:
+ case IR_SUB:
+ case IR_MUL:
+ case IR_DOT4:
+ case IR_DOT3:
+ case IR_CROSS:
+ case IR_MIN:
+ case IR_MAX:
+ case IR_SEQUAL:
+ case IR_SNEQUAL:
+ case IR_SGE:
+ case IR_SGT:
+ case IR_POW:
+ case IR_EXP:
+ case IR_EXP2:
+ return gen_binop(gc, n, prog);
+ break;
+ case IR_RSQ:
+ case IR_RCP:
+ case IR_FLOOR:
+ case IR_FRAC:
+ case IR_ABS:
+ case IR_SIN:
+ case IR_COS:
+ return gen_unop(gc, n, prog);
+ break;
+ case IR_LABEL:
+ /*printf("LAB: %s\n", n->Target);*/
+ break;
+ case IR_JUMP:
+#if 0
+ inst = new_instruction(prog, OPCODE_BRA);
+ inst->Comment = _mesa_strdup(n->Target);
+#endif
+ break;
+ case IR_FLOAT:
+ n->Store = alloc_constant(n->Value, 4, prog); /*XXX fix size */
+ break;
+ default:
+ printf("gen: ?\n");
+ abort();
+ }
+ return NULL;
+}
+
+
+
+GLboolean
+_slang_emit_code(slang_ir_node *n, struct gl_program *prog)
+{
+ slang_gen_context *gc;
+ /*GET_CURRENT_CONTEXT(ctx);*/
+
+ gc = (slang_gen_context *) _mesa_calloc(sizeof(*gc));
+
+ printf("************ Begin generate code\n");
+
+ gen(gc, n, prog);
+
+ {
+ struct prog_instruction *inst;
+ inst = new_instruction(prog, OPCODE_END);
+ }
+
+ printf("************ End generate code (%u inst):\n", prog->NumInstructions);
+
+#if 0
+ _mesa_print_program(prog);
+ _mesa_print_program_parameters(ctx,prog);
+#endif
+
+ _mesa_free(gc);
+
+ return GL_FALSE;
+}
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 2005-2007 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_EMIT_H
+#define SLANG_EMIT_H
+
+
+#include "imports.h"
+#include "slang_compile.h"
+#include "slang_ir.h"
+#include "mtypes.h"
+
+
+typedef struct {
+ GLboolean TempUsed[MAX_PROGRAM_TEMPS];
+} slang_gen_context;
+
+
+extern void
+slang_print_ir(const slang_ir_node *n, int indent);
+
+
+extern slang_ir_storage *
+_slang_new_ir_storage(enum register_file file, GLint index, GLint size);
+
+
+extern void
+slang_resolve_storage(slang_gen_context *gc, slang_ir_node *n,
+ struct gl_program *prog);
+
+extern GLboolean
+_slang_emit_code(slang_ir_node *n, struct gl_program *prog);
+
+
+#endif /* SLANG_EMIT_H */
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+#include "imports.h"
+#include "slang_error.h"
+
+
+static char ErrorText[10000];
+static char FormattedErrorText[10000];
+static int ErrorPos;
+
+
+void
+_slang_reset_error(void)
+{
+ ErrorText[0] = 0;
+ ErrorPos = -1;
+}
+
+
+/**
+ * Record an error message, if one hasn't been recorded already.
+ */
+void
+_slang_record_error(const char *msg1, const char *msg2,
+ GLint pos, const char *file, int line)
+{
+ /* don't overwrite a previously recorded error */
+ if (!ErrorText[0]) {
+ _mesa_sprintf(ErrorText, "%s %s", msg1, msg2);
+ ErrorPos = -1;
+#ifdef DEBUG
+ fprintf(stderr, "Mesa shader compile error: %s %s at %d (%s line %d)\n",
+ msg1, msg2, pos, file, line);
+#endif
+ }
+}
+
+
+/**
+ * Return formatted error text.
+ */
+const char *
+_slang_error_text(void)
+{
+ /*
+ * NVIDIA formats errors like this:
+ * (LINE_NUMBER) : error ERROR_CODE: ERROR_TEXT
+ * Example:
+ * (7) : error C1048: invalid character 'P' in swizzle "P"
+ */
+ _mesa_sprintf(FormattedErrorText,
+ "(%d) : error: %s", ErrorPos, ErrorText);
+ return FormattedErrorText;
+}
+
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 2005-2006 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_ERROR_H
+#define SLANG_ERROR_H
+
+
+extern void
+_slang_reset_error(void);
+
+
+extern void
+_slang_record_error(const char *msg1, const char *msg2,
+ GLint pos, const char *file, int line);
+
+
+extern const char *
+_slang_error_text(void);
+
+
+/**
+ * Record a compilation error, single string message.
+ */
+#define RETURN_ERROR(MSG, POS) \
+do { \
+ _slang_record_error(MSG, "", POS, __FILE__, __LINE__); \
+ return GL_FALSE; \
+} while (0)
+
+
+/**
+ * Record a compilation error, two-string message.
+ */
+#define RETURN_ERROR2(MSG1, MSG2, POS) \
+do { \
+ _slang_record_error(MSG1, MSG2, POS, __FILE__, __LINE__); \
+ return GL_FALSE; \
+} while (0)
+
+
+/**
+ * Record a nil error. Either a real error message or out of memory should
+ * have already been recorded.
+ */
+#define RETURN_NIL() \
+do { \
+ _slang_record_error("unknown", "", -1, __FILE__, __LINE__); \
+ return GL_FALSE; \
+} while (0)
+
+
+/**
+ * Used to report an out of memory condition.
+ */
+#define RETURN_OUT_OF_MEMORY() \
+do { \
+ _slang_record_error("Out of memory", "", -1, __FILE__, __LINE__); \
+ return GL_FALSE; \
+} while (0)
+
+
+
+
+#endif /* SLANG_ERROR_H */
case slang_asm_int_copy:
case slang_asm_bool_copy:
/* store top value on stack to memory */
+#if 0
{
GLuint address
= (stack[mach->sp + a->param[0] / 4]._addr + a->param[1]) / 4;
GLfloat value = stack[mach->sp]._float;
mach->mem[address]._float = value;
}
+#else
+ mach->mem[(stack[mach->sp + a->param[0] / 4]._addr +a->param[1]) / 4]._float = stack[mach->sp]._float;
+#endif
mach->sp++;
break;
case slang_asm_float_move:
stack[mach->sp + 1]._float += stack[mach->sp]._float;
mach->sp++;
break;
+ case slang_asm_float_subtract:
+ stack[mach->sp + 1]._float -= stack[mach->sp]._float;
+ mach->sp++;
+ break;
case slang_asm_float_multiply:
stack[mach->sp + 1]._float *= stack[mach->sp]._float;
mach->sp++;
case slang_asm_float_log2:
stack[mach->sp]._float = LOG2(stack[mach->sp]._float);
break;
+#if 0
case slang_asm_float_floor:
stack[mach->sp]._float = FLOORF(stack[mach->sp]._float);
break;
case slang_asm_float_ceil:
stack[mach->sp]._float = CEILF(stack[mach->sp]._float);
break;
+#endif
case slang_asm_float_noise1:
stack[mach->sp]._float =
_slang_library_noise1(stack[mach->sp]._float);
-mach->mem[(da + 12) / 4]._float;
}
break;
+#if 0
case slang_asm_vec4_dot:
/* [vec4] | vec4 > [float] */
{
mach->sp += 4;
}
break;
+#endif
case slang_asm_vec4_copy:
/* [vec4] | vec4 > [vec4] */
{
}
}
break;
+ case slang_asm_vec4_dot:
+ case slang_asm_vec3_dot:
+ {
+ /* XXX almost certainly wrong */
+ GLuint da = stack[mach->sp + 4]._addr;
+ mach->mem[da / 4]._float =
+ mach->mem[da / 4]._float * stack[mach->sp]._float +
+ mach->mem[(da + 4) / 4]._float * stack[mach->sp + 1]._float +
+ mach->mem[(da + 8) / 4]._float * stack[mach->sp + 2]._float +
+ mach->mem[(da + 12) / 4]._float * stack[mach->sp + 3]._float;
+ mach->sp += 4;
+ }
+ break;
default:
_mesa_problem(NULL, "bad slang opcode 0x%x", a->type);
return GL_FALSE;
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 2005-2007 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.
+ */
+
+/**
+ * \file slang_ir.h
+ * Mesa GLSL Itermediate Representation tree types and constants.
+ * \author Brian Paul
+ */
+
+
+#ifndef SLANG_IR_H
+#define SLANG_IR_H
+
+
+#include "imports.h"
+#include "slang_compile.h"
+#include "mtypes.h"
+
+
+/**
+ * Intermediate Representation opcode
+ */
+typedef enum
+{
+ IR_NOP = 0,
+ IR_SEQ,
+ IR_LABEL, /* target of a jump or cjump */
+ IR_JUMP, /* unconditional jump */
+ IR_CJUMP, /* conditional jump */
+ IR_CALL,
+ IR_MOVE,
+ IR_ADD,
+ IR_SUB,
+ IR_MUL,
+ IR_DIV,
+ IR_DOT4,
+ IR_DOT3,
+ IR_CROSS,
+ IR_MIN,
+ IR_MAX,
+ IR_SEQUAL,
+ IR_SNEQUAL,
+ IR_SGE,
+ IR_SGT,
+ IR_POW,
+ IR_EXP,
+ IR_EXP2,
+ IR_LOG2,
+ IR_RSQ,
+ IR_RCP,
+ IR_FLOOR,
+ IR_FRAC,
+ IR_ABS,
+ IR_SIN,
+ IR_COS,
+ IR_LESS,
+ IR_NOT,
+ IR_VAR,
+ IR_VAR_DECL,
+ IR_FLOAT,
+ IR_FIELD,
+ IR_I_TO_F
+} slang_ir_opcode;
+
+
+/**
+ * Describes where data storage is allocated.
+ */
+typedef struct
+{
+ enum register_file File; /**< PROGRAM_TEMPORARY, PROGRAM_INPUT, etc */
+ GLint Index; /**< -1 means unallocated */
+ GLint Size; /**< number of floats */
+} slang_ir_storage;
+
+
+/**
+ * Intermediate Representation (IR) tree node
+ */
+typedef struct slang_ir_node_
+{
+ slang_ir_opcode Opcode;
+ struct slang_ir_node_ *Children[2];
+ const char *Comment;
+ const char *Target;
+ GLuint Swizzle;
+ GLuint Writemask; /**< If Op == IR_MOVE */
+ GLfloat Value[4]; /**< If Op == IR_FLOAT */
+ slang_variable *Var;
+ slang_ir_storage *Store;
+} slang_ir_node;
+
+
+#endif /* SLANG_IR_H */
SLANG_COMMON_CODE_MAX
};
+/**
+ * XXX promote this to mtypes.h?
+ */
typedef struct
{
slang_active_variables active_uniforms;
extern GLboolean
_slang_link (slang_program *, slang_code_object **, GLuint);
+
+extern void
+_slang_link2(GLcontext *ctx, GLhandleARB h,
+ struct gl_linked_program *linked);
+
#ifdef __cplusplus
}
#endif
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.6
+ *
+ * Copyright (C) 2006 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.
+ */
+
+/**
+ * \file slang_link.c
+ * slang linker
+ * \author Michal Krol
+ */
+
+#include "imports.h"
+#include "context.h"
+#include "hash.h"
+#include "macros.h"
+#include "program.h"
+#include "shaderobjects.h"
+#include "slang_link.h"
+
+
+
+
+#define RELEASE_GENERIC(x)\
+ (**x)._unknown.Release ((struct gl2_unknown_intf **) (x))
+
+#define RELEASE_CONTAINER(x)\
+ (**x)._generic._unknown.Release ((struct gl2_unknown_intf **) (x))
+
+#define RELEASE_PROGRAM(x)\
+ (**x)._container._generic._unknown.Release ((struct gl2_unknown_intf **) (x))
+
+#define RELEASE_SHADER(x)\
+ (**x)._generic._unknown.Release ((struct gl2_unknown_intf **) (x))
+
+
+
+static struct gl2_unknown_intf **
+lookup_handle(GLcontext * ctx, GLhandleARB handle, enum gl2_uiid uiid,
+ const char *function)
+{
+ struct gl2_unknown_intf **unk;
+
+ /*
+ * Note: _mesa_HashLookup() requires non-zero input values, so the
+ * passed-in handle value must be checked beforehand.
+ */
+ if (handle == 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, function);
+ return NULL;
+ }
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+ unk = (struct gl2_unknown_intf **) _mesa_HashLookup(ctx->Shared->GL2Objects,
+ handle);
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+
+ if (unk == NULL) {
+ _mesa_error(ctx, GL_INVALID_VALUE, function);
+ }
+ else {
+ unk = (**unk).QueryInterface(unk, uiid);
+ if (unk == NULL)
+ _mesa_error(ctx, GL_INVALID_OPERATION, function);
+ }
+ return unk;
+}
+
+#define GET_GENERIC(x, handle, function)\
+ struct gl2_generic_intf **x = (struct gl2_generic_intf **)\
+ lookup_handle (ctx, handle, UIID_GENERIC, function);
+
+#define GET_CONTAINER(x, handle, function)\
+ struct gl2_container_intf **x = (struct gl2_container_intf **)\
+ lookup_handle (ctx, handle, UIID_CONTAINER, function);
+
+#define GET_PROGRAM(x, handle, function)\
+ struct gl2_program_intf **x = (struct gl2_program_intf **)\
+ lookup_handle (ctx, handle, UIID_PROGRAM, function);
+
+#define GET_SHADER(x, handle, function)\
+ struct gl2_shader_intf **x = (struct gl2_shader_intf **)\
+ lookup_handle (ctx, handle, UIID_SHADER, function);
+
+
+static void
+prelink(GLhandleARB programObj, struct gl_linked_program *linked)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ linked->VertexProgram = NULL;
+ linked->FragmentProgram = NULL;
+
+ if (programObj != 0) {
+ GET_PROGRAM(program, programObj, "glUseProgramObjectARB(program)");
+
+ if (program == NULL)
+ return;
+
+ /* XXX terrible hack to find the real vertex/fragment programs */
+ {
+ GLuint handle;
+ GLsizei cnt, i;
+ cnt = (**program)._container.GetAttachedCount((struct gl2_container_intf **) (program));
+
+ for (i = 0; i < cnt; i++) {
+ struct gl2_generic_intf **x
+ = (**program)._container.GetAttached((struct gl2_container_intf **) program, i);
+ handle = (**x).GetName(x);
+ {
+ struct gl_program *prog;
+ GET_SHADER(sha, handle, "foo");
+ if (sha && (*sha)->Program) {
+ prog = (*sha)->Program;
+ if (prog->Target == GL_VERTEX_PROGRAM_ARB)
+ linked->VertexProgram = (struct gl_vertex_program *) prog;
+ else if (prog->Target == GL_FRAGMENT_PROGRAM_ARB)
+ linked->FragmentProgram = (struct gl_fragment_program *) prog;
+ }
+ }
+#if 0
+ if (linked->VertexProgram)
+ printf("Found vert prog %p %d\n",
+ linked->VertexProgram,
+ linked->VertexProgram->Base.NumInstructions);
+ if (linked->FragmentProgram)
+ printf("Found frag prog %p %d\n",
+ linked->FragmentProgram,
+ linked->FragmentProgram->Base.NumInstructions);
+#endif
+ RELEASE_GENERIC(x);
+ }
+ }
+
+ }
+}
+
+
+
+void
+_slang_link2(GLcontext *ctx,
+ GLhandleARB programObj,
+ struct gl_linked_program *linked)
+{
+ struct gl_vertex_program *vertProg;
+ struct gl_fragment_program *fragProg;
+
+ prelink(programObj, linked);
+
+ vertProg = linked->VertexProgram;
+ fragProg = linked->FragmentProgram;
+
+ /* free old linked data, if any */
+ if (linked->NumUniforms > 0) {
+ GLuint i;
+ for (i = 0; i < linked->NumUniforms; i++) {
+ _mesa_free((char *) linked->Uniforms[i].Name);
+ linked->Uniforms[i].Name = NULL;
+ linked->Uniforms[i].Value = NULL;
+ }
+ linked->NumUniforms = 0;
+ }
+
+ /*
+ * Find uniforms.
+ * XXX what about dups?
+ */
+ if (vertProg) {
+ GLuint i;
+ for (i = 0; i < vertProg->Base.Parameters->NumParameters; i++) {
+ struct gl_program_parameter *p
+ = vertProg->Base.Parameters->Parameters + i;
+ if (p->Name) {
+ struct gl_uniform *u = linked->Uniforms + linked->NumUniforms;
+ u->Name = _mesa_strdup(p->Name);
+ u->Value = &vertProg->Base.Parameters->ParameterValues[i][0];
+ linked->NumUniforms++;
+ assert(linked->NumUniforms < MAX_UNIFORMS);
+ }
+ }
+ }
+ if (fragProg) {
+ GLuint i;
+ for (i = 0; i < fragProg->Base.Parameters->NumParameters; i++) {
+ struct gl_program_parameter *p
+ = fragProg->Base.Parameters->Parameters + i;
+ if (p->Name) {
+ struct gl_uniform *u = linked->Uniforms + linked->NumUniforms;
+ u->Name = _mesa_strdup(p->Name);
+ u->Value = &fragProg->Base.Parameters->ParameterValues[i][0];
+ linked->NumUniforms++;
+ assert(linked->NumUniforms < MAX_UNIFORMS);
+ }
+ }
+ }
+
+ /* For varying:
+ * scan both programs for varyings, rewrite programs so they agree
+ * on locations of varyings.
+ */
+
+ /**
+ * Linking should _copy_ the vertex and fragment shader code,
+ * rewriting varying references as we go along...
+ */
+
+ linked->LinkStatus = (vertProg && fragProg);
+}
+
--- /dev/null
+
+/**
+ * Dump/print a slang_operation tree
+ */
+
+
+#include "imports.h"
+#include "slang_compile.h"
+#include "slang_print.h"
+
+
+static void
+spaces(int n)
+{
+ while (n--)
+ printf(" ");
+}
+
+
+static void
+print_type(const slang_fully_specified_type *t)
+{
+ switch (t->qualifier) {
+ case slang_qual_none:
+ /*printf("");*/
+ break;
+ case slang_qual_const:
+ printf("const ");
+ break;
+ case slang_qual_attribute:
+ printf("attrib ");
+ break;
+ case slang_qual_varying:
+ printf("varying ");
+ break;
+ case slang_qual_uniform:
+ printf("uniform ");
+ break;
+ case slang_qual_out:
+ printf("output ");
+ break;
+ case slang_qual_inout:
+ printf("inout ");
+ break;
+ case slang_qual_fixedoutput:
+ printf("fixedoutput");
+ break;
+ case slang_qual_fixedinput:
+ printf("fixedinput");
+ break;
+ default:
+ printf("unknown qualifer!");
+ }
+
+ switch (t->specifier.type) {
+ case slang_spec_void:
+ printf("void");
+ break;
+ case slang_spec_bool:
+ printf("bool");
+ break;
+ case slang_spec_bvec2:
+ printf("bvec2");
+ break;
+ case slang_spec_bvec3:
+ printf("bvec3");
+ break;
+ case slang_spec_bvec4:
+ printf("bvec4");
+ break;
+ case slang_spec_int:
+ printf("int");
+ break;
+ case slang_spec_ivec2:
+ printf("ivec2");
+ break;
+ case slang_spec_ivec3:
+ printf("ivec3");
+ break;
+ case slang_spec_ivec4:
+ printf("ivec4");
+ break;
+ case slang_spec_float:
+ printf("float");
+ break;
+ case slang_spec_vec2:
+ printf("vec2");
+ break;
+ case slang_spec_vec3:
+ printf("vec3");
+ break;
+ case slang_spec_vec4:
+ printf("vec4");
+ break;
+ case slang_spec_mat2:
+ printf("mat2");
+ break;
+ case slang_spec_mat3:
+ printf("mat3");
+ break;
+ case slang_spec_mat4:
+ printf("mat4");
+ break;
+ case slang_spec_sampler1D:
+ printf("sampler1D");
+ break;
+ case slang_spec_sampler2D:
+ printf("sampler2D");
+ break;
+ case slang_spec_sampler3D:
+ printf("sampler3D");
+ break;
+ case slang_spec_samplerCube:
+ printf("samplerCube");
+ break;
+ case slang_spec_sampler1DShadow:
+ printf("sampler1DShadow");
+ break;
+ case slang_spec_sampler2DShadow:
+ printf("sampler2DShadow");
+ break;
+ case slang_spec_struct:
+ printf("struct");
+ break;
+ case slang_spec_array:
+ printf("array");
+ break;
+ default:
+ printf("unknown type");
+ }
+ /*printf("\n");*/
+}
+
+
+static void
+print_variable(const slang_variable *v, int indent)
+{
+ spaces(indent);
+ printf("VAR ");
+ print_type(&v->type);
+ printf(" %s", (char *) v->a_name);
+ if (v->initializer) {
+ printf(" :=\n");
+ slang_print_tree(v->initializer, indent + 3);
+ }
+ else {
+ printf(";\n");
+ }
+}
+
+
+static void
+print_binary(const slang_operation *op, const char *oper, int indent)
+{
+ assert(op->num_children == 2);
+ slang_print_tree(&op->children[0], indent + 3);
+ spaces(indent);
+ printf("%s\n", oper);
+ slang_print_tree(&op->children[1], indent + 3);
+}
+
+
+static void
+print_generic2(const slang_operation *op, const char *oper,
+ const char *s, int indent)
+{
+ int i;
+ if (oper) {
+ spaces(indent);
+ printf("[%p locals %p] %s %s\n", (void*) op, (void*) op->locals, oper, s);
+ }
+ for (i = 0; i < op->num_children; i++) {
+ spaces(indent);
+ printf("//child %d:\n", i);
+ slang_print_tree(&op->children[i], indent);
+ }
+}
+
+static void
+print_generic(const slang_operation *op, const char *oper, int indent)
+{
+ print_generic2(op, oper, "", indent);
+}
+
+
+static const slang_variable_scope *
+find_scope(const slang_variable_scope *s, slang_atom name)
+{
+ GLuint i;
+ for (i = 0; i < s->num_variables; i++) {
+ if (s->variables[i].a_name == name)
+ return s;
+ }
+ if (s->outer_scope)
+ return find_scope(s->outer_scope, name);
+ else
+ return NULL;
+}
+
+static const slang_variable *
+find_var(const slang_variable_scope *s, slang_atom name)
+{
+ GLuint i;
+ for (i = 0; i < s->num_variables; i++) {
+ if (s->variables[i].a_name == name)
+ return &s->variables[i];
+ }
+ if (s->outer_scope)
+ return find_var(s->outer_scope, name);
+ else
+ return NULL;
+}
+
+
+void
+slang_print_tree(const slang_operation *op, int indent)
+{
+ int i;
+
+ switch (op->type) {
+
+ case slang_oper_none:
+ spaces(indent);
+ printf("slang_oper_none\n");
+ break;
+
+ case slang_oper_block_no_new_scope:
+ spaces(indent);
+ printf("{ locals %p\n", (void*)op->locals);
+ print_generic(op, NULL, indent+3);
+ spaces(indent);
+ printf("}\n");
+ break;
+
+ case slang_oper_block_new_scope:
+ spaces(indent);
+ printf("{{ // new scope locals %p\n", (void*)op->locals);
+ print_generic(op, NULL, indent+3);
+ spaces(indent);
+ printf("}}\n");
+ break;
+
+ case slang_oper_variable_decl:
+ assert(op->num_children == 0 || op->num_children == 1);
+ {
+ slang_variable *v;
+ v = _slang_locate_variable(op->locals, op->a_id, GL_TRUE);
+ if (v) {
+ spaces(indent);
+ printf("DECL (locals=%p outer=%p) ", (void*)op->locals, (void*) op->locals->outer_scope);
+ print_type(&v->type);
+ printf(" %s (%p)", (char *) op->a_id,
+ (void *) find_var(op->locals, op->a_id));
+
+ printf(" (in scope %p) ",
+ (void *) find_scope(op->locals, op->a_id));
+ if (op->num_children == 1) {
+ printf(" :=\n");
+ slang_print_tree(&op->children[0], indent + 3);
+ }
+ else if (v->initializer) {
+ printf(" := INITIALIZER\n");
+ slang_print_tree(v->initializer, indent + 3);
+ }
+ else {
+ printf(";\n");
+ }
+ /*
+ spaces(indent);
+ printf("TYPE: ");
+ print_type(&v->type);
+ spaces(indent);
+ printf("ADDR: %d size: %d\n", v->address, v->size);
+ */
+ }
+ else {
+ abort();
+ spaces(indent);
+ printf("DECL %s (anonymous variable!!!!)\n", (char *) op->a_id);
+ /*abort();*/
+ }
+ }
+ break;
+
+ case slang_oper_asm:
+ spaces(indent);
+ printf("ASM: %s\n", (char*) op->a_id);
+ print_generic(op, NULL, indent+3);
+ break;
+
+ case slang_oper_break:
+ spaces(indent);
+ printf("BREAK\n");
+ break;
+
+ case slang_oper_continue:
+ spaces(indent);
+ printf("CONTINUE\n");
+ break;
+
+ case slang_oper_discard:
+ spaces(indent);
+ printf("DISCARD\n");
+ break;
+
+ case slang_oper_return:
+ spaces(indent);
+ printf("RETURN\n");
+ if (op->num_children > 0)
+ slang_print_tree(&op->children[0], indent + 3);
+ break;
+
+ case slang_oper_goto:
+ spaces(indent);
+ printf("GOTO %s\n", (char *) op->a_id);
+ break;
+
+ case slang_oper_label:
+ spaces(indent);
+ printf("LABEL %s\n", (char *) op->a_id);
+ break;
+
+ case slang_oper_expression:
+ spaces(indent);
+ printf("EXPR: locals %p\n", (void*) op->locals);
+ /*print_generic(op, "slang_oper_expression", indent);*/
+ slang_print_tree(&op->children[0], indent + 3);
+ break;
+
+ case slang_oper_if:
+ spaces(indent);
+ printf("IF\n");
+ slang_print_tree(&op->children[0], indent + 3);
+ spaces(indent);
+ printf("THEN\n");
+ slang_print_tree(&op->children[1], indent + 3);
+ spaces(indent);
+ printf("ELSE\n");
+ slang_print_tree(&op->children[2], indent + 3);
+ spaces(indent);
+ printf("ENDIF\n");
+ break;
+
+ case slang_oper_while:
+ assert(op->num_children == 2);
+ spaces(indent);
+ printf("WHILE cond:\n");
+ slang_print_tree(&op->children[0], indent + 3);
+ spaces(indent);
+ printf("WHILE body:\n");
+ slang_print_tree(&op->children[1], indent + 3);
+ break;
+
+ case slang_oper_do:
+ spaces(indent);
+ printf("DO body:\n");
+ slang_print_tree(&op->children[0], indent + 3);
+ spaces(indent);
+ printf("DO cond:\n");
+ slang_print_tree(&op->children[1], indent + 3);
+ break;
+
+ case slang_oper_for:
+ spaces(indent);
+ printf("FOR init:\n");
+ slang_print_tree(&op->children[0], indent + 3);
+ spaces(indent);
+ printf("FOR while:\n");
+ slang_print_tree(&op->children[1], indent + 3);
+ spaces(indent);
+ printf("FOR step:\n");
+ slang_print_tree(&op->children[2], indent + 3);
+ spaces(indent);
+ printf("FOR body:\n");
+ slang_print_tree(&op->children[3], indent + 3);
+ spaces(indent);
+ printf("ENDFOR\n");
+ /*
+ print_generic(op, "FOR", indent + 3);
+ */
+ break;
+
+ case slang_oper_void:
+ spaces(indent);
+ printf("(oper-void)\n");
+ break;
+
+ case slang_oper_literal_bool:
+ spaces(indent);
+ /*printf("slang_oper_literal_bool\n");*/
+ printf("%s\n", op->literal[0] ? "TRUE" : "FALSE");
+ break;
+
+ case slang_oper_literal_int:
+ spaces(indent);
+ /*printf("slang_oper_literal_int\n");*/
+ printf("(%d %d %d %d)\n", (int) op->literal[0], (int) op->literal[1],
+ (int) op->literal[2], (int) op->literal[3]);
+ break;
+
+ case slang_oper_literal_float:
+ spaces(indent);
+ /*printf("slang_oper_literal_float\n");*/
+ printf("(%f %f %f %f)\n", op->literal[0], op->literal[1], op->literal[2],
+ op->literal[3]);
+ break;
+
+ case slang_oper_identifier:
+ spaces(indent);
+ if (op->var && op->var->a_name)
+ printf("VAR %s (in scope %p)\n", (char *) op->var->a_name,
+ (void *) find_scope(op->locals, op->a_id));
+ else
+ printf("VAR' %s (in scope %p)\n", (char *) op->a_id,
+ (void *) find_scope(op->locals, op->a_id));
+ break;
+
+ case slang_oper_sequence:
+ print_generic(op, "COMMA-SEQ", indent+3);
+ break;
+
+ case slang_oper_assign:
+ spaces(indent);
+ printf("ASSIGNMENT locals %p\n", (void*)op->locals);
+ print_binary(op, ":=", indent);
+ break;
+
+ case slang_oper_addassign:
+ spaces(indent);
+ printf("ASSIGN\n");
+ print_binary(op, "+=", indent);
+ break;
+
+ case slang_oper_subassign:
+ spaces(indent);
+ printf("ASSIGN\n");
+ print_binary(op, "-=", indent);
+ break;
+
+ case slang_oper_mulassign:
+ spaces(indent);
+ printf("ASSIGN\n");
+ print_binary(op, "*=", indent);
+ break;
+
+ case slang_oper_divassign:
+ spaces(indent);
+ printf("ASSIGN\n");
+ print_binary(op, "/=", indent);
+ break;
+
+ /*slang_oper_modassign,*/
+ /*slang_oper_lshassign,*/
+ /*slang_oper_rshassign,*/
+ /*slang_oper_orassign,*/
+ /*slang_oper_xorassign,*/
+ /*slang_oper_andassign,*/
+ case slang_oper_select:
+ spaces(indent);
+ printf("slang_oper_select n=%d\n", op->num_children);
+ assert(op->num_children == 3);
+ slang_print_tree(&op->children[0], indent+3);
+ spaces(indent);
+ printf("?\n");
+ slang_print_tree(&op->children[1], indent+3);
+ spaces(indent);
+ printf(":\n");
+ slang_print_tree(&op->children[2], indent+3);
+ break;
+
+ case slang_oper_logicalor:
+ print_binary(op, "||", indent);
+ break;
+
+ case slang_oper_logicalxor:
+ print_binary(op, "^^", indent);
+ break;
+
+ case slang_oper_logicaland:
+ print_binary(op, "&&", indent);
+ break;
+
+ /*slang_oper_bitor*/
+ /*slang_oper_bitxor*/
+ /*slang_oper_bitand*/
+ case slang_oper_equal:
+ print_binary(op, "==", indent);
+ break;
+
+ case slang_oper_notequal:
+ print_binary(op, "!=", indent);
+ break;
+
+ case slang_oper_less:
+ print_binary(op, "<", indent);
+ break;
+
+ case slang_oper_greater:
+ print_binary(op, ">", indent);
+ break;
+
+ case slang_oper_lessequal:
+ print_binary(op, "<=", indent);
+ break;
+
+ case slang_oper_greaterequal:
+ print_binary(op, ">=", indent);
+ break;
+
+ /*slang_oper_lshift*/
+ /*slang_oper_rshift*/
+ case slang_oper_add:
+ print_binary(op, "+", indent);
+ break;
+
+ case slang_oper_subtract:
+ print_binary(op, "-", indent);
+ break;
+
+ case slang_oper_multiply:
+ print_binary(op, "*", indent);
+ break;
+
+ case slang_oper_divide:
+ print_binary(op, "/", indent);
+ break;
+
+ /*slang_oper_modulus*/
+ case slang_oper_preincrement:
+ spaces(indent);
+ printf("PRE++\n");
+ slang_print_tree(&op->children[0], indent+3);
+ break;
+
+ case slang_oper_predecrement:
+ spaces(indent);
+ printf("PRE--\n");
+ slang_print_tree(&op->children[0], indent+3);
+ break;
+
+ case slang_oper_plus:
+ spaces(indent);
+ printf("slang_oper_plus\n");
+ break;
+
+ case slang_oper_minus:
+ spaces(indent);
+ printf("slang_oper_minus\n");
+ break;
+
+ /*slang_oper_complement*/
+ case slang_oper_not:
+ spaces(indent);
+ printf("NOT\n");
+ slang_print_tree(&op->children[0], indent+3);
+ break;
+
+ case slang_oper_subscript:
+ spaces(indent);
+ printf("slang_oper_subscript\n");
+ print_generic(op, NULL, indent+3);
+ break;
+
+ case slang_oper_call:
+#if 0
+ slang_function *fun
+ = _slang_locate_function(A->space.funcs, oper->a_id,
+ oper->children,
+ oper->num_children, &A->space, A->atoms);
+#endif
+ spaces(indent);
+ printf("CALL %s(\n", (char *) op->a_id);
+ for (i = 0; i < op->num_children; i++) {
+ slang_print_tree(&op->children[i], indent+3);
+ if (i + 1 < op->num_children) {
+ spaces(indent + 3);
+ printf(",\n");
+ }
+ }
+ spaces(indent);
+ printf(")\n");
+ break;
+
+ case slang_oper_field:
+ spaces(indent);
+ printf("FIELD %s of\n", (char*) op->a_id);
+ slang_print_tree(&op->children[0], indent+3);
+ break;
+
+ case slang_oper_postincrement:
+ spaces(indent);
+ printf("POST++\n");
+ slang_print_tree(&op->children[0], indent+3);
+ break;
+
+ case slang_oper_postdecrement:
+ spaces(indent);
+ printf("POST--\n");
+ slang_print_tree(&op->children[0], indent+3);
+ break;
+
+ default:
+ printf("unknown op->type %d\n", (int) op->type);
+ }
+
+}
+
+
+
+void
+slang_print_function(const slang_function *f, GLboolean body)
+{
+ int i;
+
+#if 0
+ if (_mesa_strcmp((char *) f->header.a_name, "main") != 0)
+ return;
+#endif
+
+ printf("FUNCTION %s (\n",
+ (char *) f->header.a_name);
+
+ for (i = 0; i < f->param_count; i++) {
+ print_variable(&f->parameters->variables[i], 3);
+ }
+
+ printf(")\n");
+ if (body && f->body)
+ slang_print_tree(f->body, 0);
+}
+
+
+
+
+/* operation */
+#define OP_END 0
+#define OP_BLOCK_BEGIN_NO_NEW_SCOPE 1
+#define OP_BLOCK_BEGIN_NEW_SCOPE 2
+#define OP_DECLARE 3
+#define OP_ASM 4
+#define OP_BREAK 5
+#define OP_CONTINUE 6
+#define OP_DISCARD 7
+#define OP_RETURN 8
+#define OP_EXPRESSION 9
+#define OP_IF 10
+#define OP_WHILE 11
+#define OP_DO 12
+#define OP_FOR 13
+#define OP_PUSH_VOID 14
+#define OP_PUSH_BOOL 15
+#define OP_PUSH_INT 16
+#define OP_PUSH_FLOAT 17
+#define OP_PUSH_IDENTIFIER 18
+#define OP_SEQUENCE 19
+#define OP_ASSIGN 20
+#define OP_ADDASSIGN 21
+#define OP_SUBASSIGN 22
+#define OP_MULASSIGN 23
+#define OP_DIVASSIGN 24
+/*#define OP_MODASSIGN 25*/
+/*#define OP_LSHASSIGN 26*/
+/*#define OP_RSHASSIGN 27*/
+/*#define OP_ORASSIGN 28*/
+/*#define OP_XORASSIGN 29*/
+/*#define OP_ANDASSIGN 30*/
+#define OP_SELECT 31
+#define OP_LOGICALOR 32
+#define OP_LOGICALXOR 33
+#define OP_LOGICALAND 34
+/*#define OP_BITOR 35*/
+/*#define OP_BITXOR 36*/
+/*#define OP_BITAND 37*/
+#define OP_EQUAL 38
+#define OP_NOTEQUAL 39
+#define OP_LESS 40
+#define OP_GREATER 41
+#define OP_LESSEQUAL 42
+#define OP_GREATEREQUAL 43
+/*#define OP_LSHIFT 44*/
+/*#define OP_RSHIFT 45*/
+#define OP_ADD 46
+#define OP_SUBTRACT 47
+#define OP_MULTIPLY 48
+#define OP_DIVIDE 49
+/*#define OP_MODULUS 50*/
+#define OP_PREINCREMENT 51
+#define OP_PREDECREMENT 52
+#define OP_PLUS 53
+#define OP_MINUS 54
+/*#define OP_COMPLEMENT 55*/
+#define OP_NOT 56
+#define OP_SUBSCRIPT 57
+#define OP_CALL 58
+#define OP_FIELD 59
+#define OP_POSTINCREMENT 60
+#define OP_POSTDECREMENT 61
+
+
+void
+slang_print_opcode(unsigned int opcode)
+{
+ switch (opcode) {
+ case OP_PUSH_VOID:
+ printf("OP_PUSH_VOID\n");
+ break;
+ case OP_PUSH_BOOL:
+ printf("OP_PUSH_BOOL\n");
+ break;
+ case OP_PUSH_INT:
+ printf("OP_PUSH_INT\n");
+ break;
+ case OP_PUSH_FLOAT:
+ printf("OP_PUSH_FLOAT\n");
+ break;
+ case OP_PUSH_IDENTIFIER:
+ printf("OP_PUSH_IDENTIFIER\n");
+ break;
+ case OP_SEQUENCE:
+ printf("OP_SEQUENCE\n");
+ break;
+ case OP_ASSIGN:
+ printf("OP_ASSIGN\n");
+ break;
+ case OP_ADDASSIGN:
+ printf("OP_ADDASSIGN\n");
+ break;
+ case OP_SUBASSIGN:
+ printf("OP_SUBASSIGN\n");
+ break;
+ case OP_MULASSIGN:
+ printf("OP_MULASSIGN\n");
+ break;
+ case OP_DIVASSIGN:
+ printf("OP_DIVASSIGN\n");
+ break;
+ /*case OP_MODASSIGN:*/
+ /*case OP_LSHASSIGN:*/
+ /*case OP_RSHASSIGN:*/
+ /*case OP_ORASSIGN:*/
+ /*case OP_XORASSIGN:*/
+ /*case OP_ANDASSIGN:*/
+ case OP_SELECT:
+ printf("OP_SELECT\n");
+ break;
+ case OP_LOGICALOR:
+ printf("OP_LOGICALOR\n");
+ break;
+ case OP_LOGICALXOR:
+ printf("OP_LOGICALXOR\n");
+ break;
+ case OP_LOGICALAND:
+ printf("OP_LOGICALAND\n");
+ break;
+ /*case OP_BITOR:*/
+ /*case OP_BITXOR:*/
+ /*case OP_BITAND:*/
+ case OP_EQUAL:
+ printf("OP_EQUAL\n");
+ break;
+ case OP_NOTEQUAL:
+ printf("OP_NOTEQUAL\n");
+ break;
+ case OP_LESS:
+ printf("OP_LESS\n");
+ break;
+ case OP_GREATER:
+ printf("OP_GREATER\n");
+ break;
+ case OP_LESSEQUAL:
+ printf("OP_LESSEQUAL\n");
+ break;
+ case OP_GREATEREQUAL:
+ printf("OP_GREATEREQUAL\n");
+ break;
+ /*case OP_LSHIFT:*/
+ /*case OP_RSHIFT:*/
+ case OP_ADD:
+ printf("OP_ADD\n");
+ break;
+ case OP_SUBTRACT:
+ printf("OP_SUBTRACT\n");
+ break;
+ case OP_MULTIPLY:
+ printf("OP_MULTIPLY\n");
+ break;
+ case OP_DIVIDE:
+ printf("OP_DIVIDE\n");
+ break;
+ /*case OP_MODULUS:*/
+ case OP_PREINCREMENT:
+ printf("OP_PREINCREMENT\n");
+ break;
+ case OP_PREDECREMENT:
+ printf("OP_PREDECREMENT\n");
+ break;
+ case OP_PLUS:
+ printf("OP_PLUS\n");
+ break;
+ case OP_MINUS:
+ printf("OP_MINUS\n");
+ break;
+ case OP_NOT:
+ printf("OP_NOT\n");
+ break;
+ /*case OP_COMPLEMENT:*/
+ case OP_SUBSCRIPT:
+ printf("OP_SUBSCRIPT\n");
+ break;
+ case OP_CALL:
+ printf("OP_CALL\n");
+ break;
+ case OP_FIELD:
+ printf("OP_FIELD\n");
+ break;
+ case OP_POSTINCREMENT:
+ printf("OP_POSTINCREMENT\n");
+ break;
+ case OP_POSTDECREMENT:
+ printf("OP_POSTDECREMENT\n");
+ break;
+ default:
+ printf("UNKNOWN OP %d\n", opcode);
+ }
+}
+
+
+
+const char *
+slang_asm_string(slang_assembly_type t)
+{
+ switch (t) {
+ /* core */
+ case slang_asm_none:
+ return "none";
+ case slang_asm_float_copy:
+ return "float_copy";
+ case slang_asm_float_move:
+ return "float_move";
+ case slang_asm_float_push:
+ return "float_push";
+ case slang_asm_float_deref:
+ return "float_deref";
+ case slang_asm_float_add:
+ return "float_add";
+ case slang_asm_float_multiply:
+ return "float_multiply";
+ case slang_asm_float_divide:
+ return "float_divide";
+ case slang_asm_float_negate:
+ return "float_negate";
+ case slang_asm_float_less:
+ return "float_less";
+ case slang_asm_float_equal_exp:
+ return "float_equal";
+ case slang_asm_float_equal_int:
+ return "float_equal";
+ case slang_asm_float_to_int:
+ return "float_to_int";
+ case slang_asm_float_sine:
+ return "float_sine";
+ case slang_asm_float_arcsine:
+ return "float_arcsine";
+ case slang_asm_float_arctan:
+ return "float_arctan";
+ case slang_asm_float_power:
+ return "float_power";
+ case slang_asm_float_log2:
+ return "float_log2";
+ case slang_asm_vec4_floor:
+ return "vec4_floor";
+ case slang_asm_float_ceil:
+ return "float_ceil";
+ case slang_asm_float_noise1:
+ return "float_noise1";
+ case slang_asm_float_noise2:
+ return "float_noise2";
+ case slang_asm_float_noise3:
+ return "float_noise3";
+ case slang_asm_float_noise4:
+ return "float_noise4";
+ case slang_asm_int_copy:
+ return "int_copy";
+ case slang_asm_int_move:
+ return "int_move";
+ case slang_asm_int_push:
+ return "int_push";
+ case slang_asm_int_deref:
+ return "int_deref";
+ case slang_asm_int_to_float:
+ return "int_to_float";
+ case slang_asm_int_to_addr:
+ return "int_to_addr";
+ case slang_asm_bool_copy:
+ return "bool_copy";
+ case slang_asm_bool_move:
+ return "bool_move";
+ case slang_asm_bool_push:
+ return "bool_push";
+ case slang_asm_bool_deref:
+ return "bool_deref";
+ case slang_asm_addr_copy:
+ return "addr_copy";
+ case slang_asm_addr_push:
+ return "addr_push";
+ case slang_asm_addr_deref:
+ return "addr_deref";
+ case slang_asm_addr_add:
+ return "addr_add";
+ case slang_asm_addr_multiply:
+ return "addr_multiply";
+ case slang_asm_vec4_tex1d:
+ return "vec4_tex1d";
+ case slang_asm_vec4_tex2d:
+ return "vec4_tex2d";
+ case slang_asm_vec4_tex3d:
+ return "vec4_tex3d";
+ case slang_asm_vec4_texcube:
+ return "vec4_texcube";
+ case slang_asm_vec4_shad1d:
+ return "vec4_shad1d";
+ case slang_asm_vec4_shad2d:
+ return "vec4_shad2d";
+ case slang_asm_jump:
+ return "jump";
+ case slang_asm_jump_if_zero:
+ return "jump_if_zero";
+ case slang_asm_enter:
+ return "enter";
+ case slang_asm_leave:
+ return "leave";
+ case slang_asm_local_alloc:
+ return "local_alloc";
+ case slang_asm_local_free:
+ return "local_free";
+ case slang_asm_local_addr:
+ return "local_addr";
+ case slang_asm_global_addr:
+ return "global_addr";
+ case slang_asm_call:
+ return "call";
+ case slang_asm_return:
+ return "return";
+ case slang_asm_discard:
+ return "discard";
+ case slang_asm_exit:
+ return "exit";
+ /* GL_MESA_shader_debug */
+ case slang_asm_float_print:
+ return "float_print";
+ case slang_asm_int_print:
+ return "int_print";
+ case slang_asm_bool_print:
+ return "bool_print";
+ /* vec4 */
+ case slang_asm_float_to_vec4:
+ return "float_to_vec4";
+ case slang_asm_vec4_add:
+ return "vec4_add";
+ case slang_asm_vec4_subtract:
+ return "vec4_subtract";
+ case slang_asm_vec4_multiply:
+ return "vec4_multiply";
+ case slang_asm_vec4_divide:
+ return "vec4_divide";
+ case slang_asm_vec4_negate:
+ return "vec4_negate";
+ case slang_asm_vec4_dot:
+ return "vec4_dot";
+ case slang_asm_vec4_copy:
+ return "vec4_copy";
+ case slang_asm_vec4_deref:
+ return "vec4_deref";
+ case slang_asm_vec4_equal_int:
+ return "vec4_equal";
+ default:
+ return "??asm??";
+ }
+}
+
+
+const char *
+slang_type_qual_string(slang_type_qualifier q)
+{
+ switch (q) {
+ case slang_qual_none:
+ return "none";
+ case slang_qual_const:
+ return "const";
+ case slang_qual_attribute:
+ return "attribute";
+ case slang_qual_varying:
+ return "varying";
+ case slang_qual_uniform:
+ return "uniform";
+ case slang_qual_out:
+ return "out";
+ case slang_qual_inout:
+ return "inout";
+ case slang_qual_fixedoutput:
+ return "fixedoutput";
+ case slang_qual_fixedinput:
+ return "fixedinputk";
+ default:
+ return "qual?";
+ }
+}
+
+
+static const char *
+slang_type_string(slang_type_specifier_type t)
+{
+ switch (t) {
+ case slang_spec_void:
+ return "void";
+ case slang_spec_bool:
+ return "bool";
+ case slang_spec_bvec2:
+ return "bvec2";
+ case slang_spec_bvec3:
+ return "bvec3";
+ case slang_spec_bvec4:
+ return "bvec4";
+ case slang_spec_int:
+ return "int";
+ case slang_spec_ivec2:
+ return "ivec2";
+ case slang_spec_ivec3:
+ return "ivec3";
+ case slang_spec_ivec4:
+ return "ivec4";
+ case slang_spec_float:
+ return "float";
+ case slang_spec_vec2:
+ return "vec2";
+ case slang_spec_vec3:
+ return "vec3";
+ case slang_spec_vec4:
+ return "vec4";
+ case slang_spec_mat2:
+ return "mat2";
+ case slang_spec_mat3:
+ return "mat3";
+ case slang_spec_mat4:
+ return "mat4";
+ case slang_spec_sampler1D:
+ return "sampler1D";
+ case slang_spec_sampler2D:
+ return "sampler2D";
+ case slang_spec_sampler3D:
+ return "sampler3D";
+ case slang_spec_samplerCube:
+ return "samplerCube";
+ case slang_spec_sampler1DShadow:
+ return "sampler1DShadow";
+ case slang_spec_sampler2DShadow:
+ return "sampler2DShadow";
+ case slang_spec_struct:
+ return "struct";
+ case slang_spec_array:
+ return "array";
+ default:
+ return "type?";
+ }
+}
+
+
+static const char *
+slang_fq_type_string(const slang_fully_specified_type *t)
+{
+ static char str[1000];
+ sprintf(str, "%s %s", slang_type_qual_string(t->qualifier),
+ slang_type_string(t->specifier.type));
+ return str;
+}
+
+
+void
+slang_print_type(const slang_fully_specified_type *t)
+{
+ printf("%s %s", slang_type_qual_string(t->qualifier),
+ slang_type_string(t->specifier.type));
+}
+
+
+static char *
+slang_var_string(const slang_variable *v)
+{
+ static char str[1000];
+ sprintf(str, "%s : %s",
+ (char *) v->a_name,
+ slang_fq_type_string(&v->type));
+ return str;
+}
+
+
+void
+slang_print_variable(const slang_variable *v)
+{
+ printf("Name: %s\n", (char *) v->a_name);
+ printf("Type: %s\n", slang_fq_type_string(&v->type));
+}
+
+
+void
+_slang_print_var_scope(const slang_variable_scope *vars, int indent)
+{
+ GLuint i;
+
+ spaces(indent);
+ printf("Var scope %p %d vars\n", (void *) vars, vars->num_variables);
+ for (i = 0; i < vars->num_variables; i++) {
+ spaces(indent + 3);
+ printf("%s\n", (char *) vars->variables[i].a_name);
+ }
+
+ if (vars->outer_scope) {
+ spaces(indent + 3);
+ printf("outer_scope = %p\n", (void*) vars->outer_scope);
+ _slang_print_var_scope(vars->outer_scope, indent + 3);
+ }
+}
+
+
+
+int
+slang_checksum_tree(const slang_operation *op)
+{
+ int s = op->num_children;
+ int i;
+
+ for (i = 0; i < op->num_children; i++) {
+ s += slang_checksum_tree(&op->children[i]);
+ }
+ return s;
+}
--- /dev/null
+
+
+#ifndef SLANG_PRINT
+#define SLANG_PRINT
+
+extern void
+slang_print_function(const slang_function *f, GLboolean body);
+
+extern void
+slang_print_tree(const slang_operation *op, int indent);
+
+
+extern void
+slang_print_opcode(unsigned int opcode);
+
+
+extern const char *
+slang_asm_string(slang_assembly_type t);
+
+
+extern const char *
+slang_type_qual_string(slang_type_qualifier q);
+
+extern void
+slang_print_type(const slang_fully_specified_type *t);
+
+extern void
+slang_print_variable(const slang_variable *v);
+
+extern void
+_slang_print_var_scope(const slang_variable_scope *s, int indent);
+
+
+extern int
+slang_checksum_tree(const slang_operation *op);
+
+#endif /* SLANG_PRINT */
+
--- /dev/null
+/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 2005-2006 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.
+ */
+
+/**
+ * \file slang_assemble_typeinfo.c
+ * slang type info
+ * \author Michal Krol
+ */
+
+#include "imports.h"
+#include "macros.h"
+#include "slang_compile.h"
+#include "slang_simplify.h"
+
+
+/**
+ * Recursively traverse an AST tree, applying simplifications wherever
+ * possible.
+ * At the least, we do constant folding. We need to do that much so that
+ * compile-time expressions can be evaluated for things like array
+ * declarations. I.e.: float foo[3 + 5];
+ */
+void
+slang_simplify(slang_operation *oper,
+ const slang_assembly_name_space * space,
+ slang_atom_pool * atoms)
+{
+ GLboolean isFloat[4];
+ GLboolean isBool[4];
+ GLuint i, n;
+
+ /* first, simplify children */
+ for (i = 0; i < oper->num_children; i++) {
+ slang_simplify(&oper->children[i], space, atoms);
+ }
+
+ /* examine children */
+ n = MIN2(oper->num_children, 4);
+ for (i = 0; i < n; i++) {
+ isFloat[i] = (oper->children[i].type == slang_oper_literal_float ||
+ oper->children[i].type == slang_oper_literal_int);
+ isBool[i] = (oper->children[i].type == slang_oper_literal_bool);
+ }
+
+ if (n == 2 && isFloat[0] && isFloat[1]) {
+ /* probably simple arithmetic */
+ switch (oper->type) {
+ case slang_oper_add:
+ for (i = 0; i < 4; i++) {
+ oper->literal[i]
+ = oper->children[0].literal[i] + oper->children[1].literal[i];
+ }
+ slang_operation_destruct(oper);
+ oper->type = slang_oper_literal_float;
+ break;
+ case slang_oper_subtract:
+ for (i = 0; i < 4; i++) {
+ oper->literal[i]
+ = oper->children[0].literal[i] - oper->children[1].literal[i];
+ }
+ slang_operation_destruct(oper);
+ oper->type = slang_oper_literal_float;
+ break;
+ case slang_oper_multiply:
+ for (i = 0; i < 4; i++) {
+ oper->literal[i]
+ = oper->children[0].literal[i] * oper->children[1].literal[i];
+ }
+ slang_operation_destruct(oper);
+ oper->type = slang_oper_literal_float;
+ break;
+ case slang_oper_divide:
+ for (i = 0; i < 4; i++) {
+ oper->literal[i]
+ = oper->children[0].literal[i] / oper->children[1].literal[i];
+ }
+ slang_operation_destruct(oper);
+ oper->type = slang_oper_literal_float;
+ break;
+ default:
+ ; /* nothing */
+ }
+ }
+ else if (n == 1 && isFloat[0]) {
+ switch (oper->type) {
+ case slang_oper_minus:
+ for (i = 0; i < 4; i++) {
+ oper->literal[i] = -oper->children[0].literal[i];
+ }
+ slang_operation_destruct(oper);
+ oper->type = slang_oper_literal_float;
+ break;
+ case slang_oper_plus:
+ COPY_4V(oper->literal, oper->children[0].literal);
+ slang_operation_destruct(oper);
+ oper->type = slang_oper_literal_float;
+ break;
+ default:
+ ; /* nothing */
+ }
+ }
+ else if (n == 2 && isBool[0] && isBool[1]) {
+ /* simple boolean expression */
+ switch (oper->type) {
+ case slang_oper_logicaland:
+ for (i = 0; i < 4; i++) {
+ const GLint a = oper->children[0].literal[i] ? 1 : 0;
+ const GLint b = oper->children[1].literal[i] ? 1 : 0;
+ oper->literal[i] = (GLfloat) (a && b);
+ }
+ slang_operation_destruct(oper);
+ oper->type = slang_oper_literal_bool;
+ break;
+ case slang_oper_logicalor:
+ for (i = 0; i < 4; i++) {
+ const GLint a = oper->children[0].literal[i] ? 1 : 0;
+ const GLint b = oper->children[1].literal[i] ? 1 : 0;
+ oper->literal[i] = (GLfloat) (a || b);
+ }
+ slang_operation_destruct(oper);
+ oper->type = slang_oper_literal_bool;
+ break;
+ case slang_oper_logicalxor:
+ for (i = 0; i < 4; i++) {
+ const GLint a = oper->children[0].literal[i] ? 1 : 0;
+ const GLint b = oper->children[1].literal[i] ? 1 : 0;
+ oper->literal[i] = (GLfloat) (a ^ b);
+ }
+ slang_operation_destruct(oper);
+ oper->type = slang_oper_literal_bool;
+ break;
+ default:
+ ; /* nothing */
+ }
+ }
+ else if (n == 4 && isFloat[0] && isFloat[1] && isFloat[2] && isFloat[3]) {
+ if (oper->type == slang_oper_call) {
+ if (strcmp((char *) oper->a_id, "vec4") == 0) {
+ oper->literal[0] = oper->children[0].literal[0];
+ oper->literal[1] = oper->children[1].literal[0];
+ oper->literal[2] = oper->children[2].literal[0];
+ oper->literal[3] = oper->children[3].literal[0];
+ slang_operation_destruct(oper);
+ oper->type = slang_oper_literal_float;
+ }
+ }
+ }
+}
+
--- /dev/null
+
+#ifndef SLANG_SIMPLIFY_H
+#define SLANG_SIMPLIFY_H
+
+extern void
+slang_simplify(slang_operation *oper,
+ const slang_assembly_name_space * space,
+ slang_atom_pool * atoms);
+
+
+
+#endif /* SLANG_SIMPLIFY_H */
return (const char *) (atom);
}
+
+/**
+ * Generate a new, unique atom with given prefix.
+ */
+slang_atom
+slang_atom_pool_gen(slang_atom_pool * pool, const char *prefix)
+{
+ char name[1000];
+ static int nextFree = 100;
+ sprintf(name, "%s%d", prefix, nextFree);
+ nextFree++;
+ return slang_atom_pool_atom(pool, name);
+}
slang_atom slang_atom_pool_atom (slang_atom_pool *, const char *);
const char *slang_atom_pool_id (slang_atom_pool *, slang_atom);
+slang_atom
+slang_atom_pool_gen(slang_atom_pool * pool, const char *prefix);
+
+
#ifdef __cplusplus
}
#endif