Пример #1
0
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler)
        {
            var dest = context.Operand1;
            var src  = context.Operand2;

            var v0       = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.Void);
            var v1       = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.Void);
            var offset16 = methodCompiler.CreateConstant(16);

            context.SetInstruction(X86.MovupsLoad, v0, dest, methodCompiler.ConstantZero);
            context.AppendInstruction(X86.MovupsLoad, v1, dest, offset16);
            context.AppendInstruction(X86.MovupsStore, null, dest, methodCompiler.ConstantZero, v0);
            context.AppendInstruction(X86.MovupsStore, null, dest, offset16, v1);
        }
Пример #2
0
        private static void Memcpy256(Context context, MethodCompiler methodCompiler)
        {
            var dest = context.Operand1;
            var src  = context.Operand2;

            var v0       = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.Void);
            var v1       = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.Void);
            var offset16 = methodCompiler.CreateConstant(16);

            context.SetInstruction(X86.MovupsLoad, v0, dest, methodCompiler.ConstantZero);
            context.AppendInstruction(X86.MovupsLoad, v1, dest, offset16);
            context.AppendInstruction(X86.MovupsStore, null, dest, methodCompiler.ConstantZero, v0);
            context.AppendInstruction(X86.MovupsStore, null, dest, offset16, v1);
        }
        /// <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>
        public override void Resolve(Context context, MethodCompiler methodCompiler)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            base.Resolve(context, methodCompiler);

            var result = StackTypeCode.Unknown;

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

            switch (opcode)
            {
            case OpCode.Add_ovf_un: result = addovfunTable[(int)op1][(int)op2]; break;

            case OpCode.Sub_ovf_un: result = subovfunTable[(int)op1][(int)op2]; break;

            default: result = operandTable[(int)op1][(int)op2]; break;
            }

            if (StackTypeCode.Unknown == result)
            {
                throw new CompilerException($"Invalid operand types passed to {opcode}");
            }

            context.Result = methodCompiler.CreateVirtualRegister(methodCompiler.Compiler.GetStackTypeFromCode(result));
        }
        /// <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);

            // Simple result is the same type as the unary argument
            context.Result = compiler.CreateVirtualRegister(context.Operand1.Type);
        }
Пример #5
0
        private Operand Map(Operand operand, Dictionary <Operand, Operand> map, InstructionNode callNode)
        {
            if (operand == null)
            {
                return(null);
            }

            Operand mappedOperand;

            if (map.TryGetValue(operand, out mappedOperand))
            {
                return(mappedOperand);
            }

            if (operand.IsSymbol)
            {
                if (operand.StringData != null)
                {
                    mappedOperand = Operand.CreateStringSymbol(operand.Type.TypeSystem, operand.Name, operand.StringData);
                }
                else if (operand.Method != null)
                {
                    mappedOperand = Operand.CreateSymbolFromMethod(operand.Type.TypeSystem, operand.Method);
                }
                else if (operand.Name != null)
                {
                    mappedOperand = Operand.CreateManagedSymbol(operand.Type, operand.Name);
                }
            }
            else if (operand.IsParameter)
            {
                mappedOperand = callNode.GetOperand(operand.Index + 1);
            }
            else if (operand.IsStackLocal)
            {
                mappedOperand = MethodCompiler.StackLayout.AddStackLocal(operand.Type);
            }
            else if (operand.IsVirtualRegister)
            {
                mappedOperand = MethodCompiler.CreateVirtualRegister(operand.Type);
            }
            else if (operand.IsField)
            {
                mappedOperand = Operand.CreateField(operand.Field);
            }
            else if (operand.IsConstant)
            {
                mappedOperand = operand;
            }
            else if (operand.IsCPURegister)
            {
                mappedOperand = operand;
            }

            Debug.Assert(mappedOperand != null);

            map.Add(operand, mappedOperand);

            return(mappedOperand);
        }
        private void PerformStaticAllocationOf(InstructionNode allocation, InstructionNode assignment)
        {
            var allocatedType   = (allocation.InvokeMethod != null) ? allocation.InvokeMethod.DeclaringType : allocation.Result.Type;
            var assignmentField = assignment.MosaField;

            // Get size of type
            int typeSize = TypeLayout.GetTypeSize(allocatedType);

            // If instruction is newarr then get the size of the element, multiply it by array size, and add array header size
            // Also need to align to a 4-byte boundary
            if (allocation.Instruction is NewarrInstruction)
            {
                int elements = GetConstant(allocation.Operand1);
                typeSize = (TypeLayout.GetTypeSize(allocatedType.ElementType) * elements) + (TypeLayout.NativePointerSize * 3);
            }

            // Allocate a linker symbol to refer to this allocation. Use the destination field name as the linker symbol name.
            var symbolName = MethodCompiler.Linker.CreateSymbol(assignmentField.FullName + @"<<$cctor", SectionKind.ROData, Architecture.NativeAlignment, typeSize);

            // Try to get typeDefinitionSymbol if allocatedType isn't a value type
            string typeDefinitionSymbol = GetTypeDefinition(allocatedType);

            if (typeDefinitionSymbol != null)
            {
                MethodCompiler.Linker.Link(LinkType.AbsoluteAddress, PatchType.I4, symbolName, 0, 0, typeDefinitionSymbol, SectionKind.ROData, 0);
            }

            Operand staticAddress = Operand.CreateManagedSymbol(assignmentField.FieldType, symbolName.Name);
            Operand result1       = MethodCompiler.CreateVirtualRegister(assignmentField.FieldType);

            //Operand result2 = MethodCompiler.CreateVirtualRegister(assignmentField.FieldType);

            // Issue a load request before the newobj and before the assignment.
            new Context(allocation).InsertBefore().SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), result1, staticAddress);
            assignment.Operand1 = result1;

            // If the instruction is a newarr
            if (allocation.Instruction is NewarrInstruction)
            {
                allocation.SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), allocation.Result, result1);
                return;
            }

            //new Context(allocation).InsertBefore().SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), result2, staticAddress);

            // Change the newobj to a call and increase the operand count to include the this ptr.
            // If the instruction is a newarr, then just replace with a nop instead
            allocation.Result      = null;
            allocation.ResultCount = 0;
            allocation.OperandCount++;

            for (int i = allocation.OperandCount; i > 0; i--)
            {
                var op = allocation.GetOperand(i - 1);
                allocation.SetOperand(i, op);
            }

            allocation.Operand1    = result1;
            allocation.Instruction = CILInstruction.Get(OpCode.Call);
        }
Пример #7
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>
        public override void Resolve(Context context, MethodCompiler compiler)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            base.Resolve(context, compiler);

            StackTypeCode result = StackTypeCode.Unknown;

            switch (opcode)
            {
            case OpCode.Add_ovf_un: result = addovfunTable[(int)context.Operand1.Type.GetStackTypeCode()][(int)context.Operand2.Type.GetStackTypeCode()]; break;

            case OpCode.Sub_ovf_un: result = subovfunTable[(int)context.Operand1.Type.GetStackTypeCode()][(int)context.Operand2.Type.GetStackTypeCode()]; break;

            default: result = operandTable[(int)context.Operand1.Type.GetStackTypeCode()][(int)context.Operand2.Type.GetStackTypeCode()]; break;
            }

            if (StackTypeCode.Unknown == result)
            {
                throw new InvalidOperationException("Invalid operand types passed to " + opcode);
            }

            context.Result = compiler.CreateVirtualRegister(compiler.TypeSystem.GetStackTypeFromCode(result));
        }
Пример #8
0
        private void InsertBlockProtectInstructions()
        {
            foreach (var handler in MethodCompiler.Method.ExceptionHandlers)
            {
                var tryBlock = BasicBlocks.GetByLabel(handler.TryStart);

                var tryHandler = BasicBlocks.GetByLabel(handler.HandlerStart);

                var context = new Context(tryBlock);

                while (context.IsEmpty || context.Instruction == IRInstruction.TryStart)
                {
                    context.GotoNext();
                }

                context.AppendInstruction(IRInstruction.TryStart, tryHandler);

                context = new Context(tryHandler);

                if (handler.HandlerType == ExceptionHandlerType.Finally)
                {
                    var exceptionObject = MethodCompiler.CreateVirtualRegister(exceptionType);
                    var finallyOperand  = MethodCompiler.CreateVirtualRegister(TypeSystem.BuiltIn.I4);

                    context.AppendInstruction2(IRInstruction.FinallyStart, exceptionObject, finallyOperand);
                }
            }
        }
        private void CompoundLoad(Context context)
        {
            var type                 = context.Result.Type;
            int typeSize             = TypeLayout.GetTypeSize(type);
            int alignedTypeSize      = typeSize - (typeSize % NativeAlignment);
            int largeAlignedTypeSize = typeSize - (typeSize % LargeAlignment);

            Debug.Assert(typeSize > 0, context.Operand2.Name);

            int offset = 0;

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

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

            Debug.Assert(dest.IsMemoryAddress, dest.Name);

            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);
            var tmpLarge = Operand.CreateCPURegister(MethodCompiler.TypeSystem.BuiltIn.Void, SSE2Register.XMM1);

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

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

            for (int i = 0; i < largeAlignedTypeSize; i += LargeAlignment)
            {
                // Large Aligned moves allow 128bits to be copied at a time
                var index   = Operand.CreateConstant(TypeSystem.BuiltIn.I4, i);
                var offset2 = Operand.CreateConstant(TypeSystem.BuiltIn.I4, i + offset);
                context.AppendInstruction(X86.MovupsLoad, tmpLarge, srcReg, index);
                context.AppendInstruction(X86.MovupsStore, null, dstReg, index, tmpLarge);
            }
            for (int i = largeAlignedTypeSize; i < alignedTypeSize; i += NativeAlignment)
            {
                var index   = Operand.CreateConstant(TypeSystem.BuiltIn.I4, i);
                var offset2 = Operand.CreateConstant(TypeSystem.BuiltIn.I4, i + offset);
                context.AppendInstruction(X86.MovLoad, InstructionSize.Size32, tmp, srcReg, offset2);
                context.AppendInstruction(X86.MovStore, InstructionSize.Size32, null, dstReg, index, tmp);
            }
            for (int i = alignedTypeSize; i < typeSize; i++)
            {
                var index   = Operand.CreateConstant(TypeSystem.BuiltIn.I4, i);
                var offset2 = Operand.CreateConstant(TypeSystem.BuiltIn.I4, i + offset);
                context.AppendInstruction(X86.MovzxLoad, InstructionSize.Size8, tmp, srcReg, offset2);
                context.AppendInstruction(X86.MovStore, InstructionSize.Size8, null, dstReg, index, tmp);
            }
        }
Пример #10
0
        private static void In32(Context context, MethodCompiler methodCompiler)
        {
            var v1 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.U8);

            var result = context.Result;

            context.SetInstruction(X64.In32, v1, context.Operand1);
            context.AppendInstruction(X64.Movzx16To64, result, v1);
        }
        private Operand InsertLoadBeforeInstruction(Context context, string symbolName, MosaType type)
        {
            var     before = context.InsertBefore();
            Operand result = MethodCompiler.CreateVirtualRegister(type);
            Operand op     = Operand.CreateManagedSymbol(type, symbolName);

            before.SetInstruction(CILInstruction.Get(OpCode.Ldc_i4), result, op);

            return(result);
        }
Пример #12
0
        void IIRVisitor.CompoundStore(Context context)
        {
            var type                 = context.Operand3.Type;
            int typeSize             = TypeLayout.GetTypeSize(type);
            int alignedTypeSize      = typeSize - (typeSize % NativeAlignment);
            int largeAlignedTypeSize = typeSize - (typeSize % LargeAlignment);

            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);
            var tmpLarge = Operand.CreateCPURegister(MethodCompiler.TypeSystem.BuiltIn.Void, SSE2Register.XMM1);

            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 < largeAlignedTypeSize; i += LargeAlignment)
            {
                // Large Aligned moves allow 128bits to be copied at a time
                var memSrc  = Operand.CreateMemoryAddress(MethodCompiler.TypeSystem.BuiltIn.Void, srcReg, i);
                var memDest = Operand.CreateMemoryAddress(MethodCompiler.TypeSystem.BuiltIn.Void, dstReg, i + offset);
                context.AppendInstruction(X86.MovAPS, InstructionSize.Size128, tmpLarge, memSrc);
                context.AppendInstruction(X86.MovAPS, InstructionSize.Size128, memDest, tmpLarge);
            }
            for (int i = largeAlignedTypeSize; 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);
            }
        }
Пример #13
0
        private static void In16(Context context, MethodCompiler methodCompiler)
        {
            Operand v1 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.U4);

            var result = context.Result;

            context.SetInstruction(X86.In16, v1, context.Operand1);
            context.AppendInstruction(X86.Movzx16To32, result, v1);

            //context.SetInstruction(X86.In16, result, context.Operand1);
        }
Пример #14
0
        private static void Div(Context context, MethodCompiler methodCompiler)
        {
            Operand n       = context.Operand1;
            Operand d       = context.Operand2;
            Operand result  = context.Result;
            Operand result2 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.U4);

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

            context.SetInstruction2(X86.Div32, result2, result, op0H, op0L, d);
        }
Пример #15
0
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler)
        {
            Operand n       = context.Operand1;
            Operand d       = context.Operand2;
            Operand result  = context.Result;
            Operand result2 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.U4);

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

            context.SetInstruction2(X86.Div32, result2, result, op0H, op0L, d);
        }
Пример #16
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>
        public override void Resolve(Context context, MethodCompiler methodCompiler)
        {
            if (context == null)
            {
                throw new System.ArgumentNullException(nameof(context));
            }

            base.Resolve(context, methodCompiler);

            context.Result = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.U);
        }
Пример #17
0
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler)
        {
            Operand v1 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.U4);

            var result = context.Result;

            context.SetInstruction(X86.In16, v1, context.Operand1);
            context.AppendInstruction(X86.Movzx16To32, result, v1);

            //context.SetInstruction(X86.In16, result, context.Operand1);
        }
Пример #18
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);
        }
Пример #19
0
        protected void Promote(Operand local)
        {
            var stacktype = local.Type.GetStackType();

            var v = MethodCompiler.CreateVirtualRegister(stacktype);

            if (trace.Active)
            {
                trace.Log("*** Replacing: " + local.ToString() + " with " + v.ToString());
            }

            foreach (var node in local.Uses.ToArray())
            {
                for (int i = 0; i < node.OperandCount; i++)
                {
                    var operand = node.GetOperand(i);

                    if (local == operand)
                    {
                        if (trace.Active)
                        {
                            trace.Log("BEFORE:\t" + node.ToString());
                        }
                        node.SetOperand(i, v);
                        if (trace.Active)
                        {
                            trace.Log("AFTER: \t" + node.ToString());
                        }
                    }
                }
            }

            foreach (var node in local.Definitions.ToArray())
            {
                for (int i = 0; i < node.OperandCount; i++)
                {
                    var operand = node.GetResult(i);

                    if (local == operand)
                    {
                        if (trace.Active)
                        {
                            trace.Log("BEFORE:\t" + node.ToString());
                        }
                        node.SetResult(i, v);
                        if (trace.Active)
                        {
                            trace.Log("AFTER: \t" + node.ToString());
                        }
                    }
                }
            }
        }
Пример #20
0
        private static void Remainder(Context context, MethodCompiler methodCompiler)
        {
            var result   = context.Result;
            var dividend = context.Operand1;
            var divisor  = context.Operand2;

            if (result.IsR8)
            {
                var xmm1 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R8);
                var xmm2 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R8);
                var xmm3 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R8);

                context.SetInstruction(X86.Divsd, xmm1, dividend, divisor);
                context.AppendInstruction(X86.Roundsd, xmm2, xmm1, methodCompiler.CreateConstant((byte)0x3));
                context.AppendInstruction(X86.Mulsd, xmm3, divisor, xmm2);
                context.AppendInstruction(X86.Subsd, result, dividend, xmm3);
            }
            else
            {
                var xmm1 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R4);
                var xmm2 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R4);
                var xmm3 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R4);

                context.SetInstruction(X86.Divss, xmm1, dividend, divisor);
                context.AppendInstruction(X86.Roundss, xmm2, xmm1, methodCompiler.CreateConstant((byte)0x3));
                context.AppendInstruction(X86.Mulss, xmm3, divisor, xmm2);
                context.AppendInstruction(X86.Subss, result, dividend, xmm3);
            }
        }
Пример #21
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>
        public override void Resolve(Context context, MethodCompiler methodCompiler)
        {
            base.Resolve(context, methodCompiler);

            var result = StackTypeCode.Unknown;

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

            switch (opcode)
            {
            case OpCode.Add: result = addTable[(int)op1][(int)op2]; break;

            case OpCode.Sub: result = subTable[(int)op1][(int)op2]; break;

            default: result = operandTable[(int)op1][(int)op2]; break;
            }

            if (result == StackTypeCode.Unknown)
            {
                throw new CompilerException($"Invalid operand types passed to {opcode}");
            }

            MosaType resultType;

            if (StackTypeCode.UnmanagedPointer != result)
            {
                resultType = methodCompiler.Compiler.GetStackTypeFromCode(result);

                if (result == StackTypeCode.F && context.Operand1.IsR4 && context.Operand2.IsR4)
                {
                    resultType = methodCompiler.TypeSystem.BuiltIn.R4;
                }
            }
            else
            {
                if (context.Operand1.IsPointer)
                {
                    resultType = context.Operand1.Type;
                }
                else if (context.Operand2.IsPointer)
                {
                    resultType = context.Operand2.Type;
                }
                else
                {
                    throw new CompilerException($"Invalid operand types passed to {opcode}");
                }
            }

            context.Result = methodCompiler.CreateVirtualRegister(resultType);
        }
        private void CompoundMove(Context context)
        {
            var type                 = context.Result.Type;
            int typeSize             = TypeLayout.GetTypeSize(type);
            int alignedTypeSize      = typeSize - (typeSize % NativeAlignment);
            int largeAlignedTypeSize = typeSize - (typeSize % LargeAlignment);

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

            var src  = context.Operand1;
            var dest = context.Result;

            Debug.Assert((src.IsMemoryAddress || src.IsSymbol) && dest.IsMemoryAddress, context.ToString());

            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);
            var tmpLarge = Operand.CreateCPURegister(MethodCompiler.TypeSystem.BuiltIn.Void, SSE2Register.XMM1);

            context.SetInstruction(X86.Nop);

            if (src.IsSymbol)
            {
                context.AppendInstruction(X86.Mov, srcReg, src);
            }
            else
            {
                context.AppendInstruction(X86.Lea, srcReg, src);
            }

            context.AppendInstruction(X86.Lea, dstReg, dest);

            for (int i = 0; i < largeAlignedTypeSize; i += LargeAlignment)
            {
                // Large Aligned moves allow 128bits to be copied at a time
                var index = Operand.CreateConstant(TypeSystem.BuiltIn.I4, i);
                context.AppendInstruction(X86.MovupsLoad, tmpLarge, srcReg, index);
                context.AppendInstruction(X86.MovupsStore, null, dstReg, index, tmpLarge);
            }
            for (int i = largeAlignedTypeSize; i < alignedTypeSize; i += NativeAlignment)
            {
                var index = Operand.CreateConstant(TypeSystem.BuiltIn.I4, i);
                context.AppendInstruction(X86.MovLoad, InstructionSize.Size32, tmp, srcReg, index);
                context.AppendInstruction(X86.MovStore, InstructionSize.Size32, null, dstReg, index, tmp);
            }
            for (int i = alignedTypeSize; i < typeSize; i++)
            {
                var index = Operand.CreateConstant(TypeSystem.BuiltIn.I4, i);
                context.AppendInstruction(X86.MovzxLoad, InstructionSize.Size8, tmp, srcReg, index);
                context.AppendInstruction(X86.MovStore, InstructionSize.Size8, null, dstReg, index, tmp);
            }
        }
Пример #23
0
        private static void XAddLoad32(Context context, MethodCompiler methodCompiler)
        {
            var location = context.Operand1;
            var value    = context.Operand2;
            var result   = context.Result;

            var v1 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.U4);

            context.SetInstruction(X86.Mov32, v1, value);
            context.AppendInstruction(X86.Lock);
            context.AppendInstruction(X86.XAddLoad32, v1, location, methodCompiler.ConstantZero32, v1);
            context.AppendInstruction(X86.Mov32, result, v1);
        }
Пример #24
0
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="methodCompiler">The compiler.</param>
        public override void Resolve(Context context, MethodCompiler methodCompiler)
        {
            base.Resolve(context, methodCompiler);

            var result = opTable[(int)methodCompiler.Compiler.GetStackTypeCode(context.Operand1.Type)];

            if (StackTypeCode.Unknown == result)
            {
                throw new InvalidOperationException("Invalid operand to Not instruction.");
            }

            context.Result = methodCompiler.CreateVirtualRegister(context.Operand1.Type);
        }
Пример #25
0
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, MethodCompiler methodCompiler)
        {
            var location = context.Operand1;
            var value    = context.Operand2;
            var result   = context.Result;

            var v1 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.U4);

            context.SetInstruction(X86.Mov32, v1, value);
            context.AppendInstruction(X86.Lock);
            context.AppendInstruction(X86.XChgLoad32, v1, location, methodCompiler.ConstantZero, v1);
            context.AppendInstruction(X86.Mov32, result, v1);
        }
Пример #26
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>
        public override void Resolve(Context context, MethodCompiler methodCompiler)
        {
            base.Resolve(context, methodCompiler);

            // If we're ldind.i8, fix an IL deficiency that the result may be U8
            if (opcode == OpCode.Ldind_i8 && elementType.Value == MosaTypeCode.I8)
            {
                if (context.Operand1.Type.ElementType?.IsU8 == true)
                {
                    context.Result = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.U8);
                }
            }
        }
Пример #27
0
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="methodCompiler">The compiler.</param>
        public override void Resolve(Context context, MethodCompiler methodCompiler)
        {
            base.Resolve(context, methodCompiler);

            // Validate the typecode & determine the resulting stack type
            MosaType resultType;

            switch (opcode)
            {
            case OpCode.Conv_u: resultType = methodCompiler.TypeSystem.BuiltIn.U; break;

            case OpCode.Conv_i: resultType = methodCompiler.TypeSystem.BuiltIn.I; break;

            case OpCode.Conv_i1: resultType = methodCompiler.TypeSystem.BuiltIn.I1; break;

            case OpCode.Conv_i2: resultType = methodCompiler.TypeSystem.BuiltIn.I2; break;

            case OpCode.Conv_i4: resultType = methodCompiler.TypeSystem.BuiltIn.I4; break;

            case OpCode.Conv_i8: resultType = methodCompiler.TypeSystem.BuiltIn.I8; break;

            case OpCode.Conv_r4: resultType = methodCompiler.TypeSystem.BuiltIn.R4; break;

            case OpCode.Conv_r8: resultType = methodCompiler.TypeSystem.BuiltIn.R8; break;

            case OpCode.Conv_u1: resultType = methodCompiler.TypeSystem.BuiltIn.U1; break;

            case OpCode.Conv_u2: resultType = methodCompiler.TypeSystem.BuiltIn.U2; break;

            case OpCode.Conv_u4: resultType = methodCompiler.TypeSystem.BuiltIn.U4; break;

            case OpCode.Conv_u8: resultType = methodCompiler.TypeSystem.BuiltIn.U8; break;

            case OpCode.Conv_ovf_i: goto case OpCode.Conv_i;

            case OpCode.Conv_ovf_u: goto case OpCode.Conv_u;

            case OpCode.Conv_ovf_i_un: goto case OpCode.Conv_i;

            case OpCode.Conv_ovf_u_un: goto case OpCode.Conv_u;

            case OpCode.Conv_r_un: resultType = methodCompiler.TypeSystem.BuiltIn.R8; break;

            default: throw new CompilerException("Overflow checking conversions not supported");
            }

            var result = methodCompiler.Compiler.GetStackType(resultType);

            context.Result   = methodCompiler.CreateVirtualRegister(resultType);
            context.MosaType = resultType;
        }
Пример #28
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>
        public override void Resolve(Context context, MethodCompiler compiler)
        {
            base.Resolve(context, compiler);

            StackTypeCode result = StackTypeCode.Unknown;

            switch (opcode)
            {
            case OpCode.Add: result = addTable[(int)context.Operand1.Type.GetStackTypeCode()][(int)context.Operand2.Type.GetStackTypeCode()]; break;

            case OpCode.Sub: result = subTable[(int)context.Operand1.Type.GetStackTypeCode()][(int)context.Operand2.Type.GetStackTypeCode()]; break;

            default: result = operandTable[(int)context.Operand1.Type.GetStackTypeCode()][(int)context.Operand2.Type.GetStackTypeCode()]; break;
            }

            if (result == StackTypeCode.Unknown)
            {
                throw new InvalidOperationException("Invalid operand types passed to " + opcode);
            }

            MosaType resultType = null;

            if (StackTypeCode.UnmanagedPointer != result)
            {
                resultType = compiler.TypeSystem.GetStackTypeFromCode(result);

                if (result == StackTypeCode.F && context.Operand1.Type.IsR4 && context.Operand2.Type.IsR4)
                {
                    resultType = compiler.TypeSystem.BuiltIn.R4;
                }
            }
            else
            {
                if (context.Operand1.Type.IsPointer)
                {
                    resultType = context.Operand1.Type;
                }
                else if (context.Operand2.Type.IsPointer)
                {
                    resultType = context.Operand2.Type;
                }
                else
                {
                    throw new InvalidOperationException("Invalid operand types passed to " + opcode);
                }
            }

            //Debug.Assert(resultType != null, ctx.ToString());

            context.Result = compiler.CreateVirtualRegister(resultType);
        }
Пример #29
0
        /// <summary>
        /// Validates the instruction operands and creates a matching variable for the result.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="compiler">The compiler.</param>
        public override void Resolve(Context context, MethodCompiler compiler)
        {
            base.Resolve(context, compiler);

            // Validate the operand
            var result = typeCodes[(int)context.Operand1.Type.GetStackTypeCode()];

            if (StackTypeCode.Unknown == result)
            {
                throw new InvalidOperationException("Invalid operand to Neg instruction [" + result + "]");
            }

            context.Result = compiler.CreateVirtualRegister(context.Operand1.Type);
        }
Пример #30
0
        private static void CmpXChgLoad32(Context context, MethodCompiler methodCompiler)
        {
            var location  = context.Operand1;
            var value     = context.Operand2;
            var comparand = context.Operand3;
            var result    = context.Result;

            var eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.U4, GeneralPurposeRegister.EAX);
            var v1  = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.U4);

            context.SetInstruction(X86.Mov32, eax, comparand);
            context.AppendInstruction(X86.Mov32, v1, value);
            context.AppendInstruction(X86.Lock);
            context.AppendInstruction(X86.CmpXChgLoad32, eax, eax, location, methodCompiler.ConstantZero, v1);
            context.AppendInstruction(X86.Mov32, result, eax);
        }