Ejemplo n.º 1
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="context"></param>
 /// <param name="emitter"></param>
 protected override void Emit(Context context, MachineCodeEmitter emitter)
 {
     OpCode opCode = ComputeOpCode(context.Result, context.Operand1, context.Operand2);
     if (context.Operand1 is ConstantOperand)
     {
         ConstantOperand op = context.Operand1 as ConstantOperand;
         op = new ConstantOperand(BuiltInSigType.Byte, op.Value);
         emitter.Emit(opCode, context.Result, op);
     }
     else
         emitter.Emit(opCode, context.Operand1, null);
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Emits the specified platform instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="emitter">The emitter.</param>
        protected override void Emit(Context context, MachineCodeEmitter emitter)
        {
            OpCode opCode = ComputeOpCode(context.Result, context.Operand1, context.Operand2);
            if (context.Operand2 is ConstantOperand)
            {
                // TODO/FIXME: Move these two lines into a stage
                ConstantOperand op = context.Operand2 as ConstantOperand;
                op = new ConstantOperand(BuiltInSigType.Byte, op.Value);

                emitter.Emit(opCode, context.Result, context.Operand1, op);
            }
            else
                emitter.Emit(opCode, context.Result, context.Operand1, context.Operand2);
        }
Ejemplo n.º 3
0
 protected bool IsConstantBetween(ConstantOperand op, int lo, int hi, out int value)
 {
     value = 0;
     switch (op.Type.Type)
     {
         case CilElementType.I:
             try
             {
                 if (op.Value is Token)
                 {
                     value = ((Token)op.Value).ToInt32();
                     return value >= lo && value <= hi;
                 }
                 else
                 {
                     value = Convert.ToInt32(op.Value);
                     return value >= lo && value <= hi;
                 }
             }
             catch (OverflowException)
             {
                 return false;
             }
         case CilElementType.I1:
         case CilElementType.I2:
         case CilElementType.I4:
         case CilElementType.U1:
         case CilElementType.Char:
         case CilElementType.U2:
         case CilElementType.Ptr:
         case CilElementType.U4:
             goto case CilElementType.I;
         case CilElementType.I8:
         case CilElementType.U8:
         case CilElementType.R4:
         case CilElementType.R8:
             goto default;
         case CilElementType.Object:
             goto case CilElementType.I;
         default:
             throw new NotSupportedException(String.Format(@"CilElementType.{0} is not supported.", op.Type.Type));
     }
 }
        private static void SplitFromConstantOperand(Operand operand, out Operand operandLow, out Operand operandHigh)
        {
            SigType HighType = (operand.Type.Type == CilElementType.I8) ? BuiltInSigType.Int32 : BuiltInSigType.UInt32;

            ConstantOperand constantOperand = operand as ConstantOperand;

            if (HighType.Type == CilElementType.I4)
            {
                long value = (long)constantOperand.Value;
                operandLow = new ConstantOperand(BuiltInSigType.UInt32, (uint)(value & 0xFFFFFFFF));
                operandHigh = new ConstantOperand(HighType, (int)(value >> 32));
            }
            else
            {
                ulong value = (ulong)constantOperand.Value;
                operandLow = new ConstantOperand(BuiltInSigType.UInt32, (uint)(value & 0xFFFFFFFF));
                operandHigh = new ConstantOperand(HighType, (uint)(value >> 32));
            }
        }
        /// <summary>
        /// Expands the unary branch instruction for 64-bits.
        /// </summary>
        /// <param name="context">The context.</param>
        private void ExpandUnaryBranch(Context context)
        {
            Debug.Assert(context.Branch.Targets.Length == 2);

            int target = context.Branch.Targets[0];

            Operand op1H, op1L, op2H, op2L;
            Operand zero = new ConstantOperand(BuiltInSigType.Int32, (int)0);
            SplitLongOperand(context.Operand1, out op1L, out op1H);
            SplitLongOperand(zero, out op2L, out op2H);
            IR.ConditionCode code;

            switch (((context.Instruction) as CIL.ICILInstruction).OpCode)
            {
                // Signed
                case CIL.OpCode.Brtrue: code = IR.ConditionCode.NotEqual; break;
                case CIL.OpCode.Brfalse: code = IR.ConditionCode.Equal; break;
                case CIL.OpCode.Beq_s: code = IR.ConditionCode.Equal; break;
                case CIL.OpCode.Bge_s: code = IR.ConditionCode.GreaterOrEqual; break;
                case CIL.OpCode.Bgt_s: code = IR.ConditionCode.GreaterThan; break;
                case CIL.OpCode.Ble_s: code = IR.ConditionCode.LessOrEqual; break;
                case CIL.OpCode.Blt_s: code = IR.ConditionCode.LessThan; break;

                // Unsigned
                case CIL.OpCode.Bne_un_s: code = IR.ConditionCode.NotEqual; break;
                case CIL.OpCode.Bge_un_s: code = IR.ConditionCode.UnsignedGreaterOrEqual; break;
                case CIL.OpCode.Bgt_un_s: code = IR.ConditionCode.UnsignedGreaterThan; break;
                case CIL.OpCode.Ble_un_s: code = IR.ConditionCode.UnsignedLessOrEqual; break;
                case CIL.OpCode.Blt_un_s: code = IR.ConditionCode.UnsignedLessThan; break;

                // Long form signed
                case CIL.OpCode.Beq: goto case CIL.OpCode.Beq_s;
                case CIL.OpCode.Bge: goto case CIL.OpCode.Bge_s;
                case CIL.OpCode.Bgt: goto case CIL.OpCode.Bgt_s;
                case CIL.OpCode.Ble: goto case CIL.OpCode.Ble_s;
                case CIL.OpCode.Blt: goto case CIL.OpCode.Blt_s;

                // Long form unsigned
                case CIL.OpCode.Bne_un: goto case CIL.OpCode.Bne_un_s;
                case CIL.OpCode.Bge_un: goto case CIL.OpCode.Bge_un_s;
                case CIL.OpCode.Bgt_un: goto case CIL.OpCode.Bgt_un_s;
                case CIL.OpCode.Ble_un: goto case CIL.OpCode.Ble_un_s;
                case CIL.OpCode.Blt_un: goto case CIL.OpCode.Blt_un_s;
                default: throw new NotImplementedException();
            }

            //UNUSED:
            //IR.ConditionCode conditionHigh = GetHighCondition(code);

            Context[] newBlocks = CreateEmptyBlockContexts(context.Label, 3);
            Context nextBlock = SplitContext(context, false);

            context.SetInstruction(Instruction.JmpInstruction, newBlocks[0].BasicBlock);
            LinkBlocks(context, newBlocks[0]);
            // Compare high dwords
            // TODO:
            //newBlocks[0].AppendInstruction(Instruction.DirectCompareInstruction, op1H, op2H);
            // Branch if check already gave results
            newBlocks[0].AppendInstruction(Instruction.BranchInstruction, IR.ConditionCode.Equal, newBlocks[2].BasicBlock);
            newBlocks[0].AppendInstruction(Instruction.JmpInstruction, newBlocks[1].BasicBlock);
            LinkBlocks(newBlocks[0], newBlocks[1], newBlocks[2]);

            newBlocks[1].AppendInstruction(Instruction.BranchInstruction, code, FindBlock(target));
            //            newBlocks[1].SetBranch(target);
            newBlocks[1].AppendInstruction(Instruction.JmpInstruction);
            newBlocks[1].SetBranch(nextBlock.BasicBlock);
            LinkBlocks(newBlocks[1], FindBlock(target));
            LinkBlocks(newBlocks[1], nextBlock);

            // Compare low dwords
            // TODO:
            //newBlocks[2].SetInstruction(Instruction.DirectCompareInstruction, op1L, op2L);
            // Set the unsigned result...
            newBlocks[2].AppendInstruction(Instruction.BranchInstruction, code, FindBlock(target));
            //            newBlocks[1].SetBranch(target);
            newBlocks[2].AppendInstruction(Instruction.JmpInstruction);
            newBlocks[2].SetBranch(nextBlock.BasicBlock);
            LinkBlocks(newBlocks[2], FindBlock(target));
            LinkBlocks(newBlocks[2], nextBlock);
        }
        /// <summary>
        /// Splits the long operand into its high and low parts.
        /// </summary>
        /// <param name="operand">The operand to split.</param>
        /// <param name="operandLow">The low operand.</param>
        /// <param name="operandHigh">The high operand.</param>
        /// <exception cref="T:System.ArgumentException"><paramref name="operand"/> is not a ConstantOperand and not a MemoryOperand.</exception>
        public static void SplitLongOperand(Operand operand, out Operand operandLow, out Operand operandHigh)
        {
            if (operand.Type.Type != CilElementType.I8 && operand.Type.Type != CilElementType.U8)
            {
                operandLow = operand;
                operandHigh = new ConstantOperand(BuiltInSigType.Int32, (int)0);
                return;
            }

            Debug.Assert(operand is MemoryOperand || operand is ConstantOperand, @"Long operand not memory or constant.");

            if (operand is ConstantOperand)
                SplitFromConstantOperand(operand, out operandLow, out operandHigh);
            else
                SplitFromNonConstantOperand(operand, out operandLow, out operandHigh);
        }
Ejemplo n.º 7
0
 /// <summary>
 /// Determines if the given constant operand is a large constant.
 /// </summary>
 /// <remarks>
 /// Only constants, which have special types or do not fit into an immediate argument
 /// are large and are moved to memory.
 /// </remarks>
 /// <param name="co">The constant operand to check.</param>
 /// <returns>True if the constant is large and needs to be moved to a literal.</returns>
 private static bool IsLargeConstant(ConstantOperand co)
 {
     return (Array.IndexOf<CilElementType>(_largeCilTypes, co.Type.Type) != -1);
 }
Ejemplo n.º 8
0
        /// <summary>
        /// Visitation function for Ldfld instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Ldfld(Context context)
        {
            Operand resultOperand = context.Result;
            Operand objectOperand = context.Operand1;
            Operand temp = methodCompiler.CreateVirtualRegister(context.RuntimeField.SignatureType);
            RuntimeField field = context.RuntimeField;

            int offset = typeLayout.GetFieldOffset(field);
            ConstantOperand offsetOperand = new ConstantOperand(BuiltInSigType.IntPtr, offset);

            IInstruction loadInstruction = IRInstruction.Load;
            if (MustSignExtendOnLoad(field.SignatureType.Type))
            {
                loadInstruction = IRInstruction.SignExtendedMove;
            }
            else if (MustZeroExtendOnLoad(field.SignatureType.Type))
            {
                loadInstruction = IRInstruction.ZeroExtendedMove;
            }

            context.SetInstruction(loadInstruction, temp, objectOperand, offsetOperand);
            context.AppendInstruction(IRInstruction.Move, resultOperand, temp);
        }
Ejemplo n.º 9
0
        private Operand CalculateArrayElementOffset(Context context, SZArraySigType arraySignatureType, Operand arrayIndexOperand)
        {
            int elementSizeInBytes = 0, alignment = 0;
            architecture.GetTypeRequirements(arraySignatureType.ElementType, out elementSizeInBytes, out alignment);

            //
            // The sequence we're emitting is:
            //
            //      offset = arrayIndexOperand * elementSize
            //      temp = offset + 12
            //      result = *(arrayOperand * temp)
            //
            // The array data starts at offset 12 from the array object itself. The 12 is a hardcoded assumption
            // of x86, which might change for other platforms. We need to refactor this into some helper classes.
            //

            Operand elementOffset = methodCompiler.CreateVirtualRegister(BuiltInSigType.Int32);
            Operand elementSizeOperand = new ConstantOperand(BuiltInSigType.Int32, elementSizeInBytes);
            context.AppendInstruction(IRInstruction.MulS, elementOffset, arrayIndexOperand, elementSizeOperand);

            return elementOffset;
        }
Ejemplo n.º 10
0
 private Operand LoadArrayBaseAddress(Context context, SZArraySigType arraySignatureType, Operand arrayOperand)
 {
     Operand arrayAddress = methodCompiler.CreateVirtualRegister(new PtrSigType(arraySignatureType.ElementType));
     Operand fixedOffset = new ConstantOperand(BuiltInSigType.Int32, 12);
     context.SetInstruction(IRInstruction.AddS, arrayAddress, arrayOperand, fixedOffset);
     return arrayAddress;
 }
Ejemplo n.º 11
0
        /// <summary>
        /// Visitation function for Stfld instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Stfld(Context context)
        {
            Operand objectOperand = context.Operand1;
            Operand valueOperand = context.Operand2;
            Operand temp = methodCompiler.CreateVirtualRegister(context.RuntimeField.SignatureType);

            int offset = typeLayout.GetFieldOffset(context.RuntimeField);
            ConstantOperand offsetOperand = new ConstantOperand(BuiltInSigType.IntPtr, offset);

            context.SetInstruction(IRInstruction.Move, temp, valueOperand);
            context.AppendInstruction(IRInstruction.Store, objectOperand, objectOperand, offsetOperand, temp);
        }
Ejemplo n.º 12
0
 /// <summary>
 /// Visitation function for Neg instruction.
 /// </summary>
 /// <param name="context">The context.</param>
 public void Neg(Context context)
 {
     if (IsUnsigned(context.Operand1))
     {
         ConstantOperand zero = new ConstantOperand(context.Operand1.Type, 0UL);
         context.SetInstruction(IRInstruction.SubU, context.Result, zero, context.Operand1);
     }
     else if (context.Operand1.Type.Type == CilElementType.R4)
     {
         ConstantOperand minusOne = new ConstantOperand(context.Operand1.Type, -1.0f);
         context.SetInstruction(IRInstruction.MulF, context.Result, minusOne, context.Operand1);
     }
     else if (context.Operand1.Type.Type == CilElementType.R8)
     {
         ConstantOperand minusOne = new ConstantOperand(context.Operand1.Type, -1.0);
         context.SetInstruction(IRInstruction.MulF, context.Result, minusOne, context.Operand1);
     }
     else
     {
         ConstantOperand minusOne = new ConstantOperand(context.Operand1.Type, -1L);
         context.SetInstruction(IRInstruction.MulS, context.Result, minusOne, context.Operand1);
     }
 }
Ejemplo n.º 13
0
        /// <summary>
        /// Visitation function for Ldflda instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        public void Ldflda(Context context)
        {
            Operand fieldAddress = context.Result;
            Operand objectOperand = context.Operand1;

            int offset = typeLayout.GetFieldOffset(context.RuntimeField);
            Operand fixedOffset = new ConstantOperand(BuiltInSigType.Int32, offset);

            context.SetInstruction(IRInstruction.AddU, fieldAddress, objectOperand, fixedOffset);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Decodes the specified instruction.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="decoder">The instruction decoder, which holds the code stream.</param>
        public override void Decode(Context ctx, IInstructionDecoder decoder)
        {
            // Decode base classes first
            base.Decode(ctx, decoder);

            ConstantOperand constantValueOperand;

            // Opcode specific handling
            switch (opcode)
            {
                case OpCode.Ldc_i4:
                    {
                        int i = decoder.DecodeInt();
                        constantValueOperand = new ConstantOperand(BuiltInSigType.Int32, i);
                    }
                    break;

                case OpCode.Ldc_i4_s:
                    {
                        sbyte sb = decoder.DecodeSByte();
                        constantValueOperand = new ConstantOperand(BuiltInSigType.Int32, sb);
                    }
                    break;

                case OpCode.Ldc_i8:
                    {
                        long l = decoder.DecodeLong();
                        constantValueOperand = new ConstantOperand(BuiltInSigType.Int64, l);
                    }
                    break;

                case OpCode.Ldc_r4:
                    {
                        float f = decoder.DecodeFloat();
                        constantValueOperand = new ConstantOperand(BuiltInSigType.Single, f);
                    }
                    break;

                case OpCode.Ldc_r8:
                    {
                        double d = decoder.DecodeDouble();
                        constantValueOperand = new ConstantOperand(BuiltInSigType.Double, d);
                    }
                    break;

                case OpCode.Ldnull:
                    constantValueOperand = ConstantOperand.GetNull();
                    break;

                case OpCode.Ldc_i4_0:
                    constantValueOperand = ConstantOperand.FromValue(0);
                    break;

                case OpCode.Ldc_i4_1:
                    constantValueOperand = ConstantOperand.FromValue(1);
                    break;

                case OpCode.Ldc_i4_2:
                    constantValueOperand = ConstantOperand.FromValue(2);
                    break;

                case OpCode.Ldc_i4_3:
                    constantValueOperand = ConstantOperand.FromValue(3);
                    break;

                case OpCode.Ldc_i4_4:
                    constantValueOperand = ConstantOperand.FromValue(4);
                    break;

                case OpCode.Ldc_i4_5:
                    constantValueOperand = ConstantOperand.FromValue(5);
                    break;

                case OpCode.Ldc_i4_6:
                    constantValueOperand = ConstantOperand.FromValue(6);
                    break;

                case OpCode.Ldc_i4_7:
                    constantValueOperand = ConstantOperand.FromValue(7);
                    break;

                case OpCode.Ldc_i4_8:
                    constantValueOperand = ConstantOperand.FromValue(8);
                    break;

                case OpCode.Ldc_i4_m1:
                    constantValueOperand = ConstantOperand.FromValue(-1);
                    break;

                default:
                    throw new System.NotImplementedException();
            }

            ctx.Operand1 = constantValueOperand;
            ctx.Result = decoder.Compiler.CreateTemporary(constantValueOperand.Type);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Folds the add signed.
        /// </summary>
        /// <param name="context">The context.</param>
        private void FoldAddSigned(Context context)
        {
            if (context.Ignore)
                return;

            if (!(context.Instruction is IR.AddSigned))
                return;

            Operand result = context.Result;
            ConstantOperand op1 = context.Operand1 as ConstantOperand;
            ConstantOperand op2 = context.Operand2 as ConstantOperand;

            if (op1 == null || op2 == null)
                return;

            if (result.Type.Type != op1.Type.Type || op1.Type.Type != op2.Type.Type)
                return;

            ConstantOperand constant = null;

            switch (result.Type.Type)
            {
                case CilElementType.U1: constant = new ConstantOperand(result.Type, (byte)(op1.Value) + (byte)(op2.Value)); break;
                case CilElementType.I4: constant = new ConstantOperand(result.Type, (int)(op1.Value) + (int)(op2.Value)); break;
                default: break;
            }

            if (constant != null)
            {
                AddContextResultToWorkList(context);

                context.SetInstruction(IRInstruction.Move, context.Result, constant);
            }
        }
Ejemplo n.º 16
0
 /// <summary>
 /// Determines whether the value is zero.
 /// </summary>
 /// <param name="cilElementType">Type of the cil element.</param>
 /// <param name="constantOperand">The constant operand.</param>
 /// <returns>
 /// 	<c>true</c> if the value is zero; otherwise, <c>false</c>.
 /// </returns>
 private static bool IsValueZero(Metadata.CilElementType cilElementType, ConstantOperand constantOperand)
 {
     switch (cilElementType)
     {
         case Metadata.CilElementType.Char: goto case Metadata.CilElementType.U2;
         case Metadata.CilElementType.U1: return (byte)(constantOperand.Value) == 0;
         case Metadata.CilElementType.U2: return (ushort)(constantOperand.Value) == 0;
         case Metadata.CilElementType.U4: return (int)(constantOperand.Value) == 0;
         case Metadata.CilElementType.I1: return (sbyte)(constantOperand.Value) == 0;
         case Metadata.CilElementType.I2: return (short)(constantOperand.Value) == 0;
         case Metadata.CilElementType.I4: return (int)(constantOperand.Value) == 0;
         case Metadata.CilElementType.R4: return (float)(constantOperand.Value) == 0;
         case Metadata.CilElementType.R8: return (double)(constantOperand.Value) == 0;
         case Metadata.CilElementType.I: goto case Metadata.CilElementType.I4;
         case Metadata.CilElementType.U: goto case Metadata.CilElementType.U4;
         default: goto case Metadata.CilElementType.I4;
     }
 }
Ejemplo n.º 17
0
        /// <summary>
        /// Visitation function for UnaryBranch instruction.
        /// </summary>
        /// <param name="context">The context.</param>
        public void UnaryBranch(Context context)
        {
            IBranch branch = context.Branch;

            ConditionCode cc;
            Operand first = context.Operand1;
            Operand second = new ConstantOperand(BuiltInSigType.Int32, 0UL);

            CIL.OpCode opcode = ((CIL.ICILInstruction)context.Instruction).OpCode;
            if (opcode == CIL.OpCode.Brtrue || opcode == CIL.OpCode.Brtrue_s)
            {
                cc = ConditionCode.NotEqual;
            }
            else if (opcode == CIL.OpCode.Brfalse || opcode == CIL.OpCode.Brfalse_s)
            {
                cc = ConditionCode.Equal;
            }
            else
            {
                throw new NotSupportedException(@"CILTransformationStage.UnaryBranch doesn't support CIL opcode " + opcode);
            }

            context.SetInstruction(Instruction.IntegerCompareBranchInstruction, null, first, second);
            context.ConditionCode = cc;
            context.SetBranch(branch.Targets[0]);
        }