mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-22 23:40:23 +01:00
Implement do/while loops. Replace IR_CJUMP with IR_CJUMP0 and IR_CJUMP1 so
we can either jump on zero, or non-zero predicate.
This commit is contained in:
parent
eff9690351
commit
3cec66512d
3 changed files with 79 additions and 16 deletions
|
|
@ -562,18 +562,22 @@ new_float_literal(float x, float y, float z, float w)
|
|||
}
|
||||
|
||||
/**
|
||||
* Conditional jump.
|
||||
* \param zeroOrOne indicates if the jump is to be taken on zero, or non-zero
|
||||
* condition code state.
|
||||
* XXX maybe pass an IR node as second param to indicate the jump target???
|
||||
*/
|
||||
static slang_ir_node *
|
||||
new_cjump(slang_atom target)
|
||||
new_cjump(slang_atom target, GLuint zeroOrOne)
|
||||
{
|
||||
slang_ir_node *n = new_node(IR_CJUMP, NULL, NULL);
|
||||
slang_ir_node *n = new_node(zeroOrOne ? IR_CJUMP1 : IR_CJUMP0, NULL, NULL);
|
||||
if (n)
|
||||
n->Target = (char *) target;
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unconditional jump.
|
||||
* XXX maybe pass an IR node as second param to indicate the jump target???
|
||||
*/
|
||||
static slang_ir_node *
|
||||
|
|
@ -1386,7 +1390,7 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
|
|||
cond = _slang_gen_cond(cond);
|
||||
tree = new_seq(startLab, cond);
|
||||
|
||||
bra = new_cjump(endAtom);
|
||||
bra = new_cjump(endAtom, 0);
|
||||
tree = new_seq(tree, bra);
|
||||
|
||||
body = _slang_gen_operation(A, &oper->children[1]);
|
||||
|
|
@ -1406,6 +1410,52 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 for-loop.
|
||||
*/
|
||||
|
|
@ -1443,7 +1493,7 @@ _slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
|
|||
cond = _slang_gen_cond(cond);
|
||||
tree = new_seq(tree, cond);
|
||||
|
||||
bra = new_cjump(endAtom);
|
||||
bra = new_cjump(endAtom, 0);
|
||||
tree = new_seq(tree, bra);
|
||||
|
||||
body = _slang_gen_operation(A, &oper->children[3]);
|
||||
|
|
@ -1493,7 +1543,7 @@ _slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper)
|
|||
cond = _slang_gen_operation(A, &oper->children[0]);
|
||||
cond = _slang_gen_cond(cond);
|
||||
/*assert(cond->Store);*/
|
||||
bra = new_cjump(haveElseClause ? elseAtom : endifAtom);
|
||||
bra = new_cjump(haveElseClause ? elseAtom : endifAtom, 0);
|
||||
tree = new_seq(cond, bra);
|
||||
|
||||
trueBody = _slang_gen_operation(A, &oper->children[1]);
|
||||
|
|
@ -1593,8 +1643,8 @@ _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
|
|||
cond = _slang_gen_cond(cond);
|
||||
tree = new_seq(tmpDecl, cond);
|
||||
|
||||
/* jump if true to "alt" label */
|
||||
cjump = new_cjump(altAtom);
|
||||
/* jump if false to "alt" label */
|
||||
cjump = new_cjump(altAtom, 0);
|
||||
tree = new_seq(tree, cjump);
|
||||
|
||||
/* evaluate child 2 (y) and assign to tmp */
|
||||
|
|
@ -2042,6 +2092,8 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
|
|||
break;
|
||||
case slang_oper_while:
|
||||
return _slang_gen_while(A, oper);
|
||||
case slang_oper_do:
|
||||
return _slang_gen_do(A, oper);
|
||||
case slang_oper_for:
|
||||
return _slang_gen_for(A, oper);
|
||||
case slang_oper_break:
|
||||
|
|
|
|||
|
|
@ -89,7 +89,8 @@ static slang_ir_info IrInfo[] = {
|
|||
{ IR_SCOPE, "IR_SCOPE", 0, 0, 0 },
|
||||
{ IR_LABEL, "IR_LABEL", 0, 0, 0 },
|
||||
{ IR_JUMP, "IR_JUMP", 0, 0, 0 },
|
||||
{ IR_CJUMP, "IR_CJUMP", 0, 0, 0 },
|
||||
{ IR_CJUMP0, "IR_CJUMP0", 0, 0, 0 },
|
||||
{ IR_CJUMP1, "IR_CJUMP1", 0, 0, 0 },
|
||||
{ IR_KILL, "IR_KILL", 0, 0, 0 },
|
||||
{ IR_COND, "IR_COND", 0, 0, 0 },
|
||||
{ IR_CALL, "IR_CALL", 0, 0, 0 },
|
||||
|
|
@ -262,8 +263,12 @@ slang_print_ir(const slang_ir_node *n, int indent)
|
|||
case IR_JUMP:
|
||||
printf("JUMP %s\n", n->Target);
|
||||
break;
|
||||
case IR_CJUMP:
|
||||
printf("CJUMP %s\n", n->Target);
|
||||
case IR_CJUMP0:
|
||||
printf("CJUMP0 %s\n", n->Target);
|
||||
slang_print_ir(n->Children[0], indent+3);
|
||||
break;
|
||||
case IR_CJUMP1:
|
||||
printf("CJUMP1 %s\n", n->Target);
|
||||
slang_print_ir(n->Children[0], indent+3);
|
||||
break;
|
||||
case IR_VAR:
|
||||
|
|
@ -515,11 +520,14 @@ emit_label(const char *target, struct gl_program *prog)
|
|||
|
||||
|
||||
static struct prog_instruction *
|
||||
emit_cjump(const char *target, struct gl_program *prog)
|
||||
emit_cjump(const char *target, struct gl_program *prog, GLuint zeroOrOne)
|
||||
{
|
||||
struct prog_instruction *inst;
|
||||
inst = new_instruction(prog, OPCODE_BRA);
|
||||
inst->DstReg.CondMask = COND_EQ; /* branch if equal to zero */
|
||||
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);
|
||||
return inst;
|
||||
|
|
@ -666,7 +674,7 @@ emit_cond(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
|
|||
{
|
||||
/* Conditional expression (in if/while/for stmts).
|
||||
* Need to update condition code register.
|
||||
* Next instruction is typically an IR_CJUMP.
|
||||
* Next instruction is typically an IR_CJUMP0/1.
|
||||
*/
|
||||
/* last child expr instruction: */
|
||||
struct prog_instruction *inst = emit(vt, n->Children[0], prog);
|
||||
|
|
@ -842,8 +850,10 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
|
|||
return emit_label(n->Target, prog);
|
||||
case IR_JUMP:
|
||||
return emit_jump(n->Target, prog);
|
||||
case IR_CJUMP:
|
||||
return emit_cjump(n->Target, prog);
|
||||
case IR_CJUMP0:
|
||||
return emit_cjump(n->Target, prog, 0);
|
||||
case IR_CJUMP1:
|
||||
return emit_cjump(n->Target, prog, 1);
|
||||
case IR_KILL:
|
||||
return emit_kill(prog);
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,8 @@ typedef enum
|
|||
IR_SCOPE, /* new variable scope (one child) */
|
||||
IR_LABEL, /* target of a jump or cjump */
|
||||
IR_JUMP, /* unconditional jump */
|
||||
IR_CJUMP, /* conditional jump */
|
||||
IR_CJUMP0, /* conditional jump if zero */
|
||||
IR_CJUMP1, /* conditional jump if one (or non-zero) */
|
||||
IR_COND, /* conditional expression */
|
||||
IR_CALL, /* call subroutine */
|
||||
IR_MOVE,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue