summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mesa/shader/slang/slang_codegen.c79
-rw-r--r--src/mesa/shader/slang/slang_emit.c35
-rw-r--r--src/mesa/shader/slang/slang_ir.h3
-rw-r--r--src/mesa/shader/slang/slang_typeinfo.h1
4 files changed, 58 insertions, 60 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 88d61a5a68..a4e2935ea8 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -490,10 +490,12 @@ static void
_slang_free_ir_tree(slang_ir_node *n)
{
#if 0
+ GLuint i;
if (!n)
return;
- _slang_free_ir_tree(n->Children[0]);
- _slang_free_ir_tree(n->Children[1]);
+ for (i = 0; i < 3; i++)
+ _slang_free_ir_tree(n->Children[i]);
+ /* Do not free n->BranchNode since it's a child elsewhere */
free(n);
#endif
}
@@ -537,9 +539,10 @@ new_node0(slang_ir_opcode op)
static slang_ir_node *
new_seq(slang_ir_node *left, slang_ir_node *right)
{
- /* XXX if either left or right is null, just return pointer to other?? */
- assert(left);
- assert(right);
+ if (!left)
+ return right;
+ if (!right)
+ return left;
return new_node2(IR_SEQ, left, right);
}
@@ -592,32 +595,20 @@ new_jump(slang_atom target)
static slang_ir_node *
-new_begin_loop(void)
-{
- slang_ir_node *n = new_node0(IR_BEGIN_LOOP);
- return n;
-}
-
-
-static slang_ir_node *
-new_end_loop(slang_ir_node *beginNode)
+new_loop(slang_ir_node *body)
{
- slang_ir_node *n = new_node0(IR_END_LOOP);
- assert(beginNode);
- if (n) {
- n->BranchNode = beginNode;
- }
- return n;
+ return new_node1(IR_LOOP, body);
}
static slang_ir_node *
-new_break(slang_ir_node *beginNode)
+new_break(slang_ir_node *loopNode)
{
slang_ir_node *n = new_node0(IR_BREAK);
- assert(beginNode);
+ assert(loopNode);
+ assert(loopNode->Opcode == IR_LOOP);
if (n) {
- n->BranchNode = beginNode;
+ n->BranchNode = loopNode;
}
return n;
}
@@ -1415,43 +1406,43 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
/**
- * Generate IR tree for a while-loop using high-level BGNLOOP/ENDLOOP,
- * IF/ENDIF instructions.
+ * Generate IR tree for a while-loop using high-level LOOP, IF instructions.
*/
static slang_ir_node *
_slang_gen_hl_while(slang_assemble_ctx * A, const slang_operation *oper)
{
+ slang_ir_node *prevLoop;
/*
- * BGNLOOP
+ * LOOP:
* eval expr (child[0]), updating condcodes
- * IF !expr THEN
+ * IF !expr:
* BRK
- * ENDIF
* body code (child[1])
- * ENDLOOP
*/
- slang_ir_node *beginLoop, *endLoop, *ifThen;
- slang_ir_node *cond, *body, *tree;
+ slang_ir_node *ifThen, *cond, *body, *loop;
- beginLoop = new_begin_loop();
+ loop = new_loop(NULL);
+
+ /* save old, push new loop */
+ prevLoop = A->CurLoop;
+ A->CurLoop = loop;
cond = _slang_gen_operation(A, &oper->children[0]);
cond = new_node1(IR_NOT, cond);
cond = _slang_gen_cond(cond);
ifThen = new_if(cond,
- new_break(beginLoop),
+ new_break(A->CurLoop),
NULL);
- tree = new_seq(beginLoop, ifThen);
body = _slang_gen_operation(A, &oper->children[1]);
- if (body)
- tree = new_seq(tree, body);
- endLoop = new_end_loop(beginLoop);
- tree = new_seq(tree, endLoop);
+ loop->Children[0] = new_seq(ifThen, body);
- return tree;
+
+ A->CurLoop = prevLoop; /* pop loop, restore prev */
+
+ return loop;
}
@@ -2433,11 +2424,15 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
else
return _slang_gen_for(A, oper);
case slang_oper_break:
- if (!A->CurLoopBreak) {
+ if (!A->CurLoop && !A->CurLoopBreak) {
RETURN_ERROR("'break' not in loop", 0);
}
- /* XXX emit IR_BREAK instruction */
- return new_jump(A->CurLoopBreak);
+ if (UseHighLevelInstructions) {
+ return new_break(A->CurLoop);
+ }
+ else {
+ return new_jump(A->CurLoopBreak);
+ }
case slang_oper_continue:
if (!A->CurLoopCont) {
RETURN_ERROR("'continue' not in loop", 0);
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index 82a8f0befb..c18f1e364c 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -317,11 +317,11 @@ slang_print_ir(const slang_ir_node *n, int indent)
printf("CALL\n");
break;
- case IR_BEGIN_LOOP:
- printf("BEGIN_LOOP\n");
- break;
- case IR_END_LOOP:
- printf("END_LOOP\n");
+ case IR_LOOP:
+ printf("LOOP\n");
+ slang_print_ir(n->Children[0], indent+3);
+ spaces(indent);
+ printf("ENDLOOP\n");
break;
case IR_CONT:
printf("CONT\n");
@@ -1301,23 +1301,22 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
case IR_IF:
return emit_if(vt, n, prog);
- case IR_BEGIN_LOOP:
+ case IR_LOOP:
{
+ struct prog_instruction *beginInst;
+
/* save location of this instruction, used by OPCODE_ENDLOOP */
n->InstLocation = prog->NumInstructions;
(void) new_instruction(prog, OPCODE_BGNLOOP);
- }
- break;
- case IR_END_LOOP:
- {
- struct prog_instruction *inst, *beginInst;
+
+ /* body */
+ emit(vt, n->Children[0], prog);
+
inst = new_instruction(prog, OPCODE_ENDLOOP);
- assert(n->BranchNode);
- assert(n->BranchNode->InstLocation >= 0);
/* The instruction BranchTarget points to top of loop */
- inst->BranchTarget = n->BranchNode->InstLocation;
- /* Update BEGIN_LOOP's BranchTarget to point to this instruction */
- beginInst = prog->Instructions + n->BranchNode->InstLocation;
+ inst->BranchTarget = n->InstLocation;
+ /* Update BGNLOOP's BranchTarget to point to this instruction */
+ beginInst = prog->Instructions + n->InstLocation;
beginInst->BranchTarget = prog->NumInstructions - 1;
return inst;
}
@@ -1336,6 +1335,7 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
inst->BranchTarget = n->BranchNode->InstLocation;
return inst;
}
+
case IR_BEGIN_SUB:
return new_instruction(prog, OPCODE_BGNSUB);
case IR_END_SUB:
@@ -1343,6 +1343,9 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
case IR_RETURN:
return new_instruction(prog, OPCODE_RET);
+ case IR_NOP:
+ return NULL;
+
default:
_mesa_problem(NULL, "Unexpected IR opcode in emit()\n");
abort();
diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h
index 0f2ceb03c0..a7c858c69f 100644
--- a/src/mesa/shader/slang/slang_ir.h
+++ b/src/mesa/shader/slang/slang_ir.h
@@ -60,8 +60,7 @@ typedef enum
IR_RETURN, /* return from subroutine */
IR_CALL, /* call subroutine */
- IR_BEGIN_LOOP,/* begin loop */
- IR_END_LOOP, /* end loop */
+ IR_LOOP, /* high-level loop-begin / loop-end */
IR_CONT, /* continue loop */
IR_BREAK, /* break loop */
diff --git a/src/mesa/shader/slang/slang_typeinfo.h b/src/mesa/shader/slang/slang_typeinfo.h
index 6e27079ff8..d23bb6be14 100644
--- a/src/mesa/shader/slang/slang_typeinfo.h
+++ b/src/mesa/shader/slang/slang_typeinfo.h
@@ -63,6 +63,7 @@ typedef struct slang_assemble_ctx_
struct slang_function_ *CurFunction;
slang_atom CurLoopBreak;
slang_atom CurLoopCont;
+ struct slang_ir_node_ *CurLoop;
} slang_assemble_ctx;