Get rid of SLANG_OPER_GOTO, start rewrite of 'return' handling.
authorBrian <brian@yutani.localnet.net>
Mon, 26 Mar 2007 22:56:45 +0000 (16:56 -0600)
committerBrian <brian@yutani.localnet.net>
Mon, 26 Mar 2007 22:56:45 +0000 (16:56 -0600)
src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_compile_operation.h
src/mesa/shader/slang/slang_emit.c
src/mesa/shader/slang/slang_print.c

index c2a33778c6de79582433766f8a9e37058cbc1251..0ca5054eadce23e18d1b8fe1c3fe257f155ae6d9 100644 (file)
@@ -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;
@@ -606,6 +606,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 */
    }
 
index 3bed3218a6c3543eaf9c8ba98574f78fd66245df..b63db04e7ebfcf453b2cbd44ef54e4e2b86db081 100644 (file)
@@ -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;
 
 
index 109b2df7aad4de26037a66a4088fe65b8dbda90f..92bfb54d80c621dda2698670e239e06a2153a1b2 100644 (file)
@@ -726,6 +726,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)
 {
@@ -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;
index c80a6c7e11db958e03a266cbbf23107e76898692..90e6fe2a965ef9ff6becb419c54cb10903d21f03 100644 (file)
@@ -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);