static kbool_t FuelVM_VisitIfNode(KonohaContext *kctx, KBuilder *builder, kNode *stmt, void *thunk) { kNode *expr = kNode_getFirstNode(kctx, stmt); Block *ThenBB = CreateBlock(BLD(builder)); Block *ElseBB = CreateBlock(BLD(builder)); Block *MergeBB = CreateBlock(BLD(builder)); /* if */ SUGAR VisitNode(kctx, builder, expr, thunk); CreateBranch(BLD(builder), FuelVM_getExpression(builder), ThenBB, ElseBB); { /* then */ IRBuilder_setBlock(BLD(builder), ThenBB); SUGAR VisitNode(kctx, builder, kNode_getFirstBlock(kctx, stmt), thunk); if(!Block_HasTerminatorInst(BLD(builder)->Current)) { IRBuilder_JumpTo(BLD(builder), MergeBB); } } { /* else */ IRBuilder_setBlock(BLD(builder), ElseBB); SUGAR VisitNode(kctx, builder, kNode_getElseBlock(kctx, stmt), thunk); if(!Block_HasTerminatorInst(BLD(builder)->Current)) { IRBuilder_JumpTo(BLD(builder), MergeBB); } } /* endif */ IRBuilder_setBlock(BLD(builder), MergeBB); return true; }
static struct KVirtualCode *FuelVM_GenerateVirtualCode(KonohaContext *kctx, kMethod *mtd, kNode *block, int option) { if(unlikely(AbstractMethodPtr == 0)) { AbstractMethodPtr = mtd->invokeKMethodFunc; } kNameSpace *ns = kNode_ns(block); KBuilder builderbuf = {}, *builder = &builderbuf; FuelIRBuilder Builder = {}; INIT_GCSTACK(); IRBuilder_Init(&Builder, kctx, ns); builder->builder = &Builder; builder->common.api = ns->builderApi; Block *EntryBlock = CreateBlock(BLD(builder)); IRBuilder_setBlock(BLD(builder), EntryBlock); INode *Self = SetUpArguments(kctx, &Builder, mtd); SUGAR VisitNode(kctx, builder, block, NULL); if(!Block_HasTerminatorInst(BLD(builder)->Current)) { if(mtd->mn == MN_new) { INode *Ret = CreateReturn(BLD(builder), Self); INode_setType(Ret, ConvertToTypeId(kctx, mtd->typeId)); } else { ktypeattr_t retTy = kMethod_GetReturnType(mtd)->typeId; if(retTy == KType_void) { CreateReturn(BLD(builder), 0); } else { enum TypeId Type = ConvertToTypeId(kctx, retTy); INode *Ret; if(KType_Is(UnboxType, retTy)) { SValue V; V.bits = 0; Ret = CreateConstant(BLD(builder), Type, V); } else { kObject *obj = KLIB Knull(kctx, KClass_(retTy)); Ret = CreateObject(BLD(builder), Type, (void *)obj); } Ret = CreateReturn(BLD(builder), Ret); INode_setType(Ret, Type); CreateReturn(BLD(builder), 0); } } } RESET_GCSTACK(); IMethod Mtd = {kctx, mtd, EntryBlock, ns}; BLD(builder)->Method = &Mtd; bool JITCompiled = false; union ByteCode *code = IRBuilder_Compile(BLD(builder), &Mtd, option, &JITCompiled); if(mtd->invokeKMethodFunc == FuelVM_RunVirtualMachine) { mtd->virtualCodeApi_plus1[-1]->FreeVirtualCode(kctx, mtd->vcode_start); } KLIB kMethod_SetFunc(kctx, mtd, 0); if(JITCompiled) { KLIB kMethod_SetFunc(kctx, mtd, (KMethodFunc) code); } KFieldSet(mtd, ((kMethodVar *)mtd)->CompiledNode, block); IRBuilder_Exit(&Builder); return (struct KVirtualCode *) code; }
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 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; }