📄 slang_emit.c
字号:
} 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 + -