summaryrefslogtreecommitdiff
path: root/src/mesa/shader
diff options
context:
space:
mode:
authorBrian <brian@yutani.localnet.net>2007-03-26 16:56:45 -0600
committerBrian <brian@yutani.localnet.net>2007-03-26 16:56:45 -0600
commitc042a91b8b202e4c0623e647bda035c715f7c308 (patch)
tree5a3db377e5c55625397757dc56a72d31a93d3754 /src/mesa/shader
parent813a0e11f1eb903883aef18c5cb5c4702dcb6213 (diff)
Get rid of SLANG_OPER_GOTO, start rewrite of 'return' handling.
Diffstat (limited to 'src/mesa/shader')
-rw-r--r--src/mesa/shader/slang/slang_codegen.c94
-rw-r--r--src/mesa/shader/slang/slang_compile_operation.h3
-rw-r--r--src/mesa/shader/slang/slang_emit.c19
-rw-r--r--src/mesa/shader/slang/slang_print.c5
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 c2a33778c6..0ca5054ead 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 3bed3218a6..b63db04e7e 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 109b2df7aa..92bfb54d80 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 c80a6c7e11..90e6fe2a96 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);