Esempio n. 1
0
        public override Value Visit(ForLoop node)
        {
            //		store startval, id
            //	forloop:
            //		body
            //		idval = load id
            //		incr/decr idval
            //		store idval, id
            //		cmp idval, endval
            //		br slt/sgt forloop, forend
            //	forend:
            // NOTE: it is invalid to modify the id var inside the loop

            // func was set in Visit(RoutineDefinition node)
            Function func = evalCtx.func;

            Value id       = traverse(node.var);
            Value startval = traverse(node.start);
            Value endval   = traverse(node.end);

            builder.BuildStore(startval, id);

            Debug.Assert(!id.IsNull, "Invalid For var id");
            Debug.Assert(!startval.IsNull, "Invalid For start value");
            Debug.Assert(!endval.IsNull, "Invalid For end value");

            BasicBlock forloop = func.AppendBasicBlock("forloop");
            BasicBlock forend  = func.AppendBasicBlock("forend");

            evalCtx.EnterLoop(forloop, forend);
            builder.BuildBr(forloop);
            builder.ResetInsertPoint(func, forloop);

            Value body = traverse(node.block);

            Debug.Assert(!body.IsNull, "Invalid For loop body");

            // emit the step and test
            Value idval = builder.BuildLoad(id);

            if (node.direction > 0)             // incr
            {
                idval = builder.BuildAdd(idval, Value.CreateConstInt32(1));
            }
            else                // decr
            {
                idval = builder.BuildSub(idval, Value.CreateConstInt32(1));
            }

            builder.BuildStore(idval, id);              // persist the final value after the For
            var   op     = (node.direction > 0) ? LLVMIntPredicate.IntULT : LLVMIntPredicate.IntUGT;
            Value cmpres = builder.BuildICmp(idval, op, endval);

            builder.BuildCondBr(cmpres, forloop, forend);

            builder.ResetInsertPoint(func, forend);
            evalCtx.LeaveLoop();
            return(Value.NonNull);
        }