예제 #1
0
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;
}
예제 #2
0
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);
	}
}
예제 #3
0
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;
}
예제 #4
0
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;
		}
	}
}
예제 #5
0
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;
		}
	}
}
예제 #6
0
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;
	}
}