public void IsARM64CallingConvention()
        {
            IgnoreIfNotLinkAll();
#if __WATCHOS__
            if (!Runtime.IsARM64CallingConvention && Runtime.Arch == Arch.DEVICE)
            {
                Assert.Ignore("Can't inline when running on armv7k.");
            }
#endif

#if DEBUG // Release builds will strip IL, so any IL checking has to be done in debug builds.
            MethodInfo method;
            IEnumerable <ILInstruction> instructions;
            IEnumerable <ILInstruction> call_instructions;

            method            = typeof(BaseOptimizeGeneratedCodeTest).GetMethod(nameof(GetIsARM64CallingConventionOptimized), BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static);
            instructions      = new ILReader(method);
            call_instructions = instructions.Where((v) => v.OpCode.Name == "ldsfld");
            Assert.AreEqual(0, call_instructions.Count(), "optimized: no ldsfld instruction");

            method            = typeof(BaseOptimizeGeneratedCodeTest).GetMethod(nameof(GetIsARM64CallingConventionNotOptimized), BindingFlags.NonPublic | BindingFlags.Instance);
            instructions      = new ILReader(method);
            call_instructions = instructions.Where((v) => v.OpCode.Name == "ldsfld");
            Assert.AreEqual(1, call_instructions.Count(), "not optimized: 1 ldsfld instruction");

            method       = typeof(Runtime).GetMethod("GetIsARM64CallingConvention", BindingFlags.Static | BindingFlags.NonPublic);
            instructions = new ILReader(method);
            Assert.AreEqual(2, instructions.Count(), "IL Count");
            Assert.That(instructions.Skip(0).First().OpCode, Is.EqualTo(OpCodes.Ldc_I4_0).Or.EqualTo(OpCodes.Ldc_I4_1), "IL 1");
            Assert.That(instructions.Skip(1).First().OpCode, Is.EqualTo(OpCodes.Ret), "IL 2");
#endif

            Assert.AreEqual(Runtime.IsARM64CallingConvention, GetIsARM64CallingConventionOptimized(), "Value optimized");
            Assert.AreEqual(Runtime.IsARM64CallingConvention, GetIsARM64CallingConventionNotOptimized(), "Value unoptimized");
        }
Example #2
0
        public void IntPtrSizeTest()
        {
            var S8methods = new MethodInfo []
            {
                GetType().GetMethod(nameof(Size8Test), BindingFlags.NonPublic | BindingFlags.Instance),
                GetType().GetMethod(nameof(Size8Test_Optimizable), BindingFlags.NonPublic | BindingFlags.Instance)
            };
            var S4methods = new MethodInfo []
            {
                GetType().GetMethod(nameof(Size4Test), BindingFlags.NonPublic | BindingFlags.Instance),
                GetType().GetMethod(nameof(Size4Test_Optimizable), BindingFlags.NonPublic | BindingFlags.Instance)
            };

            MethodInfo[] passingMethods = null;
            MethodInfo[] failingMethods = null;
            switch (IntPtr.Size)
            {
            case 4:
                Size4Test();
                Size4Test_Optimizable();
                passingMethods = S4methods;
                failingMethods = S8methods;
                break;

            case 8:
                Size8Test();
                Size8Test_Optimizable();
                passingMethods = S8methods;
                failingMethods = S4methods;
                break;

            default:
                Assert.Fail("Invalid size: {0}", IntPtr.Size);
                break;
            }

#if !DEBUG
            // Verify that the passing method is completely empty (save for nop instructions and a final ret instruction).
            // Unfortunately in debug mode csc produces IL sequences the optimizer doesn't understand (a lot of unnecessary instructions),
            // which means we can only check this in release mode. Also on device this will probably always pass,
            // since we strip assemblies (and the methods will always be empty), but running the test shouldn't hurt.
            foreach (var passingMethod in passingMethods)
            {
                IEnumerable <ILInstruction> passingInstructions = new ILReader(passingMethod);
                passingInstructions = passingInstructions.Where((v) => v.OpCode.Name != "nop");
                Assert.AreEqual(1, passingInstructions.Count(), "empty body");
            }
            foreach (var failingMethod in failingMethods)
            {
                IEnumerable <ILInstruction> failingInstructions = new ILReader(failingMethod);
                failingInstructions = failingInstructions.Where((v) => v.OpCode.Name != "nop");
                Assert.That(failingInstructions.Count(), Is.GreaterThan(1), "non-empty body");
            }
#endif
        }