Пример #1
0
static kbool_t MiniVM_VisitDoWhileNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk)
{
	bblock_t HeadBB  = new_BasicBlockLABEL(kctx);
	bblock_t BodyBB  = new_BasicBlockLABEL(kctx);
	bblock_t MergeBB = new_BasicBlockLABEL(kctx);

	kUntypedNode_SetLabelBlock(kctx, node, KSymbol_("continue"), HeadBB);
	kUntypedNode_SetLabelBlock(kctx, node, KSymbol_("break"),    MergeBB);

	MiniVMBuilder_JumpTo(kctx, builder, BodyBB);
	{ /* Head */
		MiniVMBuilder_setBlock(kctx, builder, HeadBB);
		KLIB VisitNode(kctx, builder, kUntypedNode_getFirstNode(kctx, node), thunk);
		CreateBranch(kctx, builder, MiniVM_getExpression(builder), MergeBB, BodyBB, true);
	}

	{ /* Body */
		MiniVMBuilder_setBlock(kctx, builder, BodyBB);
		KLIB VisitNode(kctx, builder, kUntypedNode_getFirstBlock(kctx, node), thunk);
		MiniVMBuilder_JumpTo(kctx, builder, HeadBB);
	}

	MiniVMBuilder_setBlock(kctx, builder, MergeBB);
	return true;
}
Пример #2
0
static void kMethod_genCode(KonohaContext *kctx, kMethod *mtd, kBlock *bk)
{
	DBG_P("START CODE GENERATION..");
	INIT_GCSTACK();
	if(ctxcode == NULL) {
		kmodcode->h.setup(kctx, NULL, 0);
	}
	KLIB kMethod_setFunc(kctx, mtd, MethodFunc_runVirtualMachine);
	DBG_ASSERT(kArray_size(ctxcode->codeList) == 0);
	kBasicBlock* lbINIT  = new_BasicBlockLABEL(kctx);
	kBasicBlock* lbBEGIN = new_BasicBlockLABEL(kctx);
	ctxcode->lbEND = new_BasicBlockLABEL(kctx);
	PUSH_GCSTACK(lbINIT);
	PUSH_GCSTACK(lbBEGIN);
	PUSH_GCSTACK(ctxcode->lbEND);
	ctxcode->currentWorkingBlock = lbINIT;
//	BUILD_pushLABEL(kctx, NULL, lbBEGIN, lbEND);
	ASM(THCODE, _THCODE);
	ASM(CHKSTACK, 0);
	ASM_LABEL(kctx, lbBEGIN);
	BLOCK_asm(kctx, bk, 0);
	ASM_LABEL(kctx, ctxcode->lbEND);
	if (mtd->mn == MN_new) {
		ASM(NMOV, OC_(K_RTNIDX), OC_(0), CT_(mtd->typeId));   // FIXME: Type 'This' must be resolved
	}
	ASM(RET);
	assert(ctxcode->lbEND);/* scan-build: remove warning */
//	BUILD_popLABEL(kctx);
	BUILD_compile(kctx, mtd, lbINIT, ctxcode->lbEND);
	ctxcode->lbEND = NULL;
	RESET_GCSTACK();
}
Пример #3
0
static void AND_asm(KonohaContext *kctx, kStmt *stmt, int a, kExpr *expr, int shift, int espidx)
{
	int i, size = kArray_size(expr->cons);
	kBasicBlock*  lbTRUE = new_BasicBlockLABEL(kctx);
	kBasicBlock*  lbFALSE = new_BasicBlockLABEL(kctx);
	for(i = 1; i < size; i++) {
		EXPR_asmJMPIF(kctx, stmt, a, kExpr_at(expr, i), 0/*FALSE*/, lbFALSE, shift, espidx);
	}
	ASM(NSET, NC_(a), 1/*O_data(K_TRUE)*/, CT_Boolean);
	ASM_JMP(kctx, lbTRUE);
	ASM_LABEL(kctx, lbFALSE); // false
	ASM(NSET, NC_(a), 0/*O_data(K_FALSE)*/, CT_Boolean);
	ASM_LABEL(kctx, lbTRUE);   // TRUE
}
Пример #4
0
static struct KVirtualCode *MiniVM_GenerateVirtualCode(KonohaContext *kctx, kMethod *mtd, kUntypedNode *block, int option)
{
	KVirtualCode *vcode;
	KBuffer wb;
	KBuilder builderbuf = {{0}}, *builder = &builderbuf;
	kNameSpace *ns = kUntypedNode_ns(block);

	INIT_GCSTACK();
	KLIB KBuffer_Init(&(kctx->stack->cwb), &wb);
	builder->common.api = ns->builderApi;
	builder->constPools = ns->NameSpaceConstList;
	builder->bbBeginId  = new_BasicBlockLABEL(kctx);
	builder->bbReturnId = new_BasicBlockLABEL(kctx);
	builder->bbMainId   = builder->bbBeginId;
	builder->currentMtd = mtd;
	builder->Value      = 0;
	builder->stackbase  = 0;
	builder->InstructionSize = 0;

	builder->common.api = &CollectLocalVar_BuilderAPI;
	KLIB VisitNode(kctx, builder, block, NULL);
	builder->stackbase += builder->localVarSize + 1/* == this object */;
	builder->common.api = ns->builderApi;

	KLIB KArray_Init(kctx, &builder->localVar, sizeof(LocalVarInfo) * builder->stackbase);

	ASM(THCODE, 0, _THCODE);
	ASM(CHKSTACK, 0);

	KLIB VisitNode(kctx, builder, block, NULL);

	if(!Block_HasTerminatorInst(kctx, builder->bbMainId)) {
		MiniVMBuilder_JumpTo(kctx, builder, builder->bbReturnId);
	}

	MiniVMBuilder_setBlock(kctx, builder, builder->bbReturnId);
	if(mtd->mn == MN_new) {
		// FIXME: Type 'This' must be resolved
		ASM(NMOV, OC_(K_RTNIDX), OC_(0), KClass_(mtd->typeId));
	}
	ASM(RET);
	vcode = CompileVirtualCode(kctx, builder, builder->bbBeginId, builder->bbReturnId);

	KLIB KArray_Free(kctx, &builder->localVar);
	RESET_GCSTACK();
	KLIB KBuffer_Free(&wb);
	return vcode;

}
Пример #5
0
static void IfStmt_asm(KonohaContext *kctx, kStmt *stmt, int shift, int espidx)
{
	kBasicBlock*  lbELSE = new_BasicBlockLABEL(kctx);
	kBasicBlock*  lbEND  = new_BasicBlockLABEL(kctx);
	/* if */
	lbELSE = EXPR_asmJMPIF(kctx, stmt, espidx, SUGAR kStmt_getExpr(kctx, stmt, KW_ExprPattern, NULL), 0/*FALSE*/, lbELSE, shift, espidx);
	/* then */
	BLOCK_asm(kctx, SUGAR kStmt_getBlock(kctx, stmt, NULL/*DefaultNameSpace*/, KW_BlockPattern, K_NULLBLOCK), shift);
	ASM_JMP(kctx, lbEND);
	/* else */
	ASM_LABEL(kctx, lbELSE);
	BLOCK_asm(kctx, SUGAR kStmt_getBlock(kctx, stmt, NULL/*DefaultNameSpace*/, KW_else, K_NULLBLOCK), shift);
	/* endif */
	ASM_LABEL(kctx, lbEND);
}
Пример #6
0
static void LoopStmt_asm(KonohaContext *kctx, kStmt *stmt, int shift, int espidx)
{
	kBasicBlock* lbCONTINUE = new_BasicBlockLABEL(kctx);
	kBasicBlock* lbBREAK = new_BasicBlockLABEL(kctx);
//	BUILD_pushLABEL(kctx, stmt, lbCONTINUE, lbBREAK);
	KLIB kObject_setObject(kctx, stmt, SYM_("continue"), TY_BasicBlock, lbCONTINUE);
	KLIB kObject_setObject(kctx, stmt, SYM_("break"), TY_BasicBlock, lbBREAK);
	ASM_LABEL(kctx, lbCONTINUE);
	ASM_SAFEPOINT(kctx, espidx);
	EXPR_asmJMPIF(kctx, stmt, espidx, SUGAR kStmt_getExpr(kctx, stmt, KW_ExprPattern, NULL), 0/*FALSE*/, lbBREAK, shift, espidx);
	//BLOCK_asm(kctx, SUGAR kStmt_getBlock(kctx, stmt, KW_("iteration"), K_NULLBLOCK));
	BLOCK_asm(kctx, SUGAR kStmt_getBlock(kctx, stmt, NULL/*DefaultNameSpace*/, KW_BlockPattern, K_NULLBLOCK), shift);
	ASM_JMP(kctx, lbCONTINUE);
	ASM_LABEL(kctx, lbBREAK);
//	BUILD_popLABEL(kctx);
}
Пример #7
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;
}
Пример #8
0
static void CreateCond(KonohaContext *kctx, KBuilder *builder, kUntypedNode *expr, enum ConditionalOp Op, void *thunk)
{
	intptr_t cond;
	kUntypedNode *LHS = kUntypedNode_At(expr, 1);
	kUntypedNode *RHS = kUntypedNode_At(expr, 2);

	bblock_t HeadBB  = new_BasicBlockLABEL(kctx);
	bblock_t ThenBB  = new_BasicBlockLABEL(kctx);
	bblock_t MergeBB = new_BasicBlockLABEL(kctx);

	/* [CondExpr]
	 * LogicalAnd case
	 *       | goto Head
	 * Head  | let bval = LHS
	 *       | if(bval) { goto Then } else { goto Merge }
	 * Then  | bval = RHS
	 *       | goto Merge
	 * Merge | ...
	 */

	MiniVMBuilder_JumpTo(kctx, builder, HeadBB);
	cond = builder->stackbase;
	builder->stackbase += 1;
	{ /* Head */
		MiniVMBuilder_setBlock(kctx, builder, HeadBB);
		KLIB VisitNode(kctx, builder, LHS, thunk);
		CreateUpdate(kctx, builder, KType_Boolean, cond, MiniVM_getExpression(builder));
		if(Op == LogicalAnd)
			CreateBranch(kctx, builder, cond, ThenBB, MergeBB, false);
		else {
			CreateBranch(kctx, builder, cond, ThenBB, MergeBB, true);
		}
	}
	{ /* Then */
		MiniVMBuilder_setBlock(kctx, builder, ThenBB);
		KLIB VisitNode(kctx, builder, RHS, thunk);
		CreateUpdate(kctx, builder, KType_Boolean, cond, MiniVM_getExpression(builder));
		MiniVMBuilder_JumpTo(kctx, builder, MergeBB);
	}

	MiniVMBuilder_setBlock(kctx, builder, MergeBB);
	builder->stackbase -= 1;
	builder->Value = builder->stackbase;
}
Пример #9
0
static kbool_t MiniVM_VisitLoopNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk, enum LoopType Loop)
{
	kUntypedNode *ItrBlock;
	bblock_t HeadBB  = new_BasicBlockLABEL(kctx);
	bblock_t BodyBB  = new_BasicBlockLABEL(kctx);
	bblock_t ItrBB   = new_BasicBlockLABEL(kctx);
	bblock_t MergeBB = new_BasicBlockLABEL(kctx);

	kUntypedNode_SetLabelBlock(kctx, node, KSymbol_("continue"), ItrBB);
	kUntypedNode_SetLabelBlock(kctx, node, KSymbol_("break"),    MergeBB);

	ItrBlock = KLIB kUntypedNode_GetNode(kctx, node, KSymbol_("Iterator"), NULL);
	if(ItrBlock != NULL) {
		assert(Loop == ForLoop);
		MiniVMBuilder_JumpTo(kctx, builder, HeadBB);
	}
	else if(Loop == WhileLoop) {
		MiniVMBuilder_JumpTo(kctx, builder, HeadBB);
	} else {
		MiniVMBuilder_JumpTo(kctx, builder, BodyBB);
	}

	{ /* Head */
		MiniVMBuilder_setBlock(kctx, builder, HeadBB);
		KLIB VisitNode(kctx, builder, kUntypedNode_getFirstNode(kctx, node), thunk);
		CreateBranch(kctx, builder, MiniVM_getExpression(builder), BodyBB, MergeBB, false);
	}

	{ /* Body */
		MiniVMBuilder_setBlock(kctx, builder, BodyBB);
		KLIB VisitNode(kctx, builder, kUntypedNode_getFirstBlock(kctx, node), thunk);
		MiniVMBuilder_JumpTo(kctx, builder, ItrBB);

		/* Itr */
		MiniVMBuilder_setBlock(kctx, builder, ItrBB);
		if(ItrBlock != NULL) {
			KLIB VisitNode(kctx, builder, ItrBlock, thunk);
		}
		MiniVMBuilder_JumpTo(kctx, builder, HeadBB);
	}

	MiniVMBuilder_setBlock(kctx, builder, MergeBB);
	return true;
}
Пример #10
0
static kbool_t MiniVM_VisitBlockNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *block, void *thunk)
{
	size_t i;
	bblock_t NewBlock = new_BasicBlockLABEL(kctx);
	MiniVMBuilder_JumpTo(kctx, builder, NewBlock);
	MiniVMBuilder_setBlock(kctx, builder, NewBlock);
	for(i = 0; i < kUntypedNode_GetNodeListSize(kctx, block); i++) {
		kUntypedNode *stmt = block->NodeList->NodeItems[i];
		builder->common.uline = kUntypedNode_uline(stmt);
		if(!KLIB VisitNode(kctx, builder, stmt, thunk))
			break;
	}
	return true;
}
Пример #11
0
static kbool_t MiniVM_VisitIfNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk)
{
	bblock_t ThenBB  = new_BasicBlockLABEL(kctx);
	bblock_t ElseBB  = new_BasicBlockLABEL(kctx);
	bblock_t MergeBB = new_BasicBlockLABEL(kctx);
	/* if */
	KLIB VisitNode(kctx, builder, kUntypedNode_getFirstNode(kctx, node), thunk);
	CreateBranch(kctx, builder, MiniVM_getExpression(builder), ThenBB, ElseBB, false);
	{ /* then */
		MiniVMBuilder_setBlock(kctx, builder, ThenBB);
		KLIB VisitNode(kctx, builder, kUntypedNode_getFirstBlock(kctx, node), thunk);
		if(!Block_HasTerminatorInst(kctx, builder->bbMainId))
			MiniVMBuilder_JumpTo(kctx, builder, MergeBB);
	}
	{ /* else */
		MiniVMBuilder_setBlock(kctx, builder, ElseBB);
		KLIB VisitNode(kctx, builder, kUntypedNode_getElseBlock(kctx, node), thunk);
		if(!Block_HasTerminatorInst(kctx, builder->bbMainId))
			MiniVMBuilder_JumpTo(kctx, builder, MergeBB);
	}
	/* endif */
	MiniVMBuilder_setBlock(kctx, builder, MergeBB);
	return true;
}
Пример #12
0
static bblock_t AsmJMPF(KonohaContext *kctx, KBuilder *builder, int localStack, bblock_t jumpId)
{
	BasicBlock *bb = BasicBlock_FindById(kctx, builder->bbMainId);
	DBG_ASSERT(bb != NULL);
	DBG_ASSERT(bb->nextid == -1 && bb->branchid == -1);
	bblock_t nextId = new_BasicBlockLABEL(kctx);
	ASM(JMPF, NULL, NC_(localStack));
	bb = BasicBlock_FindById(kctx, builder->bbMainId);
	BasicBlock *jumpBlock = BasicBlock_FindById(kctx, jumpId);
	BasicBlock *nextBlock = BasicBlock_FindById(kctx, nextId);
	bb->branchid = BasicBlock_id(kctx, jumpBlock);
	bb->nextid = nextId;
	nextBlock->incoming += 1;
	jumpBlock->incoming += 1;
	builder->bbMainId = nextId;
	return nextId;
}
Пример #13
0
static kBasicBlock* ASM_JMPF(KonohaContext *kctx, int flocal, kBasicBlock *lbJUMP)
{
	kBasicBlock *bb = ctxcode->currentWorkingBlock;
	kBasicBlock *lbNEXT = new_BasicBlockLABEL(kctx);
	OPJMPF op = {TADDR, OPCODE_JMPF, ASMLINE, NULL, NC_(flocal)};
	if(BUILD_asmJMPF(kctx, &op)) {
		bb->branchBlock = lbNEXT;
		bb->nextBlock = lbJUMP;
	}
	else {
		bb->branchBlock = lbJUMP;
		bb->nextBlock = lbNEXT;
	}
	lbNEXT->incoming += 1;
	ctxcode->currentWorkingBlock = lbNEXT;
	lbJUMP->incoming += 1;
	return lbJUMP;
}