Rework code related to temp register allocation, both for user variables

and expression temporarires.  Much better register utilization now.
Lots of other fixes.
The OpenGL GLSL "orange book" brick shader demo works now.
This commit is contained in:
Brian 2007-01-13 14:49:52 -07:00
parent 5daa99d2a4
commit 691ed5e54b
12 changed files with 496 additions and 477 deletions

View file

@ -38,6 +38,7 @@
#include "slang_error.h"
#include "slang_simplify.h"
#include "slang_emit.h"
#include "slang_vartable.h"
#include "slang_ir.h"
#include "mtypes.h"
#include "program.h"
@ -259,10 +260,10 @@ _slang_sizeof_type_specifier(const slang_type_specifier *spec)
* 4. other?
*/
static void
slang_allocate_storage(slang_gen_context *gc, slang_ir_node *n,
struct gl_program *prog)
slang_allocate_storage(slang_assemble_ctx *A, slang_ir_node *n)
{
assert(gc);
struct gl_program *prog = A->program;
assert(A->vartable);
assert(n);
assert(n->Opcode == IR_VAR_DECL || n->Opcode == IR_VAR);
assert(prog);
@ -285,33 +286,22 @@ slang_allocate_storage(slang_gen_context *gc, slang_ir_node *n,
/* variable declaration */
assert(n->Var);
assert(!is_sampler_type(&n->Var->type));
printf("Alloc storage for %p %s:\n", (void*) n->Var, (char*) n->Var->a_name);
/*
assert(n->Store->Index < 0);
*/
n->Store->File = PROGRAM_TEMPORARY;
n->Store->Size = _slang_sizeof_type_specifier(&n->Var->type.specifier);
assert(n->Store->Size > 0);
if (n->Store->Index < 0)
n->Store->Index = _slang_alloc_temporary(gc, n->Store->Size);
printf(" Location = %d\n", n->Store->Index);
/*
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 00
if (n->Store->File == PROGRAM_UNDEFINED) {
printf("*** Var %s size %d\n", (char*) n->Var->a_name, n->Store->Size);
assert(n->Store->File != PROGRAM_UNDEFINED);
}
#endif
/**
** XXX this all has to be redone
**/
if (n->Store->Index < 0) {
/* determine storage location for this var */
@ -342,7 +332,6 @@ slang_allocate_storage(slang_gen_context *gc, slang_ir_node *n,
}
else {
/* what's this??? */
abort();
}
}
}
@ -533,54 +522,6 @@ static slang_asm_info AsmInfo[] = {
};
#if 000 /* prototype for future symbol table scheme */
#define MAX_DEPTH 100
static slang_variable_scope *Stack[MAX_DEPTH];
static int CurDepth;
static void
_slang_push_scope(slang_variable_scope *scope)
{
Stack[CurDepth++] = scope;
assert(CurDepth < MAX_DEPTH);
}
static void
_slang_pop_scope(void)
{
CurDepth--;
assert(CurDepth >= 0);
}
static slang_variable_scope *
_slang_current_scope(void)
{
if (CurDepth > 0)
return Stack[CurDepth - 1];
else
return NULL;
}
static slang_variable *
_slang_find_variable(slang_atom name)
{
int i;
for (i = CurDepth - 1; i >= 0; i--) {
int j;
for (j = 0; j < Stack[i]->num_variables; j++) {
if (Stack[i]->variables[j].a_name == name) {
return Stack[i]->variables + j;
}
}
}
return NULL;
}
#endif
/**
* Recursively free an IR tree.
*/
@ -675,15 +616,14 @@ new_var(slang_assemble_ctx *A, slang_operation *oper,
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_allocate_storage(A->codegen, n, A->program);
slang_allocate_storage(A, n);
return n;
}
@ -725,7 +665,7 @@ slang_is_writemask(const char *field, GLuint *mask)
/**
* Check if the given function is really just a wrapper for an
* Check if the given function is really just a wrapper for a
* basic assembly instruction.
*/
static GLboolean
@ -753,7 +693,7 @@ slang_inline_asm_function(slang_assemble_ctx *A,
slang_operation *inlined = slang_operation_new(1);
/*assert(oper->type == slang_oper_call); or vec4_add, etc */
printf("Inline asm %s\n", (char*) fun->header.a_name);
inlined->type = fun->body->children[0].type;
inlined->a_id = fun->body->children[0].a_id;
inlined->num_children = numArgs;
@ -833,9 +773,7 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
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 0 /* DEBUG only */
if (substNew[i]->type == slang_oper_identifier) {
assert(substNew[i]->var);
assert(substNew[i]->var->a_name);
@ -843,7 +781,7 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
(char*)v->a_name, (char*) substNew[i]->var->a_name,
(void*) oper);
}
else
else {
printf("Substitute %s with %f in id node %p\n",
(char*)v->a_name, substNew[i]->literal[0],
(void*) oper);
@ -958,15 +896,15 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
substNew = (slang_operation **)
_mesa_calloc(totalArgs * sizeof(slang_operation *));
printf("\nInline call to %s (total vars=%d nparams=%d)\n",
printf("Inline 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.
/* Create 3-child comma sequence for inlined code:
* child[0]: declare __resultTmp
* child[1]: inlined function body
* child[2]: __resultTmp
*/
slang_operation *commaSeq;
slang_operation *declOper = NULL;
@ -981,13 +919,13 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
/* allocate the return var */
resultVar = slang_variable_scope_grow(commaSeq->locals);
/*
printf("Alloc __resultTemp in scope %p for retval of calling %s\n",
printf("Alloc __resultTmp 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;*/
resultVar->isTemp = GL_TRUE;
/* child[0] = __resultTmp declaration */
declOper = &commaSeq->children[0];
@ -1027,12 +965,12 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
*/
substCount = 0;
for (i = 0; i < totalArgs; i++) {
slang_variable *p = &fun->parameters->variables[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 */
@ -1042,9 +980,10 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
else
arg = returnOper;
paramMode[i] = SUBST;
assert(arg->type == slang_oper_identifier
/*||arg->type == slang_oper_variable_decl*/);
slang_resolve_variable(arg);
if (arg->type == slang_oper_identifier)
slang_resolve_variable(arg);
/* replace parameter 'p' with argument 'arg' */
substOld[substCount] = p;
substNew[substCount] = arg; /* will get copied */
@ -1073,15 +1012,14 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
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
/*** XXX review this */
assert(inlined->type = slang_oper_block_no_new_scope);
inlined->type = slang_oper_block_new_scope;
#if 0
printf("======================= orig body code ======================\n");
printf("=== params scope = %p\n", (void*) fun->parameters);
slang_print_tree(fun->body, 8);
@ -1092,7 +1030,7 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
/* do parameter substitution in inlined code: */
slang_substitute(A, inlined, substCount, substOld, substNew, GL_FALSE);
#if 000
#if 0
printf("======================= subst code ==========================\n");
slang_print_tree(inlined, 8);
printf("=============================================================\n");
@ -1104,7 +1042,7 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
numCopyIn = 0;
for (i = 0; i < numArgs; i++) {
if (paramMode[i] == COPY_IN) {
slang_variable *p = &fun->parameters->variables[i];
slang_variable *p = fun->parameters->variables[i];
/* declare parameter 'p' */
slang_operation *decl = slang_operation_insert(&inlined->num_children,
&inlined->children,
@ -1138,7 +1076,7 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
for (i = 0; i < totalArgs; i++) {
if (paramMode[i] == COPY_OUT) {
const slang_variable *p = &fun->parameters->variables[i];
const slang_variable *p = fun->parameters->variables[i];
/* actualCallVar = outParam */
/*if (i > 0 || !haveRetValue)*/
slang_operation *ass = slang_operation_insert(&inlined->num_children,
@ -1215,7 +1153,6 @@ _slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,
printf("\n");
#endif
/* assemble what we just made XXX here??? */
n = _slang_gen_operation(A, oper);
CurFunction->end_label = NULL;
@ -1323,7 +1260,6 @@ _slang_gen_asm(slang_assemble_ctx *A, slang_operation *oper,
dest_oper = &dest_oper->children[0];
}
assert(dest_oper->type == slang_oper_identifier);
n0 = _slang_gen_operation(A, dest_oper);
assert(n0->Var);
assert(n0->Store);
@ -1676,9 +1612,8 @@ _slang_gen_declaration(slang_assemble_ctx *A, slang_operation *oper)
return NULL;
varDecl->Var = v;
v->declared = GL_TRUE;
slang_allocate_storage(A->codegen, varDecl, A->program);
slang_allocate_storage(A, varDecl);
if (oper->num_children > 0) {
/* child is initializer */
@ -1728,7 +1663,9 @@ _slang_gen_variable(slang_assemble_ctx * A, slang_operation *oper)
*/
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;
}
@ -1856,7 +1793,7 @@ _slang_gen_subscript(slang_assemble_ctx * A, slang_operation *oper)
/* new storage info since we don't want to change the original */
base->Store = _slang_clone_ir_storage(base->Store);
if (_slang_type_is_vector(array_ti.spec.type)) {
/* scalar element (float) of a basic vector (vec3) */
/* scalar element (float) of a basic vector (ex: vec3) */
const GLuint max = _slang_type_dim(array_ti.spec.type);
if (index >= max) {
RETURN_ERROR("array index out of bounds", 0);
@ -1888,39 +1825,60 @@ static slang_ir_node *
_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
{
switch (oper->type) {
case slang_oper_block_no_new_scope:
case slang_oper_block_new_scope:
{
slang_ir_node *n;
A->vartable = _slang_push_var_table(A->vartable);
oper->type = slang_oper_block_no_new_scope; /* temp change */
n = _slang_gen_operation(A, oper);
oper->type = slang_oper_block_new_scope; /* restore */
A->vartable = _slang_pop_var_table(A->vartable);
if (n)
n = new_node(IR_SCOPE, n, NULL);
return n;
}
break;
case slang_oper_block_no_new_scope:
/* list of operations */
assert(oper->num_children > 0);
{
slang_ir_node *n, *tree = NULL;
GLuint i;
for (i = 0; i < oper->num_children; i++) {
n = _slang_gen_operation(A, &oper->children[i]);
if (!n)
if (!n) {
_slang_free_ir_tree(tree);
return NULL; /* error must have occured */
}
tree = tree ? new_seq(tree, n) : n;
}
if (oper->locals->num_variables > 0) {
int i;
/*
printf("\n****** Deallocate vars in scope!\n");
*/
for (i = 0; i < oper->locals->num_variables; i++) {
slang_variable *v = oper->locals->variables + i;
if (v->aux) {
slang_ir_storage *store = (slang_ir_storage *) v->aux;
/*
printf(" Deallocate var %s\n", (char*) v->a_name);
*/
assert(store->File == PROGRAM_TEMPORARY);
assert(store->Index >= 0);
_slang_free_temporary(A->codegen, store->Index, store->Size);
#if 00
if (oper->locals->num_variables > 0) {
int i;
/*
printf("\n****** Deallocate vars in scope!\n");
*/
for (i = 0; i < oper->locals->num_variables; i++) {
slang_variable *v = oper->locals->variables + i;
if (v->aux) {
slang_ir_storage *store = (slang_ir_storage *) v->aux;
/*
printf(" Deallocate var %s\n", (char*) v->a_name);
*/
assert(store->File == PROGRAM_TEMPORARY);
assert(store->Index >= 0);
_slang_free_temp(A->vartable, store->Index, store->Size);
}
}
}
}
#endif
return tree;
}
break;
@ -2022,12 +1980,10 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
return _slang_gen_assignment(A, oper);
case slang_oper_addassign:
{
/* XXX this is broken */
slang_ir_node *n;
assert(oper->num_children == 2);
n = _slang_gen_function_call_name(A, "+=", oper, NULL);
/* The result of this operation should be stored back into child[0] */
assert(n->Children[0]->Store);
n->Store = n->Children[0]->Store;
n = _slang_gen_function_call_name(A, "+=", oper, &oper->children[0]);
return n;
}
case slang_oper_subassign:
@ -2171,9 +2127,7 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
/* We know it's a uniform, but don't allocate storage unless
* it's really used.
*/
store = _slang_new_ir_storage(PROGRAM_STATE_VAR, -1, size);
}
if (dbg) printf("UNIFORM ");
}
@ -2260,10 +2214,12 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
if (!n)
return GL_FALSE;
n->Var = var;
var->declared = GL_TRUE;
store = _slang_new_ir_storage(PROGRAM_TEMPORARY, index, size);
var->aux = store; /* save var's storage info */
slang_allocate_storage(A->codegen, n, A->program);
slang_allocate_storage(A, n);
_slang_add_variable(A->vartable, var);
/* IR code for the var's initializer, if present */
if (var->initializer) {
@ -2284,7 +2240,7 @@ _slang_codegen_global_variable(slang_assemble_ctx *A, slang_variable *var,
n = new_seq(n, init);
}
success = _slang_emit_code(n, A->codegen, A->program, GL_FALSE);
success = _slang_emit_code(n, A->vartable, A->program, GL_FALSE);
_slang_free_ir_tree(n);
}
@ -2328,8 +2284,7 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
assert(A->program->Parameters );
assert(A->program->Varying);
assert(A->codegen);
/* A->codegen = _slang_new_codegen_context();*/
assert(A->vartable);
/* fold constant expressions, etc. */
slang_simplify(fun->body, &A->space, A->atoms);
@ -2340,8 +2295,16 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
if (!CurFunction->end_label)
CurFunction->end_label = slang_atom_pool_gen(A->atoms, "__endOfFunc_main_");
/* push new vartable scope */
A->vartable = _slang_push_var_table(A->vartable);
/* Generate IR tree for the function body code */
n = _slang_gen_operation(A, fun->body);
if (n)
n = new_node(IR_SCOPE, n, NULL);
/* pop vartable, restore previous */
A->vartable = _slang_pop_var_table(A->vartable);
if (!n) {
/* XXX record error */
@ -2361,11 +2324,13 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
#if 0
printf("************* IR for %s *******\n", (char*)fun->header.a_name);
slang_print_ir(n, 0);
#endif
#if 1
printf("************* End codegen function ************\n\n");
#endif
/* Emit program instructions */
success = _slang_emit_code(n, A->codegen, A->program, GL_TRUE);
success = _slang_emit_code(n, A->vartable, A->program, GL_TRUE);
_slang_free_ir_tree(n);
/* free codegen context */

View file

@ -39,6 +39,7 @@
#include "slang_storage.h"
#include "slang_error.h"
#include "slang_emit.h"
#include "slang_vartable.h"
#include "slang_print.h"
@ -98,7 +99,9 @@ _slang_code_object_ctr(slang_code_object * self)
for (i = 0; i < SLANG_BUILTIN_TOTAL; i++)
_slang_code_unit_ctr(&self->builtin[i], self);
_slang_code_unit_ctr(&self->unit, self);
#if 01
_slang_assembly_file_ctr(&self->assembly);
#endif
slang_machine_ctr(&self->machine);
self->varpool.next_addr = 0;
slang_atom_pool_construct(&self->atompool);
@ -116,7 +119,9 @@ _slang_code_object_dtr(slang_code_object * self)
for (i = 0; i < SLANG_BUILTIN_TOTAL; i++)
_slang_code_unit_dtr(&self->builtin[i]);
_slang_code_unit_dtr(&self->unit);
#if 01
slang_assembly_file_destruct(&self->assembly);
#endif
slang_machine_dtr(&self->machine);
slang_atom_pool_destruct(&self->atompool);
slang_export_data_table_dtr(&self->expdata);
@ -248,7 +253,7 @@ typedef struct slang_output_ctx_
slang_var_pool *global_pool;
slang_machine *machine;
struct gl_program *program;
slang_gen_context *codegen;
slang_var_table *vartable;
} slang_output_ctx;
/* _slang_compile() */
@ -868,7 +873,7 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
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;
o->a_id = O->vars->variables[i]->a_name;
}
}
}
@ -879,9 +884,6 @@ parse_statement(slang_parse_ctx * C, slang_output_ctx * O,
*/
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) {
@ -1547,15 +1549,19 @@ parse_function_definition(slang_parse_ctx * C, slang_output_ctx * O,
static GLboolean
initialize_global(slang_assemble_ctx * A, slang_variable * var)
{
#if 01
slang_assembly_file_restore_point point;
#endif
slang_machine mach;
slang_assembly_local_info save_local = A->local;
slang_operation op_id, op_assign;
GLboolean result;
#if 01
/* save the current assembly */
if (!slang_assembly_file_restore_point_save(A->file, &point))
return GL_FALSE;
#endif
/* setup the machine */
mach = *A->mach;
@ -1578,13 +1584,13 @@ initialize_global(slang_assemble_ctx * A, slang_variable * var)
/* put the variable into operation's scope */
op_id.locals->variables =
(slang_variable *) slang_alloc_malloc(sizeof(slang_variable));
(slang_variable **) slang_alloc_malloc(sizeof(slang_variable *));
if (op_id.locals->variables == NULL) {
slang_operation_destruct(&op_id);
return GL_FALSE;
}
op_id.locals->num_variables = 1;
op_id.locals->variables[0] = *var;
op_id.locals->variables[0] = var;
/* construct the assignment expression */
if (!slang_operation_construct(&op_assign)) {
@ -1605,8 +1611,12 @@ initialize_global(slang_assemble_ctx * A, slang_variable * var)
op_assign.children[0] = op_id;
op_assign.children[1] = *var->initializer;
#if 0 /* this should go away */
/* insert the actual expression */
result = _slang_assemble_operation(A, &op_assign, slang_ref_forbid);
#else
result = 1;
#endif
/* carefully destroy the operations */
op_assign.num_children = 0;
@ -1627,9 +1637,11 @@ initialize_global(slang_assemble_ctx * A, slang_variable * var)
return GL_FALSE;
#endif
#if 01
/* restore the old assembly */
if (!slang_assembly_file_restore_point_load(A->file, &point))
return GL_FALSE;
#endif
A->local = save_local;
/* now we copy the contents of the initialized variable back to the original machine */
@ -1732,8 +1744,11 @@ parse_init_declarator(slang_parse_ctx * C, slang_output_ctx * O,
A.space.funcs = O->funs;
A.space.structs = O->structs;
A.space.vars = O->vars;
A.codegen = O->codegen;
A.program = O->program;
#if 0
A.codegen = O->codegen;
#endif
A.vartable = O->vartable;
_slang_codegen_global_variable(&A, var, C->type);
}
@ -1896,7 +1911,10 @@ parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
A.space.structs = O->structs;
A.space.vars = O->vars;
A.program = O->program;
#if 0
A.codegen = O->codegen;
#endif
A.vartable = O->vartable;
_slang_reset_error();
@ -1906,14 +1924,14 @@ parse_function(slang_parse_ctx * C, slang_output_ctx * O, int definition,
(*parsed_func_ret)->param_count);
#endif
#if 0
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;
}
#endif
#if 0
printf("**************************************\n");
@ -1961,6 +1979,7 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
struct gl_program *program)
{
slang_output_ctx o;
GLboolean success;
/* setup output context */
o.funs = &unit->funs;
@ -1970,7 +1989,7 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
o.global_pool = &unit->object->varpool;
o.machine = &unit->object->machine;
o.program = program;
o.codegen = _slang_new_codegen_context();
o.vartable = _slang_push_var_table(NULL);
/* parse individual functions and declarations */
while (*C->I != EXTERNAL_NULL) {
@ -1978,20 +1997,25 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,
case EXTERNAL_FUNCTION_DEFINITION:
{
slang_function *func;
if (!parse_function(C, &o, 1, &func))
return GL_FALSE;
success = parse_function(C, &o, 1, &func);
}
break;
case EXTERNAL_DECLARATION:
if (!parse_declaration(C, &o))
return GL_FALSE;
success = parse_declaration(C, &o);
break;
default:
success = GL_FALSE;
}
if (!success) {
/* xxx free codegen */
_slang_pop_var_table(o.vartable);
return GL_FALSE;
}
}
C->I++;
_slang_pop_var_table(o.vartable);
return GL_TRUE;
}

View file

@ -34,6 +34,7 @@
#include "program.h"
#include "prog_instruction.h"
#include "prog_parameter.h"
#include "prog_print.h"
#include "slang_emit.h"
@ -83,6 +84,7 @@ static slang_ir_info IrInfo[] = {
{ IR_COS, "IR_COS", OPCODE_COS, 1, 1 },
/* other */
{ IR_SEQ, "IR_SEQ", 0, 0, 0 },
{ IR_SCOPE, "IR_SCOPE", 0, 0, 0 },
{ IR_LABEL, "IR_LABEL", 0, 0, 0 },
{ IR_JUMP, "IR_JUMP", 0, 0, 0 },
{ IR_CJUMP, "IR_CJUMP", 0, 0, 0 },
@ -227,6 +229,11 @@ slang_print_ir(const slang_ir_node *n, int indent)
slang_print_ir(n->Children[0], indent + IND);
slang_print_ir(n->Children[1], indent + IND);
break;
case IR_SCOPE:
printf("NEW SCOPE\n");
assert(!n->Children[1]);
slang_print_ir(n->Children[0], indent + 3);
break;
case IR_MOVE:
printf("MOVE (writemask = %s)\n", writemask_string(n->Writemask));
slang_print_ir(n->Children[0], indent+3);
@ -279,71 +286,36 @@ slang_print_ir(const slang_ir_node *n, int indent)
}
GLint
_slang_alloc_temporary(slang_gen_context *gc, GLint size)
{
const GLuint sz4 = (size + 3) / 4;
GLuint i, j;
ASSERT(size > 0); /* number of floats */
for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
GLuint found = 0;
for (j = 0; j < sz4; j++) {
if (!gc->TempUsed[i + j]) {
found++;
}
}
if (found == sz4) {
/* found block of size/4 free regs */
for (j = 0; j < sz4; j++)
gc->TempUsed[i + j] = 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;
}
void
_slang_free_temporary(slang_gen_context *gc, GLuint r, GLint size)
{
const GLuint sz4 = (size + 3) / 4;
GLuint i;
for (i = 0; i < sz4; i++) {
if (gc->TempUsed[r + i])
gc->TempUsed[r + i] = GL_FALSE;
}
}
/**
* 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)
alloc_temp_storage(slang_var_table *vt, slang_ir_node *n, GLint size)
{
GLint indx;
assert(!n->Var);
assert(!n->Store);
assert(size > 0);
printf("Allocate binop temp:\n");
indx = _slang_alloc_temporary(gc, size);
indx = _slang_alloc_temp(vt, size);
n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, indx, size);
}
static void
free_temp_storage(slang_var_table *vt, slang_ir_node *n)
{
if (n->Store->File == PROGRAM_TEMPORARY && n->Store->Index >= 0) {
if (_slang_is_temp(vt, n->Store->Index)) {
_slang_free_temp(vt, n->Store->Index, n->Store->Size);
/* XXX free(store)? */
n->Store->Index = -1;
n->Store->Size = -1;
}
}
}
static slang_ir_storage *
alloc_constant(const GLfloat v[], GLuint size, struct gl_program *prog)
{
@ -445,14 +417,14 @@ new_instruction(struct gl_program *prog, gl_inst_opcode opcode)
static struct prog_instruction *
emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog);
emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog);
/**
* Generate code for a simple binary-op instruction.
*/
static struct prog_instruction *
emit_binop(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
emit_binop(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
{
struct prog_instruction *inst;
const slang_ir_info *info = slang_find_ir_info(n->Opcode);
@ -460,25 +432,32 @@ emit_binop(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
assert(info->InstOpcode != OPCODE_NOP);
emit(gc, n->Children[0], prog);
emit(gc, n->Children[1], prog);
/* gen code for children */
emit(vt, n->Children[0], prog);
emit(vt, n->Children[1], prog);
/* gen this instruction */
inst = new_instruction(prog, info->InstOpcode);
/* alloc temp storage for the result: */
if (!n->Store || n->Store->File == PROGRAM_UNDEFINED) {
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);
storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store,
n->Children[1]->Swizzle);
free_temp_storage(vt, n->Children[0]);
free_temp_storage(vt, n->Children[1]);
if (!n->Store) {
alloc_temp_storage(vt, n, info->ResultSize);
}
storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
inst->Comment = n->Comment;
/*_mesa_print_instruction(inst);*/
return inst;
}
static struct prog_instruction *
emit_unop(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
emit_unop(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
{
struct prog_instruction *inst;
const slang_ir_info *info = slang_find_ir_info(n->Opcode);
@ -486,26 +465,28 @@ emit_unop(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
assert(info->NumParams == 1);
emit(gc, n->Children[0], prog);
/* gen code for child */
emit(vt, n->Children[0], prog);
/* gen this instruction */
inst = new_instruction(prog, info->InstOpcode);
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);
free_temp_storage(vt, n->Children[0]);
if (!n->Store) {
alloc_temp_storage(vt, n, info->ResultSize);
}
storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
inst->Comment = n->Comment;
/*_mesa_print_instruction(inst);*/
return inst;
}
static struct prog_instruction *
emit_negation(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
emit_negation(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
{
/* Implement as MOV dst, -src; */
/* XXX we could look at the previous instruction and in some circumstances
@ -513,10 +494,10 @@ emit_negation(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
*/
struct prog_instruction *inst;
emit(gc, n->Children[0], prog);
emit(vt, n->Children[0], prog);
if (!n->Store)
slang_alloc_temp_storage(gc, n, n->Children[0]->Store->Size);
alloc_temp_storage(vt, n, n->Children[0]->Store->Size);
inst = new_instruction(prog, OPCODE_MOV);
storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
@ -563,7 +544,7 @@ emit_jump(const char *target, struct gl_program *prog)
static struct prog_instruction *
emit_tex(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
emit_tex(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
{
struct prog_instruction *inst;
if (n->Opcode == IR_TEX) {
@ -578,7 +559,7 @@ emit_tex(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
}
if (!n->Store)
slang_alloc_temp_storage(gc, n, 4);
alloc_temp_storage(vt, n, 4);
storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
@ -600,7 +581,7 @@ emit_tex(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
static struct prog_instruction *
emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
{
struct prog_instruction *inst;
if (!n)
@ -610,34 +591,54 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
case IR_SEQ:
assert(n->Children[0]);
assert(n->Children[1]);
emit(gc, n->Children[0], prog);
inst = emit(gc, n->Children[1], prog);
emit(vt, n->Children[0], prog);
inst = emit(vt, n->Children[1], prog);
n->Store = n->Children[1]->Store;
return inst;
break;
case IR_SCOPE:
/* new variable scope */
vt = _slang_push_var_table(vt);
inst = emit(vt, n->Children[0], prog);
vt = _slang_pop_var_table(vt);
return inst;
case IR_VAR_DECL:
/* Variable declaration - allocate a register for it */
assert(n->Store);
assert(n->Store->File != PROGRAM_UNDEFINED);
assert(n->Store->Size > 0);
if (n->Var->isTemp)
n->Store->Index = _slang_alloc_temp(vt, n->Store->Size);
else
n->Store->Index = _slang_alloc_var(vt, n->Store->Size);
break;
case IR_VAR:
/* Storage should have already been resolved/allocated */
/* Reference to a variable
* Storage should have already been resolved/allocated.
*/
assert(n->Store);
assert(n->Store->File != PROGRAM_UNDEFINED);
assert(n->Store->Index >= 0);
assert(n->Store->Size > 0);
break;
case IR_MOVE:
/* rhs */
assert(n->Children[1]);
inst = emit(gc, n->Children[1], prog);
inst = emit(vt, n->Children[1], prog);
/* lhs */
emit(gc, n->Children[0], prog);
emit(vt, n->Children[0], prog);
#if 1
if (inst && is_temporary(gc, n->Children[1]->Store)) {
if (inst && _slang_is_temp(vt, n->Children[1]->Store->Index)) {
/* Peephole optimization:
* Just modify the RHS to put its result into the dest of this
* MOVE operation. Then, this MOVE is a no-op.
*/
_slang_free_temporary(gc, n->Children[1]->Store->Index,
n->Children[1]->Store->Size);
_slang_free_temp(vt, n->Children[1]->Store->Index,
n->Children[1]->Store->Size);
*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);
@ -673,9 +674,9 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
n->Children[1]->Swizzle);
}
/* XXX is this test correct? */
if (n->Children[1]->Store->File == PROGRAM_TEMPORARY) {
_slang_free_temporary(gc, n->Children[1]->Store->Index,
n->Children[1]->Store->Size);
if (_slang_is_temp(vt, n->Children[1]->Store->Index)) {
_slang_free_temp(vt, n->Children[1]->Store->Index,
n->Children[1]->Store->Size);
}
/*inst->Comment = _mesa_strdup("IR_MOVE");*/
n->Store = n->Children[0]->Store; /*XXX new */
@ -697,7 +698,7 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
case IR_POW:
case IR_EXP:
case IR_EXP2:
return emit_binop(gc, n, prog);
return emit_binop(vt, n, prog);
case IR_RSQ:
case IR_RCP:
case IR_FLOOR:
@ -707,13 +708,13 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
case IR_COS:
case IR_DDX:
case IR_DDY:
return emit_unop(gc, n, prog);
return emit_unop(vt, n, prog);
case IR_TEX:
case IR_TEXB:
case IR_TEXP:
return emit_tex(gc, n, prog);
return emit_tex(vt, n, prog);
case IR_NEG:
return emit_negation(gc, n, prog);
return emit_negation(vt, n, prog);
case IR_LABEL:
return emit_label(n->Target, prog);
case IR_FLOAT:
@ -726,7 +727,7 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
* Next instruction is typically an IR_CJUMP.
*/
/* last child expr instruction: */
struct prog_instruction *inst = emit(gc, n->Children[0], prog);
struct prog_instruction *inst = emit(vt, n->Children[0], prog);
if (inst) {
/* set inst's CondUpdate flag */
inst->CondUpdate = GL_TRUE;
@ -737,13 +738,13 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
* is normally generated for the expression "i".
* Generate a move instruction just to set condition codes.
*/
slang_alloc_temp_storage(gc, n, 1);
alloc_temp_storage(vt, n, 1);
inst = new_instruction(prog, OPCODE_MOV);
inst->CondUpdate = GL_TRUE;
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);
_slang_free_temporary(gc, n->Store->Index, n->Store->Size);
_slang_free_temp(vt, n->Store->Index, n->Store->Size);
return inst; /* XXX or null? */
}
}
@ -760,23 +761,14 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
}
slang_gen_context *
_slang_new_codegen_context(void)
{
slang_gen_context *gc = (slang_gen_context *) _mesa_calloc(sizeof(*gc));
return gc;
}
GLboolean
_slang_emit_code(slang_ir_node *n, slang_gen_context *gc,
_slang_emit_code(slang_ir_node *n, slang_var_table *vt,
struct gl_program *prog, GLboolean withEnd)
{
GLboolean success;
if (emit(gc, n, prog)) {
/* finish up by addeing the END opcode to program */
if (emit(vt, n, prog)) {
/* finish up by adding the END opcode to program */
if (withEnd) {
struct prog_instruction *inst;
inst = new_instruction(prog, OPCODE_END);
@ -788,8 +780,8 @@ _slang_emit_code(slang_ir_node *n, slang_gen_context *gc,
success = GL_FALSE;
}
#if 0
printf("*********** End generate code (%u inst):\n", prog->NumInstructions);
#if 0
_mesa_print_program(prog);
_mesa_print_program_parameters(ctx,prog);
#endif

View file

@ -32,10 +32,6 @@
#include "mtypes.h"
extern slang_gen_context *
_slang_new_codegen_context(void);
extern void
slang_print_ir(const slang_ir_node *n, int indent);
@ -48,15 +44,8 @@ extern slang_ir_storage *
_slang_clone_ir_storage(slang_ir_storage *store);
extern GLint
_slang_alloc_temporary(slang_gen_context *gc, GLint size);
extern void
_slang_free_temporary(slang_gen_context *gc, GLuint r, GLint size);
extern GLboolean
_slang_emit_code(slang_ir_node *n, slang_gen_context *gc,
_slang_emit_code(slang_ir_node *n, slang_var_table *vartable,
struct gl_program *prog, GLboolean withEnd);

View file

@ -45,6 +45,7 @@ typedef enum
{
IR_NOP = 0,
IR_SEQ, /* sequence (eval left, then right) */
IR_SCOPE, /* new variable scope (one child) */
IR_LABEL, /* target of a jump or cjump */
IR_JUMP, /* unconditional jump */
IR_CJUMP, /* conditional jump */

View file

@ -259,8 +259,10 @@ link_uniform_vars(struct gl_shader_program *shProg, struct gl_program *prog)
if (inst->Opcode == OPCODE_TEX ||
inst->Opcode == OPCODE_TXB ||
inst->Opcode == OPCODE_TXP) {
/*
printf("====== remap sampler from %d to %d\n",
inst->Sampler, map[ inst->Sampler ]);
*/
inst->Sampler = map[ inst->Sampler ];
}
}

View file

@ -188,7 +188,7 @@ 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)
if (s->variables[i]->a_name == name)
return s;
}
if (s->outer_scope)
@ -202,8 +202,8 @@ 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->variables[i]->a_name == name)
return s->variables[i];
}
if (s->outer_scope)
return find_var(s->outer_scope, name);
@ -621,7 +621,7 @@ slang_print_function(const slang_function *f, GLboolean body)
(char *) f->header.a_name);
for (i = 0; i < f->param_count; i++) {
print_variable(&f->parameters->variables[i], 3);
print_variable(f->parameters->variables[i], 3);
}
printf(")\n");
@ -632,199 +632,6 @@ slang_print_function(const slang_function *f, GLboolean body)
/* 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)
@ -1083,6 +890,7 @@ slang_print_type(const slang_fully_specified_type *t)
}
#if 0
static char *
slang_var_string(const slang_variable *v)
{
@ -1092,6 +900,7 @@ slang_var_string(const slang_variable *v)
slang_fq_type_string(&v->type));
return str;
}
#endif
void
@ -1111,13 +920,13 @@ _slang_print_var_scope(const slang_variable_scope *vars, int 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);
printf("%s (at %p)\n", (char *) vars->variables[i]->a_name, (void*) (vars->variables + i));
}
spaces(indent + 3);
printf("outer_scope = %p\n", (void*) vars->outer_scope);
if (vars->outer_scope) {
spaces(indent + 3);
/*spaces(indent + 3);*/
_slang_print_var_scope(vars->outer_scope, indent + 3);
}
}

View file

@ -10,10 +10,6 @@ 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);

View file

@ -126,8 +126,8 @@ static GLboolean aggregate_variables (slang_storage_aggregate *agg, slang_variab
GLuint i;
for (i = 0; i < vars->num_variables; i++)
if (!_slang_aggregate_variable (agg, &vars->variables[i].type.specifier,
vars->variables[i].array_len, funcs, structs, globals, mach, file, atoms))
if (!_slang_aggregate_variable (agg, &vars->variables[i]->type.specifier,
vars->variables[i]->array_len, funcs, structs, globals, mach, file, atoms))
return GL_FALSE;
return GL_TRUE;
}

View file

@ -0,0 +1,202 @@
#include "imports.h"
#include "slang_compile.h"
#include "slang_compile_variable.h"
#include "slang_vartable.h"
static int dbg = 0;
typedef enum {
FREE,
VAR,
TEMP
} TempState;
static int Level = 0;
struct slang_var_table_
{
int level;
int num_entries;
slang_variable **vars; /* array [num_entries] */
TempState temps[MAX_PROGRAM_TEMPS];
struct slang_var_table_ *parent;
};
/**
* Create new table, put at head, return ptr to it.
*/
slang_var_table *
_slang_push_var_table(slang_var_table *parent)
{
slang_var_table *t
= (slang_var_table *) _mesa_calloc(sizeof(slang_var_table));
if (t) {
t->level = Level++;
t->parent = parent;
if (parent) {
/* copy the info indicating which temp regs are in use */
memcpy(t->temps, parent->temps, sizeof(t->temps));
}
if (dbg) printf("Pushing level %d\n", t->level);
}
return t;
}
/**
* Destroy given table, return ptr to parent
*/
slang_var_table *
_slang_pop_var_table(slang_var_table *t)
{
slang_var_table *parent = t->parent;
int i;
if (dbg) printf("Popping level %d\n", t->level);
if (t->parent) {
for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
if (t->temps[i] && !t->parent->temps[i])
if (dbg) printf(" Free reg %d\n", i);
}
}
for (i = 0; i < t->num_entries; i++) {
if (dbg) printf(" Free var %s\n", (char*) t->vars[i]->a_name);
}
if (t->vars)
free(t->vars);
free(t);
Level--;
return parent;
}
/**
* Add a new variable to the given symbol table.
*/
void
_slang_add_variable(slang_var_table *t, slang_variable *v)
{
assert(t);
t->vars = realloc(t->vars, (t->num_entries + 1) * sizeof(slang_variable *));
t->vars[t->num_entries] = v;
t->num_entries++;
}
/**
* Look for variable by name in given table.
* If not found, parent table will be searched.
*/
slang_variable *
_slang_find_variable(const slang_var_table *t, slang_atom name)
{
while (1) {
int i;
for (i = 0; i < t->num_entries; i++) {
if (t->vars[i]->a_name == name)
return t->vars[i];
}
if (t->parent)
t = t->parent;
else
return NULL;
}
}
static GLint
alloc_reg(slang_var_table *t, GLint size, GLboolean isTemp)
{
const GLuint sz4 = (size + 3) / 4;
GLuint i, j;
assert(size > 0); /* number of floats */
for (i = 0; i < MAX_PROGRAM_TEMPS; i++) {
GLuint found = 0;
for (j = 0; j < sz4; j++) {
if (!t->temps[i + j]) {
found++;
}
else {
break;
}
}
if (found == sz4) {
/* found block of size/4 free regs */
for (j = 0; j < sz4; j++)
t->temps[i + j] = isTemp ? TEMP : VAR;
return i;
}
}
return -1;
}
/**
* Allocate temp register(s) for storing a variable.
*/
GLint
_slang_alloc_var(slang_var_table *t, GLint size)
{
int i = alloc_reg(t, size, GL_FALSE);
if (dbg) printf("Alloc var %d (level %d)\n", i, t->level);
return i;
}
void
_slang_reserve_var(slang_var_table *t, GLint r, GLint size)
{
const GLint sz4 = (size + 3) / 4;
GLint i;
for (i = 0; i < sz4; i++) {
t->temps[r + i] = VAR;
}
}
/**
* Allocate temp register(s) for storing an unnamed intermediate value.
*/
GLint
_slang_alloc_temp(slang_var_table *t, GLint size)
{
int i = alloc_reg(t, size, GL_TRUE);
if (dbg) printf("Alloc temp %d (level %d)\n", i, t->level);
return i;
}
void
_slang_free_temp(slang_var_table *t, GLint r, GLint size)
{
const GLuint sz4 = (size + 3) / 4;
GLuint i;
assert(size > 0);
assert(r >= 0);
assert(r < MAX_PROGRAM_TEMPS);
if (dbg) printf("Free temp %d (level %d)\n", r, t->level);
for (i = 0; i < sz4; i++) {
assert(t->temps[r + i] == TEMP);
t->temps[r + i] = FREE;
}
}
GLboolean
_slang_is_temp(slang_var_table *t, GLint r)
{
assert(r >= 0);
assert(r < MAX_PROGRAM_TEMPS);
if (t->temps[r] == TEMP)
return GL_TRUE;
else
return GL_FALSE;
}

View file

@ -0,0 +1,38 @@
#ifndef SLANG_VARTABLE_H
#define SLANG_VARTABLE_H
typedef struct slang_var_table_ slang_var_table;
struct slang_variable_;
extern slang_var_table *
_slang_push_var_table(slang_var_table *parent);
extern slang_var_table *
_slang_pop_var_table(slang_var_table *t);
extern void
_slang_add_variable(slang_var_table *t, struct slang_variable_ *v);
extern struct slang_variable_ *
_slang_find_variable(const slang_var_table *t, slang_atom name);
extern GLint
_slang_alloc_var(slang_var_table *t, GLint size);
extern void
_slang_reserve_var(slang_var_table *t, GLint r, GLint size);
extern GLint
_slang_alloc_temp(slang_var_table *t, GLint size);
extern void
_slang_free_temp(slang_var_table *t, GLint r, GLint size);
extern GLboolean
_slang_is_temp(slang_var_table *t, GLint r);
#endif /* SLANG_VARTABLE_H */

View file

@ -189,6 +189,7 @@ SLANG_SOURCES = \
shader/slang/slang_preprocess.c \
shader/slang/slang_simplify.c \
shader/slang/slang_storage.c \
shader/slang/slang_vartable.c \
shader/slang/slang_print.c \
shader/slang/slang_utility.c