}
+static slang_ir_node *
+_slang_gen_cond(slang_ir_node *n)
+{
+ slang_ir_node *c = new_node(IR_COND, n, NULL);
+ return c;
+}
+
+
/**
* Assemble a function call, given a particular function name.
* \param name the function's name (operators like '*' are possible).
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);
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);
slang_atom endifAtom = slang_atom_pool_gen(A->atoms, "__endif");
cond = _slang_gen_operation(A, &oper->children[0]);
+ cond = _slang_gen_cond(cond);
/*assert(cond->Store);*/
bra = new_cjump(haveElseClause ? elseAtom : endifAtom);
tree = new_seq(cond, bra);
{ IR_LABEL, "IR_LABEL", 0, 0, 0 },
{ IR_JUMP, "IR_JUMP", 0, 0, 0 },
{ IR_CJUMP, "IR_CJUMP", 0, 0, 0 },
+ { IR_COND, "IR_COND", 0, 0, 0 },
{ IR_CALL, "IR_CALL", 0, 0, 0 },
{ IR_MOVE, "IR_MOVE", 0, 0, 1 },
{ IR_NOT, "IR_NOT", 0, 1, 1 },
case IR_LABEL:
printf("LABEL: %s\n", n->Target);
break;
+ case IR_COND:
+ printf("COND\n");
+ slang_print_ir(n->Children[0], indent + 3);
+ break;
case IR_JUMP:
printf("JUMP %s\n", n->Target);
break;
storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store,
n->Children[1]->Swizzle);
inst->Comment = n->Comment;
-
- if (inst->Opcode == OPCODE_SGT) {
- /* update cond codes */
- inst->CondUpdate = GL_TRUE;
- }
-
return inst;
}
case IR_EXP:
case IR_EXP2:
return emit_binop(gc, n, prog);
- break;
case IR_RSQ:
case IR_RCP:
case IR_FLOOR:
case IR_SIN:
case IR_COS:
return emit_unop(gc, n, prog);
- break;
case IR_LABEL:
return emit_label(n->Target, prog);
case IR_FLOAT:
n->Store = alloc_constant(n->Value, 4, prog); /*XXX fix size */
break;
+ case IR_COND:
+ {
+ /* Conditional expression (in if/while/for stmts).
+ * Need to update condition code register.
+ * Next instruction is typically an IR_CJUMP.
+ */
+ /* last child expr instruction: */
+ struct prog_instruction *inst = emit(gc, n->Children[0], prog);
+ if (inst) {
+ /* set inst's CondUpdate flag */
+ inst->CondUpdate = GL_TRUE;
+ return inst; /* XXX or null? */
+ }
+ else {
+ /* This'll happen for things like "if (i) ..." where no code
+ * is normally generated for the expression "i".
+ * Generate a move instruction just to set condition codes.
+ */
+ slang_alloc_temp_storage(gc, n, 1);
+ inst = new_instruction(prog, OPCODE_MOV);
+ inst->CondUpdate = GL_TRUE;
+ storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+ storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store,
+ n->Children[0]->Swizzle);
+ free_temporary(gc, n->Store->Index, n->Store->Size);
+ return inst; /* XXX or null? */
+ }
+ }
+ return NULL;
case IR_JUMP:
return emit_jump(n->Target, prog);
case IR_CJUMP:
typedef enum
{
IR_NOP = 0,
- IR_SEQ,
+ IR_SEQ, /* sequence (eval left, then right) */
IR_LABEL, /* target of a jump or cjump */
IR_JUMP, /* unconditional jump */
IR_CJUMP, /* conditional jump */
- IR_CALL,
+ IR_COND, /* conditional expression */
+ IR_CALL, /* call subroutine */
IR_MOVE,
IR_ADD,
IR_SUB,
IR_DIV,
IR_DOT4,
IR_DOT3,
- IR_CROSS,
+ IR_CROSS, /* vec3 cross product */
IR_MIN,
IR_MAX,
- IR_SEQUAL,
- IR_SNEQUAL,
- IR_SGE,
- IR_SGT,
- IR_POW,
- IR_EXP,
- IR_EXP2,
- IR_LOG2,
- IR_RSQ,
- IR_RCP,
+ IR_SEQUAL, /* Set if not equal */
+ IR_SNEQUAL, /* Set if equal */
+ IR_SGE, /* Set if greater or equal */
+ IR_SGT, /* Set if greater than */
+ IR_POW, /* x^y */
+ IR_EXP, /* e^x */
+ IR_EXP2, /* 2^x */
+ IR_LOG2, /* log base 2 */
+ IR_RSQ, /* 1/sqrt() */
+ IR_RCP, /* recipricol */
IR_FLOOR,
IR_FRAC,
IR_ABS,
- IR_SIN,
- IR_COS,
- IR_NOT,
- IR_VAR,
- IR_VAR_DECL,
+ IR_SIN, /* sine */
+ IR_COS, /* cosine */
+ IR_NOT, /* logical not */
+ IR_VAR, /* variable reference */
+ IR_VAR_DECL,/* var declaration */
IR_FLOAT,
IR_FIELD,
IR_I_TO_F