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 void KStackReturnTypeCheck(KonohaContext *kctx, KonohaStack *sfp, kMethod *mtd, KClass *reqType, KClass *thisClass) { if(!kMethod_Is(SmartReturn, mtd)) { KClass *returnType = kMethod_GetReturnType(mtd); returnType = returnType->realtype(kctx, returnType, thisClass); if(reqType == returnType || returnType->isSubType(kctx, returnType, reqType)) { if(KClass_Is(UnboxType, returnType) && !KClass_Is(UnboxType, reqType)) { KReturn(KLIB new_kObject(kctx, OnStack, returnType, sfp[K_RTNIDX].unboxValue)); } } else { ThrowTypeError(kctx, sfp, -1); } } }
/* * cbufferevent Class (*buffer_event_cb)() 1st stage callback from event_base_dispatch(), NEVER BE CALLED FROM OTHERS. */ static void Cbev_eventCB_1st(struct bufferevent *bev, short what, void *arg) { kbuffereventCBArg *cbArg = arg; KonohaContext *kctx = cbArg->kctx; BEGIN_UnusedStack(lsfp); KClass *returnType = kMethod_GetReturnType(cbArg->kcb[BEV_EventCB]->method); KUnsafeFieldSet(lsfp[0].asObject, K_NULL); KUnsafeFieldSet(lsfp[1].asObject, (kObject *)cbArg->cbev); lsfp[2].intValue = what; KUnsafeFieldSet(lsfp[3].asObject, (kObject *)cbArg->arg); KStackSetFuncAll(lsfp, KLIB Knull(kctx, returnType), 0/*UL*/, cbArg->kcb[BEV_EventCB], 3); KStackCall(lsfp); END_UnusedStack(); }
static void Cbev_dataCB_dispatcher(enum e_buffereventCB cat, struct bufferevent *bev, void *arg) { kbuffereventCBArg *cbArg = arg; KonohaContext *kctx = cbArg->kctx; BEGIN_UnusedStack(lsfp); KClass *returnType = kMethod_GetReturnType(cbArg->kcb[cat]->method); KUnsafeFieldSet(lsfp[0].asObject, K_NULL); KUnsafeFieldSet(lsfp[1].asObject, (kObject *)cbArg->cbev); KUnsafeFieldSet(lsfp[2].asObject, (kObject *)cbArg->arg); KStackSetFuncAll(lsfp, KLIB Knull(kctx, returnType), 0/*UL*/, cbArg->kcb[cat], 2); KStackCall(lsfp); END_UnusedStack(); }
/* * cevent_base Class 1st stage callback from event_base_dispatch(), NEVER BE CALLED FROM OTHERS. */ static void cevent_callback_1st(evutil_socket_t evd, short event, void *arg) { keventCBArg *cbArg = arg; KonohaContext *kctx = cbArg->kctx; BEGIN_UnusedStack(lsfp); KClass *returnType = kMethod_GetReturnType(cbArg->kcb->method); KUnsafeFieldSet(lsfp[0].asObject, K_NULL); lsfp[1].intValue = evd; lsfp[2].intValue = event; KUnsafeFieldSet(lsfp[3].asObject, (kObject *)cbArg->arg); KStackSetFuncAll(lsfp, KLIB Knull(kctx, returnType), 0/*UL*/, cbArg->kcb, 3); KStackCall(lsfp); END_UnusedStack(); }
static INode *CreateSpecialInstruction(KonohaContext *kctx, KBuilder *builder, kMethod *mtd, kNode *expr, void *thunk) { ktypeattr_t thisTy = mtd->typeId; kmethodn_t mn = mtd->mn; ktypeattr_t retTy = kMethod_GetReturnType(mtd)->typeId; kParam *params = kMethod_GetParam(mtd); kNode *stmt = expr->Parent; assert(IS_Node(stmt)); if(thisTy == KType_Boolean) { if(params->psize == 0) { /* UnaryOperator */ if(retTy == KType_Boolean) { /* booleaen booleaen.opNEG() */ enum UnaryOp Op = KMethodName_toUnaryOperator(kctx, mn); INode *Param = FetchINode(kctx, builder, expr, 1, KType_Boolean, thunk); return CreateUnaryInst(BLD(builder), Op, Param, kNode_uline(stmt)); } } else if(params->psize == 1) { /* BinaryOperator */ ktypeattr_t ptype = params->paramtypeItems[0].attrTypeId; if(retTy == KType_Boolean && ptype == KType_Boolean) { /* boolean boolean.(opEQ|opNE) (boolean x) */ enum BinaryOp Op = KMethodName_toBinaryOperator(kctx, mn); assert(Op == Eq || Op == Nq); INode *LHS = FetchINode(kctx, builder, expr, 1, KType_Boolean, thunk); INode *RHS = FetchINode(kctx, builder, expr, 2, KType_Boolean, thunk); return CreateBinaryInst(BLD(builder), Op, LHS, RHS, kNode_uline(stmt)); } } } else if(thisTy == KType_Int) { if(params->psize == 0) { /* UnaryOperator */ if(retTy == KType_Int) { /* int int.opSUB() */ enum UnaryOp Op = KMethodName_toUnaryOperator(kctx, mn); INode *Param = FetchINode(kctx, builder, expr, 1, KType_Int, thunk); return CreateUnaryInst(BLD(builder), Op, Param, kNode_uline(stmt)); } } else if(params->psize == 1) { /* BinaryOperator */ ktypeattr_t ptype = params->paramtypeItems[0].attrTypeId; if(retTy == KType_Boolean && ptype == KType_Int) { /* boolean int.(opEQ|opNE|opGT|opGE|opLT|opLE) (int x) */ enum BinaryOp Op = KMethodName_toBinaryOperator(kctx, mn); INode *LHS = FetchINode(kctx, builder, expr, 1, KType_Int, thunk); INode *RHS = FetchINode(kctx, builder, expr, 2, KType_Int, thunk); return CreateBinaryInst(BLD(builder), Op, LHS, RHS, kNode_uline(stmt)); } else if(retTy == KType_Int && ptype == KType_Int) { /* int int.(opADD|opSUB|opMUL|opDIV|opMOD|opLSHIFT|opRSHIFT|opAND|opOR|opXOR) (int x) */ enum BinaryOp Op = KMethodName_toBinaryOperator(kctx, mn); INode *LHS = FetchINode(kctx, builder, expr, 1, KType_Int, thunk); INode *RHS = FetchINode(kctx, builder, expr, 2, KType_Int, thunk); return CreateBinaryInst(BLD(builder), Op, LHS, RHS, kNode_uline(stmt)); } } } else if(FloatIsDefined() && thisTy == KType_float) { if(params->psize == 0) { /* UnaryOperator */ if(retTy == KType_float) { /* int int.opSUB() */ enum UnaryOp Op = KMethodName_toUnaryOperator(kctx, mn); INode *Param = FetchINode(kctx, builder, expr, 1, KType_float, thunk); return CreateUnaryInst(BLD(builder), Op, Param, kNode_uline(stmt)); } } else if(params->psize == 1) { /* BinaryOperator */ ktypeattr_t ptype = params->paramtypeItems[0].attrTypeId; if(retTy == KType_Boolean && ptype == KType_float) { /* boolean float.(opEQ|opNE|opGT|opGE|opLT|opLE) (float x) */ enum BinaryOp Op = KMethodName_toBinaryOperator(kctx, mn); INode *LHS = FetchINode(kctx, builder, expr, 1, KType_float, thunk); INode *RHS = FetchINode(kctx, builder, expr, 2, KType_float, thunk); return CreateBinaryInst(BLD(builder), Op, LHS, RHS, kNode_uline(stmt)); } else if(retTy == KType_float && ptype == KType_float) { /* float float.(opADD|opSUB|opMUL|opDIV) (float x) */ enum BinaryOp Op = KMethodName_toBinaryOperator(kctx, mn); INode *LHS = FetchINode(kctx, builder, expr, 1, KType_float, thunk); INode *RHS = FetchINode(kctx, builder, expr, 2, KType_float, thunk); return CreateBinaryInst(BLD(builder), Op, LHS, RHS, kNode_uline(stmt)); } } } return 0; }