Ejemplo n.º 1
0
static kbool_t FuelVM_VisitErrorNode(KonohaContext *kctx, KBuilder *builder, kNode *stmt, void *thunk)
{
	kString *Err  = kNode_getErrorMessage(kctx, stmt);
	INode   *Node = CreateObject(BLD(builder), TYPE_String, (void *)Err);
	CreateThrow(BLD(builder), Node, KException_("RuntimeScript"), SoftwareFault, kNode_uline(stmt));
	return true;
}
Ejemplo n.º 2
0
void print(enum log_level lvl, const char *fmt, ...)
{
	struct timeval tv;

	va_list ap;
	va_start(ap, fmt);

	/* Timestamp */
	gettimeofday(&tv, NULL);
	
	fprintf(stderr, "%8.3f ", timespec_delta(&epoch, &tv));

	switch (lvl) {
		case DEBUG: fprintf(stderr, BLD("%-5s "), GRY("Debug")); break;
		case INFO:  fprintf(stderr, BLD("%-5s "), WHT(" Info")); break;
		case WARN:  fprintf(stderr, BLD("%-5s "), YEL(" Warn")); break;
		case ERROR: fprintf(stderr, BLD("%-5s "), RED("Error")); break;
	}

	if (_indent) {
		for (int i = 0; i < _indent-1; i++)
			fprintf(stderr, GFX("\x78") " ");

		fprintf(stderr, GFX("\x74") " ");
	}

	vfprintf(stderr, fmt, ap);
	fprintf(stderr, "\n");

	va_end(ap);
}
Ejemplo n.º 3
0
static kbool_t FuelVM_VisitAssignNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk)
{
	/*
	 * [LetExpr] := lhs = rhs
	 * expr->NodeList = [NULL, lhs, rhs]
	 **/

	kNode *left = kNode_At(expr, 1);
	kNode *right = kNode_At(expr, 2);
	INode *Node;
	FuelIRBuilder *flbuilder = BLD(builder);
	if(left->node == KNode_Local) {
		enum TypeId type = ConvertToTypeId(kctx, left->attrTypeId);
		if((Node = IRBuilder_FindLocalVarByHash(flbuilder, type, left->index)) == 0) {
			Node = CreateLocal(flbuilder, type);
			IField_setHash((IField *) Node, left->index);
		}
		SUGAR VisitNode(kctx, builder, right, thunk);
		INode *RHS = FuelVM_getExpression(builder);
		//if(RHS->Type != Node->Type) {
		//	INode_setType(Node, RHS->Type);
		//}
		CreateUpdate(flbuilder, Node, RHS);
	}
	//else if(left->node == TEXPR_STACKTOP) {
	//	enum TypeId type = ConvertToTypeId(kctx, left->attrTypeId);
	//	uintptr_t Hash = (uintptr_t) left;
	//	if((Node = IRBuilder_FindLocalVarByHash(flbuilder, type, Hash)) == 0) {
	//		Node = CreateLocal(flbuilder, type);
	//		IField_setHash((IField *) Node, Hash);
	//		ARRAY_add(INodePtr, &BLD(builder)->Stack, Node);
	//	}
	//	SUGAR VisitNode(kctx, builder, right, thunk);
	//	INode *RHS = FuelVM_getExpression(builder);
	//	if(RHS->Type != Node->Type)
	//		INode_setType(Node, RHS->Type);
	//	CreateUpdate(BLD(builder), Node, RHS);
	//}
	else{
		assert(left->node == KNode_Field);
		SUGAR VisitNode(kctx, builder, right, thunk);
		kshort_t index  = (kshort_t)left->index;
		kshort_t xindex = (kshort_t)(left->index >> (sizeof(kshort_t)*8));

		INode *Left;
		if((Left = IRBuilder_FindLocalVarByHash(BLD(builder), TYPE_Object, index)) == 0) {
			Left = CreateLocal(BLD(builder), TYPE_Object);
			IField_setHash((IField *) Left, index);
		}
		enum TypeId type = ConvertToTypeId(kctx, left->attrTypeId);
		Node = CreateField(BLD(builder), FieldScope, type, Left, xindex);
		SUGAR VisitNode(kctx, builder, right, thunk);
		CreateUpdate(BLD(builder), Node, FuelVM_getExpression(builder));
	}
	builder->Value = Node;
	return true;
}
Ejemplo n.º 4
0
static kbool_t FuelVM_VisitLocalNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk)
{
	INode *Inst;
	if((Inst = IRBuilder_FindLocalVarByHash(BLD(builder), ConvertToTypeId(kctx, expr->attrTypeId), expr->index)) == 0) {
		Inst = CreateLocal(BLD(builder), ConvertToTypeId(kctx, expr->attrTypeId));
		IField_setHash((IField *) Inst, expr->index);
	}
	builder->Value = Inst;
	return true;
}
Ejemplo n.º 5
0
static kbool_t FuelVM_VisitReturnNode(KonohaContext *kctx, KBuilder *builder, kNode *stmt, void *thunk)
{
	kNode *expr = SUGAR kNode_GetNode(kctx, stmt, KSymbol_ExprPattern, NULL);
	if(expr != NULL && IS_Node(expr) && expr->attrTypeId != KType_void) {
		SUGAR VisitNode(kctx, builder, expr, thunk);
		INode *Ret  = FuelVM_getExpression(builder);
		INode *Inst = CreateReturn(BLD(builder), Ret);
		INode_setType(Inst, ConvertToTypeId(kctx, expr->attrTypeId));
	} else {
		CreateReturn(BLD(builder), 0);
	}
	return true;
}
Ejemplo n.º 6
0
static kbool_t FuelVM_VisitFieldNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk)
{
	INode *Node;
	kshort_t index  = (kshort_t)expr->index;
	kshort_t xindex = (kshort_t)(expr->index >> (sizeof(kshort_t)*8));
	enum TypeId Type = ConvertToTypeId(kctx, expr->attrTypeId);
	if((Node = IRBuilder_FindLocalVarByHash(BLD(builder), TYPE_Object, index)) == 0) {
		Node = CreateLocal(BLD(builder), TYPE_Object);
		IField_setHash((IField *) Node, index);
	}
	Node = CreateField(BLD(builder), FieldScope, Type, Node, xindex);
	builder->Value = Node;
	return true;
}
Ejemplo n.º 7
0
static kbool_t FuelVM_VisitNewNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk)
{
	enum TypeId Type = ConvertToTypeId(kctx, expr->attrTypeId);
	INode *Expr = CreateNew(BLD(builder), expr->unboxConstValue, Type);
	builder->Value = Expr;
	return true;
}
Ejemplo n.º 8
0
static kbool_t FuelVM_VisitJumpNode(KonohaContext *kctx, KBuilder *builder, kNode *stmt, void *thunk, ksymbol_t label)
{
	kNode *jump = kNode_GetNode(kctx, stmt, label);
	DBG_ASSERT(jump != NULL && IS_Node(jump));
	Block *target = kNode_GetTargetBlock(kctx, jump, label);
	IRBuilder_JumpTo(BLD(builder), target);
	return true;
}
Ejemplo n.º 9
0
static kbool_t FuelVM_VisitMethodCallNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk)
{
	kMethod *mtd = CallNode_getMethod(expr);
	DBG_ASSERT(IS_Method(mtd));
	enum TypeId Type = ConvertToTypeId(kctx, expr->attrTypeId);
	if(mtd->mn == KMethodName_("box")) {
		Type = ToBoxType(Type);
	}

	/*
	 * [CallExpr] := this.method(arg1, arg2, ...)
	 * expr->NodeList = [method, this, arg1, arg2, ...]
	 **/
	INode *Inst;
	if((Inst = CreateSpecialInstruction(kctx, builder, mtd, expr, thunk)) != 0) {
		INode_setType(Inst, Type);
		builder->Value = Inst;
		return true;
	}
	int i, s = kMethod_Is(Static, mtd) ? 2 : 1;
	int argc = CallExpr_getArgCount(expr);
	INode *Params[argc+2];

	if(kMethod_Is(Static, mtd)) {
		kObject *obj = KLIB Knull(kctx, KClass_(mtd->typeId));
		INode *Self = CreateObject(BLD(builder), mtd->typeId, (void *) obj);
		Params[1] = Self;
	}
	for (i = s; i < argc + 2; i++) {
		kNode *exprN = kNode_At(expr, i);
		DBG_ASSERT(IS_Node(exprN));
		SUGAR VisitNode(kctx, builder, exprN, thunk);
		INode *Node = FuelVM_getExpression(builder);
		assert(Node->Type != TYPE_void);
		Params[i] = Node;
	}

	INode *MtdObj = CreateObject(BLD(builder), KType_Method, (void *) mtd);
	enum CallOp Op = (kMethod_Is(Virtual, mtd)) ? VirtualCall : DefaultCall;
	Params[0] = MtdObj;
	kNode *stmt = expr->Parent;
	assert(IS_Node(stmt));
	Inst = CreateICall(BLD(builder), Type, Op, kNode_uline(stmt), Params, argc + 2);
	builder->Value = Inst;
	return true;
}
Ejemplo n.º 10
0
static kbool_t FuelVM_VisitConstNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk)
{
	kObject *v = expr->ObjectConstValue;
	DBG_ASSERT(!KType_Is(UnboxType, expr->attrTypeId));
	//DBG_ASSERT(kNode_HasObjectConstValue(expr));
	builder->Value = CreateObject(BLD(builder), expr->attrTypeId, (void *)v);
	return true;
}
Ejemplo n.º 11
0
static kbool_t FuelVM_VisitUnboxConstNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk)
{
	DBG_ASSERT(KType_Is(UnboxType, expr->attrTypeId));
	//DBG_ASSERT(!kNode_HasObjectConstValue(expr));

	SValue Val = {};
	Val.bits = expr->unboxConstValue;
	builder->Value = CreateConstant(BLD(builder), ConvertToTypeId(kctx, expr->attrTypeId), Val);
	return true;
}
Ejemplo n.º 12
0
static kbool_t FuelVM_VisitBlockNode(KonohaContext *kctx, KBuilder *builder, kNode *block, void *thunk)
{
	unsigned size = ARRAY_size(BLD(builder)->Stack);
	Block *NewBlock = CreateBlock(BLD(builder));
	IRBuilder_JumpTo(BLD(builder), NewBlock);
	IRBuilder_setBlock(BLD(builder), NewBlock);
	size_t i;
	for(i = 0; i < kNode_GetNodeListSize(kctx, block); i++) {
		kNode *stmt = block->NodeList->NodeItems[i];
		builder->common.uline = kNode_uline(stmt);
		if(!SUGAR VisitNode(kctx, builder, stmt, thunk))
			break;
	}
	ARRAY_size(BLD(builder)->Stack) = size;
	if(builder->Value) {
		INode *Node = FuelVM_getExpression(builder);
		builder->Value = Node;
	}
	return true;
}
Ejemplo n.º 13
0
static kbool_t FuelVM_VisitNullNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk)
{
	SValue Val = {};
	ktypeattr_t type = expr->attrTypeId;
	if(KType_Is(UnboxType, type)) {
		Val.bits = 0;
	} else {
		Val.ptr = (void *) KLIB Knull(kctx, KClass_(type));
	}
	builder->Value = CreateConstant(BLD(builder), ConvertToTypeId(kctx, expr->attrTypeId), Val);
	return true;
}
Ejemplo n.º 14
0
static kbool_t FuelVM_VisitFunctionNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk)
{
	/*
	 * [FunctionExpr] := new Function(method, env1, env2, ...)
	 * expr->NodeList = [method, defObj, env1, env2, ...]
	 **/
	enum TypeId Type;
	kMethod *mtd = CallNode_getMethod(expr);
	kObject *obj = expr->NodeList->ObjectItems[1];
	INode *MtdObj = CreateObject(BLD(builder), KType_Method, (void *) mtd);

	Type = ConvertToTypeId(kctx, kObject_class(obj)->typeId);
	INode *NewEnv  = CreateNew(BLD(builder), 0, Type);

	size_t i, ParamSize = kArray_size(expr->NodeList)-2;
	for(i = 0; i < ParamSize; i++) {
		kNode *envN = kNode_At(expr, i+2);
		enum TypeId FieldType = ConvertToTypeId(kctx, envN->attrTypeId);
		INode *Node = CreateField(BLD(builder), FieldScope, FieldType, NewEnv, i);
		SUGAR VisitNode(kctx, builder, envN, thunk);
		CreateUpdate(BLD(builder), Node, FuelVM_getExpression(builder));
	}

	Type = ConvertToTypeId(kctx, expr->attrTypeId);
	INode *NewFunc = CreateNew(BLD(builder), 0, Type);

	kNameSpace *ns = kNode_ns(expr);
	mtd =  KLIB kNameSpace_GetMethodByParamSizeNULL(kctx, ns, KClass_Func, KMethodName_("_Create"), 2, KMethodMatch_NoOption);

	INode *CallMtd = CreateObject(BLD(builder), KType_Method, (void *) mtd);
	INode *Params[4];
	Params[0] = CallMtd;
	Params[1] = NewFunc;
	Params[2] = NewEnv;
	Params[3] = MtdObj;
	builder->Value = CreateICall(BLD(builder), Type, DefaultCall, kNode_uline(expr), Params, 4);

	return true;
}
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 16
0
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;
}
Ejemplo n.º 17
0
static void CreateCond(KonohaContext *kctx, KBuilder *builder, kNode *expr, enum ConditionalOp Op, void *thunk)
{
	kNode *LHS = kNode_At(expr, 1);
	kNode *RHS = kNode_At(expr, 2);

	Block *HeadBB  = CreateBlock(BLD(builder));
	Block *ThenBB  = CreateBlock(BLD(builder));
	Block *MergeBB = CreateBlock(BLD(builder));

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

	INode *Node;
	IRBuilder_JumpTo(BLD(builder), HeadBB);
	{ /* Head */
		IRBuilder_setBlock(BLD(builder), HeadBB);
		Node = CreateLocal(BLD(builder), TYPE_boolean);
		SUGAR VisitNode(kctx, builder, LHS, thunk);
		INode *Left = FuelVM_getExpression(builder);
		CreateUpdate(BLD(builder), Node, Left);

		if(Op == LogicalAnd) {
			CreateBranch(BLD(builder), Left, ThenBB, MergeBB);
		} else {
			CreateBranch(BLD(builder), Left, MergeBB, ThenBB);
		}
	}
	{ /* Then */
		IRBuilder_setBlock(BLD(builder), ThenBB);
		SUGAR VisitNode(kctx, builder, RHS, thunk);
		INode *Right = FuelVM_getExpression(builder);
		CreateUpdate(BLD(builder), Node, Right);
		IRBuilder_JumpTo(BLD(builder), MergeBB);
	}

	IRBuilder_setBlock(BLD(builder), MergeBB);
	builder->Value = Node;
}
Ejemplo n.º 18
0
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;
}
Ejemplo n.º 19
0
static kbool_t FuelVM_VisitLoopNode(KonohaContext *kctx, KBuilder *builder, kNode *stmt, void *thunk, enum LoopType Loop)
{
	Block *HeadBB  = CreateBlock(BLD(builder));
	Block *BodyBB  = CreateBlock(BLD(builder));
	Block *ItrBB   = CreateBlock(BLD(builder));
	Block *MergeBB = CreateBlock(BLD(builder));

	kNode_SetLabelBlock(kctx, stmt, KSymbol_("continue"), ItrBB);
	kNode_SetLabelBlock(kctx, stmt, KSymbol_("break"),    MergeBB);

	kNode *itrBlock = SUGAR kNode_GetNode(kctx, stmt, KSymbol_("Iterator"), NULL);
	if(itrBlock != NULL) {
		assert(Loop == ForLoop);
		IRBuilder_JumpTo(BLD(builder), HeadBB);
	}
	else if(Loop == WhileLoop) {
		/* [WhileStmt]
		 * "Head" is Join Node
		 * Head  : if(COND) { goto Body } else {goto Merge }
		 * Body  : Body
		 *         ...
		 *         goto Itr
		 * Itr   : Body3
		 *         goto Head
		 * Merge : ...
		 */
		IRBuilder_JumpTo(BLD(builder), HeadBB);
	} else {
		/* [LoopStmt] (e.g. do-while loop)
		 * "Body" is Join Node
		 * Body  : Body
		 *         ...
		 *         goto Itr
		 * Itr   : Body3
		 *         goto Head
		 * Head  : if(COND) { goto Body } else {goto Merge }
		 * Merge : ...
		 */
		IRBuilder_JumpTo(BLD(builder), BodyBB);
	}

	{ /* Head */
		IRBuilder_setBlock(BLD(builder), HeadBB);
		SUGAR VisitNode(kctx, builder, kNode_getFirstNode(kctx, stmt), thunk);
		CreateBranch(BLD(builder), FuelVM_getExpression(builder), BodyBB, MergeBB);
	}

	{ /* Body */
		IRBuilder_setBlock(BLD(builder), BodyBB);
		SUGAR VisitNode(kctx, builder, kNode_getFirstBlock(kctx, stmt), thunk);
		IRBuilder_JumpTo(BLD(builder), ItrBB);

		/* Itr */
		IRBuilder_setBlock(BLD(builder), ItrBB);
		if(itrBlock != NULL) {
			SUGAR VisitNode(kctx, builder, itrBlock, thunk);
		}
		IRBuilder_JumpTo(BLD(builder), HeadBB);
	}

	IRBuilder_setBlock(BLD(builder), MergeBB);
	return true;
}