Re-implement branching with slang_labels.
authorBrian <brian@yutani.localnet.net>
Fri, 23 Feb 2007 16:38:17 +0000 (09:38 -0700)
committerBrian <brian@yutani.localnet.net>
Fri, 23 Feb 2007 16:38:17 +0000 (09:38 -0700)
This eliminates the NOP instructions that had been used as placeholders for
branch targets.
Also, fix "return" statement bug.

src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_compile_function.h
src/mesa/shader/slang/slang_compile_operation.h
src/mesa/shader/slang/slang_emit.c
src/mesa/shader/slang/slang_ir.h
src/mesa/shader/slang/slang_link.c

index 51c8f27c80b890e8975c555c899687906a728cf6..3d9b23693ac3fed920eef26f1dab410034e7f5c1 100644 (file)
@@ -39,6 +39,7 @@
 #include "slang_codegen.h"
 #include "slang_compile.h"
 #include "slang_error.h"
+#include "slang_label.h"
 #include "slang_simplify.h"
 #include "slang_emit.h"
 #include "slang_vartable.h"
@@ -425,10 +426,11 @@ new_seq(slang_ir_node *left, slang_ir_node *right)
 }
 
 static slang_ir_node *
-new_label(slang_atom labName)
+new_label(slang_label *label)
 {
    slang_ir_node *n = new_node0(IR_LABEL);
-   n->Target = (char *) labName; /*_mesa_strdup(name);*/
+   if (n)
+      n->Label = label;
    return n;
 }
 
@@ -450,11 +452,11 @@ new_float_literal(const float v[4])
  * XXX maybe pass an IR node as second param to indicate the jump target???
  */
 static slang_ir_node *
-new_cjump(slang_atom target, GLuint zeroOrOne)
+new_cjump(slang_label *dest, GLuint zeroOrOne)
 {
    slang_ir_node *n = new_node0(zeroOrOne ? IR_CJUMP1 : IR_CJUMP0);
    if (n)
-      n->Target = (char *) target;
+      n->Label = dest;
    return n;
 }
 
@@ -463,11 +465,11 @@ new_cjump(slang_atom target, GLuint zeroOrOne)
  * XXX maybe pass an IR node as second param to indicate the jump target???
  */
 static slang_ir_node *
-new_jump(slang_atom target)
+new_jump(slang_label *dest)
 {
    slang_ir_node *n = new_node0(IR_JUMP);
    if (n)
-      n->Target = (char *) target;
+      n->Label = dest;
    return n;
 }
 
@@ -599,6 +601,18 @@ slang_is_asm_function(const slang_function *fun)
 }
 
 
+static GLboolean
+_slang_is_noop(const slang_operation *oper)
+{
+   if (!oper ||
+       oper->type == SLANG_OPER_VOID ||
+       (oper->num_children == 1 && oper->children[0].type == SLANG_OPER_VOID))
+      return GL_TRUE;
+   else
+      return GL_FALSE;
+}
+
+
 /**
  * Produce inline code for a call to an assembly instruction.
  */
@@ -709,11 +723,11 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
         }
       }
       break;
-#if 1 /* XXX rely on default case below */
+
    case SLANG_OPER_RETURN:
       /* do return replacement here too */
       assert(oper->num_children == 0 || oper->num_children == 1);
-      if (oper->num_children == 1) {
+      if (!_slang_is_noop(oper)) {
          /* replace:
           *   return expr;
           * with:
@@ -751,7 +765,7 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
          slang_operation_destruct(blockOper);
       }
       break;
-#endif
+
    case SLANG_OPER_ASSIGN:
    case SLANG_OPER_SUBSCRIPT:
       /* special case:
@@ -992,8 +1006,7 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
                                                     &inlined->children,
                                                     inlined->num_children);
       lab->type = SLANG_OPER_LABEL;
-      lab->a_id = slang_atom_pool_atom(A->atoms,
-                                       (char *) A->CurFunction->end_label);
+      lab->label = A->CurFunction->end_label;
    }
 
    for (i = 0; i < totalArgs; i++) {
@@ -1044,7 +1057,7 @@ _slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,
    if (!A->CurFunction->end_label) {
       char name[200];
       sprintf(name, "__endOfFunc_%s_", (char *) A->CurFunction->header.a_name);
-      A->CurFunction->end_label = slang_atom_pool_gen(A->atoms, name);
+      A->CurFunction->end_label = _slang_label_new(name);
    }
 
    if (slang_is_asm_function(fun) && !dest) {
@@ -1075,7 +1088,7 @@ _slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,
 
    n = _slang_gen_operation(A, oper);
 
-   A->CurFunction->end_label = NULL;
+   A->CurFunction->end_label = NULL; /* XXX delete/free? */
 
    A->CurFunction = prevFunc;
 
@@ -1198,19 +1211,6 @@ _slang_gen_asm(slang_assemble_ctx *A, slang_operation *oper,
 }
 
 
-
-static GLboolean
-_slang_is_noop(const slang_operation *oper)
-{
-   if (!oper ||
-       oper->type == SLANG_OPER_VOID ||
-       (oper->num_children == 1 && oper->children[0].type == SLANG_OPER_VOID))
-      return GL_TRUE;
-   else
-      return GL_FALSE;
-}
-
-
 static void
 print_funcs(struct slang_function_scope_ *scope, const char *name)
 {
@@ -1617,8 +1617,7 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var)
 static slang_ir_node *
 _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
 {
-   slang_atom altAtom = slang_atom_pool_gen(A->atoms, "__selectAlt");
-   slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__selectEnd");
+   slang_label *altLabel, *endLabel;
    slang_ir_node *altLab, *endLab;
    slang_ir_node *tree, *tmpDecl, *tmpVar, *cond, *cjump, *jump;
    slang_ir_node *bodx, *body, *assignx, *assigny;
@@ -1628,6 +1627,9 @@ _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
    assert(oper->type == SLANG_OPER_SELECT);
    assert(oper->num_children == 3);
 
+   altLabel = _slang_label_new("selectAlt");
+   endLabel = _slang_label_new("selectEnd");
+
    /* size of x or y's type */
    slang_typeinfo_construct(&type);
    _slang_typeof_operation(A, &oper->children[1], &type);
@@ -1643,7 +1645,7 @@ _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
    tree = new_seq(tmpDecl, cond);
 
    /* jump if false to "alt" label */
-   cjump = new_cjump(altAtom, 0);
+   cjump = new_cjump(altLabel, 0);
    tree = new_seq(tree, cjump);
 
    /* evaluate child 1 (x) and assign to tmp */
@@ -1654,11 +1656,11 @@ _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
    tree = new_seq(tree, assigny);
 
    /* jump to "end" label */
-   jump = new_jump(endAtom);
+   jump = new_jump(endLabel);
    tree = new_seq(tree, jump);
 
    /* "alt" label */
-   altLab = new_label(altAtom);
+   altLab = new_label(altLabel);
    tree = new_seq(tree, altLab);
 
    /* evaluate child 2 (y) and assign to tmp */
@@ -1669,7 +1671,7 @@ _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
    tree = new_seq(tree, assignx);
 
    /* "end" label */
-   endLab = new_label(endAtom);
+   endLab = new_label(endLabel);
    tree = new_seq(tree, endLab);
    
    /* tmp var value */
@@ -1762,8 +1764,8 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
       slang_operation_construct(&gotoOp);
       gotoOp.type = SLANG_OPER_GOTO;
       /* XXX don't call function? */
-      gotoOp.a_id = slang_atom_pool_atom(A->atoms,
-                                         (char *) A->CurFunction->end_label);
+      gotoOp.label = A->CurFunction->end_label;
+
       /* assemble the new code */
       n = _slang_gen_operation(A, &gotoOp);
       /* destroy temp code */
@@ -1819,8 +1821,7 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
       jump->type = SLANG_OPER_GOTO;
       assert(A->CurFunction->end_label);
       /* XXX don't call function? */
-      jump->a_id = slang_atom_pool_atom(A->atoms,
-                                        (char *) A->CurFunction->end_label);
+      jump->label = A->CurFunction->end_label;
 
 #if 0 /* debug */
       printf("NEW RETURN:\n");
@@ -2439,9 +2440,9 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
    case SLANG_OPER_RETURN:
       return _slang_gen_return(A, oper);
    case SLANG_OPER_GOTO:
-      return new_jump((char*) oper->a_id);
+      return new_jump(oper->label);
    case SLANG_OPER_LABEL:
-      return new_label((char*) oper->a_id);
+      return new_label(oper->label);
    case SLANG_OPER_IDENTIFIER:
       return _slang_gen_variable(A, oper);
    case SLANG_OPER_IF:
@@ -2716,7 +2717,7 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
 
    /* Create an end-of-function label */
    if (!A->CurFunction->end_label)
-      A->CurFunction->end_label = slang_atom_pool_gen(A->atoms, "__endOfFunc_main_");
+      A->CurFunction->end_label = _slang_label_new("__endOfFunc__main");
 
    /* push new vartable scope */
    _slang_push_var_table(A->vartable);
index b60b4a223f5d40acf135393f12eaaf95a4fe2600..09fbfd9090042dbe77e10df42c71484b4b854adb 100644 (file)
@@ -25,9 +25,6 @@
 #ifndef SLANG_COMPILE_FUNCTION_H
 #define SLANG_COMPILE_FUNCTION_H
 
-#if defined __cplusplus
-extern "C" {
-#endif
 
 struct slang_code_unit_;
 
@@ -69,7 +66,11 @@ typedef struct slang_function_
    slang_operation *body;      /**< The instruction tree */
    unsigned int address;       /**< Address of this func in memory */
    slang_fixup_table fixups;   /**< Mem locations which need func's address */
+#if 0
    slang_atom end_label;       /**< The end-of-function label */
+#else
+   struct slang_label_ *end_label;
+#endif
 } slang_function;
 
 extern int slang_function_construct(slang_function *);
@@ -102,8 +103,4 @@ slang_function_scope_find_by_name(slang_function_scope *, slang_atom, int);
 extern slang_function *
 slang_function_scope_find(slang_function_scope *, slang_function *, int);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* SLANG_COMPILE_FUNCTION_H */
index a59f968456103e23cae6f4a9fdfa0a0eaf38e20f..4adcd2ab0e6691b7e19cb702df96773cd84098f7 100644 (file)
 #ifndef SLANG_COMPILE_OPERATION_H
 #define SLANG_COMPILE_OPERATION_H
 
-#if defined __cplusplus
-extern "C" {
-#endif
-
 
 /**
  * Types of slang operations.
@@ -122,6 +118,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 */
 } slang_operation;
 
 
@@ -148,8 +145,4 @@ slang_operation_insert(GLuint *numChildren, slang_operation **children,
                        GLuint pos);
 
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif /* SLANG_COMPILE_OPERATION_H */
index 76b03753b6a3d77e5acd9f5a5b02f7a9ff026f31..6b950debf4c8e14cf66e15995e151a0bb9ddf726 100644 (file)
@@ -278,7 +278,7 @@ slang_print_ir(const slang_ir_node *n, int indent)
       slang_print_ir(n->Children[1], indent+3);
       break;
    case IR_LABEL:
-      printf("LABEL: %s\n", n->Target);
+      printf("LABEL: %s\n", n->Label->Name);
       break;
    case IR_COND:
       printf("COND\n");
@@ -848,38 +848,44 @@ emit_negation(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
 
 
 static struct prog_instruction *
-emit_label(const char *target, struct gl_program *prog)
+emit_label(const slang_ir_node *n, struct gl_program *prog)
 {
-   struct prog_instruction *inst;
-   inst = new_instruction(prog, OPCODE_NOP);
-   inst->Comment = _mesa_strdup(target);
-   return inst;
+   assert(n->Label);
+   assert(_slang_label_get_location(n->Label) < 0);
+   _slang_label_set_location(n->Label, prog->NumInstructions, prog);
+   return NULL;
 }
 
 
 static struct prog_instruction *
-emit_cjump(const char *target, struct gl_program *prog, GLuint zeroOrOne)
+emit_cjump(slang_ir_node *n, struct gl_program *prog, GLuint zeroOrOne)
 {
    struct prog_instruction *inst;
+   assert(n->Opcode == IR_CJUMP0 || n->Opcode == IR_CJUMP1);
    inst = new_instruction(prog, OPCODE_BRA);
    if (zeroOrOne)
       inst->DstReg.CondMask = COND_NE;  /* branch if non-zero */
    else
       inst->DstReg.CondMask = COND_EQ;  /* branch if equal to zero */
    inst->DstReg.CondSwizzle = SWIZZLE_X;
-   inst->Comment = _mesa_strdup(target);
+   inst->BranchTarget = _slang_label_get_location(n->Label);
+   if (inst->BranchTarget < 0) {
+      _slang_label_add_reference(n->Label, prog->NumInstructions - 1);
+   }
    return inst;
 }
 
 
 static struct prog_instruction *
-emit_jump(const char *target, struct gl_program *prog)
+emit_jump(slang_ir_node *n, struct gl_program *prog)
 {
    struct prog_instruction *inst;
    inst = new_instruction(prog, OPCODE_BRA);
    inst->DstReg.CondMask = COND_TR;  /* always branch */
-   /*inst->DstReg.CondSwizzle = SWIZZLE_X;*/
-   inst->Comment = _mesa_strdup(target);
+   inst->BranchTarget = _slang_label_get_location(n->Label);
+   if (inst->BranchTarget < 0) {
+      _slang_label_add_reference(n->Label, prog->NumInstructions - 1);
+   }
    return inst;
 }
 
@@ -1522,13 +1528,13 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
       return emit_not(vt, n, prog);
 
    case IR_LABEL:
-      return emit_label(n->Target, prog);
+      return emit_label(n, prog);
    case IR_JUMP:
-      return emit_jump(n->Target, prog);
+      return emit_jump(n, prog);
    case IR_CJUMP0:
-      return emit_cjump(n->Target, prog, 0);
+      return emit_cjump(n, prog, 0);
    case IR_CJUMP1:
-      return emit_cjump(n->Target, prog, 1);
+      return emit_cjump(n, prog, 1);
    case IR_KILL:
       return emit_kill(prog);
 
@@ -1572,18 +1578,14 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt,
 {
    GLboolean success;
 
-   if (emit(vt, n, prog)) {
-      /* finish up by adding the END opcode to program */
-      if (withEnd) {
-         struct prog_instruction *inst;
-         inst = new_instruction(prog, OPCODE_END);
-      }
-      success = GL_TRUE;
-   }
-   else {
-      /* record an error? */
-      success = GL_FALSE;
+   (void) emit(vt, n, prog);
+
+   /* finish up by adding the END opcode to program */
+   if (withEnd) {
+      struct prog_instruction *inst;
+      inst = new_instruction(prog, OPCODE_END);
    }
+   success = GL_TRUE;
 
    printf("*********** End generate code (%u inst):\n", prog->NumInstructions);
 #if 0
index 0c827d9cd8ce6560a60f81cb38fd24c0161f5e09..ba8b613112dca947e5feeda9381935e283da00f2 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "imports.h"
 #include "slang_compile.h"
+#include "slang_label.h"
 #include "mtypes.h"
 
 
@@ -153,7 +154,8 @@ typedef struct slang_ir_node_
    slang_variable *Var;  /**< If Opcode == IR_VAR or IR_VAR_DECL */
    slang_ir_storage *Store;  /**< location of result of this operation */
    GLint InstLocation;  /**< Location of instruction emitted for this node */
-   struct slang_ir_node_ *BranchNode;  /**< Used for branch instructions */
+   struct slang_ir_node_ *BranchNode;  /**< Used for branching instructions */
+   slang_label *Label;  /**< Used for branches */
 } slang_ir_node;
 
 
index 23977b7c2c224110beb7ed0ece36fc7b67f7d18c..e2bb6ee2d80dbb7b18510290263de49fa14a1e53 100644 (file)
@@ -273,46 +273,6 @@ link_uniform_vars(struct gl_shader_program *shProg, struct gl_program *prog)
 }
 
 
-/**
- * XXX Temporary
- */
-static void
-_slang_resolve_branches(struct gl_program *prog)
-{
-   struct target {
-      const char *Name;
-      GLuint Pos;
-   };
-   struct target targets[500];
-   GLuint numTargets = 0;
-   GLuint i, j;
-
-   for (i = 0; i < prog->NumInstructions; i++) {
-      struct prog_instruction *inst = prog->Instructions + i;
-      if (inst->Opcode == OPCODE_NOP && inst->Comment) {
-         targets[numTargets].Name = inst->Comment;
-         targets[numTargets].Pos = i;
-         numTargets++;
-      }
-   }
-
-   for (i = 0; i < prog->NumInstructions; i++) {
-      struct prog_instruction *inst = prog->Instructions + i;
-      if (inst->Opcode == OPCODE_BRA && inst->BranchTarget < 0) {
-         for (j = 0; j < numTargets; j++) {
-            if (!strcmp(inst->Comment, targets[j].Name)) {
-               inst->BranchTarget = targets[j].Pos;
-               break;
-            }
-         }
-         if (j == numTargets) {
-            abort();
-         }
-      }
-   }
-}
-
-
 /**
  * Resolve binding of generic vertex attributes.
  * For example, if the vertex shader declared "attribute vec4 foobar" we'll
@@ -574,11 +534,9 @@ _slang_link(GLcontext *ctx,
    }
 
    if (shProg->VertexProgram) {
-      _slang_resolve_branches(&shProg->VertexProgram->Base);
       _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
    }
    if (shProg->FragmentProgram) {
-      _slang_resolve_branches(&shProg->FragmentProgram->Base);
       _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
    }