static kbool_t KBuilder_VisitMethodCallNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk) { kshort_t a = AssignStack(thunk), espidx = expr->stackbase, thisidx = espidx + K_CALLDELTA; DBG_ASSERT(a <= espidx); kMethod *mtd = CallNode_getMethod(expr); DBG_ASSERT(IS_Method(mtd)); int i, s = kMethod_Is(Static, mtd) ? 2 : 1; int argc = CallNode_getArgCount(expr); for (i = s; i < argc + 2; i++) { intptr_t a = thisidx + i - 1; kNode *paramNode = kNode_At(expr, i); if(!kNode_IsValue(paramNode) && paramNode->stackbase != a) { DBG_P("a=%d, stackbase=%d", a, paramNode->stackbase); DBG_ASSERT(paramNode->stackbase == a); } SUGAR VisitNode(kctx, builder, paramNode, &a); } if(kMethod_Is(Final, mtd) || !kMethod_Is(Virtual, mtd)) { ASM(NSET, NC_(thisidx-1), (intptr_t)mtd, KClass_Method); if(kMethod_Is(Virtual, mtd)) { // set namespace to enable method lookups ASM(NSET, OC_(thisidx-2), (intptr_t)kNode_ns(expr), KClass_NameSpace); } } else { ASM(NSET, OC_(thisidx-2), (intptr_t)kNode_ns(expr), KClass_NameSpace); ASM(LOOKUP, SFP_(thisidx), kNode_ns(expr), mtd); } int esp_ = SFP_(espidx + argc + K_CALLDELTA + 1); ASM(CALL, builder->common.uline, SFP_(thisidx), esp_, KLIB Knull(kctx, KClass_(expr->attrTypeId))); ReAssignNonValueNode(kctx, builder, a, expr); 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 NMOV_asm(KonohaContext *kctx, int a, ktype_t ty, int b) { if(TY_isUnbox(ty)) { ASM(NMOV, NC_(a), NC_(b), CT_(ty)); } else { ASM(NMOV, OC_(a), OC_(b), CT_(ty)); } }
static kbool_t MiniVM_VisitMethodCallNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk) { kMethod *mtd = CallNode_getMethod(node); /* * [CallExpr] := this.method(arg1, arg2, ...) * node->NodeList = [method, this, arg1, arg2, ...] **/ intptr_t stackbase, thisidx; int i, s, argc = CallNode_getArgCount(node); DBG_ASSERT(IS_Method(mtd)); s = kMethod_Is(Static, mtd) ? 2 : 1; if(kMethod_Is(Static, mtd)) { KClass *selfTy = KClass_(mtd->typeId); kObject *obj = KLIB Knull(kctx, selfTy); ASM(NSET, OC_(builder->stackbase), (uintptr_t) obj, selfTy); } stackbase = builder->stackbase; thisidx = stackbase + K_CALLDELTA; for (i = s; i < argc + 2; i++) { kUntypedNode *exprN = kUntypedNode_At(node, i); builder->stackbase = thisidx + i - 1; DBG_ASSERT(IS_Node(exprN)); KLIB VisitNode(kctx, builder, exprN, thunk); if(builder->Value != builder->stackbase) { KClass *ty = KClass_(exprN->typeAttr); ASM_NMOV(kctx, builder, ty, builder->stackbase, builder->Value); } } if(kMethod_Is(Final, mtd) || !kMethod_Is(Virtual, mtd)) { ASM(NSET, NC_(thisidx-1), (intptr_t)mtd, KClass_Method); if(kMethod_Is(Virtual, mtd)) { // set namespace to enable method lookups ASM(NSET, OC_(thisidx-2), (intptr_t)kUntypedNode_ns(node), KClass_NameSpace); } } else { ASM(NSET, OC_(thisidx-2), (intptr_t)kUntypedNode_ns(node), KClass_NameSpace); ASM(LOOKUP, SFP_(thisidx), kUntypedNode_ns(node), mtd); } ASM(CALL, kUntypedNode_uline(node), SFP_(thisidx), SFP_(thisidx + argc + 1), KLIB Knull(kctx, KClass_(node->typeAttr))); builder->stackbase = stackbase; builder->Value = builder->stackbase; return 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 kbool_t KBuilder_VisitConstNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk) { DBG_ASSERT(!KType_Is(UnboxType, expr->attrTypeId)); kObject *v = KBuilder_AddConstPool(kctx, builder, expr->ObjectConstValue); kshort_t a = AssignStack(thunk); ASM(NSET, OC_(a), (uintptr_t)v, KClass_(expr->attrTypeId)); return true; }
static kbool_t MiniVM_VisitConstNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk) { kObject *v = MiniVM_AddConstPool(kctx, builder, node->ObjectConstValue); DBG_ASSERT(!KType_Is(UnboxType, node->typeAttr)); ASM(NSET, OC_(builder->stackbase), (uintptr_t) v, KClass_(node->typeAttr)); builder->Value = builder->stackbase; return true; }
static kbool_t KBuilder_VisitFieldNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk) { kshort_t a = AssignStack(thunk); kshort_t index = (kshort_t)expr->index; kshort_t xindex = (kshort_t)(expr->index >> (sizeof(kshort_t)*8)); KClass *ty = KClass_(expr->attrTypeId); ASM(NMOVx, TC_(a, ty), OC_(index), xindex, ty); return true; }
static kbool_t MiniVM_VisitNullNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk) { if(KType_Is(UnboxType, node->typeAttr)) { ASM(NSET, NC_(builder->stackbase), 0, KClass_(node->typeAttr)); } else { ASM(NUL, OC_(builder->stackbase), KClass_(node->typeAttr)); } builder->Value = builder->stackbase; return true; }
static kbool_t MiniVM_VisitBoxNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk) { /* * [box] := box(this) **/ KLIB VisitNode(kctx, builder, node->NodeToPush, thunk); ASM(BOX, OC_(builder->stackbase), NC_(MiniVM_getExpression(builder)), KClass_(node->typeAttr)); builder->Value = builder->stackbase; return true; }
static kbool_t KBuilder_VisitNullNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk) { kshort_t a = AssignStack(thunk); if(KType_Is(UnboxType, expr->attrTypeId)) { ASM(NSET, NC_(a), 0, KClass_(expr->attrTypeId)); } else { ASM(NUL, OC_(a), KClass_(expr->attrTypeId)); } return true; }
static kbool_t MiniVM_VisitAssignNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk) { /* * [LetExpr] := lhs = rhs * expr->NodeList = [NULL, lhs, rhs] **/ intptr_t dst = -1; kUntypedNode *left = kUntypedNode_At(node, 1); kUntypedNode *right = kUntypedNode_At(node, 2); ktypeattr_t type = left->typeAttr; ksymbol_t symbol; assert(IS_Token(left->TermToken)); symbol = left->TermToken->symbol; if(kUntypedNode_node(left) == KNode_Local) { if((dst = MiniVMBuilder_FindLocalVar(kctx, builder, symbol, type, left->index)) == -1) { dst = AddLocal(kctx, builder, left->index, symbol, type); } KLIB VisitNode(kctx, builder, right, thunk); CreateUpdate(kctx, builder, type, dst, MiniVM_getExpression(builder)); builder->Value = dst; } else { khalfword_t index = (khalfword_t)left->index; khalfword_t xindex = (khalfword_t)(left->index >> (sizeof(khalfword_t)*8)); KClass *lhsClass = KClass_(left->typeAttr); KClass *rhsClass = KClass_(right->typeAttr); assert(kUntypedNode_node(left) == KNode_Field); if((dst = MiniVMBuilder_FindLocalVar(kctx, builder, symbol, KType_Object, index)) == -1) { dst = AddLocal(kctx, builder, index, symbol, KType_Object); } KLIB VisitNode(kctx, builder, right, thunk); ASM(XNMOV, OC_(index), xindex, TC_(MiniVM_getExpression(builder), rhsClass), lhsClass); if(node->typeAttr != KType_void) { builder->Value = builder->stackbase; ASM(NMOVx, TC_(builder->stackbase, rhsClass), OC_(index), xindex, lhsClass); } } return true; }
static kbool_t KBuilder_VisitAssignNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk) { kNode *leftHandNode = kNode_At(expr, 1); kNode *rightHandNode = kNode_At(expr, 2); //DBG_P("LET (%s) a=%d, shift=%d, espidx=%d", KType_text(expr->attrTypeId), a, shift, espidx); if(kNode_node(leftHandNode) == KNode_Local) { kshort_t a = AssignStack(thunk); SUGAR VisitNode(kctx, builder, rightHandNode, &(leftHandNode->index)); if(expr->attrTypeId != KType_void && a != leftHandNode->index) { AsmMOV(kctx, builder, a, KClass_(leftHandNode->attrTypeId), leftHandNode->index); } } else if(kNode_node(leftHandNode) == KNode_Field) { intptr_t espidx = expr->stackbase; SUGAR VisitNode(kctx, builder, rightHandNode, &espidx); kshort_t index = (kshort_t)leftHandNode->index; kshort_t xindex = (kshort_t)(leftHandNode->index >> (sizeof(kshort_t)*8)); KClass *lhsClass = KClass_(leftHandNode->attrTypeId), *rhClass = KClass_(rightHandNode->attrTypeId); ASM(XNMOV, OC_(index), xindex, TC_(espidx, rhClass), lhsClass); if(expr->attrTypeId != KType_void) { kshort_t a = AssignStack(thunk); ASM(NMOVx, TC_(a, rhClass), OC_(index), xindex, lhsClass); } }
static kbool_t MiniVM_VisitFieldNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk) { ksymbol_t symbol; intptr_t src; KClass *ty; khalfword_t index = (khalfword_t)(node->index); khalfword_t xindex = (khalfword_t)(node->index >> (sizeof(khalfword_t)*8)); assert(IS_Token(node->TermToken)); symbol = node->TermToken->symbol; if((src = MiniVMBuilder_FindLocalVar(kctx, builder, symbol, KType_Object, index)) == -1) { src = AddLocal(kctx, builder, index, symbol, KType_Object); } ty = KClass_(node->typeAttr); ASM(NMOVx, TC_(builder->stackbase, ty), OC_(src), xindex, ty); builder->Value = builder->stackbase; return true; }
static void LETEXPR_asm(KonohaContext *kctx, kStmt *stmt, int a, kExpr *expr, int shift, int espidx) { kExpr *leftHandExpr = kExpr_at(expr, 1); kExpr *rightHandExpr = kExpr_at(expr, 2); DBG_P("LET (%s) a=%d, shift=%d, espidx=%d", TY_t(expr->ty), a, shift, espidx); if(leftHandExpr->build == TEXPR_LOCAL) { EXPR_asm(kctx, stmt, leftHandExpr->index, rightHandExpr, shift, espidx); if(expr->ty != TY_void && a != leftHandExpr->index) { NMOV_asm(kctx, a, leftHandExpr->ty, leftHandExpr->index); } } else if(leftHandExpr->build == TEXPR_STACKTOP) { DBG_P("LET TEXPR_STACKTOP a=%d, leftHandExpr->index=%d, espidx=%d", a, leftHandExpr->index, espidx); EXPR_asm(kctx, stmt, leftHandExpr->index + shift, rightHandExpr, shift, espidx); if(expr->ty != TY_void && a != leftHandExpr->index + shift) { NMOV_asm(kctx, a, leftHandExpr->ty, leftHandExpr->index + shift); } } else{ assert(leftHandExpr->build == TEXPR_FIELD); EXPR_asm(kctx, stmt, espidx, rightHandExpr, shift, espidx); kshort_t index = (kshort_t)leftHandExpr->index; kshort_t xindex = (kshort_t)(leftHandExpr->index >> (sizeof(kshort_t)*8)); if(TY_isUnbox(rightHandExpr->ty)) { ASM(XNMOV, OC_(index), xindex, NC_(espidx), CT_(leftHandExpr->ty)); if(expr->ty != TY_void) { ASM(NMOVx, NC_(a), OC_(index), xindex, CT_(leftHandExpr->ty)); } } else { ASM(XNMOV, OC_(index), xindex, OC_(espidx), CT_(leftHandExpr->ty)); if(expr->ty != TY_void) { ASM(NMOVx, OC_(a), OC_(index), xindex, CT_(leftHandExpr->ty)); } } } }
static kbool_t MiniVM_VisitNewNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk) { ASM(NEW, OC_(builder->stackbase), 0, KClass_(node->typeAttr)); builder->Value = builder->stackbase; return true; }
static kbool_t KBuilder_VisitNewNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk) { kshort_t a = AssignStack(thunk); ASM(NEW, OC_(a), expr->index, KClass_(expr->attrTypeId)); return true; }
static void EXPR_asm(KonohaContext *kctx, kStmt *stmt, int a, kExpr *expr, int shift, int espidx) { DBG_ASSERT(expr != NULL); //DBG_P("a=%d, shift=%d, espidx=%d", a, shift, espidx); switch(expr->build) { case TEXPR_CONST : { kObject *v = expr->objectConstValue; DBG_ASSERT(!TY_isUnbox(expr->ty)); DBG_ASSERT(Expr_hasObjectConstValue(expr)); v = BUILD_addConstPool(kctx, v); ASM(NSET, OC_(a), (uintptr_t)v, CT_(expr->ty)); break; } case TEXPR_NEW : { ASM(NEW, OC_(a), expr->index, CT_(expr->ty)); break; } case TEXPR_NULL : { if(TY_isUnbox(expr->ty)) { ASM(NSET, NC_(a), 0, CT_(expr->ty)); } else { ASM(NULL, OC_(a), CT_(expr->ty)); } break; } case TEXPR_NCONST : { ASM(NSET, NC_(a), expr->unboxConstValue, CT_(expr->ty)); break; } case TEXPR_LOCAL : { NMOV_asm(kctx, a, expr->ty, expr->index); break; } case TEXPR_BLOCK : { DBG_ASSERT(IS_Block(expr->block)); BLOCK_asm(kctx, expr->block, espidx); NMOV_asm(kctx, a, expr->ty, /*expr->index*/ espidx); break; } case TEXPR_FIELD : { kshort_t index = (kshort_t)expr->index; kshort_t xindex = (kshort_t)(expr->index >> (sizeof(kshort_t)*8)); if(TY_isUnbox(expr->ty)) { ASM(NMOVx, NC_(a), OC_(index), xindex, CT_(expr->ty)); } else { ASM(NMOVx, OC_(a), OC_(index), xindex, CT_(expr->ty)); } break; } case TEXPR_CALL : CALL_asm(kctx, stmt, a, expr, shift, espidx); if(a != espidx) { NMOV_asm(kctx, a, expr->ty, espidx); } break; case TEXPR_AND : AND_asm(kctx, stmt, a, expr, shift, espidx); break; case TEXPR_OR : OR_asm(kctx, stmt, a, expr, shift, espidx); break; case TEXPR_LET : LETEXPR_asm(kctx, stmt, a, expr, shift, espidx); break; case TEXPR_STACKTOP : //DBG_P("STACKTOP mov %d, %d, < %d", a, expr->index + shift, espidx); DBG_ASSERT(expr->index + shift < espidx); NMOV_asm(kctx, a, expr->ty, expr->index + shift); break; default: DBG_ABORT("unknown expr=%d", expr->build); } }