mesa: Branch 'glsl-compiler-1' - 5 commits
Brian Paul
brianp at kemper.freedesktop.org
Thu Feb 8 05:28:38 UTC 2007
src/mesa/shader/prog_print.c | 2
src/mesa/shader/slang/slang_codegen.c | 256 ++++++---------------------------
src/mesa/shader/slang/slang_emit.c | 179 ++++++++++++++---------
src/mesa/shader/slang/slang_ir.h | 7
src/mesa/shader/slang/slang_link.c | 2
src/mesa/shader/slang/slang_typeinfo.h | 2
src/mesa/swrast/s_fragprog.c | 12 -
7 files changed, 179 insertions(+), 281 deletions(-)
New commits:
diff-tree 2c75ef62ea8dfd690aab6fa4f2c85afba569a21f (from b35b4566c2d3bbf21c8fd955912f4c3c671f2bb9)
Author: Brian <brian at nostromo.localnet.net>
Date: Wed Feb 7 16:19:19 2007 -0700
remove old loop break/cont stuff
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 61b5df5..bd7b30c 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -2295,25 +2295,15 @@ _slang_gen_operation(slang_assemble_ctx
case slang_oper_while:
return _slang_gen_while(A, oper);
case slang_oper_break:
- if (!A->CurLoop && !A->CurLoopBreak) {
+ if (!A->CurLoop) {
RETURN_ERROR("'break' not in loop", 0);
}
- if (UseHighLevelInstructions) {
- return new_break(A->CurLoop);
- }
- else {
- return new_jump(A->CurLoopBreak);
- }
+ return new_break(A->CurLoop);
case slang_oper_continue:
- if (!A->CurLoop && !A->CurLoopCont) {
+ if (!A->CurLoop) {
RETURN_ERROR("'continue' not in loop", 0);
}
- if (UseHighLevelInstructions) {
- return new_cont(A->CurLoop);
- }
- else {
- return new_jump(A->CurLoopCont);
- }
+ return new_cont(A->CurLoop);
case slang_oper_discard:
return new_node0(IR_KILL);
diff --git a/src/mesa/shader/slang/slang_typeinfo.h b/src/mesa/shader/slang/slang_typeinfo.h
index d23bb6b..0f72fad 100644
--- a/src/mesa/shader/slang/slang_typeinfo.h
+++ b/src/mesa/shader/slang/slang_typeinfo.h
@@ -61,8 +61,6 @@ typedef struct slang_assemble_ctx_
struct gl_program *program;
slang_var_table *vartable;
struct slang_function_ *CurFunction;
- slang_atom CurLoopBreak;
- slang_atom CurLoopCont;
struct slang_ir_node_ *CurLoop;
} slang_assemble_ctx;
diff-tree b35b4566c2d3bbf21c8fd955912f4c3c671f2bb9 (from c5e6bf63e6f8256c9e10bbbe8fb7a38de9d22921)
Author: Brian <brian at nostromo.localnet.net>
Date: Wed Feb 7 16:11:00 2007 -0700
high vs. low level if/then/else code emit
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index 2958837..6e2394f 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -43,7 +43,7 @@
#define ANNOTATE 1
-static GLboolean EmitHighLevelInstructions = GL_FALSE;
+static GLboolean EmitHighLevelInstructions = GL_TRUE;
/**
@@ -523,9 +523,9 @@ storage_annotation(const slang_ir_node *
if (st->Index >= 0) {
const GLfloat *val = prog->Parameters->ParameterValues[st->Index];
if (st->Swizzle == SWIZZLE_NOOP)
- sprintf(s, "{%f, %f, %f, %f}", val[0], val[1], val[2], val[3]);
+ sprintf(s, "{%g, %g, %g, %g}", val[0], val[1], val[2], val[3]);
else {
- sprintf(s, "%f", val[GET_SWZ(st->Swizzle, 0)]);
+ sprintf(s, "%g", val[GET_SWZ(st->Swizzle, 0)]);
}
}
break;
@@ -1059,28 +1059,50 @@ emit_if(slang_var_table *vt, slang_ir_no
emit(vt, n->Children[0], prog); /* the condition */
ifInstLoc = prog->NumInstructions;
- ifInst = new_instruction(prog, OPCODE_IF);
- ifInst->DstReg.CondMask = COND_NE; /* if cond is non-zero */
- ifInst->DstReg.CondSwizzle = SWIZZLE_X;
+ if (EmitHighLevelInstructions) {
+ ifInst = new_instruction(prog, OPCODE_IF);
+ ifInst->DstReg.CondMask = COND_NE; /* if cond is non-zero */
+ ifInst->DstReg.CondSwizzle = SWIZZLE_X;
+ }
+ else {
+ /* conditional jump to else, or endif */
+ ifInst = new_instruction(prog, OPCODE_BRA);
+ ifInst->DstReg.CondMask = COND_EQ; /* BRA if cond is zero */
+ ifInst->DstReg.CondSwizzle = SWIZZLE_X;
+ ifInst->Comment = _mesa_strdup("if zero");
+ }
/* if body */
emit(vt, n->Children[1], prog);
if (n->Children[2]) {
- /* else body */
+ /* have else body */
elseInstLoc = prog->NumInstructions;
- (void) new_instruction(prog, OPCODE_ELSE);
+ if (EmitHighLevelInstructions) {
+ (void) new_instruction(prog, OPCODE_ELSE);
+ }
+ else {
+ /* jump to endif instruction */
+ struct prog_instruction *inst;
+ inst = new_instruction(prog, OPCODE_BRA);
+ inst->Comment = _mesa_strdup("else");
+ inst->DstReg.CondMask = COND_TR; /* always branch */
+ }
ifInst = prog->Instructions + ifInstLoc;
ifInst->BranchTarget = prog->NumInstructions;
emit(vt, n->Children[2], prog);
}
else {
+ /* no else body */
ifInst = prog->Instructions + ifInstLoc;
ifInst->BranchTarget = prog->NumInstructions + 1;
}
- (void) new_instruction(prog, OPCODE_ENDIF);
+ if (EmitHighLevelInstructions) {
+ (void) new_instruction(prog, OPCODE_ENDIF);
+ }
+
if (n->Children[2]) {
struct prog_instruction *elseInst;
elseInst = prog->Instructions + elseInstLoc;
@@ -1090,6 +1112,85 @@ emit_if(slang_var_table *vt, slang_ir_no
}
+static struct prog_instruction *
+emit_loop(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
+{
+ struct prog_instruction *beginInst, *endInst;
+ GLuint beginInstLoc, endInstLoc;
+ slang_ir_node *ir;
+
+ /* emit OPCODE_BGNLOOP */
+ beginInstLoc = prog->NumInstructions;
+ if (EmitHighLevelInstructions) {
+ (void) new_instruction(prog, OPCODE_BGNLOOP);
+ }
+
+ /* body */
+ emit(vt, n->Children[0], prog);
+
+ endInstLoc = prog->NumInstructions;
+ if (EmitHighLevelInstructions) {
+ /* emit OPCODE_ENDLOOP */
+ endInst = new_instruction(prog, OPCODE_ENDLOOP);
+ }
+ else {
+ /* emit unconditional BRA-nch */
+ endInst = new_instruction(prog, OPCODE_BRA);
+ endInst->DstReg.CondMask = COND_TR; /* always true */
+ }
+ /* end instruction's BranchTarget points to top of loop */
+ endInst->BranchTarget = beginInstLoc;
+
+ if (EmitHighLevelInstructions) {
+ /* BGNLOOP's BranchTarget points to the ENDLOOP inst */
+ beginInst = prog->Instructions + beginInstLoc;
+ beginInst->BranchTarget = prog->NumInstructions - 1;
+ }
+
+ /* Done emitting loop code. Now walk over the loop's linked list
+ * of BREAK and CONT nodes, filling in their BranchTarget fields
+ * (which will point to the ENDLOOP or ENDLOOP+1 instructions).
+ */
+ for (ir = n->BranchNode; ir; ir = ir->BranchNode) {
+ struct prog_instruction *inst = prog->Instructions + ir->InstLocation;
+ if (ir->Opcode == IR_BREAK) {
+ assert(inst->Opcode == OPCODE_BRK ||
+ inst->Opcode == OPCODE_BRA);
+ inst->BranchTarget = endInstLoc + 1;
+ }
+ else {
+ assert(ir->Opcode == IR_CONT);
+ assert(inst->Opcode == OPCODE_CONT ||
+ inst->Opcode == OPCODE_BRA);
+ /* XXX goto top of loop instead! */
+ inst->BranchTarget = endInstLoc;
+ }
+ }
+ return NULL;
+}
+
+
+/**
+ * Emit code for IR_CONT or IR_BREAK.
+ */
+static struct prog_instruction *
+emit_cont_break(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
+{
+ gl_inst_opcode opcode;
+ struct prog_instruction *inst;
+ n->InstLocation = prog->NumInstructions;
+ if (EmitHighLevelInstructions) {
+ opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK;
+ }
+ else {
+ opcode = OPCODE_BRA;
+ }
+ inst = new_instruction(prog, opcode);
+ inst->DstReg.CondMask = COND_TR; /* always true */
+ return inst;
+}
+
+
/**
* Remove any SWIZZLE_NIL terms from given swizzle mask (smear prev term).
* Ex: fix_swizzle("zyNN") -> "zyyy"
@@ -1305,77 +1406,11 @@ emit(slang_var_table *vt, slang_ir_node
return emit_if(vt, n, prog);
case IR_LOOP:
- {
- struct prog_instruction *beginInst, *endInst;
- GLuint beginInstLoc, endInstLoc;
- slang_ir_node *ir;
-
- /* emit OPCODE_BGNLOOP */
- beginInstLoc = prog->NumInstructions;
- if (EmitHighLevelInstructions) {
- (void) new_instruction(prog, OPCODE_BGNLOOP);
- }
-
- /* body */
- emit(vt, n->Children[0], prog);
-
- endInstLoc = prog->NumInstructions;
- if (EmitHighLevelInstructions) {
- /* emit OPCODE_ENDLOOP */
- endInst = new_instruction(prog, OPCODE_ENDLOOP);
- }
- else {
- /* emit unconditional BRA-nch */
- endInst = new_instruction(prog, OPCODE_BRA);
- endInst->DstReg.CondMask = COND_TR; /* always true */
- }
- /* end instruction's BranchTarget points to top of loop */
- endInst->BranchTarget = beginInstLoc;
-
- if (EmitHighLevelInstructions) {
- /* BGNLOOP's BranchTarget points to the ENDLOOP inst */
- beginInst = prog->Instructions + beginInstLoc;
- beginInst->BranchTarget = prog->NumInstructions - 1;
- }
-
- /* Done emitting loop code. Now walk over the loop's linked list
- * of BREAK and CONT nodes, filling in their BranchTarget fields
- * (which will point to the ENDLOOP or ENDLOOP+1 instructions).
- */
- for (ir = n->BranchNode; ir; ir = ir->BranchNode) {
- struct prog_instruction *inst
- = prog->Instructions + ir->InstLocation;
- if (ir->Opcode == IR_BREAK) {
- assert(inst->Opcode == OPCODE_BRK ||
- inst->Opcode == OPCODE_BRA);
- inst->BranchTarget = endInstLoc + 1;
- }
- else {
- assert(ir->Opcode == IR_CONT);
- assert(inst->Opcode == OPCODE_CONT ||
- inst->Opcode == OPCODE_BRA);
- inst->BranchTarget = endInstLoc;
- }
- }
- return NULL;
- }
+ return emit_loop(vt, n, prog);
case IR_BREAK:
/* fall-through */
case IR_CONT:
- {
- gl_inst_opcode opcode;
- struct prog_instruction *inst;
- n->InstLocation = prog->NumInstructions;
- if (EmitHighLevelInstructions) {
- opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK;
- }
- else {
- opcode = OPCODE_BRA;
- }
- inst = new_instruction(prog, opcode);
- inst->DstReg.CondMask = COND_TR; /* always true */
- return inst;
- }
+ return emit_cont_break(vt, n, prog);
case IR_BEGIN_SUB:
return new_instruction(prog, OPCODE_BGNSUB);
diff-tree c5e6bf63e6f8256c9e10bbbe8fb7a38de9d22921 (from a7c2c7d6b28570230fb1b4fbc47b94581ef7e6fa)
Author: Brian <brian at nostromo.localnet.net>
Date: Wed Feb 7 16:09:13 2007 -0700
s/%f/%g/
diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c
index 6c303de..0adb589 100644
--- a/src/mesa/shader/prog_print.c
+++ b/src/mesa/shader/prog_print.c
@@ -429,7 +429,7 @@ _mesa_print_parameter_list(const struct
for (i = 0; i < list->NumParameters; i++){
struct gl_program_parameter *param = list->Parameters + i;
const GLfloat *v = list->ParameterValues[i];
- _mesa_printf("param[%d] sz=%d %s %s = {%.3f, %.3f, %.3f, %.3f};\n",
+ _mesa_printf("param[%d] sz=%d %s %s = {%.3g, %.3g, %.3g, %.3g};\n",
i, param->Size,
program_file_string(list->Parameters[i].Type),
param->Name, v[0], v[1], v[2], v[3]);
diff-tree a7c2c7d6b28570230fb1b4fbc47b94581ef7e6fa (from 4aa487e7968d015af4fe729f697105448fcb843f)
Author: Brian <brian at nostromo.localnet.net>
Date: Wed Feb 7 15:14:20 2007 -0700
Remove old functions for generating BRA-based looping.
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 14870f5..61b5df5 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -1373,60 +1373,10 @@ _slang_gen_function_call_name(slang_asse
/**
- * Generate IR tree for a while-loop. Use BRA-nch instruction.
- */
-static slang_ir_node *
-_slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
-{
- /*
- * label "__startWhile"
- * eval expr (child[0]), updating condcodes
- * branch if false to "__endWhile"
- * body code
- * jump "__startWhile"
- * label "__endWhile"
- */
- slang_atom startAtom = slang_atom_pool_gen(A->atoms, "__startWhile");
- slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__endWhile");
- slang_ir_node *startLab, *cond, *bra, *body, *jump, *endLab, *tree;
- slang_atom prevLoopBreak = A->CurLoopBreak;
- slang_atom prevLoopCont = A->CurLoopCont;
-
- /* Push this loop */
- A->CurLoopBreak = endAtom;
- A->CurLoopCont = startAtom;
-
- startLab = new_label(startAtom);
- cond = _slang_gen_operation(A, &oper->children[0]);
- cond = _slang_gen_cond(cond);
- tree = new_seq(startLab, cond);
-
- bra = new_cjump(endAtom, 0);
- tree = new_seq(tree, bra);
-
- body = _slang_gen_operation(A, &oper->children[1]);
- if (body)
- tree = new_seq(tree, body);
-
- jump = new_jump(startAtom);
- tree = new_seq(tree, jump);
-
- endLab = new_label(endAtom);
- tree = new_seq(tree, endLab);
-
- /* Pop this loop */
- A->CurLoopBreak = prevLoopBreak;
- A->CurLoopCont = prevLoopCont;
-
- return tree;
-}
-
-
-/**
* Generate loop code using high-level IR_LOOP instruction
*/
static slang_ir_node *
-_slang_gen_hl_while(slang_assemble_ctx * A, const slang_operation *oper)
+_slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
{
slang_ir_node *prevLoop;
/*
@@ -1464,56 +1414,10 @@ _slang_gen_hl_while(slang_assemble_ctx *
/**
- * Generate IR tree for a do-while-loop.
- */
-static slang_ir_node *
-_slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper)
-{
- /*
- * label "__startDo"
- * code body
- * eval expr (child[0]), updating condcodes
- * branch if true to "__startDo"
- * label "__endDo"
- */
- slang_atom startAtom = slang_atom_pool_gen(A->atoms, "__startDo");
- slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__endDo");
- slang_ir_node *startLab, *cond, *bra, *body, *endLab, *tree;
- slang_atom prevLoopBreak = A->CurLoopBreak;
- slang_atom prevLoopCont = A->CurLoopCont;
-
- /* Push this loop */
- A->CurLoopBreak = endAtom;
- A->CurLoopCont = startAtom;
-
- startLab = new_label(startAtom);
-
- body = _slang_gen_operation(A, &oper->children[0]);
- tree = new_seq(startLab, body);
-
- cond = _slang_gen_operation(A, &oper->children[1]);
- cond = _slang_gen_cond(cond);
- tree = new_seq(tree, cond);
-
- bra = new_cjump(startAtom, 1);
- tree = new_seq(tree, bra);
-
- endLab = new_label(endAtom);
- tree = new_seq(tree, endLab);
-
- /* Pop this loop */
- A->CurLoopBreak = prevLoopBreak;
- A->CurLoopCont = prevLoopCont;
-
- return tree;
-}
-
-
-/**
* Generate IR tree for a do-while loop using high-level LOOP, IF instructions.
*/
static slang_ir_node *
-_slang_gen_hl_do(slang_assemble_ctx * A, const slang_operation *oper)
+_slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper)
{
slang_ir_node *prevLoop;
/*
@@ -1550,73 +1454,10 @@ _slang_gen_hl_do(slang_assemble_ctx * A,
/**
- * Generate IR tree for a for-loop.
- */
-static slang_ir_node *
-_slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
-{
- /*
- * init code (child[0])
- * label "__startFor"
- * eval expr (child[1]), updating condcodes
- * branch if false to "__endFor"
- * code body (child[3])
- * label "__continueFor"
- * incr code (child[2])
- * jump "__startFor"
- * label "__endFor"
- */
- slang_atom startAtom = slang_atom_pool_gen(A->atoms, "__startFor");
- slang_atom contAtom = slang_atom_pool_gen(A->atoms, "__continueFor");
- slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__endFor");
- slang_ir_node *init, *startLab, *cond, *bra, *body, *contLab;
- slang_ir_node *incr, *jump, *endLab, *tree;
- slang_atom prevLoopBreak = A->CurLoopBreak;
- slang_atom prevLoopCont = A->CurLoopCont;
-
- /* Push this loop */
- A->CurLoopBreak = endAtom;
- A->CurLoopCont = contAtom;
-
- init = _slang_gen_operation(A, &oper->children[0]);
- startLab = new_label(startAtom);
- tree = new_seq(init, startLab);
-
- cond = _slang_gen_operation(A, &oper->children[1]);
- cond = _slang_gen_cond(cond);
- tree = new_seq(tree, cond);
-
- bra = new_cjump(endAtom, 0);
- tree = new_seq(tree, bra);
-
- body = _slang_gen_operation(A, &oper->children[3]);
- tree = new_seq(tree, body);
-
- contLab = new_label(contAtom);
- tree = new_seq(tree, contLab);
-
- incr = _slang_gen_operation(A, &oper->children[2]);
- tree = new_seq(tree, incr);
-
- jump = new_jump(startAtom);
- tree = new_seq(tree, jump);
-
- endLab = new_label(endAtom);
- tree = new_seq(tree, endLab);
-
- /* Pop this loop */
- A->CurLoopBreak = prevLoopBreak;
- A->CurLoopCont = prevLoopCont;
-
- return tree;
-}
-
-
-/**
* Generate for-loop using high-level IR_LOOP instruction.
*/
static slang_ir_node *
-_slang_gen_hl_for(slang_assemble_ctx * A, const slang_operation *oper)
+_slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
{
slang_ir_node *prevLoop;
/*
@@ -2447,21 +2288,12 @@ _slang_gen_operation(slang_assemble_ctx
case slang_oper_expression:
return _slang_gen_operation(A, &oper->children[0]);
break;
- case slang_oper_while:
- if (UseHighLevelInstructions)
- return _slang_gen_hl_while(A, oper);
- else
- return _slang_gen_while(A, oper);
- case slang_oper_do:
- if (UseHighLevelInstructions)
- return _slang_gen_hl_do(A, oper);
- else
- return _slang_gen_do(A, oper);
case slang_oper_for:
- if (UseHighLevelInstructions)
- return _slang_gen_hl_for(A, oper);
- else
- return _slang_gen_for(A, oper);
+ return _slang_gen_for(A, oper);
+ case slang_oper_do:
+ return _slang_gen_do(A, oper);
+ case slang_oper_while:
+ return _slang_gen_while(A, oper);
case slang_oper_break:
if (!A->CurLoop && !A->CurLoopBreak) {
RETURN_ERROR("'break' not in loop", 0);
diff-tree 4aa487e7968d015af4fe729f697105448fcb843f (from 1f99a7514e9c36b7ce2c6c1724a6584790656415)
Author: Brian <brian at nostromo.localnet.net>
Date: Wed Feb 7 15:12:13 2007 -0700
Use IR_LOOP to represent do-while and for-loops.
Also, start moving high vs. low-level instruction selection into slang_emit.c
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 42c1f08..14870f5 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -1423,7 +1423,7 @@ _slang_gen_while(slang_assemble_ctx * A,
/**
- * Generate IR tree for a while-loop using high-level LOOP, IF instructions.
+ * Generate loop code using high-level IR_LOOP instruction
*/
static slang_ir_node *
_slang_gen_hl_while(slang_assemble_ctx * A, const slang_operation *oper)
@@ -1510,6 +1510,46 @@ _slang_gen_do(slang_assemble_ctx * A, co
/**
+ * Generate IR tree for a do-while loop using high-level LOOP, IF instructions.
+ */
+static slang_ir_node *
+_slang_gen_hl_do(slang_assemble_ctx * A, const slang_operation *oper)
+{
+ slang_ir_node *prevLoop;
+ /*
+ * LOOP:
+ * body code (child[0])
+ * eval expr (child[1]), updating condcodes
+ * IF !expr:
+ * BRK
+ */
+ slang_ir_node *ifThen, *cond, *body, *loop;
+
+ loop = new_loop(NULL);
+
+ /* save old, push new loop */
+ prevLoop = A->CurLoop;
+ A->CurLoop = loop;
+
+ body = _slang_gen_operation(A, &oper->children[0]);
+
+ cond = _slang_gen_operation(A, &oper->children[1]);
+ cond = new_node1(IR_NOT, cond);
+ cond = _slang_gen_cond(cond);
+
+ ifThen = new_if(cond,
+ new_break(A->CurLoop),
+ NULL);
+
+ loop->Children[0] = new_seq(body, ifThen);
+
+ A->CurLoop = prevLoop; /* pop loop, restore prev */
+
+ return loop;
+}
+
+
+/**
* Generate IR tree for a for-loop.
*/
static slang_ir_node *
@@ -1573,69 +1613,48 @@ _slang_gen_for(slang_assemble_ctx * A, c
/**
- * Generate IR tree for a for-loop, using high-level BGNLOOP/ENDLOOP and
- * IF/ENDIF instructions.
- *
- * XXX note done yet!
+ * Generate for-loop using high-level IR_LOOP instruction.
*/
static slang_ir_node *
_slang_gen_hl_for(slang_assemble_ctx * A, const slang_operation *oper)
{
+ slang_ir_node *prevLoop;
/*
- * init code (child[0])
- * BGNLOOP
+ * init (child[0])
+ * LOOP:
* eval expr (child[1]), updating condcodes
- * IF !expr THEN
+ * IF !expr:
* BRK
- * ENDIF
- * code body (child[3])
- * label "__continueFor" // jump here for "continue"
- * incr code (child[2])
- * ENDLOOP
+ * body code (child[3])
+ * incr code (child[2]) // XXX continue here
*/
- slang_atom startAtom = slang_atom_pool_gen(A->atoms, "__startFor");
- slang_atom contAtom = slang_atom_pool_gen(A->atoms, "__continueFor");
- slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__endFor");
- slang_ir_node *init, *startLab, *cond, *bra, *body, *contLab;
- slang_ir_node *incr, *jump, *endLab, *tree;
- slang_atom prevLoopBreak = A->CurLoopBreak;
- slang_atom prevLoopCont = A->CurLoopCont;
-
- /* Push this loop */
- A->CurLoopBreak = endAtom;
- A->CurLoopCont = contAtom;
+ slang_ir_node *init, *ifThen, *cond, *body, *loop, *incr;
init = _slang_gen_operation(A, &oper->children[0]);
- startLab = new_label(startAtom);
- tree = new_seq(init, startLab);
+ loop = new_loop(NULL);
+
+ /* save old, push new loop */
+ prevLoop = A->CurLoop;
+ A->CurLoop = loop;
cond = _slang_gen_operation(A, &oper->children[1]);
+ cond = new_node1(IR_NOT, cond);
cond = _slang_gen_cond(cond);
- tree = new_seq(tree, cond);
- bra = new_cjump(endAtom, 0);
- tree = new_seq(tree, bra);
+ ifThen = new_if(cond,
+ new_break(A->CurLoop),
+ NULL);
body = _slang_gen_operation(A, &oper->children[3]);
- tree = new_seq(tree, body);
-
- contLab = new_label(contAtom);
- tree = new_seq(tree, contLab);
incr = _slang_gen_operation(A, &oper->children[2]);
- tree = new_seq(tree, incr);
-
- jump = new_jump(startAtom);
- tree = new_seq(tree, jump);
- endLab = new_label(endAtom);
- tree = new_seq(tree, endLab);
+ loop->Children[0] = new_seq(ifThen,
+ new_seq(body,incr));
- /* Pop this loop */
- A->CurLoopBreak = prevLoopBreak;
- A->CurLoopCont = prevLoopCont;
+ A->CurLoop = prevLoop; /* pop loop, restore prev */
- return tree;
+ return new_seq(init, loop);
}
@@ -2434,7 +2453,10 @@ _slang_gen_operation(slang_assemble_ctx
else
return _slang_gen_while(A, oper);
case slang_oper_do:
- return _slang_gen_do(A, oper);
+ if (UseHighLevelInstructions)
+ return _slang_gen_hl_do(A, oper);
+ else
+ return _slang_gen_do(A, oper);
case slang_oper_for:
if (UseHighLevelInstructions)
return _slang_gen_hl_for(A, oper);
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index 2d5a7cf..2958837 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -43,6 +43,9 @@
#define ANNOTATE 1
+static GLboolean EmitHighLevelInstructions = GL_FALSE;
+
+
/**
* Assembly and IR info
*/
@@ -1304,57 +1307,72 @@ emit(slang_var_table *vt, slang_ir_node
case IR_LOOP:
{
struct prog_instruction *beginInst, *endInst;
- GLuint endInstLoc;
- slang_ir_node *p;
+ GLuint beginInstLoc, endInstLoc;
+ slang_ir_node *ir;
- /* save location of this instruction, used by OPCODE_ENDLOOP */
- n->InstLocation = prog->NumInstructions;
- (void) new_instruction(prog, OPCODE_BGNLOOP);
+ /* emit OPCODE_BGNLOOP */
+ beginInstLoc = prog->NumInstructions;
+ if (EmitHighLevelInstructions) {
+ (void) new_instruction(prog, OPCODE_BGNLOOP);
+ }
/* body */
emit(vt, n->Children[0], prog);
endInstLoc = prog->NumInstructions;
- endInst = new_instruction(prog, OPCODE_ENDLOOP);
- /* The ENDLOOP's BranchTarget points to top of loop */
- endInst->BranchTarget = n->InstLocation;
- /* Update BGNLOOP's BranchTarget to point to this instruction */
- beginInst = prog->Instructions + n->InstLocation;
- beginInst->BranchTarget = prog->NumInstructions - 1;
+ if (EmitHighLevelInstructions) {
+ /* emit OPCODE_ENDLOOP */
+ endInst = new_instruction(prog, OPCODE_ENDLOOP);
+ }
+ else {
+ /* emit unconditional BRA-nch */
+ endInst = new_instruction(prog, OPCODE_BRA);
+ endInst->DstReg.CondMask = COND_TR; /* always true */
+ }
+ /* end instruction's BranchTarget points to top of loop */
+ endInst->BranchTarget = beginInstLoc;
+
+ if (EmitHighLevelInstructions) {
+ /* BGNLOOP's BranchTarget points to the ENDLOOP inst */
+ beginInst = prog->Instructions + beginInstLoc;
+ beginInst->BranchTarget = prog->NumInstructions - 1;
+ }
/* Done emitting loop code. Now walk over the loop's linked list
- * of BREAK and CONT nodes, filling in their BranchTarget fields.
+ * of BREAK and CONT nodes, filling in their BranchTarget fields
+ * (which will point to the ENDLOOP or ENDLOOP+1 instructions).
*/
- for (p = n->BranchNode; p; p = p->BranchNode) {
- if (p->Opcode == IR_BREAK) {
- struct prog_instruction *brkInst
- = prog->Instructions + p->InstLocation;
- assert(brkInst->Opcode == OPCODE_BRK);
- brkInst->BranchTarget = endInstLoc + 1;
+ for (ir = n->BranchNode; ir; ir = ir->BranchNode) {
+ struct prog_instruction *inst
+ = prog->Instructions + ir->InstLocation;
+ if (ir->Opcode == IR_BREAK) {
+ assert(inst->Opcode == OPCODE_BRK ||
+ inst->Opcode == OPCODE_BRA);
+ inst->BranchTarget = endInstLoc + 1;
}
else {
- assert(p->Opcode == IR_CONT);
- struct prog_instruction *contInst
- = prog->Instructions + p->InstLocation;
- assert(contInst->Opcode == OPCODE_CONT);
- contInst->BranchTarget = endInstLoc;
+ assert(ir->Opcode == IR_CONT);
+ assert(inst->Opcode == OPCODE_CONT ||
+ inst->Opcode == OPCODE_BRA);
+ inst->BranchTarget = endInstLoc;
}
}
return NULL;
}
- case IR_CONT:
- {
- struct prog_instruction *inst;
- n->InstLocation = prog->NumInstructions;
- inst = new_instruction(prog, OPCODE_CONT);
- inst->DstReg.CondMask = COND_TR; /* always true */
- return inst;
- }
case IR_BREAK:
+ /* fall-through */
+ case IR_CONT:
{
+ gl_inst_opcode opcode;
struct prog_instruction *inst;
n->InstLocation = prog->NumInstructions;
- inst = new_instruction(prog, OPCODE_BRK);
+ if (EmitHighLevelInstructions) {
+ opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK;
+ }
+ else {
+ opcode = OPCODE_BRA;
+ }
+ inst = new_instruction(prog, opcode);
inst->DstReg.CondMask = COND_TR; /* always true */
return inst;
}
diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h
index a7c858c..0c827d9 100644
--- a/src/mesa/shader/slang/slang_ir.h
+++ b/src/mesa/shader/slang/slang_ir.h
@@ -39,7 +39,7 @@
/**
- * Intermediate Representation opcode
+ * Intermediate Representation opcodes
*/
typedef enum
{
@@ -64,6 +64,11 @@ typedef enum
IR_CONT, /* continue loop */
IR_BREAK, /* break loop */
+ IR_BREAK_IF_TRUE,
+ IR_BREAK_IF_FALSE,
+ IR_CONT_IF_TRUE,
+ IR_CONT_IF_FALSE,
+
IR_MOVE,
IR_ADD,
IR_SUB,
diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c
index 017cf60..b1d355f 100644
--- a/src/mesa/shader/slang/slang_link.c
+++ b/src/mesa/shader/slang/slang_link.c
@@ -298,7 +298,7 @@ _slang_resolve_branches(struct gl_progra
for (i = 0; i < prog->NumInstructions; i++) {
struct prog_instruction *inst = prog->Instructions + i;
- if (inst->Opcode == OPCODE_BRA) {
+ 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;
diff --git a/src/mesa/swrast/s_fragprog.c b/src/mesa/swrast/s_fragprog.c
index 403a03a..ace10a9 100644
--- a/src/mesa/swrast/s_fragprog.c
+++ b/src/mesa/swrast/s_fragprog.c
@@ -675,9 +675,10 @@ execute_program( GLcontext *ctx,
}
}
break;
- case OPCODE_BGNLOOP: /* begin loop */
+ case OPCODE_BGNLOOP:
+ /* no-op */
break;
- case OPCODE_ENDLOOP: /* end loop */
+ case OPCODE_ENDLOOP:
/* subtract 1 here since pc is incremented by for(pc) loop */
pc = inst->BranchTarget - 1; /* go to matching BNGLOOP */
break;
@@ -695,10 +696,7 @@ execute_program( GLcontext *ctx,
test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) ||
test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) {
/* take branch */
- pc = inst->BranchTarget;
- /*
- printf("Take branch to %u\n", pc);
- */
+ pc = inst->BranchTarget - 1;
}
}
break;
@@ -721,7 +719,7 @@ execute_program( GLcontext *ctx,
return GL_TRUE; /* Per GL_NV_vertex_program2 spec */
}
machine->CallStack[machine->StackDepth++] = pc + 1;
- pc = inst->BranchTarget;
+ pc = inst->BranchTarget; /* XXX - 1 ??? */
}
}
break;
More information about the mesa-commit
mailing list