From 552a65e4546bd543d60ffe87dc298a41d8a318be Mon Sep 17 00:00:00 2001 From: Brian Date: Tue, 16 Jan 2007 17:38:39 -0700 Subject: [PATCH] Implement codegen for the selection operator ( b ? x : y ) --- src/mesa/shader/slang/slang_codegen.c | 120 ++++++++++++++++++++++---- src/mesa/shader/slang/slang_emit.c | 3 +- 2 files changed, 104 insertions(+), 19 deletions(-) diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 4213e1c4b4f..0189b751347 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -1477,6 +1477,96 @@ _slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper) } +/** + * Generate IR node for storage of a temporary of given size. + */ +static slang_ir_node * +_slang_gen_temporary(GLint size) +{ + slang_ir_storage *store; + slang_ir_node *n; + + store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, size); + if (store) { + n = new_node(IR_VAR_DECL, NULL, NULL); + if (n) { + n->Store = store; + } + else { + free(store); + } + } + return n; +} + + +/** + * Generate code for a selection expression: b ? x : y + */ +static slang_ir_node * +_slang_gen_select(slang_assemble_ctx *A, slang_operation *oper) +{ + slang_atom altAtom = slang_atom_pool_gen(A->atoms, "__selectAlt"); + slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__selectEnd"); + slang_ir_node *altLab, *endLab; + slang_ir_node *tree, *tmpDecl, *tmpVar, *cond, *cjump, *jump; + slang_ir_node *bodx, *body, *assignx, *assigny; + slang_assembly_typeinfo type; + int size; + + /* size of x or y's type */ + slang_assembly_typeinfo_construct(&type); + _slang_typeof_operation(A, &oper->children[1], &type); + size = _slang_sizeof_type_specifier(&type.spec); + assert(size > 0); + + /* temporary var */ + tmpDecl = _slang_gen_temporary(size); + + /* eval condition */ + cond = _slang_gen_operation(A, &oper->children[0]); + cond = _slang_gen_cond(cond); + tree = new_seq(tmpDecl, cond); + + /* jump if true to "alt" label */ + cjump = new_cjump(altAtom); + tree = new_seq(tree, cjump); + + /* evaluate child 2 (y) and assign to tmp */ + tmpVar = new_node(IR_VAR, NULL, NULL); + tmpVar->Store = tmpDecl->Store; + body = _slang_gen_operation(A, &oper->children[2]); + assigny = new_node(IR_MOVE, tmpVar, body); + tree = new_seq(tree, assigny); + + /* jump to "end" label */ + jump = new_jump(endAtom); + tree = new_seq(tree, jump); + + /* "alt" label */ + altLab = new_label(altAtom); + tree = new_seq(tree, altLab); + + /* evaluate child 1 (x) and assign to tmp */ + tmpVar = new_node(IR_VAR, NULL, NULL); + tmpVar->Store = tmpDecl->Store; + bodx = _slang_gen_operation(A, &oper->children[1]); + assignx = new_node(IR_MOVE, tmpVar, bodx); + tree = new_seq(tree, assignx); + + /* "end" label */ + endLab = new_label(endAtom); + tree = new_seq(tree, endLab); + + /* tmp var value */ + tmpVar = new_node(IR_VAR, NULL, NULL); + tmpVar->Store = tmpDecl->Store; + tree = new_seq(tree, tmpVar); + + return tree; +} + + /** * Generate IR tree for a return statement. */ @@ -1643,24 +1733,6 @@ _slang_gen_variable(slang_assemble_ctx * A, slang_operation *oper) } -#if 0 -static slang_ir_node * -_slang_gen_logical_and(slang_assemble_ctx * A, slang_operation *oper) -{ - /* - * bool b; - * b = test(child[0]); - * if !b goto endLab; - * b = test(child[1]); - * endLab: - * (b) - */ - slang_ir_node *temp; - -} -#endif - - /** * Generate IR tree for an assignment (=). */ @@ -1671,6 +1743,10 @@ _slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper) oper->children[1].type == slang_oper_call) { /* Special case of: x = f(a, b) * Replace with f(a, b, x) (where x == hidden __retVal out param) + * + * XXX this could be even more effective if we could accomodate + * cases such as "v.x = f();" - would help with typical vertex + * transformation. */ slang_ir_node *n; n = _slang_gen_function_call_name(A, @@ -2023,6 +2099,14 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) return n; } + case slang_oper_select: /* b ? x : y */ + { + slang_ir_node *n; + assert(oper->num_children == 3); + n = _slang_gen_select(A, oper ); + return n; + } + case slang_oper_asm: return _slang_gen_asm(A, oper, NULL); case slang_oper_call: diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index e58256c9f1b..1142bc6416b 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -617,7 +617,8 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) assert(n->Store); assert(n->Store->File != PROGRAM_UNDEFINED); assert(n->Store->Size > 0); - if (n->Var->isTemp) + assert(n->Store->Index < 0); + if (!n->Var || n->Var->isTemp) n->Store->Index = _slang_alloc_temp(vt, n->Store->Size); else n->Store->Index = _slang_alloc_var(vt, n->Store->Size); -- 2.30.2