Beispiel #1
0
        private bool TryGenerateCode(ILInstruction instruction)
        {
            switch (instruction.InstructionType)
            {
            case ILInstructionType.Nop:
                MakeNop();
                return(true);

            case ILInstructionType.Break:
                MakeTrap();
                return(true);

            case ILInstructionType.LdToken:
                MakeLoadToken(instruction.Argument);
                return(true);

            case ILInstructionType.Ldarg:
            {
                var index = instruction.GetArgumentAs <int>() -
                            LambdaArgumentOffset;
                if (index >= 0)
                {
                    LoadVariable(
                        new VariableRef(
                            index,
                            VariableRefType.Argument));
                }
            }
                return(true);

            case ILInstructionType.Ldarga:
            {
                var index = instruction.GetArgumentAs <int>() -
                            LambdaArgumentOffset;
                if (index >= 0)
                {
                    LoadVariableAddress(
                        new VariableRef(
                            index,
                            VariableRefType.Argument));
                }
            }
                return(true);

            case ILInstructionType.Starg:
            {
                var index = instruction.GetArgumentAs <int>() -
                            LambdaArgumentOffset;
                if (index >= 0)
                {
                    StoreVariable(
                        new VariableRef(
                            index,
                            VariableRefType.Argument));
                }
            }
                return(true);

            case ILInstructionType.Ldloc:
                LoadVariable(
                    new VariableRef(
                        instruction.GetArgumentAs <int>(),
                        VariableRefType.Local));
                return(true);

            case ILInstructionType.Ldloca:
                LoadVariableAddress(
                    new VariableRef(
                        instruction.GetArgumentAs <int>(),
                        VariableRefType.Local));
                return(true);

            case ILInstructionType.Stloc:
                StoreVariable(
                    new VariableRef(
                        instruction.GetArgumentAs <int>(),
                        VariableRefType.Local));
                return(true);

            case ILInstructionType.LdI4:
                Load(instruction.GetArgumentAs <int>());
                return(true);

            case ILInstructionType.LdI8:
                Load(instruction.GetArgumentAs <long>());
                return(true);

            case ILInstructionType.LdR4:
                Load(instruction.GetArgumentAs <float>());
                return(true);

            case ILInstructionType.LdR8:
                Load(instruction.GetArgumentAs <double>());
                return(true);

            case ILInstructionType.Ldstr:
                LoadString(instruction.GetArgumentAs <string>());
                return(true);

            case ILInstructionType.Dup:
                MakeDup();
                return(true);

            case ILInstructionType.Pop:
                MakePop();
                return(true);

            case ILInstructionType.Ret:
                MakeReturn();
                return(true);

            case ILInstructionType.Call:
                MakeCall(instruction.GetArgumentAs <MethodBase>());
                return(true);

            case ILInstructionType.Callvirt:
                MakeVirtualCall(instruction);
                return(true);

            case ILInstructionType.Calli:
                MakeCalli(instruction.Argument);
                return(true);

            case ILInstructionType.Jmp:
                MakeJump(instruction.GetArgumentAs <MethodBase>());
                return(true);

            case ILInstructionType.Box:
                MakeBox();
                return(true);

            case ILInstructionType.Unbox:
                MakeUnbox(instruction.GetArgumentAs <Type>());
                return(true);

            case ILInstructionType.Br:
                MakeBranch();
                return(true);

            case ILInstructionType.Brfalse:
                MakeBranchFalse();
                return(true);

            case ILInstructionType.Brtrue:
                MakeBranchTrue();
                return(true);

            case ILInstructionType.Beq:
                MakeBranch(CompareKind.Equal, instruction.Flags);
                return(true);

            case ILInstructionType.Bne:
                MakeBranch(CompareKind.NotEqual, instruction.Flags);
                return(true);

            case ILInstructionType.Bge:
                MakeBranch(CompareKind.GreaterEqual, instruction.Flags);
                return(true);

            case ILInstructionType.Bgt:
                MakeBranch(CompareKind.GreaterThan, instruction.Flags);
                return(true);

            case ILInstructionType.Ble:
                MakeBranch(CompareKind.LessEqual, instruction.Flags);
                return(true);

            case ILInstructionType.Blt:
                MakeBranch(CompareKind.LessThan, instruction.Flags);
                return(true);

            case ILInstructionType.Switch:
                MakeSwitch(instruction.GetArgumentAs <ILInstructionBranchTargets>());
                return(true);

            case ILInstructionType.Add:
                MakeArithmetic(BinaryArithmeticKind.Add, instruction);
                return(true);

            case ILInstructionType.Sub:
                MakeArithmetic(BinaryArithmeticKind.Sub, instruction);
                return(true);

            case ILInstructionType.Mul:
                MakeArithmetic(BinaryArithmeticKind.Mul, instruction);
                return(true);

            case ILInstructionType.Div:
                MakeArithmetic(BinaryArithmeticKind.Div, instruction);
                return(true);

            case ILInstructionType.Rem:
                MakeArithmetic(BinaryArithmeticKind.Rem, instruction);
                return(true);

            case ILInstructionType.And:
                MakeArithmetic(BinaryArithmeticKind.And, instruction);
                return(true);

            case ILInstructionType.Or:
                MakeArithmetic(BinaryArithmeticKind.Or, instruction);
                return(true);

            case ILInstructionType.Xor:
                MakeArithmetic(BinaryArithmeticKind.Xor, instruction);
                return(true);

            case ILInstructionType.Shl:
                MakeArithmetic(BinaryArithmeticKind.Shl, instruction);
                return(true);

            case ILInstructionType.Shr:
                MakeArithmetic(BinaryArithmeticKind.Shr, instruction);
                return(true);

            case ILInstructionType.Neg:
                MakeArithmetic(UnaryArithmeticKind.Neg);
                return(true);

            case ILInstructionType.Not:
                MakeArithmetic(UnaryArithmeticKind.Not);
                return(true);

            case ILInstructionType.Conv:
                MakeConvert(instruction.GetArgumentAs <Type>(), instruction.Flags);
                return(true);

            case ILInstructionType.Initobj:
                MakeInitObject(instruction.GetArgumentAs <Type>());
                return(true);

            case ILInstructionType.Newobj:
                MakeNewObject(instruction.GetArgumentAs <MethodBase>());
                return(true);

            case ILInstructionType.Isinst:
                MakeIsInstance(instruction.GetArgumentAs <Type>());
                return(true);

            case ILInstructionType.Ldfld:
                MakeLoadField(instruction.GetArgumentAs <FieldInfo>());
                return(true);

            case ILInstructionType.Ldsfld:
                MakeLoadStaticField(instruction.GetArgumentAs <FieldInfo>());
                return(true);

            case ILInstructionType.Ldflda:
                MakeLoadFieldAddress(instruction.GetArgumentAs <FieldInfo>());
                return(true);

            case ILInstructionType.Ldsflda:
                MakeLoadStaticFieldAddress(instruction.GetArgumentAs <FieldInfo>());
                return(true);

            case ILInstructionType.Stfld:
                MakeStoreField(instruction.GetArgumentAs <FieldInfo>());
                return(true);

            case ILInstructionType.Stsfld:
                MakeStoreStaticField(instruction.GetArgumentAs <FieldInfo>());
                return(true);

            case ILInstructionType.Ceq:
                MakeCompare(CompareKind.Equal, instruction.Flags);
                return(true);

            case ILInstructionType.Cgt:
                MakeCompare(CompareKind.GreaterThan, instruction.Flags);
                return(true);

            case ILInstructionType.Clt:
                MakeCompare(CompareKind.LessThan, instruction.Flags);
                return(true);

            case ILInstructionType.Ldobj:
            case ILInstructionType.Ldind:
                MakeLoadObject(instruction.GetArgumentAs <Type>());
                return(true);

            case ILInstructionType.Stobj:
            case ILInstructionType.Stind:
                MakeStoreObject(instruction.GetArgumentAs <Type>());
                return(true);

            case ILInstructionType.Newarr:
                MakeNewArray(instruction.GetArgumentAs <Type>());
                return(true);

            case ILInstructionType.Ldelem:
                MakeLoadElement(instruction.GetArgumentAs <Type>());
                return(true);

            case ILInstructionType.Ldelema:
                MakeLoadElementAddress(instruction.GetArgumentAs <Type>());
                return(true);

            case ILInstructionType.Stelem:
                MakeStoreElement(instruction.GetArgumentAs <Type>());
                return(true);

            case ILInstructionType.Ldlen:
                MakeLoadArrayLength();
                return(true);

            case ILInstructionType.SizeOf:
                LoadSizeOf(instruction.GetArgumentAs <Type>());
                return(true);

            default:
                return(false);
            }
        }
Beispiel #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 = 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)
                {
                    // Check the size of the element type and devide the raw offset
                    // by the element size to retrieve the actual element index.
                    var elementType = left.Type.As <PointerType>(Location).ElementType;
                    var elementSize = Builder.CreateSizeOf(Location, elementType);

                    // Create the actual address computation
                    var leaIndex = Builder.CreateArithmetic(
                        Location,
                        right,
                        elementSize,
                        BinaryArithmeticKind.Div);
                    result = Builder.CreateLoadElementAddress(
                        Location,
                        left,
                        leaIndex);
                }
                // 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);
        }