Exemplo n.º 1
0
        /// <summary>
        /// Realizes an arithmetic operation.
        /// </summary>
        /// <param name="block">The current basic block.</param>
        /// <param name="builder">The current builder.</param>
        /// <param name="kind">The kind of the arithmetic operation.</param>
        /// <param name="instruction">The current IL instruction.</param>
        private static void MakeArithmetic(
            Block block,
            IRBuilder builder,
            BinaryArithmeticKind kind,
            ILInstruction instruction)
        {
            var arithmeticFlags = ArithmeticFlags.None;
            var convertFlags    = ConvertFlags.None;

            if (instruction.HasFlags(ILInstructionFlags.Overflow))
            {
                arithmeticFlags |= ArithmeticFlags.Overflow;
            }
            if (instruction.HasFlags(ILInstructionFlags.Unsigned))
            {
                convertFlags    |= ConvertFlags.TargetUnsigned;
                arithmeticFlags |= ArithmeticFlags.Unsigned;
            }
            block.PopArithmeticArgs(convertFlags, out Value left, out Value right);
            switch (kind)
            {
            case BinaryArithmeticKind.Shl:
            case BinaryArithmeticKind.Shr:
                // Convert right operand to 32bits
                right = CreateConversion(
                    builder,
                    right,
                    builder.GetPrimitiveType(BasicValueType.Int32),
                    convertFlags);
                break;
            }
            var arithmetic = builder.CreateArithmetic(left, right, kind, arithmeticFlags);

            block.Push(arithmetic);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Realizes an arithmetic operation.
        /// </summary>
        /// <param name="kind">The kind of the arithmetic operation.</param>
        /// <param name="instruction">The current IL instruction.</param>
        private void MakeArithmetic(
            BinaryArithmeticKind kind,
            ILInstruction instruction)
        {
            var arithmeticFlags = ArithmeticFlags.None;
            var convertFlags    = ConvertFlags.None;

            if (instruction.HasFlags(ILInstructionFlags.Overflow))
            {
                arithmeticFlags |= ArithmeticFlags.Overflow;
            }
            if (instruction.HasFlags(ILInstructionFlags.Unsigned))
            {
                convertFlags    |= ConvertFlags.TargetUnsigned;
                arithmeticFlags |= ArithmeticFlags.Unsigned;
            }

            ValueReference result;

            if (Block.PopArithmeticArgs(
                    Location,
                    convertFlags,
                    out var left,
                    out var right) == Block.ArithmeticOperandKind.Pointer)
            {
                // This is a pointer access
                bool isLeftPointer = left.Type.IsPointerType;
                if (!isLeftPointer)
                {
                    Utilities.Swap(ref left, ref right);
                }

                if (kind != BinaryArithmeticKind.Add || right.Type.IsPointerType)
                {
                    throw Location.GetNotSupportedException(
                              ErrorMessages.NotSupportedArithmeticArgumentType,
                              kind);
                }
                result = Builder.CreateLoadElementAddress(
                    Location,
                    left,
                    right);
            }
Exemplo n.º 3
0
        /// <summary>
        /// Realizes a virtual-call instruction.
        /// </summary>
        /// <param name="instruction">The current IL instruction.</param>
        private void MakeVirtualCall(ILInstruction instruction)
        {
            var method = instruction.GetArgumentAs <MethodInfo>();

            if (instruction.HasFlags(ILInstructionFlags.Constrained))
            {
                MakeVirtualCall(
                    method,
                    instruction.FlagsContext.Argument as Type);
            }
            else
            {
                MakeVirtualCall(method, null);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Realizes an arithmetic operation.
        /// </summary>
        /// <param name="kind">The kind of the arithmetic operation.</param>
        /// <param name="instruction">The current IL instruction.</param>
        private void MakeArithmetic(
            BinaryArithmeticKind kind,
            ILInstruction instruction)
        {
            var arithmeticFlags = ArithmeticFlags.None;
            var convertFlags    = ConvertFlags.None;

            if (instruction.HasFlags(ILInstructionFlags.Overflow))
            {
                arithmeticFlags |= ArithmeticFlags.Overflow;
            }
            if (instruction.HasFlags(ILInstructionFlags.Unsigned))
            {
                convertFlags    |= ConvertFlags.TargetUnsigned;
                arithmeticFlags |= ArithmeticFlags.Unsigned;
            }

            ValueReference result = default;

            if (Block.PopArithmeticArgs(
                    Location,
                    convertFlags,
                    out var left,
                    out var right) == Block.ArithmeticOperandKind.Pointer)
            {
                // This is a pointer access
                bool isLeftPointer = left.Type.IsPointerType;
                if (!isLeftPointer)
                {
                    Utilities.Swap(ref left, ref right);
                }

                // Check for raw combinations of two pointer values
                if (
                    !right.Type.IsPointerType &&
                    // Check whether this can be safely converted into a LEA value
                    kind == BinaryArithmeticKind.Add)
                {
                    result = Builder.CreateLoadElementAddress(
                        Location,
                        left,
                        right);
                }
                // Check whether this operation on pointer values can be converted
                // into a LEA instruction
                // FIXME: remove this code once we add additional LEA nodes
                else if (
                    kind == BinaryArithmeticKind.Add &&
                    right is BinaryArithmeticValue baseAddress &&
                    TryConvertIntoLoadElementAddress(left, baseAddress, out var lea))
                {
                    result = lea;
                }
            }

            if (!result.IsValid)
            {
                switch (kind)
                {
                case BinaryArithmeticKind.Shl:
                case BinaryArithmeticKind.Shr:
                    // Convert right operand to 32bits
                    right = CreateConversion(
                        right,
                        Builder.GetPrimitiveType(BasicValueType.Int32),
                        convertFlags);
                    break;
                }
                result = Builder.CreateArithmetic(
                    Location,
                    left,
                    right,
                    kind,
                    arithmeticFlags);
            }
            Block.Push(result);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Realizes an arithmetic operation.
        /// </summary>
        /// <param name="kind">The kind of the arithmetic operation.</param>
        /// <param name="instruction">The current IL instruction.</param>
        private void MakeArithmetic(
            BinaryArithmeticKind kind,
            ILInstruction instruction)
        {
            var arithmeticFlags = ArithmeticFlags.None;
            var convertFlags    = ConvertFlags.None;

            if (instruction.HasFlags(ILInstructionFlags.Overflow))
            {
                arithmeticFlags |= ArithmeticFlags.Overflow;
            }
            if (instruction.HasFlags(ILInstructionFlags.Unsigned))
            {
                convertFlags    |= ConvertFlags.TargetUnsigned;
                arithmeticFlags |= ArithmeticFlags.Unsigned;
            }

            ValueReference result = default;

            if (Block.PopArithmeticArgs(
                    Location,
                    convertFlags,
                    out var left,
                    out var right) == Block.ArithmeticOperandKind.Pointer)
            {
                // This is a pointer access
                bool isLeftPointer = left.Type.IsPointerType;
                if (!isLeftPointer)
                {
                    Utilities.Swap(ref left, ref right);
                }

                // Check for raw combinations of two pointer values
                if (
                    !right.Type.IsPointerType &&
                    // Check whether this can be safely converted into a LEA value
                    kind == BinaryArithmeticKind.Add)
                {
                    result = Builder.CreateLoadElementAddress(
                        Location,
                        left,
                        right);
                }
                // Check whether this operation on pointer values can be converted
                // into a LEA instruction
                // FIXME: remove this code once we add additional LEA nodes
                else if (
                    kind == BinaryArithmeticKind.Add &&
                    right is BinaryArithmeticValue baseAddress &&
                    baseAddress.Kind == BinaryArithmeticKind.Mul &&
                    // Extract the element stride from the multiplication pattern
                    // (must be the right operand since we have moved all pointer
                    // values the left hand side by definition)
                    TryGetBasicValueSize(baseAddress.Right, out var strideType))
                {
                    // Cast raw pointer into an appropriate target type
                    var targetElementType = Builder.GetPrimitiveType(strideType);
                    left = Builder.CreatePointerCast(
                        Location,
                        left,
                        targetElementType);
                    result = Builder.CreateLoadElementAddress(
                        Location,
                        left,
                        baseAddress.Left);
                }
            }

            if (!result.IsValid)
            {
                switch (kind)
                {
                case BinaryArithmeticKind.Shl:
                case BinaryArithmeticKind.Shr:
                    // Convert right operand to 32bits
                    right = CreateConversion(
                        right,
                        Builder.GetPrimitiveType(BasicValueType.Int32),
                        convertFlags);
                    break;
                }
                result = Builder.CreateArithmetic(
                    Location,
                    left,
                    right,
                    kind,
                    arithmeticFlags);
            }
            Block.Push(result);
        }