static size_t BasicBlock_size(KonohaContext *kctx, kBasicBlock *bb, size_t c) { L_TAIL:; if(bb == NULL || BasicBlock_isVisited(bb)) return c; BasicBlock_setVisited(bb, 1); if(bb->nextBlock != NULL) { if(BasicBlock_isVisited(bb) || BasicBlock_opcode(bb->nextBlock) == OPCODE_RET) { kBasicBlock *bb2 = (kBasicBlock*)new_BasicBlockLABEL(kctx); bb2->branchBlock = bb->nextBlock; ((kBasicBlock*)bb)->nextBlock = bb2; } } if(bb->branchBlock != NULL && bb->nextBlock != NULL) { DBG_ASSERT(bb->branchBlock != bb->nextBlock); c = BasicBlock_size(kctx, bb->nextBlock, c + BasicBlock_peephole(kctx, bb)); bb = bb->branchBlock; goto L_TAIL; } if(bb->branchBlock != NULL) { DBG_ASSERT(bb->nextBlock == NULL); kBasicBlock_add(bb, JMP); c = BasicBlock_peephole(kctx, bb) + c; bb = bb->branchBlock; goto L_TAIL; } c = BasicBlock_peephole(kctx, bb) + c; bb = bb->nextBlock; goto L_TAIL; }
static void BasicBlock_SetJumpAddr(KonohaContext *kctx, BasicBlock *bb, char *vcode) { while(bb != NULL) { BasicBlock_SetVisited(bb); if(bb->branchid != -1) { BasicBlock *bbJ = BasicBlock_leapJump(kctx, BasicBlock_FindById(kctx, bb->branchid)); KVirtualCode *op = (KVirtualCode *)(vcode + bb->lastoffset); OPJMP *j = (OPJMP *) op; DBG_ASSERT(j->opcode == OPCODE_JMP || j->opcode == OPCODE_JMPF); j->jumppc = (KVirtualCode *)(vcode + bbJ->codeoffset); if(BasicBlock_size(bb) > 1) { KVirtualCode *opPREV = (KVirtualCode *)(vcode + bb->lastoffset - sizeof(KVirtualCode)); if(opPREV->opcode == OPCODE_JMPF && bb->nextid != -1) { BasicBlock *block = BasicBlock_leapJump(kctx, BasicBlock_FindById(kctx, bb->nextid)); ((OPJMPF *)opPREV)->jumppc = (KVirtualCode *)(vcode + block->codeoffset); } } bbJ = BasicBlock_FindById(kctx, bb->branchid); if(!BasicBlock_isVisited(bbJ)) { BasicBlock_SetVisited(bbJ); BasicBlock_SetJumpAddr(kctx, bbJ, vcode); } } bb = BasicBlock_FindById(kctx, bb->nextid); } }
static VirtualMachineInstruction* BasicBlock_copy(KonohaContext *kctx, VirtualMachineInstruction *dst, kBasicBlock *bb, kBasicBlock **prev) { BasicBlock_setVisited(bb, 0); DBG_ASSERT(!BasicBlock_isVisited(bb)); // DBG_P("BB%d: asm nextBlock=BB%d, branchBlock=BB%d", BB_(bb), BB_(bb->nextBlock), BB_(bb->branchBlock)); if(bb->code != NULL) { return dst; } if(prev[0] != NULL && prev[0]->nextBlock == NULL && prev[0]->branchBlock == bb) { dst -= 1; //DBG_P("BB%d: REMOVE unnecessary JMP/(?%s)", BB_(bb), T_opcode(dst->opcode)); DBG_ASSERT(dst->opcode == OPCODE_JMP/* || dst->opcode == OPJMP_*/); prev[0]->branchBlock = NULL; prev[0]->nextBlock = bb; } bb->code = dst; if(BasicBlock_codesize(bb) > 0) { memcpy(dst, BBOP(bb), sizeof(VirtualMachineInstruction) * BasicBlock_codesize(bb)); if(bb->branchBlock != NULL) { bb->opjmp = (dst + (BasicBlock_codesize(bb) - 1)); } dst = dst + BasicBlock_codesize(bb); KLIB Karray_free(kctx, &bb->codeTable); prev[0] = bb; } if(bb->nextBlock != NULL) { //DBG_P("BB%d: NEXT=BB%d", BB_(bb), BB_(bb->nextBlock)); DBG_ASSERT(bb->nextBlock->code == NULL); dst = BasicBlock_copy(kctx, dst, bb->nextBlock, prev); } if(bb->branchBlock != NULL) { dst = BasicBlock_copy(kctx, dst, bb->branchBlock, prev); } return dst; }
static void BasicBlock_strip1(KonohaContext *kctx, kBasicBlock *bb) { while(true) { if(!BasicBlock_isVisited(bb)) return; BasicBlock_setVisited(bb, 0); // MUST call after strip0 if(bb->branchBlock != NULL) { if(bb->nextBlock == NULL) { bb = bb->branchBlock; } else { BasicBlock_strip1(kctx, bb->branchBlock); bb = bb->nextBlock; } continue; } if(bb->nextBlock != NULL) { kBasicBlock *bbN = bb->nextBlock; if(bbN->incoming == 1 && BasicBlock_opcode(bbN) != OPCODE_RET) { BasicBlock_join(kctx, bb, bbN); BasicBlock_setVisited(bb, 1); continue; } bb = bb->nextBlock; } } }
static void BasicBlock_strip0(KonohaContext *kctx, kBasicBlock *bb) { while(true) { if(BasicBlock_isVisited(bb)) return; BasicBlock_setVisited(bb, 1); if(bb->branchBlock != NULL) { L_JUMP:; { kBasicBlock *bbJ = (kBasicBlock*)bb->branchBlock; if(bbJ->codeTable.bytesize == 0 && bbJ->branchBlock != NULL && bbJ->nextBlock == NULL) { //DBG_P("DIRECT JMP id=%d JMP to id=%d", bbJ->id, DP(bbJ->branchBlock)->id); bbJ->incoming -= 1; bb->branchBlock = bbJ->branchBlock; bb->branchBlock->incoming += 1; goto L_JUMP; } if(bbJ->codeTable.bytesize == 0 && bbJ->branchBlock == NULL && bbJ->nextBlock != NULL) { //DBG_P("DIRECT JMP id=%d NEXT to id=%d", bbJ->id, DP(bbJ->nextBlock)->id); bbJ->incoming -= 1; bb->branchBlock = bbJ->nextBlock; bb->branchBlock->incoming += 1; goto L_JUMP; } if(bb->nextBlock == NULL) { if(bbJ->incoming == 1 ) { //DBG_P("REMOVED %d JMP TO %d", bb->id, bbJ->id); bb->nextBlock = bbJ; bb->branchBlock = NULL; goto L_NEXT; } } BasicBlock_strip0(kctx, bbJ); } } if(bb->branchBlock != NULL && bb->nextBlock != NULL) { bb = bb->nextBlock; continue; } L_NEXT:; if(bb->nextBlock != NULL) { kBasicBlock *bbN = bb->nextBlock; if(bbN->codeTable.bytesize == 0 && bbN->nextBlock != NULL && bbN->branchBlock == NULL) { bbN->incoming -= 1; bb->nextBlock = bbN->nextBlock; bb->nextBlock->incoming += 1; goto L_NEXT; } if(bbN->codeTable.bytesize == 0 && bbN->nextBlock == NULL && bbN->branchBlock != NULL) { bbN->incoming -= 1; bb->nextBlock = NULL; bb->branchBlock = bbN->branchBlock; bb->branchBlock->incoming += 1; goto L_JUMP; } bb = bb->nextBlock; } } }
static void BasicBlock_setjump(kBasicBlock *bb) { while(bb != NULL) { BasicBlock_setVisited(bb, 1); if(bb->branchBlock != NULL) { kBasicBlock *bbJ = bb->branchBlock; OPJMP *j = (OPJMP*)bb->opjmp; j->jumppc = bbJ->code; bb->branchBlock = NULL; if(!BasicBlock_isVisited(bbJ)) { BasicBlock_setVisited(bbJ, 1); BasicBlock_setjump(bbJ); } } bb = bb->nextBlock; } }