Esempio n. 1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MethodCompiler" /> class.
        /// </summary>
        /// <param name="compiler">The assembly compiler.</param>
        /// <param name="method">The method to compile by this instance.</param>
        /// <param name="basicBlocks">The basic blocks.</param>
        /// <param name="threadID">The thread identifier.</param>
        public MethodCompiler(Compiler compiler, MosaMethod method, BasicBlocks basicBlocks, int threadID)
        {
            Stopwatch = Stopwatch.StartNew();

            Compiler        = compiler;
            Method          = method;
            MethodScheduler = compiler.MethodScheduler;
            Architecture    = compiler.Architecture;
            TypeSystem      = compiler.TypeSystem;
            TypeLayout      = compiler.TypeLayout;
            Trace           = compiler.CompilerTrace;
            Linker          = compiler.Linker;
            MethodScanner   = compiler.MethodScanner;

            BasicBlocks      = basicBlocks ?? new BasicBlocks();
            LocalStack       = new List <Operand>();
            VirtualRegisters = new VirtualRegisters();

            Parameters = new Operand[method.Signature.Parameters.Count + (method.HasThis || method.HasExplicitThis ? 1 : 0)];

            ConstantZero32 = CreateConstant((uint)0);
            ConstantZero64 = CreateConstant((ulong)0);
            ConstantZeroR4 = CreateConstant(0.0f);
            ConstantZeroR8 = CreateConstant(0.0d);

            ConstantZero = Architecture.Is32BitPlatform ? ConstantZero32 : ConstantZero64;

            LocalVariables = emptyOperandList;
            ThreadID       = threadID;

            IsStopped            = false;
            IsExecutePipeline    = true;
            IsCILDecodeRequired  = true;
            IsStackFrameRequired = true;
            IsMethodInlined      = false;
            HasProtectedRegions  = Method.ExceptionHandlers.Count != 0;

            MethodData = Compiler.GetMethodData(Method);
            MethodData.Counters.Reset();

            MethodData.Version++;
            MethodData.IsMethodImplementationReplaced = IsMethodPlugged;

            if (Symbol == null)
            {
                Symbol            = Linker.DefineSymbol(Method.FullName, SectionKind.Text, 0, 0);
                Symbol.MethodData = MethodData;             // for debugging
                Symbol.MosaMethod = Method;                 // for debugging
            }
            else
            {
                Symbol.RemovePatches();
            }

            EvaluateParameterOperands();

            CalculateMethodParameterSize();

            MethodData.Counters.NewCountSkipLock("ExecutionTime.Setup.Ticks", (int)Stopwatch.ElapsedTicks);
        }
Esempio n. 2
0
        private MethodCompiler GetMethodCompiler(MosaMethod method, BasicBlocks basicBlocks, int threadID = 0)
        {
            var methodCompiler = new MethodCompiler(this, method, basicBlocks, threadID);

            var pipeline = methodStagePipelines[threadID];

            if (pipeline == null)
            {
                pipeline = new Pipeline <BaseMethodCompilerStage>();

                methodStagePipelines[threadID] = pipeline;

                pipeline.Add(GetDefaultMethodPipeline(CompilerOptions));

                foreach (var extension in CompilerExtensions)
                {
                    extension.ExtendMethodCompilerPipeline(pipeline);
                }

                Architecture.ExtendMethodCompilerPipeline(pipeline);

                foreach (var stage in pipeline)
                {
                    stage.Initialize(this);
                }
            }

            methodCompiler.Pipeline = pipeline;

            return(methodCompiler);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="BaseMethodCompiler" /> class.
        /// </summary>
        /// <param name="compiler">The assembly compiler.</param>
        /// <param name="method">The method to compile by this instance.</param>
        /// <param name="basicBlocks">The basic blocks.</param>
        /// <param name="threadID">The thread identifier.</param>
        protected BaseMethodCompiler(BaseCompiler compiler, MosaMethod method, BasicBlocks basicBlocks, int threadID)
        {
            Compiler     = compiler;
            Method       = method;
            Type         = method.DeclaringType;
            Scheduler    = compiler.CompilationScheduler;
            Architecture = compiler.Architecture;
            TypeSystem   = compiler.TypeSystem;
            TypeLayout   = compiler.TypeLayout;
            Trace        = compiler.CompilerTrace;
            Linker       = compiler.Linker;
            BasicBlocks  = basicBlocks ?? new BasicBlocks();
            Pipeline     = new CompilerPipeline();
            LocalStack   = new List <Operand>();

            ConstantZero     = Operand.CreateConstant(0, TypeSystem);
            StackFrame       = Operand.CreateCPURegister(TypeSystem.BuiltIn.Pointer, Architecture.StackFrameRegister);
            StackPointer     = Operand.CreateCPURegister(TypeSystem.BuiltIn.Pointer, Architecture.StackPointerRegister);
            Parameters       = new Operand[method.Signature.Parameters.Count + (method.HasThis || method.HasExplicitThis ? 1 : 0)];
            VirtualRegisters = new VirtualRegisters();
            LocalVariables   = emptyOperandList;
            ThreadID         = threadID;
            PluggedMethod    = compiler.PlugSystem.GetPlugMethod(Method);
            stop             = false;

            MethodData = compiler.CompilerData.GetCompilerMethodData(Method);
            MethodData.Counters.Clear();

            EvaluateParameterOperands();

            CalculateMethodParameterSize();
        }
Esempio n. 4
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MethodCompiler" /> class.
        /// </summary>
        /// <param name="compiler">The assembly compiler.</param>
        /// <param name="method">The method to compile by this instance.</param>
        /// <param name="basicBlocks">The basic blocks.</param>
        /// <param name="threadID">The thread identifier.</param>
        public MethodCompiler(Compiler compiler, MosaMethod method, BasicBlocks basicBlocks, int threadID)
        {
            Compiler     = compiler;
            Method       = method;
            Type         = method.DeclaringType;
            Scheduler    = compiler.CompilationScheduler;
            Architecture = compiler.Architecture;
            TypeSystem   = compiler.TypeSystem;
            TypeLayout   = compiler.TypeLayout;
            Trace        = compiler.CompilerTrace;
            Linker       = compiler.Linker;

            BasicBlocks      = basicBlocks ?? new BasicBlocks();
            LocalStack       = new List <Operand>();
            VirtualRegisters = new VirtualRegisters();

            StackFrame   = Operand.CreateCPURegister(TypeSystem.BuiltIn.Pointer, Architecture.StackFrameRegister);
            StackPointer = Operand.CreateCPURegister(TypeSystem.BuiltIn.Pointer, Architecture.StackPointerRegister);
            Parameters   = new Operand[method.Signature.Parameters.Count + (method.HasThis || method.HasExplicitThis ? 1 : 0)];
            ConstantZero = Architecture.Is32BitPlatform ? CreateConstant((uint)0) : CreateConstant((ulong)0);

            LocalVariables = emptyOperandList;
            ThreadID       = threadID;
            PluggedMethod  = compiler.PlugSystem.GetReplacement(Method);

            IsStopped   = false;
            IsInSSAForm = false;

            MethodData = compiler.CompilerData.GetCompilerMethodData(Method);
            MethodData.Counters.Reset();

            EvaluateParameterOperands();

            CalculateMethodParameterSize();
        }
Esempio n. 5
0
        private void PlugMethod()
        {
            var plugMethod = Compiler.PlugSystem.GetReplacement(Method);

            if (plugMethod == null)
            {
                return;
            }

            Compiler.MethodScanner.MethodInvoked(plugMethod, Method);

            IsMethodPlugged = true;

            Debug.Assert(plugMethod != null);

            var plugSymbol = Operand.CreateSymbolFromMethod(plugMethod, TypeSystem);

            var block = BasicBlocks.CreateBlock(BasicBlock.PrologueLabel);

            BasicBlocks.AddHeadBlock(block);

            var ctx = new Context(block);

            ctx.AppendInstruction(IRInstruction.Jmp, null, plugSymbol);

            IsCILDecodeRequired  = false;
            IsExecutePipeline    = true;
            IsStackFrameRequired = false;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="BaseMethodCompiler" /> class.
        /// </summary>
        /// <param name="compiler">The assembly compiler.</param>
        /// <param name="method">The method to compile by this instance.</param>
        /// <param name="basicBlocks">The basic blocks.</param>
        /// <param name="threadID">The thread identifier.</param>
        protected BaseMethodCompiler(BaseCompiler compiler, MosaMethod method, BasicBlocks basicBlocks, int threadID)
        {
            Compiler          = compiler;
            Method            = method;
            Type              = method.DeclaringType;
            Scheduler         = compiler.CompilationScheduler;
            Architecture      = compiler.Architecture;
            TypeSystem        = compiler.TypeSystem;
            TypeLayout        = compiler.TypeLayout;
            Trace             = compiler.CompilerTrace;
            Linker            = compiler.Linker;
            BasicBlocks       = basicBlocks ?? new BasicBlocks();
            Pipeline          = new CompilerPipeline();
            StackLayout       = new StackLayout(Architecture, method.Signature.Parameters.Count + (method.HasThis || method.HasExplicitThis ? 1 : 0));
            VirtualRegisters  = new VirtualRegisters(Architecture);
            LocalVariables    = emptyOperandList;
            ThreadID          = threadID;
            DominanceAnalysis = new Dominance(Compiler.CompilerOptions.DominanceAnalysisFactory, BasicBlocks);
            PluggedMethod     = compiler.PlugSystem.GetPlugMethod(Method);
            stop              = false;

            MethodData = compiler.CompilerData.GetCompilerMethodData(Method);
            MethodData.Counters.Clear();

            EvaluateParameterOperands();
        }
Esempio n. 7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="BaseMethodCompiler" /> class.
        /// </summary>
        /// <param name="compiler">The assembly compiler.</param>
        /// <param name="method">The method to compile by this instance.</param>
        /// <param name="basicBlocks">The basic blocks.</param>
        /// <param name="threadID">The thread identifier.</param>
        protected BaseMethodCompiler(BaseCompiler compiler, MosaMethod method, BasicBlocks basicBlocks, int threadID)
        {
            this.Compiler          = compiler;
            this.Method            = method;
            this.Type              = method.DeclaringType;
            this.Scheduler         = compiler.CompilationScheduler;
            this.Architecture      = compiler.Architecture;
            this.TypeSystem        = compiler.TypeSystem;
            this.TypeLayout        = Compiler.TypeLayout;
            this.Trace             = Compiler.CompilerTrace;
            this.Linker            = compiler.Linker;
            this.BasicBlocks       = basicBlocks ?? new BasicBlocks();
            this.Pipeline          = new CompilerPipeline();
            this.StackLayout       = new StackLayout(Architecture, method.Signature.Parameters.Count + (method.HasThis || method.HasExplicitThis ? 1 : 0));
            this.VirtualRegisters  = new VirtualRegisters(Architecture);
            this.LocalVariables    = emptyOperandList;
            this.ThreadID          = threadID;
            this.DominanceAnalysis = new Dominance(Compiler.CompilerOptions.DominanceAnalysisFactory, this.BasicBlocks);

            EvaluateParameterOperands();

            this.stop = false;

            Debug.Assert(this.Linker != null);
        }
Esempio n. 8
0
        /// <summary>
        /// Compiles the method.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <param name="basicBlocks">The basic blocks.</param>
        /// <param name="threadID">The thread identifier.</param>
        public void CompileMethod(MosaMethod method, BasicBlocks basicBlocks, int threadID = 0)
        {
            NewCompilerTraceEvent(CompilerEvent.CompilingMethod, method.FullName, threadID);

            var methodCompiler = CreateMethodCompiler(method, basicBlocks, threadID);

            Architecture.ExtendMethodCompilerPipeline(methodCompiler.Pipeline);

            methodCompiler.Compile();
        }
Esempio n. 9
0
        /// <summary>
        /// Compiles the method.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <param name="basicBlocks">The basic blocks.</param>
        /// <param name="threadID">The thread identifier.</param>
        public void CompileMethod(MosaMethod method, BasicBlocks basicBlocks, int threadID = 0)
        {
            NewCompilerTraceEvent(CompilerEvent.CompilingMethod, method.FullName, threadID);

            var methodCompiler = GetMethodCompiler(method, basicBlocks, threadID);

            methodCompiler.Compile();

            NewCompilerTraceEvent(CompilerEvent.CompiledMethod, method.FullName, threadID);
            CompilerTrace.TraceListener.OnMethodcompiled(method);
        }
Esempio n. 10
0
        public InlineMethodData SwapInlineMethodData(BasicBlocks basicBlocks)
        {
            lock (_lock)
            {
                var tmp = InlineMethodData;

                InlineMethodData = new InlineMethodData(basicBlocks, Version);

                return(tmp);
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MethodCompiler" /> class.
        /// </summary>
        /// <param name="compiler">The assembly compiler.</param>
        /// <param name="method">The method to compile by this instance.</param>
        /// <param name="basicBlocks">The basic blocks.</param>
        /// <param name="threadID">The thread identifier.</param>
        public MethodCompiler(Compiler compiler, MosaMethod method, BasicBlocks basicBlocks, int threadID)
        {
            Stopwatch = Stopwatch.StartNew();

            Compiler        = compiler;
            Method          = method;
            MethodScheduler = compiler.MethodScheduler;
            Architecture    = compiler.Architecture;
            TypeSystem      = compiler.TypeSystem;
            TypeLayout      = compiler.TypeLayout;
            Trace           = compiler.CompilerTrace;
            Linker          = compiler.Linker;
            MethodScanner   = compiler.MethodScanner;

            BasicBlocks      = basicBlocks ?? new BasicBlocks();
            LocalStack       = new List <Operand>();
            VirtualRegisters = new VirtualRegisters();

            StackFrame   = Operand.CreateCPURegister(TypeSystem.BuiltIn.Pointer, Architecture.StackFrameRegister);
            StackPointer = Operand.CreateCPURegister(TypeSystem.BuiltIn.Pointer, Architecture.StackPointerRegister);
            Parameters   = new Operand[method.Signature.Parameters.Count + (method.HasThis || method.HasExplicitThis ? 1 : 0)];

            ConstantZero32 = CreateConstant((uint)0);
            ConstantZero64 = CreateConstant((ulong)0);
            ConstantZero   = Architecture.Is32BitPlatform ? ConstantZero32 : ConstantZero64;

            LocalVariables = emptyOperandList;
            ThreadID       = threadID;

            IsStopped            = false;
            IsExecutePipeline    = true;
            IsCILDecodeRequired  = true;
            IsStackFrameRequired = true;
            IsMethodInlined      = false;

            MethodData = compiler.CompilerData.GetMethodData(Method);

            MethodData.Counters.Reset();

            // Both defines the symbol and also clears the data
            Symbol = Linker.DefineSymbol(Method.FullName, SectionKind.Text, 0, 0);

            EvaluateParameterOperands();

            CalculateMethodParameterSize();

            MethodData.Counters.NewCountSkipLock("ExecutionTime.Setup.Ticks", (int)Stopwatch.ElapsedTicks);
        }
Esempio n. 12
0
        /// <summary>
        /// Compiles the method.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <param name="basicBlocks">The basic blocks.</param>
        /// <param name="threadID">The thread identifier.</param>
        public void CompileMethod(MosaMethod method, BasicBlocks basicBlocks, int threadID = 0)
        {
            PostCompilerTraceEvent(CompilerEvent.CompilingMethod, method.FullName, threadID);

            var pipeline = GetOrCreateMethodStagePipeline(threadID);

            var methodCompiler = new MethodCompiler(this, method, basicBlocks, threadID)
            {
                Pipeline = pipeline
            };

            methodCompiler.Compile();

            PostCompilerTraceEvent(CompilerEvent.CompiledMethod, method.FullName, threadID);

            CompilerTrace.PostMethodCompiled(method);
        }
Esempio n. 13
0
        /// <summary>
        /// Compiles the method.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <param name="basicBlocks">The basic blocks.</param>
        /// <param name="threadID">The thread identifier.</param>
        public void CompileMethod(MosaMethod method, BasicBlocks basicBlocks, int threadID = 0)
        {
            PostEvent(CompilerEvent.MethodCompileStart, method.FullName, threadID);

            var pipeline = GetOrCreateMethodStagePipeline(threadID);

            var methodCompiler = new MethodCompiler(this, method, basicBlocks, threadID)
            {
                Pipeline = pipeline
            };

            methodCompiler.Compile();

            PostEvent(CompilerEvent.MethodCompileEnd, method.FullName, threadID);

            CompilerHooks.NotifyMethodCompiled?.Invoke(method);
        }
Esempio n. 14
0
        private void StubMethod()
        {
            var intrinsicAttribute = Method.FindCustomAttribute("System.Runtime.CompilerServices.IntrinsicAttribute");

            if (intrinsicAttribute == null)
            {
                return;
            }

            var methodName = $"{Method.DeclaringType.Namespace}.{Method.DeclaringType.Name}::{Method.Name}";
            var stub       = Compiler.GetStubMethod(methodName);

            if (stub == null)
            {
                return;
            }

            IsCILStream       = false;
            IsExecutePipeline = true;

            // Create the prologue block
            var prologue = BasicBlocks.CreateBlock(BasicBlock.PrologueLabel);

            BasicBlocks.AddHeadBlock(prologue);

            // Create the epilogue block
            var epilogue = BasicBlocks.CreateBlock(BasicBlock.EpilogueLabel);

            var start = BasicBlocks.CreateBlock(BasicBlock.StartLabel);

            // Add a jump instruction to the first block from the prologue
            prologue.First.Insert(new InstructionNode(IRInstruction.Jmp, start));

            stub(new Context(start), this);

            if (NotifyInstructionTraceHandler != null)
            {
                var traceLog = new TraceLog(TraceType.MethodInstructions, Method, "XX-Stubbed Method", MethodData.Version);
                traceLog?.Log($"This method is a stubbed method");
                NotifyInstructionTraceHandler.Invoke(traceLog);
            }
        }
 /// <summary>
 /// Create an empty block.
 /// </summary>
 /// <returns></returns>
 protected BasicBlock CreateNewBlock()
 {
     return(BasicBlocks.CreateBlock());
 }
Esempio n. 16
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MethodCompiler" /> class.
        /// </summary>
        /// <param name="compiler">The assembly compiler.</param>
        /// <param name="method">The method to compile by this instance.</param>
        /// <param name="basicBlocks">The basic blocks.</param>
        /// <param name="threadID">The thread identifier.</param>
        public MethodCompiler(Compiler compiler, MosaMethod method, BasicBlocks basicBlocks, int threadID)
        {
            Stopwatch = Stopwatch.StartNew();

            Compiler        = compiler;
            Method          = method;
            MethodScheduler = compiler.MethodScheduler;
            Architecture    = compiler.Architecture;
            TypeSystem      = compiler.TypeSystem;
            TypeLayout      = compiler.TypeLayout;
            Linker          = compiler.Linker;
            MethodScanner   = compiler.MethodScanner;
            CompilerHooks   = compiler.CompilerHooks;

            NotifyTraceLogHandler = GetMethodInstructionTraceHandler();
            Statistics            = compiler.Statistics;
            IsInSSAForm           = false;

            BasicBlocks      = basicBlocks ?? new BasicBlocks();
            LocalStack       = new List <Operand>();
            VirtualRegisters = new VirtualRegisters();

            Parameters = new Operand[method.Signature.Parameters.Count + (method.HasThis || method.HasExplicitThis ? 1 : 0)];

            ConstantZero32 = CreateConstant((uint)0);
            ConstantZero64 = CreateConstant((ulong)0);
            ConstantZeroR4 = CreateConstant(0.0f);
            ConstantZeroR8 = CreateConstant(0.0d);

            ConstantZero = Architecture.Is32BitPlatform ? ConstantZero32 : ConstantZero64;              // FUTURE: This could just be Constant64 or Constant32 once the caling stage uses the method signature intead of the operand types

            LocalVariables = emptyOperandList;
            ThreadID       = threadID;

            IsStopped           = false;
            IsExecutePipeline   = true;
            IsMethodInlined     = false;
            IsCILStream         = !Method.IsCompilerGenerated;
            HasProtectedRegions = Method.ExceptionHandlers.Count != 0;

            MethodData = Compiler.GetMethodData(Method);

            MethodData.Counters.Reset();
            MethodData.HasCode = false;
            MethodData.Version++;
            MethodData.IsMethodImplementationReplaced = IsMethodPlugged;

            IsStackFrameRequired = MethodData.StackFrameRequired;

            if (Symbol == null)
            {
                Symbol            = Linker.DefineSymbol(Method.FullName, SectionKind.Text, 0, 0);
                Symbol.MethodData = MethodData;             // for debugging
                Symbol.MosaMethod = Method;                 // for debugging
            }
            else
            {
                Symbol.RemovePatches();
            }

            var methodInfo = TypeLayout.__GetMethodInfo(Method);

            MethodData.ParameterSizes     = methodInfo.ParameterSizes;
            MethodData.ParameterOffsets   = methodInfo.ParameterOffsets;
            MethodData.ParameterStackSize = methodInfo.ParameterStackSize;
            MethodData.ReturnSize         = methodInfo.ReturnSize;
            MethodData.ReturnInRegister   = methodInfo.ReturnInRegister;

            EvaluateParameterOperands();

            MethodData.Counters.NewCountSkipLock("ExecutionTime.Setup.Ticks", (int)Stopwatch.ElapsedTicks);
        }
Esempio n. 17
0
 public InlineMethodData(BasicBlocks basicBlocks, int version)
 {
     References  = new HashSet <MosaMethod>();
     BasicBlocks = basicBlocks;
     Version     = version;
 }
 /// <summary>
 /// Create an empty block.
 /// </summary>
 /// <param name="blockLabel">The label.</param>
 /// <returns></returns>
 protected BasicBlock CreateNewBlock(int blockLabel)
 {
     return(BasicBlocks.CreateBlock(blockLabel));
 }
 /// <summary>
 /// Creates the new block.
 /// </summary>
 /// <param name="blockLabel">The label.</param>
 /// <param name="instructionLabel">The instruction label.</param>
 /// <returns></returns>
 protected BasicBlock CreateNewBlock(int blockLabel, int instructionLabel)
 {
     return(BasicBlocks.CreateBlock(blockLabel, instructionLabel));
 }
Esempio n. 20
0
 /// <summary>
 /// Creates a method compiler
 /// </summary>
 /// <param name="method">The method to compile.</param>
 /// <param name="basicBlocks">The basic blocks.</param>
 /// <param name="threadID">The thread identifier.</param>
 /// <returns></returns>
 protected abstract BaseMethodCompiler CreateMethodCompiler(MosaMethod method, BasicBlocks basicBlocks, int threadID = 0);