summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian <brian@yutani.localnet.net>2007-02-23 09:38:17 -0700
committerBrian <brian@yutani.localnet.net>2007-02-23 09:38:17 -0700
commitafbf7c7e6b7613d8d219807adaf7d17971ac2e6d (patch)
treecc11a86f7d0f831f80b2f507f507a0832b55142a
parentd8d07b2a8aa5cf9c5ce877b20351983b1aa8d01d (diff)
Re-implement branching with slang_labels.
This eliminates the NOP instructions that had been used as placeholders for branch targets. Also, fix "return" statement bug.
-rw-r--r--src/mesa/shader/slang/slang_codegen.c79
-rw-r--r--src/mesa/shader/slang/slang_compile_function.h11
-rw-r--r--src/mesa/shader/slang/slang_compile_operation.h9
-rw-r--r--src/mesa/shader/slang/slang_emit.c54
-rw-r--r--src/mesa/shader/slang/slang_ir.h4
-rw-r--r--src/mesa/shader/slang/slang_link.c42
6 files changed, 76 insertions, 123 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 51c8f27c80..3d9b23693a 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -39,6 +39,7 @@
#include "slang_codegen.h"
#include "slang_compile.h"
#include "slang_error.h"
+#include "slang_label.h"
#include "slang_simplify.h"
#include "slang_emit.h"
#include "slang_vartable.h"
@@ -425,10 +426,11 @@ new_seq(slang_ir_node *left, slang_ir_node *right)
}
static slang_ir_node *
-new_label(slang_atom labName)
+new_label(slang_label *label)
{
slang_ir_node *n = new_node0(IR_LABEL);
- n->Target = (char *) labName; /*_mesa_strdup(name);*/
+ if (n)
+ n->Label = label;
return n;
}
@@ -450,11 +452,11 @@ new_float_literal(const float v[4])
* XXX maybe pass an IR node as second param to indicate the jump target???
*/
static slang_ir_node *
-new_cjump(slang_atom target, GLuint zeroOrOne)
+new_cjump(slang_label *dest, GLuint zeroOrOne)
{
slang_ir_node *n = new_node0(zeroOrOne ? IR_CJUMP1 : IR_CJUMP0);
if (n)
- n->Target = (char *) target;
+ n->Label = dest;
return n;
}
@@ -463,11 +465,11 @@ new_cjump(slang_atom target, GLuint zeroOrOne)
* XXX maybe pass an IR node as second param to indicate the jump target???
*/
static slang_ir_node *
-new_jump(slang_atom target)
+new_jump(slang_label *dest)
{
slang_ir_node *n = new_node0(IR_JUMP);
if (n)
- n->Target = (char *) target;
+ n->Label = dest;
return n;
}
@@ -599,6 +601,18 @@ slang_is_asm_function(const slang_function *fun)
}
+static GLboolean
+_slang_is_noop(const slang_operation *oper)
+{
+ if (!oper ||
+ oper->type == SLANG_OPER_VOID ||
+ (oper->num_children == 1 && oper->children[0].type == SLANG_OPER_VOID))
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}
+
+
/**
* Produce inline code for a call to an assembly instruction.
*/
@@ -709,11 +723,11 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
}
}
break;
-#if 1 /* XXX rely on default case below */
+
case SLANG_OPER_RETURN:
/* do return replacement here too */
assert(oper->num_children == 0 || oper->num_children == 1);
- if (oper->num_children == 1) {
+ if (!_slang_is_noop(oper)) {
/* replace:
* return expr;
* with:
@@ -751,7 +765,7 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
slang_operation_destruct(blockOper);
}
break;
-#endif
+
case SLANG_OPER_ASSIGN:
case SLANG_OPER_SUBSCRIPT:
/* special case:
@@ -992,8 +1006,7 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
&inlined->children,
inlined->num_children);
lab->type = SLANG_OPER_LABEL;
- lab->a_id = slang_atom_pool_atom(A->atoms,
- (char *) A->CurFunction->end_label);
+ lab->label = A->CurFunction->end_label;
}
for (i = 0; i < totalArgs; i++) {
@@ -1044,7 +1057,7 @@ _slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,
if (!A->CurFunction->end_label) {
char name[200];
sprintf(name, "__endOfFunc_%s_", (char *) A->CurFunction->header.a_name);
- A->CurFunction->end_label = slang_atom_pool_gen(A->atoms, name);
+ A->CurFunction->end_label = _slang_label_new(name);
}
if (slang_is_asm_function(fun) && !dest) {
@@ -1075,7 +1088,7 @@ _slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,
n = _slang_gen_operation(A, oper);
- A->CurFunction->end_label = NULL;
+ A->CurFunction->end_label = NULL; /* XXX delete/free? */
A->CurFunction = prevFunc;
@@ -1198,19 +1211,6 @@ _slang_gen_asm(slang_assemble_ctx *A, slang_operation *oper,
}
-
-static GLboolean
-_slang_is_noop(const slang_operation *oper)
-{
- if (!oper ||
- oper->type == SLANG_OPER_VOID ||
- (oper->num_children == 1 && oper->children[0].type == SLANG_OPER_VOID))
- return GL_TRUE;
- else
- return GL_FALSE;
-}
-
-
static void
print_funcs(struct slang_function_scope_ *scope, const char *name)
{
@@ -1617,8 +1617,7 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var)
static slang_ir_node *
_slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
{
- slang_atom altAtom = slang_atom_pool_gen(A->atoms, "__selectAlt");
- slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__selectEnd");
+ slang_label *altLabel, *endLabel;
slang_ir_node *altLab, *endLab;
slang_ir_node *tree, *tmpDecl, *tmpVar, *cond, *cjump, *jump;
slang_ir_node *bodx, *body, *assignx, *assigny;
@@ -1628,6 +1627,9 @@ _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
assert(oper->type == SLANG_OPER_SELECT);
assert(oper->num_children == 3);
+ altLabel = _slang_label_new("selectAlt");
+ endLabel = _slang_label_new("selectEnd");
+
/* size of x or y's type */
slang_typeinfo_construct(&type);
_slang_typeof_operation(A, &oper->children[1], &type);
@@ -1643,7 +1645,7 @@ _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
tree = new_seq(tmpDecl, cond);
/* jump if false to "alt" label */
- cjump = new_cjump(altAtom, 0);
+ cjump = new_cjump(altLabel, 0);
tree = new_seq(tree, cjump);
/* evaluate child 1 (x) and assign to tmp */
@@ -1654,11 +1656,11 @@ _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
tree = new_seq(tree, assigny);
/* jump to "end" label */
- jump = new_jump(endAtom);
+ jump = new_jump(endLabel);
tree = new_seq(tree, jump);
/* "alt" label */
- altLab = new_label(altAtom);
+ altLab = new_label(altLabel);
tree = new_seq(tree, altLab);
/* evaluate child 2 (y) and assign to tmp */
@@ -1669,7 +1671,7 @@ _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
tree = new_seq(tree, assignx);
/* "end" label */
- endLab = new_label(endAtom);
+ endLab = new_label(endLabel);
tree = new_seq(tree, endLab);
/* tmp var value */
@@ -1762,8 +1764,8 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
slang_operation_construct(&gotoOp);
gotoOp.type = SLANG_OPER_GOTO;
/* XXX don't call function? */
- gotoOp.a_id = slang_atom_pool_atom(A->atoms,
- (char *) A->CurFunction->end_label);
+ gotoOp.label = A->CurFunction->end_label;
+
/* assemble the new code */
n = _slang_gen_operation(A, &gotoOp);
/* destroy temp code */
@@ -1819,8 +1821,7 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
jump->type = SLANG_OPER_GOTO;
assert(A->CurFunction->end_label);
/* XXX don't call function? */
- jump->a_id = slang_atom_pool_atom(A->atoms,
- (char *) A->CurFunction->end_label);
+ jump->label = A->CurFunction->end_label;
#if 0 /* debug */
printf("NEW RETURN:\n");
@@ -2439,9 +2440,9 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
case SLANG_OPER_RETURN:
return _slang_gen_return(A, oper);
case SLANG_OPER_GOTO:
- return new_jump((char*) oper->a_id);
+ return new_jump(oper->label);
case SLANG_OPER_LABEL:
- return new_label((char*) oper->a_id);
+ return new_label(oper->label);
case SLANG_OPER_IDENTIFIER:
return _slang_gen_variable(A, oper);
case SLANG_OPER_IF:
@@ -2716,7 +2717,7 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
/* Create an end-of-function label */
if (!A->CurFunction->end_label)
- A->CurFunction->end_label = slang_atom_pool_gen(A->atoms, "__endOfFunc_main_");
+ A->CurFunction->end_label = _slang_label_new("__endOfFunc__main");
/* push new vartable scope */
_slang_push_var_table(A->vartable);
diff --git a/src/mesa/shader/slang/slang_compile_function.h b/src/mesa/shader/slang/slang_compile_function.h
index b60b4a223f..09fbfd9090 100644
--- a/src/mesa/shader/slang/slang_compile_function.h
+++ b/src/mesa/shader/slang/slang_compile_function.h
@@ -25,9 +25,6 @@
#ifndef SLANG_COMPILE_FUNCTION_H
#define SLANG_COMPILE_FUNCTION_H
-#if defined __cplusplus
-extern "C" {
-#endif
struct slang_code_unit_;
@@ -69,7 +66,11 @@ typedef struct slang_function_
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 */
+#if 0
slang_atom end_label; /**< The end-of-function label */
+#else
+ struct slang_label_ *end_label;
+#endif
} slang_function;
extern int slang_function_construct(slang_function *);
@@ -102,8 +103,4 @@ slang_function_scope_find_by_name(slang_function_scope *, slang_atom, int);
extern slang_function *
slang_function_scope_find(slang_function_scope *, slang_function *, int);
-#ifdef __cplusplus
-}
-#endif
-
#endif /* SLANG_COMPILE_FUNCTION_H */
diff --git a/src/mesa/shader/slang/slang_compile_operation.h b/src/mesa/shader/slang/slang_compile_operation.h
index a59f968456..4adcd2ab0e 100644
--- a/src/mesa/shader/slang/slang_compile_operation.h
+++ b/src/mesa/shader/slang/slang_compile_operation.h
@@ -25,10 +25,6 @@
#ifndef SLANG_COMPILE_OPERATION_H
#define SLANG_COMPILE_OPERATION_H
-#if defined __cplusplus
-extern "C" {
-#endif
-
/**
* Types of slang operations.
@@ -122,6 +118,7 @@ typedef struct slang_operation_
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 */
+ struct slang_label_ *label; /**< If type == SLANG_OPER_LABEL or GOTO */
} slang_operation;
@@ -148,8 +145,4 @@ slang_operation_insert(GLuint *numChildren, slang_operation **children,
GLuint pos);
-#ifdef __cplusplus
-}
-#endif
-
#endif /* SLANG_COMPILE_OPERATION_H */
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index 76b03753b6..6b950debf4 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -278,7 +278,7 @@ slang_print_ir(const slang_ir_node *n, int indent)
slang_print_ir(n->Children[1], indent+3);
break;
case IR_LABEL:
- printf("LABEL: %s\n", n->Target);
+ printf("LABEL: %s\n", n->Label->Name);
break;
case IR_COND:
printf("COND\n");
@@ -848,38 +848,44 @@ emit_negation(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
static struct prog_instruction *
-emit_label(const char *target, struct gl_program *prog)
+emit_label(const slang_ir_node *n, struct gl_program *prog)
{
- struct prog_instruction *inst;
- inst = new_instruction(prog, OPCODE_NOP);
- inst->Comment = _mesa_strdup(target);
- return inst;
+ assert(n->Label);
+ assert(_slang_label_get_location(n->Label) < 0);
+ _slang_label_set_location(n->Label, prog->NumInstructions, prog);
+ return NULL;
}
static struct prog_instruction *
-emit_cjump(const char *target, struct gl_program *prog, GLuint zeroOrOne)
+emit_cjump(slang_ir_node *n, struct gl_program *prog, GLuint zeroOrOne)
{
struct prog_instruction *inst;
+ assert(n->Opcode == IR_CJUMP0 || n->Opcode == IR_CJUMP1);
inst = new_instruction(prog, OPCODE_BRA);
if (zeroOrOne)
inst->DstReg.CondMask = COND_NE; /* branch if non-zero */
else
inst->DstReg.CondMask = COND_EQ; /* branch if equal to zero */
inst->DstReg.CondSwizzle = SWIZZLE_X;
- inst->Comment = _mesa_strdup(target);
+ inst->BranchTarget = _slang_label_get_location(n->Label);
+ if (inst->BranchTarget < 0) {
+ _slang_label_add_reference(n->Label, prog->NumInstructions - 1);
+ }
return inst;
}
static struct prog_instruction *
-emit_jump(const char *target, struct gl_program *prog)
+emit_jump(slang_ir_node *n, struct gl_program *prog)
{
struct prog_instruction *inst;
inst = new_instruction(prog, OPCODE_BRA);
inst->DstReg.CondMask = COND_TR; /* always branch */
- /*inst->DstReg.CondSwizzle = SWIZZLE_X;*/
- inst->Comment = _mesa_strdup(target);
+ inst->BranchTarget = _slang_label_get_location(n->Label);
+ if (inst->BranchTarget < 0) {
+ _slang_label_add_reference(n->Label, prog->NumInstructions - 1);
+ }
return inst;
}
@@ -1522,13 +1528,13 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
return emit_not(vt, n, prog);
case IR_LABEL:
- return emit_label(n->Target, prog);
+ return emit_label(n, prog);
case IR_JUMP:
- return emit_jump(n->Target, prog);
+ return emit_jump(n, prog);
case IR_CJUMP0:
- return emit_cjump(n->Target, prog, 0);
+ return emit_cjump(n, prog, 0);
case IR_CJUMP1:
- return emit_cjump(n->Target, prog, 1);
+ return emit_cjump(n, prog, 1);
case IR_KILL:
return emit_kill(prog);
@@ -1572,18 +1578,14 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt,
{
GLboolean success;
- 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);
- }
- success = GL_TRUE;
- }
- else {
- /* record an error? */
- success = GL_FALSE;
+ (void) 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);
}
+ success = GL_TRUE;
printf("*********** End generate code (%u inst):\n", prog->NumInstructions);
#if 0
diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h
index 0c827d9cd8..ba8b613112 100644
--- a/src/mesa/shader/slang/slang_ir.h
+++ b/src/mesa/shader/slang/slang_ir.h
@@ -35,6 +35,7 @@
#include "imports.h"
#include "slang_compile.h"
+#include "slang_label.h"
#include "mtypes.h"
@@ -153,7 +154,8 @@ typedef struct slang_ir_node_
slang_variable *Var; /**< If Opcode == IR_VAR or IR_VAR_DECL */
slang_ir_storage *Store; /**< location of result of this operation */
GLint InstLocation; /**< Location of instruction emitted for this node */
- struct slang_ir_node_ *BranchNode; /**< Used for branch instructions */
+ struct slang_ir_node_ *BranchNode; /**< Used for branching instructions */
+ slang_label *Label; /**< Used for branches */
} slang_ir_node;
diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c
index 23977b7c2c..e2bb6ee2d8 100644
--- a/src/mesa/shader/slang/slang_link.c
+++ b/src/mesa/shader/slang/slang_link.c
@@ -274,46 +274,6 @@ link_uniform_vars(struct gl_shader_program *shProg, struct gl_program *prog)
/**
- * XXX Temporary
- */
-static void
-_slang_resolve_branches(struct gl_program *prog)
-{
- struct target {
- const char *Name;
- GLuint Pos;
- };
- struct target targets[500];
- GLuint numTargets = 0;
- GLuint i, j;
-
- for (i = 0; i < prog->NumInstructions; i++) {
- struct prog_instruction *inst = prog->Instructions + i;
- if (inst->Opcode == OPCODE_NOP && inst->Comment) {
- targets[numTargets].Name = inst->Comment;
- targets[numTargets].Pos = i;
- numTargets++;
- }
- }
-
- for (i = 0; i < prog->NumInstructions; i++) {
- struct prog_instruction *inst = prog->Instructions + i;
- if (inst->Opcode == OPCODE_BRA && inst->BranchTarget < 0) {
- for (j = 0; j < numTargets; j++) {
- if (!strcmp(inst->Comment, targets[j].Name)) {
- inst->BranchTarget = targets[j].Pos;
- break;
- }
- }
- if (j == numTargets) {
- abort();
- }
- }
- }
-}
-
-
-/**
* Resolve binding of generic vertex attributes.
* For example, if the vertex shader declared "attribute vec4 foobar" we'll
* allocate a generic vertex attribute for "foobar" and plug that value into
@@ -574,11 +534,9 @@ _slang_link(GLcontext *ctx,
}
if (shProg->VertexProgram) {
- _slang_resolve_branches(&shProg->VertexProgram->Base);
_slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
}
if (shProg->FragmentProgram) {
- _slang_resolve_branches(&shProg->FragmentProgram->Base);
_slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
}