⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 slang_emit.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 4 页
字号:
   }   else if (n->Opcode == IR_TEXB) {      inst = new_instruction(emitInfo, OPCODE_TXB);   }   else {      assert(n->Opcode == IR_TEXP);      inst = new_instruction(emitInfo, OPCODE_TXP);   }   if (!alloc_node_storage(emitInfo, n, 4))      return NULL;   storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);   /* Child[1] is the coord */   assert(n->Children[1]->Store->Index >= 0);   storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store);   /* 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->TexSrcTarget = n->Children[0]->Store->Size;#if 0   inst->TexSrcUnit = 27; /* Dummy value; the TexSrcUnit will be computed at                           * link time, using the sampler uniform's value.                           */   inst->Sampler = n->Children[0]->Store->Index; /* i.e. uniform's index */#else   inst->TexSrcUnit = n->Children[0]->Store->Index; /* i.e. uniform's index */#endif   return inst;}/** * Assignment/copy */static struct prog_instruction *emit_copy(slang_emit_info *emitInfo, slang_ir_node *n){   struct prog_instruction *inst;   assert(n->Opcode == IR_COPY);   /* 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 || 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   if (inst &&       _slang_is_temp(emitInfo->vt, n->Children[1]->Store) &&       (inst->DstReg.File == n->Children[1]->Store->File) &&       (inst->DstReg.Index == n->Children[1]->Store->Index)) {      /* Peephole optimization:       * The Right-Hand-Side has its results in a temporary place.       * Modify the RHS (and the prev instruction) to store its results       * in the destination specified by n->Children[0].       * Then, this MOVE is a no-op.       */      if (n->Children[1]->Opcode != IR_SWIZZLE)         _slang_free_temp(emitInfo->vt, n->Children[1]->Store);      *n->Children[1]->Store = *n->Children[0]->Store;      /* fixup the previous instruction (which stored the RHS result) */      assert(n->Children[0]->Store->Index >= 0);      /* use tighter writemask when possible */      if (n->Writemask == WRITEMASK_XYZW)         n->Writemask = inst->DstReg.WriteMask;      storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask);      return inst;   }   else#endif   {      if (n->Children[0]->Store->Size > 4) {         /* move matrix/struct etc (block of registers) */         slang_ir_storage dstStore = *n->Children[0]->Store;         slang_ir_storage srcStore = *n->Children[1]->Store;         GLint size = srcStore.Size;         ASSERT(n->Children[0]->Writemask == WRITEMASK_XYZW);         ASSERT(n->Children[1]->Store->Swizzle == SWIZZLE_NOOP);         dstStore.Size = 4;         srcStore.Size = 4;         while (size >= 4) {            inst = new_instruction(emitInfo, OPCODE_MOV);            inst->Comment = _mesa_strdup("IR_COPY block");            storage_to_dst_reg(&inst->DstReg, &dstStore, n->Writemask);            storage_to_src_reg(&inst->SrcReg[0], &srcStore);            srcStore.Index++;            dstStore.Index++;            size -= 4;         }      }      else {         /* single register move */         char *srcAnnot, *dstAnnot;         inst = new_instruction(emitInfo, OPCODE_MOV);         assert(n->Children[0]->Store->Index >= 0);         storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store, n->Writemask);         storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store);         dstAnnot = storage_annotation(n->Children[0], emitInfo->prog);         srcAnnot = storage_annotation(n->Children[1], emitInfo->prog);         inst->Comment = instruction_annotation(inst->Opcode, dstAnnot,                                                srcAnnot, NULL, NULL);      }      free_node_storage(emitInfo->vt, n->Children[1]);      return inst;   }}/** * An IR_COND node wraps a boolean expression which is used by an * IF or WHILE test.  This is where we'll set condition codes, if needed. */static struct prog_instruction *emit_cond(slang_emit_info *emitInfo, slang_ir_node *n){   struct prog_instruction *inst;   assert(n->Opcode == IR_COND);   if (!n->Children[0])      return NULL;   /* emit code for the expression */   inst = emit(emitInfo, n->Children[0]);   if (!n->Children[0]->Store) {      /* error recovery */      return NULL;   }   assert(n->Children[0]->Store);   /*assert(n->Children[0]->Store->Size == 1);*/   if (emitInfo->EmitCondCodes) {      if (inst &&          n->Children[0]->Store &&          inst->DstReg.File == n->Children[0]->Store->File &&          inst->DstReg.Index == n->Children[0]->Store->Index) {         /* The previous instruction wrote to the register who's value          * we're testing.  Just fix that instruction so that the          * condition codes are computed.          */         inst->CondUpdate = GL_TRUE;         n->Store = n->Children[0]->Store;         return inst;      }      else {         /* This'll happen for things like "if (i) ..." where no code          * is normally generated for the expression "i".          * Generate a move instruction just to set condition codes.          */         if (!alloc_node_storage(emitInfo, n, 1))            return NULL;         inst = new_instruction(emitInfo, OPCODE_MOV);         inst->CondUpdate = GL_TRUE;         storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);         storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store);         _slang_free_temp(emitInfo->vt, n->Store);         inst->Comment = _mesa_strdup("COND expr");         return inst;      }   }   else {      /* No-op: the boolean result of the expression is in a regular reg */      n->Store = n->Children[0]->Store;      return inst;   }}/** * Logical-NOT */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 */   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 (!alloc_node_storage(emitInfo, n, n->Children[0]->Store->Size))      return NULL;   inst = new_instruction(emitInfo, OPCODE_SEQ);   storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);   storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store);   constant_to_src_reg(&inst->SrcReg[1], 0.0, emitInfo);   free_node_storage(emitInfo->vt, n->Children[0]);   inst->Comment = _mesa_strdup("NOT");   return inst;}static struct prog_instruction *emit_if(slang_emit_info *emitInfo, slang_ir_node *n){   struct gl_program *prog = emitInfo->prog;   GLuint ifInstLoc, elseInstLoc = 0;   GLuint condWritemask = 0;   /* emit condition expression code */   {      struct prog_instruction *inst;      inst = emit(emitInfo, n->Children[0]);      if (emitInfo->EmitCondCodes) {         if (!inst) {            /* error recovery */            return NULL;         }         condWritemask = inst->DstReg.WriteMask;      }   }   if (!n->Children[0]->Store)      return NULL;#if 0   assert(n->Children[0]->Store->Size == 1); /* a bool! */#endif   ifInstLoc = prog->NumInstructions;   if (emitInfo->EmitHighLevelInstructions) {      struct prog_instruction *ifInst = new_instruction(emitInfo, OPCODE_IF);      if (emitInfo->EmitCondCodes) {         ifInst->DstReg.CondMask = COND_NE;  /* if cond is non-zero */         /* only test the cond code (1 of 4) that was updated by the          * previous instruction.          */         ifInst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);      }      else {         /* test reg.x */         storage_to_src_reg(&ifInst->SrcReg[0], n->Children[0]->Store);      }   }   else {      /* conditional jump to else, or endif */      struct prog_instruction *ifInst = new_instruction(emitInfo, OPCODE_BRA);      ifInst->DstReg.CondMask = COND_EQ;  /* BRA if cond is zero */      ifInst->Comment = _mesa_strdup("if zero");      ifInst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);   }   /* if body */   emit(emitInfo, n->Children[1]);   if (n->Children[2]) {      /* have else body */      elseInstLoc = prog->NumInstructions;      if (emitInfo->EmitHighLevelInstructions) {         (void) new_instruction(emitInfo, OPCODE_ELSE);      }      else {         /* jump to endif instruction */         struct prog_instruction *inst;         inst = new_instruction(emitInfo, OPCODE_BRA);         inst->Comment = _mesa_strdup("else");         inst->DstReg.CondMask = COND_TR;  /* always branch */      }      prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions;      emit(emitInfo, n->Children[2]);   }   else {      /* no else body */      prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions;   }   if (emitInfo->EmitHighLevelInstructions) {      (void) new_instruction(emitInfo, OPCODE_ENDIF);   }   if (n->Children[2]) {      prog->Instructions[elseInstLoc].BranchTarget = prog->NumInstructions;   }   return NULL;}static struct prog_instruction *emit_loop(slang_emit_info *emitInfo, slang_ir_node *n){   struct gl_program *prog = emitInfo->prog;   struct prog_instruction *endInst;   GLuint beginInstLoc, tailInstLoc, endInstLoc;   slang_ir_node *ir;   /* emit OPCODE_BGNLOOP */   beginInstLoc = prog->NumInstructions;   if (emitInfo->EmitHighLevelInstructions) {      (void) new_instruction(emitInfo, OPCODE_BGNLOOP);   }   /* body */   emit(emitInfo, n->Children[0]);   /* tail */   tailInstLoc = prog->NumInstructions;   if (n->Children[1]) {      if (emitInfo->EmitComments)         emit_comment(emitInfo, "Loop tail code:");      emit(emitInfo, n->Children[1]);   }   endInstLoc = prog->NumInstructions;   if (emitInfo->EmitHighLevelInstructions) {      /* emit OPCODE_ENDLOOP */      endInst = new_instruction(emitInfo, OPCODE_ENDLOOP);   }   else {      /* emit unconditional BRA-nch */      endInst = new_instruction(emitInfo, OPCODE_BRA);      endInst->DstReg.CondMask = COND_TR;  /* always true */   }   /* ENDLOOP's BranchTarget points to the BGNLOOP inst */   endInst->BranchTarget = beginInstLoc;   if (emitInfo->EmitHighLevelInstructions) {      /* BGNLOOP's BranchTarget points to the ENDLOOP inst */      prog->Instructions[beginInstLoc].BranchTarget = prog->NumInstructions -1;   }   /* Done emitting loop code.  Now walk over the loop's linked list of    * BREAK and CONT nodes, filling in their BranchTarget fields (which    * will point to the ENDLOOP+1 or BGNLOOP instructions, respectively).    */   for (ir = n->List; ir; ir = ir->List) {      struct prog_instruction *inst = prog->Instructions + ir->InstLocation;      assert(inst->BranchTarget < 0);      if (ir->Opcode == IR_BREAK ||          ir->Opcode == IR_BREAK_IF_TRUE) {         assert(inst->Opcode == OPCODE_BRK ||                inst->Opcode == OPCODE_BRA);         /* go to instruction after end of loop */         inst->BranchTarget = endInstLoc + 1;      }      else {         assert(ir->Opcode == IR_CONT ||                ir->Opcode == IR_CONT_IF_TRUE);         assert(inst->Opcode == OPCODE_CONT ||                inst->Opcode == OPCODE_BRA);         /* go to instruction at tail of loop */         inst->BranchTarget = endInstLoc;      }   }   return NULL;}/** * Unconditional "continue" or "break" statement. * Either OPCODE_CONT, OPCODE_BRK or OPCODE_BRA will be emitted. */static struct prog_instruction *emit_cont_break(slang_emit_info *emitInfo, slang_ir_node *n){   gl_inst_opcode opcode;   struct prog_instruction *inst;   if (n->Opcode == IR_CONT) {      /* we need to execute the loop's tail code before doing CONT */      assert(n->Parent);      assert(n->Parent->Opcode == IR_LOOP);      if (n->Parent->Children[1]) {         /* emit tail code */         if (emitInfo->EmitComments) {            emit_comment(emitInfo, "continue - tail code:");         }         emit(emitInfo, n->Parent->Children[1]);      }   }   /* opcode selection */   if (emitInfo->EmitHighLevelInstructions) {      opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK;   }   else {      opcode = OPCODE_BRA;   }   n->InstLocation = emitInfo->prog->NumInstructions;   inst = new_instruction(emitInfo, opcode);   inst->DstReg.CondMask = COND_TR;  /* always true */   return inst;}/** * Conditional "continue" or "break" statement. * Either OPCODE_CONT, OPCODE_BRK or OPCODE_BRA will be emitted. */static struct prog_instruction *emit_cont_break_if_true(slang_emit_info *emitInfo, slang_ir_node *n){   struct prog_instruction *inst;   assert(n->Opcode == IR_CONT_IF_TRUE ||          n->Opcode == IR_BREAK_IF_TRUE);   /* evaluate condition expr, setting cond codes */   inst = emit(emitInfo, n->Children[0]);   if (emitInfo->EmitCondCodes) {      assert(inst);      inst->CondUpdate = GL_TRUE;   }   n->InstLocation = emitInfo->prog->NumInstructions;   /* opcode selection */   if (emitInfo->EmitHighLevelInstructions) {      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 {         /* IF reg          *    BRK/CONT;          * ENDIF          */         GLint ifInstLoc;         ifInstLoc = emitInfo->prog->NumInstructions;         inst = new_instruction(emitInfo, OPCODE_IF);         storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store);         n->InstLocation = emitInfo->prog->NumInstructions;         inst = new_instruction(emitInfo, opcode);         inst = new_instruction(emitInfo, OPCODE_ENDIF);         emitInfo->prog->Instructions[ifInstLoc].BranchTarget            = emitInfo->prog->NumInstructions;         return inst;      }   }   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;   }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -