コード例 #1
0
ファイル: ZCompiler.cs プロジェクト: taradinoc/ZDebug
        private static void OptimizeReuseStoreVariable(OpcodeGenerator generator, OpcodeGenerator nextGenerator)
        {
            Debug.Assert(generator.Instruction.HasStoreVariable);

            if (nextGenerator.CanReuseFirstOperand || nextGenerator.CanReuseSecondOperand)
            {
                if (nextGenerator.CanReuseFirstOperand)
                {
                    Debug.Assert(nextGenerator.Instruction.OperandCount > 0);

                    var firstOperand = nextGenerator.Instruction.Operands[0];
                    if (firstOperand.IsVariable)
                    {
                        if (firstOperand.Value == generator.Instruction.StoreVariable.ToByte())
                        {
                            Debug.WriteLine("{0:x4}: Optimizing {1} between {2} and {3}",
                                            generator.Instruction.Address,
                                            generator.Instruction.StoreVariable,
                                            generator.Instruction.Opcode.Name,
                                            nextGenerator.Instruction.Opcode.Name);

                            generator.ReuseStoreVariable    = true;
                            nextGenerator.ReuseFirstOperand = true;
                        }
                    }
                }

                if (nextGenerator.CanReuseSecondOperand && !nextGenerator.ReuseFirstOperand)
                {
                    Debug.Assert(nextGenerator.Instruction.OperandCount > 1);

                    var secondOperand = nextGenerator.Instruction.Operands[1];
                    if (secondOperand.IsVariable)
                    {
                        if (secondOperand.Value == generator.Instruction.StoreVariable.ToByte())
                        {
                            Debug.WriteLine("{0:x4}: Optimizing {1} between {2} and {3}",
                                            generator.Instruction.Address,
                                            generator.Instruction.StoreVariable,
                                            generator.Instruction.Opcode.Name,
                                            nextGenerator.Instruction.Opcode.Name);

                            generator.ReuseStoreVariable     = true;
                            nextGenerator.ReuseSecondOperand = true;
                        }
                    }
                }
            }
            else if (nextGenerator.CanReuseStack && generator.Instruction.StoreVariable.Kind == VariableKind.Stack)
            {
                Debug.WriteLine("{0:x4}: Optimizing {1} between {2} and {3}",
                                generator.Instruction.Address,
                                generator.Instruction.StoreVariable,
                                generator.Instruction.Opcode.Name,
                                nextGenerator.Instruction.Opcode.Name);

                generator.ReuseStoreVariable = true;
                nextGenerator.ReuseStack     = true;
            }
        }
コード例 #2
0
ファイル: ZCompiler.cs プロジェクト: taradinoc/ZDebug
        private static void OptimizeStoreVariableSign(OpcodeGenerator generator, OpcodeGenerator nextGenerator)
        {
            Debug.Assert(generator.Instruction.HasStoreVariable);

            if (nextGenerator.SignsOperands)
            {
                Debug.WriteLine("{0:x4}: Optimizing store variable sign between {1} and {2}",
                                generator.Instruction.Address,
                                generator.Instruction.Opcode.Name,
                                nextGenerator.Instruction.Opcode.Name);

                generator.LeaveStoreVariableSigned = true;
            }
        }
コード例 #3
0
ファイル: ZCompiler.cs プロジェクト: taradinoc/ZDebug
        public ZCompilerResult Compile()
        {
            var sw = Stopwatch.StartNew();

            var dm = CreateDynamicMethod(routine);

            this.il = new ILBuilder(dm.GetILGenerator());

            this.calls = new List <ZRoutineCall>();

            Profiler_EnterRoutine();

            this.controlFlowGraph  = ControlFlowGraph.Build(this.routine);
            this.addressToLabelMap = new Dictionary <int, ILabel>(this.controlFlowGraph.CodeBlocks.Count());

            // Determine whether stack, memory, screen and outputStreams are used.
            foreach (var codeBlock in this.controlFlowGraph.CodeBlocks)
            {
                this.addressToLabelMap.Add(codeBlock.Address, il.NewLabel());

                foreach (var i in codeBlock.Instructions)
                {
                    if (!this.usesStack && i.UsesStack())
                    {
                        this.usesStack = true;
                    }

                    if (!this.usesMemory && i.UsesMemory())
                    {
                        this.usesMemory = true;
                    }
                }
            }

            var instructionStatistics = new List <InstructionStatistics>(this.routine.Instructions.Length);

            // Emit IL
            foreach (var codeBlock in this.controlFlowGraph.CodeBlocks)
            {
                var generators = codeBlock.Instructions
                                 .Select(i => OpcodeGenerator.GetGenerator(i, machine.Version))
                                 .ToList();

                Optimize(generators);

                foreach (var generator in generators)
                {
                    ILabel label;
                    if (this.addressToLabelMap.TryGetValue(generator.Instruction.Address, out label))
                    {
                        label.Mark();
                    }

                    if (machine.Debugging)
                    {
                        il.Arguments.LoadMachine();
                        il.Call(Reflection <CompiledZMachine> .GetMethod("Tick", @public: false));
                    }

                    Profiler_ExecutingInstruction(generator.Instruction);
                    il.DebugWrite(generator.Instruction.PrettyPrint(machine));

                    var offset = il.Size;

                    generator.Generate(il, this);

                    instructionStatistics.Add(new InstructionStatistics(generator.Instruction, offset, il.Size - offset));
                }
            }

            var code = (ZRoutineCode)dm.CreateDelegate(typeof(ZRoutineCode), machine);

            sw.Stop();

            var statistics = new RoutineCompilationStatistics(
                this.routine,
                il.OpcodeCount,
                il.LocalCount,
                il.Size,
                sw.Elapsed,
                calculatedLoadVariableCount,
                calculatedStoreVariableCount,
                instructionStatistics);

            return(new ZCompilerResult(this.routine, calls.ToArray(), code, statistics));
        }
コード例 #4
0
ファイル: ZCompiler.cs プロジェクト: taradinoc/ZDebug
        private static void OptimizeReuseByRefOperand(OpcodeGenerator generator, OpcodeGenerator nextGenerator)
        {
            Debug.Assert(generator.Instruction.Opcode.IsFirstOpByRef);
            Debug.Assert(generator.Instruction.OperandCount > 0);

            var byRefOperand = generator.Instruction.Operands[0];

            if (byRefOperand.Kind == OperandKind.SmallConstant)
            {
                if (nextGenerator.CanReuseFirstOperand || nextGenerator.CanReuseSecondOperand)
                {
                    if (nextGenerator.CanReuseFirstOperand)
                    {
                        Debug.Assert(nextGenerator.Instruction.OperandCount > 0);

                        var firstOperand = nextGenerator.Instruction.Operands[0];
                        if (firstOperand.IsVariable)
                        {
                            if (firstOperand.Value == byRefOperand.Value)
                            {
                                Debug.WriteLine("{0:x4}: Optimizing {1} between {2} and {3}",
                                                generator.Instruction.Address,
                                                Variable.FromByte((byte)byRefOperand.Value),
                                                generator.Instruction.Opcode.Name,
                                                nextGenerator.Instruction.Opcode.Name);

                                generator.ReuseByRefOperand     = true;
                                nextGenerator.ReuseFirstOperand = true;
                            }
                        }
                    }

                    if (nextGenerator.CanReuseSecondOperand && !nextGenerator.ReuseFirstOperand)
                    {
                        Debug.Assert(nextGenerator.Instruction.OperandCount > 1);

                        var secondOperand = nextGenerator.Instruction.Operands[1];
                        if (secondOperand.IsVariable)
                        {
                            if (secondOperand.Value == byRefOperand.Value)
                            {
                                Debug.WriteLine("{0:x4}: Optimizing {1} between {2} and {3}",
                                                generator.Instruction.Address,
                                                Variable.FromByte((byte)byRefOperand.Value),
                                                generator.Instruction.Opcode.Name,
                                                nextGenerator.Instruction.Opcode.Name);

                                generator.ReuseByRefOperand      = true;
                                nextGenerator.ReuseSecondOperand = true;
                            }
                        }
                    }
                }
                else if (nextGenerator.CanReuseStack && byRefOperand.Value == 0)
                {
                    Debug.WriteLine("{0:x4}: Optimizing {1} between {2} and {3}",
                                    generator.Instruction.Address,
                                    Variable.FromByte((byte)byRefOperand.Value),
                                    generator.Instruction.Opcode.Name,
                                    nextGenerator.Instruction.Opcode.Name);

                    generator.ReuseByRefOperand = true;
                    nextGenerator.ReuseStack    = true;
                }
            }
        }