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; }
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(); }
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 }
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; }
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); }
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); }
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 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; }
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; }
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; }
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; }
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; }
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; }