diff options
Diffstat (limited to 'src/mesa/shader/slang/slang_codegen.c')
-rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 35e80e04523..8b2bdd74b59 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -536,7 +536,7 @@ new_not(slang_ir_node *n) static slang_ir_node * new_inlined_function_call(slang_ir_node *code, slang_label *name) { - slang_ir_node *n = new_node1(IR_FUNC, code); + slang_ir_node *n = new_node1(IR_CALL, code); assert(name); if (n) n->Label = name; @@ -1202,17 +1202,29 @@ _slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun, /* non-assembly function */ inlined = slang_inline_function_call(A, fun, oper, dest); if (inlined && _slang_find_node_type(inlined, SLANG_OPER_RETURN)) { - /* This inlined function has one or more 'return' statements. + slang_operation *callOper; + /* The function we're calling has one or more 'return' statements. * So, we can't truly inline this function because we need to * implement 'return' with RET (and CAL). + * Nevertheless, we performed "inlining" to make a new instance + * of the function body to deal with static register allocation. + * * XXX check if there's one 'return' and if it's the very last * statement in the function - we can optimize that case. */ assert(inlined->type == SLANG_OPER_BLOCK_NEW_SCOPE || inlined->type == SLANG_OPER_SEQUENCE); - inlined->type = SLANG_OPER_INLINED_CALL; - inlined->fun = fun; - inlined->label = _slang_label_new_unique((char*) fun->header.a_name); + if (_slang_function_has_return_value(fun) && !dest) { + assert(inlined->children[0].type == SLANG_OPER_VARIABLE_DECL); + assert(inlined->children[2].type == SLANG_OPER_IDENTIFIER); + callOper = &inlined->children[1]; + } + else { + callOper = inlined; + } + callOper->type = SLANG_OPER_INLINED_CALL; + callOper->fun = fun; + callOper->label = _slang_label_new_unique((char*) fun->header.a_name); } } @@ -1949,8 +1961,7 @@ static slang_ir_node * _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) { const GLboolean haveReturnValue - = (oper->num_children == 1 && - oper->children[0].type != SLANG_OPER_VOID); + = (oper->num_children == 1 && oper->children[0].type != SLANG_OPER_VOID); /* error checking */ assert(A->CurFunction); @@ -1960,7 +1971,7 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) return NULL; } else if (!haveReturnValue && - A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) { + A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) { slang_info_log_error(A->log, "return statement requires an expression"); return NULL; } @@ -2236,7 +2247,9 @@ _slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper) } if (var->type.qualifier == SLANG_QUAL_CONST || var->type.qualifier == SLANG_QUAL_ATTRIBUTE || - var->type.qualifier == SLANG_QUAL_UNIFORM) { + var->type.qualifier == SLANG_QUAL_UNIFORM || + (var->type.qualifier == SLANG_QUAL_VARYING && + A->program->Target == GL_FRAGMENT_PROGRAM_ARB)) { slang_info_log_error(A->log, "illegal assignment to read-only variable '%s'", (char *) oper->children[0].a_id); @@ -2264,10 +2277,11 @@ _slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper) lhs = _slang_gen_operation(A, &oper->children[0]); if (lhs) { - if (lhs->Store->File != PROGRAM_OUTPUT && - lhs->Store->File != PROGRAM_TEMPORARY && - lhs->Store->File != PROGRAM_VARYING && - lhs->Store->File != PROGRAM_UNDEFINED) { + if (!(lhs->Store->File == PROGRAM_OUTPUT || + lhs->Store->File == PROGRAM_TEMPORARY || + (lhs->Store->File == PROGRAM_VARYING && + A->program->Target == GL_VERTEX_PROGRAM_ARB) || + lhs->Store->File == PROGRAM_UNDEFINED)) { slang_info_log_error(A->log, "illegal assignment to read-only l-value"); return NULL; |