Be more consistant with paths in #includes. Eventually, eliminate a bunch of -I...
[mesa.git] / src / mesa / shader / slang / slang_emit.c
index b5a2dfaafc4d661e7a1bd5fef10dc46365f7b276..02c74095a9e500b4f003ce7dca4061e32cb2e064 100644 (file)
  ***/
 
 
-#include "imports.h"
-#include "context.h"
-#include "macros.h"
-#include "program.h"
-#include "prog_instruction.h"
-#include "prog_parameter.h"
-#include "prog_print.h"
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "shader/program.h"
+#include "shader/prog_instruction.h"
+#include "shader/prog_parameter.h"
+#include "shader/prog_print.h"
 #include "slang_builtin.h"
 #include "slang_emit.h"
+#include "slang_mem.h"
 
 
 #define PEEPHOLE_OPTIMIZATIONS 1
@@ -126,7 +127,7 @@ slang_ir_storage *
 _slang_new_ir_storage(enum register_file file, GLint index, GLint size)
 {
    slang_ir_storage *st;
-   st = (slang_ir_storage *) _mesa_calloc(sizeof(slang_ir_storage));
+   st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
    if (st) {
       st->File = file;
       st->Index = index;
@@ -151,6 +152,8 @@ alloc_temp_storage(slang_emit_info *emitInfo, slang_ir_node *n, GLint size)
    if (!_slang_alloc_temp(emitInfo->vt, n->Store)) {
       slang_info_log_error(emitInfo->log,
                            "Ran out of registers, too many temporaries");
+      _slang_free(n->Store);
+      n->Store = NULL;
       return GL_FALSE;
    }
    return GL_TRUE;
@@ -895,7 +898,11 @@ emit_tex(slang_emit_info *emitInfo, slang_ir_node *n)
 
    /* Child[0] is the sampler (a uniform which'll indicate the texture unit) */
    assert(n->Children[0]->Store);
+   /* Store->Index is the sampler index */
+   assert(n->Children[0]->Store->Index >= 0);
+   /* Store->Size is the texture target */
    assert(n->Children[0]->Store->Size >= TEXTURE_1D_INDEX);
+   assert(n->Children[0]->Store->Size <= TEXTURE_RECT_INDEX);
 
    inst->Sampler = n->Children[0]->Store->Index; /* i.e. uniform's index */
    inst->TexSrcTarget = n->Children[0]->Store->Size;
@@ -913,17 +920,26 @@ emit_move(slang_emit_info *emitInfo, slang_ir_node *n)
 
    /* lhs */
    emit(emitInfo, n->Children[0]);
+   if (!n->Children[0]->Store || n->Children[0]->Store->Index < 0) {
+      /* an error should have been already recorded */
+      return NULL;
+   }
 
    /* rhs */
    assert(n->Children[1]);
    inst = emit(emitInfo, n->Children[1]);
 
-   if (!n->Children[1]->Store) {
-      slang_info_log_error(emitInfo->log, "invalid assignment");
+   if (!n->Children[1]->Store || n->Children[1]->Store->Index < 0) {
+      if (!emitInfo->log->text) {
+         slang_info_log_error(emitInfo->log, "invalid assignment");
+      }
       return NULL;
    }
+
    assert(n->Children[1]->Store->Index >= 0);
 
+   /*assert(n->Children[0]->Store->Size == n->Children[1]->Store->Size);*/
+
    n->Store = n->Children[0]->Store;
 
 #if PEEPHOLE_OPTIMIZATIONS
@@ -1053,12 +1069,37 @@ emit_cond(slang_emit_info *emitInfo, slang_ir_node *n)
 static struct prog_instruction *
 emit_not(slang_emit_info *emitInfo, slang_ir_node *n)
 {
+   static const struct {
+      gl_inst_opcode op, opNot;
+   } operators[] = {
+      { OPCODE_SLT, OPCODE_SGE },
+      { OPCODE_SLE, OPCODE_SGT },
+      { OPCODE_SGT, OPCODE_SLE },
+      { OPCODE_SGE, OPCODE_SLT },
+      { OPCODE_SEQ, OPCODE_SNE },
+      { OPCODE_SNE, OPCODE_SEQ },
+      { 0, 0 }
+   };
    struct prog_instruction *inst;
+   GLuint i;
 
    /* child expr */
-   (void) emit(emitInfo, n->Children[0]);
-   /* XXXX if child instr is SGT convert to SLE, if SEQ, SNE, etc */
+   inst = emit(emitInfo, n->Children[0]);
 
+#if PEEPHOLE_OPTIMIZATIONS
+   if (inst) {
+      /* if the prev instruction was a comparison instruction, invert it */
+      for (i = 0; operators[i].op; i++) {
+         if (inst->Opcode == operators[i].op) {
+            inst->Opcode = operators[i].opNot;
+            n->Store = n->Children[0]->Store;
+            return inst;
+         }
+      }
+   }
+#endif
+
+   /* else, invert using SEQ (v = v == 0) */
    if (!n->Store)
       if (!alloc_temp_storage(emitInfo, n, n->Children[0]->Store->Size))
          return NULL;
@@ -1289,8 +1330,13 @@ emit_cont_break_if_true(slang_emit_info *emitInfo, slang_ir_node *n)
       const gl_inst_opcode opcode
          = (n->Opcode == IR_CONT_IF_TRUE) ? OPCODE_CONT : OPCODE_BRK;
       if (emitInfo->EmitCondCodes) {
+         /* Get the writemask from the previous instruction which set
+          * the condcodes.  Use that writemask as the CondSwizzle.
+          */
+         const GLuint condWritemask = inst->DstReg.WriteMask;
          inst = new_instruction(emitInfo, opcode);
          inst->DstReg.CondMask = COND_NE;
+         inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
          return inst;
       }
       else {
@@ -1313,9 +1359,11 @@ emit_cont_break_if_true(slang_emit_info *emitInfo, slang_ir_node *n)
       }
    }
    else {
+      const GLuint condWritemask = inst->DstReg.WriteMask;
       assert(emitInfo->EmitCondCodes);
       inst = new_instruction(emitInfo, OPCODE_BRA);
       inst->DstReg.CondMask = COND_NE;
+      inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
       return inst;
    }
 }
@@ -1535,9 +1583,9 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n)
       }
 
       if (n->Store->Index < 0) {
-         printf("#### VAR %s not allocated!\n", (char*)n->Var->a_name);
+         /* probably ran out of registers */
+         return NULL;
       }
-      assert(n->Store->Index >= 0);
       assert(n->Store->Size > 0);
       break;
 
@@ -1715,6 +1763,7 @@ _slang_resolve_subroutines(slang_emit_info *emitInfo)
    mainP->Instructions = _mesa_realloc_instructions(mainP->Instructions,
                                                     mainP->NumInstructions,
                                                     total);
+   mainP->NumInstructions = total;
    for (i = 0; i < emitInfo->NumSubroutines; i++) {
       struct gl_program *sub = emitInfo->Subroutines[i];
       _mesa_copy_instructions(mainP->Instructions + subroutineLoc[i],
@@ -1724,7 +1773,13 @@ _slang_resolve_subroutines(slang_emit_info *emitInfo)
       sub->Parameters = NULL; /* prevent double-free */
       _mesa_delete_program(ctx, sub);
    }
-   mainP->NumInstructions = total;
+
+   /* free subroutine list */
+   if (emitInfo->Subroutines) {
+      _mesa_free(emitInfo->Subroutines);
+      emitInfo->Subroutines = NULL;
+   }
+   emitInfo->NumSubroutines = 0;
 
    /* Examine CAL instructions.
     * At this point, the BranchTarget field of the CAL instructions is
@@ -1762,9 +1817,9 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt,
    emitInfo.NumSubroutines = 0;
 
    emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions;
-   emitInfo.EmitCondCodes = 0*ctx->Shader.EmitCondCodes;
+   emitInfo.EmitCondCodes = ctx->Shader.EmitCondCodes;
    emitInfo.EmitComments = ctx->Shader.EmitComments;
-   emitInfo.EmitBeginEndSub = 0;  /* XXX for compiler debug only */
+   emitInfo.EmitBeginEndSub = GL_TRUE;
 
    if (!emitInfo.EmitCondCodes) {
       emitInfo.EmitHighLevelInstructions = GL_TRUE;