/** * Generate an extended swizzle (SWZ) instruction. * * @param gen reference to code generator object * @param op instruction opcode * @param prec precision flags for instruction * @param dst destination * @param src source operand * @param optionX swizzle selector for x coordinate * @param optionY swizzle selector for y coordinate * @param optionZ swizzle selector for z coordinate * @param optionW swizzle selector for w coordinate */ void GlesGenInstSwizzle(ShaderProgramGenerator * gen, Opcode op, Precision prec, const DstReg * dst, SrcRef src, ExtSwizzleOption optionX, ExtSwizzleOption optionY, ExtSwizzleOption optionZ, ExtSwizzleOption optionW) { Inst * inst; GLES_ASSERT(gen); GLES_ASSERT(dst); GLES_ASSERT(src.base); gen->instructionCount++; if (!gen->currentList) { /* * Code generation is currently suppressed; keep track of violation of * constant expressions. */ return; } inst = GlesMemoryPoolAllocate(gen->result->memory, sizeof(InstSwizzle)); InitInstSwizzle(&inst->swizzle, op, prec, dst, src, optionX, optionY, optionZ, optionW); AppendInst(gen->currentList->tail, inst); }
/** * Generate an conditional instruction. * * @param gen reference to code generator object * @param op instruction opcode * @param cond branch condition * @param selectX selector for 1st condition flag * @param selectY selector for 2nd condition flag * @param selectZ selector for 3rd condition flag * @param selectW selector for 4th condition flag */ void GlesGenInstCond(struct ShaderProgramGenerator * gen, Opcode op, Cond cond, GLubyte selectX, GLubyte selectY, GLubyte selectZ, GLubyte selectW) { Inst * inst; GLES_ASSERT(gen); /* this is a special case, since an IF with a constant condition will be removed */ if (cond != CondT && cond != CondF) { gen->instructionCount++; } if (!gen->currentList) { /* * Code generation is currently suppressed; keep track of violation of * constant expressions. */ return; } inst = GlesMemoryPoolAllocate(gen->result->memory, sizeof(InstCond)); InitInstCond(&inst->cond, op, cond, selectX, selectY, selectZ, selectW); AppendInst(gen->currentList->tail, inst); }
/** * Generate a texture access instruction. * * @param gen reference to code generator object * @param op instruction opcode * @param prec precision modifier * @param target texture target to use * @param dst destination * @param src texture coordinate vector * @param sampler texture sampler variable to access texture memory * @param offset offset for sampler array */ void GlesGenInstTex(ShaderProgramGenerator * gen, Opcode op, Precision prec, TextureTarget target, const DstReg * dst, const SrcReg * src, ProgVar * sampler, GLsizeiptr offset) { Inst * inst; GLES_ASSERT(gen); GLES_ASSERT(dst); GLES_ASSERT(src); GLES_ASSERT(sampler); gen->instructionCount++; if (!gen->currentList) { /* * Code generation is currently suppressed; keep track of violation of * constant expressions. */ return; } inst = GlesMemoryPoolAllocate(gen->result->memory, sizeof(InstTex)); InitInstTex(&inst->tex, op, prec, target, dst, src, sampler, offset); AppendInst(gen->currentList->tail, inst); }
/** * Generate a binary instruction. * * @param gen reference to code generator object * @param op instruction opcode * @param prec precision flags for instruction * @param dst destination * @param arg0 source operand 0 * @param arg1 source operand 1 * @param arg2 source operand 2 */ void GlesGenInstTernary(ShaderProgramGenerator * gen, Opcode op, Precision prec, const DstReg * dst, const SrcReg * arg0, const SrcReg * arg1, const SrcReg * arg2) { Inst * inst; GLES_ASSERT(gen); GLES_ASSERT(dst); GLES_ASSERT(arg0); GLES_ASSERT(arg1); GLES_ASSERT(arg2); gen->instructionCount++; if (!gen->currentList) { /* * Code generation is currently suppressed; keep track of violation of * constant expressions. */ return; } inst = GlesMemoryPoolAllocate(gen->result->memory, sizeof(InstTernary)); InitInstTernary(&inst->ternary, op, prec, dst, arg0, arg1, arg2); AppendInst(gen->currentList->tail, inst); }
/** * Generate a branch or subroutine call instruction. * * @param gen reference to code generator object * @param op instruction opcode * @param target branch target * @param cond branch condition * @param selectX selector for 1st condition flag * @param selectY selector for 2nd condition flag * @param selectZ selector for 3rd condition flag * @param selectW selector for 4th condition flag */ void GlesGenInstBranch(ShaderProgramGenerator * gen, Opcode op, Label * target, Cond cond, GLubyte selectX, GLubyte selectY, GLubyte selectZ, GLubyte selectW) { Inst * inst; GLES_ASSERT(gen); GLES_ASSERT(target); gen->instructionCount++; if (!gen->currentList) { /* * Code generation is currently suppressed; keep track of violation of * constant expressions. */ return; } inst = GlesMemoryPoolAllocate(gen->result->memory, sizeof(InstBranch)); InitInstBranch(&inst->branch, op, target, cond, selectX, selectY, selectZ, selectW); AppendInst(gen->currentList->tail, inst); }
/* * CallInst -> [VarName =] call VarName(Operand, Operand, ...) * */ void GenerateFunctionCall (Type ty, Symbol recv, Symbol faddr, Vector args, int callNum) { ILArg p; IRInst inst; CALLOC(inst); if (recv) recv->ref++; faddr->ref++; FOR_EACH_ITEM (ILArg, p, args) p->sym->ref++; ENDFOR inst->ty = ty; inst->opcode = CALL; inst->callNum = callNum; /* 返回值 */ inst->opds[0] = recv; inst->opds[1] = faddr; /* 参数 */ inst->opds[2] = (Symbol)args; AppendInst (inst); /* 给返回值创建临时变量 */ if (recv != NULL) DefineTemp (recv, CALL, (Symbol)inst, NULL); }
/* * ReturnInst -> return VarName * */ void GenerateReturn (Type ty, Symbol src) { IRInst inst; CALLOC(inst); src->ref++; inst->ty = ty; inst->opcode = RET; inst->opds[0] = src; inst->opds[1] = inst->opds[2] = NULL; AppendInst (inst); }
void GenerateJump(BBlock dstBB) { IRInst inst; ALLOC(inst); dstBB->ref++; DrawCFGEdge(CurrentBB, dstBB); inst->ty = T(VOID); inst->opcode = JMP; inst->opds[0] = (Symbol)dstBB; inst->opds[1] = inst->opds[2] = NULL; AppendInst(inst); }
void GenerateIndirectMove(Type ty, Symbol dst, Symbol src) { IRInst inst; ALLOC(inst); dst->ref++; src->ref++; inst->ty = ty; inst->opcode = IMOV; inst->opds[0] = dst; inst->opds[1] = src; inst->opds[2] = NULL; AppendInst(inst); }
/* * ClearInst -> Clear VarName, constant * */ void GenerateClear (Symbol dst, int size) { IRInst inst; CALLOC (inst); dst->ref++; inst->ty = T(UCHAR); inst->opcode = CLR; inst->opds[0] = dst; inst->opds[1] = IntConstant (size); inst->opds[1]->ref++; inst->opds[2] = NULL; AppendInst (inst); }
/** * Generate a base instruction. * * @param gen reference to code generator object * @param op instruction opcode */ void GlesGenInstBase(ShaderProgramGenerator * gen, Opcode op) { Inst * inst; GLES_ASSERT(gen); if (!gen->currentList) { return; } inst = GlesMemoryPoolAllocate(gen->result->memory, sizeof(InstBase)); InitInstBase(&inst->base, InstKindBase, op); AppendInst(gen->currentList->tail, inst); }
void GenerateBranch(Type ty, BBlock dstBB, int opcode, Symbol src1, Symbol src2) { IRInst inst; ALLOC(inst); dstBB->ref++; src1->ref++; if (src2) src2->ref++; DrawCFGEdge(CurrentBB, dstBB); inst->ty = ty; inst->opcode = opcode; inst->opds[0] = (Symbol)dstBB; inst->opds[1] = src1; inst->opds[2] = src2; AppendInst(inst); }
void GenerateAssign(Type ty, Symbol dst, int opcode, Symbol src1, Symbol src2) { IRInst inst; ALLOC(inst); dst->ref++; src1->ref++; if (src2) src2->ref++; inst->ty = ty; inst->opcode = opcode; inst->opds[0] = dst; inst->opds[1] = src1; inst->opds[2] = src2; AppendInst(inst); DefineTemp(dst, opcode, src1, src2); }
static PCODEBLOCK DuplicateCodeBlock(PINTERMEDIATE_STATE psState, PCODEBLOCK psCodeBlock, PCFG psCfg) { PINST psCurrInst; PCODEBLOCK psDuplicateCodeBlock = AllocateBlock(psState, psCfg); if (psCodeBlock->uFlags & USC_CODEBLOCK_CFG) { psDuplicateCodeBlock->u.sUncond.psCfg = DuplicateCfg(psState, psCfg); psDuplicateCodeBlock->uFlags |= USC_CODEBLOCK_CFG; } for (psCurrInst = psCodeBlock->psBody; psCurrInst != NULL; psCurrInst = psCurrInst->psNext) { PINST psDuplicateInst = CopyInst(psState, psCurrInst); AppendInst(psState, psDuplicateCodeBlock, psDuplicateInst); } CopyRegLiveSet(psState, &psCodeBlock->sRegistersLiveOut, &psDuplicateCodeBlock->sRegistersLiveOut); return psDuplicateCodeBlock; }
void GenerateIndirectJump(BBlock *dstBBs, int len, Symbol index) { IRInst inst; int i; ALLOC(inst); index->ref++; for (i = 0; i < len; ++i) { dstBBs[i]->ref++; DrawCFGEdge(CurrentBB, dstBBs[i]); } inst->ty = T(VOID); inst->opcode = IJMP; inst->opds[0] = (Symbol)dstBBs; inst->opds[1] = index; inst->opds[2] = NULL; AppendInst(inst); }
/** * Generate an instruction that takes a vector argument but does not * have any result register. * * @param gen reference to code generator object * @param op instruction opcode * @param src source operand */ void GlesGenInstSrc(struct ShaderProgramGenerator * gen, Opcode op, const SrcReg * src) { Inst * inst; GLES_ASSERT(gen); GLES_ASSERT(src); gen->instructionCount++; if (!gen->currentList) { /* * Code generation is currently suppressed; keep track of violation of * constant expressions. */ return; } inst = GlesMemoryPoolAllocate(gen->result->memory, sizeof(InstSrc)); InitInstSrc(&inst->src, op, src); AppendInst(gen->currentList->tail, inst); }
/* 生成赋值指令 */ void GenerateMove (Type ty, Symbol dst, Symbol src) { IRInst inst; ALLOC(inst); dst->ref++; src->ref++; inst->ty = ty; inst->opcode = MOV; inst->opds[0] = dst; inst->opds[1] = src; inst->opds[2] = NULL; AppendInst (inst); if (dst->kind == SK_Variable) { TrackValueChange (dst); } else if (dst->kind == SK_Temp) { DefineTemp (dst, MOV, (Symbol)inst, NULL); } }
/* * AssignInst -> VarName = Expression | * -> VarName = Operand | * -> *VarName = Operand * */ void GenerateAssign (Type ty, Symbol dst, int opcode, Symbol src1, Symbol src2) { IRInst inst; CALLOC(inst); /* 符号被引用一次 */ dst->ref++; src1->ref++; if (src2) src2->ref++; /* 构造三地址码 */ inst->ty = ty; inst->opcode = opcode; inst->opds[0] = dst; inst->opds[1] = src1; inst->opds[2] = src2; /* 将三地址码添加到当前基本块中 */ AppendInst (inst); /* 构造表达式值,并添加到dst,src1,src2的uses中 */ DefineTemp (dst, opcode, src1, src2); }
/** * Generate memory access instruction (only used in low level IL). * * @param gen reference to code generator object * @param op instruction opcode * @param dst destination * @param src source operand * @param index index to use, can be NULL * @param offset constant offset to apply */ void GlesGenInstMemory(ShaderProgramGenerator * gen, Opcode op, const DstReg * dst, const SrcReg * src, const SrcReg * index, GLsizeiptr offset) { Inst * inst; GLES_ASSERT(gen); GLES_ASSERT(dst); if (!gen->currentList) { /* * Code generation is currently suppressed; keep track of violation of * constant expressions. */ gen->constViolation |= gen->constExpression; return; } inst = GlesMemoryPoolAllocate(gen->result->memory, sizeof(InstMemory)); InitInstMemory(&inst->memory, op, dst, src, index, offset); AppendInst(gen->currentList->tail, inst); }
/****************************************************************************** FUNCTION : AppendExecPredInst DESCRIPTION : Append a Execution Predication related instruciton to a CFG block PARAMETERS : psState - Compiler intermediate state psBlock - CFG block in which to append the instruction eOpcode - Opcode of the new instruction uCondPred - Index of the intermediate predicate controlling conditional execution (result of previous test) Not used for ICNDEND; bCondPredInv - Whether the state of the predicate should be inverted. Not used for ICNDEND. uLoopPred - Index of the intermediate predicate to indicate whether a loop is complete. Used for ICNDLT only. RETURNS : IMG_VOID OUTPUT : Nothing ******************************************************************************/ static IMG_VOID AppendExecPredInst( PINTERMEDIATE_STATE psState, PCODEBLOCK psBlock, IOPCODE eOpcode, IMG_UINT32 uCondPred, IMG_BOOL bCondPredInv, IMG_UINT32 uLoopPred, IMG_UINT32 uAdjust) { PINST psExecPredInst; IMG_UINT32 uCurrSrc = 0; if (psState->uExecPredTemp == USC_UNDEF) { psState->uExecPredTemp = GetNextRegister(psState); } /* Create and append the CNDx instruction to the block */ psExecPredInst = AllocateInst(psState, NULL); if(eOpcode == ICNDLT || eOpcode == ICNDEND) { SetOpcodeAndDestCount(psState, psExecPredInst, eOpcode, 2); } else { SetOpcodeAndDestCount(psState, psExecPredInst, eOpcode, 1); } SetDest(psState, psExecPredInst, 0 /* uDestIdx */, USEASM_REGTYPE_TEMP, psState->uExecPredTemp, UF_REGFORMAT_F32); if (eOpcode == ICNDLT) { MakePredicateDest(psState, psExecPredInst, 1, uLoopPred); } else if (eOpcode == ICNDEND) { psExecPredInst->asDest[1].uType = USC_REGTYPE_DUMMY; } SetSrc(psState, psExecPredInst, uCurrSrc, USEASM_REGTYPE_TEMP, psState->uExecPredTemp, UF_REGFORMAT_F32); uCurrSrc++; if (eOpcode != ICNDEND) { if(uCondPred != USC_PREDREG_NONE) { MakePredicateSource(psState, psExecPredInst, uCurrSrc, uCondPred); } else { psExecPredInst->asArg[uCurrSrc].uType = USEASM_REGTYPE_IMMEDIATE; psExecPredInst->asArg[uCurrSrc].uNumber = 0; } uCurrSrc++; psExecPredInst->asArg[uCurrSrc].uType = USEASM_REGTYPE_IMMEDIATE; if(bCondPredInv) { psExecPredInst->asArg[uCurrSrc].uNumber = 1; } else { psExecPredInst->asArg[uCurrSrc].uNumber = 0; } uCurrSrc++; } { psExecPredInst->asArg[uCurrSrc].uType = USEASM_REGTYPE_IMMEDIATE; if ((eOpcode == ICNDLT) || (eOpcode == ICNDSTLOOP) || (eOpcode == ICNDEFLOOP) || (eOpcode == ICNDSM)) { psExecPredInst->asArg[uCurrSrc].uNumber = uAdjust; } else { psExecPredInst->asArg[uCurrSrc].uNumber = 1; } } AppendInst(psState, psBlock, psExecPredInst); }
static IMG_VOID LayoutCfgFromCtrlDepNode(PINTERMEDIATE_STATE psState, PCTRL_DEP_NODE psCtrlDepNode, PCFG psCfg, PCODEBLOCK* ppsEntryBlock, PCODEBLOCK* ppsExitBlock, PCODEBLOCK psCfgActualExitBlock, IMG_BOOL bDuplicateCodeBlocks) { if (psCtrlDepNode->eCtrlDepType == CTRL_DEP_TYPE_BLOCK) { if (bDuplicateCodeBlocks == IMG_FALSE) { IMG_UINT32 uLstNodesCount = GetListNodesCount(&(psCtrlDepNode->u.sBlock.sPredLst)); if (uLstNodesCount > 1) { PUSC_LIST_ENTRY psListEntry = RemoveListHead(&(psCtrlDepNode->u.sBlock.sPredLst)); PCTRL_DEP_NODE_LISTENTRY psCtrlDepNodeLstEntry; psCtrlDepNodeLstEntry = IMG_CONTAINING_RECORD(psListEntry, PCTRL_DEP_NODE_LISTENTRY, sListEntry); UscFree(psState, psCtrlDepNodeLstEntry); //printf("duplication needed\n"); bDuplicateCodeBlocks = IMG_TRUE; } } if (psCtrlDepNode->u.sBlock.uNumSucc == 0) { if (psCtrlDepNode->u.sBlock.psBlock != psCfgActualExitBlock) { (*ppsExitBlock) = (*ppsEntryBlock) = DuplicateCodeBlockIfNeeded(psState, bDuplicateCodeBlocks, psCtrlDepNode->u.sBlock.psBlock); } else { PCODEBLOCK psReturnBlock; PINST psReturnInst; psReturnBlock = AllocateBlock(psState, psCfg); psReturnInst = AllocateInst(psState, NULL); SetOpcodeAndDestCount(psState, psReturnInst, IRETURN, 0); AppendInst(psState, psReturnBlock, psReturnInst); (*ppsExitBlock) = (*ppsEntryBlock) = psReturnBlock; } } else if (psCtrlDepNode->u.sBlock.uNumSucc == 1) { PCODEBLOCK psSubCfgEntryBlock; PCODEBLOCK psSubCfgExitBlock; LayoutCfgFromCtrlDepNode(psState, psCtrlDepNode->u.sBlock.apsSucc[0], psCfg, &psSubCfgEntryBlock, &psSubCfgExitBlock, psCfgActualExitBlock, bDuplicateCodeBlocks); { PCODEBLOCK psCndExeStBlock = AllocateBlock(psState, psCfg); PCODEBLOCK psCndExeEndBlock = AllocateBlock(psState, psCfg); PCODEBLOCK psCurrCodeBlock; AppendExecPredInst(psState, psCndExeStBlock, ICNDST, psCtrlDepNode->u.sBlock.psBlock->u.sCond.sPredSrc.uNumber, psCtrlDepNode->u.sBlock.auSuccIdx[0] == 0 ? IMG_FALSE : IMG_TRUE /* uCondPredInv */, USC_PREDREG_NONE, 1); psCurrCodeBlock = DuplicateCodeBlockIfNeeded(psState, bDuplicateCodeBlocks, psCtrlDepNode->u.sBlock.psBlock); SetBlockUnconditional(psState, psCurrCodeBlock, psCndExeStBlock); AppendExecPredInst(psState, psCndExeEndBlock, ICNDEND, USC_PREDREG_NONE, IMG_FALSE /* uCondPredInv */, USC_PREDREG_NONE, 1); SetBlockConditionalExecPred(psState, psCndExeStBlock, psSubCfgEntryBlock, psCndExeEndBlock, IMG_FALSE); SetBlockUnconditional(psState, psSubCfgExitBlock, psCndExeEndBlock); (*ppsEntryBlock) = psCurrCodeBlock; (*ppsExitBlock) = psCndExeEndBlock; } } else { PCODEBLOCK psSubCfgEntryBlock; PCODEBLOCK psSubCfgExitBlock; PCODEBLOCK psCndExeEfBlock; LayoutCfgFromCtrlDepNode(psState, psCtrlDepNode->u.sBlock.apsSucc[0], psCfg, &psSubCfgEntryBlock, &psSubCfgExitBlock, psCfgActualExitBlock, bDuplicateCodeBlocks); psCndExeEfBlock = AllocateBlock(psState, psCfg); { PCODEBLOCK psCndExeStBlock = AllocateBlock(psState, psCfg); PCODEBLOCK psCurrCodeBlock; AppendExecPredInst(psState, psCndExeStBlock, ICNDST, psCtrlDepNode->u.sBlock.psBlock->u.sCond.sPredSrc.uNumber, psCtrlDepNode->u.sBlock.auSuccIdx[0] == 0 ? IMG_FALSE : IMG_TRUE /* uCondPredInv */, USC_PREDREG_NONE, 1); psCurrCodeBlock = DuplicateCodeBlockIfNeeded(psState, bDuplicateCodeBlocks, psCtrlDepNode->u.sBlock.psBlock); SetBlockUnconditional(psState, psCurrCodeBlock, psCndExeStBlock); AppendExecPredInst(psState, psCndExeEfBlock, ICNDEF, USC_PREDREG_NONE, IMG_TRUE /* uCondPredInv */, USC_PREDREG_NONE, 1); SetBlockConditionalExecPred(psState, psCndExeStBlock, psSubCfgEntryBlock, psCndExeEfBlock, IMG_FALSE); SetBlockUnconditional(psState, psSubCfgExitBlock, psCndExeEfBlock); (*ppsEntryBlock) = psCurrCodeBlock; } LayoutCfgFromCtrlDepNode(psState, psCtrlDepNode->u.sBlock.apsSucc[1], psCfg, &psSubCfgEntryBlock, &psSubCfgExitBlock, psCfgActualExitBlock, bDuplicateCodeBlocks); { PCODEBLOCK psCndExeEndBlock = AllocateBlock(psState, psCfg); AppendExecPredInst(psState, psCndExeEndBlock, ICNDEND, USC_PREDREG_NONE, IMG_FALSE /* uCondPredInv */, USC_PREDREG_NONE, 1); SetBlockConditionalExecPred(psState, psCndExeEfBlock, psSubCfgEntryBlock, psCndExeEndBlock, IMG_FALSE); SetBlockUnconditional(psState, psSubCfgExitBlock, psCndExeEndBlock); (*ppsExitBlock) = psCndExeEndBlock; } } } else { PCODEBLOCK psPrevSubCfgExitBlock = NULL; PCODEBLOCK psSubCfgEntryBlock; PCODEBLOCK psSubCfgExitBlock; PUSC_LIST_ENTRY psListEntry; PCTRL_DEP_NODE_LISTENTRY psCtrlDepNodeLstEntry; for (psListEntry = psCtrlDepNode->u.sRegion.sSuccLst.psHead; psListEntry != NULL; psListEntry = psListEntry->psNext) { psCtrlDepNodeLstEntry = IMG_CONTAINING_RECORD(psListEntry, PCTRL_DEP_NODE_LISTENTRY, sListEntry); LayoutCfgFromCtrlDepNode(psState, psCtrlDepNodeLstEntry->psCtrlDepNode, psCfg, &psSubCfgEntryBlock, &psSubCfgExitBlock, psCfgActualExitBlock, bDuplicateCodeBlocks); if (psPrevSubCfgExitBlock == NULL) { (*ppsEntryBlock) = psSubCfgEntryBlock; } else { SetBlockUnconditional(psState, psPrevSubCfgExitBlock, psSubCfgEntryBlock); } psPrevSubCfgExitBlock = psSubCfgExitBlock; } (*ppsExitBlock) = psPrevSubCfgExitBlock; } }