diff options
Diffstat (limited to 'src/mesa/shader')
-rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 79 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 35 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_ir.h | 3 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_typeinfo.h | 1 |
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; |