diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 27 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 16 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_ir.c | 2 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_ir.h | 2 | 
4 files changed, 29 insertions, 18 deletions
| diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index c1664a5ccb..8b2bdd74b5 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;     } diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 02c74095a9..fe13f2865c 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -780,16 +780,18 @@ emit_label(slang_emit_info *emitInfo, const slang_ir_node *n)  /** - * Emit code for an inlined function call (subroutine). + * Emit code for a function call. + * Note that for each time a function is called, we emit the function's + * body code again because the set of available registers may be different.   */  static struct prog_instruction * -emit_func(slang_emit_info *emitInfo, slang_ir_node *n) +emit_fcall(slang_emit_info *emitInfo, slang_ir_node *n)  {     struct gl_program *progSave;     struct prog_instruction *inst;     GLuint subroutineId; -   assert(n->Opcode == IR_FUNC); +   assert(n->Opcode == IR_CALL);     assert(n->Label);     /* save/push cur program */ @@ -1687,10 +1689,10 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n)     case IR_KILL:        return emit_kill(emitInfo); -   case IR_FUNC: -      /* new variable scope for subroutines/function calls*/ +   case IR_CALL: +      /* new variable scope for subroutines/function calls */        _slang_push_var_table(emitInfo->vt); -      inst = emit_func(emitInfo, n); +      inst = emit_fcall(emitInfo, n);        _slang_pop_var_table(emitInfo->vt);        return inst; @@ -1782,7 +1784,7 @@ _slang_resolve_subroutines(slang_emit_info *emitInfo)     emitInfo->NumSubroutines = 0;     /* Examine CAL instructions. -    * At this point, the BranchTarget field of the CAL instructions is +    * At this point, the BranchTarget field of the CAL instruction is      * the number/id of the subroutine to call (an index into the      * emitInfo->Subroutines list).      * Translate that into an actual instruction location now. diff --git a/src/mesa/shader/slang/slang_ir.c b/src/mesa/shader/slang/slang_ir.c index a29f302687..92e8d0345e 100644 --- a/src/mesa/shader/slang/slang_ir.c +++ b/src/mesa/shader/slang/slang_ir.c @@ -311,7 +311,7 @@ _slang_print_ir_tree(const slang_ir_node *n, int indent)        printf("RETURN\n");        break;     case IR_CALL: -      printf("CALL\n"); +      printf("CALL %s\n", n->Label->Name);        break;     case IR_LOOP: diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h index 69db4b5451..c7c0ddbf9a 100644 --- a/src/mesa/shader/slang/slang_ir.h +++ b/src/mesa/shader/slang/slang_ir.h @@ -62,8 +62,6 @@ typedef enum     IR_RETURN,    /* return from subroutine */     IR_CALL,      /* call subroutine */ -   IR_FUNC,      /* inlined function code */ -     IR_LOOP,      /* high-level loop-begin / loop-end */                   /* Children[0] = loop body */                   /* Children[1] = loop tail code, or NULL */ | 
