Revert "Revert "Merge branch 'master' of https://github.com/mono/mono""
authorRolf Bjarne Kvinge <rolf@xamarin.com>
Fri, 25 Apr 2014 14:57:01 +0000 (16:57 +0200)
committerRolf Bjarne Kvinge <rolf@xamarin.com>
Fri, 25 Apr 2014 14:57:01 +0000 (16:57 +0200)
This reverts commit 8f09dad4353bb75afebf96ad58d08f7e7f3bf56d.

8f09dad4353bb75afebf96ad58d08f7e7f3bf56d is reverting a merge commit,
which will not do what you think it does. It will revert much more,
so revert the revert to get back the unintentionally reverted commits.

It looks like the next commit (1a15d4ec541eaf20ed78eac53149b1b83e1450fe)
is doing the original intention (reverting 164f9cbec4f79cc013c7b1cf674e70e4573f4b36),
so this revert will leave the tree in a good state, with no pending
reverts.

52 files changed:
acinclude.m4
configure.in
eglib/configure.ac
mcs/class/Mono.CSharp/monotouch.cs
mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs
mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/StepEventRequest.cs
mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs
mcs/class/Mono.Debugger.Soft/Test/dtest.cs
mcs/class/System.Core/System/TimeZoneInfo.cs
mcs/class/System.Core/Test/System/TimeZoneInfoTest.cs
mcs/class/System/System.Net/HttpWebResponse.cs
mono/arch/Makefile.am
mono/arch/arm64/Makefile.am [new file with mode: 0644]
mono/arch/arm64/arm64-codegen.h [new file with mode: 0644]
mono/metadata/domain-internals.h
mono/metadata/mono-config.c
mono/metadata/sgen-archdep.h
mono/metadata/sgen-stw.c
mono/mini/Makefile.am.in
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/cpu-arm64.md [new file with mode: 0644]
mono/mini/debugger-agent.c
mono/mini/exceptions-arm64.c [new file with mode: 0644]
mono/mini/genmdesc.pl
mono/mini/helpers.c
mono/mini/image-writer.c
mono/mini/method-to-ir.c
mono/mini/mini-arch.h
mono/mini/mini-arm64.c [new file with mode: 0644]
mono/mini/mini-arm64.h [new file with mode: 0644]
mono/mini/mini-codegen.c
mono/mini/mini-gc.c
mono/mini/mini-ops.h
mono/mini/mini-trampolines.c
mono/mini/mini.c
mono/mini/mini.h
mono/mini/tramp-arm64.c [new file with mode: 0644]
mono/mini/unwind.c
mono/tests/Makefile.am
mono/utils/Makefile.am
mono/utils/mach-support-arm.c
mono/utils/mach-support.h
mono/utils/mono-codeman.c
mono/utils/mono-compiler.h
mono/utils/mono-context.c
mono/utils/mono-context.h
mono/utils/mono-hwcap-arm64.c [new file with mode: 0644]
mono/utils/mono-hwcap-arm64.h [new file with mode: 0644]
mono/utils/mono-sigcontext.h
mono/utils/mono-threads-mach-helper.c
mono/utils/mono-threads-mach.c

index 5b38b2fe3ef8108083daa3a4b959b5f5b795c029..16fecf7f8608938102a35d90aadc6319ada10d17 100644 (file)
@@ -23,7 +23,7 @@ if test x$GCC != xyes; then
 fi
 case $host in
 i?86-*-linux*|x86_64-*-linux*|powerpc-*-linux*|powerpc64-*-linux* \
-|amd64-*-freebsd*|i?86-*-freebsd*|ia64-*-freebsd*|arm*-*-linux*|sparc*-*-linux*|mips*-*-linux*|x86_64-apple-darwin*)
+|amd64-*-freebsd*|i?86-*-freebsd*|ia64-*-freebsd*|arm*-*-linux*|sparc*-*-linux*|mips*-*-linux*|x86_64-apple-darwin*|aarch64*)
     pic_options='-fPIC'
     ;;
 ?86-pc-cygwin*|i?86-pc-cygwin*)
index dd09f8fa3c776e0ca0051bd2af4359e86da78d31..1f1e4ffc1f4cf0b1e574828ba52ebae23450fdd5 100644 (file)
@@ -237,6 +237,12 @@ case "$host" in
                        # available during cross-compilation
                        mono_cv_uscore=no
                 fi
+               case "$host" in
+               aarch64-*)
+                       support_boehm=no
+                       with_gc=sgen
+                       ;;
+               esac
                ;;
        *-*-nacl*)
                host_win32=no
@@ -2507,6 +2513,7 @@ sizeof_register="SIZEOF_VOID_P"
 jit_wanted=true
 interp_wanted=false
 sgen_supported=false
+boehm_supported=true
 case "$host" in
        mips*)
                TARGET=MIPS;
@@ -2683,6 +2690,14 @@ case "$host" in
 #              sgen_supported=true
 #              AOT_SUPPORTED="no"
 #              ;;
+       aarch64-*)
+               # https://lkml.org/lkml/2012/7/15/133
+               TARGET=ARM64
+               arch_target=arm64
+               JIT_SUPPORTED=yes
+               sgen_supported=true
+               boehm_supported=false
+               ;;
        s390x-*-linux*)
                TARGET=S390X;
                arch_target=s390x;
@@ -2788,6 +2803,11 @@ if test "x$host" != "x$target"; then
                        ;;
                esac
                ;;
+       aarch64-*)
+               TARGET=ARM64
+               JIT_SUPPORTED=yes
+               jit_wanted=true
+               ;;
        *)
                AC_MSG_ERROR([Cross compiling is not supported for target $target])
        esac
@@ -2803,6 +2823,9 @@ AMD64)
 ARM)
        AC_DEFINE(TARGET_ARM, 1, [...])
        ;;
+ARM64)
+       AC_DEFINE(TARGET_ARM64, 1, [...])
+       ;;
 POWERPC)
        AC_DEFINE(TARGET_POWERPC, 1, [...])
        ;;
@@ -2830,14 +2853,14 @@ esac
 dnl Use GCC atomic ops if they work on the target.
 if test x$GCC = "xyes"; then
        case $TARGET in
-       X86 | AMD64 | ARM | POWERPC | POWERPC64 | MIPS | S390X | SPARC | SPARC64)
+       X86 | AMD64 | ARM | ARM64 | POWERPC | POWERPC64 | MIPS | S390X | SPARC | SPARC64)
                AC_DEFINE(USE_GCC_ATOMIC_OPS, 1, [...])
                ;;
        esac
 fi
 
 if test "x$target_mach" = "xyes"; then
-   if test "x$TARGET" = "xARM"; then
+   if test "x$TARGET" = "xARM" -o "x$TARGET" = "xARM64"; then
          AC_DEFINE(TARGET_IOS,1,[The JIT/AOT targets iOS])
          CPPFLAGS_FOR_LIBGC="$CPPFLAGS_FOR_LIBGC -DTARGET_IOS"
          CFLAGS_FOR_LIBGC="$CFLAGS_FOR_LIBGC -DTARGET_IOS"
@@ -3304,10 +3327,12 @@ AM_CONDITIONAL(MIPS, test x$TARGET = xMIPS)
 AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC)
 AM_CONDITIONAL(POWERPC64, test x$TARGET = xPOWERPC64)
 AM_CONDITIONAL(ARM, test x$TARGET = xARM)
+AM_CONDITIONAL(ARM64, test x$TARGET = xARM64)
 AM_CONDITIONAL(S390X, test x$TARGET = xS390X)
 AM_CONDITIONAL(HOST_X86, test x$HOST = xX86)
 AM_CONDITIONAL(HOST_AMD64, test x$HOST = xAMD64)
 AM_CONDITIONAL(HOST_ARM, test x$HOST = xARM)
+AM_CONDITIONAL(HOST_ARM64, test x$HOST = xARM64)
 AM_CONDITIONAL(CROSS_COMPILE, test "x$host" != "x$target")
 
 AM_CONDITIONAL(JIT_SUPPORTED, test x$JIT_SUPPORTED = xyes)
@@ -3526,6 +3551,7 @@ mono/arch/ppc/Makefile
 mono/arch/sparc/Makefile
 mono/arch/s390x/Makefile
 mono/arch/arm/Makefile
+mono/arch/arm64/Makefile
 mono/arch/ia64/Makefile
 mono/arch/mips/Makefile
 mono/interpreter/Makefile
index fdbce134b9767857b4641d0991cf384fc9911696..f8853385a8df8bd94d3abbf83b767a94cc4c00e1 100644 (file)
@@ -88,7 +88,7 @@ case $host in
 esac
 
 case $target in
-arm*-darwin*)
+arm*-darwin*|aarch64*-*)
     CFLAGS="$CFLAGS -U_FORTIFY_SOURCE"
     ;;
 i*86-*-darwin*)
index fed14757214c04e26c51000b3724149f6c1b1e49..a8260819907e8cef35ea7e90ed327970965f6c00 100644 (file)
@@ -40,6 +40,11 @@ namespace System.Reflection.Emit
                        throw new NotSupportedException ();
                }
 
+               public void BeginExceptFilterBlock ()
+               {
+                       throw new NotSupportedException ();
+               }
+
                public void BeginFinallyBlock ()
                {
                        throw new NotSupportedException ();
index 7b69efb22b8ff5e5564f87e1932dad310f1903ee..60b7e2c384ca72c99479b4d5d4ce6aa55aa807ab 100644 (file)
@@ -411,7 +411,7 @@ namespace Mono.Debugger.Soft
                 * with newer runtimes, and vice versa.
                 */
                internal const int MAJOR_VERSION = 2;
-               internal const int MINOR_VERSION = 29;
+               internal const int MINOR_VERSION = 30;
 
                enum WPSuspendPolicy {
                        NONE = 0,
index 035fbcee56df096c804a3b8de2989ca9db83a9d8..3bf93807ae5e84dfe70c77456123f3b36badcb43 100644 (file)
@@ -28,6 +28,9 @@ namespace Mono.Debugger.Soft
                /* Since protocol version 2.26 */
                /* Methods which have the [DebuggerStepThrough] attribute */
                DebuggerStepThrough = 4,
+               /* Since protocol version 2.30 */
+               /* Methods which have the [DebuggerNonUserCode] attribute */
+               DebuggerNonUserCode = 8
        }
 
        public sealed class StepEventRequest : EventRequest {
index 194b436f080076b9f3b8ce01d632fa50445ec0b4..4397ab005bf734def18df0a05a93f029578723b6 100644 (file)
@@ -362,6 +362,7 @@ public class Tests : TestsBase, ITest2
                ss_nested ();
                ss_regress_654694 ();
                ss_step_through ();
+               ss_non_user_code ();
                ss_recursive (1);
                ss_fp_clobber ();
        }
@@ -481,6 +482,30 @@ public class Tests : TestsBase, ITest2
        public static void step_through_3 () {
        }
 
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void ss_non_user_code () {
+               non_user_code_1 ();
+               StepNonUserCodeClass.non_user_code_2 ();
+               non_user_code_3 ();
+       }
+
+       [DebuggerNonUserCode]
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void non_user_code_1 () {
+       }
+
+       [DebuggerNonUserCode]
+       class StepNonUserCodeClass {
+               [MethodImplAttribute (MethodImplOptions.NoInlining)]
+               public static void non_user_code_2 () {
+               }
+       }
+
+       [DebuggerNonUserCode]
+       [MethodImplAttribute (MethodImplOptions.NoInlining)]
+       public static void non_user_code_3 () {
+       }
+
        [MethodImplAttribute (MethodImplOptions.NoInlining)]
        public static void ss_recursive (int n) {
                if (n == 10)
index 901d56adc9207d5c5eb9ea949ef84c1f96899627..86e533b4aead6f55d19a0eb44551b6a92e8464d0 100644 (file)
@@ -542,6 +542,23 @@ public class DebuggerTests
                assert_location (e, "step_through_3");
                req.Disable ();
 
+               // Check DebuggerNonUserCode support
+               e = run_until ("ss_non_user_code");
+               req = create_step (e);
+               req.Filter = StepFilter.DebuggerNonUserCode;
+               e = step_into ();
+               // Step through non_user_code_1 ()
+               e = step_into ();
+               assert_location (e, "ss_non_user_code");
+               // Step through StepThroughClass.non_user_code_2 ()
+               e = step_into ();
+               assert_location (e, "ss_non_user_code");
+               req.Disable ();
+               req.Filter = StepFilter.None;
+               e = step_into ();
+               assert_location (e, "non_user_code_3");
+               req.Disable ();
+
                // Check that step-over doesn't stop at inner frames with recursive functions
                e = run_until ("ss_recursive");
                req = create_step (e);
index 4dbaf3eeb885d75e757cb47be56a5e99575c5459..bdcda5654690c0ce670dcd414a2c6c0c3892069b 100644 (file)
@@ -227,36 +227,38 @@ namespace System
 
                public static DateTime ConvertTime (DateTime dateTime, TimeZoneInfo destinationTimeZone)
                {
-                       return ConvertTime (dateTime, TimeZoneInfo.Local, destinationTimeZone);
+                       return ConvertTime (dateTime, dateTime.Kind == DateTimeKind.Utc ? TimeZoneInfo.Utc : TimeZoneInfo.Local, destinationTimeZone);
                }
 
                public static DateTime ConvertTime (DateTime dateTime, TimeZoneInfo sourceTimeZone, TimeZoneInfo destinationTimeZone)
                {
+                       if (sourceTimeZone == null)
+                               throw new ArgumentNullException ("sourceTimeZone");
+
+                       if (destinationTimeZone == null)
+                               throw new ArgumentNullException ("destinationTimeZone");
+                       
                        if (dateTime.Kind == DateTimeKind.Local && sourceTimeZone != TimeZoneInfo.Local)
                                throw new ArgumentException ("Kind property of dateTime is Local but the sourceTimeZone does not equal TimeZoneInfo.Local");
 
                        if (dateTime.Kind == DateTimeKind.Utc && sourceTimeZone != TimeZoneInfo.Utc)
                                throw new ArgumentException ("Kind property of dateTime is Utc but the sourceTimeZone does not equal TimeZoneInfo.Utc");
-
+                       
                        if (sourceTimeZone.IsInvalidTime (dateTime))
                                throw new ArgumentException ("dateTime parameter is an invalid time");
 
-                       if (sourceTimeZone == null)
-                               throw new ArgumentNullException ("sourceTimeZone");
-
-                       if (destinationTimeZone == null)
-                               throw new ArgumentNullException ("destinationTimeZone");
-
                        if (dateTime.Kind == DateTimeKind.Local && sourceTimeZone == TimeZoneInfo.Local && destinationTimeZone == TimeZoneInfo.Local)
                                return dateTime;
 
                        DateTime utc = ConvertTimeToUtc (dateTime);
 
-                       if (destinationTimeZone == TimeZoneInfo.Utc)
-                               return utc;
-
-                       return ConvertTimeFromUtc (utc, destinationTimeZone);   
-
+                       if (destinationTimeZone != TimeZoneInfo.Utc) {
+                               utc = ConvertTimeFromUtc (utc, destinationTimeZone);
+                               if (dateTime.Kind == DateTimeKind.Unspecified)
+                                       return DateTime.SpecifyKind (utc, DateTimeKind.Unspecified);
+                       }
+                       
+                       return utc;
                }
 
                public static DateTimeOffset ConvertTime(DateTimeOffset dateTimeOffset, TimeZoneInfo destinationTimeZone) 
@@ -311,7 +313,6 @@ namespace System
 
 
                        AdjustmentRule rule = GetApplicableRule (dateTime);
-               
                        if (rule != null && IsDaylightSavingTime (DateTime.SpecifyKind (dateTime, DateTimeKind.Utc)))
                                return DateTime.SpecifyKind (dateTime + BaseUtcOffset + rule.DaylightDelta , DateTimeKind.Unspecified);
                        else
@@ -754,6 +755,18 @@ namespace System
                        throw new NotImplementedException ();
                }
 
+               bool IsInDSTForYear (AdjustmentRule rule, DateTime dateTime, int year)
+               {
+                       DateTime DST_start = TransitionPoint (rule.DaylightTransitionStart, year);
+                       DateTime DST_end = TransitionPoint (rule.DaylightTransitionEnd, year + ((rule.DaylightTransitionStart.Month < rule.DaylightTransitionEnd.Month) ? 0 : 1));
+                       if (dateTime.Kind == DateTimeKind.Utc) {
+                               DST_start -= BaseUtcOffset;
+                               DST_end -= (BaseUtcOffset + rule.DaylightDelta);
+                       }
+
+                       return (dateTime >= DST_start && dateTime < DST_end);
+               }
+               
                public bool IsDaylightSavingTime (DateTime dateTime)
                {
                        if (dateTime.Kind == DateTimeKind.Local && IsInvalidTime (dateTime))
@@ -761,29 +774,28 @@ namespace System
 
                        if (this == TimeZoneInfo.Utc)
                                return false;
-
+                       
                        if (!SupportsDaylightSavingTime)
                                return false;
+                       
                        //FIXME: do not rely on DateTime implementation !
                        if ((dateTime.Kind == DateTimeKind.Local || dateTime.Kind == DateTimeKind.Unspecified) && this == TimeZoneInfo.Local)
                                return dateTime.IsDaylightSavingTime ();
-
+                       
                        //FIXME: do not rely on DateTime implementation !
                        if (dateTime.Kind == DateTimeKind.Local && this != TimeZoneInfo.Utc)
                                return IsDaylightSavingTime (DateTime.SpecifyKind (dateTime.ToUniversalTime (), DateTimeKind.Utc));
-                               
+                       
                        AdjustmentRule rule = GetApplicableRule (dateTime.Date);
                        if (rule == null)
                                return false;
 
-                       DateTime DST_start = TransitionPoint (rule.DaylightTransitionStart, dateTime.Year);
-                       DateTime DST_end = TransitionPoint (rule.DaylightTransitionEnd, dateTime.Year + ((rule.DaylightTransitionStart.Month < rule.DaylightTransitionEnd.Month) ? 0 : 1));
-                       if (dateTime.Kind == DateTimeKind.Utc) {
-                               DST_start -= BaseUtcOffset;
-                               DST_end -= (BaseUtcOffset + rule.DaylightDelta);
-                       }
+                       // Check whether we're in the dateTime year's DST period
+                       if (IsInDSTForYear (rule, dateTime, dateTime.Year))
+                               return true;
 
-                       return (dateTime >= DST_start && dateTime < DST_end);
+                       // We might be in the dateTime previous year's DST period
+                       return IsInDSTForYear (rule, dateTime, dateTime.Year - 1);
                }
 
                public bool IsDaylightSavingTime (DateTimeOffset dateTimeOffset)
index d6a66d79ba77ac02da5d178fbe63b6c54bc6246d..f6ea66e98c69321b32c060c184913b9fb3a832fe 100644 (file)
@@ -263,6 +263,30 @@ namespace MonoTests.System
                                }
                        }
                #endif
+                       [Test (Description="Description xambug #17155")]
+                       public void AdjustmentRuleAfterNewYears ()
+                       {
+                               TimeZoneInfo tz;
+                               if (Environment.OSVersion.Platform == PlatformID.Unix)
+                                       tz = TimeZoneInfo.FindSystemTimeZoneById ("Pacific/Auckland"); // *nix
+                               else
+                                       tz = TimeZoneInfo.FindSystemTimeZoneById ("New Zealand Standard Time"); // Windows
+
+                               // DST start: 9/29/2013 2:00:00 AM
+                               // DST end: 4/6/2014 3:00:00 AM
+                               DateTime dt = new DateTime (2014, 1, 9, 23, 0, 0, DateTimeKind.Utc);
+                               Assert.IsTrue (tz.IsDaylightSavingTime (dt), "#1.1");
+
+                               // DST start: 9/29/2014 2:00:00 AM
+                               // DST end: 4/6/2015 3:00:00 AM
+                               dt = new DateTime (2014, 6, 9, 23, 0, 0, DateTimeKind.Utc);
+                               Assert.IsFalse (tz.IsDaylightSavingTime (dt), "#2.1");
+
+                               // DST start: 9/29/2014 2:00:00 AM
+                               // DST end: 4/6/2015 3:00:00 AM
+                               dt = new DateTime (2014, 10, 9, 23, 0, 0, DateTimeKind.Utc);
+                               Assert.IsTrue (tz.IsDaylightSavingTime (dt), "#3.1");
+                       }
                }
                
                [TestFixture]
@@ -412,6 +436,89 @@ namespace MonoTests.System
 
                                TimeZoneInfo.ConvertTime (DateTime.Now, TimeZoneInfo.FindSystemTimeZoneById("Pacific/Auckland"));
                        }
+
+                       [Test]
+                       [ExpectedException (typeof (ArgumentNullException))]
+                       public void ConvertTime_DateTime_TimeZoneInfo_DestinationTimeZoneIsNull ()
+                       {
+                               TimeZoneInfo.ConvertTime (DateTime.Now, null);
+                       }
+
+                       [Test]
+                       public void ConvertTime_DateTime_TimeZoneInfo_DateTimeKindMatch ()
+                       {
+                               var sdt = new DateTime (2014, 1, 9, 23, 0, 0, DateTimeKind.Utc);
+                               var ddt = TimeZoneInfo.ConvertTime (sdt, TimeZoneInfo.Utc);
+                               Assert.AreEqual (ddt.Kind, sdt.Kind, "#1.1");
+                               Assert.AreEqual (ddt.Kind, DateTimeKind.Utc, "#1.2");
+                               
+                               sdt = new DateTime (2014, 1, 9, 23, 0, 0, DateTimeKind.Local);
+                               ddt = TimeZoneInfo.ConvertTime (sdt, TimeZoneInfo.Local);
+                               Assert.AreEqual (ddt.Kind, sdt.Kind, "#2.1");
+                               Assert.AreEqual (ddt.Kind, DateTimeKind.Local, "#2.2");
+
+                               sdt = new DateTime (2014, 1, 9, 23, 0, 0);
+                               ddt = TimeZoneInfo.ConvertTime (sdt, TimeZoneInfo.Local);
+                               Assert.AreEqual (ddt.Kind, sdt.Kind, "#3.1");
+                               Assert.AreEqual (ddt.Kind, DateTimeKind.Unspecified, "#3.2");
+                       }
+
+                       [Test]
+                       [ExpectedException (typeof (ArgumentNullException))]
+                       public void ConverTime_DateTime_TimeZoneInfo_TimeZoneInfo_SourceTimeZoneIsNull ()
+                       {
+                               TimeZoneInfo.ConvertTime (DateTime.Now, null, TimeZoneInfo.Local);
+                       }
+
+                       [Test]
+                       [ExpectedException (typeof (ArgumentNullException))]
+                       public void ConverTime_DateTime_TimeZoneInfo_TimeZoneInfo_DestinationTimeZoneIsNull ()
+                       {
+                               TimeZoneInfo.ConvertTime (DateTime.Now, TimeZoneInfo.Utc, null);
+                       }
+
+                       [Test (Description="Fix for xambug https://bugzilla.xamarin.com/show_bug.cgi?id=17155")]
+                       public void ConvertTime_AdjustmentRuleAfterNewYears ()
+                       {
+                               TimeZoneInfo tz;
+                               if (Environment.OSVersion.Platform == PlatformID.Unix)
+                                       tz = TimeZoneInfo.FindSystemTimeZoneById ("Pacific/Auckland"); // *nix
+                               else
+                                       tz = TimeZoneInfo.FindSystemTimeZoneById ("New Zealand Standard Time"); // Windows
+
+                               // DST start: 9/29/2013 2:00:00 AM
+                               // DST end: 4/6/2014 3:00:00 AM
+                               DateTime sdt = new DateTime (2014, 1, 9, 23, 0, 0, DateTimeKind.Utc);
+                               DateTime ddt = TimeZoneInfo.ConvertTime (sdt, tz);
+                               Assert.AreEqual (10, ddt.Day, "#1.1");
+                               Assert.AreEqual (1, ddt.Month, "#1.2");
+                               Assert.AreEqual (2014, ddt.Year, "#1.3");
+                               Assert.AreEqual (12, ddt.Hour, "#1.4");
+                               Assert.AreEqual (0, ddt.Minute, "#1.5");
+                               Assert.AreEqual (0, ddt.Second, "#1.6");
+                               
+                               // DST start: 9/29/2014 2:00:00 AM
+                               // DST end: 4/6/2015 3:00:00 AM
+                               sdt = new DateTime (2014, 6, 9, 23, 0, 0, DateTimeKind.Utc);
+                               ddt = TimeZoneInfo.ConvertTime (sdt, tz);
+                               Assert.AreEqual (10, ddt.Day, "#2.1");
+                               Assert.AreEqual (6, ddt.Month, "#2.2");
+                               Assert.AreEqual (2014, ddt.Year, "#2.3");
+                               Assert.AreEqual (11, ddt.Hour, "#2.4");
+                               Assert.AreEqual (0, ddt.Minute, "#2.5");
+                               Assert.AreEqual (0, ddt.Second, "#2.6");
+                               
+                               // DST start: 9/29/2014 2:00:00 AM
+                               // DST end: 4/6/2015 3:00:00 AM
+                               sdt = new DateTime (2014, 10, 9, 23, 0, 0, DateTimeKind.Utc);
+                               ddt = TimeZoneInfo.ConvertTime (sdt, tz);
+                               Assert.AreEqual (10, ddt.Day, "#3.1");
+                               Assert.AreEqual (10, ddt.Month, "#3.2");
+                               Assert.AreEqual (2014, ddt.Year, "#3.3");
+                               Assert.AreEqual (12, ddt.Hour, "#3.4");
+                               Assert.AreEqual (0, ddt.Minute, "#3.5");
+                               Assert.AreEqual (0, ddt.Second, "#3.6");
+                       }
                }
                
                [TestFixture]
index 2b756a97bd1e513400a25f64f3484ddc7e40f117..79e61a436249dc4f6653567b75d6080e397f4c72 100644 (file)
@@ -347,22 +347,31 @@ namespace System.Net
                        if (webHeaders == null)
                                return;
 
-                       string value = webHeaders.Get ("Set-Cookie");
-                       if (value != null) {
-                               SetCookie (value);
+                       //
+                       // Don't terminate response reading on bad cookie value
+                       //
+                       string value;
+                       try {
+                               value = webHeaders.Get ("Set-Cookie");
+                               if (value != null && SetCookie (value))
+                                       return;
+                       } catch {
                        }
 
-                       value = webHeaders.Get ("Set-Cookie2");
-                       if (value != null) {
-                               SetCookie (value);
+                       try {
+                               value = webHeaders.Get ("Set-Cookie2");
+                               if (value != null)
+                                       SetCookie (value);
+                       } catch {
                        }
                }
 
-               void SetCookie (string header)
+               bool SetCookie (string header)
                {
                        if (cookieCollection == null)
                                cookieCollection = new CookieCollection ();
 
+                       bool at_least_one_set = false;
                        var parser = new CookieParser (header);
                        foreach (var cookie in parser.Parse ()) {
                                if (cookie.Domain == "") {
@@ -375,9 +384,13 @@ namespace System.Net
                                        continue;
 
                                cookieCollection.Add (cookie);
-                               if (cookie_container != null)
+                               if (cookie_container != null) {
                                        cookie_container.Add (uri, cookie);
+                                       at_least_one_set = true;
+                               }
                        }
+
+                       return at_least_one_set;
                }
        }       
 }
index e7700ed3a61a3439f3ec570b2ffc5e5f54a477c0..3d687949f92a8ed21f1e339eca6ead21c9e74615 100644 (file)
@@ -1,4 +1,4 @@
-DIST_SUBDIRS = x86 ppc sparc arm s390x amd64 ia64 mips
+DIST_SUBDIRS = x86 ppc sparc arm arm64 s390x amd64 ia64 mips
 
 AM_CPPFLAGS = $(GLIB_CFLAGS) -I$(top_srcdir)
 
diff --git a/mono/arch/arm64/Makefile.am b/mono/arch/arm64/Makefile.am
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/mono/arch/arm64/arm64-codegen.h b/mono/arch/arm64/arm64-codegen.h
new file mode 100644 (file)
index 0000000..259ff96
--- /dev/null
@@ -0,0 +1,3 @@
+#include "../../../../mono-extensions/mono/arch/arm64/arm64-codegen.h"
+
+
index a98b484b5ee1f3bed3b2075471006c9cbc01591e..09c6479c03d3805e5e1f6f12a43ba7f530168154 100644 (file)
@@ -215,6 +215,8 @@ struct _MonoJitInfo {
        gboolean    async:1;
        gboolean    dbg_step_through_inited:1;
        gboolean    dbg_step_through:1;
+       gboolean    dbg_non_user_code_inited:1;
+       gboolean    dbg_non_user_code:1;
 
        /* FIXME: Embed this after the structure later*/
        gpointer    gc_info; /* Currently only used by SGen */
index d0af8b07f6163ac3f6b65baf332be61e71dc5daa..5d7d9429b1ddaa16f4a5c96ae3e5206d17e5d0f4 100644 (file)
@@ -75,6 +75,9 @@
 #elif defined(__arm__)
 #define CONFIG_CPU "arm"
 #define CONFIG_WORDSIZE "32"
+#elif defined(__aarch64__)
+#define CONFIG_CPU "armv8"
+#define CONFIG_WORDSIZE "64"
 #elif defined(__ia64__)
 #define CONFIG_CPU "ia64"
 #define CONFIG_WORDSIZE "64"
index 5e7b5f8f1a3975641f76ea18f0fbafbad1659488..b86ec318c7cb8bfb0e2139c578deacf455b507c9 100755 (executable)
        ((a)[13]) = (gpointer) (UCONTEXT_REG_LR((ctx)));        \
        } while (0)
 
+#elif defined(TARGET_ARM64)
+
+#include <mono/utils/mono-sigcontext.h>
+
+#ifdef __linux__
+#define REDZONE_SIZE    0
+#elif defined(__APPLE__)
+#define REDZONE_SIZE   128
+#else
+#error "Not implemented."
+#endif
+#define USE_MONO_CTX
+#define ARCH_NUM_REGS 31
+
+#define ARCH_STORE_REGS(ptr) do { g_assert_not_reached (); } while (0)
+
+#define ARCH_SIGCTX_SP(ctx)    UCONTEXT_REG_SP (ctx)
+#define ARCH_SIGCTX_IP(ctx)    UCONTEXT_REG_PC (ctx)
+#define ARCH_COPY_SIGCTX_REGS(a,ctx) do { g_assert_not_reached (); } while (0)
+
 #elif defined(__mips__)
 
 #define REDZONE_SIZE   0
index ed66db2ce5ee876a957c162b0cb48d7fb3a3a266..5a2ab0e968730c6085c111060753d217ae5f6b7c 100755 (executable)
@@ -50,7 +50,7 @@ align_pointer (void *ptr)
 }
 
 #ifdef USE_MONO_CTX
-static MonoContext cur_thread_ctx = {0};
+static MonoContext cur_thread_ctx;
 #else
 static mword cur_thread_regs [ARCH_NUM_REGS] = {0};
 #endif
index 55e5f14abf26e2204fb82ac5bb7f6c75f676d07a..cd935b50bb78fd589bc654a90f2819d07b3d3fec 100755 (executable)
@@ -317,6 +317,12 @@ arm_sources = \
        exceptions-arm.c        \
        tramp-arm.c
 
+arm64_sources = \
+       mini-arm64.c            \
+       mini-arm64.h            \
+       exceptions-arm64.c      \
+       tramp-arm64.c
+
 mips_sources = \
        mini-mips.c             \
        mini-mips.h             \
@@ -486,6 +492,12 @@ arch_built=cpu-arm.h
 arch_define=__arm__
 endif
 
+if ARM64
+arch_sources = $(arm64_sources)
+arch_built=cpu-arm64.h
+arch_define=__aarch64__
+endif
+
 if SPARC
 arch_sources = $(sparc_sources)
 arch_built=cpu-sparc.h
@@ -614,6 +626,9 @@ cpu-ppc64.h: cpu-ppc64.md genmdesc$(EXEEXT)
 cpu-arm.h: cpu-arm.md genmdesc$(EXEEXT)
        $(GENMDESC_PRG) cpu-arm.h arm_cpu_desc $(srcdir)/cpu-arm.md
 
+cpu-arm64.h: cpu-arm64.md genmdesc$(EXEEXT)
+       $(GENMDESC_PRG) cpu-arm64.h arm64_cpu_desc $(srcdir)/cpu-arm64.md
+
 cpu-sparc.h: cpu-sparc.md genmdesc$(EXEEXT)
        $(GENMDESC_PRG) cpu-sparc.h sparc_desc $(srcdir)/cpu-sparc.md
 
@@ -718,6 +733,7 @@ EXTRA_DIST = TestDriver.cs ldscript ldscript.mono \
        $(amd64_sources) cpu-amd64.md           \
        $(ppc_sources) cpu-ppc.md cpu-ppc64.md  \
        $(arm_sources) cpu-arm.md               \
+       $(arm64_sources) cpu-arm64.md           \
        $(mips_sources) cpu-mips.md             \
        $(sparc_sources) cpu-sparc.md           \
        $(s390x_sources) cpu-s390x.md           \
index c28ec1d5b08ca990a33b39dd135531f4dbfe0492..2cd4bb7311a7f35545d276e96bcee179e5c0124f 100644 (file)
@@ -225,6 +225,7 @@ typedef struct MonoAotCompile {
        const char *temp_prefix;
        const char *user_symbol_prefix;
        const char *llvm_label_prefix;
+       const char *inst_directive;
        guint32 label_generator;
        gboolean llvm;
        MonoAotFileFlags flags;
@@ -564,7 +565,16 @@ emit_set_arm_mode (MonoAotCompile *acfg)
 static inline void
 emit_code_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
 {
+#ifdef TARGET_ARM64
+       int i;
+
+       g_assert (size % 4 == 0);
+       emit_unset_mode (acfg);
+       for (i = 0; i < size; i += 4)
+               fprintf (acfg->fp, "%s 0x%x\n", acfg->inst_directive, *(guint32*)(buf + i));
+#else
        emit_bytes (acfg, buf, size);
+#endif
 }
 
 /* ARCHITECTURE SPECIFIC CODE */
@@ -603,6 +613,14 @@ emit_code_bytes (MonoAotCompile *acfg, const guint8* buf, int size)
 #endif
 #endif
 
+#ifdef TARGET_ARM64
+#ifdef TARGET_MACH
+#define AOT_TARGET_STR "ARM64 (MACH)"
+#else
+#define AOT_TARGET_STR "ARM64 (!MACH)"
+#endif
+#endif
+
 #ifdef TARGET_POWERPC64
 #ifdef __mono_ilp32__
 #define AOT_TARGET_STR "POWERPC64 (mono ilp32)"
@@ -670,9 +688,16 @@ arch_init (MonoAotCompile *acfg)
                mono_arch_set_target (acfg->aot_opts.mtriple);
 #endif
 
+#ifdef TARGET_ARM64
+       acfg->inst_directive = ".inst";
+       if (acfg->aot_opts.mtriple)
+               mono_arch_set_target (acfg->aot_opts.mtriple);
+#endif
+
 #ifdef TARGET_MACH
        acfg->user_symbol_prefix = "_";
        acfg->llvm_label_prefix = "_";
+       acfg->inst_directive = ".word";
        acfg->need_no_dead_strip = TRUE;
        acfg->aot_opts.gnu_asm = TRUE;
 #endif
@@ -687,6 +712,12 @@ arch_init (MonoAotCompile *acfg)
 #endif
 }
 
+#ifdef TARGET_ARM64
+
+#include "../../../mono-extensions/mono/mini/aot-compiler-arm64.c"
+
+#endif
+
 #ifdef MONO_ARCH_AOT_SUPPORTED
 /*
  * arch_emit_direct_call:
@@ -725,6 +756,8 @@ arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean extern
                        fprintf (acfg->fp, "bl %s\n", target);
        }
        *call_size = 4;
+#elif defined(TARGET_ARM64)
+       arm64_emit_direct_call (acfg, target, external, thumb, ji, call_size);
 #elif defined(TARGET_POWERPC)
        if (acfg->use_bin_writer) {
                g_assert_not_reached ();
@@ -836,6 +869,8 @@ arch_emit_got_access (MonoAotCompile *acfg, guint8 *code, int got_slot, int *cod
 #elif defined(TARGET_ARM)
        emit_symbol_diff (acfg, acfg->got_symbol, ".", (unsigned int) ((got_slot * sizeof (gpointer))) - 12);
        *code_size = mono_arch_get_patch_offset (code) + 4;
+#elif defined(TARGET_ARM64)
+       arm64_emit_got_access (acfg, code, got_slot, code_size);
 #elif defined(TARGET_POWERPC)
        {
                guint8 buf [32];
@@ -879,6 +914,8 @@ arch_emit_objc_selector_ref (MonoAotCompile *acfg, guint8 *code, int index, int
        fprintf (acfg->fp, ".long %s-(%s+12)", symbol2, symbol1);
 
        *code_size = 12;
+#elif defined(TARGET_ARM64)
+       arm64_emit_objc_selector_ref (acfg, code, index, code_size);
 #else
        g_assert_not_reached ();
 #endif
@@ -961,6 +998,8 @@ arch_emit_plt_entry (MonoAotCompile *acfg, int index)
                emit_symbol_diff (acfg, acfg->got_symbol, ".", ((acfg->plt_got_offset_base + index) * sizeof (gpointer)) - 4);
                /* Used by mono_aot_get_plt_info_offset */
                emit_int32 (acfg, acfg->plt_got_info_offsets [index]);
+#elif defined(TARGET_ARM64)
+               arm64_emit_plt_entry (acfg, index);
 #elif defined(TARGET_POWERPC)
                guint32 offset = (acfg->plt_got_offset_base + index) * sizeof (gpointer);
 
@@ -1195,6 +1234,8 @@ arch_emit_specific_trampoline_pages (MonoAotCompile *acfg)
                g_assert (code - buf == 8);
                emit_bytes (acfg, buf, code - buf);
        }
+#elif defined(TARGET_ARM64)
+       arm64_emit_specific_trampoline_pages (acfg);
 #endif
 }
 
@@ -1309,6 +1350,8 @@ arch_emit_specific_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size
         */
        emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) - 4 + 4);
        //emit_symbol_diff (acfg, acfg->got_symbol, ".", ((offset + 1) * sizeof (gpointer)) - 4 + 8);
+#elif defined(TARGET_ARM64)
+       arm64_emit_specific_trampoline (acfg, offset, tramp_size);
 #elif defined(TARGET_POWERPC)
        guint8 buf [128];
        guint8 *code;
@@ -1456,6 +1499,8 @@ arch_emit_unbox_trampoline (MonoAotCompile *acfg, MonoCompile *cfg, MonoMethod *
                else
                        fprintf (acfg->fp, "\n\tb %s\n", call_target);
        }
+#elif defined(TARGET_ARM64)
+       arm64_emit_unbox_trampoline (acfg, cfg, method, call_target);
 #elif defined(TARGET_POWERPC)
        int this_pos = 3;
 
@@ -1541,6 +1586,8 @@ arch_emit_static_rgctx_trampoline (MonoAotCompile *acfg, int offset, int *tramp_
        emit_bytes (acfg, buf, code - buf);
        emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) - 4 + 8);
        emit_symbol_diff (acfg, acfg->got_symbol, ".", ((offset + 1) * sizeof (gpointer)) - 4 + 4);
+#elif defined(TARGET_ARM64)
+       arm64_emit_static_rgctx_trampoline (acfg, offset, tramp_size);
 #elif defined(TARGET_POWERPC)
        guint8 buf [128];
        guint8 *code;
@@ -1845,6 +1892,8 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
        emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) + (code - (labels [0] + 8)) - 4);
 
        *tramp_size = code - buf + 4;
+#elif defined(TARGET_ARM64)
+       arm64_emit_imt_thunk (acfg, offset, tramp_size);
 #elif defined(TARGET_POWERPC)
        guint8 buf [128];
        guint8 *code, *labels [16];
@@ -1960,6 +2009,8 @@ arch_emit_gsharedvt_arg_trampoline (MonoAotCompile *acfg, int offset, int *tramp
        /* Emit it */
        emit_bytes (acfg, buf, code - buf);
        emit_symbol_diff (acfg, acfg->got_symbol, ".", (offset * sizeof (gpointer)) + 4);
+#elif defined(TARGET_ARM64)
+       arm64_emit_gsharedvt_arg_trampoline (acfg, offset, tramp_size);
 #else
        g_assert_not_reached ();
 #endif
@@ -4494,7 +4545,11 @@ get_file_index (MonoAotCompile *acfg, const char *source_file)
        return findex;
 }
 
+#ifdef TARGET_ARM64
+#define INST_LEN 4
+#else
 #define INST_LEN 1
+#endif
 
 /*
  * emit_and_reloc_code:
@@ -6274,7 +6329,7 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
                        opts->direct_pinvoke = TRUE;
                } else if (str_begins_with (arg, "direct-icalls")) {
                        opts->direct_icalls = TRUE;
-#if defined(TARGET_ARM)
+#if defined(TARGET_ARM) || defined(TARGET_ARM64)
                } else if (str_begins_with (arg, "iphone-abi")) {
                        // older full-aot users did depend on this.
 #endif
@@ -8268,7 +8323,7 @@ emit_objc_selectors (MonoAotCompile *acfg)
        img_writer_emit_unset_mode (acfg->w);
        g_assert (acfg->fp);
        fprintf (acfg->fp, ".section    __DATA,__objc_selrefs,literal_pointers,no_dead_strip\n");
-       fprintf (acfg->fp, ".align      2\n");
+       fprintf (acfg->fp, ".align      3\n");
        for (i = 0; i < acfg->objc_selectors->len; ++i) {
                fprintf (acfg->fp, "L_OBJC_SELECTOR_REFERENCES_%d:\n", i);
                fprintf (acfg->fp, ".long       L_OBJC_METH_VAR_NAME_%d\n", i);
@@ -8280,7 +8335,7 @@ emit_objc_selectors (MonoAotCompile *acfg)
        }
 
        fprintf (acfg->fp, ".section    __DATA,__objc_imageinfo,regular,no_dead_strip\n");
-       fprintf (acfg->fp, ".align      2\n");
+       fprintf (acfg->fp, ".align      3\n");
        fprintf (acfg->fp, "L_OBJC_IMAGE_INFO:\n");
        fprintf (acfg->fp, ".long       0\n");
        fprintf (acfg->fp, ".long       16\n");
index abf214f405c291f25243711c73cc36ae3131d02e..f2a417faf86ff1046cf8b250654d3aec11dbcbb4 100644 (file)
@@ -1549,6 +1549,8 @@ get_arm_bl_target (guint32 *ins_addr)
                offset = (((int)ins & 0xffffff) << 8) >> 8;
                return (char*)ins_addr + (offset * 4) + 8;
        }
+#elif defined(TARGET_ARM64)
+       return mono_arch_get_call_target (((guint8*)ins_addr) + 4);
 #else
        g_assert_not_reached ();
        return NULL;
@@ -1778,7 +1780,7 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
                        /* method_addresses () contains a table of branches, since the ios linker can update those correctly */
                        void *addr = NULL;
 
-#ifdef TARGET_ARM
+#if defined(TARGET_ARM) || defined(TARGET_ARM64)
                        addr = get_arm_bl_target ((guint32*)amodule->method_addresses + i);
 #elif defined(TARGET_X86) || defined(TARGET_AMD64)
                        addr = mono_arch_get_call_target ((guint8*)amodule->method_addresses + (i * 5) + 5);
@@ -3880,16 +3882,24 @@ find_aot_module (guint8 *code)
 }
 
 void
-mono_aot_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint8 *addr)
+mono_aot_patch_plt_entry (guint8 *code, guint8 *plt_entry, gpointer *got, mgreg_t *regs, guint8 *addr)
 {
+       MonoAotModule *amodule;
+
        /*
         * Since AOT code is only used in the root domain, 
         * mono_domain_get () != mono_get_root_domain () means the calling method
         * is AppDomain:InvokeInDomain, so this is the same check as in 
         * mono_method_same_domain () but without loading the metadata for the method.
         */
-       if (mono_domain_get () == mono_get_root_domain ())
-               mono_arch_patch_plt_entry (code, got, regs, addr);
+       if (mono_domain_get () == mono_get_root_domain ()) {
+               if (!got) {
+                       amodule = find_aot_module (code);
+                       if (amodule)
+                               got = amodule->got;
+               }
+               mono_arch_patch_plt_entry (plt_entry, got, regs, addr);
+       }
 }
 
 /*
@@ -3968,7 +3978,7 @@ mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code
        /* Patch the PLT entry with target which might be the actual method not a trampoline */
        plt_entry = mono_aot_get_plt_entry (code);
        g_assert (plt_entry);
-       mono_aot_patch_plt_entry (plt_entry, module->got, NULL, target);
+       mono_aot_patch_plt_entry (code, plt_entry, module->got, NULL, target);
 
        return target;
 #else
@@ -4378,10 +4388,14 @@ get_new_trampoline_from_page (int tramp_type)
                page = (TrampolinePage*)addr;
                page->next = trampoline_pages [tramp_type];
                trampoline_pages [tramp_type] = page;
+#ifdef TARGET_ARM64
+               page->trampolines = (void*)(taddr + amodule->info.tramp_page_code_offsets [tramp_type]);
+#else
                page->trampolines = (void*)(taddr + trampolines_pages_code_offsets [tramp_type]);
-               page->trampolines_end = (void*)(taddr + psize);
+#endif
+               page->trampolines_end = (void*)(taddr + psize - 64);
                code = page->trampolines;
-               page->trampolines += 8;
+               page->trampolines += specific_trampoline_size;
                mono_aot_page_unlock ();
                return code;
        }
@@ -4879,7 +4893,7 @@ mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code
 }
 
 void
-mono_aot_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint8 *addr)
+mono_aot_patch_plt_entry (guint8 *code, guint8 *plt_entry, gpointer *got, mgreg_t *regs, guint8 *addr)
 {
 }
 
diff --git a/mono/mini/cpu-arm64.md b/mono/mini/cpu-arm64.md
new file mode 100644 (file)
index 0000000..d57b6ee
--- /dev/null
@@ -0,0 +1,424 @@
+# Copyright 2011-2013 Xamarin, Inc (http://www.xamarin.com)
+# Copyright 2003-2011 Novell, Inc (http://www.novell.com)
+# arm64 cpu description file
+# this file is read by genmdesc to pruduce a table with all the relevant information
+# about the cpu instructions that may be used by the regsiter allocator, the scheduler
+# and other parts of the arch-dependent part of mini.
+#
+# An opcode name is followed by a colon and optional specifiers.
+# A specifier has a name, a colon and a value. Specifiers are separated by white space.
+# Here is a description of the specifiers valid for this file and their possible values.
+#
+# dest:register       describes the destination register of an instruction
+# src1:register       describes the first source register of an instruction
+# src2:register       describes the second source register of an instruction
+#
+# register may have the following values:
+#      i  integer register
+#      a  r3 register (output from calls)
+#      b  base register (used in address references)
+#      f  floating point register
+#      g  floating point register returned in r0:r1 for soft-float mode
+#
+# len:number         describe the maximun length in bytes of the instruction
+# number is a positive integer
+#
+# cost:number        describe how many cycles are needed to complete the instruction (unused)
+#
+# clob:spec          describe if the instruction clobbers registers or has special needs
+#
+# spec can be one of the following characters:
+#      c  clobbers caller-save registers
+#      r  'reserves' the destination register until a later instruction unreserves it
+#          used mostly to set output registers in function calls
+#
+# flags:spec        describe if the instruction uses or sets the flags (unused)
+#
+# spec can be one of the following chars:
+#      s  sets the flags
+#       u  uses the flags
+#       m  uses and modifies the flags
+#
+# res:spec          describe what units are used in the processor (unused)
+#
+# delay:            describe delay slots (unused)
+#
+# the required specifiers are: len, clob (if registers are clobbered), the registers
+# specifiers if the registers are actually used, flags (when scheduling is implemented).
+#
+# See the code in mini-x86.c for more details on how the specifiers are used.
+#
+memory_barrier: len:8 clob:a
+nop: len:4
+relaxed_nop: len:4
+break: len:20
+jmp: len:92
+br: len:16
+switch: src1:i len:12
+# See the comment in resume_from_signal_handler, we can't copy the fp regs from sigctx to MonoContext on linux,
+# since the corresponding sigctx structures are not well defined.
+seq_point: len:38 clob:c
+
+throw: src1:i len:24
+rethrow: src1:i len:20
+start_handler: len:32
+endfinally: len:32
+call_handler: len:16 clob:c
+endfilter: src1:i len:32
+
+ckfinite: dest:f src1:f len:64
+ceq: dest:i len:12
+cgt: dest:i len:12
+cgt.un: dest:i len:12
+clt: dest:i len:12
+clt.un: dest:i len:12
+localloc: dest:i src1:i len:96
+compare: src1:i src2:i len:4
+compare_imm: src1:i len:20
+fcompare: src1:f src2:f len:12
+oparglist: src1:i len:12
+setlret: src1:i src2:i len:12
+checkthis: src1:b len:4
+call: dest:a clob:c len:32
+call_reg: dest:a src1:i len:32 clob:c
+call_membase: dest:a src1:b len:32 clob:c
+voidcall: len:32 clob:c
+voidcall_reg: src1:i len:32 clob:c
+voidcall_membase: src1:b len:32 clob:c
+fcall: dest:f len:32 clob:c
+fcall_reg: dest:f src1:i len:32 clob:c
+fcall_membase: dest:f src1:b len:32 clob:c
+lcall: dest:l len:32 clob:c
+lcall_reg: dest:l src1:i len:32 clob:c
+lcall_membase: dest:l src1:b len:32 clob:c
+vcall: len:32 clob:c
+vcall_reg: src1:i len:32 clob:c
+vcall_membase: src1:b len:32 clob:c
+tailcall: len:64
+iconst: dest:i len:16
+r4const: dest:f len:24
+r8const: dest:f len:20
+label: len:0
+store_membase_imm: dest:b len:20
+store_membase_reg: dest:b src1:i len:20
+storei1_membase_imm: dest:b len:20
+storei1_membase_reg: dest:b src1:i len:12
+storei2_membase_imm: dest:b len:20
+storei2_membase_reg: dest:b src1:i len:12
+storei4_membase_imm: dest:b len:20
+storei4_membase_reg: dest:b src1:i len:20
+storer4_membase_reg: dest:b src1:f len:20
+storer8_membase_reg: dest:b src1:f len:24
+store_memindex: dest:b src1:i src2:i len:4
+storei1_memindex: dest:b src1:i src2:i len:4
+storei2_memindex: dest:b src1:i src2:i len:4
+storei4_memindex: dest:b src1:i src2:i len:4
+load_membase: dest:i src1:b len:20
+loadi1_membase: dest:i src1:b len:32
+loadu1_membase: dest:i src1:b len:32
+loadi2_membase: dest:i src1:b len:32
+loadu2_membase: dest:i src1:b len:32
+loadi4_membase: dest:i src1:b len:32
+loadu4_membase: dest:i src1:b len:32
+loadr4_membase: dest:f src1:b len:32
+loadr8_membase: dest:f src1:b len:32
+load_memindex: dest:i src1:b src2:i len:4
+loadi1_memindex: dest:i src1:b src2:i len:4
+loadu1_memindex: dest:i src1:b src2:i len:4
+loadi2_memindex: dest:i src1:b src2:i len:4
+loadu2_memindex: dest:i src1:b src2:i len:4
+loadi4_memindex: dest:i src1:b src2:i len:4
+loadu4_memindex: dest:i src1:b src2:i len:4
+loadu4_mem: dest:i len:8
+move: dest:i src1:i len:4
+fmove: dest:f src1:f len:4
+add_imm: dest:i src1:i len:12
+sub_imm: dest:i src1:i len:12
+mul_imm: dest:i src1:i len:12
+and_imm: dest:i src1:i len:12
+or_imm: dest:i src1:i len:12
+xor_imm: dest:i src1:i len:12
+shl_imm: dest:i src1:i len:8
+shr_imm: dest:i src1:i len:8
+shr_un_imm: dest:i src1:i len:8
+cond_exc_eq: len:8
+cond_exc_ne_un: len:8
+cond_exc_lt: len:8
+cond_exc_lt_un: len:8
+cond_exc_gt: len:8
+cond_exc_gt_un: len:8
+cond_exc_ge: len:8
+cond_exc_ge_un: len:8
+cond_exc_le: len:8
+cond_exc_le_un: len:8
+cond_exc_ov: len:12
+cond_exc_no: len:8
+cond_exc_c: len:12
+cond_exc_nc: len:8
+#float_beq: src1:f src2:f len:20
+#float_bne_un: src1:f src2:f len:20
+#float_blt: src1:f src2:f len:20
+#float_blt_un: src1:f src2:f len:20
+#float_bgt: src1:f src2:f len:20
+#float_bgt_un: src1:f src2:f len:20
+#float_bge: src1:f src2:f len:20
+#float_bge_un: src1:f src2:f len:20
+#float_ble: src1:f src2:f len:20
+#float_ble_un: src1:f src2:f len:20
+float_add: dest:f src1:f src2:f len:4
+float_sub: dest:f src1:f src2:f len:4
+float_mul: dest:f src1:f src2:f len:4
+float_div: dest:f src1:f src2:f len:4
+float_div_un: dest:f src1:f src2:f len:4
+float_rem: dest:f src1:f src2:f len:16
+float_rem_un: dest:f src1:f src2:f len:16
+float_neg: dest:f src1:f len:4
+float_not: dest:f src1:f len:4
+float_conv_to_i1: dest:i src1:f len:40
+float_conv_to_i2: dest:i src1:f len:40
+float_conv_to_i4: dest:i src1:f len:40
+float_conv_to_i8: dest:l src1:f len:40
+float_conv_to_r4: dest:f src1:f len:8
+float_conv_to_u4: dest:i src1:f len:40
+float_conv_to_u8: dest:l src1:f len:40
+float_conv_to_u2: dest:i src1:f len:40
+float_conv_to_u1: dest:i src1:f len:40
+float_conv_to_i: dest:i src1:f len:40
+float_ceq: dest:i src1:f src2:f len:16
+float_cgt: dest:i src1:f src2:f len:16
+float_cgt_un: dest:i src1:f src2:f len:20
+float_clt: dest:i src1:f src2:f len:16
+float_clt_un: dest:i src1:f src2:f len:20
+float_cneq: dest:i src1:f src2:f len:20
+float_cge: dest:i src1:f src2:f len:20
+float_cle: dest:i src1:f src2:f len:20
+float_conv_to_u: dest:i src1:f len:36
+setfret: src1:f len:12
+aot_const: dest:i len:16
+objc_get_selector: dest:i len:32
+sqrt: dest:f src1:f len:4
+adc: dest:i src1:i src2:i len:4
+addcc: dest:i src1:i src2:i len:4
+subcc: dest:i src1:i src2:i len:4
+adc_imm: dest:i src1:i len:12
+addcc_imm: dest:i src1:i len:12
+subcc_imm: dest:i src1:i len:12
+sbb: dest:i src1:i src2:i len:4
+sbb_imm: dest:i src1:i len:12
+br_reg: src1:i len:8
+bigmul: len:8 dest:l src1:i src2:i
+bigmul_un: len:8 dest:l src1:i src2:i
+tls_get: dest:i len:32
+tls_get_reg: dest:i src1:i len:32
+tls_set: src1:i len:32
+tls_set_reg: src1:i src2:i len:32
+
+# 32 bit opcodes
+int_add: dest:i src1:i src2:i len:4
+int_sub: dest:i src1:i src2:i len:4
+int_mul: dest:i src1:i src2:i len:4
+int_div: dest:i src1:i src2:i len:72
+int_div_un: dest:i src1:i src2:i len:72
+int_rem: dest:i src1:i src2:i len:72
+int_rem_un: dest:i src1:i src2:i len:72
+int_and: dest:i src1:i src2:i len:4
+int_or: dest:i src1:i src2:i len:4
+int_xor: dest:i src1:i src2:i len:4
+int_shl: dest:i src1:i src2:i len:4
+int_shr: dest:i src1:i src2:i len:4
+int_shr_un: dest:i src1:i src2:i len:4
+int_neg: dest:i src1:i len:4
+int_not: dest:i src1:i len:4
+int_conv_to_i1: dest:i src1:i len:8
+int_conv_to_i2: dest:i src1:i len:8
+int_conv_to_i4: dest:i src1:i len:4
+int_conv_to_r4: dest:f src1:i len:36
+int_conv_to_r8: dest:f src1:i len:36
+int_conv_to_u4: dest:i src1:i
+int_conv_to_r_un: dest:f src1:i len:56
+int_conv_to_u2: dest:i src1:i len:8
+int_conv_to_u1: dest:i src1:i len:4
+int_beq: len:16
+int_bge: len:16
+int_bgt: len:16
+int_ble: len:16
+int_blt: len:16
+int_bne_un: len:16
+int_bge_un: len:16
+int_bgt_un: len:16
+int_ble_un: len:16
+int_blt_un: len:16
+int_add_ovf: dest:i src1:i src2:i len:16
+int_add_ovf_un: dest:i src1:i src2:i len:16
+int_mul_ovf: dest:i src1:i src2:i len:16
+int_mul_ovf_un: dest:i src1:i src2:i len:16
+int_sub_ovf: dest:i src1:i src2:i len:16
+int_sub_ovf_un: dest:i src1:i src2:i len:16
+add_ovf_carry: dest:i src1:i src2:i len:16
+sub_ovf_carry: dest:i src1:i src2:i len:16
+add_ovf_un_carry: dest:i src1:i src2:i len:16
+sub_ovf_un_carry: dest:i src1:i src2:i len:16
+
+arm_rsbs_imm: dest:i src1:i len:4
+arm_rsc_imm: dest:i src1:i len:4
+
+# Linear IR opcodes
+dummy_use: src1:i len:0
+dummy_store: len:0
+not_reached: len:0
+not_null: src1:i len:0
+
+int_adc: dest:i src1:i src2:i len:4
+int_addcc: dest:i src1:i src2:i len:4
+int_subcc: dest:i src1:i src2:i len:4
+int_sbb: dest:i src1:i src2:i len:4
+int_adc_imm: dest:i src1:i len:12
+int_sbb_imm: dest:i src1:i len:12
+
+int_add_imm: dest:i src1:i len:12
+int_sub_imm: dest:i src1:i len:12
+int_mul_imm: dest:i src1:i len:12
+int_div_imm: dest:i src1:i len:20
+int_div_un_imm: dest:i src1:i len:12
+int_rem_imm: dest:i src1:i len:28
+int_rem_un_imm: dest:i src1:i len:16
+int_and_imm: dest:i src1:i len:12
+int_or_imm: dest:i src1:i len:12
+int_xor_imm: dest:i src1:i len:12
+int_shl_imm: dest:i src1:i len:8
+int_shr_imm: dest:i src1:i len:8
+int_shr_un_imm: dest:i src1:i len:8
+
+int_ceq: dest:i len:12
+int_cgt: dest:i len:12
+int_cgt_un: dest:i len:12
+int_clt: dest:i len:12
+int_clt_un: dest:i len:12
+
+int_cneq: dest:i len:12
+int_cge: dest:i len:12
+int_cle: dest:i len:12
+int_cge_un: dest:i len:12
+int_cle_un: dest:i len:12
+
+cond_exc_ieq: len:16
+cond_exc_ine_un: len:16
+cond_exc_ilt: len:16
+cond_exc_ilt_un: len:16
+cond_exc_igt: len:16
+cond_exc_igt_un: len:16
+cond_exc_ige: len:16
+cond_exc_ige_un: len:16
+cond_exc_ile: len:16
+cond_exc_ile_un: len:16
+cond_exc_iov: len:20
+cond_exc_ino: len:16
+cond_exc_ic: len:20
+cond_exc_inc: len:16
+
+icompare: src1:i src2:i len:4
+icompare_imm: src1:i len:12
+
+long_conv_to_ovf_i4_2: dest:i src1:i src2:i len:36
+
+vcall2: len:32 clob:c
+vcall2_reg: src1:i len:32 clob:c
+vcall2_membase: src1:b len:32 clob:c
+dyn_call: src1:i src2:i len:120 clob:c
+
+# This is different from the original JIT opcodes
+float_beq: len:32
+float_bne_un: len:32
+float_blt: len:32
+float_blt_un: len:32
+float_bgt: len:32
+float_bgt_un: len:32
+float_bge: len:32
+float_bge_un: len:32
+float_ble: len:32
+float_ble_un: len:32
+
+liverange_start: len:0
+liverange_end: len:0
+gc_liveness_def: len:0
+gc_liveness_use: len:0
+gc_spill_slot_liveness_def: len:0
+gc_param_slot_liveness_def: len:0
+
+# 64 bit opcodes
+i8const: dest:i len:16
+sext_i4: dest:i src1:i len:4
+zext_i4: dest:i src1:i len:4
+jump_table: dest:i len:16
+long_add: dest:i src1:i src2:i len:4
+long_sub: dest:i src1:i src2:i len:4
+long_mul: dest:i src1:i src2:i len:4
+long_div: dest:i src1:i src2:i len:80
+long_div_un: dest:i src1:i src2:i len:64
+long_rem: dest:i src1:i src2:i len:80
+long_rem_un: dest:i src1:i src2:i len:64
+long_and: dest:i src1:i src2:i len:4
+long_or: dest:i src1:i src2:i len:4
+long_xor: dest:i src1:i src2:i len:4
+long_shl: dest:i src1:i src2:i len:4
+long_shr: dest:i src1:i src2:i len:4
+long_shr_un: dest:i src1:i src2:i len:4
+long_neg: dest:i src1:i len:4
+long_not: dest:i src1:i len:4
+long_add_imm: dest:i src1:i len:12
+long_sub_imm: dest:i src1:i len:12
+long_mul_imm: dest:i src1:i len:12
+long_and_imm: dest:i src1:i len:12
+long_or_imm: dest:i src1:i len:12
+long_xor_imm: dest:i src1:i len:12
+long_shl_imm: dest:i src1:i len:12
+long_shr_imm: dest:i src1:i len:12
+long_shr_un_imm: dest:i src1:i len:12
+long_add_ovf: dest:i src1:i src2:i len:16
+long_add_ovf_un: dest:i src1:i src2:i len:16
+long_mul_ovf: dest:i src1:i src2:i len:16
+long_mul_ovf_un: dest:i src1:i src2:i len:16
+long_sub_ovf: dest:i src1:i src2:i len:16
+long_sub_ovf_un: dest:i src1:i src2:i len:16
+lcompare: src1:i src2:i len:4
+lcompare_imm: src1:i len:20
+long_beq: len:4
+long_bge: len:4
+long_bgt: len:4
+long_ble: len:4
+long_blt: len:4
+long_bne_un: len:4
+long_bge_un: len:4
+long_bgt_un: len:4
+long_ble_un: len:4
+long_blt_un: len:4
+long_ceq: dest:i len:12
+long_cgt: dest:i len:12
+long_cgt_un: dest:i len:12
+long_clt: dest:i len:12
+long_clt_un: dest:i len:12
+long_conv_to_i1: dest:i src1:i len:4
+long_conv_to_i2: dest:i src1:i len:4
+long_conv_to_u1: dest:i src1:i len:4
+long_conv_to_u2: dest:i src1:i len:4
+long_conv_to_r8: dest:f src1:i len:8
+long_conv_to_r4: dest:f src1:i len:12
+loadi8_membase: dest:i src1:b len:12
+storei8_membase_imm: dest:b  len:20
+storei8_membase_reg: dest:b src1:i len:12
+long_conv_to_r_un: dest:f src1:i len:8
+arm_setfreg_r4: dest:f src1:f len:8
+localloc_imm: dest:i len:64
+arm64_cbzw: src1:i len:16
+arm64_cbzx: src1:i len:16
+arm64_cbnzw: src1:i len:16
+arm64_cbnzx: src1:i len:16
+
+atomic_add_new_i4: dest:i src1:i src2:i len:32
+atomic_add_new_i8: dest:i src1:i src2:i len:32
+atomic_exchange_i4: dest:i src1:i src2:i len:32
+atomic_exchange_i8: dest:i src1:i src2:i len:32
+atomic_cas_i4: dest:i src1:i src2:i src3:i len:32
+atomic_cas_i8: dest:i src1:i src2:i src3:i len:32
+
+
index 9eb0c294976101e19a897b123a68ea96c221124d..16ccadc9aa61b3822d7cc7aaea54c72c1a34ba7b 100644 (file)
@@ -285,7 +285,7 @@ typedef struct {
 #define HEADER_LENGTH 11
 
 #define MAJOR_VERSION 2
-#define MINOR_VERSION 29
+#define MINOR_VERSION 30
 
 typedef enum {
        CMD_SET_VM = 1,
@@ -371,7 +371,8 @@ typedef enum {
        STEP_FILTER_NONE = 0,
        STEP_FILTER_STATIC_CTOR = 1,
        STEP_FILTER_DEBUGGER_HIDDEN = 2,
-       STEP_FILTER_DEBUGGER_STEP_THROUGH = 4
+       STEP_FILTER_DEBUGGER_STEP_THROUGH = 4,
+       STEP_FILTER_DEBUGGER_NON_USER_CODE = 8
 } StepFilter;
 
 typedef enum {
@@ -3498,6 +3499,32 @@ create_event_list (EventKind event, GPtrArray *reqs, MonoJitInfo *ji, EventInfo
                                                if (ji->dbg_step_through)
                                                        filtered = TRUE;
                                        }
+                                       if ((mod->data.filter & STEP_FILTER_DEBUGGER_NON_USER_CODE) && ji) {
+                                               MonoCustomAttrInfo *ainfo;
+                                               static MonoClass *klass;
+
+                                               if (!klass) {
+                                                       klass = mono_class_from_name (mono_defaults.corlib, "System.Diagnostics", "DebuggerNonUserCodeAttribute");
+                                                       g_assert (klass);
+                                               }
+                                               if (!ji->dbg_non_user_code_inited) {
+                                                       ainfo = mono_custom_attrs_from_method (jinfo_get_method (ji));
+                                                       if (ainfo) {
+                                                               if (mono_custom_attrs_has_attr (ainfo, klass))
+                                                                       ji->dbg_non_user_code = TRUE;
+                                                               mono_custom_attrs_free (ainfo);
+                                                       }
+                                                       ainfo = mono_custom_attrs_from_class (jinfo_get_method (ji)->klass);
+                                                       if (ainfo) {
+                                                               if (mono_custom_attrs_has_attr (ainfo, klass))
+                                                                       ji->dbg_non_user_code = TRUE;
+                                                               mono_custom_attrs_free (ainfo);
+                                                       }
+                                                       ji->dbg_non_user_code_inited = TRUE;
+                                               }
+                                               if (ji->dbg_non_user_code)
+                                                       filtered = TRUE;
+                                       }
                                }
                        }
 
diff --git a/mono/mini/exceptions-arm64.c b/mono/mini/exceptions-arm64.c
new file mode 100644 (file)
index 0000000..333fd13
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../mono-extensions/mono/mini/exceptions-arm64.c"
index 8c13a6171dd947081cc78d7eb28b58ab8a8618b3..b3a4cc8b78b06658dd2f1bf7734dd35beb801c54 100644 (file)
@@ -20,7 +20,7 @@ sub INST_MAX   () {return 6;}
 
 # this must include all the #defines used in mini-ops.h
 my @defines = qw (__i386__ __x86_64__ __ppc__ __powerpc__ __ppc64__ __arm__ 
-       __sparc__ sparc __s390__ s390 __ia64__ __alpha__ __mips__);
+       __sparc__ sparc __s390__ s390 __ia64__ __alpha__ __mips__ __aarch64__);
 my %table =();
 my %template_table =();
 my @opcodes = ();
@@ -85,6 +85,9 @@ sub load_opcodes
        if ($arch =~ "__arm__") {
                $arch_define = "TARGET_ARM";
        }
+       if ($arch =~ "__aarch64__") {
+               $arch_define = "TARGET_ARM64";
+       }
 
        parse_file ($arch_define, "$srcdir/mini-ops.h");
        return;
index d945a39b8f2e4e900c08968e3465ee390e17c6bb..43bd17e2fa499d3fe6904a97f71492646718b10b 100644 (file)
@@ -66,10 +66,14 @@ opnames[] = {
 #endif /* DISABLE_LOGGING */
 
 #if defined(__i386__) || defined(__x86_64__)
+#ifndef TARGET_ARM64
 #define emit_debug_info  TRUE
 #else
 #define emit_debug_info  FALSE
 #endif
+#else
+#define emit_debug_info  FALSE
+#endif
 
 /*This enables us to use the right tooling when building the cross compiler for iOS.*/
 #if defined (__APPLE__) && defined (TARGET_ARM) && (defined(__i386__) || defined(__x86_64__))
@@ -237,6 +241,12 @@ mono_disassemble_code (MonoCompile *cfg, guint8 *code, int size, char *id)
 #  else
 #    define AS_CMD "as -gstabs"
 #  endif
+#elif defined (TARGET_ARM64)
+#  if defined (__APPLE__)
+#    define AS_CMD "clang -c -arch arm64 -g -x assembler"
+#  else
+#    define AS_CMD "as -gstabs"
+#  endif
 #elif defined(__mips__) && (_MIPS_SIM == _ABIO32)
 #define AS_CMD "as -mips32"
 #elif defined(__ppc64__)
@@ -275,7 +285,7 @@ mono_disassemble_code (MonoCompile *cfg, guint8 *code, int size, char *id)
        cmd = g_strdup_printf (ARCH_PREFIX DIS_CMD " %s %s", objdump_args, o_file);
        unused = system (cmd);
        g_free (cmd);
-       
+
 #ifndef HOST_WIN32
        unlink (o_file);
        unlink (as_file);
index a5d7488da85df18fb35a763a4bb6a2e3db902080..62b2b3525a5509a9f2dded8a9443218af17b6711 100644 (file)
 
 #if (defined(TARGET_AMD64) || defined(TARGET_POWERPC64)) && !defined(__mono_ilp32__)
 #define AS_POINTER_DIRECTIVE ".quad"
+#elif defined(TARGET_ARM64)
+
+#ifdef TARGET_ASM_APPLE
+#define AS_POINTER_DIRECTIVE ".quad"
+#else
+#define AS_POINTER_DIRECTIVE ".xword"
+#endif
+
 #else
 #define AS_POINTER_DIRECTIVE ".long"
 #endif
@@ -1713,7 +1721,7 @@ asm_writer_emit_section_change (MonoImageWriter *acfg, const char *section_name,
                fprintf (acfg->fp, ".section __DWARF, __%s,regular,debug\n", section_name + 1);
        } else
                fprintf (acfg->fp, "%s\n", section_name);
-#elif defined(TARGET_ARM) || defined(TARGET_POWERPC)
+#elif defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_POWERPC)
        /* ARM gas doesn't seem to like subsections of .bss */
        if (!strcmp (section_name, ".text") || !strcmp (section_name, ".data")) {
                fprintf (acfg->fp, "%s %d\n", section_name, subsection_index);
index 2e35b7ab17f8ef7677be8b3e9db35455f0670e71..1ecf79c9ac355a72f79b02ec999f8d1e724570ed 100644 (file)
@@ -1953,10 +1953,26 @@ emit_push_lmf (MonoCompile *cfg)
                }
 #else
                lmf_ins = mono_get_lmf_addr_intrinsic (cfg);
-               if (lmf_ins) 
+               if (lmf_ins) {
                        MONO_ADD_INS (cfg->cbb, lmf_ins);
-               else
+               } else {
+#ifdef TARGET_IOS
+                       MonoInst *args [16], *jit_tls_ins, *ins;
+
+                       /* Inline mono_get_lmf_addr () */
+                       /* jit_tls = pthread_getspecific (mono_jit_tls_id); lmf_addr = &jit_tls->lmf; */
+
+                       /* Load mono_jit_tls_id */
+                       EMIT_NEW_AOTCONST (cfg, args [0], MONO_PATCH_INFO_JIT_TLS_ID, NULL);
+                       /* call pthread_getspecific () */
+                       jit_tls_ins = mono_emit_jit_icall (cfg, pthread_getspecific, args);
+                       /* lmf_addr = &jit_tls->lmf */
+                       EMIT_NEW_BIALU_IMM (cfg, ins, OP_PADD_IMM, cfg->lmf_addr_var->dreg, jit_tls_ins->dreg, G_STRUCT_OFFSET (MonoJitTlsData, lmf));
+                       lmf_ins = ins;
+#else
                        lmf_ins = mono_emit_jit_icall (cfg, mono_get_lmf_addr, NULL);
+#endif
+               }
 #endif
                lmf_ins->dreg = cfg->lmf_addr_var->dreg;
 
@@ -5686,10 +5702,10 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                if (args [0]->opcode == OP_GOT_ENTRY) {
                        pi = args [0]->inst_p1;
                        g_assert (pi->opcode == OP_PATCH_INFO);
-                       g_assert ((int)pi->inst_p1 == MONO_PATCH_INFO_LDSTR);
+                       g_assert (GPOINTER_TO_INT (pi->inst_p1) == MONO_PATCH_INFO_LDSTR);
                        ji = pi->inst_p0;
                } else {
-                       g_assert ((int)args [0]->inst_p1 == MONO_PATCH_INFO_LDSTR);
+                       g_assert (GPOINTER_TO_INT (args [0]->inst_p1) == MONO_PATCH_INFO_LDSTR);
                        ji = args [0]->inst_p0;
                }
 
index a005fc98ad4eadfbee8b53847b24939e41ef6718..6d52aecf6da191d0a89a555015a7a97f31d32a4b 100644 (file)
@@ -19,6 +19,8 @@
 #include "mini-ia64.h"
 #elif defined(TARGET_ARM)
 #include "mini-arm.h"
+#elif defined(TARGET_ARM64)
+#include "mini-arm64.h"
 #elif defined(__mips__)
 #include "mini-mips.h"
 #else
diff --git a/mono/mini/mini-arm64.c b/mono/mini/mini-arm64.c
new file mode 100644 (file)
index 0000000..517f6c6
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../mono-extensions/mono/mini/mini-arm64.c"
diff --git a/mono/mini/mini-arm64.h b/mono/mini/mini-arm64.h
new file mode 100644 (file)
index 0000000..a963c75
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../mono-extensions/mono/mini/mini-arm64.h"
index 48fac064cbdc675bdf85b5d7a42d143688b809bb..6e5bf2f8586b331670c76f02325d0cb7585f3d95 100644 (file)
@@ -1065,8 +1065,9 @@ assign_reg (MonoCompile *cfg, MonoRegState *rs, int reg, int hreg, int bank)
        else {
                g_assert (reg >= MONO_MAX_IREGS);
                g_assert (hreg < MONO_MAX_IREGS);
-#ifndef TARGET_ARM
+#if !defined(TARGET_ARM) && !defined(TARGET_ARM64)
                /* this seems to trigger a gcc compilation bug sometime (hreg is 0) */
+               /* On arm64, rgctx_reg is a global hreg, and it is used to pass an argument */
                g_assert (! is_global_ireg (hreg));
 #endif
 
@@ -1124,7 +1125,7 @@ mono_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb)
                desc_to_fixed_reg_inited = TRUE;
 
                /* Validate the cpu description against the info in mini-ops.h */
-#if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_ARM)
+#if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_ARM) || defined(TARGET_ARM64)
                for (i = OP_LOAD; i < OP_LAST; ++i) {
                        const char *ispec;
 
index bc6a1aabb6c037c6cc5487edbbf7fac0c160404e..a2e1f2f602962a8cbbfd3298c117031e0e00e691 100644 (file)
@@ -436,6 +436,9 @@ static int callee_saved_regs [] = { AMD64_RBP, AMD64_RBX, AMD64_R12, AMD64_R13,
 static int callee_saved_regs [] = { X86_EBX, X86_ESI, X86_EDI };
 #elif defined(TARGET_ARM)
 static int callee_saved_regs [] = { ARMREG_V1, ARMREG_V2, ARMREG_V3, ARMREG_V4, ARMREG_V5, ARMREG_V7, ARMREG_FP };
+#elif defined(TARGET_ARM64)
+// FIXME:
+static int callee_saved_regs [] = { };
 #elif defined(TARGET_S390X)
 static int callee_saved_regs [] = { s390_r6, s390_r7, s390_r8, s390_r9, s390_r10, s390_r11, s390_r12, s390_r13, s390_r14 };
 #endif
index bccdb295d44e363a3d6ea038531d1a05f8b6821c..b1a31ee16d760a892f4782aa404a173625e0442f 100644 (file)
@@ -1033,9 +1033,11 @@ MINI_OP(OP_PPC_SUBFZE,             "ppc_subfze", IREG, IREG, NONE)
 MINI_OP(OP_CHECK_FINITE,           "ppc_check_finite", NONE, IREG, NONE)
 #endif
 
-#if defined(TARGET_ARM)
+#if defined(TARGET_ARM) || defined(TARGET_ARM64)
 MINI_OP(OP_ARM_RSBS_IMM,            "arm_rsbs_imm", IREG, IREG, NONE)
 MINI_OP(OP_ARM_RSC_IMM,             "arm_rsc_imm", IREG, IREG, NONE)
+/* Set dreg to an r4 value */
+MINI_OP(OP_ARM_SETFREG_R4,             "arm_setfreg_r4", FREG, FREG, NONE)
 #endif
 
 #if defined(__sparc__) || defined(sparc)
@@ -1238,6 +1240,15 @@ MINI_OP(OP_MIPS_COND_EXC_INC, "mips_cond_exc_inc", NONE, IREG, IREG)
 
 #endif
 
+#if defined(TARGET_ARM64)
+/* Branch if sreg1 == 0 */
+MINI_OP(OP_ARM64_CBZW, "arm64_cbzw", NONE, IREG, NONE)
+MINI_OP(OP_ARM64_CBZX, "arm64_cbzx", NONE, IREG, NONE)
+/* Branch if sreg1 != 0 */
+MINI_OP(OP_ARM64_CBNZW, "arm64_cbnzw", NONE, IREG, NONE)
+MINI_OP(OP_ARM64_CBNZX, "arm64_cbnzx", NONE, IREG, NONE)
+#endif
+
 /* Same as OUTARG_VT, but has a dreg */
 #ifdef ENABLE_LLVM
 MINI_OP(OP_LLVM_OUTARG_VT,     "llvm_outarg_vt", IREG, VREG, NONE)
index 09183038c99b5b271a28af5c7a699a8320996764..537a0bbfdcc22a7e95e355bedd894054188cfb8c 100644 (file)
@@ -673,7 +673,7 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, guint8* tram
                                }
                        }
                        if (!no_patch)
-                               mono_aot_patch_plt_entry (plt_entry, NULL, regs, addr);
+                               mono_aot_patch_plt_entry (code, plt_entry, NULL, regs, addr);
                } else {
                        if (generic_shared) {
                                if (m->wrapper_type != MONO_WRAPPER_NONE)
@@ -869,7 +869,7 @@ mono_aot_trampoline (mgreg_t *regs, guint8 *code, guint8 *token_info,
        plt_entry = mono_aot_get_plt_entry (code);
        g_assert (plt_entry);
 
-       mono_aot_patch_plt_entry (plt_entry, NULL, regs, addr);
+       mono_aot_patch_plt_entry (code, plt_entry, NULL, regs, addr);
 
        return addr;
 }
@@ -917,7 +917,7 @@ mono_class_init_trampoline (mgreg_t *regs, guint8 *code, MonoVTable *vtable, gui
 
        if (vtable->initialized) {
                if (plt_entry)
-                       mono_arch_patch_plt_entry (plt_entry, NULL, regs, mini_get_nullified_class_init_trampoline ());
+                       mono_aot_patch_plt_entry (code, plt_entry, NULL, regs, mini_get_nullified_class_init_trampoline ());
                else
                        mono_arch_nullify_class_init_trampoline (code, regs);
        }
index 110540968a2a6121ddced521f828225725b73724..3a9ff6b7c2765f9c91d810df2d9cca58f980cf2b 100644 (file)
@@ -2405,6 +2405,8 @@ register_opcode_emulation (int opcode, const char *name, const char *sigstr, gpo
 /*
  * For JIT icalls implemented in C.
  * NAME should be the same as the name of the C function whose address is FUNC.
+ * If SAVE is TRUE, no wrapper is generated. This is for perf critical icalls which
+ * can't throw exceptions.
  */
 static void
 register_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
@@ -7622,7 +7624,7 @@ mini_init (const char *filename, const char *runtime_version)
 #endif
 
 #ifdef TARGET_IOS
-       register_icall (pthread_getspecific, "pthread_getspecific", NULL, TRUE);
+       register_icall (pthread_getspecific, "pthread_getspecific", "ptr ptr", TRUE);
 #endif
 
        mono_generic_sharing_init ();
index 3870d7b65c3d171b967dbcf0ab57cf0bd2f80854..664788b5f5bad8a8d644d518d038974851417de7 100644 (file)
@@ -2126,7 +2126,7 @@ gboolean  mono_aot_get_cached_class_info    (MonoClass *klass, MonoCachedClassIn
 gboolean  mono_aot_get_class_from_name      (MonoImage *image, const char *name_space, const char *name, MonoClass **klass) MONO_INTERNAL;
 MonoJitInfo* mono_aot_find_jit_info         (MonoDomain *domain, MonoImage *image, gpointer addr) MONO_INTERNAL;
 gpointer mono_aot_plt_resolve               (gpointer aot_module, guint32 plt_info_offset, guint8 *code) MONO_INTERNAL;
-void     mono_aot_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint8 *addr) MONO_INTERNAL;
+void     mono_aot_patch_plt_entry           (guint8 *code, guint8 *plt_entry, gpointer *got, mgreg_t *regs, guint8 *addr) MONO_INTERNAL;
 gpointer mono_aot_get_method_from_vt_slot   (MonoDomain *domain, MonoVTable *vtable, int slot) MONO_INTERNAL;
 gpointer mono_aot_create_specific_trampoline   (MonoImage *image, gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len) MONO_INTERNAL;
 gpointer mono_aot_get_trampoline            (const char *name) MONO_INTERNAL;
diff --git a/mono/mini/tramp-arm64.c b/mono/mini/tramp-arm64.c
new file mode 100644 (file)
index 0000000..1650437
--- /dev/null
@@ -0,0 +1 @@
+#include "../../../mono-extensions/mono/mini/tramp-arm64.c"
index 018ad903e40307776f205a93c9962bc66d260e4b..87b71984b50aeede7075664d4c8bc1207829a17c 100644 (file)
@@ -56,6 +56,15 @@ static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
 #define NUM_REGS 272
 #define DWARF_DATA_ALIGN (-4)
 #define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (ARMREG_LR))
+#elif defined(TARGET_ARM64)
+/* +1 is for pc */
+#define NUM_REGS (32 + 1)
+#define DWARF_DATA_ALIGN (-8)
+#define DWARF_PC_REG 32
+static int map_hw_reg_to_dwarf_reg [] = {
+       0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+       16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
+};
 #elif defined (TARGET_X86)
 #ifdef __APPLE__
 /*
index 997dac1d8961b096bd48f1bb6ba956e8067a6496..0bf8f486bc67f2b34e513a5eb8fa03f829dd925e 100644 (file)
@@ -914,7 +914,12 @@ SGEN_CONFIGURATIONS =      \
        "major=marksweep-conc|ms-conc"  \
        "major=marksweep-conc,minor=split|ms-conc-split"        \
        "minor=split|ms-split"  \
-       "minor=split,alloc-ratio=95|ms-split-95"
+       "minor=split,alloc-ratio=95|ms-split-95"        \
+       "|plain-clear-at-gc|clear-at-gc"        \
+       "major=marksweep-par|ms-par-clear-at-gc|clear-at-gc"    \
+       "major=marksweep-conc|ms-conc-clear-at-gc|clear-at-gc"  \
+       "minor=split|ms-split-clear-at-gc|clear-at-gc"
+
 
 #FIXME We should move to use SGEN_CONFIGURATIONS once sgen supports trailling commas or its argument list.
 SGEN_BRIDGE_CONFIGURATIONS =   \
@@ -935,8 +940,9 @@ sgen-regular-tests: $(SGEN_TESTS)
                for conf in $(SGEN_CONFIGURATIONS); do  \
                        name=`echo $$conf | cut -d\| -f 2`;     \
                        params=`echo $$conf | cut -d\| -f 1`;   \
+                       debug_opt=`echo $$conf | cut -d\| -f 3`;        \
                        test_name="$${test}|$${name}";  \
-                       if MONO_GC_PARAMS="$$params" MONO_ENV_OPTIONS="--gc=sgen" $(srcdir)/test-driver '$(with_mono_path) $(JITTEST_PROG_RUN)' $$test_name "$(DISABLED_TESTS_SGEN)" "$${dump_action}" $(RUNTIME_ARGS); \
+                       if MONO_GC_PARAMS="$$params" MONO_ENV_OPTIONS="--gc=sgen" MONO_GC_DEBUG="$$debug_opt" $(srcdir)/test-driver '$(with_mono_path) $(JITTEST_PROG_RUN)' $$test_name "$(DISABLED_TESTS_SGEN)" "$${dump_action}" $(RUNTIME_ARGS);     \
                        then \
                                passed=`expr $${passed} + 1`; \
                        else \
index 9af5b9128f039da9837f6fc81669ced2d47108a3..c67434d7b4b8a5c7c90433bbe45d7a4d96427d75 100644 (file)
@@ -128,6 +128,10 @@ if ARM
 arch_sources += mach-support-arm.c
 endif
 
+if ARM64
+arch_sources += mach-support-arm.c
+endif
+
 else
 
 arch_sources += mach-support-unknown.c
@@ -146,6 +150,10 @@ if ARM
 arch_sources += mono-hwcap-arm.c mono-hwcap-arm.h
 endif
 
+if ARM64
+arch_sources += mono-hwcap-arm64.c mono-hwcap-arm64.h
+endif
+
 if MIPS
 arch_sources += mono-hwcap-mips.c mono-hwcap-mips.h
 endif
index 5f242752ef75d6e211a390373268f94e92bc4bb2..eb1e009bfc20c8648ef993432ee01ef1f7f25cda 100644 (file)
@@ -45,66 +45,113 @@ static int tls_vector_offset;
 void *
 mono_mach_arch_get_ip (thread_state_t state)
 {
+       /* Can't use unified_thread_state on !ARM64 since this has to compile on armv6 too */
+#ifdef TARGET_ARM64
+       arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state;
+
+       return (void *) arch_state->ts_64.__pc;
+#else
        arm_thread_state_t *arch_state = (arm_thread_state_t *) state;
 
        return (void *) arch_state->__pc;
+#endif
 }
 
 void *
 mono_mach_arch_get_sp (thread_state_t state)
 {
+#ifdef TARGET_ARM64
+       arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state;
+
+       return (void *) arch_state->ts_64.__sp;
+#else
        arm_thread_state_t *arch_state = (arm_thread_state_t *) state;
 
        return (void *) arch_state->__sp;
+#endif
 }
 
 int
 mono_mach_arch_get_mcontext_size ()
 {
+#ifdef TARGET_ARM64
+       return sizeof (struct __darwin_mcontext64);
+#else
        return sizeof (struct __darwin_mcontext);
+#endif
 }
 
 void
 mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context)
 {
+#ifdef TARGET_ARM64
+       arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state;
+       struct __darwin_mcontext64 *ctx = (struct __darwin_mcontext64 *) context;
+
+       ctx->__ss = arch_state->ts_64;
+#else
        arm_thread_state_t *arch_state = (arm_thread_state_t *) state;
        struct __darwin_mcontext *ctx = (struct __darwin_mcontext *) context;
 
        ctx->__ss = *arch_state;
+#endif
 }
 
 void
 mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state)
 {
+#ifdef TARGET_ARM64
+       arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state;
+       struct __darwin_mcontext64 *ctx = (struct __darwin_mcontext64 *) context;
+
+       arch_state->ts_64 = ctx->__ss;
+#else
        arm_thread_state_t *arch_state = (arm_thread_state_t *) state;
        struct __darwin_mcontext *ctx = (struct __darwin_mcontext *) context;
 
        *arch_state = ctx->__ss;
+#endif
 }
 
 int
 mono_mach_arch_get_thread_state_size ()
 {
+#ifdef TARGET_ARM64
+       return sizeof (arm_unified_thread_state_t);
+#else
        return sizeof (arm_thread_state_t);
+#endif
 }
 
 kern_return_t
 mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count)
 {
+#ifdef TARGET_ARM64
+       arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state;
+       kern_return_t ret;
+
+       *count = ARM_UNIFIED_THREAD_STATE_COUNT;
+
+       ret = thread_get_state (thread, ARM_UNIFIED_THREAD_STATE, (thread_state_t) arch_state, count);
+#else
        arm_thread_state_t *arch_state = (arm_thread_state_t *) state;
        kern_return_t ret;
 
        *count = ARM_THREAD_STATE_COUNT;
 
        ret = thread_get_state (thread, ARM_THREAD_STATE, (thread_state_t) arch_state, count);
-
+#endif
        return ret;
 }
 
 kern_return_t
 mono_mach_arch_set_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count)
 {
+#ifdef TARGET_ARM64
+       return thread_set_state (thread, ARM_UNIFIED_THREAD_STATE_COUNT, state, count);
+#else
        return thread_set_state (thread, ARM_THREAD_STATE_COUNT, state, count);
+#endif
 }
 
 void *
index 55fd9850fc27e64d3ccbc43a4f96cb697cccbf40..8d8bb1e9037961460897556771b389e96d5fcfa7 100644 (file)
@@ -15,6 +15,8 @@
 #define MONO_MACH_ARCH_SUPPORTED 1
 #if defined(__arm__)
 typedef _STRUCT_MCONTEXT *mcontext_t;
+#elif defined(__aarch64__)
+typedef _STRUCT_MCONTEXT64 *mcontext_t;
 #endif
 
 // We need to define this here since we need _XOPEN_SOURCE for mono
index af2d9fbff5af9905fd2d526d7ee43624d5957cbf..9e468bfd6e098c36d53e81d51f0c181d19b4a2ca 100644 (file)
@@ -489,6 +489,9 @@ mono_code_manager_foreach (MonoCodeManager *cman, MonoCodeManagerFunc func, void
 #if defined(__arm__)
 #define BIND_ROOM 8
 #endif
+#if defined(TARGET_ARM64)
+#define BIND_ROOM 8
+#endif
 
 static CodeChunk*
 new_codechunk (CodeChunk *last, int dynamic, int size)
index a533a9f01e33867044ce77558d92992f1bfac588..22623d074fb5923ebc622041d261c894645e68b0 100644 (file)
 #endif
 #elif defined(__arm__) && defined(__ARM_EABI__) && !defined(PIC)
 #define MONO_THREAD_VAR_OFFSET(var,offset) __asm ("    ldr     %0, 1f; b 2f; 1: .word " #var "(tpoff); 2:" : "=r" (offset))
+#elif defined(__aarch64__) && !defined(PIC)
+#define MONO_THREAD_VAR_OFFSET(var,offset) \
+       __asm ( "mov %0, #0\n add %0, %0, #:tprel_hi12:" #var "\n add %0, %0, #:tprel_lo12_nc:" #var "\n" \
+                       : "=r" (offset))
 #elif defined(__mono_ppc__) && defined(__GNUC__)
 #if defined(PIC)
 #ifdef PIC_INITIAL_EXEC
index 81f3ca84ec30ae4da29072e8b9db66d8beb0a4d4..bc0286485fc008a9d5d7cdf3ba8e2dde36e92a80 100644 (file)
@@ -288,6 +288,38 @@ mono_monoctx_to_sigctx (MonoContext *mctx, void *ctx)
 #endif
 }
 
+#elif (defined(__aarch64__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_ARM64))
+
+#include <mono/utils/mono-context.h>
+
+void
+mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx)
+{
+#ifdef MONO_CROSS_COMPILE
+       g_assert_not_reached ();
+#else
+       memcpy (mctx->regs, UCONTEXT_GREGS (sigctx), sizeof (mgreg_t) * 31);
+       mctx->pc = UCONTEXT_REG_PC (sigctx);
+       mctx->regs [ARMREG_SP] = UCONTEXT_REG_SP (sigctx);
+       /*
+        * We don't handle fp regs, this is not currrently a
+        * problem, since we don't allocate them globally.
+        */
+#endif
+}
+
+void
+mono_monoctx_to_sigctx (MonoContext *mctx, void *sigctx)
+{
+#ifdef MONO_CROSS_COMPILE
+       g_assert_not_reached ();
+#else
+       memcpy (UCONTEXT_GREGS (sigctx), mctx->regs, sizeof (mgreg_t) * 31);
+       UCONTEXT_REG_PC (sigctx) = mctx->pc;
+       UCONTEXT_REG_SP (sigctx) = mctx->regs [ARMREG_SP];
+#endif
+}
+
 #elif (defined(__mips__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_MIPS))
 
 #include <mono/utils/mono-context.h>
index 84409cf1e77d9b0e3dc31d24a0862d342737bd46..a4d29461ca6251a4921961b679e03991ebedca3d 100755 (executable)
@@ -274,6 +274,57 @@ typedef struct {
        ctx.pc = ctx.regs [15];                 \
 } while (0)
 
+#elif (defined(__aarch64__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_ARM64))
+
+#include <mono/arch/arm64/arm64-codegen.h>
+
+typedef struct {
+       mgreg_t regs [32];
+       double fregs [32];
+       mgreg_t pc;
+} MonoContext;
+
+#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->pc = (mgreg_t)ip; } while (0)
+#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->regs [ARMREG_FP] = (mgreg_t)bp; } while (0);
+#define MONO_CONTEXT_SET_SP(ctx,bp) do { (ctx)->regs [ARMREG_SP] = (mgreg_t)bp; } while (0);
+
+#define MONO_CONTEXT_GET_IP(ctx) (gpointer)((ctx)->pc)
+#define MONO_CONTEXT_GET_BP(ctx) (gpointer)((ctx)->regs [ARMREG_FP])
+#define MONO_CONTEXT_GET_SP(ctx) (gpointer)((ctx)->regs [ARMREG_SP])
+
+#define MONO_CONTEXT_GET_CURRENT(ctx)  do {    \
+       __asm__ __volatile__(                   \
+               "mov x16, %0\n" \
+               "stp x0, x1, [x16], #16\n"      \
+               "stp x2, x3, [x16], #16\n"      \
+               "stp x4, x5, [x16], #16\n"      \
+               "stp x6, x7, [x16], #16\n"      \
+               "stp x8, x9, [x16], #16\n"      \
+               "stp x10, x11, [x16], #16\n"    \
+               "stp x12, x13, [x16], #16\n"    \
+               "stp x14, x15, [x16], #16\n"    \
+               "stp xzr, x17, [x16], #16\n"    \
+               "stp x18, x19, [x16], #16\n"    \
+               "stp x20, x21, [x16], #16\n"    \
+               "stp x22, x23, [x16], #16\n"    \
+               "stp x24, x25, [x16], #16\n"    \
+               "stp x26, x27, [x16], #16\n"    \
+               "stp x28, x29, [x16], #16\n"    \
+               "stp x30, xzr, [x16]\n" \
+               "mov x30, sp\n"                         \
+               "str x30, [x16, #8]\n"          \
+               :                                                       \
+               : "r" (&ctx.regs)                       \
+               : "x30", "memory"                       \
+       );                                                              \
+       __asm__ __volatile__( \
+               "adr %0, L0\n" \
+               "L0:\n" \
+               : "=r" (ctx.pc)         \
+               :                                       \
+               : "memory"                       \
+       ); \
+} while (0)
 
 #elif defined(__mono_ppc__) /* defined(__arm__) */
 
diff --git a/mono/utils/mono-hwcap-arm64.c b/mono/utils/mono-hwcap-arm64.c
new file mode 100644 (file)
index 0000000..5149cc0
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * mono-hwcap-arm64.c: ARM hardware feature detection
+ *
+ * Copyright 2013 Xamarin Inc
+ */
+
+#include "mono/utils/mono-hwcap-arm64.h"
+
+#if defined(MONO_CROSS_COMPILE)
+void
+mono_hwcap_arch_init (void)
+{
+}
+#else
+void
+mono_hwcap_arch_init (void)
+{
+}
+#endif
+
+void
+mono_hwcap_print(FILE *f)
+{
+}
diff --git a/mono/utils/mono-hwcap-arm64.h b/mono/utils/mono-hwcap-arm64.h
new file mode 100644 (file)
index 0000000..2d41209
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __MONO_UTILS_HWCAP_ARM64_H__
+#define __MONO_UTILS_HWCAP_ARM64_H__
+
+#include "mono/utils/mono-hwcap.h"
+
+#endif
index 03247cf02a68d33381c602bbfb89d4a9527e4f2d..daa82bbef3742d8ea07529776eefc31589ced3cf 100644 (file)
@@ -355,6 +355,30 @@ typedef struct ucontext {
        #define UCONTEXT_REG_R12(ctx) (((arm_ucontext*)(ctx))->sig_ctx.arm_ip)
        #define UCONTEXT_REG_CPSR(ctx) (((arm_ucontext*)(ctx))->sig_ctx.arm_cpsr)
 #endif
+
+#elif defined(TARGET_ARM64)
+
+#if defined(MONO_CROSS_COMPILE)
+       #define UCONTEXT_REG_PC(ctx) NULL
+       #define UCONTEXT_REG_SP(ctx) NULL
+       #define UCONTEXT_REG_R0(ctx) NULL
+       #define UCONTEXT_GREGS(ctx) NULL
+#elif defined(__APPLE__)
+#include <machine/_mcontext.h>
+#include <sys/_types/_ucontext64.h>
+       /* mach/arm/_structs.h */
+       #define UCONTEXT_REG_PC(ctx) (((ucontext64_t*)(ctx))->uc_mcontext64->__ss.__pc)
+       #define UCONTEXT_REG_SP(ctx) (((ucontext64_t*)(ctx))->uc_mcontext64->__ss.__sp)
+       #define UCONTEXT_REG_R0(ctx) (((ucontext64_t*)(ctx))->uc_mcontext64->__ss.__x [ARMREG_R0])
+       #define UCONTEXT_GREGS(ctx) (&(((ucontext64_t*)(ctx))->uc_mcontext64->__ss.__x))
+#else
+#include <ucontext.h>
+       #define UCONTEXT_REG_PC(ctx) (((ucontext_t*)(ctx))->uc_mcontext.pc)
+       #define UCONTEXT_REG_SP(ctx) (((ucontext_t*)(ctx))->uc_mcontext.sp)
+       #define UCONTEXT_REG_R0(ctx) (((ucontext_t*)(ctx))->uc_mcontext.regs [ARMREG_R0])
+       #define UCONTEXT_GREGS(ctx) (&(((ucontext_t*)(ctx))->uc_mcontext.regs))
+#endif
+
 #elif defined(__mips__)
 
 # if HAVE_UCONTEXT_H
index ec4220838f2939a4da12e6a91ef51f7cd7964d67..0e95d4e878e6eb1c7f3789dc8c13b92fdd456731 100644 (file)
@@ -72,7 +72,20 @@ mono_threads_install_dead_letter (void)
        dict = objc_msgSend (cur, threadDictionary);
        if (dict && objc_msgSend (dict, objectForKey, mono_dead_letter_key) == nil) {
                id value = objc_msgSend (objc_msgSend ((id)mono_dead_letter_class, alloc), init);
+
+#ifdef TARGET_ARM64
+               /*
+                * See the 'Dispatch Objective-C Messages Using the Method Function’s Prototype' section in
+                * the '64-Bit Transition Guide for Cocoa Touch' as to why this is required.
+                */
+               {
+                       void (*action)(id, SEL, id, id) = (void (*)(id, SEL, id, id)) objc_msgSend;
+                       action (dict, setObjectForKey, value, mono_dead_letter_key);
+               }
+#else
                objc_msgSend (dict, setObjectForKey, value, mono_dead_letter_key);
+#endif
+
                objc_msgSend (value, release);
        }
 }
@@ -84,6 +97,7 @@ mono_threads_init_dead_letter (void)
        id nsautoreleasepool = objc_getClass ("NSAutoreleasePool");
        SEL stringWithUTF8String = sel_registerName ("stringWithUTF8String:");
        SEL retain = sel_registerName ("retain");
+       id pool;
 
        nsthread = (Class)objc_getClass ("NSThread");
        nsobject = (Class)objc_getClass ("NSObject");
@@ -105,8 +119,17 @@ mono_threads_init_dead_letter (void)
        objc_registerClassPair (mono_dead_letter_class);
 
        // create the dict key
-       id pool = objc_msgSend (objc_msgSend (nsautoreleasepool, alloc), init);
+       pool = objc_msgSend (objc_msgSend (nsautoreleasepool, alloc), init);
+
+#ifdef TARGET_ARM64
+       {
+               id (*action)(id, SEL, char*) = (id (*)(id, SEL, char*)) objc_msgSend;
+               mono_dead_letter_key = action(nsstring, stringWithUTF8String, "mono-dead-letter");
+       }
+#else
        mono_dead_letter_key = objc_msgSend (nsstring, stringWithUTF8String, "mono-dead-letter");
+#endif
+
        objc_msgSend (mono_dead_letter_key, retain);
        objc_msgSend (pool, release);
 }
index e8011d350f9e75139ac87b62f6fd2c6aac05e47a..2f0e3ad5916513b7bc7bb2033df8163cf2994fed 100644 (file)
@@ -87,7 +87,11 @@ mono_threads_core_resume (MonoThreadInfo *info)
                        return FALSE;
 
                mono_mach_arch_thread_state_to_mcontext (state, mctx);
+#ifdef TARGET_ARM64
+               g_assert_not_reached ();
+#else
                uctx.uc_mcontext = mctx;
+#endif
                mono_monoctx_to_sigctx (&tmp, &uctx);
 
                mono_mach_arch_mcontext_to_thread_state (mctx, state);