protected void CompileMethod(string source, INamingConventionResolver namingConvention = null, IRuntimeLibrary runtimeLibrary = null, IErrorReporter errorReporter = null, string methodName = "M", bool addSkeleton = true, bool referenceSystemCore = false)
        {
            Compile(new[] { addSkeleton ? "using System; class C { " + source + "}" : source }, namingConvention, runtimeLibrary, errorReporter, (m, res, mc) => {
                if (m.Name == methodName) {
                    Method = m;
                    MethodCompiler = mc;
                    CompiledMethod = res;
                }
            }, referenceSystemCore: referenceSystemCore);

            Assert.That(Method, Is.Not.Null, "Method " + methodName + " was not compiled");
        }
        protected void CompileMethod(string source, IMetadataImporter metadataImporter = null, INamer namer = null, IRuntimeLibrary runtimeLibrary = null, IErrorReporter errorReporter = null, string methodName = "M", bool addSkeleton = true, bool referenceSystemCore = false, bool allowUserDefinedStructs = false)
        {
            Compile(new[] { addSkeleton ? "using System; class C { " + source + "}" : source }, metadataImporter: metadataImporter, namer: namer, runtimeLibrary: runtimeLibrary, errorReporter: errorReporter, methodCompiled: (m, res, mc) => {
                if (m.Name == methodName) {
                    Method = m;
                    MethodCompiler = mc;
                    CompiledMethod = res;
                }
            }, referenceSystemCore: referenceSystemCore, allowUserDefinedStructs: allowUserDefinedStructs);

            Assert.That(Method, Is.Not.Null, "Method " + methodName + " was not compiled");
        }
예제 #3
0
        public static void OrderLoadOperands(InstructionNode node, MethodCompiler methodCompiler)
        {
            if (node.Operand1.IsResolvedConstant && node.Operand2.IsResolvedConstant)
            {
                node.Operand1 = methodCompiler.CreateConstant(node.Operand1.ConstantUnsignedLongInteger + node.Operand2.ConstantUnsignedLongInteger);
                node.Operand2 = methodCompiler.ConstantZero;
            }

            if (node.Operand1.IsConstant && !node.Operand2.IsConstant)
            {
                var operand1 = node.Operand1;
                var operand2 = node.Operand2;

                node.Operand2 = operand1;
                node.Operand1 = operand2;
            }
        }
예제 #4
0
        public static void OrderStoreOperands(Context context, MethodCompiler methodCompiler)
        {
            if (context.Operand1.IsResolvedConstant && context.Operand2.IsResolvedConstant)
            {
                context.Operand1 = methodCompiler.CreateConstant(context.Operand1.ConstantUnsignedLongInteger + context.Operand2.ConstantUnsignedLongInteger);
                context.Operand2 = methodCompiler.ConstantZero;
            }

            if (context.Operand1.IsConstant && !context.Operand2.IsConstant)
            {
                var operand1 = context.Operand1;
                var operand2 = context.Operand2;

                context.Operand2 = operand1;
                context.Operand1 = operand2;
            }
        }
예제 #5
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        /// <exception cref="CompilerException"></exception>
        void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler)
        {
            if (context.OperandCount == 2)
            {
                context.SetInstruction(IRInstruction.StoreInt64, null, context.Operand1, methodCompiler.ConstantZero, context.Operand2);
            }
            else if (context.OperandCount == 3)
            {
                context.SetInstruction(IRInstruction.StoreInt64, null, context.Operand1, context.Operand2, context.Operand3);
            }
            else
            {
                throw new CompilerException();
            }

            LoadStore.OrderStoreOperands(context.Node, methodCompiler);
        }
예제 #6
0
        private static void Load64(Context context, MethodCompiler methodCompiler)
        {
            if (context.OperandCount == 1)
            {
                context.SetInstruction(IRInstruction.LoadInt64, context.Result, context.Operand1, methodCompiler.ConstantZero);
            }
            else if (context.OperandCount == 2)
            {
                context.SetInstruction(IRInstruction.LoadInt64, context.Result, context.Operand1, context.Operand2);
            }
            else
            {
                throw new CompilerException();
            }

            LoadStore.OrderLoadOperands(context.Node, methodCompiler);
        }
예제 #7
0
        private static void Store32(Context context, MethodCompiler methodCompiler)
        {
            if (context.OperandCount == 2)
            {
                context.SetInstruction(IRInstruction.StoreInt32, null, context.Operand1, methodCompiler.ConstantZero, context.Operand2);
            }
            else if (context.OperandCount == 3)
            {
                context.SetInstruction(IRInstruction.StoreInt32, null, context.Operand1, context.Operand2, context.Operand3);
            }
            else
            {
                throw new CompilerException();
            }

            LoadStore.OrderStoreOperands(context.Node, methodCompiler);
        }
        void IIRVisitor.CompoundStore(Context context)
        {
            var type            = context.Operand3.Type;
            int typeSize        = TypeLayout.GetTypeSize(type);
            int alignedTypeSize = typeSize - (typeSize % NativeAlignment);

            Debug.Assert(typeSize > 0, MethodCompiler.Method.FullName);

            int offset = 0;

            if (context.Operand2.IsConstant)
            {
                offset = (int)context.Operand2.ConstantSignedLongInteger;
            }

            var offsetop = context.Operand2;
            var src      = context.Operand3;
            var dest     = context.Operand1;

            Debug.Assert(src.IsMemoryAddress);

            var srcReg = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4);
            var dstReg = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4);
            var tmp    = MethodCompiler.CreateVirtualRegister(dest.Type.TypeSystem.BuiltIn.I4);

            context.SetInstruction(X86.Nop);
            context.AppendInstruction(X86.Lea, srcReg, src);
            context.AppendInstruction(X86.Mov, dstReg, dest);

            if (!offsetop.IsConstant)
            {
                context.AppendInstruction(X86.Add, dstReg, dstReg, offsetop);
            }

            for (int i = 0; i < alignedTypeSize; i += NativeAlignment)
            {
                context.AppendInstruction(X86.Mov, InstructionSize.Size32, tmp, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, srcReg, i));
                context.AppendInstruction(X86.Mov, InstructionSize.Size32, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, dstReg, i + offset), tmp);
            }
            for (int i = alignedTypeSize; i < typeSize; i++)
            {
                context.AppendInstruction(X86.Mov, InstructionSize.Size8, tmp, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, srcReg, i));
                context.AppendInstruction(X86.Mov, InstructionSize.Size8, Operand.CreateMemoryAddress(TypeSystem.BuiltIn.I4, dstReg, i + offset), tmp);
            }
        }
예제 #9
0
        private void LoadParam64(Context context)
        {
            Debug.Assert(!context.Result.IsR4);
            Debug.Assert(!context.Result.IsR8);
            Debug.Assert(context.Result.Is64BitInteger);

            var result   = context.Result;
            var operand1 = context.Operand1;

            var resultLow  = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
            var resultHigh = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);

            MethodCompiler.SplitLongOperand(operand1, out Operand op1Low, out Operand op1High);

            context.SetInstruction(IRInstruction.LoadParam32, resultLow, op1Low);
            context.AppendInstruction(IRInstruction.LoadParam32, resultHigh, op1High);
            context.AppendInstruction(IRInstruction.To64, result, resultLow, resultHigh);
        }
예제 #10
0
        private void LoadParamSignExtend8x64(Context context)
        {
            Debug.Assert(!context.Result.IsR4);
            Debug.Assert(!context.Result.IsR8);
            Debug.Assert(context.Result.Is64BitInteger);

            var result   = context.Result;
            var operand1 = context.Operand1;

            MethodCompiler.SplitLongOperand(operand1, out Operand op0Low, out Operand _);

            var resultLow  = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);
            var resultHigh = AllocateVirtualRegister(TypeSystem.BuiltIn.I4);

            context.SetInstruction(IRInstruction.LoadParamSignExtend8x32, resultLow, op0Low);
            context.AppendInstruction(IRInstruction.ArithShiftRight32, resultHigh, resultLow, CreateConstant((byte)31));
            context.AppendInstruction(IRInstruction.To64, result, resultLow, resultHigh);
        }
예제 #11
0
        public static void Unsafe_SizeOf(Context context, MethodCompiler methodCompiler)
        {
            var type     = methodCompiler.Method.GenericArguments[0];
            var size     = methodCompiler.TypeLayout.GetTypeSize(type);
            var opReturn = methodCompiler.AllocateVirtualRegisterOrStackSlot(methodCompiler.Method.Signature.ReturnType);

            // Move constant into return operand
            var move = methodCompiler.Is32BitPlatform ? (BaseInstruction)IRInstruction.Move32 : IRInstruction.Move64;

            context.AppendInstruction(move, opReturn, methodCompiler.CreateConstant(size));

            // Set return
            var setReturn = BaseMethodCompilerStage.GetSetReturnInstruction(opReturn.Type, methodCompiler.Is32BitPlatform);

            context.AppendInstruction(setReturn, null, opReturn);

            context.AppendInstruction(IRInstruction.Jmp, methodCompiler.BasicBlocks.EpilogueBlock);
        }
예제 #12
0
        private IntPtr CreateMethodStub(MethodCompiler methodCompiler)
        {
            if (methodCompiler == null)
                throw new ArgumentNullException("methodCompiler");

            _unmanagedDelegates.Add(methodCompiler);
            IntPtr methodPtr = Marshal.GetFunctionPointerForDelegate(methodCompiler);

            Assembler assembler = new Assembler();
            Label label = assembler.DefineLabel();
            assembler.Call(label);
            assembler.MarkLabel(label);
            assembler.Sub(Mem.sysint_ptr(Register.nsp), 5);
            assembler.Call(methodPtr);
            assembler.Add(Register.nsp, IntPtr.Size);
            assembler.Jmp(Register.nax);
            return assembler.Make();
        }
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="compiler">The compiler.</param>
        public override void Resolve(Context context, MethodCompiler compiler)
        {
            base.Resolve(context, compiler);

            // Make sure the base is a typed reference
            throw new NotImplementCompilerException();

            /*
             *      if (!Object.ReferenceEquals(_operands[0].Type, MetadataTypeReference.FromName(compiler.Assembly.Metadata, @"System", @"TypedReference")))
             *      {
             *              Debug.Assert(false);
             *              throw new InvalidProgramException(@"Invalid stack object.");
             *      }
             *
             *      // Push the loaded value
             *      _results[0] = CreateResultOperand(_typeRef);
             */
        }
예제 #14
0
        private static void LoadPointer(Context context, MethodCompiler methodCompiler)
        {
            var instruction = methodCompiler.Is32BitPlatform ? (BaseInstruction)IRInstruction.Load32 : IRInstruction.LoadZeroExtend32x64;

            if (context.OperandCount == 1)
            {
                context.SetInstruction(instruction, context.Result, context.Operand1, methodCompiler.ConstantZero);
            }
            else if (context.OperandCount == 2)
            {
                context.SetInstruction(instruction, context.Result, context.Operand1, context.Operand2);
            }
            else
            {
                throw new CompilerException();
            }

            LoadStore.OrderOperands(context, methodCompiler);
        }
예제 #15
0
        internal static BoundStatement ParseAndBindMethodBody(string program, bool lower, string typeName = DefaultTypeName, string methodName = DefaultMethodName)
        {
            var compilation = CreateCompilationWithMscorlib(program);
            var method      = (MethodSymbol)compilation.GlobalNamespace.GetTypeMembers(typeName).Single().GetMembers(methodName).Single();
            var diagnostics = DiagnosticBag.GetInstance();

            try
            {
                // Provide an Emit.Module so that the lowering passes will be run
                var module = new PEAssemblyBuilder(
                    (SourceAssemblySymbol)compilation.Assembly,
                    null,
                    OutputKind.ConsoleApplication,
                    GetDefaultModulePropertiesForSerialization(),
                    Enumerable.Empty <ResourceDescription>(),
                    assemblySymbolMapper: null);

                TypeCompilationState compilationState = new TypeCompilationState(method.ContainingType, compilation, module);

                var block = MethodCompiler.BindMethodBody(method, compilationState, diagnostics);
                if ((block == null) || !lower)
                {
                    return(block);
                }

                NamedTypeSymbol       stateMachineTypeOpt;
                VariableSlotAllocator variableSlotAllocatorOpt;
                var body = MethodCompiler.LowerBodyOrInitializer(
                    method: method,
                    body: block,
                    previousSubmissionFields: null,
                    compilationState: compilationState,
                    diagnostics: diagnostics,
                    stateMachineTypeOpt: out stateMachineTypeOpt,
                    variableSlotAllocatorOpt: out variableSlotAllocatorOpt);

                return(body);
            }
            finally
            {
                diagnostics.Free();
            }
        }
예제 #16
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        /// <exception cref="CompilerException"></exception>
        void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler)
        {
            var instruction = methodCompiler.Architecture.Is32BitPlatform ? (BaseInstruction)IRInstruction.LoadZeroExtend16x32 : IRInstruction.LoadZeroExtend16x64;

            if (context.OperandCount == 1)
            {
                context.SetInstruction(instruction, context.Result, context.Operand1, methodCompiler.ConstantZero);
            }
            else if (context.OperandCount == 2)
            {
                context.SetInstruction(instruction, context.Result, context.Operand1, context.Operand2);
            }
            else
            {
                throw new CompilerException();
            }

            LoadStore.OrderLoadOperands(context.Node, methodCompiler);
        }
예제 #17
0
        private static void StorePointer(Context context, MethodCompiler methodCompiler)
        {
            var instruction = methodCompiler.Architecture.Is32BitPlatform ? (BaseInstruction)IRInstruction.Store32 : IRInstruction.Store64;

            if (context.OperandCount == 2)
            {
                context.SetInstruction(instruction, null, context.Operand1, methodCompiler.ConstantZero, context.Operand2);
            }
            else if (context.OperandCount == 3)
            {
                context.SetInstruction(instruction, null, context.Operand1, context.Operand2, context.Operand3);
            }
            else
            {
                throw new CompilerException();
            }

            LoadStore.OrderOperands(context, methodCompiler);
        }
예제 #18
0
        private static void FrameCallRetR8(Context context, MethodCompiler methodCompiler)
        {
            var result        = context.Result;
            var methodAddress = context.Operand1;

            var eax  = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I8, GeneralPurposeRegister.EAX);
            var edx  = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I8, GeneralPurposeRegister.EDX);
            var xmm0 = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I8, SSE2Register.XMM0);

            methodCompiler.SplitLongOperand(result, out Operand op0L, out Operand op0H);

            context.SetInstruction(X64.Call, null, methodAddress);
            context.AppendInstruction(IRInstruction.Gen, xmm0);

            //context.AppendInstruction(X64.Movdi64ss, eax, xmm0);        // FIXME: X64
            context.AppendInstruction(X64.Pextrd64, edx, xmm0, methodCompiler.CreateConstant((byte)1));

            context.AppendInstruction(X64.Mov64, op0L, eax);
            context.AppendInstruction(X64.Mov64, op0H, edx);
        }
예제 #19
0
        private static void SetSegments(Context context, MethodCompiler methodCompiler)
        {
            var operand1 = context.Operand1;
            var operand2 = context.Operand2;
            var operand3 = context.Operand3;
            var operand4 = context.GetOperand(3);
            var operand5 = context.GetOperand(4);

            var ds = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.DS);
            var es = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.ES);
            var fs = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.FS);
            var gs = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.GS);
            var ss = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I2, SegmentRegister.SS);

            context.SetInstruction(X64.MovStoreSeg64, ds, operand1);
            context.AppendInstruction(X64.MovStoreSeg64, es, operand2);
            context.AppendInstruction(X64.MovStoreSeg64, fs, operand3);
            context.AppendInstruction(X64.MovStoreSeg64, gs, operand4);
            context.AppendInstruction(X64.MovStoreSeg64, ss, operand5);
        }
예제 #20
0
        private Operand GetFinalVirtualRegister(Operand operand)
        {
            Operand final;

            if (!finalVirtualRegisters.TryGetValue(operand, out final))
            {
                if (operand.SSAVersion == 0)
                {
                    final = operand.SSAParent;
                }
                else
                {
                    final = MethodCompiler.CreateVirtualRegister(operand.Type);
                }

                finalVirtualRegisters.Add(operand, final);
            }

            return(final);
        }
예제 #21
0
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="compiler">The compiler.</param>
        /// <exception cref="ArgumentNullException">context</exception>
        /// <exception cref="InvalidOperationException">Invalid virtualLocal state for pairing (" + context.Operand1.Type.GetStackType() + ", " + context.Operand2.Type.GetStackType() + ")</exception>
        public override void Resolve(Context context, MethodCompiler compiler)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            base.Resolve(context, compiler);

            var result = operandTable[(int)context.Operand1.Type.GetStackTypeCode()][(int)context.Operand2.Type.GetStackTypeCode()];

            Debug.Assert(StackTypeCode.Unknown != result, "Can't shift with the given virtualLocal operands.");

            if (StackTypeCode.Unknown == result)
            {
                throw new InvalidOperationException("Invalid virtualLocal state for pairing (" + context.Operand1.Type.GetStackType() + ", " + context.Operand2.Type.GetStackType() + ")");
            }

            context.Result = compiler.CreateVirtualRegister(compiler.TypeSystem.GetStackTypeFromCode(result));
        }
예제 #22
0
        /// <summary>
        /// Create platform compound move.
        /// </summary>
        /// <param name="methodCompiler">The compiler.</param>
        /// <param name="context">The context.</param>
        /// <param name="destinationBase">The destination base.</param>
        /// <param name="destination">The destination.</param>
        /// <param name="sourceBase">The source base.</param>
        /// <param name="source">The source.</param>
        /// <param name="size">The size.</param>
        public override void InsertCompoundCopy(MethodCompiler methodCompiler, Context context, Operand destinationBase, Operand destination, Operand sourceBase, Operand source, int size)
        {
            const int LargeAlignment       = 16;
            int       alignedSize          = size - (size % NativeAlignment);
            int       largeAlignedTypeSize = size - (size % LargeAlignment);

            Debug.Assert(size > 0);

            var srcReg = methodCompiler.CreateVirtualRegister(destinationBase.Type.TypeSystem.BuiltIn.I4);
            var dstReg = methodCompiler.CreateVirtualRegister(destinationBase.Type.TypeSystem.BuiltIn.I4);

            context.AppendInstruction(IRInstruction.UnstableObjectTracking);

            context.AppendInstruction(X86.Lea32, srcReg, sourceBase, source);
            context.AppendInstruction(X86.Lea32, dstReg, destinationBase, destination);

            var tmp      = methodCompiler.CreateVirtualRegister(destinationBase.Type.TypeSystem.BuiltIn.I4);
            var tmpLarge = methodCompiler.CreateVirtualRegister(destinationBase.Type.TypeSystem.BuiltIn.R8);

            for (int i = 0; i < largeAlignedTypeSize; i += LargeAlignment)
            {
                // Large aligned moves allow 128bits to be copied at a time
                var index = methodCompiler.CreateConstant((int)i);
                context.AppendInstruction(X86.MovupsLoad, tmpLarge, srcReg, index);
                context.AppendInstruction(X86.MovupsStore, null, dstReg, index, tmpLarge);
            }
            for (int i = largeAlignedTypeSize; i < alignedSize; i += 4)
            {
                var index = methodCompiler.CreateConstant(i);
                context.AppendInstruction(X86.MovLoad32, tmp, srcReg, index);
                context.AppendInstruction(X86.MovStore32, null, dstReg, index, tmp);
            }
            for (int i = alignedSize; i < size; i++)
            {
                var index = methodCompiler.CreateConstant(i);
                context.AppendInstruction(X86.MovLoad8, tmp, srcReg, index);
                context.AppendInstruction(X86.MovStore8, null, dstReg, index, tmp);
            }

            context.AppendInstruction(IRInstruction.StableObjectTracking);
        }
        private void InsertExceptionStartInstructions()
        {
            var objectType = TypeSystem.GetTypeByName("System", "Object");

            foreach (var clause in MethodCompiler.Method.ExceptionHandlers)
            {
                if (clause.ExceptionHandlerType == ExceptionHandlerType.Exception)
                {
                    var handler = BasicBlocks.GetByLabel(clause.HandlerStart);

                    var exceptionObject = MethodCompiler.CreateVirtualRegister(clause.Type);

                    var context = new Context(handler);

                    context.AppendInstruction(IRInstruction.ExceptionStart, exceptionObject);
                }

                if (clause.ExceptionHandlerType == ExceptionHandlerType.Filter)
                {
                    {
                        var handler = BasicBlocks.GetByLabel(clause.HandlerStart);

                        var exceptionObject = MethodCompiler.CreateVirtualRegister(objectType);

                        var context = new Context(handler);

                        context.AppendInstruction(IRInstruction.ExceptionStart, exceptionObject);
                    }

                    {
                        var handler = BasicBlocks.GetByLabel(clause.FilterStart.Value);

                        var exceptionObject = MethodCompiler.CreateVirtualRegister(objectType);

                        var context = new Context(handler);

                        context.AppendInstruction(IRInstruction.FilterStart, exceptionObject);
                    }
                }
            }
        }
예제 #24
0
        /// <summary>
        /// Allows quick internal call replacements
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        /// <param name="internalMethod">The internal method to replace with.</param>
        /// <param name="internalClass">The internal class that has the internal method.</param>
        /// <exception cref="ArgumentNullException"></exception>
        public static void MapToRunTime(Context context, MethodCompiler methodCompiler, string internalMethod, string internalClass = "Internal")
        {
            if (context == null || methodCompiler == null || internalMethod == null || internalClass == null)
            {
                throw new ArgumentNullException();
            }

            var type = methodCompiler.TypeSystem.GetTypeByName("Mosa.Runtime", internalClass);

            Debug.Assert(type != null, "Cannot find Mosa.Runtime." + internalClass);

            var method = type.FindMethodByName(internalMethod);

            Debug.Assert(method != null, "Cannot find " + internalMethod + " in " + type.Name);

            var symbol   = Operand.CreateSymbolFromMethod(method, methodCompiler.TypeSystem);
            var result   = context.Result;
            var operands = new List <Operand>(context.Operands);

            context.SetInstruction(IRInstruction.CallStatic, result, symbol, operands);
        }
예제 #25
0
        internal ImmutableArray <Diagnostic> FlowDiagnostics(CSharpCompilation compilation)
        {
            var flowDiagnostics = DiagnosticBag.GetInstance();

            foreach (var method in AllMethods(compilation.SourceModule.GlobalNamespace))
            {
                var sourceSymbol = method as SourceMemberMethodSymbol;
                if (sourceSymbol == null)
                {
                    continue;
                }

                var boundBody = MethodCompiler.BindMethodBody(sourceSymbol, new TypeCompilationState(sourceSymbol.ContainingType, compilation, null), new DiagnosticBag());
                if (boundBody != null)
                {
                    FlowAnalysisPass.Rewrite(sourceSymbol, boundBody, flowDiagnostics, hasTrailingExpression: false, originalBodyNested: false);
                }
            }

            return(flowDiagnostics.ToReadOnlyAndFree <Diagnostic>());
        }
예제 #26
0
        private static void FrameCallRetR8(Context context, MethodCompiler methodCompiler)
        {
            var result        = context.Result;
            var methodAddress = context.Operand1;
            var newESP        = context.Operand2;

            var eax  = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX);
            var edx  = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EDX);
            var mmx1 = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, SSE2Register.XMM0);

            methodCompiler.SplitLongOperand(result, out Operand op0L, out Operand op0H);

            context.SetInstruction(X86.Call, null, methodAddress);
            context.AppendInstruction(IRInstruction.Gen, mmx1);

            context.AppendInstruction(X86.Movdi32ss, eax, mmx1);                // CHECK
            context.AppendInstruction(X86.Pextrd32, edx, mmx1, methodCompiler.CreateConstant((byte)1));

            context.AppendInstruction(X86.Mov32, op0L, eax);
            context.AppendInstruction(X86.Mov32, op0H, edx);
        }
예제 #27
0
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler)
        {
            var result        = context.Result;
            var methodAddress = context.Operand1;
            var newESP        = context.Operand2;

            var eax  = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX);
            var edx  = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EDX);
            var mmx1 = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, SSE2Register.XMM0);

            methodCompiler.SplitLongOperand(result, out Operand op0L, out Operand op0H);

            context.SetInstruction(X86.CallReg, null, methodAddress);
            context.AppendInstruction(IRInstruction.Gen, mmx1);

            context.AppendInstruction(X86.Movd, eax, mmx1);
            context.AppendInstruction(X86.Pextrd, edx, mmx1, methodCompiler.CreateConstant((byte)1));

            context.AppendInstruction(X86.Mov32, op0L, eax);
            context.AppendInstruction(X86.Mov32, op0H, edx);
        }
예제 #28
0
        internal ImmutableArray <Diagnostic> FlowDiagnostics(CSharpCompilation compilation)
        {
            var flowDiagnostics = DiagnosticBag.GetInstance();

            foreach (var method in AllMethods(compilation.SourceModule.GlobalNamespace))
            {
                var sourceSymbol = method as SourceMethodSymbol;
                if (sourceSymbol == null)
                {
                    continue;
                }

                var boundBody = MethodCompiler.BindMethodBody(sourceSymbol, new DiagnosticBag());
                if (boundBody != null)
                {
                    FlowAnalysisPass.Rewrite(sourceSymbol, boundBody, flowDiagnostics);
                }
            }

            return(flowDiagnostics.ToReadOnlyAndFree <Diagnostic>());
        }
예제 #29
0
        internal static BoundBlock ParseAndBindMethodBody(string program, string typeName = DefaultTypeName, string methodName = DefaultMethodName)
        {
            var compilation = CreateCompilation(program);
            var method      = (MethodSymbol)compilation.GlobalNamespace.GetTypeMembers(typeName).Single().GetMembers(methodName).Single();

            // Provide an Emit.Module so that the lowering passes will be run
            var module = new PEAssemblyBuilder(
                (SourceAssemblySymbol)compilation.Assembly,
                emitOptions: EmitOptions.Default,
                outputKind: OutputKind.ConsoleApplication,
                serializationProperties: GetDefaultModulePropertiesForSerialization(),
                manifestResources: Enumerable.Empty <ResourceDescription>());

            TypeCompilationState compilationState = new TypeCompilationState(method.ContainingType, compilation, module);

            var diagnostics = DiagnosticBag.GetInstance();
            var block       = MethodCompiler.BindMethodBody(method, compilationState, diagnostics);

            diagnostics.Free();
            return(block);
        }
예제 #30
0
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The compiler.</param>
        /// <exception cref="ArgumentNullException">context</exception>
        /// <exception cref="InvalidOperationException">Invalid virtualLocal state for pairing (" + context.Operand1.Type.GetStackType() + ", " + context.Operand2.Type.GetStackType() + ")</exception>
        public override void Resolve(Context context, MethodCompiler methodCompiler)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            base.Resolve(context, methodCompiler);

            var op1 = methodCompiler.Compiler.GetStackTypeCode(context.Operand1.Type);
            var op2 = methodCompiler.Compiler.GetStackTypeCode(context.Operand2.Type);

            var result = operandTable[(int)op1][(int)op2];

            if (StackTypeCode.Unknown == result)
            {
                throw new CompilerException($"Invalid pairing ({context.Operand1.Type}, {context.Operand2.Type})");
            }

            context.Result = methodCompiler.CreateVirtualRegister(methodCompiler.Compiler.GetStackTypeFromCode(result));
        }
예제 #31
0
        protected void GenerateMethodBodyCore(
            TypeCompilationState compilationState,
            BindingDiagnosticBag diagnostics
            )
        {
            var factory = new SyntheticBoundNodeFactory(
                this,
                this.GetNonNullSyntaxNode(),
                compilationState,
                diagnostics
                );

            factory.CurrentFunction = this;
            if (ContainingType.BaseTypeNoUseSiteDiagnostics is MissingMetadataTypeSymbol)
            {
                // System_Attribute was not found or was inaccessible
                factory.CloseMethod(factory.Block());
                return;
            }

            var baseConstructorCall =
                MethodCompiler.GenerateBaseParameterlessConstructorInitializer(this, diagnostics);

            if (baseConstructorCall == null)
            {
                // Attribute..ctor was not found or was inaccessible
                factory.CloseMethod(factory.Block());
                return;
            }

            var statements = ArrayBuilder <BoundStatement> .GetInstance();

            statements.Add(factory.ExpressionStatement(baseConstructorCall));
            GenerateMethodBodyStatements(factory, statements, diagnostics);
            statements.Add(factory.Return());

            var block = factory.Block(statements.ToImmutableAndFree());

            factory.CloseMethod(block);
        }
예제 #32
0
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        public void Run()
        {
            // The size of the code in bytes
            MethodHeader header = new MethodHeader();

            using (Stream code = MethodCompiler.GetInstructionStream())
            {
                // Initalize the instruction, setting the initalize size to 10 times the code stream
                MethodCompiler.InstructionSet = new InstructionSet((int)code.Length * 10);

                // update the base class
                InstructionSet = MethodCompiler.InstructionSet;

                using (BinaryReader reader = new BinaryReader(code))
                {
                    _compiler   = MethodCompiler;
                    _method     = MethodCompiler.Method;
                    _codeReader = reader;

                    ReadMethodHeader(reader, ref header);
                    //Debug.WriteLine("Decoding " + compiler.Method.ToString());

                    if (0 != header.localsSignature)
                    {
                        StandAloneSigRow  row;
                        IMetadataProvider md = _method.Module.Metadata;
                        md.Read(header.localsSignature, out row);
                        MethodCompiler.SetLocalVariableSignature(LocalVariableSignature.Parse(md, row.SignatureBlobIdx));
                    }

                    /* Decode the instructions */
                    Decode(MethodCompiler, ref header);

                    // When we leave, the operand stack must only contain the locals...
                    //Debug.Assert(_operandStack.Count == _method.Locals.Count);
                    _codeReader = null;
                    _compiler   = null;
                }
            }
        }
예제 #33
0
        private static void Store(Context context, MethodCompiler methodCompiler)
        {
            if (context.OperandCount == 2)
            {
                var instruction = !context.Operand2.Is64BitInteger ? (BaseInstruction)IRInstruction.StoreInt32 : IRInstruction.StoreInt64;

                if (context.Operand2.IsR4)
                {
                    instruction = IRInstruction.StoreFloatR4;
                }
                else if (context.Operand2.IsR8)
                {
                    instruction = IRInstruction.StoreFloatR8;
                }

                context.SetInstruction(instruction, null, context.Operand1, methodCompiler.ConstantZero, context.Operand2);
            }
            else if (context.OperandCount == 3)
            {
                var instruction = !context.Operand3.Is64BitInteger ? (BaseInstruction)IRInstruction.StoreInt32 : IRInstruction.StoreInt64;

                if (context.Operand3.IsR4)
                {
                    instruction = IRInstruction.StoreFloatR4;
                }
                else if (context.Operand3.IsR8)
                {
                    instruction = IRInstruction.StoreFloatR8;
                }

                context.SetInstruction(instruction, null, context.Operand1, context.Operand2, context.Operand3);
            }
            else
            {
                throw new CompilerException();
            }

            LoadStore.OrderStoreOperands(context, methodCompiler);
        }
예제 #34
0
        protected void Compile(string source, IMetadataImporter metadataImporter = null, IRuntimeLibrary runtimeLibrary = null, IErrorReporter errorReporter = null, bool useFirstConstructor = false)
        {
            Compile(new[] { source }, metadataImporter: metadataImporter, runtimeLibrary: runtimeLibrary, errorReporter: errorReporter, methodCompiled: (m, res, mc) => {
                if (m.IsConstructor && (m.Attributes.Any() || useFirstConstructor)) {
                    Constructor = m;
                    MethodCompiler = mc;
                    CompiledConstructor = res;
                }
            });

            Assert.That(Constructor, Is.Not.Null, "No constructors with attributes were compiled.");
        }
예제 #35
0
 public CilToX86CodeVisitor(MethodCompiler methodCompiler)
 {
     this.MethodCompiler = methodCompiler;
 }
 public void Setup()
 {
     Method = null;
     MethodCompiler = null;
     CompiledMethod = null;
 }
        protected void Compile(string source, INamingConventionResolver namingConvention = null, IRuntimeLibrary runtimeLibrary = null, IErrorReporter errorReporter = null, bool useFirstConstructor = false)
        {
            Compile(new[] { source }, namingConvention, runtimeLibrary, errorReporter, (m, res, mc) => {
                if (m.IsConstructor && (m.Attributes.Any() || useFirstConstructor)) {
                    Constructor = m;
                    MethodCompiler = mc;
                    CompiledConstructor = res;
                }
            });

            Assert.That(Constructor, Is.Not.Null, "No constructors with attributes were compiled.");
        }
예제 #38
0
 private void OnMethodCompiled(IMethod method, JsFunctionDefinitionExpression result, MethodCompiler mc)
 {
     if (MethodCompiled != null)
         MethodCompiled(method, result, mc);
 }
예제 #39
0
        public void IgnoreOtherDiagnosticsCompilingSynthesizedMethods()
        {
            var source =
@"class C
{
    static object F = new object(); // generate .cctor
    static System.Action M()
    {
        return () => { }; // generate lambda
    }
}";
            var compilation = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseDll.WithConcurrentBuild(false));
            var options = compilation.Options;
            var diagnostics = DiagnosticBag.GetInstance();

            var assembly = (SourceAssemblySymbol)compilation.Assembly;
            var module = new PEAssemblyBuilder(
                assembly,
                EmitOptions.Default,
                options.OutputKind,
                GetDefaultModulePropertiesForSerialization(),
                new ResourceDescription[0]);

            var methodBodyCompiler = new MethodCompiler(
                compilation: compilation,
                moduleBeingBuiltOpt: module,
                emittingPdb: false,
                hasDeclarationErrors: false,
                diagnostics: diagnostics,
                filterOpt: null,
                cancellationToken: CancellationToken.None);

            // Add diagnostic to MethodBodyCompiler bag, as if
            // code gen for an earlier method had generated an error.
            diagnostics.Add(new CSDiagnostic(new CSDiagnosticInfo(ErrorCode.ERR_IntDivByZero), NoLocation.Singleton));

            // Compile all methods for type including synthesized methods.
            var type = compilation.GlobalNamespace.GetMember<NamedTypeSymbol>("C");
            methodBodyCompiler.Visit(type);

            Assert.Equal(1, diagnostics.AsEnumerable().Count());
            diagnostics.Free();
        }