diff options
author | Brian <brian@nostromo.localnet.net> | 2007-02-06 22:31:19 -0700 |
---|---|---|
committer | Brian <brian@nostromo.localnet.net> | 2007-02-06 22:31:19 -0700 |
commit | f22ed0986a743e033d827c78371612c7115ff913 (patch) | |
tree | c9df47eeb7033ebdc2b5b596737bd14b24f41c9d /src/mesa/shader/slang | |
parent | 5f7d4668c4b7de1c0d2269809d30aef6d0a089e9 (diff) |
Implement CONT, improve BRK.
IR_LOOP's BranchNode ptr is the head of a linked list of CONT and BRK nodes.
After emitting loop, walk over the linked list, filling in the CONT/BRK
instruction's BranchTarget field (location of the ENDLOOP instruction, or
one past).
Diffstat (limited to 'src/mesa/shader/slang')
-rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 29 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 47 |
2 files changed, 60 insertions, 16 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index a4e2935ea8..42c1f0897e 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -608,7 +608,24 @@ new_break(slang_ir_node *loopNode) assert(loopNode); assert(loopNode->Opcode == IR_LOOP); if (n) { - n->BranchNode = loopNode; + /* insert this node at head of linked list */ + n->BranchNode = loopNode->BranchNode; + loopNode->BranchNode = n; + } + return n; +} + + +static slang_ir_node * +new_cont(slang_ir_node *loopNode) +{ + slang_ir_node *n = new_node0(IR_CONT); + assert(loopNode); + assert(loopNode->Opcode == IR_LOOP); + if (n) { + /* insert this node at head of linked list */ + n->BranchNode = loopNode->BranchNode; + loopNode->BranchNode = n; } return n; } @@ -2434,11 +2451,15 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) return new_jump(A->CurLoopBreak); } case slang_oper_continue: - if (!A->CurLoopCont) { + if (!A->CurLoop && !A->CurLoopCont) { RETURN_ERROR("'continue' not in loop", 0); } - /* XXX emit IR_CONT instruction */ - return new_jump(A->CurLoopCont); + if (UseHighLevelInstructions) { + return new_cont(A->CurLoop); + } + else { + return new_jump(A->CurLoopCont); + } case slang_oper_discard: return new_node0(IR_KILL); diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index c18f1e364c..2d5a7cf6f9 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -1303,7 +1303,9 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) case IR_LOOP: { - struct prog_instruction *beginInst; + struct prog_instruction *beginInst, *endInst; + GLuint endInstLoc; + slang_ir_node *p; /* save location of this instruction, used by OPCODE_ENDLOOP */ n->InstLocation = prog->NumInstructions; @@ -1312,27 +1314,48 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) /* body */ emit(vt, n->Children[0], prog); - inst = new_instruction(prog, OPCODE_ENDLOOP); - /* The instruction BranchTarget points to top of loop */ - inst->BranchTarget = n->InstLocation; + 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; - return inst; + + /* Done emitting loop code. Now walk over the loop's linked list + * of BREAK and CONT nodes, filling in their BranchTarget fields. + */ + 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; + } + else { + assert(p->Opcode == IR_CONT); + struct prog_instruction *contInst + = prog->Instructions + p->InstLocation; + assert(contInst->Opcode == OPCODE_CONT); + contInst->BranchTarget = endInstLoc; + } + } + return NULL; } case IR_CONT: - return new_instruction(prog, OPCODE_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: { struct prog_instruction *inst; + n->InstLocation = prog->NumInstructions; inst = new_instruction(prog, OPCODE_BRK); inst->DstReg.CondMask = COND_TR; /* always true */ - /* This instruction's branch target is top of loop, not bottom of - * loop because we don't know where it is yet! - */ - assert(n->BranchNode); - assert(n->BranchNode->InstLocation >= 0); - inst->BranchTarget = n->BranchNode->InstLocation; return inst; } |