Пример #1
0
        public void TestLoopInstruction()
        {
            var count1 = 0;
            var count2 = 0;

            var instructions = new List <Instruction>
            {
                new CustomInstruction(_ => ++ count1 % 10 != 0),
                new CustomInstruction(_ => ++ count2 % 15 != 0),
            };

            var loop         = new LoopInstruction(instructions, 10);
            var critterState = new CritterState();

            var count = 0;

            for (; count < 1000; count++)
            {
                if (loop.Tick(critterState) == false)
                {
                    break;
                }
            }

            if (count >= 1000)
            {
                Assert.Fail("Too many ticks");
            }

            Assert.AreEqual(100, count1);
            Assert.AreEqual(150, count2);
        }
Пример #2
0
        private IEnumerable <Instruction> Parse(IEnumerator <BrainfuckInstruction> cursor)
        {
            while (cursor.MoveNext())
            {
                var currentBrainfuckInstruction = cursor.Current;

                if (!_loopInstructions.Contains(currentBrainfuckInstruction))
                {
                    yield return(CreateInstruction(currentBrainfuckInstruction));
                }
                else if (currentBrainfuckInstruction == BrainfuckInstruction.StartLoop)
                {
                    var loopInstruction = new LoopInstruction();
                    loopInstruction.AddRange(Parse(cursor));
                    yield return(loopInstruction);
                }
            }
        }
Пример #3
0
    private Instruction ParseInstruction(List <Instruction> instructions, ref int i)
    {
        var instruction = instructions[i++];

        if (instruction is LoopInstruction)
        {
            List <Instruction> loopedInstructions = new List <Instruction>();

            //Instruction nextInstruction = ParseInstruction(instructions, ref i);
            //while(!nextInstruction.IsLoopBreaker) {
            //	loopedInstructions.Add(nextInstruction);
            //	nextInstruction = ParseInstruction(instructions, ref i);
            //}

            Instruction nextInstruction = instructions[i++];
            while (!nextInstruction.IsLoopBreaker)
            {
                loopedInstructions.Add(nextInstruction);
                nextInstruction = instructions[i++];
            }

            if (loopedInstructions.Count > 0)
            {
                var lastInstruction = loopedInstructions.Last();
                lastInstruction.DecrementForLoopOnLine = instruction.CorrespondingUILineNumber;
            }

            instructions.Remove(instruction);
            i -= 2;
            LoopInstruction loopInstruction = instruction as LoopInstruction;
            for (int j = 1; j < loopInstruction.End; j++)
            {
                instructions.InsertRange(i, loopedInstructions);
                i += loopedInstructions.Count;
            }
            i--;
        }
        return(instruction);
    }
Пример #4
0
        internal Instruction ReadInstruction()
        {
            OpCodes     opcode = (OpCodes)this.ReadByte();
            Instruction result = Instruction.FixedOpCodes[(int)opcode];

            if (null != result)
            {
                return(result);
            }
            switch (opcode)
            {
            case OpCodes.Block:
                return(BlockInstruction.Create(this));

            case OpCodes.Loop:
                return(LoopInstruction.Create(this));

            case OpCodes.If:
                // block_type
                return(IfInstruction.Create(this));

            case OpCodes.Br:
            case OpCodes.BrIf:
                // varuint32
                return(BranchInstruction.Create(this, opcode));

            case OpCodes.BrTable:
                // custom
                return(BranchTableInstruction.Create(this));

            case OpCodes.Call:
            case OpCodes.CallIndirect:
                // varuint32 + varuint1
                return(CallInstruction.Create(this, opcode));

            case OpCodes.GetLocal:
            case OpCodes.SetLocal:
            case OpCodes.TeeLocal:
                // local_index
                return(LocalAccessorInstruction.Create(this, opcode));

            case OpCodes.GetGlobal:
            case OpCodes.SetGlobal:
                // global_index
                return(GlobalAccessorInstruction.Create(this, (OpCodes.GetGlobal == opcode)));

            case OpCodes.I32Load:
            case OpCodes.I64Load:
            case OpCodes.F32Load:
            case OpCodes.F64Load:
            case OpCodes.I32Load8_s:
            case OpCodes.I32Load8_u:
            case OpCodes.I32Load16_s:
            case OpCodes.I32Load16_u:
            case OpCodes.I64Load8_s:
            case OpCodes.I64Load8_u:
            case OpCodes.I64Load16_s:
            case OpCodes.I64Load16_u:
            case OpCodes.I64Load32_s:
            case OpCodes.I64Load32_u:
            case OpCodes.I32Store:
            case OpCodes.I64Store:
            case OpCodes.F32Store:
            case OpCodes.F64Store:
            case OpCodes.I32Store8:
            case OpCodes.I32Store16:
            case OpCodes.I64Store8:
            case OpCodes.I64Store16:
            case OpCodes.I64Store32:
                // memory_immediate
                return(MemoryAccessInstruction.Create(this, opcode));

            case OpCodes.CurrentMemory:
            case OpCodes.GrowMemory:
                // varuint1
                return(MemoryControlInstruction.Create(this, opcode));

            case OpCodes.I32Const:
                // varint32
                return(ConstantValueInstruction <int> .Create(this, OpCodes.I32Const, this.ReadVarInt32()));

            case OpCodes.I64Const:
                // varint64
                return(ConstantValueInstruction <long> .Create(this, OpCodes.I64Const, this.ReadVarInt64()));

            case OpCodes.F32Const:
                // uint32
                return(ConstantValueInstruction <float> .Create(this, OpCodes.F32Const, this.ReadVarFloat32()));

            case OpCodes.F64Const:
                // uint64
                return(ConstantValueInstruction <double> .Create(this, OpCodes.F64Const, this.ReadVarFloat64()));

            case OpCodes.F32eq:
            case OpCodes.F32ge:
            case OpCodes.F32gt:
            case OpCodes.F32le:
            case OpCodes.F32lt:
            case OpCodes.F32ne:
            case OpCodes.F64eq:
            case OpCodes.F64ge:
            case OpCodes.F64gt:
            case OpCodes.F64le:
            case OpCodes.F64lt:
            case OpCodes.F64ne:
            case OpCodes.I32eq:
            case OpCodes.I32ge_s:
            case OpCodes.I32ge_u:
            case OpCodes.I32gt_s:
            case OpCodes.I32gt_u:
            case OpCodes.I32le_s:
            case OpCodes.I32le_u:
            case OpCodes.I32lt_s:
            case OpCodes.I32lt_u:
            case OpCodes.I32ne:
            case OpCodes.I64eq:
            case OpCodes.I64ge_s:
            case OpCodes.I64ge_u:
            case OpCodes.I64gt_s:
            case OpCodes.I64gt_u:
            case OpCodes.I64le_s:
            case OpCodes.I64le_u:
            case OpCodes.I64lt_s:
            case OpCodes.I64lt_u:
            case OpCodes.I64ne:
                return(RelationalInstruction.GetInstruction(opcode));

            case OpCodes.F32Convert_sI32:
            case OpCodes.F32Convert_uI32:
            case OpCodes.F32Convert_sI64:
            case OpCodes.F32Convert_uI64:
            case OpCodes.F32demoteF64:
            case OpCodes.F64Convert_sI32:
            case OpCodes.F64Convert_uI32:
            case OpCodes.F64Convert_sI64:
            case OpCodes.F64Convert_uI64:
            case OpCodes.F64PromoteF32:
            case OpCodes.I32Trunc_sF32:
            case OpCodes.I32Trunc_uF32:
            case OpCodes.I32Trunc_sF64:
            case OpCodes.I32Trunc_uF64:
            case OpCodes.I32wrapI64:
            case OpCodes.I64Extend_sI32:
            case OpCodes.I64Extend_uI32:
            case OpCodes.I64Trunc_sF32:
            case OpCodes.I64Trunc_uF32:
            case OpCodes.I64Trunc_sF64:
            case OpCodes.I64Trunc_uF64:
                return(ConversionInstruction.GetInstruction(opcode));

            default:
                throw new NotSupportedException();
            }
        }
Пример #5
0
 private string TryReduceJump(BasicBlock root, JumpBasicBlock jumpbb)
 {
     // Try to find a linear chain of branches of length > 1
     var group = new Set<BasicBlock> { jumpbb };
     var chain = new Seq<BasicBlock> { jumpbb };
     var start = jumpbb;
     while (start.Sources.Count == 1 && start.Sources[0] is JumpBasicBlock &&
            !group.Contains(start.Sources[0]))
     {
         // Extend chain upwards
         start = (JumpBasicBlock)start.Sources[0];
         group.Add(start);
         chain.Insert(0, start);
     }
     var endjump = jumpbb;
     while (endjump.Target.Sources.Count == 1 && endjump.Target is JumpBasicBlock && !group.Contains(endjump.Target))
     {
         // Extend chain downwards
         endjump = (JumpBasicBlock)endjump.Target;
         group.Add(endjump);
         chain.Add(endjump);
     }
     var end = (BasicBlock)endjump;
     if (endjump.Target.Sources.Count == 1 && endjump.Target.AcceptsInstructions && !group.Contains(endjump.Target))
     {
         // Extend chain downwards to include a final non jump basic block, provided we can put all
         // the accumulated instructions there
         end = endjump.Target;
         group.Add(end);
         chain.Add(end);
     }
     if (chain.Count > 1)
     {
         // Coalesce and peephole
         var instructions = new Seq<Instruction>();
         foreach (var bb in chain)
             bb.Block.AccumInstructions(instructions);
         var newbb = end.CloneWithInstructions(nextBlockId++, Peephole(chain[0].Block.BeforeState, instructions));
         root.Coalesce(start, group, newbb);
         return String.Format("collapsed chain of {0} jump blocks from B{1}", chain.Count, start.Id); 
     }
     else if (start.Block.Count == 0 && !start.Target.Equals(start))
     {
         // Short-circuit a trivial jump
         root.Delete(start);
         return String.Format("short-circuited trivial jump at B{0}", start.Id);
     }
     else if (start.Target.Equals(start))
     {
         // loop
         var li = new LoopInstruction(NextInstructionId--, start.Block)
                   { BeforeState = jumpbb.Block.BeforeState, AfterState = jumpbb.Block.AfterState };
         var newbb = new NonReturningBasicBlock(nextBlockId++, new Instructions(li));
         root.Coalesce(start, new Set<BasicBlock> { start }, newbb);
         return String.Format("trival loop at B{0}", start.Id);
     }
     else
         return null;
 }