summaryrefslogtreecommitdiff
path: root/src/mesa/shader/slang
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/shader/slang')
-rw-r--r--src/mesa/shader/slang/slang_codegen.c75
1 files changed, 68 insertions, 7 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 4623b6b5bc..7b2c8b84f7 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -980,6 +980,8 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
&oper->children[0]);
returnOper->type = SLANG_OPER_RETURN; /* return w/ no value */
+ returnOper->locals->outer_scope = blockOper->locals;
+
assert(returnOper->num_children == 0);
/* do substitutions on the "__retVal = expr" sub-tree */
@@ -1392,7 +1394,7 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
/**
- * Insert declaration for "bool _returnFlag" in given block operation.
+ * Insert declaration for "bool __returnFlag" in given block operation.
* This is used when we can't emit "early" return statements in subroutines.
*/
static void
@@ -1406,12 +1408,45 @@ declare_return_flag(slang_assemble_ctx *A, slang_operation *oper)
decl = slang_operation_insert_child(oper, 1);
slang_generate_declaration(A, oper->locals, decl,
- SLANG_SPEC_BOOL, "_returnFlag", GL_FALSE);
+ SLANG_SPEC_BOOL, "__returnFlag", GL_FALSE);
slang_print_tree(oper, 0);
}
+/**
+ * Replace 'return' with '__returnFlag = true'.
+ * This is used to remove 'early returns' from functions.
+ */
+static void
+replace_return_with_flag_set(slang_assemble_ctx *A, slang_operation *oper)
+{
+ slang_atom id = slang_atom_pool_atom(A->atoms, "__returnFlag");
+ assert(oper->type == SLANG_OPER_RETURN);
+
+ /* replace 'return' with __returnFlag = true' */
+ slang_operation_free_children(oper);
+ oper->type = SLANG_OPER_ASSIGN;
+ slang_operation_add_children(oper, 2);
+ {
+ slang_operation *lhs = slang_oper_child(oper, 0);
+ lhs->type = SLANG_OPER_IDENTIFIER;
+ lhs->a_id = id;
+ }
+ {
+ slang_operation *rhs = slang_oper_child(oper, 1);
+ slang_operation_literal_bool(rhs, GL_TRUE);
+ }
+
+ {
+ slang_variable *var;
+ var = _slang_variable_locate(oper->locals, id, GL_TRUE);
+ assert(var);
+ }
+
+}
+
+
static slang_ir_node *
_slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,
slang_operation *oper, slang_operation *dest)
@@ -1483,8 +1518,6 @@ _slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,
assert(callOper->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
callOper->type == SLANG_OPER_SEQUENCE);
declare_return_flag(A, callOper);
- printf("DECLARE _returnFlag\n");
-
}
callOper->type = SLANG_OPER_NON_INLINED_CALL;
callOper->fun = fun;
@@ -3871,6 +3904,8 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
const GLboolean haveReturnValue
= (oper->num_children == 1 && oper->children[0].type != SLANG_OPER_VOID);
+ assert(oper->type == SLANG_OPER_RETURN);
+
/* error checking */
assert(A->CurFunction);
if (haveReturnValue &&
@@ -3885,7 +3920,13 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
}
if (!haveReturnValue) {
- return new_return(A->curFuncEndLabel);
+ if (A->EmitContReturn) {
+ return new_return(A->curFuncEndLabel);
+ }
+ else {
+ replace_return_with_flag_set(A, oper);
+ return _slang_gen_operation(A, oper);
+ }
}
else {
/*
@@ -3926,8 +3967,28 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
slang_operation_copy(&assign->children[1], &oper->children[0]);
/* assemble the new code */
- n = new_seq(_slang_gen_operation(A, assign),
- new_return(A->curFuncEndLabel));
+ if (A->EmitContReturn) {
+ n = new_seq(_slang_gen_operation(A, assign),
+ new_return(A->curFuncEndLabel));
+ }
+ else {
+ slang_operation *setFlag = slang_operation_new(1);
+ setFlag->type = SLANG_OPER_ASSIGN;
+ setFlag->locals->outer_scope = oper->locals;
+ slang_operation_add_children(setFlag, 2);
+ {
+ slang_operation *lhs = slang_oper_child(setFlag, 0);
+ lhs->type = SLANG_OPER_IDENTIFIER;
+ lhs->a_id = slang_atom_pool_atom(A->atoms, "__returnFlag");
+ }
+ {
+ slang_operation *rhs = slang_oper_child(setFlag, 1);
+ slang_operation_literal_bool(rhs, GL_TRUE);
+ }
+ n = new_seq(_slang_gen_operation(A, assign),
+ _slang_gen_operation(A, setFlag));
+ slang_operation_delete(setFlag);
+ }
slang_operation_delete(assign);
return n;