Fix function call bug 11731. Also, fix up IR_CALL/IR_FUNC confusion.
authorBrian <brian.paul@tungstengraphics.com>
Thu, 26 Jul 2007 21:32:02 +0000 (15:32 -0600)
committerBrian <brian.paul@tungstengraphics.com>
Thu, 26 Jul 2007 21:32:02 +0000 (15:32 -0600)
src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_emit.c
src/mesa/shader/slang/slang_ir.c
src/mesa/shader/slang/slang_ir.h

index c1664a5..8b2bdd7 100644 (file)
@@ -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;
    }
index 02c7409..fe13f28 100644 (file)
@@ -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.
index a29f302..92e8d03 100644 (file)
@@ -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:
index 69db4b5..c7c0ddb 100644 (file)
@@ -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 */