diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 94 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_compile_operation.h | 3 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 19 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_print.c | 5 |
4 files changed, 65 insertions, 56 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index c2a33778c6d..0ca5054eadc 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -472,9 +472,9 @@ new_float_literal(const float v[4], GLuint size) * Unconditional jump. */ static slang_ir_node * -new_jump(slang_label *dest) +new_return(slang_label *dest) { - slang_ir_node *n = new_node0(IR_JUMP); + slang_ir_node *n = new_node0(IR_RETURN); assert(dest); if (n) n->Label = dest; @@ -607,6 +607,24 @@ _slang_is_noop(const slang_operation *oper) /** + * Recursively search tree for a node of the given type. + */ +static slang_operation * +_slang_find_node_type(slang_operation *oper, slang_operation_type type) +{ + GLuint i; + if (oper->type == type) + return oper; + for (i = 0; i < oper->num_children; i++) { + slang_operation *p = _slang_find_node_type(&oper->children[i], type); + if (p) + return p; + } + return NULL; +} + + +/** * Produce inline code for a call to an assembly instruction. * XXX Note: children are passed as asm args in-order, not by name! */ @@ -749,7 +767,7 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper, slang_operation_copy(&assignOper->children[1], &oper->children[0]); - returnOper->type = SLANG_OPER_RETURN; + returnOper->type = SLANG_OPER_RETURN; /* return w/ no value */ assert(returnOper->num_children == 0); /* do substitutions on the "__retVal = expr" sub-tree */ @@ -1744,22 +1762,7 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) } if (!haveReturnValue) { - /* Convert from: - * return; - * To: - * goto __endOfFunction; - */ - slang_ir_node *n; - slang_operation gotoOp; - slang_operation_construct(&gotoOp); - gotoOp.type = SLANG_OPER_GOTO; - gotoOp.label = A->curFuncEndLabel; - assert(gotoOp.label); - - n = _slang_gen_operation(A, &gotoOp); - /* destroy temp code */ - slang_operation_destruct(&gotoOp); - return n; + return new_return(A->curFuncEndLabel); } else { /* @@ -1767,9 +1770,9 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) * return expr; * To: * __retVal = expr; - * goto __endOfFunction; + * return; // goto __endOfFunction */ - slang_operation *block, *assign, *jump; + slang_operation *assign; slang_atom a_retVal; slang_ir_node *n; @@ -1787,17 +1790,8 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) } #endif - block = slang_operation_new(1); - block->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE; - assert(block->locals); - block->locals->outer_scope = oper->locals->outer_scope; - block->num_children = 2; - block->children = slang_operation_new(2); - - /* child[0]: __retVal = expr; */ - assign = &block->children[0]; + assign = slang_operation_new(1); assign->type = SLANG_OPER_ASSIGN; - assign->locals->outer_scope = block->locals; assign->num_children = 2; assign->children = slang_operation_new(2); /* lhs (__retVal) */ @@ -1808,22 +1802,11 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) /* XXX we might be able to avoid this copy someday */ slang_operation_copy(&assign->children[1], &oper->children[0]); - /* child[1]: goto __endOfFunction */ - jump = &block->children[1]; - jump->type = SLANG_OPER_GOTO; - assert(A->curFuncEndLabel); - /* XXX don't call function? */ - jump->label = A->curFuncEndLabel; - assert(jump->label); - -#if 0 /* debug */ - printf("NEW RETURN:\n"); - slang_print_tree(block, 0); -#endif - /* assemble the new code */ - n = _slang_gen_operation(A, block); - slang_operation_delete(block); + n = new_seq(_slang_gen_operation(A, assign), + new_return(A->curFuncEndLabel)); + + slang_operation_delete(assign); return n; } } @@ -2552,8 +2535,6 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) oper, NULL); case SLANG_OPER_RETURN: return _slang_gen_return(A, oper); - case SLANG_OPER_GOTO: - return new_jump(oper->label); case SLANG_OPER_LABEL: return new_label(oper->label); case SLANG_OPER_IDENTIFIER: @@ -2817,6 +2798,23 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun) /* we only really generate code for main, all other functions get * inlined. */ +#if 0 + /* do some basic error checking though */ + if (fun->header.type.specifier.type != SLANG_SPEC_VOID) { + /* check that non-void functions actually return something */ + slang_operation *op + = _slang_find_node_type(fun->body, SLANG_OPER_RETURN); + if (!op) { + slang_info_log_error(A->log, + "function \"%s\" has no return statement", + (char *) fun->header.a_name); + printf( + "function \"%s\" has no return statement\n", + (char *) fun->header.a_name); + return GL_FALSE; + } + } +#endif return GL_TRUE; /* not an error */ } diff --git a/src/mesa/shader/slang/slang_compile_operation.h b/src/mesa/shader/slang/slang_compile_operation.h index 3bed3218a6c..b63db04e7eb 100644 --- a/src/mesa/shader/slang/slang_compile_operation.h +++ b/src/mesa/shader/slang/slang_compile_operation.h @@ -42,7 +42,6 @@ typedef enum slang_operation_type_ SLANG_OPER_CONTINUE, /* "continue" statement */ SLANG_OPER_DISCARD, /* "discard" (kill fragment) statement */ SLANG_OPER_RETURN, /* "return" [expr] */ - SLANG_OPER_GOTO, /* jump to label */ SLANG_OPER_LABEL, /* a jump target */ SLANG_OPER_EXPRESSION, /* [expr] */ SLANG_OPER_IF, /* "if" [0] then [1] else [2] */ @@ -118,7 +117,7 @@ typedef struct slang_operation_ slang_variable_scope *locals; /**< local vars for scope */ struct slang_function_ *fun; /**< If type == SLANG_OPER_CALL */ struct slang_variable_ *var; /**< If type == slang_oper_identier */ - struct slang_label_ *label; /**< If type == SLANG_OPER_LABEL or GOTO */ + struct slang_label_ *label; /**< If type == SLANG_OPER_LABEL */ } slang_operation; diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 109b2df7aad..92bfb54d80c 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -727,6 +727,23 @@ emit_jump(slang_emit_info *emitInfo, slang_ir_node *n) static struct prog_instruction * +emit_return(slang_emit_info *emitInfo, slang_ir_node *n) +{ + struct prog_instruction *inst; + assert(n); + assert(n->Opcode == IR_RETURN); + assert(n->Label); + inst = new_instruction(emitInfo, OPCODE_BRA /*RET*/); /*XXX TEMPORARY*/ + inst->DstReg.CondMask = COND_TR; /* always branch */ + inst->BranchTarget = _slang_label_get_location(n->Label); + if (inst->BranchTarget < 0) { + _slang_label_add_reference(n->Label, emitInfo->prog->NumInstructions - 1); + } + return inst; +} + + +static struct prog_instruction * emit_kill(slang_emit_info *emitInfo) { struct prog_instruction *inst; @@ -1528,7 +1545,7 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n) case IR_END_SUB: return new_instruction(emitInfo, OPCODE_ENDSUB); case IR_RETURN: - return new_instruction(emitInfo, OPCODE_RET); + return emit_return(emitInfo, n); case IR_NOP: return NULL; diff --git a/src/mesa/shader/slang/slang_print.c b/src/mesa/shader/slang/slang_print.c index c80a6c7e11d..90e6fe2a965 100644 --- a/src/mesa/shader/slang/slang_print.c +++ b/src/mesa/shader/slang/slang_print.c @@ -308,11 +308,6 @@ slang_print_tree(const slang_operation *op, int indent) slang_print_tree(&op->children[0], indent + 3); break; - case SLANG_OPER_GOTO: - spaces(indent); - printf("GOTO %s\n", (char *) op->a_id); - break; - case SLANG_OPER_LABEL: spaces(indent); printf("LABEL %s\n", (char *) op->a_id); |