diff --git a/Makefile.in b/Makefile.in
index db4fa6c6260..9d91d1d8efa 100644
--- Makefile.in
+++ Makefile.in
@@ -338,6 +338,7 @@ RAW_CXX_TARGET_EXPORTS = \
 
 NORMAL_TARGET_EXPORTS = \
 	$(BASE_TARGET_EXPORTS) \
+	CXX_FOR_TARGET="$(CXX_FOR_TARGET)"; export CXX_FOR_TARGET; \
 	CXX="$(CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export CXX;
 
 # Where to find GMP
diff --git a/Makefile.tpl b/Makefile.tpl
index 1d5813cd569..1ebadce64f9 100644
--- Makefile.tpl
+++ Makefile.tpl
@@ -341,6 +341,7 @@ RAW_CXX_TARGET_EXPORTS = \
 
 NORMAL_TARGET_EXPORTS = \
 	$(BASE_TARGET_EXPORTS) \
+	CXX_FOR_TARGET="$(CXX_FOR_TARGET)"; export CXX_FOR_TARGET; \
 	CXX="$(CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export CXX;
 
 # Where to find GMP
diff --git a/configure b/configure
index 3b0abeb8b2e..f7a7da118cc 100755
--- configure
+++ configure
@@ -3518,6 +3518,8 @@ esac
 
 # Disable libffi for some systems.
 case "${target}" in
+  aarch64*-*-darwin2*)
+    ;;
   powerpc-*-darwin*)
     ;;
   i[3456789]86-*-darwin*)
diff --git a/configure.ac b/configure.ac
index 042681c27be..21218446587 100644
--- configure.ac
+++ configure.ac
@@ -747,6 +747,8 @@ esac
 
 # Disable libffi for some systems.
 case "${target}" in
+  aarch64*-*-darwin2*)
+    ;;
   powerpc-*-darwin*)
     ;;
   i[[3456789]]86-*-darwin*)
diff --git a/fixincludes/fixincl.x b/fixincludes/fixincl.x
index 45d65f4872a..7b2cde88854 100644
--- fixincludes/fixincl.x
+++ fixincludes/fixincl.x
@@ -2,11 +2,11 @@
  *
  * DO NOT EDIT THIS FILE   (fixincl.x)
  *
- * It has been AutoGen-ed  April  1, 2025 at 03:28:07 PM by AutoGen 5.18.16
+ * It has been AutoGen-ed  May 15, 2025 at 08:18:24 PM by AutoGen 5.18.16
  * From the definitions    inclhack.def
  * and the template file   fixincl
  */
-/* DO NOT SVN-MERGE THIS FILE, EITHER Tue Apr  1 15:28:07 BST 2025
+/* DO NOT SVN-MERGE THIS FILE, EITHER Thu May 15 20:18:24 BST 2025
  *
  * You must regenerate it.  Use the ./genfixes script.
  *
@@ -15,7 +15,7 @@
  * certain ANSI-incompatible system header files which are fixed to work
  * correctly with ANSI C and placed in a directory that GNU C will search.
  *
- * This file contains 274 fixup descriptions.
+ * This file contains 272 fixup descriptions.
  *
  * See README for more information.
  *
@@ -267,56 +267,6 @@ static const char* apzAab_Darwin7_9_Long_Double_FuncsPatch[] = {
 #endif /* __MATH__ */",
     (char*)NULL };
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- *  Description of Darwin_Api_Availability fix
- */
-tSCC zDarwin_Api_AvailabilityName[] =
-     "darwin_api_availability";
-
-/*
- *  File name selection pattern
- */
-tSCC zDarwin_Api_AvailabilityList[] =
-  "os/availability.h\0";
-/*
- *  Machine/OS name selection pattern
- */
-tSCC* apzDarwin_Api_AvailabilityMachs[] = {
-        "*-*-darwin*",
-        (const char*)NULL };
-
-/*
- *  content selection pattern - do fix if pattern found
- */
-tSCC zDarwin_Api_AvailabilitySelect0[] =
-       " *#define __API_AVAILABLE.*\n\
- *#define __API_DEPRECATED.*\n\
- *#define __API_DEPRECATED_WITH_REPLACEMENT.*\n\
- *#define __API_UNAVAILABLE.*\n";
-
-/*
- *  content bypass pattern - skip fix if pattern found
- */
-tSCC zDarwin_Api_AvailabilityBypass0[] =
-       "__IPHONE_OS_VERSION_MIN_REQUIRED";
-
-#define    DARWIN_API_AVAILABILITY_TEST_CT  2
-static tTestDesc aDarwin_Api_AvailabilityTests[] = {
-  { TT_NEGREP,   zDarwin_Api_AvailabilityBypass0, (regex_t*)NULL },
-  { TT_EGREP,    zDarwin_Api_AvailabilitySelect0, (regex_t*)NULL }, };
-
-/*
- *  Fix Command Arguments for Darwin_Api_Availability
- */
-static const char* apzDarwin_Api_AvailabilityPatch[] = {
-    "format",
-    "    #define API_AVAILABLE(...)\n\
-    #define API_DEPRECATED(...)\n\
-    #define API_DEPRECATED_WITH_REPLACEMENT(...)\n\
-    #define API_UNAVAILABLE(...)\n",
-    (char*)NULL };
-
 /* * * * * * * * * * * * * * * * * * * * * * * * * *
  *
  *  Description of Aab_Fd_Zero_Asm_Posix_Types_H fix
@@ -2763,51 +2713,6 @@ extern \"C\" {\n\
 #endif\n",
     (char*)NULL };
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- *  Description of Darwin_Availabilityinternal fix
- */
-tSCC zDarwin_AvailabilityinternalName[] =
-     "darwin_availabilityinternal";
-
-/*
- *  File name selection pattern
- */
-tSCC zDarwin_AvailabilityinternalList[] =
-  "AvailabilityInternal.h\0";
-/*
- *  Machine/OS name selection pattern
- */
-tSCC* apzDarwin_AvailabilityinternalMachs[] = {
-        "*-*-darwin*",
-        (const char*)NULL };
-
-/*
- *  content selection pattern - do fix if pattern found
- */
-tSCC zDarwin_AvailabilityinternalSelect0[] =
-       "#define[ \t]+(__API_[ADU]\\([^)]*\\)).*";
-
-#define    DARWIN_AVAILABILITYINTERNAL_TEST_CT  1
-static tTestDesc aDarwin_AvailabilityinternalTests[] = {
-  { TT_EGREP,    zDarwin_AvailabilityinternalSelect0, (regex_t*)NULL }, };
-
-/*
- *  Fix Command Arguments for Darwin_Availabilityinternal
- */
-static const char* apzDarwin_AvailabilityinternalPatch[] = {
-    "format",
-    "#if defined(__has_attribute)\n\
-  #if __has_attribute(availability)\n\
-%0\n\
-  #else\n\
-    #define %1\n\
-  #endif\n\
-#else\n\
-    #define %1\n\
-#endif",
-    (char*)NULL };
-
 /* * * * * * * * * * * * * * * * * * * * * * * * * *
  *
  *  Description of Darwin_9_Long_Double_Funcs_2 fix
@@ -11169,9 +11074,9 @@ static const char* apzX11_SprintfPatch[] = {
  *
  *  List of all fixes
  */
-#define REGEX_COUNT          313
+#define REGEX_COUNT          310
 #define MACH_LIST_SIZE_LIMIT 187
-#define FIX_COUNT            274
+#define FIX_COUNT            272
 
 /*
  *  Enumerate the fixes
@@ -11180,7 +11085,6 @@ typedef enum {
     AAB_AIX_STDIO_FIXIDX,
     AAB_AIX_FCNTL_FIXIDX,
     AAB_DARWIN7_9_LONG_DOUBLE_FUNCS_FIXIDX,
-    DARWIN_API_AVAILABILITY_FIXIDX,
     AAB_FD_ZERO_ASM_POSIX_TYPES_H_FIXIDX,
     AAB_FD_ZERO_GNU_TYPES_H_FIXIDX,
     AAB_FD_ZERO_SELECTBITS_H_FIXIDX,
@@ -11242,7 +11146,6 @@ typedef enum {
     CTRL_QUOTES_DEF_FIXIDX,
     CTRL_QUOTES_USE_FIXIDX,
     CXX_UNREADY_FIXIDX,
-    DARWIN_AVAILABILITYINTERNAL_FIXIDX,
     DARWIN_9_LONG_DOUBLE_FUNCS_2_FIXIDX,
     DARWIN_EXTERNC_FIXIDX,
     DARWIN_GCC4_BREAKAGE_FIXIDX,
@@ -11469,11 +11372,6 @@ tFixDesc fixDescList[ FIX_COUNT ] = {
      AAB_DARWIN7_9_LONG_DOUBLE_FUNCS_TEST_CT, FD_MACH_ONLY | FD_REPLACEMENT,
      aAab_Darwin7_9_Long_Double_FuncsTests,   apzAab_Darwin7_9_Long_Double_FuncsPatch, 0 },
 
-  {  zDarwin_Api_AvailabilityName,    zDarwin_Api_AvailabilityList,
-     apzDarwin_Api_AvailabilityMachs,
-     DARWIN_API_AVAILABILITY_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
-     aDarwin_Api_AvailabilityTests,   apzDarwin_Api_AvailabilityPatch, 0 },
-
   {  zAab_Fd_Zero_Asm_Posix_Types_HName,    zAab_Fd_Zero_Asm_Posix_Types_HList,
      apzAab_Fd_Zero_Asm_Posix_Types_HMachs,
      AAB_FD_ZERO_ASM_POSIX_TYPES_H_TEST_CT, FD_MACH_ONLY | FD_REPLACEMENT,
@@ -11779,11 +11677,6 @@ tFixDesc fixDescList[ FIX_COUNT ] = {
      CXX_UNREADY_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
      aCxx_UnreadyTests,   apzCxx_UnreadyPatch, 0 },
 
-  {  zDarwin_AvailabilityinternalName,    zDarwin_AvailabilityinternalList,
-     apzDarwin_AvailabilityinternalMachs,
-     DARWIN_AVAILABILITYINTERNAL_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
-     aDarwin_AvailabilityinternalTests,   apzDarwin_AvailabilityinternalPatch, 0 },
-
   {  zDarwin_9_Long_Double_Funcs_2Name,    zDarwin_9_Long_Double_Funcs_2List,
      apzDarwin_9_Long_Double_Funcs_2Machs,
      DARWIN_9_LONG_DOUBLE_FUNCS_2_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
diff --git a/fixincludes/inclhack.def b/fixincludes/inclhack.def
index 67a1082f926..560b455717e 100644
--- fixincludes/inclhack.def
+++ fixincludes/inclhack.def
@@ -194,33 +194,6 @@ fix = {
 	_EndOfHeader_;
 };
 
-/*
- *  SDKs for 10.13 and 10.14 omit the definitions for API_AVAILABLE where
- *  __attribute__((availability)) is not supported.
- */
-fix = {
-    hackname  = darwin_api_availability;
-    mach      = "*-*-darwin*";
-    files     = os/availability.h;
-    bypass    = "__IPHONE_OS_VERSION_MIN_REQUIRED";
-    select    =
-    " *#define __API_AVAILABLE.*\n"
-    " *#define __API_DEPRECATED.*\n"
-    " *#define __API_DEPRECATED_WITH_REPLACEMENT.*\n"
-    " *#define __API_UNAVAILABLE.*\n";
-    c_fix     = format;
-    c_fix_arg =
-    "    #define API_AVAILABLE(...)\n"
-    "    #define API_DEPRECATED(...)\n"
-    "    #define API_DEPRECATED_WITH_REPLACEMENT(...)\n"
-    "    #define API_UNAVAILABLE(...)\n";
-    test_text =
-    "#define __API_AVAILABLE(...)\n"
-    "#define __API_DEPRECATED(...)\n"
-    "#define __API_DEPRECATED_WITH_REPLACEMENT(...)\n"
-    "#define __API_UNAVAILABLE(...)\n";
-};
-
 /*
  *  This fixes __FD_ZERO bug for linux 2.x.y (x <= 2 && y <= some n)
  */
@@ -1351,32 +1324,6 @@ fix = {
     test_text = "extern void* malloc( size_t );";
 };
 
-/*
- *  macOS 10.12 <AvailabilityInternal.h> uses __attribute__((availability))
- *  unconditionally.
- */
-fix = {
-    hackname  = darwin_availabilityinternal;
-    mach      = "*-*-darwin*";
-    files     = AvailabilityInternal.h;
-    select    = "#define[ \t]+(__API_[ADU]\\([^)]*\\)).*";
-    c_fix     = format;
-    c_fix_arg = <<- _EOFix_
-	#if defined(__has_attribute)
-	  #if __has_attribute(availability)
-	%0
-	  #else
-	    #define %1
-	  #endif
-	#else
-	    #define %1
-	#endif
-	_EOFix_;
-
-    test_text = "#define __API_A(x) __attribute__((availability(__API_AVAILABLE_PLATFORM_##x)))\n"
-		"#define __API_D(msg,x) __attribute__((availability(__API_DEPRECATED_PLATFORM_##x,message=msg)))";
-};
-
 /*
  *  For the AAB_darwin7_9_long_double_funcs fix (and later fixes for long long)
  *  to be useful, the main math.h must use <> and not "" includes.
diff --git a/gcc/ada/init.c b/gcc/ada/init.c
index 7cf77471f1d..8d5acdd6fb6 100644
--- gcc/ada/init.c
+++ gcc/ada/init.c
@@ -2479,7 +2479,10 @@ __gnat_map_signal (int sig, siginfo_t *si, void *mcontext ATTRIBUTE_UNUSED)
       /* Reset the use of alt stack, so that the alt stack will be used
 	 for the next signal delivery.
 	 The stack can't be used in case of stack checking.  */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
       syscall (SYS_sigreturn, NULL, UC_RESET_ALT_STACK);
+#pragma GCC diagnostic pop
       break;
 
     case SIGFPE:
diff --git a/gcc/builtins.cc b/gcc/builtins.cc
index 3e0b590039f..73fa5bf84ee 100644
--- gcc/builtins.cc
+++ gcc/builtins.cc
@@ -5929,6 +5929,13 @@ expand_builtin_trap (void)
 static void
 expand_builtin_unreachable (void)
 {
+  /* If the target wants a trap in place of the fall-through, use that.  */
+  if (targetm.unreachable_should_trap ())
+    {
+      expand_builtin_trap ();
+      return;
+    }
+
   /* Use gimple_build_builtin_unreachable or builtin_decl_unreachable
      to avoid this.  */
   gcc_checking_assert (!sanitize_flags_p (SANITIZE_UNREACHABLE));
diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index 04e39b41bdf..6cb2637f3cf 100644
--- gcc/c-family/c-attribs.cc
+++ gcc/c-family/c-attribs.cc
@@ -665,6 +665,18 @@ attribute_takes_identifier_p (const_tree attr_id)
     return targetm.attribute_takes_identifier_p (attr_id);
 }
 
+/* Returns TRUE iff the attribute indicated by ATTR_ID needs its
+   arguments converted to string constants.  */
+
+bool
+attribute_clang_form_p (const_tree attr_id)
+{
+  const struct attribute_spec *spec = lookup_attribute_spec (attr_id);
+  if (spec && !strcmp ("availability", spec->name))
+    return true;
+  return false;
+}
+
 /* Verify that argument value POS at position ARGNO to attribute NAME
    applied to function FN (which is either a function declaration or function
    type) refers to a function parameter at position POS and the expected type
diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index 0d05694b6d0..11e35647c18 100644
--- gcc/c-family/c-common.cc
+++ gcc/c-family/c-common.cc
@@ -346,7 +346,11 @@ static constexpr hf_feature_info has_feature_table[] =
   { "enumerator_attributes",		  HF_FLAG_NONE, 0 },
   { "tls",				  HF_FLAG_NONE, 0 },
   { "gnu_asm_goto_with_outputs",	  HF_FLAG_EXT, 0 },
-  { "gnu_asm_goto_with_outputs_full",	  HF_FLAG_EXT, 0 }
+  { "gnu_asm_goto_with_outputs_full",	  HF_FLAG_EXT, 0 },
+  { "attribute_availability",		  HF_FLAG_NONE, 0 },
+  { "attribute_availability_with_message",  HF_FLAG_NONE, 0 },
+  { "attribute_availability_with_replacement",  HF_FLAG_NONE, 0 },
+  { "attribute_availability_with_version_underscores",  HF_FLAG_NONE, 0 }
 };
 
 /* Global visibility options.  */
@@ -384,8 +388,8 @@ static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT);
 */
 const struct c_common_resword c_common_reswords[] =
 {
-  { "_Alignas",		RID_ALIGNAS,   D_CONLY },
-  { "_Alignof",		RID_ALIGNOF,   D_CONLY },
+  { "_Alignas",		RID_ALIGNAS,   D_EXT_C_IN_CXX },
+  { "_Alignof",		RID_ALIGNOF,   D_EXT_C_IN_CXX },
   { "_Atomic",		RID_ATOMIC,    D_CONLY },
   { "_BitInt",		RID_BITINT,    D_CONLY },
   { "_Bool",		RID_BOOL,      D_CONLY },
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 8d8bead5030..325b2eca611 100644
--- gcc/c-family/c-common.h
+++ gcc/c-family/c-common.h
@@ -445,6 +445,8 @@ extern machine_mode c_default_pointer_mode;
 #define D_CXX20		0x8000  /* In C++, C++20 only.  */
 #define D_CXX_COROUTINES 0x10000  /* In C++, only with coroutines.  */
 #define D_CXX_MODULES	0x20000  /* In C++, only with modules.  */
+#define D_EXT_C_IN_CXX	0x40000  /* In C++, allow additional C keywords.  */
+#define D_EXT_CXX_IN_C	0x80000  /* In C, allow additional C++ keywords.  */
 
 #define D_CXX_CONCEPTS_FLAGS D_CXXONLY | D_CXX_CONCEPTS
 #define D_CXX_CHAR8_T_FLAGS D_CXXONLY | D_CXX_CHAR8_T
@@ -1635,6 +1637,7 @@ extern void check_for_xor_used_as_pow (location_t lhs_loc, tree lhs_val,
 /* In c-attribs.cc.  */
 extern bool attribute_takes_identifier_p (const_tree);
 extern tree handle_deprecated_attribute (tree *, tree, tree, int, bool *);
+extern bool attribute_clang_form_p (const_tree);
 extern tree handle_unused_attribute (tree *, tree, tree, int, bool *);
 extern tree handle_fallthrough_attribute (tree *, tree, tree, int, bool *);
 extern int parse_tm_stmt_attr (tree, int);
diff --git a/gcc/c-family/c-lex.cc b/gcc/c-family/c-lex.cc
index ff5ce2bf729..d5cc6fa43a9 100644
--- gcc/c-family/c-lex.cc
+++ gcc/c-family/c-lex.cc
@@ -584,6 +584,21 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
 
     case CPP_NUMBER:
       {
+	/* If the user wants number-like entities to be returned as a raw
+	   string, then don't try to classify them, which emits unwanted
+	   diagnostics.  */
+	if (lex_flags & C_LEX_NUMBER_AS_STRING)
+	  {
+	    /* build_string adds a trailing NUL at [len].  */
+	    tree num_string = build_string (tok->val.str.len + 1,
+					    (const char *) tok->val.str.text);
+	    TREE_TYPE (num_string) = char_array_type_node;
+	    *value = num_string;
+	    /* We will effectively note this as CPP_N_INVALID, because we
+	       made no checks here.  */
+	    break;
+	  }
+
 	const char *suffix = NULL;
 	unsigned int flags = cpp_classify_number (parse_in, tok, &suffix, *loc);
 
diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
index f4dced8d826..4b45f83ca05 100644
--- gcc/c-family/c-opts.cc
+++ gcc/c-family/c-opts.cc
@@ -1119,7 +1119,7 @@ c_common_post_options (const char **pfilename)
 
   if (flag_extern_tls_init)
     {
-      if (!TARGET_SUPPORTS_ALIASES || !SUPPORTS_WEAK)
+      if (!SUPPORTS_WEAK)
 	{
 	  /* Lazy TLS initialization for a variable in another TU requires
 	     alias and weak reference support.  */
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index ce93a52fa57..95828547713 100644
--- gcc/c-family/c-pragma.h
+++ gcc/c-family/c-pragma.h
@@ -276,6 +276,9 @@ extern void pragma_lex_discard_to_eol ();
 #define C_LEX_STRING_NO_JOIN	  2 /* Do not concatenate strings
 				       nor translate them into execution
 				       character set.  */
+#define C_LEX_NUMBER_AS_STRING	  4 /* Do not classify a number, but
+				       instead return it as a raw
+				       string.  */
 
 /* This is not actually available to pragma parsers.  It's merely a
    convenient location to declare this function for c-lex, after
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index b310b40d857..5969b53a7dc 100644
--- gcc/c-family/c.opt
+++ gcc/c-family/c.opt
@@ -1708,6 +1708,18 @@ static-libmpxwrappers
 Driver WarnRemoved
 Removed in GCC 9.  This switch has no effect.
 
+fallow-const-var-array-size
+C ObjC C++ ObjC++ LTO Var(flag_allow_const_var_array_size) Init(0)
+Allow arrays sizes to be const-qualified vars in C and Objective-C.
+
+fallow-extended-attribute-placement
+C ObjC C++ ObjC++ LTO Var(flag_allow_ext_attr_placement) Init(0)
+Allow placement of attributes on function definitions.
+
+fallow-extra-keywords
+C ObjC C++ ObjC++ LTO Var(flag_allow_extra_keywords) Init(0)
+Allow additional C keywords in C++ and vice versa.
+
 fcilkplus
 C ObjC C++ ObjC++ LTO Undocumented Ignore
 Removed in GCC 8.  This switch has no effect.
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 70f3faf6d68..b18b129e2c5 100644
--- gcc/c/c-decl.cc
+++ gcc/c/c-decl.cc
@@ -7273,6 +7273,25 @@ grokdeclarator (const struct c_declarator *declarator,
 		  }
 
 		size = c_fully_fold (size, false, &size_maybe_const);
+		bool size_const_var = false;
+		if (flag_allow_const_var_array_size)
+		  {
+		    tree maybe_const_size = TREE_CODE (size) == NOP_EXPR
+					    ? TREE_OPERAND (size, 0) : size;
+		    size_const_var
+		      = (TREE_CODE (maybe_const_size) == VAR_DECL
+			 && TREE_READONLY (maybe_const_size)
+			 && !TREE_THIS_VOLATILE (maybe_const_size));
+		    if (size_const_var
+			&& size_maybe_const
+			&& DECL_INITIAL (maybe_const_size))
+		      {
+			size = DECL_INITIAL (maybe_const_size);
+			size = c_fully_fold (size, false, &size_maybe_const);
+			size_int_const = (TREE_CODE (size) == INTEGER_CST
+					  && !TREE_OVERFLOW (size));
+		      }
+		  }
 
 		if (pedantic && size_maybe_const && integer_zerop (size))
 		  {
@@ -7314,6 +7333,9 @@ grokdeclarator (const struct c_declarator *declarator,
 			  this_size_varies = size_varies = true;
 			warn_variable_length_array (name, size);
 		      }
+		    if (flag_allow_const_var_array_size && size_const_var)
+		      pedwarn (input_location, OPT_Wpedantic,
+			       "variably modified %qE at file scope", name);
 		  }
 		else if ((decl_context == NORMAL || decl_context == FIELD)
 			 && current_scope == file_scope)
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index dccceb7a478..73205c24a47 100644
--- gcc/c/c-parser.cc
+++ gcc/c/c-parser.cc
@@ -217,6 +217,9 @@ struct GTY(()) c_parser {
      should translate them to the execution character set (false
      inside attributes).  */
   BOOL_BITFIELD translate_strings_p : 1;
+  /* True if we want to lex arbitrary number-like sequences as their
+     string representation.  */
+  BOOL_BITFIELD lex_number_as_string : 1;
 
   /* Objective-C specific parser/lexer information.  */
 
@@ -308,10 +311,10 @@ c_lex_one_token (c_parser *parser, c_token *token, bool raw = false)
 
   if (raw || vec_safe_length (parser->raw_tokens) == 0)
     {
+      int lex_flags = parser->lex_joined_string ? 0 : C_LEX_STRING_NO_JOIN;
+      lex_flags |= parser->lex_number_as_string ? C_LEX_NUMBER_AS_STRING : 0;
       token->type = c_lex_with_flags (&token->value, &token->location,
-				      &token->flags,
-				      (parser->lex_joined_string
-				       ? 0 : C_LEX_STRING_NO_JOIN));
+				      &token->flags, lex_flags);
       token->id_kind = C_ID_NONE;
       token->keyword = RID_MAX;
       token->pragma_kind = PRAGMA_NONE;
@@ -2579,15 +2582,28 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	    d = d->declarator;
 	  underspec_name = d->u.id.id;
 	}
+      tree postfix_attrs = NULL_TREE;
+      if (flag_allow_ext_attr_placement
+	  && c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+	{
+	  postfix_attrs = c_parser_gnu_attributes (parser);
+	  /* IF we have a function definition, and we're allowing it then
+	     treat these attributes as if they had been prepended.  */
+	  if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+	    {
+	      all_prefix_attrs = chainon (all_prefix_attrs, postfix_attrs);
+	      postfix_attrs = NULL_TREE;
+	    }
+	}
       if (c_parser_next_token_is (parser, CPP_EQ)
 	  || c_parser_next_token_is (parser, CPP_COMMA)
 	  || c_parser_next_token_is (parser, CPP_SEMICOLON)
 	  || c_parser_next_token_is_keyword (parser, RID_ASM)
 	  || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)
+	  || postfix_attrs
 	  || c_parser_next_token_is_keyword (parser, RID_IN))
 	{
 	  tree asm_name = NULL_TREE;
-	  tree postfix_attrs = NULL_TREE;
 	  if (!diagnosed_no_specs && !specs->declspecs_seen_p)
 	    {
 	      diagnosed_no_specs = true;
@@ -2599,8 +2615,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	  if (c_parser_next_token_is_keyword (parser, RID_ASM))
 	    asm_name = c_parser_simple_asm_expr (parser);
 	  if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+	    postfix_attrs = c_parser_gnu_attributes (parser);
+	  if (postfix_attrs)
 	    {
-	      postfix_attrs = c_parser_gnu_attributes (parser);
 	      if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
 		{
 		  /* This means there is an attribute specifier after
@@ -5213,6 +5230,88 @@ c_parser_gnu_attribute_any_word (c_parser *parser)
   return attr_name;
 }
 
+/* Handle parsing clang-form attribute arguments, where we need to adjust
+   the parsing rules to relate to a specific attribute.  */
+
+static tree
+c_parser_clang_attribute_arguments (c_parser *parser, tree /*attr_id*/)
+{
+  /* We can, if required, alter the parsing on the basis of the attribute.
+     At present, we handle the availability attr, where ach entry can be :
+	identifier
+	identifier=N.MM.Z
+	identifier="string"
+	followed by ',' or ) for the last entry*/
+
+  tree attr_args = NULL_TREE;
+  do
+    {
+      tree name = NULL_TREE;
+      tree value = NULL_TREE;
+
+      if (c_parser_next_token_is (parser, CPP_NAME)
+	  && c_parser_peek_token (parser)->id_kind == C_ID_ID)
+	{
+	  name = c_parser_peek_token (parser)->value;
+	  c_parser_consume_token (parser);
+	}
+      else if (c_parser_next_token_is (parser, CPP_COMMA))
+	name = error_mark_node; /* Comma handled below.  */
+      else
+	{
+	  bool saved_join_state = parser->lex_joined_string;
+	  parser->lex_number_as_string = 1;
+	  parser->lex_joined_string = 1;
+	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+				     "expected an attribute keyword");
+	  parser->lex_number_as_string = 0;
+	  parser->lex_joined_string = saved_join_state;
+	  return error_mark_node;
+	}
+      if (c_parser_next_token_is (parser, CPP_EQ))
+	{
+	  c_parser_consume_token (parser); /* eat the '=' */
+	  /* We need to bludgeon the lexer into not trying to interpret the
+	     xx.yy.zz form, since that just looks like a malformed float.
+	     Also, as a result of macro processing, we can have strig literals
+	     that are in multiple pieces so, for this specific part of the
+	     parse, we need to join strings.  */
+	  bool saved_join_state = parser->lex_joined_string;
+	  parser->lex_number_as_string = 1;
+	  parser->lex_joined_string = 1;
+	  /* So look at the next token, expecting a string, or something that
+	     looks initially like a number, but might be a version number.  */
+	  c_parser_peek_token (parser);
+	  /* Done with the funky number parsing.  */
+	  parser->lex_number_as_string = 0;
+	  parser->lex_joined_string = saved_join_state;
+	  if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)
+	      && c_parser_next_token_is_not (parser, CPP_COMMA))
+	    {
+	      value = c_parser_peek_token (parser)->value;
+	      /* ???: check for error mark and early-return?  */
+	      c_parser_consume_token (parser);
+	    }
+	  /* else value is absent.  */
+	}
+      else if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)
+	       && c_parser_next_token_is_not (parser, CPP_COMMA))
+	{
+	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+				     "expected %<,%> or %<=%>");
+	  return error_mark_node;
+	}
+    if (c_parser_next_token_is (parser, CPP_COMMA))
+      c_parser_consume_token (parser); /* Just skip the comma.  */
+    tree t = tree_cons (value, name, NULL);
+    if (!attr_args)
+      attr_args = t;
+    else
+      chainon (attr_args, t);
+  } while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN));
+  return attr_args;
+}
+
 /* Parse attribute arguments.  This is a common form of syntax
    covering all currently valid GNU and standard attributes.
 
@@ -5378,9 +5477,13 @@ c_parser_gnu_attribute (c_parser *parser, tree attrs,
       attrs = chainon (attrs, attr);
       return attrs;
     }
-  c_parser_consume_token (parser);
+  c_parser_consume_token (parser); /* The '('.  */
 
-  tree attr_args
+  tree attr_args;
+  if (attribute_clang_form_p (attr_name))
+    attr_args = c_parser_clang_attribute_arguments (parser, attr_name);
+  else
+    attr_args
     = c_parser_attribute_arguments (parser,
 				    attribute_takes_identifier_p (attr_name),
 				    false,
diff --git a/gcc/calls.cc b/gcc/calls.cc
index 21d78f9779f..d84998668a4 100644
--- gcc/calls.cc
+++ gcc/calls.cc
@@ -1376,7 +1376,8 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
 	 with those made by function.cc.  */
 
       /* See if this argument should be passed by invisible reference.  */
-      function_arg_info arg (type, argpos < n_named_args);
+      function_arg_info arg (type, argpos < n_named_args,
+			     argpos == n_named_args - 1);
       if (pass_by_reference (args_so_far_pnt, arg))
 	{
 	  const bool callee_copies
@@ -1496,10 +1497,13 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
 
       unsignedp = TYPE_UNSIGNED (type);
       arg.type = type;
-      arg.mode
-	= promote_function_mode (type, TYPE_MODE (type), &unsignedp,
-				 fndecl ? TREE_TYPE (fndecl) : fntype, 0);
-
+      arg.mode = TYPE_MODE (type);
+//      arg.mode
+//	= promote_function_mode (type, TYPE_MODE (type), &unsignedp,
+//				 fndecl ? TREE_TYPE (fndecl) : fntype, 0);
+      arg.mode = promote_function_mode (args_so_far, arg,
+					fndecl ? TREE_TYPE (fndecl) : fntype,
+					&unsignedp, 0);
       args[i].unsignedp = unsignedp;
       args[i].mode = arg.mode;
 
@@ -1549,6 +1553,7 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
 #endif
 			     reg_parm_stack_space,
 			     args[i].pass_on_stack ? 0 : args[i].partial,
+			     args_so_far,
 			     fndecl, args_size, &args[i].locate);
 #ifdef BLOCK_REG_PADDING
       else
@@ -4096,6 +4101,7 @@ split_complex_types (tree types)
   return types;
 }
 
+extern void debug_tree (tree);
 /* Output a library call to function ORGFUN (a SYMBOL_REF rtx)
    for a value of mode OUTMODE,
    with NARGS different arguments, passed as ARGS.
@@ -4281,6 +4287,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
 			   argvec[count].reg != 0,
 #endif
 			   reg_parm_stack_space, 0,
+			   args_so_far,
 			   NULL_TREE, &args_size, &argvec[count].locate);
 
       if (argvec[count].reg == 0 || argvec[count].partial != 0
@@ -4351,8 +4358,16 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
 	  val = force_operand (XEXP (slot, 0), NULL_RTX);
 	}
 
-      arg.mode = promote_function_mode (NULL_TREE, arg.mode, &unsigned_p,
-					NULL_TREE, 0);
+//      arg.mode = promote_function_mode (NULL_TREE, arg.mode, &unsigned_p,
+//					NULL_TREE, 0);
+      tree t = arg.type;
+if (t)
+  debug_tree (t);
+gcc_assert (!t);
+      arg.type = NULL_TREE;
+      arg.mode = promote_function_mode (args_so_far, arg, NULL_TREE,
+					&unsigned_p, 0);
+      arg.type = t;
       argvec[count].mode = arg.mode;
       argvec[count].value = convert_modes (arg.mode, GET_MODE (val), val,
 					   unsigned_p);
@@ -4372,6 +4387,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
 			       argvec[count].reg != 0,
 #endif
 			       reg_parm_stack_space, argvec[count].partial,
+			       args_so_far,
 			       NULL_TREE, &args_size, &argvec[count].locate);
 	  args_size.constant += argvec[count].locate.size.constant;
 	  gcc_assert (!argvec[count].locate.size.var);
diff --git a/gcc/calls.h b/gcc/calls.h
index 464a4e34e33..499f7560ee8 100644
--- gcc/calls.h
+++ gcc/calls.h
@@ -35,24 +35,43 @@ class function_arg_info
 {
 public:
   function_arg_info ()
-    : type (NULL_TREE), mode (VOIDmode), named (false),
+    : type (NULL_TREE), mode (VOIDmode), named (false), last_named (false),
       pass_by_reference (false)
   {}
 
   /* Initialize an argument of mode MODE, either before or after promotion.  */
   function_arg_info (machine_mode mode, bool named)
-    : type (NULL_TREE), mode (mode), named (named), pass_by_reference (false)
+    : type (NULL_TREE), mode (mode), named (named), last_named (false),
+      pass_by_reference (false)
+  {}
+
+  function_arg_info (machine_mode mode, bool named, bool last_named)
+    : type (NULL_TREE), mode (mode), named (named), last_named (last_named),
+      pass_by_reference (false)
   {}
 
   /* Initialize an unpromoted argument of type TYPE.  */
   function_arg_info (tree type, bool named)
-    : type (type), mode (TYPE_MODE (type)), named (named),
+    : type (type), mode (TYPE_MODE (type)), named (named), last_named (false),
       pass_by_reference (false)
   {}
 
+  /* Initialize an unpromoted argument of type TYPE.  */
+  function_arg_info (tree type, bool named, bool last_named)
+    : type (type), mode (TYPE_MODE (type)), named (named),
+      last_named (last_named), pass_by_reference (false)
+  {}
+
   /* Initialize an argument with explicit properties.  */
   function_arg_info (tree type, machine_mode mode, bool named)
-    : type (type), mode (mode), named (named), pass_by_reference (false)
+    : type (type), mode (mode), named (named), last_named (false),
+      pass_by_reference (false)
+  {}
+
+  /* Initialize an argument with explicit properties.  */
+  function_arg_info (tree type, machine_mode mode, bool named, bool last_named)
+    : type (type), mode (mode), named (named), last_named (last_named),
+      pass_by_reference (false)
   {}
 
   /* Return true if the gimple-level type is an aggregate.  */
@@ -105,6 +124,9 @@ public:
      "...").  See also TARGET_STRICT_ARGUMENT_NAMING.  */
   unsigned int named : 1;
 
+  /* True if this is the last named argument. */
+  unsigned int last_named : 1;
+
   /* True if we have decided to pass the argument by reference, in which case
      the function_arg_info describes a pointer to the original argument.  */
   unsigned int pass_by_reference : 1;
diff --git a/gcc/collect2.cc b/gcc/collect2.cc
index 902014a9cc1..a7ca609334a 100644
--- gcc/collect2.cc
+++ gcc/collect2.cc
@@ -73,7 +73,7 @@ along with GCC; see the file COPYING3.  If not see
    In a cross-compiler, this means you need a cross nm,
    but that is not quite as unpleasant as special headers.  */
 
-#if !defined (OBJECT_FORMAT_COFF)
+#if !defined (OBJECT_FORMAT_COFF) && !defined (OBJECT_FORMAT_MACHO)
 #define OBJECT_FORMAT_NONE
 #endif
 
@@ -107,7 +107,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #endif /* OBJECT_FORMAT_COFF */
 
-#ifdef OBJECT_FORMAT_NONE
+#if defined (OBJECT_FORMAT_NONE) || defined (OBJECT_FORMAT_MACHO)
 
 /* Default flags to pass to nm.  */
 #ifndef NM_FLAGS
@@ -525,7 +525,7 @@ static const char *const target_machine = TARGET_MACHINE;
 
    Return 0 if not found, otherwise return its name, allocated with malloc.  */
 
-#ifdef OBJECT_FORMAT_NONE
+#if defined (OBJECT_FORMAT_NONE) || defined (OBJECT_FORMAT_MACHO)
 
 /* Add an entry for the object file NAME to object file list LIST.
    New entries are added at the end of the list. The original pointer
@@ -764,6 +764,12 @@ do_link (char **ld_argv, const char *atsuffix)
     }
 }
 
+#if defined (OBJECT_FORMAT_MACHO)
+# define LLD_NAME "ld64.lld"
+#else
+# define LLD_NAME "ld.lld"
+#endif
+
 /* Main program.  */
 
 int
@@ -777,16 +783,19 @@ main (int argc, char **argv)
       USE_BFD_LD,
       USE_LLD_LD,
       USE_MOLD_LD,
+      USE_CLASSIC_LD,
       USE_LD_MAX
     } selected_linker = USE_DEFAULT_LD;
+
   static const char *const ld_suffixes[USE_LD_MAX] =
     {
       "ld",
       PLUGIN_LD_SUFFIX,
       "ld.gold",
       "ld.bfd",
-      "ld.lld",
-      "ld.mold"
+      LLD_NAME,
+      "ld.mold",
+      "ld-classic"
     };
   static const char *const real_ld_suffix = "real-ld";
   static const char *const collect_ld_suffix = "collect-ld";
@@ -868,7 +877,7 @@ main (int argc, char **argv)
 #ifdef CROSS_DIRECTORY_STRUCTURE
     /* lld and mold are platform-agnostic and not prefixed with target
        triple.  */
-    if (!(i == USE_LLD_LD || i == USE_MOLD_LD))
+    if (!(i == USE_LLD_LD || i == USE_MOLD_LD || i == USE_CLASSIC_LD))
       full_ld_suffixes[i] = concat (target_machine, "-", ld_suffixes[i],
 				    NULL);
     else
@@ -956,14 +965,22 @@ main (int argc, char **argv)
 	    if (selected_linker == USE_DEFAULT_LD)
 	      selected_linker = USE_PLUGIN_LD;
 	  }
+#if !defined (OBJECT_FORMAT_MACHO)
 	else if (strcmp (argv[i], "-fuse-ld=bfd") == 0)
 	  selected_linker = USE_BFD_LD;
 	else if (strcmp (argv[i], "-fuse-ld=gold") == 0)
 	  selected_linker = USE_GOLD_LD;
+#endif
 	else if (strcmp (argv[i], "-fuse-ld=lld") == 0)
 	  selected_linker = USE_LLD_LD;
 	else if (strcmp (argv[i], "-fuse-ld=mold") == 0)
 	  selected_linker = USE_MOLD_LD;
+#if defined (OBJECT_FORMAT_MACHO)
+	else if (strcmp (argv[i], "-fuse-ld=classic") == 0)
+	  selected_linker = USE_CLASSIC_LD;
+#endif
+	else if (strcmp (argv[i], "-fuse-ld=") == 0)
+	   selected_linker = USE_DEFAULT_LD;
 	else if (startswith (argv[i], "-o"))
 	  {
 	    /* Parse the output filename if it's given so that we can make
@@ -1055,7 +1072,8 @@ main (int argc, char **argv)
   ld_file_name = 0;
 #ifdef DEFAULT_LINKER
   if (selected_linker == USE_BFD_LD || selected_linker == USE_GOLD_LD ||
-      selected_linker == USE_LLD_LD || selected_linker == USE_MOLD_LD)
+      selected_linker == USE_LLD_LD || selected_linker == USE_MOLD_LD ||
+      selected_linker == USE_CLASSIC_LD)
     {
       char *linker_name;
 # ifdef HOST_EXECUTABLE_SUFFIX
@@ -2270,7 +2288,7 @@ write_aix_file (FILE *stream, struct id *list)
 }
 #endif
 
-#ifdef OBJECT_FORMAT_NONE
+#if defined (OBJECT_FORMAT_NONE) || defined (OBJECT_FORMAT_MACHO)
 
 /* Check to make sure the file is an LTO object file.  */
 
diff --git a/gcc/common.opt b/gcc/common.opt
index ad348844775..cde259257b7 100644
--- gcc/common.opt
+++ gcc/common.opt
@@ -2919,6 +2919,10 @@ fstack-usage
 Common RejectNegative Var(flag_stack_usage)
 Output stack usage information on a per-function basis.
 
+fstack-use-cumulative-args
+Common RejectNegative Var(flag_stack_use_cumulative_args) Init(STACK_USE_CUMULATIVE_ARGS_INIT)
+Use cumulative args-based stack layout hooks.
+
 fstrength-reduce
 Common Ignore
 Does nothing.  Preserved for backward compatibility.
@@ -3292,6 +3296,10 @@ fuse-ld=mold
 Common Driver Negative(fuse-ld=mold)
 Use the Modern linker (MOLD) linker instead of the default linker.
 
+fuse-ld=classic
+Common Driver Negative(fuse-ld=classic)
+Use the ld-classic linker instead of the default linker.
+
 fuse-linker-plugin
 Common Undocumented Var(flag_use_linker_plugin)
 
diff --git a/gcc/common/config/aarch64/aarch64-common.cc b/gcc/common/config/aarch64/aarch64-common.cc
index 951d041d310..496d0d82e05 100644
--- gcc/common/config/aarch64/aarch64-common.cc
+++ gcc/common/config/aarch64/aarch64-common.cc
@@ -298,8 +298,12 @@ aarch64_get_extension_string_for_isa_flags
 
      However, assemblers with Armv8-R AArch64 support should not have this
      issue, so we don't need this fix when targeting Armv8-R.  */
-  auto explicit_flags = (!(current_flags & AARCH64_FL_V8R)
-			 ? AARCH64_FL_CRC : 0);
+  aarch64_feature_flags explicit_flags =
+#ifndef DISABLE_AARCH64_AS_CRC_BUGFIX
+     (!(current_flags & AARCH64_ISA_V8R) ? AARCH64_FL_CRC : 0);
+#else
+     0;
+#endif
 
   /* Add the features in isa_flags & ~current_flags using the smallest
      possible number of extensions.  We can do this by iterating over the
@@ -329,7 +333,10 @@ aarch64_get_extension_string_for_isa_flags
     if (added & opt.flag_canonical)
       {
 	outstr += "+";
-	outstr += opt.name;
+	if (startswith (opt.name, "rdm"))
+	  outstr += "rdm";
+	else
+	  outstr += opt.name;
       }
 
   /* Remove the features in current_flags & ~isa_flags.  If the feature does
@@ -358,7 +365,10 @@ aarch64_get_extension_string_for_isa_flags
 	{
 	  current_flags &= ~opt.flags_off;
 	  outstr += "+no";
-	  outstr += opt.name;
+	  if (startswith (opt.name, "rdm"))
+	    outstr += "rdm";
+	  else
+	    outstr += opt.name;
 	}
     }
 
diff --git a/gcc/config.gcc b/gcc/config.gcc
index a3566f5c77d..6337fb0f839 100644
--- gcc/config.gcc
+++ gcc/config.gcc
@@ -1177,13 +1177,22 @@ case ${target} in
   ;;
 esac
 
-# Figure out if we need to enable heap trampolines by default
+# Figure out if we need to enable heap trampolines
+# and variadic functions handling.
 case ${target} in
+aarch64*-*-darwin2*)
+  # This applies to arm64 Darwin variadic funtions.
+  tm_defines="$tm_defines STACK_USE_CUMULATIVE_ARGS_INIT=1"
+  # Executable stack is forbidden.
+  tm_defines="$tm_defines HEAP_TRAMPOLINES_INIT=1"
+  ;;
 *-*-darwin2*)
+  tm_defines="$tm_defines STACK_USE_CUMULATIVE_ARGS_INIT=0"
   # Currently, we do this for macOS 11 and above.
   tm_defines="$tm_defines HEAP_TRAMPOLINES_INIT=1"
   ;;
 *)
+  tm_defines="$tm_defines STACK_USE_CUMULATIVE_ARGS_INIT=0"
   tm_defines="$tm_defines HEAP_TRAMPOLINES_INIT=0"
   ;;
 esac
@@ -1227,6 +1236,14 @@ aarch64*-*-elf | aarch64*-*-fuchsia* | aarch64*-*-rtems*)
 	done
 	TM_MULTILIB_CONFIG=`echo $TM_MULTILIB_CONFIG | sed 's/^,//'`
 	;;
+aarch64-*-darwin* )
+	tm_file="${tm_file} aarch64/aarch64-errata.h"
+	tmake_file="${tmake_file} aarch64/t-aarch64 aarch64/t-aarch64-darwin"
+	tm_defines="${tm_defines} TARGET_DEFAULT_ASYNC_UNWIND_TABLES=1"
+	tm_defines="${tm_defines} DISABLE_AARCH64_AS_CRC_BUGFIX=1"
+	# Choose a default CPU version that will work for all current releases.
+	with_cpu=${with_cpu:-apple-m1}
+	;;
 aarch64*-*-freebsd*)
 	tm_file="${tm_file} elfos.h ${fbsd_tm_file}"
 	tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-freebsd.h"
diff --git a/gcc/config/aarch64/aarch64-builtins.cc b/gcc/config/aarch64/aarch64-builtins.cc
index d5b5700d25d..97fe6d4caed 100644
--- gcc/config/aarch64/aarch64-builtins.cc
+++ gcc/config/aarch64/aarch64-builtins.cc
@@ -788,6 +788,8 @@ enum aarch64_builtins
   AARCH64_PLDX,
   AARCH64_PLI,
   AARCH64_PLIX,
+  /* OS-specific */
+  AARCH64_BUILTIN_CFSTRING,
   AARCH64_BUILTIN_MAX
 };
 
@@ -887,6 +889,9 @@ tree aarch64_fp16_ptr_type_node = NULL_TREE;
 /* Back-end node type for brain float (bfloat) types.  */
 tree aarch64_bf16_ptr_type_node = NULL_TREE;
 
+/* Pointer to __float128 on Mach-O, where the 128b float is not long double.  */
+tree aarch64_float128_ptr_type_node = NULL_TREE;
+
 /* Wrapper around add_builtin_function.  NAME is the name of the built-in
    function, TYPE is the function type, CODE is the function subcode
    (relative to AARCH64_BUILTIN_GENERAL), and ATTRS is the function
@@ -1662,6 +1667,29 @@ aarch64_init_bf16_types (void)
   aarch64_bf16_ptr_type_node = build_pointer_type (bfloat16_type_node);
 }
 
+/* Initialize the backend REAL_TYPE type supporting __float128 on Mach-O,
+   as well as the related built-ins.  */
+static void
+aarch64_init_float128_types (void)
+{
+  /* The __float128 type.  The node has already been created as
+     _Float128, so for C we only need to register the __float128 name for
+     it.  For C++, we create a distinct type which will mangle differently
+     (g) vs. _Float128 (DF128_) and behave backwards compatibly.  */
+  if (float128t_type_node == NULL_TREE)
+    {
+      float128t_type_node = make_node (REAL_TYPE);
+      TYPE_PRECISION (float128t_type_node)
+	= TYPE_PRECISION (float128_type_node);
+      SET_TYPE_MODE (float128t_type_node, TYPE_MODE (float128_type_node));
+      layout_type (float128t_type_node);
+    }
+  lang_hooks.types.register_builtin_type (float128t_type_node, "__float128");
+
+  aarch64_float128_ptr_type_node = build_pointer_type (float128t_type_node);
+}
+
+
 /* Pointer authentication builtins that will become NOP on legacy platform.
    Currently, these builtins are for internal use only (libgcc EH unwinder).  */
 
@@ -2044,8 +2072,9 @@ aarch64_general_init_builtins (void)
   aarch64_init_fpsr_fpcr_builtins ();
 
   aarch64_init_fp16_types ();
-
   aarch64_init_bf16_types ();
+  if (TARGET_MACHO)
+    aarch64_init_float128_types ();
 
   {
     aarch64_simd_switcher simd;
@@ -2079,6 +2108,14 @@ aarch64_general_init_builtins (void)
     handle_arm_acle_h ();
 }
 
+void
+aarch64_init_subtarget_builtins (void)
+{
+#ifdef SUBTARGET_INIT_BUILTINS
+  SUBTARGET_INIT_BUILTINS;
+#endif
+}
+
 /* Implement TARGET_BUILTIN_DECL for the AARCH64_BUILTIN_GENERAL group.  */
 tree
 aarch64_general_builtin_decl (unsigned code, bool)
diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
index 2aff097dd33..2ebaa1554a0 100644
--- gcc/config/aarch64/aarch64-c.cc
+++ gcc/config/aarch64/aarch64-c.cc
@@ -285,6 +285,16 @@ aarch64_cpu_cpp_builtins (cpp_reader *pfile)
 {
   aarch64_define_unconditional_macros (pfile);
   aarch64_update_cpp_builtins (pfile);
+
+  if (TARGET_MACHO)
+    {
+      builtin_define ("__builtin_copysignq=__builtin_copysignf128");
+      builtin_define ("__builtin_fabsq=__builtin_fabsf128");
+      builtin_define ("__builtin_huge_valq=__builtin_huge_valf128");
+      builtin_define ("__builtin_infq=__builtin_inff128");
+      builtin_define ("__builtin_nanq=__builtin_nanf128");
+      builtin_define ("__builtin_nansq=__builtin_nansf128");
+    }
 }
 
 /* Hook to validate the current #pragma GCC target and set the state, and
@@ -424,4 +434,8 @@ aarch64_register_pragmas (void)
   targetm.check_builtin_call = aarch64_check_builtin_call;
 
   c_register_pragma ("GCC", "aarch64", aarch64_pragma_aarch64);
+
+#ifdef REGISTER_SUBTARGET_PRAGMAS
+  REGISTER_SUBTARGET_PRAGMAS ();
+#endif
 }
diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
index b1eaf5512b5..af4436ae3fe 100644
--- gcc/config/aarch64/aarch64-cores.def
+++ gcc/config/aarch64/aarch64-cores.def
@@ -167,6 +167,17 @@ AARCH64_CORE("cortex-a76.cortex-a55",  cortexa76cortexa55, cortexa53, V8_2A,  (F
 /* Armv8-R Architecture Processors.  */
 AARCH64_CORE("cortex-r82", cortexr82, cortexa53, V8R, (), cortexa53, 0x41, 0xd15, -1)
 
+/* Apple (A12 and M) cores.
+   Apple implementer ID from xnu,
+   guesses for part #, guesses for scheduler ident, generic_armv8_a for costs.
+   A12 seems mostly 8.3,
+   M1 seems to be 8.4 + extras (see comments in option-extensions about f16fml),
+   M2 mostly 8.5 but with missing mandatory features.  */
+AARCH64_CORE("apple-a12", applea12, cortexa53, V8_3A,  (), generic_armv8_a, 0x61, 0x12, -1)
+AARCH64_CORE("apple-m1", applem1, cortexa57, V8_4A,  (F16, SB, SSBS), generic_armv8_a, 0x61, 0x23, -1)
+AARCH64_CORE("apple-m2", applem2, cortexa57, V8_4A,  (I8MM, BF16, F16, SB, SSBS), generic_armv8_a, 0x61, 0x23, -1)
+AARCH64_CORE("apple-m3", applem3, cortexa57, V8_4A,  (I8MM, BF16, F16, SB, SSBS), generic_armv8_a, 0x61, 0x23, -1)
+
 /* Armv9.0-A Architecture Processors.  */
 
 /* Arm ('A') cores. */
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 5d067cb64b4..a5550bf941a 100644
--- gcc/config/aarch64/aarch64-protos.h
+++ gcc/config/aarch64/aarch64-protos.h
@@ -109,6 +109,14 @@ enum aarch64_symbol_type
   SYMBOL_TLSLE24,
   SYMBOL_TLSLE32,
   SYMBOL_TLSLE48,
+  SYMBOL_MO_SMALL_ABS,
+  SYMBOL_MO_SMALL_PCR,
+  SYMBOL_MO_SMALL_GOT,
+  SYMBOL_MO_SMALL_TLS,
+  SYMBOL_MO_LARGE_ABS,
+  SYMBOL_MO_LARGE_PCR,
+  SYMBOL_MO_LARGE_GOT,
+  SYMBOL_MO_LARGE_TLS,
   SYMBOL_FORCE_TO_MEM
 };
 
@@ -748,6 +756,7 @@ void aarch64_post_cfi_startproc (void);
 poly_int64 aarch64_initial_elimination_offset (unsigned, unsigned);
 int aarch64_get_condition_code (rtx);
 bool aarch64_address_valid_for_prefetch_p (rtx, bool);
+bool aarch64_address_valid_for_unscaled_prefetch_p (rtx, bool);
 bool aarch64_bitmask_imm (unsigned HOST_WIDE_INT val, machine_mode);
 unsigned HOST_WIDE_INT aarch64_and_split_imm1 (HOST_WIDE_INT val_in);
 unsigned HOST_WIDE_INT aarch64_and_split_imm2 (HOST_WIDE_INT val_in);
@@ -782,7 +791,11 @@ bool aarch64_is_extend_from_extract (scalar_int_mode, rtx, rtx);
 bool aarch64_is_long_call_p (rtx);
 bool aarch64_is_noplt_call_p (rtx);
 bool aarch64_label_mentioned_p (rtx);
+#if TARGET_MACHO
+void aarch64_darwin_declare_function_name (FILE *, const char*, tree );
+#else
 void aarch64_declare_function_name (FILE *, const char*, tree);
+#endif
 void aarch64_asm_output_alias (FILE *, const tree, const tree);
 void aarch64_asm_output_external (FILE *, tree, const char*);
 bool aarch64_legitimate_pic_operand_p (rtx);
@@ -999,6 +1012,7 @@ void aarch64_override_options_internal (struct gcc_options *);
 
 const char *aarch64_general_mangle_builtin_type (const_tree);
 void aarch64_general_init_builtins (void);
+void aarch64_init_subtarget_builtins (void);
 tree aarch64_general_fold_builtin (unsigned int, tree, unsigned int, tree *);
 gimple *aarch64_general_gimple_fold_builtin (unsigned int, gcall *,
 					     gimple_stmt_iterator *);
diff --git a/gcc/config/aarch64/aarch64-tune.md b/gcc/config/aarch64/aarch64-tune.md
index 35b27ddb883..8ce2a93168c 100644
--- gcc/config/aarch64/aarch64-tune.md
+++ gcc/config/aarch64/aarch64-tune.md
@@ -1,5 +1,5 @@
 ;; -*- buffer-read-only: t -*-
 ;; Generated automatically by gentune.sh from aarch64-cores.def
 (define_attr "tune"
-	"cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,ampere1,ampere1a,ampere1b,emag,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,cortexa76ae,cortexa77,cortexa78,cortexa78ae,cortexa78c,cortexa65,cortexa65ae,cortexx1,cortexx1c,neoversen1,ares,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,fujitsu_monaka,tsv110,thunderx3t110,neoversev1,zeus,neoverse512tvb,saphira,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,cortexa510,cortexa520,cortexa710,cortexa715,cortexa720,cortexa725,cortexx2,cortexx3,cortexx4,cortexx925,neoversen2,cobalt100,neoversen3,neoversev2,grace,neoversev3,neoversev3ae,demeter,generic,generic_armv8_a,generic_armv9_a"
+	"cortexa34,cortexa35,cortexa53,cortexa57,cortexa72,cortexa73,thunderx,thunderxt88p1,thunderxt88,octeontx,octeontxt81,octeontxt83,thunderxt81,thunderxt83,ampere1,ampere1a,ampere1b,emag,xgene1,falkor,qdf24xx,exynosm1,phecda,thunderx2t99p1,vulcan,thunderx2t99,cortexa55,cortexa75,cortexa76,cortexa76ae,cortexa77,cortexa78,cortexa78ae,cortexa78c,cortexa65,cortexa65ae,cortexx1,cortexx1c,neoversen1,ares,neoversee1,octeontx2,octeontx2t98,octeontx2t96,octeontx2t93,octeontx2f95,octeontx2f95n,octeontx2f95mm,a64fx,fujitsu_monaka,tsv110,thunderx3t110,neoversev1,zeus,neoverse512tvb,saphira,cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,cortexa73cortexa53,cortexa75cortexa55,cortexa76cortexa55,cortexr82,applea12,applem1,applem2,applem3,cortexa510,cortexa520,cortexa710,cortexa715,cortexa720,cortexa725,cortexx2,cortexx3,cortexx4,cortexx925,neoversen2,cobalt100,neoversen3,neoversev2,grace,neoversev3,neoversev3ae,demeter,generic,generic_armv8_a,generic_armv9_a"
 	(const (symbol_ref "((enum attr_tune) aarch64_tune)")))
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index b28ebc96b1d..0ce19808bda 100644
--- gcc/config/aarch64/aarch64.cc
+++ gcc/config/aarch64/aarch64.cc
@@ -329,8 +329,10 @@ static bool aarch64_vfp_is_call_or_return_candidate (machine_mode,
 						     const_tree,
 						     machine_mode *, int *,
 						     bool *, bool);
+#if !TARGET_MACHO
 static void aarch64_elf_asm_constructor (rtx, int) ATTRIBUTE_UNUSED;
 static void aarch64_elf_asm_destructor (rtx, int) ATTRIBUTE_UNUSED;
+#endif
 static void aarch64_override_options_after_change (void);
 static bool aarch64_vector_mode_supported_p (machine_mode);
 static int aarch64_address_cost (rtx, machine_mode, addr_space_t, bool);
@@ -849,6 +851,9 @@ static const attribute_spec aarch64_gnu_attributes[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
        affects_type_identity, handler, exclude } */
+#ifdef SUBTARGET_ATTRIBUTE_TABLE
+  SUBTARGET_ATTRIBUTE_TABLE,
+#endif
   { "aarch64_vector_pcs", 0, 0, false, true,  true,  true,
 			  handle_aarch64_vector_pcs_attribute, NULL },
   { "arm_sve_vector_bits", 1, 1, false, true,  false, true,
@@ -2068,7 +2073,7 @@ aarch64_hard_regno_mode_ok (unsigned regno, machine_mode mode)
       if (known_le (GET_MODE_SIZE (mode), 8))
 	return true;
       if (known_le (GET_MODE_SIZE (mode), 16))
-	return (regno & 1) == 0;
+	return (regno & 1) == 0 || TARGET_MACHO; /* darwinpcs D.4 */
     }
   else if (FP_REGNUM_P (regno))
     {
@@ -2114,8 +2119,10 @@ static bool
 aarch64_takes_arguments_in_sve_regs_p (const_tree fntype)
 {
   CUMULATIVE_ARGS args_so_far_v;
+  /* This does not apply to variadic functions, so all the (currently
+     uncounted) arguments must be named.  */
   aarch64_init_cumulative_args (&args_so_far_v, NULL_TREE, NULL_RTX,
-				NULL_TREE, 0, true);
+				NULL_TREE, -1, true);
   cumulative_args_t args_so_far = pack_cumulative_args (&args_so_far_v);
 
   for (tree chain = TYPE_ARG_TYPES (fntype);
@@ -2863,6 +2870,7 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm,
   switch (type)
     {
     case SYMBOL_SMALL_ABSOLUTE:
+    case SYMBOL_MO_SMALL_PCR:
       {
 	/* In ILP32, the mode of dest can be either SImode or DImode.  */
 	rtx tmp_reg = dest;
@@ -2873,6 +2881,21 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm,
 	if (can_create_pseudo_p ())
 	  tmp_reg = gen_reg_rtx (mode);
 
+	if (TARGET_MACHO)
+	  {
+	    rtx sym, off;
+	    split_const (imm, &sym, &off);
+	    /* Negative offsets don't work, whether by intention is TBD.  */
+	    if (INTVAL (off) < 0 || INTVAL (off) > 8 * 1024 * 1024)
+	      {
+		emit_move_insn (tmp_reg, gen_rtx_HIGH (mode, sym));
+		emit_insn (gen_add_losym (dest, tmp_reg, sym));
+		/* FIXME: add the SI option if/when we support ilp32.  */
+		emit_insn (gen_adddi3 (dest, dest, off));
+		return;
+	      }
+	   /* else small enough positive offset is OK.  */
+	  }
 	emit_move_insn (tmp_reg, gen_rtx_HIGH (mode, copy_rtx (imm)));
 	emit_insn (gen_add_losym (dest, tmp_reg, imm));
 	return;
@@ -2956,6 +2979,7 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm,
 	return;
       }
 
+    case SYMBOL_MO_SMALL_GOT:
     case SYMBOL_SMALL_GOT_4G:
       emit_insn (gen_rtx_SET (dest, imm));
       return;
@@ -6028,6 +6052,7 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
 	case SYMBOL_SMALL_TLSIE:
 	case SYMBOL_SMALL_GOT_28K:
 	case SYMBOL_SMALL_GOT_4G:
+	case SYMBOL_MO_SMALL_GOT:
 	case SYMBOL_TINY_GOT:
 	case SYMBOL_TINY_TLSIE:
 	  if (const_offset != 0)
@@ -6041,6 +6066,7 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm)
 	  /* FALLTHRU */
 
 	case SYMBOL_SMALL_ABSOLUTE:
+	case SYMBOL_MO_SMALL_PCR:
 	case SYMBOL_TINY_ABSOLUTE:
 	case SYMBOL_TLSLE12:
 	case SYMBOL_TLSLE24:
@@ -6630,6 +6656,7 @@ aarch64_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED)
   gcc_unreachable ();
 }
 
+#if !TARGET_MACHO
 static bool
 aarch64_vfp_is_call_candidate (cumulative_args_t pcum_v, machine_mode mode,
 			       const_tree type, int *nregs)
@@ -6639,6 +6666,7 @@ aarch64_vfp_is_call_candidate (cumulative_args_t pcum_v, machine_mode mode,
 						  &pcum->aapcs_vfp_rmode,
 						  nregs, NULL, pcum->silent_p);
 }
+#endif
 
 /* Given MODE and TYPE of a function argument, return the alignment in
    bits.  The idea is to suppress any stronger alignment requested by
@@ -6667,7 +6695,7 @@ aarch64_function_arg_alignment (machine_mode mode, const_tree type,
   if (integer_zerop (TYPE_SIZE (type)))
     return 0;
 
-  gcc_assert (TYPE_MODE (type) == mode);
+  gcc_assert (TARGET_MACHO || TYPE_MODE (type) == mode);
 
   if (!AGGREGATE_TYPE_P (type))
     {
@@ -6865,6 +6893,14 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
      Both behaviors were wrong, but in different cases.  */
 
   pcum->aapcs_arg_processed = true;
+  if (TARGET_MACHO)
+    {
+      /* Set suitable defaults for queries.  */
+      pcum->darwinpcs_arg_boundary
+	= aarch64_function_arg_alignment (mode, type, &abi_break_gcc_9,
+					  &abi_break_gcc_13, &abi_break_gcc_14);
+      pcum->darwinpcs_arg_padding = BITS_PER_UNIT;
+    }
 
   pure_scalable_type_info pst_info;
   if (type && pst_info.analyze_registers (type))
@@ -6924,13 +6960,29 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
     /* No frontends can create types with variable-sized modes, so we
        shouldn't be asked to pass or return them.  */
     size = GET_MODE_SIZE (mode).to_constant ();
+
+  if (TARGET_MACHO)
+    /* Since we can pack things on the stack, we need the unrounded size.  */
+    pcum->darwinpcs_stack_bytes = size;
+
   size = ROUND_UP (size, UNITS_PER_WORD);
 
   allocate_ncrn = (type) ? !(FLOAT_TYPE_P (type)) : !FLOAT_MODE_P (mode);
+  bool is_ha = false;
+#if !TARGET_MACHO
   allocate_nvrn = aarch64_vfp_is_call_candidate (pcum_v,
 						 mode,
 						 type,
 						 &nregs);
+#else
+  /* We care if the value is a homogenous aggregate when laying out the stack,
+     so use this call directly.  */
+  allocate_nvrn
+    = aarch64_vfp_is_call_or_return_candidate (mode, type,
+						&pcum->aapcs_vfp_rmode,
+						&nregs, &is_ha,
+						pcum->silent_p);
+#endif
   gcc_assert (!sve_p || !allocate_nvrn);
 
   unsigned int alignment
@@ -6959,7 +7011,13 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
       if (!pcum->silent_p && !TARGET_FLOAT)
 	aarch64_err_no_fpadvsimd (mode);
 
-      if (nvrn + nregs <= NUM_FP_ARG_REGS)
+      if (TARGET_MACHO
+	  && !arg.named)
+	{
+	  pcum->aapcs_nextnvrn = NUM_FP_ARG_REGS;
+	  goto on_stack;
+	}
+      else if (nvrn + nregs <= NUM_FP_ARG_REGS)
 	{
 	  pcum->aapcs_nextnvrn = nvrn + nregs;
 	  if (!aarch64_composite_type_p (type, mode))
@@ -6989,6 +7047,7 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
 		}
 	      pcum->aapcs_reg = par;
 	    }
+	  pcum->darwinpcs_stack_bytes = 0;
 	  return;
 	}
       else
@@ -7005,14 +7064,24 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
   /* C6 - C9.  though the sign and zero extension semantics are
      handled elsewhere.  This is the case where the argument fits
      entirely general registers.  */
+
   if (allocate_ncrn && (ncrn + nregs <= NUM_ARG_REGS))
     {
       gcc_assert (nregs == 0 || nregs == 1 || nregs == 2);
 
+      if (TARGET_MACHO
+	  && !arg.named)
+	{
+	  pcum->aapcs_nextncrn = NUM_ARG_REGS;
+	  goto on_stack;
+	}
+
       /* C.8 if the argument has an alignment of 16 then the NGRN is
 	 rounded up to the next even number.  */
       if (nregs == 2
-	  && ncrn % 2)
+	  && ncrn % 2
+	  /* Darwin PCS deletes rule C.8.  */
+	  && !TARGET_MACHO)
 	{
 	  /* Emit a warning if the alignment changed when taking the
 	     'packed' attribute into account.  */
@@ -7082,8 +7151,8 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
 	    }
 	  pcum->aapcs_reg = par;
 	}
-
       pcum->aapcs_nextncrn = ncrn + nregs;
+      pcum->darwinpcs_stack_bytes = 0;
       return;
     }
 
@@ -7093,7 +7162,81 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg)
   /* The argument is passed on stack; record the needed number of words for
      this argument and align the total size if necessary.  */
 on_stack:
-  pcum->aapcs_stack_words = size / UNITS_PER_WORD;
+
+  if (TARGET_MACHO)
+    {
+      /* Darwin does not round up the allocation for smaller entities to 8
+	 bytes.  It only requires the natural alignment for these.
+
+	 but we don't do this for:
+	  * unnamed parms in variadic functions
+	  * complex types
+	  * unions
+	  * aggregates (except for homogeneous ones which are handles as the
+	    enclosed type).
+	 each entry starts a new slot.
+
+	16 byte entities are naturally aligned on the stack.
+	There was no darwinpcs for GCC 9, so neither the implementation
+	change nor the warning should fire here (i.e. we do not need to check
+	if 16byte entities alter the stack size).  */
+
+      gcc_checking_assert (arg.named == pcum->named_p);
+      pcum->darwinpcs_arg_padding = BITS_PER_UNIT;
+      if (!pcum->named_p
+	  || TREE_CODE (type) == COMPLEX_TYPE
+	  || (TREE_CODE (type) == RECORD_TYPE
+	      && !is_ha && !SCALAR_FLOAT_MODE_P (pcum->aapcs_vfp_rmode))
+	  || TREE_CODE (type) == UNION_TYPE)
+	{
+	  pcum->aapcs_stack_words = size / UNITS_PER_WORD;
+	  pcum->darwinpcs_sub_word_offset = 0;
+	  pcum->darwinpcs_sub_word_pos = 0;
+	  pcum->darwinpcs_arg_boundary = MAX (alignment, PARM_BOUNDARY);
+	  if (!pcum->named_p)
+	    pcum->darwinpcs_arg_padding = PARM_BOUNDARY;
+	  return;
+	}
+
+      /* Updated sub-word offset aligned for the new object.
+	 We are looking for the case that the new object will fit after some
+	 existing object(s) in the same stack slot.  In that case, we do not
+	 need to add any more stack space for it.  */
+      int new_off
+	= ROUND_UP (pcum->darwinpcs_sub_word_pos, alignment / BITS_PER_UNIT);
+
+      if (new_off >= UNITS_PER_WORD)
+	{
+	  /* That exceeds a stack slot, start a new one.  */
+	  pcum->darwinpcs_sub_word_offset = 0;
+	  pcum->darwinpcs_sub_word_pos = 0;
+	  new_off = 0;
+	}
+      /* This is the end of the new object.  */
+      int new_pos = new_off + pcum->darwinpcs_stack_bytes;
+
+      if (pcum->darwinpcs_sub_word_pos == 0)
+	/* New stack slot, just allocate one or more words, and note where
+	  the next arg will start.  */
+	pcum->aapcs_stack_words = size / UNITS_PER_WORD;
+      else if (new_pos <= UNITS_PER_WORD)
+	/* Old stack slot, object starts at new_off and goes to new_pos, we do
+	   not add any stack space.  */
+	pcum->darwinpcs_sub_word_offset = new_off;
+      pcum->darwinpcs_sub_word_pos = new_pos;
+      pcum->darwinpcs_arg_boundary = alignment ;
+      if (pcum->last_named_p && new_pos > 0)
+	{
+	  /* Round the last named arg to the start of the next stack slot.  */
+	  if (new_pos <= 4)
+	    pcum->darwinpcs_arg_padding = PARM_BOUNDARY;
+	  else if (new_pos <= 6)
+	    pcum->darwinpcs_arg_padding = 4 * BITS_PER_UNIT;
+	  else if (pcum->darwinpcs_sub_word_pos <= 7)
+	    pcum->darwinpcs_arg_padding = 2 * BITS_PER_UNIT;
+	}
+      return;
+    }
 
   if (warn_pcs_change_le_gcc14
       && abi_break_gcc_13
@@ -7109,6 +7252,8 @@ on_stack:
     inform (input_location, "parameter passing for argument of type "
 	    "%qT changed in GCC 14.1", type);
 
+  /* size was already rounded up to PARM_BOUNDARY.  */
+  pcum->aapcs_stack_words = size / UNITS_PER_WORD;
   if (alignment == 16 * BITS_PER_UNIT)
     {
       int new_size = ROUND_UP (pcum->aapcs_stack_size, 16 / UNITS_PER_WORD);
@@ -7213,12 +7358,33 @@ aarch64_init_cumulative_args (CUMULATIVE_ARGS *pcum,
   pcum->aapcs_arg_processed = false;
   pcum->aapcs_stack_words = 0;
   pcum->aapcs_stack_size = 0;
+  pcum->darwinpcs_stack_bytes = 0;
+  pcum->darwinpcs_sub_word_offset = 0;
+  pcum->darwinpcs_sub_word_pos = 0;
+  pcum->darwinpcs_arg_boundary = BITS_PER_UNIT;
+  pcum->darwinpcs_arg_padding = BITS_PER_UNIT;
+  /* If we have been invoked for incoming args, then n_named will have been
+     set to -1, but we should have a function decl - so pick up the named
+     count from that.  If that fails, and we end up with -1, this effectively
+     corresponds to assuming that there is an arbitrary number of named
+     args.  */
+  pcum->darwinpcs_n_named = n_named;
+  if (n_named == (unsigned)-1 && fndecl)
+    {
+      tree fnt = TREE_TYPE (fndecl);
+      if (fnt && TYPE_ARG_TYPES (fnt))
+	pcum->darwinpcs_n_named = list_length (TYPE_ARG_TYPES (fnt));
+    }
+  pcum->darwinpcs_n_args_processed = 0;
+  pcum->named_p = pcum->darwinpcs_n_named != 0;
+  pcum->last_named_p = pcum->darwinpcs_n_named == 1;
   pcum->silent_p = silent_p;
   pcum->shared_za_flags
     = (fntype ? aarch64_fntype_shared_flags (fntype, "za") : 0U);
   pcum->shared_zt0_flags
     = (fntype ? aarch64_fntype_shared_flags (fntype, "zt0") : 0U);
   pcum->num_sme_mode_switch_args = 0;
+  pcum->aapcs_vfp_rmode = VOIDmode;
 
   if (!silent_p
       && !TARGET_FLOAT
@@ -7257,9 +7423,11 @@ aarch64_function_arg_advance (cumulative_args_t pcum_v,
       || pcum->pcs_variant == ARM_PCS_SVE)
     {
       aarch64_layout_arg (pcum_v, arg);
-      gcc_assert ((pcum->aapcs_reg != NULL_RTX)
-		  != (pcum->aapcs_stack_words != 0));
-      if (pcum->aapcs_reg
+      pcum->darwinpcs_n_args_processed++;
+      gcc_assert (TARGET_MACHO
+		  || (pcum->aapcs_reg != NULL_RTX)
+		      != (pcum->aapcs_stack_words != 0));
+     if (pcum->aapcs_reg
 	  && aarch64_call_switches_pstate_sm (pcum->isa_mode))
 	aarch64_record_sme_mode_switch_args (pcum);
 
@@ -7270,6 +7438,12 @@ aarch64_function_arg_advance (cumulative_args_t pcum_v,
       pcum->aapcs_stack_size += pcum->aapcs_stack_words;
       pcum->aapcs_stack_words = 0;
       pcum->aapcs_reg = NULL_RTX;
+      pcum->darwinpcs_arg_boundary = BITS_PER_UNIT;
+      pcum->darwinpcs_arg_padding = BITS_PER_UNIT;
+      pcum->named_p
+	= pcum->darwinpcs_n_args_processed < pcum->darwinpcs_n_named;
+      pcum->last_named_p
+	= pcum->darwinpcs_n_args_processed + 1 == pcum->darwinpcs_n_named;
     }
 }
 
@@ -7281,12 +7455,15 @@ aarch64_function_arg_regno_p (unsigned regno)
 	  || (PR_REGNUM_P (regno) && regno < P0_REGNUM + NUM_PR_ARG_REGS));
 }
 
-/* Implement FUNCTION_ARG_BOUNDARY.  Every parameter gets at least
-   PARM_BOUNDARY bits of alignment, but will be given anything up
-   to STACK_BOUNDARY bits if the type requires it.  This makes sure
-   that both before and after the layout of each argument, the Next
-   Stacked Argument Address (NSAA) will have a minimum alignment of
-   8 bytes.  */
+/* Implement FUNCTION_ARG_BOUNDARY.
+   For AAPCS64, Every parameter gets at least PARM_BOUNDARY bits of
+   alignment, but will be given anything up to STACK_BOUNDARY bits
+   if the type requires it.  This makes sure that both before and after
+   the layout of each argument, the Next Stacked Argument Address (NSAA)
+   will have a minimum alignment of 8 bytes.
+
+   For darwinpcs, this is only called to lower va_arg entries which are
+   always aligned as for AAPCS64.  */
 
 static unsigned int
 aarch64_function_arg_boundary (machine_mode mode, const_tree type)
@@ -7300,8 +7477,108 @@ aarch64_function_arg_boundary (machine_mode mode, const_tree type)
 							   &abi_break_gcc_14);
   /* We rely on aarch64_layout_arg and aarch64_gimplify_va_arg_expr
      to emit warnings about ABI incompatibility.  */
+#if TARGET_MACHO
+  /* This can only work for unnamed args.  */
+  machine_mode comp_mode = VOIDmode;
+  int nregs;
+  bool is_ha;
+  aarch64_vfp_is_call_or_return_candidate (mode, type, &comp_mode, &nregs,
+					   &is_ha, /*silent*/true);
+  if (TREE_CODE (type) == COMPLEX_TYPE
+      || (TREE_CODE (type) == RECORD_TYPE
+	  && !is_ha && !SCALAR_FLOAT_MODE_P (comp_mode))
+      || TREE_CODE (type) == UNION_TYPE)
+    return MIN (MAX (alignment, PARM_BOUNDARY), STACK_BOUNDARY);
+  return MIN (alignment, STACK_BOUNDARY);
+#else
+  alignment = MIN (MAX (alignment, PARM_BOUNDARY), STACK_BOUNDARY);
+  return alignment;
+#endif
+}
+
+/* For Darwin, we want to use the arg boundary computed when laying out the
+   function arg, to cope with items packed on the stack and the different
+   rules applied to unnamed parms.  */
+
+static unsigned int
+aarch64_function_arg_boundary_ca (machine_mode mode ATTRIBUTE_UNUSED,
+				  const_tree type ATTRIBUTE_UNUSED,
+				  cumulative_args_t ca ATTRIBUTE_UNUSED)
+{
+  unsigned int abi_break_gcc_9;
+  unsigned int abi_break_gcc_13;
+  unsigned int abi_break_gcc_14;
+  unsigned int alignment
+    = aarch64_function_arg_alignment (mode, type, &abi_break_gcc_9,
+				      &abi_break_gcc_13, &abi_break_gcc_14);
+  /* We rely on aarch64_layout_arg and aarch64_gimplify_va_arg_expr
+     to emit warnings about ABI incompatibility.  */
+#if TARGET_MACHO
+  CUMULATIVE_ARGS *pcum = get_cumulative_args (ca);
+gcc_checking_assert (pcum->aapcs_arg_processed);
+
+  bool named_p = pcum->darwinpcs_n_args_processed < pcum->darwinpcs_n_named;
+gcc_checking_assert (named_p == pcum->named_p);
+  machine_mode comp_mode = VOIDmode;
+  int nregs;
+  bool is_ha;
+  aarch64_vfp_is_call_or_return_candidate (mode, type, &comp_mode, &nregs,
+					   &is_ha, /*silent*/true);
+  bool no_pack = (TREE_CODE (type) == COMPLEX_TYPE
+      || (TREE_CODE (type) == RECORD_TYPE
+	  && !is_ha && !SCALAR_FLOAT_MODE_P (comp_mode))
+      || TREE_CODE (type) == UNION_TYPE);
+
+  bool in_regs = (pcum->aapcs_reg != NULL_RTX);
+
+  if ((named_p && !no_pack) || in_regs)
+    ; /* Leave the alignment as natural.  */
+  else
+    alignment = MAX (alignment, PARM_BOUNDARY);
+gcc_checking_assert (alignment == pcum->darwinpcs_arg_boundary);
+  return MIN (alignment, STACK_BOUNDARY);
+
+#else
   alignment = MIN (MAX (alignment, PARM_BOUNDARY), STACK_BOUNDARY);
   return alignment;
+#endif
+}
+
+/* Implement TARGET_FUNCTION_ARG_ROUND_BOUNDARY_CA for darwinpcs which allows
+   non-standard passing of byte-aligned items [D.2].  This is done by pulling
+   the values out of the cumulative args struct.  */
+
+static unsigned int
+aarch64_function_arg_round_boundary_ca (machine_mode mode ATTRIBUTE_UNUSED,
+					const_tree type ATTRIBUTE_UNUSED,
+					cumulative_args_t ca)
+{
+  CUMULATIVE_ARGS *pcum = get_cumulative_args (ca);
+gcc_checking_assert (pcum->aapcs_arg_processed);
+  bool named_p = pcum->darwinpcs_n_args_processed < pcum->darwinpcs_n_named;
+gcc_checking_assert (named_p == pcum->named_p);
+  bool last_named_p = pcum->darwinpcs_n_args_processed + 1 == pcum->darwinpcs_n_named;
+gcc_checking_assert (last_named_p == pcum->last_named_p);
+
+  unsigned boundary = BITS_PER_UNIT;
+  if (last_named_p && pcum->darwinpcs_sub_word_pos > 0)
+    {
+      /* Round the last named arg to the start of the next stack slot.  */
+      if (pcum->darwinpcs_sub_word_pos <= 4)
+	boundary = PARM_BOUNDARY;
+      else if (pcum->darwinpcs_sub_word_pos <= 6)
+	boundary = 4 * BITS_PER_UNIT;
+      else if (pcum->darwinpcs_sub_word_pos <= 7)
+	boundary = 2 * BITS_PER_UNIT;
+    }
+  else if (named_p)
+    /* Named args are naturally aligned, but with no rounding.  */
+    ;
+  else
+    /* un-named args are rounded to fill slots.  */
+    boundary = PARM_BOUNDARY;
+gcc_checking_assert (boundary == pcum->darwinpcs_arg_padding);
+  return boundary;
 }
 
 /* Implement TARGET_GET_RAW_RESULT_MODE and TARGET_GET_RAW_ARG_MODE.  */
@@ -10714,6 +10991,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
       /* load literal: pc-relative constant pool entry.  Only supported
          for SI mode or larger.  */
       info->type = ADDRESS_SYMBOLIC;
+      info->offset = NULL_RTX;
 
       if (!load_store_pair_p
 	  && GET_MODE_SIZE (mode).is_constant (&const_size)
@@ -10721,6 +10999,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
 	{
 	  poly_int64 offset;
 	  rtx sym = strip_offset_and_salt (x, &offset);
+
 	  return ((LABEL_REF_P (sym)
 		   || (SYMBOL_REF_P (sym)
 		       && CONSTANT_POOL_ADDRESS_P (sym)
@@ -10738,10 +11017,13 @@ aarch64_classify_address (struct aarch64_address_info *info,
 	  poly_int64 offset;
 	  HOST_WIDE_INT const_offset;
 	  rtx sym = strip_offset_and_salt (info->offset, &offset);
+
 	  if (SYMBOL_REF_P (sym)
 	      && offset.is_constant (&const_offset)
 	      && (aarch64_classify_symbol (sym, const_offset)
-		  == SYMBOL_SMALL_ABSOLUTE))
+		    == SYMBOL_SMALL_ABSOLUTE
+		  || aarch64_classify_symbol (sym, const_offset)
+		      == SYMBOL_MO_SMALL_PCR))
 	    {
 	      /* The symbol and offset must be aligned to the access size.  */
 	      unsigned int align;
@@ -10791,6 +11073,55 @@ aarch64_address_valid_for_prefetch_p (rtx x, bool strict_p)
   if (!res)
     return false;
 
+  /* For ELF targets using GAS, we emit prfm unconditionally; GAS will alter
+     the instruction to pick the prfum form where possible (i.e. when the
+     offset is in the range -256..255) and fall back to prfm otherwise.
+     We can reject cases where the offset exceeds the range usable by both
+     insns [-256..32760], or for offsets > 255 when the value is not divisible
+     by 8.
+     For Mach-O (Darwin) where the assembler uses the LLVM back end, that does
+     not yet do the substitution, so we must reject all prfum cases.  */
+  if (addr.offset)
+    {
+      HOST_WIDE_INT offs = INTVAL (addr.offset);
+      if (offs < -256) /* Out of range for both prfum and prfm.  */
+	return false;
+      if (offs > 32760) /* Out of range for prfm.  */
+	return false;
+      if (offs & 0x07) /* We cannot use prfm.  */
+	{
+	  if (offs > 255) /* Out of range for prfum.  */
+	    return false;
+	  if (TARGET_MACHO)
+	    return false;
+	}
+      if (TARGET_MACHO && offs < 0)
+	return false;
+    }
+
+  /* ... except writeback forms.  */
+  return addr.type != ADDRESS_REG_WB;
+}
+
+/* Return true if the address X is valid for a PRFUM instruction.
+   STRICT_P is true if we should do strict checking with
+   aarch64_classify_address.  */
+
+bool
+aarch64_address_valid_for_unscaled_prefetch_p (rtx x, bool strict_p)
+{
+  struct aarch64_address_info addr;
+
+  /* PRFUM accepts the same addresses as DImode, but constrained to a range
+     -256..255.  */
+  bool res = aarch64_classify_address (&addr, x, DImode, strict_p);
+  if (!res)
+    return false;
+
+  if (addr.offset && ((INTVAL (addr.offset) > 255)
+		       || (INTVAL (addr.offset) < -256)))
+     return false;
+
   /* ... except writeback forms.  */
   return addr.type != ADDRESS_REG_WB;
 }
@@ -11924,6 +12255,144 @@ sizetochar (int size)
     }
 }
 
+static void
+output_macho_postfix_expr (FILE *file, rtx x, const char *postfix)
+{
+  char buf[256];
+
+ restart:
+  switch (GET_CODE (x))
+    {
+    case PC:
+      putc ('.', file);
+      break;
+
+    case SYMBOL_REF:
+      if (SYMBOL_REF_DECL (x))
+	assemble_external (SYMBOL_REF_DECL (x));
+      assemble_name (file, XSTR (x, 0));
+      fprintf (file, "@%s", postfix);
+      break;
+
+    case LABEL_REF:
+      x = label_ref_label (x);
+      /* Fall through.  */
+    case CODE_LABEL:
+      ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
+      assemble_name (file, buf);
+      fprintf (file, "@%s", postfix);
+      break;
+
+    case CONST_INT:
+      fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
+      break;
+
+    case CONST:
+      /* This used to output parentheses around the expression,
+	 but that does not work on the 386 (either ATT or BSD assembler).  */
+      output_macho_postfix_expr (file, XEXP (x, 0), postfix);
+      break;
+
+    case CONST_WIDE_INT:
+      /* We do not know the mode here so we have to use a round about
+	 way to build a wide-int to get it printed properly.  */
+      {
+	wide_int w = wide_int::from_array (&CONST_WIDE_INT_ELT (x, 0),
+					   CONST_WIDE_INT_NUNITS (x),
+					   CONST_WIDE_INT_NUNITS (x)
+					   * HOST_BITS_PER_WIDE_INT,
+					   false);
+	print_decs (w, file);
+      }
+      break;
+
+    case CONST_DOUBLE:
+      if (CONST_DOUBLE_AS_INT_P (x))
+	{
+	  /* We can use %d if the number is one word and positive.  */
+	  if (CONST_DOUBLE_HIGH (x))
+	    fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
+		     (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (x),
+		     (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x));
+	  else if (CONST_DOUBLE_LOW (x) < 0)
+	    fprintf (file, HOST_WIDE_INT_PRINT_HEX,
+		     (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x));
+	  else
+	    fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x));
+	}
+      else
+	/* We can't handle floating point constants;
+	   PRINT_OPERAND must handle them.  */
+	output_operand_lossage ("floating constant misused");
+      break;
+
+    case CONST_FIXED:
+      fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_FIXED_VALUE_LOW (x));
+      break;
+
+    case PLUS:
+      /* Some assemblers need integer constants to appear last (eg masm).  */
+      if (CONST_INT_P (XEXP (x, 0)))
+	{
+	  output_macho_postfix_expr (file, XEXP (x, 1), postfix);
+	  if (INTVAL (XEXP (x, 0)) >= 0)
+	    fprintf (file, "+");
+	  output_addr_const (file, XEXP (x, 0));
+	}
+      else
+	{
+	  output_macho_postfix_expr (file, XEXP (x, 0), postfix);
+	  if (!CONST_INT_P (XEXP (x, 1))
+	      || INTVAL (XEXP (x, 1)) >= 0)
+	    fprintf (file, "+");
+	  output_addr_const (file, XEXP (x, 1));
+	}
+      break;
+
+    case MINUS:
+      /* Avoid outputting things like x-x or x+5-x,
+	 since some assemblers can't handle that.  */
+      x = simplify_subtraction (x);
+      if (GET_CODE (x) != MINUS)
+	goto restart;
+
+      output_macho_postfix_expr (file, XEXP (x, 0), postfix);
+      fprintf (file, "-");
+      if ((CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) >= 0)
+	  || GET_CODE (XEXP (x, 1)) == PC
+	  || GET_CODE (XEXP (x, 1)) == SYMBOL_REF)
+	output_addr_const (file, XEXP (x, 1));
+      else
+	{
+	  fputs (targetm.asm_out.open_paren, file);
+	  output_addr_const (file, XEXP (x, 1));
+	  fputs (targetm.asm_out.close_paren, file);
+	}
+      break;
+
+    case ZERO_EXTEND:
+    case SIGN_EXTEND:
+    case SUBREG:
+    case TRUNCATE:
+      output_addr_const (file, XEXP (x, 0));
+      break;
+
+    case  UNSPEC:
+      if (XINT (x, 1) == UNSPEC_SALT_ADDR)
+	{
+	  output_macho_postfix_expr (file, XVECEXP (x, 0, 0), postfix);
+	  break;
+	}
+      /* FALLTHROUGH */
+    default:
+      if (targetm.asm_out.output_addr_const_extra (file, x))
+	break;
+
+      output_operand_lossage ("invalid expression as operand");
+    }
+
+}
+
 /* Print operand X to file F in a target specific manner according to CODE.
    The acceptable formatting commands given by CODE are:
      'c':		An integer or symbol address without a preceding #
@@ -11997,6 +12466,12 @@ aarch64_print_operand (FILE *f, rtx x, int code)
 	}
       break;
 
+    case 'J':
+      output_macho_postfix_expr (f, x, "PAGEOFF");
+      break;
+    case 'O':
+      output_macho_postfix_expr (f, x, "GOTPAGEOFF");
+      break;
     case 'e':
       {
 	x = unwrap_const_vec_duplicate (x);
@@ -12329,7 +12804,7 @@ aarch64_print_operand (FILE *f, rtx x, int code)
     case 'A':
       if (GET_CODE (x) == HIGH)
 	x = XEXP (x, 0);
-
+#if !TARGET_MACHO
       switch (aarch64_classify_symbolic_expression (x))
 	{
 	case SYMBOL_SMALL_GOT_4G:
@@ -12360,9 +12835,26 @@ aarch64_print_operand (FILE *f, rtx x, int code)
 	  break;
 	}
       output_addr_const (asm_out_file, x);
+#endif
+#if TARGET_MACHO
+      switch (aarch64_classify_symbolic_expression (x))
+	{
+	case SYMBOL_MO_SMALL_PCR:
+	  output_macho_postfix_expr (asm_out_file, x, "PAGE");
+	  break;
+	case SYMBOL_MO_SMALL_GOT:
+	  output_macho_postfix_expr (asm_out_file, x, "GOTPAGE");
+	  break;
+	default:
+	  /* large code model unimplemented.  */
+	  gcc_unreachable ();
+	  break;
+	}
+#endif
       break;
 
     case 'L':
+#if !TARGET_MACHO
       switch (aarch64_classify_symbolic_expression (x))
 	{
 	case SYMBOL_SMALL_GOT_4G:
@@ -12400,10 +12892,12 @@ aarch64_print_operand (FILE *f, rtx x, int code)
 	default:
 	  break;
 	}
+#endif
       output_addr_const (asm_out_file, x);
       break;
 
     case 'G':
+#if !TARGET_MACHO
       switch (aarch64_classify_symbolic_expression (x))
 	{
 	case SYMBOL_TLSLE24:
@@ -12412,6 +12906,7 @@ aarch64_print_operand (FILE *f, rtx x, int code)
 	default:
 	  break;
 	}
+#endif
       output_addr_const (asm_out_file, x);
       break;
 
@@ -12577,8 +13072,13 @@ aarch64_print_address_internal (FILE *f, machine_mode mode, rtx x,
 	break;
 
       case ADDRESS_LO_SUM:
+#if TARGET_MACHO
+	asm_fprintf (f, "[%s, #", reg_names [REGNO (addr.base)]);
+	output_macho_postfix_expr (f, addr.offset, "PAGEOFF");
+#else
 	asm_fprintf (f, "[%s, #:lo12:", reg_names [REGNO (addr.base)]);
 	output_addr_const (f, addr.offset);
+#endif
 	asm_fprintf (f, "]");
 	return true;
 
@@ -12886,7 +13386,23 @@ aarch64_frame_pointer_required ()
 {
   /* If the function needs to record the incoming value of PSTATE.SM,
      make sure that the slot is accessible from the frame pointer.  */
-  return aarch64_need_old_pstate_sm ();
+  if (!TARGET_MACHO)
+    return aarch64_need_old_pstate_sm ();
+
+  /* We could do with some more general test.
+  gcc_checking_assert (!aarch64_need_old_pstate_sm ());*/
+
+  if (crtl->calls_eh_return || aarch64_need_old_pstate_sm ())
+    return true;
+
+  /* Not used in leaf functions (unless forced).  */
+  if (flag_omit_leaf_frame_pointer && leaf_function_p ())
+    return false;
+
+  /* NOTE: We are allowing the user to force omission of the frame
+     pointer, (despite that it is not ABI-compliant).  */
+
+  return flag_omit_frame_pointer != 1;
 }
 
 static bool
@@ -13114,6 +13630,8 @@ aarch64_asm_output_labelref (FILE* f, const char *name)
   asm_fprintf (f, "%U%s", name);
 }
 
+#if !TARGET_MACHO
+
 static void
 aarch64_elf_asm_constructor (rtx symbol, int priority)
 {
@@ -13153,6 +13671,7 @@ aarch64_elf_asm_destructor (rtx symbol, int priority)
       assemble_aligned_integer (POINTER_BYTES, symbol);
     }
 }
+#endif
 
 const char*
 aarch64_output_casesi (rtx *operands)
@@ -13305,7 +13824,11 @@ aarch64_select_rtx_section (machine_mode mode,
   if (aarch64_can_use_per_function_literal_pools_p ())
     return function_section (current_function_decl);
 
+#if TARGET_MACHO
+  return machopic_select_rtx_section (mode, x, align);
+#else
   return default_elf_select_rtx_section (mode, x, align);
+#endif
 }
 
 /* Implement ASM_OUTPUT_POOL_EPILOGUE.  */
@@ -15575,15 +16098,17 @@ aarch64_init_builtins ()
 {
   aarch64_general_init_builtins ();
   aarch64_sve::init_builtins ();
-#ifdef SUBTARGET_INIT_BUILTINS
-  SUBTARGET_INIT_BUILTINS;
-#endif
+  aarch64_init_subtarget_builtins ();
 }
 
 /* Implement TARGET_FOLD_BUILTIN.  */
 static tree
 aarch64_fold_builtin (tree fndecl, int nargs, tree *args, bool)
 {
+#ifdef SUBTARGET_FOLD_BUILTIN
+  if (tree res = SUBTARGET_FOLD_BUILTIN (fndecl, nargs, args, false))
+    return res;
+#endif
   unsigned int code = DECL_MD_FUNCTION_CODE (fndecl);
   unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT;
   tree type = TREE_TYPE (TREE_TYPE (fndecl));
@@ -18995,10 +19520,14 @@ initialize_aarch64_code_model (struct gcc_options *opts)
 	}
       break;
     case AARCH64_CMODEL_LARGE:
-      if (opts->x_flag_pic)
+      if (TARGET_MACHO)
+	/* We need to implement fPIC here (arm64_32 also accepts the large
+	   model).  */
+	sorry ("code model %qs not supported yet", "large");
+      else if (opts->x_flag_pic)
 	sorry ("code model %qs with %<-f%s%>", "large",
 	       opts->x_flag_pic > 1 ? "PIC" : "pic");
-      if (opts->x_aarch64_abi == AARCH64_ABI_ILP32)
+      else if (opts->x_aarch64_abi == AARCH64_ABI_ILP32)
 	sorry ("code model %qs not supported in ilp32 mode", "large");
       break;
     case AARCH64_CMODEL_TINY_PIC:
@@ -20922,7 +21451,9 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset)
 	case AARCH64_CMODEL_SMALL_SPIC:
 	case AARCH64_CMODEL_SMALL_PIC:
 	case AARCH64_CMODEL_SMALL:
-	  return SYMBOL_SMALL_ABSOLUTE;
+	  return TARGET_MACHO
+		 ? SYMBOL_MO_SMALL_PCR
+		 : SYMBOL_SMALL_ABSOLUTE;
 
 	default:
 	  gcc_unreachable ();
@@ -20958,10 +21489,22 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset)
 
 	  return SYMBOL_TINY_ABSOLUTE;
 
-
 	case AARCH64_CMODEL_SMALL_SPIC:
 	case AARCH64_CMODEL_SMALL_PIC:
 	case AARCH64_CMODEL_SMALL:
+#if TARGET_MACHO
+	  if (TARGET_MACHO)
+	    {
+	      /* Constant pool addresses are always TU-local and PC-
+		 relative.  We indirect common, external and weak
+		 symbols (but weak only if not hidden).  */
+	      if (!CONSTANT_POOL_ADDRESS_P (x)
+		  && (MACHO_SYMBOL_MUST_INDIRECT_P (x)
+		      || !aarch64_symbol_binds_local_p (x)))
+		return SYMBOL_MO_SMALL_GOT;
+	    }
+	  else
+#endif
 	  if ((flag_pic || SYMBOL_REF_WEAK (x))
 	      && !aarch64_symbol_binds_local_p (x))
 	    return aarch64_cmodel == AARCH64_CMODEL_SMALL_SPIC
@@ -20973,7 +21516,8 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset)
 		|| offset_within_block_p (x, offset)))
 	    return SYMBOL_FORCE_TO_MEM;
 
-	  return SYMBOL_SMALL_ABSOLUTE;
+	  return TARGET_MACHO ? SYMBOL_MO_SMALL_PCR
+			      : SYMBOL_SMALL_ABSOLUTE;
 
 	case AARCH64_CMODEL_LARGE:
 	  /* This is alright even in PIC code as the constant
@@ -21103,7 +21647,10 @@ static GTY(()) tree va_list_type;
      void *__vr_top;
      int   __gr_offs;
      int   __vr_offs;
-   };  */
+   };
+
+  darwinpcs uses 'char *' for the va_list (in common with other platform
+  ports).  */
 
 static tree
 aarch64_build_builtin_va_list (void)
@@ -21111,6 +21658,13 @@ aarch64_build_builtin_va_list (void)
   tree va_list_name;
   tree f_stack, f_grtop, f_vrtop, f_groff, f_vroff;
 
+  /* darwinpcs uses a simple char * for this.  */
+  if (TARGET_MACHO)
+    {
+      va_list_type = build_pointer_type (char_type_node);
+      return va_list_type;
+    }
+
   /* Create the type.  */
   va_list_type = lang_hooks.types.make_type (RECORD_TYPE);
   /* Give it the required name.  */
@@ -21182,6 +21736,13 @@ aarch64_expand_builtin_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
   int vr_save_area_size = cfun->va_list_fpr_size;
   int vr_offset;
 
+  /* darwinpcs uses the default, char * va_list impl.  */
+  if (TARGET_MACHO)
+    {
+      std_expand_builtin_va_start (valist, nextarg);
+      return;
+    }
+
   cum = &crtl->args.info;
   if (cfun->va_list_gpr_size)
     gr_save_area_size = MIN ((NUM_ARG_REGS - cum->aapcs_ncrn) * UNITS_PER_WORD,
@@ -21272,6 +21833,9 @@ aarch64_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
   HOST_WIDE_INT size, rsize, adjust, align;
   tree t, u, cond1, cond2;
 
+  if (TARGET_MACHO)
+    return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
+
   indirect_p = pass_va_arg_by_reference (type);
   if (indirect_p)
     type = build_pointer_type (type);
@@ -21476,8 +22040,18 @@ aarch64_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
 	  field_ptr_t = double_ptr_type_node;
 	  break;
 	case E_TFmode:
-	  field_t = long_double_type_node;
-	  field_ptr_t = long_double_ptr_type_node;
+	  if (TARGET_MACHO)
+	    {
+	      /* Darwin has __float128, and long double is the same as
+		 double.  */
+	      field_t = float128_type_node;
+	      field_ptr_t = aarch64_float128_ptr_type_node;
+	    }
+	  else
+	    {
+	      field_t = long_double_type_node;
+	      field_ptr_t = long_double_ptr_type_node;
+	    }
 	  break;
 	case E_SDmode:
 	  field_t = dfloat32_type_node;
@@ -21560,6 +22134,9 @@ aarch64_setup_incoming_varargs (cumulative_args_t cum_v,
   int gr_saved = cfun->va_list_gpr_size;
   int vr_saved = cfun->va_list_fpr_size;
 
+  if (TARGET_MACHO)
+    return default_setup_incoming_varargs (cum_v, arg, pretend_size, no_rtl);
+
   /* The caller has advanced CUM up to, but not beyond, the last named
      argument.  Advance a local copy of CUM past the last "real" named
      argument, to find out how many registers are left over.  */
@@ -22403,6 +22980,12 @@ aarch64_autovectorize_vector_modes (vector_modes *modes, bool)
 static const char *
 aarch64_mangle_type (const_tree type)
 {
+  /* The darwinpcs ABI documents say that "__va_list" has to be
+     mangled as char *.  */
+  if (TARGET_MACHO
+      && lang_hooks.types_compatible_p (CONST_CAST_TREE (type), va_list_type))
+    return "Pc";
+
   /* The AArch64 ABI documents say that "__va_list" has to be
      mangled as if it is in the "std" namespace.  */
   if (lang_hooks.types_compatible_p (CONST_CAST_TREE (type), va_list_type))
@@ -22419,6 +23002,12 @@ aarch64_mangle_type (const_tree type)
 	return "Dh";
     }
 
+  /* __float128 is mangled as "g" on darwin.  _Float128 is not mangled here,
+     but handled in common code (as "DF128_").  */
+  if (TARGET_MACHO && TYPE_MODE (type) == TFmode
+      && TYPE_MAIN_VARIANT (type) == float128t_type_node)
+    return "g";
+
   /* Mangle AArch64-specific internal types.  TYPE_NAME is non-NULL_TREE for
      builtin types.  */
   if (TYPE_NAME (type) != NULL)
@@ -23116,7 +23705,8 @@ aarch64_mov_operand_p (rtx x, machine_mode mode)
 
   /* GOT accesses are valid moves.  */
   if (SYMBOL_REF_P (x)
-      && aarch64_classify_symbolic_expression (x) == SYMBOL_SMALL_GOT_4G)
+      && (aarch64_classify_symbolic_expression (x) == SYMBOL_SMALL_GOT_4G
+	  || aarch64_classify_symbolic_expression (x) == SYMBOL_MO_SMALL_GOT))
     return true;
 
   if (SYMBOL_REF_P (x) && mode == DImode && CONSTANT_ADDRESS_P (x))
@@ -24453,12 +25043,8 @@ aarch64_asm_output_variant_pcs (FILE *stream, const tree decl, const char* name)
 static std::string aarch64_last_printed_arch_string;
 static std::string aarch64_last_printed_tune_string;
 
-/* Implement ASM_DECLARE_FUNCTION_NAME.  Output the ISA features used
-   by the function fndecl.  */
-
-void
-aarch64_declare_function_name (FILE *stream, const char* name,
-				tree fndecl)
+static void
+aarch64_function_options_preamble (tree fndecl)
 {
   tree target_parts = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
 
@@ -24497,15 +25083,60 @@ aarch64_declare_function_name (FILE *stream, const char* name,
 		   this_tune->name);
       aarch64_last_printed_tune_string = this_tune->name;
     }
+}
+
+/* Implement ASM_DECLARE_FUNCTION_NAME.  Output the ISA features used
+   by the function fndecl.  */
+
+#if TARGET_MACHO
+void
+aarch64_darwin_declare_function_name (FILE *stream, const char* name,
+				      tree fndecl)
+{
+  gcc_checking_assert (TREE_CODE (fndecl) == FUNCTION_DECL);
+  gcc_checking_assert (!DECL_COMMON (fndecl));
 
+  /* Update .arch and .tune as needed.  */
+  aarch64_function_options_preamble (fndecl);
+
+  /* Darwin does not emit pcs variant info.  */
+
+  rtx decl_rtx = XEXP (DECL_RTL (fndecl), 0);
+  if (GET_CODE (decl_rtx) != SYMBOL_REF)
+    name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
+
+  if (! DECL_WEAK (fndecl)
+      && ((TREE_STATIC (fndecl) && !TREE_PUBLIC (fndecl))
+	  || DECL_INITIAL (fndecl)))
+    machopic_define_symbol (DECL_RTL (fndecl));
+  if ((TREE_STATIC (fndecl) && !TREE_PUBLIC (fndecl))
+       || DECL_INITIAL (fndecl))
+    (* targetm.encode_section_info) (fndecl, DECL_RTL (fndecl), false);
+  ASM_OUTPUT_FUNCTION_LABEL (stream, name, fndecl);
+
+  cfun->machine->label_is_assembled = true;
+}
+
+#else
+
+void
+aarch64_declare_function_name (FILE *stream, const char* name,
+				tree fndecl)
+{
+  /* Update .arch and .tune as needed.  */
+  aarch64_function_options_preamble (fndecl);
+  /* Emit any necessary pcs information.  */
   aarch64_asm_output_variant_pcs (stream, fndecl, name);
 
   /* Don't forget the type directive for ELF.  */
+#ifdef ASM_OUTPUT_TYPE_DIRECTIVE
   ASM_OUTPUT_TYPE_DIRECTIVE (stream, name, "function");
+#endif
   ASM_OUTPUT_FUNCTION_LABEL (stream, name, fndecl);
 
   cfun->machine->label_is_assembled = true;
 }
+#endif
 
 /* Implement PRINT_PATCHABLE_FUNCTION_ENTRY.  */
 
@@ -24562,12 +25193,17 @@ aarch64_output_patchable_area (unsigned int patch_area_size, bool record_p)
 /* Implement ASM_OUTPUT_DEF_FROM_DECLS.  Output .variant_pcs for aliases.  */
 
 void
-aarch64_asm_output_alias (FILE *stream, const tree decl, const tree target)
+aarch64_asm_output_alias (FILE *stream, const tree decl,
+			  const tree target ATTRIBUTE_UNUSED)
 {
   const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+#ifdef ASM_OUTPUT_DEF
   const char *value = IDENTIFIER_POINTER (target);
+#endif
   aarch64_asm_output_variant_pcs (stream, decl, name);
+#ifdef ASM_OUTPUT_DEF
   ASM_OUTPUT_DEF (stream, name, value);
+#endif
 }
 
 /* Implement ASM_OUTPUT_EXTERNAL.  Output .variant_pcs for undefined
@@ -24613,6 +25249,9 @@ aarch64_start_file (void)
 		aarch64_last_printed_arch_string.c_str ());
 
    default_file_start ();
+#if TARGET_MACHO
+  darwin_file_start ();
+#endif
 }
 
 /* Emit load exclusive.  */
@@ -25192,6 +25831,16 @@ aarch64_output_simd_mov_immediate (rtx const_vector, unsigned width,
     }
 
   gcc_assert (CONST_INT_P (info.u.mov.value));
+  unsigned HOST_WIDE_INT value = UINTVAL (info.u.mov.value);
+
+  /* We have signed chars which can result in a sign-extended 8bit value
+     which is then emitted as an unsigned hex value, and the LLVM back end
+     assembler rejects that as being too big.  */
+  if (TARGET_MACHO && (known_eq (GET_MODE_BITSIZE (info.elt_mode), 8)))
+    {
+      unsigned HOST_WIDE_INT mask = (1U << GET_MODE_BITSIZE (info.elt_mode))-1;
+      value &= mask;
+    }
 
   if (which == AARCH64_CHECK_MOV)
     {
@@ -25200,16 +25849,16 @@ aarch64_output_simd_mov_immediate (rtx const_vector, unsigned width,
 		  ? "msl" : "lsl");
       if (lane_count == 1)
 	snprintf (templ, sizeof (templ), "%s\t%%d0, " HOST_WIDE_INT_PRINT_HEX,
-		  mnemonic, UINTVAL (info.u.mov.value));
+		  mnemonic, value);
       else if (info.u.mov.shift)
 	snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, "
 		  HOST_WIDE_INT_PRINT_HEX ", %s %d", mnemonic, lane_count,
-		  element_char, UINTVAL (info.u.mov.value), shift_op,
+		  element_char, value, shift_op,
 		  info.u.mov.shift);
       else
 	snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, "
 		  HOST_WIDE_INT_PRINT_HEX, mnemonic, lane_count,
-		  element_char, UINTVAL (info.u.mov.value));
+		  element_char, value);
     }
   else
     {
@@ -25218,12 +25867,12 @@ aarch64_output_simd_mov_immediate (rtx const_vector, unsigned width,
       if (info.u.mov.shift)
 	snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, #"
 		  HOST_WIDE_INT_PRINT_DEC ", %s #%d", mnemonic, lane_count,
-		  element_char, UINTVAL (info.u.mov.value), "lsl",
+		  element_char, value, "lsl",
 		  info.u.mov.shift);
       else
 	snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, #"
 		  HOST_WIDE_INT_PRINT_DEC, mnemonic, lane_count,
-		  element_char, UINTVAL (info.u.mov.value));
+		  element_char, value);
     }
   return templ;
 }
@@ -28459,7 +29108,8 @@ aarch64_libgcc_floating_mode_supported_p (scalar_float_mode mode)
 }
 
 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P - return TRUE
-   if MODE is [BH]Fmode, and punt to the generic implementation otherwise.  */
+   if MODE is [BH]Fmode, or TFmode on Mach-O, and punt to the generic
+   implementation otherwise.  */
 
 static bool
 aarch64_scalar_mode_supported_p (scalar_mode mode)
@@ -28467,7 +29117,7 @@ aarch64_scalar_mode_supported_p (scalar_mode mode)
   if (DECIMAL_FLOAT_MODE_P (mode))
     return default_decimal_float_supported_p ();
 
-  return ((mode == HFmode || mode == BFmode)
+  return ((mode == HFmode || mode == BFmode || (mode == TFmode && TARGET_MACHO))
 	  ? true
 	  : default_scalar_mode_supported_p (mode));
 }
@@ -29284,19 +29934,37 @@ aarch64_sls_emit_shared_blr_thunks (FILE *out_file)
 	continue;
 
       const char *name = indirect_symbol_names[regnum];
-      switch_to_section (get_named_section (decl, NULL, 0));
+      /* If the target uses a unique section for this switch to it.  */
+      if (DECL_SECTION_NAME (decl))
+	switch_to_section (get_named_section (decl, NULL, 0));
+      else
+	switch_to_section (text_section);
       ASM_OUTPUT_ALIGN (out_file, 2);
-      targetm.asm_out.globalize_label (out_file, name);
+      if (!TARGET_MACHO)
+	targetm.asm_out.globalize_label (out_file, name);
+#ifdef ASM_OUTPUT_TYPE_DIRECTIVE
+      ASM_OUTPUT_TYPE_DIRECTIVE (out_file, name, "function");
+#endif
+      if (TARGET_MACHO)
+	{
+#ifdef ASM_WEAKEN_DECL
+	  if (DECL_WEAK (decl))
+	    ASM_WEAKEN_DECL (out_file, decl, name, 0);
+	  else
+#endif
+	    targetm.asm_out.globalize_decl_name (out_file, decl);
+	}
       /* Only emits if the compiler is configured for an assembler that can
 	 handle visibility directives.  */
       targetm.asm_out.assemble_visibility (decl, VISIBILITY_HIDDEN);
-      ASM_OUTPUT_TYPE_DIRECTIVE (out_file, name, "function");
       ASM_OUTPUT_LABEL (out_file, name);
       aarch64_sls_emit_function_stub (out_file, regnum);
       /* Use the most conservative target to ensure it can always be used by any
 	 function in the translation unit.  */
       asm_fprintf (out_file, "\tdsb\tsy\n\tisb\n");
+#ifdef ASM_DECLARE_FUNCTION_SIZE
       ASM_DECLARE_FUNCTION_SIZE (out_file, name, decl);
+#endif
     }
 }
 
@@ -30384,6 +31052,60 @@ aarch64_retrieve_sysreg (const char *regname, bool write_p, bool is128op)
   return sysreg->encoding;
 }
 
+#if TARGET_MACHO
+/* This handles the promotion of function return values.
+   It also handles function args under two specific curcumstances:
+     - called from combine with a register argument
+     - caller for a libcall with type == NULL.
+   The remaining cases for argument promotion are handled with access to
+   cumulative args data, below.  */
+machine_mode
+aarch64_darwin_promote_fn_mode (const_tree type, machine_mode mode,
+			       int *punsignedp,
+			       const_tree funtype ATTRIBUTE_UNUSED,
+			       int for_return ATTRIBUTE_UNUSED)
+{
+  /* With the amended use of promote using cargs, the only cases that arrive
+     here with for_return == 0 are from combine (where the value is definitely
+     in a register) and for libcalls, where type == NULL.  We want to promote
+     function return values in the callee, so this becomes pretty much
+     unconditional now.  */
+  if (type != NULL_TREE)
+    return promote_mode (type, mode, punsignedp);
+  return mode;
+}
+
+/* Ensure that we only promote the mode of named parms when they are passed in
+   a register.  Named values passed on the stack retain their original mode and
+   alignment.  */
+machine_mode
+aarch64_darwin_promote_function_mode_ca (cumulative_args_t ca,
+					 function_arg_info arg,
+					 const_tree funtype ATTRIBUTE_UNUSED,
+					 int *punsignedp,
+					 int for_return ATTRIBUTE_UNUSED)
+{
+  tree type = arg.type;
+  machine_mode mode = arg.mode;
+  machine_mode new_mode = promote_mode (type, mode, punsignedp);
+  if (new_mode == mode || arg.named == false
+      || GET_MODE_CLASS (new_mode) != MODE_INT
+      || known_gt (GET_MODE_SIZE (new_mode), 4))
+    return new_mode;
+
+  CUMULATIVE_ARGS *pcum = get_cumulative_args (ca);
+  /* Make sure that changes in assumption do not get missed.  */
+  gcc_checking_assert (for_return == 0 && new_mode == SImode
+		       && !pcum->aapcs_arg_processed);
+  /* We have a named integer value that fits in a reg; if there's one available
+     then promote the value.  */
+  if (pcum->aapcs_ncrn < 8)
+    return new_mode;
+  return mode;
+}
+
+#endif
+
 /* Target-specific selftests.  */
 
 #if CHECKING_P
@@ -30600,6 +31322,15 @@ aarch64_run_selftests (void)
 #undef TARGET_ASM_ALIGNED_SI_OP
 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
 
+#if TARGET_MACHO
+#undef TARGET_ASM_UNALIGNED_HI_OP
+#define TARGET_ASM_UNALIGNED_HI_OP "\t.short\t"
+#undef TARGET_ASM_UNALIGNED_SI_OP
+#define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
+#undef TARGET_ASM_UNALIGNED_DI_OP
+#define TARGET_ASM_UNALIGNED_DI_OP "\t.quad\t"
+#endif
+
 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
   hook_bool_const_tree_hwi_hwi_const_tree_true
@@ -30702,6 +31433,12 @@ aarch64_run_selftests (void)
 #undef TARGET_FUNCTION_ARG_BOUNDARY
 #define TARGET_FUNCTION_ARG_BOUNDARY aarch64_function_arg_boundary
 
+#undef TARGET_FUNCTION_ARG_BOUNDARY_CA
+#define TARGET_FUNCTION_ARG_BOUNDARY_CA aarch64_function_arg_boundary_ca
+
+#undef  TARGET_FUNCTION_ARG_ROUND_BOUNDARY_CA
+#define TARGET_FUNCTION_ARG_ROUND_BOUNDARY_CA aarch64_function_arg_round_boundary_ca
+
 #undef TARGET_FUNCTION_ARG_PADDING
 #define TARGET_FUNCTION_ARG_PADDING aarch64_function_arg_padding
 
@@ -31042,7 +31779,7 @@ aarch64_libgcc_floating_mode_supported_p
 
 /* The architecture reserves bits 0 and 1 so use bit 2 for descriptors.  */
 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
-#define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 4
+#define TARGET_CUSTOM_FUNCTION_DESCRIPTORS AARCH64_CUSTOM_FUNCTION_TEST
 
 #undef TARGET_HARD_REGNO_NREGS
 #define TARGET_HARD_REGNO_NREGS aarch64_hard_regno_nregs
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index fe02a02a57b..b486afb795f 100644
--- gcc/config/aarch64/aarch64.h
+++ gcc/config/aarch64/aarch64.h
@@ -72,6 +72,10 @@
 #define TARGET_SIMD (AARCH64_ISA_SIMD && AARCH64_ISA_SM_OFF)
 #define TARGET_FLOAT (AARCH64_ISA_FP)
 
+/* If this is non-zero then generated code of the object format, ABI and
+   assembler syntax used by Darwin (Mach-O) platforms.  */
+#define TARGET_MACHO		0
+
 #define UNITS_PER_WORD		8
 
 #define UNITS_PER_VREG		16
@@ -149,6 +153,12 @@
 /* Heap alignment (same as BIGGEST_ALIGNMENT and STACK_BOUNDARY).  */
 #define MALLOC_ABI_ALIGNMENT  128
 
+/* We will and with this value to test if a custom function descriptor needs
+   a static chain.  The function boundary must the adjusted so that the bit
+   this represents is no longer part of the address.  0 Disables the custom
+   function descriptors.  */
+#define AARCH64_CUSTOM_FUNCTION_TEST 4
+
 /* Defined by the ABI */
 #define WCHAR_TYPE "unsigned int"
 #define WCHAR_TYPE_SIZE			32
@@ -1146,6 +1156,24 @@ typedef struct
 				   aapcs_reg == NULL_RTX.  */
   int aapcs_stack_size;		/* The total size (in words, per 8 byte) of the
 				   stack arg area so far.  */
+
+  /* In the darwinpcs, items smaller than one word are packed onto the stack
+     naturally aligned.  Unnamed parameters passed in a variadic call are,
+     however, aligned the same way as the AAPCS64.  This means that we need to
+     pad the last named arg to the next parm boundary (and hence notice when
+     we are processing that arg).  */
+  int darwinpcs_stack_bytes;	/* If the argument is passed on the stack, this
+				   the byte-size.  */
+  int darwinpcs_sub_word_offset;/* This is the offset of this arg within a word
+				   when placing smaller items for darwinpcs.  */
+  int darwinpcs_sub_word_pos;	/* The next byte available within the word for
+				   darwinpcs.  */
+  unsigned darwinpcs_arg_boundary; /* The computed argument boundary.  */
+  unsigned darwinpcs_arg_padding; /* The computed argument padding.  */
+  unsigned darwinpcs_n_named;	/* Number of named arguments.  */
+  unsigned darwinpcs_n_args_processed; /* Processed so far.  */
+  bool named_p;			/* Is this arg named? */
+  bool last_named_p;		/* Is this the last named arg? */
   bool silent_p;		/* True if we should act silently, rather than
 				   raise an error for invalid calls.  */
 
@@ -1457,8 +1485,13 @@ extern const char *aarch64_rewrite_mcpu (int argc, const char **argv);
 #define ASM_CPU_SPEC \
    MCPU_TO_MARCH_SPEC
 
+#ifndef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS
+#endif
+
 #define EXTRA_SPECS						\
-  { "asm_cpu_spec",		ASM_CPU_SPEC }
+  { "asm_cpu_spec",		ASM_CPU_SPEC },			\
+  SUBTARGET_EXTRA_SPECS
 
 #define ASM_OUTPUT_POOL_EPILOGUE  aarch64_asm_output_pool_epilogue
 
@@ -1471,6 +1504,10 @@ extern GTY(()) tree aarch64_fp16_ptr_type_node;
    bfloat16_type_node.  Defined in aarch64-builtins.cc.  */
 extern GTY(()) tree aarch64_bf16_ptr_type_node;
 
+/* A pointer to the user-visible __float128 (on Mach-O).  Defined in
+   aarch64-builtins.c.  */
+extern GTY(()) tree aarch64_float128_ptr_type_node;
+
 /* The generic unwind code in libgcc does not initialize the frame pointer.
    So in order to unwind a function using a frame pointer, the very first
    function that is unwound must save the frame pointer.  That way the frame
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 6a481059bf0..6d62e8ec0dd 100644
--- gcc/config/aarch64/aarch64.md
+++ gcc/config/aarch64/aarch64.md
@@ -363,6 +363,7 @@
     ;; Wraps a constant integer that should be multiplied by the number
     ;; of quadwords in an SME vector.
     UNSPEC_SME_VQ
+    UNSPEC_MACHOPIC_OFFSET	; Common to Mach-O ports.
 ])
 
 (define_c_enum "unspecv" [
@@ -995,6 +996,37 @@
   [(set_attr "type" "load_4")]
 )
 
+(define_insn "prefetch_unscaled"
+  [(prefetch (match_operand:DI 0 "aarch64_unscaled_prefetch_operand" "Du")
+            (match_operand:QI 1 "const_int_operand" "")
+            (match_operand:QI 2 "const_int_operand" ""))]
+  ""
+  {
+    const char * pftype[2][4] =
+    {
+      {"prfum\\tPLDL1STRM, %0",
+       "prfum\\tPLDL3KEEP, %0",
+       "prfum\\tPLDL2KEEP, %0",
+       "prfum\\tPLDL1KEEP, %0"},
+      {"prfum\\tPSTL1STRM, %0",
+       "prfum\\tPSTL3KEEP, %0",
+       "prfum\\tPSTL2KEEP, %0",
+       "prfum\\tPSTL1KEEP, %0"},
+    };
+
+    int locality = INTVAL (operands[2]);
+
+    gcc_assert (IN_RANGE (locality, 0, 3));
+
+    /* PRFUM accepts the same addresses as a 64-bit LDR so wrap
+       the address into a DImode MEM so that aarch64_print_operand knows
+       how to print it.  */
+    operands[0] = gen_rtx_MEM (DImode, operands[0]);
+    return pftype[INTVAL(operands[1])][locality];
+  }
+  [(set_attr "type" "load_4")]
+)
+
 (define_insn "trap"
   [(trap_if (const_int 1) (const_int 8))]
   ""
@@ -1447,7 +1479,7 @@
      [w  , m  ; load_4   , fp  , 4] ldr\t%s0, %1
      [m  , r Z; store_4  , *   , 4] str\t%w1, %0
      [m  , w  ; store_4  , fp  , 4] str\t%s1, %0
-     [r  , Usw; load_4   , *   , 8] adrp\t%x0, %A1;ldr\t%w0, [%x0, %L1]
+     [r  , Usw; load_4   , *   , 8] << TARGET_MACHO ? \"adrp\\t%x0, %A1\;ldr\\t%w0, [%x0, %O1]\" : \"adrp\\t%x0, %A1\;ldr\\t%w0, [%x0, %L1]\";
      [r  , Usa; adr      , *   , 4] adr\t%x0, %c1
      [r  , Ush; adr      , *   , 4] adrp\t%x0, %A1
      [w  , r Z; f_mcr    , fp  , 4] fmov\t%s0, %w1
@@ -1484,7 +1516,7 @@
      [w, m  ; load_8   , fp  , 4] ldr\t%d0, %1
      [m, r Z; store_8  , *   , 4] str\t%x1, %0
      [m, w  ; store_8  , fp  , 4] str\t%d1, %0
-     [r, Usw; load_8   , *   , 8] << TARGET_ILP32 ? "adrp\t%0, %A1;ldr\t%w0, [%0, %L1]" : "adrp\t%0, %A1;ldr\t%0, [%0, %L1]";
+     [r, Usw; load_8   , *   , 8] << TARGET_ILP32 ? (TARGET_MACHO ? \"adrp\\t%0, %A1\;ldr\\t%w0, [%0, %O1]\" : \"adrp\\t%0, %A1\;ldr\\t%w0, [%0, %L1]\") : (TARGET_MACHO ? \"adrp\\t%0, %A1\;ldr\\t%0, [%0, %O1]\" : \"adrp\\t%0, %A1\;ldr\\t%0, [%0, %L1]\");
      [r, Usa; adr      , *   , 4] adr\t%x0, %c1
      [r, Ush; adr      , *   , 4] adrp\t%x0, %A1
      [w, r Z; f_mcr    , fp  , 4] fmov\t%d0, %x1
@@ -7390,7 +7422,10 @@
 	(lo_sum:P (match_operand:P 1 "register_operand" "r")
 		  (match_operand 2 "aarch64_valid_symref" "S")))]
   ""
-  "add\\t%<w>0, %<w>1, :lo12:%c2"
+  { return TARGET_MACHO
+    ? "add\\t%<w>0, %<w>1, %J2;"
+    : "add\\t%<w>0, %<w>1, :lo12:%c2";
+  }
   [(set_attr "type" "alu_imm")]
 )
 
diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
index 6356c419399..5c9bb0a9056 100644
--- gcc/config/aarch64/aarch64.opt
+++ gcc/config/aarch64/aarch64.opt
@@ -193,6 +193,13 @@ Enum(aarch64_abi) String(ilp32) Value(AARCH64_ABI_ILP32)
 EnumValue
 Enum(aarch64_abi) String(lp64) Value(AARCH64_ABI_LP64)
 
+EnumValue
+Enum(aarch64_abi) String(darwinpcs) Value(AARCH64_ABI_LP64)
+
+m64
+Target RejectNegative Alias(mabi=, darwinpcs)
+On Darwin for compatibility with other platform variants.
+
 mpc-relative-literal-loads
 Target Save Var(pcrelative_literal_loads) Init(2) Save
 PC relative literal loads.
diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md
index a2569cea510..9ade357cacc 100644
--- gcc/config/aarch64/constraints.md
+++ gcc/config/aarch64/constraints.md
@@ -203,7 +203,9 @@
    A constraint that matches a small GOT access."
   (and (match_code "const,symbol_ref")
        (match_test "aarch64_classify_symbolic_expression (op)
-		     == SYMBOL_SMALL_GOT_4G")))
+		     == SYMBOL_SMALL_GOT_4G
+		    || aarch64_classify_symbolic_expression (op)
+		     == SYMBOL_MO_SMALL_GOT")))
 
 (define_constraint "Uss"
   "@internal
@@ -574,6 +576,11 @@
  An address valid for a prefetch instruction."
  (match_test "aarch64_address_valid_for_prefetch_p (op, true)"))
 
+(define_address_constraint "Du"
+  "@internal
+ An address valid for a prefetch instruction with an unscaled offset."
+ (match_test "aarch64_address_valid_for_unscaled_prefetch_p (op, true)"))
+
 (define_constraint "vgb"
   "@internal
    A constraint that matches an immediate offset valid for SVE LD1B
diff --git a/gcc/config/aarch64/darwin.h b/gcc/config/aarch64/darwin.h
new file mode 100644
index 00000000000..4b6bac4cf4b
--- /dev/null
+++ gcc/config/aarch64/darwin.h
@@ -0,0 +1,291 @@
+/* Target definitions for Arm64/Aarch64 running on macOS/iOS.
+
+Copyright The GNU Toolchain Authors.
+Contributed by Iain Sandoe.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+/* Enable Mach-O bits in generic Aarch64 code.  */
+#undef TARGET_MACHO
+#define TARGET_MACHO 1
+
+#undef DARWIN_ARM64
+#define DARWIN_ARM64 1
+
+/* This is used in generic code in darwin.cc (at present, we have no support
+   for the arm64_32 target).  */
+#undef TARGET_64BIT
+#define TARGET_64BIT 1
+
+#undef  PTRDIFF_TYPE
+#define PTRDIFF_TYPE "long int"
+
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE aarch64_darwin_promote_fn_mode
+
+#undef TARGET_PROMOTE_FUNCTION_MODE_CA
+#define TARGET_PROMOTE_FUNCTION_MODE_CA aarch64_darwin_promote_function_mode_ca
+
+/* NOTE that arm64_32 is a valid thing and corresponds to darwinpcs
+   and TARGET_ILP32, but we are not implementing that for now.  */
+#define TARGET_OS_CPP_BUILTINS()		\
+  do {						\
+    builtin_define ("__LITTLE_ENDIAN__");	\
+    builtin_define ("__arm64");			\
+    builtin_define ("__arm64__");		\
+    darwin_cpp_builtins (pfile);		\
+  } while (0)
+
+/* In Darwin's Arm64 ABI, chars are signed.  */
+
+#undef DEFAULT_SIGNED_CHAR
+#define DEFAULT_SIGNED_CHAR 1
+
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE	64
+
+/* Disable custom function descriptors on Darwin (we use heap-based
+   trampolines).  */
+#undef AARCH64_CUSTOM_FUNCTION_TEST
+#define AARCH64_CUSTOM_FUNCTION_TEST 0
+
+/* Non-PIE executables are forbidden by the Arm64-darwin security model;
+   remove the option from link-lines since they just produce a warning from
+   ld64 and are then ignored anyway.  */
+#undef DARWIN_NOPIE_SPEC
+#define DARWIN_NOPIE_SPEC \
+" %<no-pie %<fno-pie %<fno-PIE "
+
+/* Force the default endianness and ABI flags onto the command line
+   in order to make the other specs easier to write.  Match clang in
+   silently ignoring mdynamic-no-pic */
+#undef DRIVER_SELF_SPECS
+#define DRIVER_SELF_SPECS \
+"%{mbig-endian:%eDarwin platforms do not support big-endian arm64}" \
+"%{!mlittle-endian:-mlittle-endian} " \
+"%{mabi=ilp32:%eSorry, support for Darwin ilp32 arm64 is not implemented} " \
+"%{!mabi=*:-mabi=lp64} " \
+" %<mdynamic-no-pic* " \
+  MCPU_MTUNE_NATIVE_SPECS \
+  SUBTARGET_DRIVER_SELF_SPECS
+
+/* We want -fPIC by default, unless we're using -static to compile for
+   the kernel or some such.  */
+
+#undef CC1_SPEC
+#define CC1_SPEC \
+"%{!mkernel:%{!static:-fPIC}} " DARWIN_CC1_SPEC
+
+#undef ASM_SPEC
+#define ASM_SPEC "-arch %(darwin_arch) %{march*} %{mtune*} "\
+  ASM_OPTIONS " %{static} " ASM_MMACOSX_VERSION_MIN_SPEC
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+  " " TM_DESTRUCTOR
+
+/* The arch is known as 'arm64' by the system tools.  */
+#define DARWIN_ARCH_SPEC "arm64"
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS					\
+  DARWIN_EXTRA_SPECS						\
+  { "darwin_arch", DARWIN_ARCH_SPEC },				\
+  { "darwin_crt2", "" },					\
+  { "darwin_subarch", DARWIN_ARCH_SPEC },
+
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END darwin_file_end
+
+/* For now, we do not give global entities any extra alignment
+   TODO: determine if we should for some optimisation level.  */
+#undef DATA_ALIGNMENT
+#define DATA_ALIGNMENT(EXP, ALIGN)			\
+  AARCH64_EXPAND_ALIGNMENT (false, EXP, ALIGN)
+
+/* Darwin binds locally for PIC code (the default) without which
+   we lose many in-lineing opportunities.  */
+#undef TARGET_BINDS_LOCAL_P
+#define TARGET_BINDS_LOCAL_P darwin_binds_local_p
+
+/* Define the syntax of pseudo-ops, labels and comments.  */
+
+#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
+/* Support for -falign-* switches.  Use .p2align to ensure that code
+   sections are padded with NOP instructions, rather than zeros.  */
+#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE, LOG, MAX_SKIP)		\
+  do								\
+    {								\
+      if ((LOG) != 0)						\
+	{							\
+	  if ((MAX_SKIP) == 0)					\
+	    fprintf ((FILE), "\t.p2align %d\n", (int) (LOG));	\
+	  else							\
+	    fprintf ((FILE), "\t.p2align %d,,%d\n",		\
+		     (int) (LOG), (int) (MAX_SKIP));		\
+	}							\
+    } while (0)
+
+#endif /* HAVE_GAS_MAX_SKIP_P2ALIGN */
+
+/* String containing the assembler's comment-starter.  */
+
+#define ASM_COMMENT_START ";"
+
+/* Define the syntax of pseudo-ops, labels and comments.  */
+
+#define LPREFIX "L"
+
+/* Assembler pseudos to introduce constants of various size.  */
+
+#define ASM_BYTE "\t.byte\t"
+#define ASM_SHORT "\t.word\t"
+#define ASM_LONG "\t.long\t"
+#define ASM_QUAD "\t.quad\t"
+
+/* darwinpcs reserves X18.  */
+
+#undef FIXED_REGISTERS
+#define FIXED_REGISTERS					\
+  {							\
+    0, 0, 0, 0,   0, 0, 0, 0,	/* R0 - R7 */		\
+    0, 0, 0, 0,   0, 0, 0, 0,	/* R8 - R15 */		\
+    0, 0, 1, 0,   0, 0, 0, 0,	/* R16 - R23 */		\
+    0, 0, 0, 0,   0, 1, 0, 1,	/* R24 - R30, SP */	\
+    0, 0, 0, 0,   0, 0, 0, 0,   /* V0 - V7 */           \
+    0, 0, 0, 0,   0, 0, 0, 0,   /* V8 - V15 */		\
+    0, 0, 0, 0,   0, 0, 0, 0,   /* V16 - V23 */         \
+    0, 0, 0, 0,   0, 0, 0, 0,   /* V24 - V31 */         \
+    1, 1, 1, 1,			/* SFP, AP, CC, VG */	\
+    0, 0, 0, 0,   0, 0, 0, 0,   /* P0 - P7 */           \
+    0, 0, 0, 0,   0, 0, 0, 0,   /* P8 - P15 */          \
+    1, 1,			/* FFR and FFRT */	\
+    1, 1, 1, 1, 1, 1, 1, 1	/* Fake registers */	\
+  }
+
+/* Assign a static chain regnum.  At the moment using R16 (IP0) is
+   available.  */
+#undef STATIC_CHAIN_REGNUM
+#define STATIC_CHAIN_REGNUM	R16_REGNUM
+
+/* Heap trampoline support in a CRT.  */
+#undef DARWIN_HEAP_T_LIB
+#define DARWIN_HEAP_T_LIB " -lheapt_w "
+
+#define SUBTARGET_ENCODE_SECTION_INFO  darwin_encode_section_info
+
+#undef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
+#define ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(FILE, ENCODING, SIZE, ADDR, DONE) \
+  if (TARGET_64BIT)							\
+    {									\
+      if ((SIZE) == 4 && ((ENCODING) & 0x70) == DW_EH_PE_pcrel)		\
+	{								\
+	  static unsigned got_pcr_count = 0;				\
+	  fprintf (FILE, "L_got_pcr%d:\n" ASM_LONG, got_pcr_count);	\
+	  assemble_name (FILE, XSTR (ADDR, 0));				\
+	  fprintf (FILE, "@GOT-L_got_pcr%d", got_pcr_count++);		\
+	  goto DONE;							\
+	}								\
+    }									\
+  else									\
+    {									\
+      if (ENCODING == ASM_PREFERRED_EH_DATA_FORMAT (2, 1))		\
+	{								\
+	  gcc_unreachable (); /* no 32b support yet.*/			\
+	  goto DONE;							\
+	}								\
+    }
+
+#undef ASM_DECLARE_FUNCTION_NAME
+#define ASM_DECLARE_FUNCTION_NAME(STR, NAME, DECL)	\
+  aarch64_darwin_declare_function_name (STR, NAME, DECL)
+
+/* Darwin assemblers support the .ident directive.  */
+
+#undef TARGET_ASM_OUTPUT_IDENT
+#define TARGET_ASM_OUTPUT_IDENT default_asm_output_ident_directive
+
+/* Darwin has experimental support for section anchors on aarch64*; it is
+   not enabled by default (the -fsection-anchors is required), see below.  */
+
+#undef TARGET_ASM_OUTPUT_ANCHOR
+#define TARGET_ASM_OUTPUT_ANCHOR darwin_asm_output_anchor
+
+#undef TARGET_USE_ANCHORS_FOR_SYMBOL_P
+#define TARGET_USE_ANCHORS_FOR_SYMBOL_P darwin_use_anchors_for_symbol_p
+
+#undef DARWIN_SECTION_ANCHORS
+#define DARWIN_SECTION_ANCHORS 1
+
+/* Executable stack is prohibited by the system security policy.  */
+#undef HAVE_ENABLE_EXECUTE_STACK
+
+/* Pull in the stuff common to all Darwin-based platforms.  */
+#define C_COMMON_OVERRIDE_OPTIONS				\
+  do {								\
+    SUBTARGET_C_COMMON_OVERRIDE_OPTIONS;			\
+  } while (0)
+
+/* We do not have a definition for a tiny code model.
+   Section anchors are (probably) not useful with ld64 atom model so
+   default them off - this can be overridden by the user at present.
+   mdynamic-no-pic is silently ignored by clang (and not applicable
+   to this port).  */
+#undef SUBTARGET_OVERRIDE_OPTIONS
+#define SUBTARGET_OVERRIDE_OPTIONS					\
+  do {									\
+    if (global_options.x_aarch64_cmodel_var == AARCH64_CMODEL_TINY)	\
+      sorry ("code model %qs is not supported on Darwin platforms",	\
+	     "tiny");							\
+    if (!global_options_set.x_flag_section_anchors)			\
+      flag_section_anchors = 0;						\
+    target_flags &= ~MASK_MACHO_DYNAMIC_NO_PIC;				\
+  } while (0); 								\
+  SUBSUBTARGET_OVERRIDE_OPTIONS
+
+#undef  SUBTARGET_INIT_BUILTINS
+#define SUBTARGET_INIT_BUILTINS						\
+  do {									\
+    aarch64_builtin_decls[AARCH64_BUILTIN_CFSTRING]			\
+      = darwin_init_cfstring_builtins ((AARCH64_BUILTIN_CFSTRING << AARCH64_BUILTIN_SHIFT) | AARCH64_BUILTIN_GENERAL); \
+  } while(0)
+
+/* Darwin on Arm64 uses dwarf-2.  */
+#ifndef DARWIN_PREFER_DWARF
+# undef PREFERRED_DEBUGGING_TYPE
+# define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+#endif
+
+#undef REGISTER_SUBTARGET_PRAGMAS
+#define REGISTER_SUBTARGET_PRAGMAS() DARWIN_REGISTER_TARGET_PRAGMAS()
+
+#undef TARGET_SET_DEFAULT_TYPE_ATTRIBUTES
+#define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES darwin_set_default_type_attributes
+
+/* FIXME:  CHECK Define the shadow offset for asan.  */
+#undef SUBTARGET_SHADOW_OFFSET
+#define SUBTARGET_SHADOW_OFFSET (HOST_WIDE_INT_1 << 44)
+
+/* First available SYMBOL flag bit for use by subtargets.  */
+#define SYMBOL_FLAG_SUBT_DEP (SYMBOL_FLAG_MACH_DEP)
+
+#undef ASM_OUTPUT_DEF_FROM_DECLS
+
+#undef CLEAR_INSN_CACHE
+#define CLEAR_INSN_CACHE(beg, end)				\
+  extern void sys_icache_invalidate(void *start, size_t len);	\
+  sys_icache_invalidate ((beg), (size_t)((end)-(beg)))
diff --git a/gcc/config/aarch64/driver-aarch64.cc b/gcc/config/aarch64/driver-aarch64.cc
index fa0c57e6074..99b5da75496 100644
--- gcc/config/aarch64/driver-aarch64.cc
+++ gcc/config/aarch64/driver-aarch64.cc
@@ -28,6 +28,74 @@
 #include "aarch64-protos.h"
 #include "aarch64-feature-deps.h"
 
+#if TARGET_MACHO
+# include <sys/types.h>
+# include <sys/sysctl.h>
+#endif
+
+
+#if TARGET_MACHO
+
+/* Default architecture to use if -mcpu=native did not detect a known CPU.  */
+#define DEFAULT_ARCH "apple-m1"
+
+/* macOS does not have /proc/cpuinfo and needs a different approach,
+   based on sysctl.  It is much simpler.  */
+
+const char *
+host_detect_local_cpu (ATTRIBUTE_UNUSED int argc, ATTRIBUTE_UNUSED const char **argv)
+{
+  bool arch = false;
+  bool tune = false;
+  bool cpu = false;
+  const char *res = NULL;
+  uint32_t family;
+  size_t len = sizeof(family);
+
+  gcc_assert (argc);
+  if (!argv[0])
+    return NULL;
+
+  /* Are we processing -march, mtune or mcpu?  */
+  arch = strcmp (argv[0], "arch") == 0;
+  if (!arch)
+    tune = strcmp (argv[0], "tune") == 0;
+  if (!arch && !tune)
+    cpu = strcmp (argv[0], "cpu") == 0;
+  if (!arch && !tune && !cpu)
+    return NULL;
+
+  sysctlbyname("hw.cpufamily", &family, &len, NULL, 0);
+
+  switch (family)
+  {
+    case 0x07d34b9f: // Vortex, Tempest
+      res = "apple-a12";
+      break;
+    case 0x573b5eec:
+    case 0x1b588bb3: // Firestorm, Icestorm
+      res = "apple-m1";
+      break;
+    case 0xda33d83d: // Blizzard, Avalanche
+      res = "apple-m2";
+      break;
+    case 0xfa33415e: // Ibiza (M3)
+    case 0x5f4dea93: // Lobos (M3 Pro)
+    case 0x72015832: // Palma (M3 Max)
+      res = "apple-m3";
+      break;
+    default:
+      res = DEFAULT_ARCH;
+  }
+
+  if (res)
+    return concat ("-m", argv[0], "=", res, NULL);
+  else
+    return NULL;
+}
+
+#else
+
 struct aarch64_arch_extension
 {
   const char *ext;
@@ -501,3 +569,4 @@ not_found:
   }
 }
 
+#endif
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index b895f5dcb86..6e7487bcef5 100644
--- gcc/config/aarch64/predicates.md
+++ gcc/config/aarch64/predicates.md
@@ -352,9 +352,24 @@
 (define_predicate "aarch64_prefetch_operand"
   (match_test "aarch64_address_valid_for_prefetch_p (op, false)"))
 
+(define_predicate "aarch64_unscaled_prefetch_operand"
+  (match_test "aarch64_address_valid_for_unscaled_prefetch_p (op, false)"))
+
 (define_predicate "aarch64_valid_symref"
   (match_code "const, symbol_ref, label_ref")
 {
+  if (TARGET_MACHO)
+    {
+      rtx x = op;
+      rtx offset;
+      split_const (x, &x, &offset);
+      if (GET_CODE (x) == CONST)
+	x = XEXP (x, 0);
+      if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_SALT_ADDR)
+	x = XVECEXP (x, 0, 0);
+      if (SYMBOL_REF_P (x) && INTVAL (offset) < 0)
+        return false;
+    }
   return (aarch64_classify_symbolic_expression (op)
 	  != SYMBOL_FORCE_TO_MEM);
 })
diff --git a/gcc/config/aarch64/t-aarch64-darwin b/gcc/config/aarch64/t-aarch64-darwin
new file mode 100644
index 00000000000..e2b8ad9237f
--- /dev/null
+++ gcc/config/aarch64/t-aarch64-darwin
@@ -0,0 +1,25 @@
+# Machine description for AArch64 architecture.
+#  Copyright (C) 2020 Free Software Foundation, Inc.
+#
+#  This file is part of GCC.
+#
+#  GCC is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3, or (at your option)
+#  any later version.
+#
+#  GCC is distributed in the hope that it will be useful, but
+#  WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with GCC; see the file COPYING3.  If not see
+#  <http://www.gnu.org/licenses/>.
+
+LIB1ASMSRC   = aarch64/lib1funcs.asm
+LIB1ASMFUNCS = _aarch64_sync_cache_range
+
+# TODO - figure out what multilib provisions we should make for
+# a) arm64e
+# b) arm64_32
diff --git a/gcc/config/darwin-driver.cc b/gcc/config/darwin-driver.cc
index eabe9bc970d..176bcfb6843 100644
--- gcc/config/darwin-driver.cc
+++ gcc/config/darwin-driver.cc
@@ -268,10 +268,13 @@ darwin_driver_init (unsigned int *decoded_options_count,
   bool seenX86_64 = false;
   bool seenPPC = false;
   bool seenPPC64 = false;
+#if !DARWIN_ARM64
+  bool seenArm64 = false;
   bool seenM32 = false;
   bool seenM64 = false;
   bool appendM32 = false;
   bool appendM64 = false;
+#endif
   const char *vers_string = NULL;
   bool seen_version_min = false;
   bool seen_sysroot_p = false;
@@ -296,6 +299,12 @@ darwin_driver_init (unsigned int *decoded_options_count,
 	    seenPPC = true;
 	  else if (!strcmp ((*decoded_options)[i].arg, "ppc64"))
 	    seenPPC64 = true;
+	  else if (!strcmp ((*decoded_options)[i].arg, "arm64"))
+#if !DARWIN_ARM64
+	    seenArm64 = true;
+#else
+	    ; /* We accept the option, but don't need to act on it.  */
+#endif
 	  else
 	    error ("this compiler does not support %qs",
 		   (*decoded_options)[i].arg);
@@ -309,7 +318,7 @@ darwin_driver_init (unsigned int *decoded_options_count,
 	  --i;
 	  --*decoded_options_count; 
 	  break;
-
+#if !DARWIN_ARM64
 	case OPT_m32:
 	  seenM32 = true;
 	  break;
@@ -317,6 +326,7 @@ darwin_driver_init (unsigned int *decoded_options_count,
 	case OPT_m64:
 	  seenM64 = true;
 	  break;
+#endif
 
 	case OPT_mmacosx_version_min_:
 	  seen_version_min = true;
@@ -366,6 +376,9 @@ darwin_driver_init (unsigned int *decoded_options_count,
   if (seenPPC || seenPPC64)
     warning (0, "this compiler does not support PowerPC"
 		" (%<-arch%> option ignored)");
+  else if (seenArm64)
+    warning (0, "this compiler does not support Arm64"
+		" (%<-arch%> option ignored)");
   if (seenX86)
     {
       if (seenX86_64 || seenM64)
@@ -389,6 +402,9 @@ darwin_driver_init (unsigned int *decoded_options_count,
   if (seenX86 || seenX86_64)
     warning (0, "this compiler does not support x86"
 		" (%<-arch%> option ignored)");
+  else if (seenArm64)
+    warning (0, "this compiler does not support Arm64"
+		" (%<-arch%> option ignored)");
   if (seenPPC)
     {
       if (seenPPC64 || seenM64)
@@ -408,12 +424,20 @@ darwin_driver_init (unsigned int *decoded_options_count,
       if (! seenM64) /* Add -m64 if the User didn't. */
 	appendM64 = true;
     }
+#elif DARWIN_ARM64
+  if (seenPPC || seenPPC64)
+    warning (0, "this compiler does not support PowerPC"
+		" (%<-arch%> option ignored)");
+  if (seenX86 || seenX86_64)
+    warning (0, "this compiler does not support x86"
+		" (%<-arch%> option ignored)");
 #endif
 
   /* If there is nothing else on the command line, do not add sysroot etc.  */
   if (*decoded_options_count <= 1)
     return;
 
+#if !DARWIN_ARM64
   if (appendM32 || appendM64)
     {
       ++*decoded_options_count;
@@ -423,6 +447,7 @@ darwin_driver_init (unsigned int *decoded_options_count,
       generate_option (appendM32 ? OPT_m32 : OPT_m64, NULL, 1, CL_DRIVER,
 		       &(*decoded_options)[*decoded_options_count - 1]);
     }
+#endif
 
   if (!seen_sysroot_p)
     {
diff --git a/gcc/config/darwin-protos.h b/gcc/config/darwin-protos.h
index b67e05264e1..35116317b59 100644
--- gcc/config/darwin-protos.h
+++ gcc/config/darwin-protos.h
@@ -86,9 +86,12 @@ extern void darwin_asm_lto_end (void);
 extern void darwin_mark_decl_preserved (const char *);
 
 extern tree darwin_handle_kext_attribute (tree *, tree, tree, int, bool *);
-extern tree darwin_handle_weak_import_attribute (tree *node, tree name,
-						 tree args, int flags,
-						 bool * no_add_attrs);
+extern tree darwin_handle_weak_import_attribute (tree *, tree, tree, int,
+						 bool *);
+extern tree darwin_handle_availability_attribute (tree *, tree, tree,
+						  int, bool *);
+extern bool darwin_attribute_takes_identifier_p (const_tree);
+
 extern void machopic_output_stub (FILE *, const char *, const char *);
 extern void darwin_globalize_label (FILE *, const char *);
 extern void darwin_assemble_visibility (tree, int);
@@ -124,6 +127,7 @@ extern void darwin_enter_string_into_cfstring_table (tree);
 extern void darwin_asm_output_anchor (rtx symbol);
 extern bool darwin_use_anchors_for_symbol_p (const_rtx symbol);
 extern bool darwin_kextabi_p (void);
+extern bool darwin_unreachable_traps_p (void);
 extern void darwin_override_options (void);
 extern void darwin_patch_builtins (void);
 extern void darwin_rename_builtins (void);
diff --git a/gcc/config/darwin.cc b/gcc/config/darwin.cc
index 63b8c509405..864c620c308 100644
--- gcc/config/darwin.cc
+++ gcc/config/darwin.cc
@@ -29,6 +29,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "cfghooks.h"
 #include "df.h"
 #include "memmodel.h"
+#include "c-family/c-common.h"  /* enum rid.  */
 #include "tm_p.h"
 #include "stringpool.h"
 #include "attribs.h"
@@ -49,6 +50,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "optabs.h"
 #include "flags.h"
 #include "opts.h"
+#include "c-family/c-objc.h"    /* for objc_method_decl().  */
 
 /* Fix and Continue.
 
@@ -102,6 +104,7 @@ int darwin_running_cxx;
 
 /* Some code-gen now depends on OS major version numbers (at least).  */
 int generating_for_darwin_version ;
+unsigned long current_os_version = 0;
 
 /* For older linkers we need to emit special sections (marked 'coalesced') for
    for weak or single-definition items.  */
@@ -131,7 +134,7 @@ struct {
 section * darwin_sections[NUM_DARWIN_SECTIONS];
 
 /* While we transition to using in-tests instead of ifdef'd code.  */
-#if !HAVE_lo_sum
+#if !HAVE_lo_sum || DARWIN_ARM64
 #define gen_macho_high(m,a,b) (a)
 #define gen_macho_low(m,a,b,c) (a)
 #endif
@@ -1104,6 +1107,7 @@ machopic_legitimize_pic_address (rtx orig, machine_mode mode, rtx reg)
   return pic_ref;
 }
 
+#if !DARWIN_ARM64
 /* Callbacks to output the stub or non-lazy pointers.
    Each works on the item in *SLOT,if it has been used.
    DATA is the FILE* for assembly output.
@@ -1259,6 +1263,7 @@ machopic_finish (FILE *out_file)
   machopic_indirections->traverse_noresize
     <FILE *, machopic_output_indirection> (out_file);
 }
+#endif
 
 int
 machopic_operand_p (rtx op)
@@ -2194,6 +2199,122 @@ darwin_handle_kext_attribute (tree *node, tree name,
   return NULL_TREE;
 }
 
+enum version_components { MAJOR, MINOR, TINY };
+
+/* Parse a version number in x.y.z form and validate it as a macOS
+   version.  Ideally, we'd put this in a common place usable by the
+   Darwin backend.  */
+
+static bool
+parse_version (unsigned version_array[3], const char *version_str)
+{
+  size_t version_len;
+  char *end, last = '\0', delimiter = '.', alt_delim = '_';
+
+  if (!version_str)
+    return false;
+
+  /* Handle the odd situation in which we get STRING_CST which contain the
+     starting and ending quotes.  */
+  if (version_str[0] == '"')
+    {
+      version_str++;
+      version_len = strrchr (&version_str[1], '"') - version_str;
+      last = '"';
+   }
+  else
+    version_len = strlen (version_str);
+
+  if (version_len < 1)
+    return false;
+
+  /* Version string must consist of digits and periods only.  */
+  if (strspn (version_str, "0123456789._") != version_len)
+    return false;
+
+  if (!ISDIGIT (version_str[0]) || !ISDIGIT (version_str[version_len - 1]))
+    return false;
+
+  version_array[MAJOR] = strtoul (version_str, &end, 10);
+  if (*end == '_')
+    {
+      delimiter = '_';
+      alt_delim = '.';
+    }
+  version_str = end + ((*end == delimiter) ? 1 : 0);
+  if (version_array[MAJOR] == 100000)
+    return true;
+  if (version_array[MAJOR]  > 99)
+    return false;
+
+  /* Version string must not contain adjacent delimiters.  */
+  if (*version_str == delimiter || *version_str == alt_delim)
+    return false;
+
+  version_array[MINOR] = strtoul (version_str, &end, 10);
+  if (*end == alt_delim)
+    return false;
+  version_str = end + ((*end == delimiter) ? 1 : 0);
+  if (version_array[MINOR]  > 99)
+    return false;
+
+  version_array[TINY] = strtoul (version_str, &end, 10);
+  if (version_array[TINY]  > 99)
+    return false;
+
+  /* Version string must contain no more than three tokens.  */
+  if (*end != last)
+    return false;
+
+  return true;
+}
+
+/* Turn a version expressed as maj.min.tiny into an unsigned long
+   integer representing the value used in macOS availability macros.  */
+
+static unsigned long
+version_from_version_array (unsigned vers[3])
+{
+  unsigned long res = 0;
+  /* There seems to be a special "unknown" value.  */
+  if (vers[0] == 100000)
+    return 999999;
+
+  /* Here, we follow the 'modern' / 'legacy' numbering scheme for versions.  */
+  if (vers[0] > 10 || vers[1] >= 10)
+    res = vers[0] * 10000 + vers[1] * 100 + vers[2];
+  else
+    {
+      res = vers[0] * 100;
+      if (vers[1] > 9)
+	res += 90;
+      else
+	res += vers[1] * 10;
+      if (vers[2] > 9)
+	res += 9;
+      else
+	res += vers[1];
+    }
+  return res;
+}
+
+/* Extract a macOS version from an availability attribute argument.  */
+
+static unsigned long
+os_version_from_avail_value (tree value)
+{
+  unsigned long res = 0;
+  unsigned vers[3] = {0,0,0};
+  if (TREE_CODE (value) == STRING_CST)
+    {
+      if (parse_version (&vers[0], TREE_STRING_POINTER (value)))
+	res = version_from_version_array (&vers[0]);
+    }
+  else
+    gcc_unreachable ();
+  return res;
+}
+
 /* Handle a "weak_import" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -2215,6 +2336,231 @@ darwin_handle_weak_import_attribute (tree *node, tree name,
   return NULL_TREE;
 }
 
+#define NUM_AV_OSES 13
+const char *availability_os[NUM_AV_OSES]
+  = { "macos", "macosx", "ios", "tvos", "watchos", "driverkit", "swift",
+      "maccatalyst", "macCatalyst", "xros", "visionos", "android", "zos" };
+
+#define NUM_AV_CLAUSES 6
+const char *availability_clause[NUM_AV_CLAUSES]
+  = { "unavailable", "introduced", "deprecated", "obsoleted", "message",
+      "replacement" };
+
+/* Validate and act upon the arguments to an 'availability' attribute.  */
+
+tree
+darwin_handle_availability_attribute (tree *node, tree name, tree args,
+				      int flags, bool * no_add_attrs)
+{
+  tree decl = *node;
+  *no_add_attrs = true;
+
+  if (!decl || (!TYPE_P (decl) && !DECL_P (decl)))
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      return NULL_TREE;
+    }
+  else if (decl == error_mark_node)
+    return NULL_TREE;
+
+  location_t loc = DECL_SOURCE_LOCATION (decl);
+  if (args == NULL_TREE)
+    {
+      error_at (loc, "%qE attribute requires at least one argument",
+		name);
+      return NULL_TREE;
+    }
+  else if (args == error_mark_node)
+    return NULL_TREE;
+
+  /* The first argument must name a supported OS - although we could choose
+     to ignore any OS we don't recognise.  */
+  gcc_checking_assert (TREE_CODE (args) == TREE_LIST);
+  tree platform = TREE_VALUE (args);
+  if (platform == error_mark_node)
+    return NULL_TREE;
+
+  gcc_checking_assert (TREE_CODE (platform) == IDENTIFIER_NODE);
+  bool platform_ok = false;
+  unsigned plat_num = 0;
+  for (; plat_num < (unsigned) NUM_AV_OSES; plat_num++)
+    if (strcmp (availability_os[plat_num], IDENTIFIER_POINTER (platform)) == 0)
+      {
+	platform_ok = true;
+	break;
+      }
+  if (!platform_ok)
+    {
+      error_at (input_location,
+		"platform %qE is not recognised for the %<availability%> "
+		"attribute", platform);
+      return NULL_TREE;
+    }
+  else if (plat_num > 1) /* We only compile for macos so far.  */
+    return NULL_TREE;
+
+  /* We might be dealing with an object or type.  */
+  tree target_decl = NULL_TREE;
+  tree type = NULL_TREE;
+  bool warn = false;
+  if (DECL_P (*node))
+    {
+      type = TREE_TYPE (decl);
+
+      if (TREE_CODE (decl) == TYPE_DECL
+	  || TREE_CODE (decl) == PARM_DECL
+	  || VAR_OR_FUNCTION_DECL_P (decl)
+	  || TREE_CODE (decl) == FIELD_DECL
+	  || TREE_CODE (decl) == CONST_DECL
+	  /*|| objc_method_decl (TREE_CODE (decl))*/)
+	target_decl = decl;
+      else
+	warn = true;
+    }
+  else if (TYPE_P (*node))
+    type = target_decl = *node;
+  else
+    warn = true;
+
+  tree what = NULL_TREE;
+  if (warn)
+    {
+      if (type && TYPE_NAME (type))
+	{
+	  if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
+	    what = TYPE_NAME (*node);
+	  else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+		   && DECL_NAME (TYPE_NAME (type)))
+	    what = DECL_NAME (TYPE_NAME (type));
+	}
+      if (what)
+	warning (OPT_Wattributes, "%qE attribute ignored for %qE", name, what);
+      else
+	warning (OPT_Wattributes, "%qE attribute ignored", name);
+      return NULL_TREE;
+    }
+
+  /* Now we have to parse the availability clauses.  */
+  tree msg = NULL_TREE;
+  tree replacement = NULL_TREE;
+  bool unavailable = false;
+  unsigned introduced = 1000;
+  unsigned deprecated = current_os_version + 1;
+  unsigned obsoleted = current_os_version + 1;
+  for (tree arg = TREE_CHAIN (args); arg; arg = TREE_CHAIN (arg))
+    {
+      tree clause_name = TREE_VALUE (arg);
+      tree clause_value = TREE_PURPOSE (arg);
+      if (clause_name == error_mark_node
+	  || clause_value == error_mark_node)
+	continue;
+      unsigned clause_num = 0;
+      for (; clause_num < (unsigned) NUM_AV_CLAUSES; clause_num++)
+	if (strcmp (availability_clause[clause_num],
+		    IDENTIFIER_POINTER (clause_name)) == 0)
+	  break;
+      switch (clause_num)
+	{
+	default:
+	  error_at (input_location,
+		    "clause %qE is not recognised for the %<availability%> "
+		    "attribute", clause_name);
+	  break;
+	case 0:
+	  unavailable = true;
+	  break;
+	case 1:
+	case 2:
+	case 3:
+	  if (!clause_value)
+	    error_at (input_location, "%<%E=%> requires a value", clause_name);
+	  else
+	    {
+	      unsigned version = os_version_from_avail_value (clause_value);
+	      if (version == 0)
+		error_at (input_location, "the value %qE provided to %qE is "
+			"not a valid OS version", clause_value, clause_name);
+	      else if (clause_num == 1)
+		introduced = version;
+	      else if (clause_num == 2)
+		deprecated = version;
+	      else if (clause_num == 3)
+		obsoleted = version;
+	    }
+	  break;
+	case 4:
+	case 5:
+	  if (!clause_value || TREE_CODE (clause_value) != STRING_CST)
+	    error_at (input_location, "%<%E=%> requires a string", clause_name);
+	  else if (clause_num == 4)
+	    msg = clause_value;
+	  else
+	    replacement = clause_value;
+	  break;
+	}
+    }
+  /* Now figure out what to do.  */
+  tree maybe_text = NULL_TREE;
+  if (replacement)
+    maybe_text = tree_cons (NULL_TREE, replacement, NULL_TREE);
+  else if (msg)
+    maybe_text = tree_cons (NULL_TREE, msg, NULL_TREE);
+
+  if (unavailable || current_os_version >= obsoleted)
+    {
+      TREE_UNAVAILABLE (*node) = true;
+      /* We do not handle the availability attribute at diagnostics-time, so
+	 if we want the informational messages, then attach them to additional
+	 attributes for the deprecation or unavailability.  TODO; maybe we can
+	 fabricate the composite here.  */
+      if (maybe_text)
+	{
+	  *no_add_attrs = false;
+	  tree new_attr = tree_cons (get_identifier ("unavailable"),
+				     maybe_text, NULL_TREE);
+	  /* This is the actual consequence of the evaluation.  */
+	  if (TYPE_P (target_decl) && !(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+	    {
+	      *node = build_variant_type_copy (*node);
+	      TYPE_ATTRIBUTES (*node) = chainon (TYPE_ATTRIBUTES (*node),
+						 new_attr);
+	    }
+	  else
+	    DECL_ATTRIBUTES (*node) = chainon (DECL_ATTRIBUTES (*node),
+					       new_attr);
+	}
+    }
+   else if (current_os_version > deprecated)
+    {
+      TREE_DEPRECATED (*node) = true;
+      if (maybe_text)
+	{
+	  *no_add_attrs = false;
+	  tree new_attr = tree_cons (get_identifier ("deprecated"),
+				     maybe_text, NULL_TREE);
+	  /* This is the actual consequence of the evaluation.  */
+	  if (TYPE_P (target_decl) && !(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+	    {
+	      *node = build_variant_type_copy (*node);
+	      TYPE_ATTRIBUTES (*node) = chainon (TYPE_ATTRIBUTES (*node),
+						 new_attr);
+	    }
+	  else
+	    DECL_ATTRIBUTES (*node) = chainon (DECL_ATTRIBUTES (*node),
+					       new_attr);
+	}
+    }
+  else if (current_os_version < introduced)
+    *no_add_attrs = false;
+  return NULL_TREE;
+}
+
+bool
+darwin_attribute_takes_identifier_p (const_tree attr_id)
+{
+  return is_attribute_p ("availability", attr_id);
+}
+
 /* Emit a label for an FDE, making it global and/or weak if appropriate.
    The third parameter is nonzero if this is for exception handling.
    The fourth parameter is nonzero if this is just a placeholder for an
@@ -2306,6 +2652,8 @@ darwin_emit_except_table_label (FILE *file)
 rtx
 darwin_make_eh_symbol_indirect (rtx orig, bool ARG_UNUSED (pubvis))
 {
+  if (DARWIN_ARM64)
+    return orig;
   if (DARWIN_PPC == 0 && TARGET_64BIT)
     return orig;
 
@@ -3154,7 +3502,12 @@ darwin_file_end (void)
       fprintf (asm_out_file, "\t.long\t0\n\t.long\t%u\n", flags);
      }
 
+#if !DARWIN_ARM64
   machopic_finish (asm_out_file);
+#else
+  gcc_checking_assert (!machopic_indirections);
+#endif
+
   if (flag_apple_kext)
     {
       /* These sections are only used for kernel code.  */
@@ -3330,6 +3683,13 @@ darwin_kextabi_p (void) {
   return flag_apple_kext;
 }
 
+/* True, iff we want to map __builtin_unreachable to a trap.  */
+
+bool
+darwin_unreachable_traps_p (void) {
+  return darwin_unreachable_traps;
+}
+
 void
 darwin_override_options (void)
 {
@@ -3350,7 +3710,14 @@ darwin_override_options (void)
 	generating_for_darwin_version = 8;
 
       /* Earlier versions are not specifically accounted, until required.  */
+      unsigned vers[3] = {0,0,0};
+      if (!parse_version (vers, darwin_macosx_version_min))
+	error_at (UNKNOWN_LOCATION, "how did we get a bad OS version? (%s)",
+		  darwin_macosx_version_min);
+      current_os_version = version_from_version_array (vers);
     }
+  else
+    current_os_version = 1058;
 
   /* Some codegen needs to account for the capabilities of the target
      linker.  */
@@ -3592,6 +3959,19 @@ darwin_override_options (void)
 
   /* The c_dialect...() macros are not available to us here.  */
   darwin_running_cxx = (strstr (lang_hooks.name, "C++") != 0);
+
+  /* Allow the clang extension to permit const vars used in array sizes.  */
+  if (!OPTION_SET_P (flag_allow_const_var_array_size))
+    flag_allow_const_var_array_size = true;
+
+  /* We need to consume attributes on function definitions from the the SDK
+     headers.  */
+  if (!OPTION_SET_P (flag_allow_ext_attr_placement))
+    flag_allow_ext_attr_placement = true;
+
+  /* We need to consume some C keywords in C++.  */
+  if (!OPTION_SET_P (flag_allow_extra_keywords))
+    flag_allow_extra_keywords = true;
 }
 
 #if DARWIN_PPC
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
index e7a6f5433ce..32bf784fc93 100644
--- gcc/config/darwin.h
+++ gcc/config/darwin.h
@@ -42,6 +42,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 #define DARWIN_X86 0
 #define DARWIN_PPC 0
+#define DARWIN_ARM64 0
 
 #define OBJECT_FORMAT_MACHO 1
 
@@ -378,7 +379,8 @@ extern GTY(()) int darwin_ms_struct;
 */
 
 #define DARWIN_NOCOMPACT_UNWIND \
-" %:version-compare(>= 10.6 mmacosx-version-min= -no_compact_unwind) "
+"%{!fuse-ld=lld: \
+    %:version-compare(>= 10.6 mmacosx-version-min= -no_compact_unwind)}"
 
 /* In Darwin linker specs we can put -lcrt0.o and ld will search the library
    path for crt0.o or -lcrtx.a and it will search for libcrtx.a.  As for
@@ -402,7 +404,8 @@ extern GTY(()) int darwin_ms_struct;
     LINK_PLUGIN_SPEC \
     "%{flto*:%<fcompare-debug*} \
      %{flto} %{fno-lto} %{flto=*} \
-    %l " \
+     %l \
+     %{fuse-ld=*:-fuse-ld=%*} " \
     DARWIN_PLATFORM_ID \
     LINK_COMPRESS_DEBUG_SPEC \
    "%X %{s} %{t} %{Z} %{u*} \
@@ -984,7 +987,12 @@ extern GTY(()) section * darwin_sections[NUM_DARWIN_SECTIONS];
   { "apple_kext_compatibility", 0, 0, false, true, false, false,	     \
     darwin_handle_kext_attribute, NULL },				     \
   { "weak_import", 0, 0, true, false, false, false,			     \
-    darwin_handle_weak_import_attribute, NULL }
+    darwin_handle_weak_import_attribute, NULL },			     \
+  { "availability", 0, -1, true, false, false, false,			     \
+    darwin_handle_availability_attribute, NULL }
+
+#undef TARGET_ATTRIBUTE_TAKES_IDENTIFIER_P
+#define TARGET_ATTRIBUTE_TAKES_IDENTIFIER_P darwin_attribute_takes_identifier_p
 
 /* Make local constant labels linker-visible, so that if one follows a
    weak_global constant, ld64 will be able to separate the atoms.  */
@@ -1001,6 +1009,8 @@ extern GTY(()) section * darwin_sections[NUM_DARWIN_SECTIONS];
       sprintf (LABEL, "*%s%ld", "lASAN", (long)(NUM));\
     else if (strcmp ("LTRAMP", PREFIX) == 0)	\
       sprintf (LABEL, "*%s%ld", "lTRAMP", (long)(NUM));\
+    else if (strncmp ("LANCHOR", PREFIX, 7) == 0)	\
+      sprintf (LABEL, "*%s%ld", "lANCHOR", (long)(NUM));\
     else						\
       sprintf (LABEL, "*%s%ld", PREFIX, (long)(NUM));	\
   } while (0)
@@ -1232,6 +1242,10 @@ void add_framework_path (char *);
 #define TARGET_N_FORMAT_TYPES 1
 #define TARGET_FORMAT_TYPES darwin_additional_format_types
 
+/* We want __builtin_unreachable to be expanded as a trap instruction.  */
+#undef TARGET_UNREACHABLE_SHOULD_TRAP
+#define TARGET_UNREACHABLE_SHOULD_TRAP darwin_unreachable_traps_p
+
 #ifndef USED_FOR_TARGET
 extern void darwin_driver_init (unsigned int *,struct cl_decoded_option **);
 #define GCC_DRIVER_HOST_INITIALIZATION \
diff --git a/gcc/config/darwin.opt b/gcc/config/darwin.opt
index 114048045b9..ea90afe108f 100644
--- gcc/config/darwin.opt
+++ gcc/config/darwin.opt
@@ -91,6 +91,10 @@ mtarget-linker
 Target RejectNegative Joined Separate Var(darwin_target_linker) Init(LD64_VERSION)
 -mtarget-linker <version>	Specify that ld64 <version> is the toolchain linker for the current invocation.
 
+munreachable-traps
+Target Var(darwin_unreachable_traps) Init(1)
+When set (the default) this makes __builtin_unreachable render as a trap.
+
 ; Driver options.
 
 all_load
diff --git a/gcc/configure b/gcc/configure
index a4dcd131783..4eee550a8b4 100755
--- gcc/configure
+++ gcc/configure
@@ -740,6 +740,8 @@ ORIGINAL_NM_FOR_TARGET
 gcc_cv_nm
 ORIGINAL_LD_GOLD_FOR_TARGET
 ORIGINAL_LD_BFD_FOR_TARGET
+ORIGINAL_CLASSIC_LD_FOR_TARGET
+ORIGINAL_LLD_FOR_TARGET
 ORIGINAL_LD_FOR_TARGET
 ORIGINAL_PLUGIN_LD_FOR_TARGET
 gcc_cv_ld
@@ -3803,20 +3805,19 @@ gcc_gxx_libcxx_include_dir=
 
 # Check whether --with-gxx-libcxx-include-dir was given.
 if test "${with_gxx_libcxx_include_dir+set}" = set; then :
-  withval=$with_gxx_libcxx_include_dir; case "${withval}" in
-yes)	as_fn_error $? "bad value ${withval} given for libc++ include directory" "$LINENO" 5 ;;
-*)	gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;;
-esac
+  withval=$with_gxx_libcxx_include_dir; gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir
 fi
 
 
 # --with-gxx-libcxx-include-dir controls the enabling of the -stdlib option.
 # if --with-gxx-libcxx-include-dir is 'no' we disable the stdlib option.
+# if --with-gxx-libcxx-include-dir is 'yes' we enable the stdlib option and use
+# the default path within the installation.
 # if --with-gxx-libcxx-include-dir is unset we enable the stdlib option
-# based on the platform (to be available on platform versions where it is the
+# based on the platform (to be available on platform versions where it is the
 # default for the system tools). We also use a default path within the compiler
-# install tree.
-# Otherwise, we use the path provided and enable the stdlib option.
+# install tree.
+# Otherwise, we use the path provided and enable the stdlib option.
 # If both --with-sysroot and --with-gxx-libcxx-include-dir are passed, we
 # check to see if the latter starts with the former and, upon success, compute
 # gcc_gxx_libcxx_include_dir as relative to the sysroot.
@@ -3824,16 +3825,20 @@ gcc_gxx_libcxx_include_dir_add_sysroot=0
 gcc_enable_stdlib_opt=0
 if test x${gcc_gxx_libcxx_include_dir} != x; then
   if test x${gcc_gxx_libcxx_include_dir} = xno; then
-    # set defaults for the dir, but the option is disabled anyway.
+    # set defaults for the dir, but the option is disabled anyway.
+    gcc_gxx_libcxx_include_dir=
+  elif test x${gcc_gxx_libcxx_include_dir} = xyes; then
+    # set defaults for the dir, and enable.
     gcc_gxx_libcxx_include_dir=
+    gcc_enable_stdlib_opt=1
   else
     gcc_enable_stdlib_opt=1
   fi
 else
   case $target in
     *-darwin1[1-9]* | *-darwin2*)
-       # Default this on for Darwin versions which default to libcxx,
-       # and embed the path in the compiler install so that we get a
+       # Default this on for Darwin versions which default to libcxx,
+       # and embed the path in the compiler install so that we get a
        # self-contained toolchain.
        gcc_enable_stdlib_opt=1
        ;;
@@ -21611,7 +21616,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 21614 "configure"
+#line 21619 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -21717,7 +21722,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 21720 "configure"
+#line 21725 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -25342,6 +25347,14 @@ fi
 $as_echo "$gold_non_default" >&6; }
 
 ORIGINAL_LD_FOR_TARGET=$gcc_cv_ld
+if test x"$ld64_flag" = x"yes"; then
+ORIGINAL_LLD_FOR_TARGET=${gcc_cv_ld}64.lld
+else
+ORIGINAL_LLD_FOR_TARGET=$gcc_cv_lld
+fi
+ORIGINAL_CLASSIC_LD_FOR_TARGET=$gcc_cv_ld-classic
+
+
 
 case "$ORIGINAL_LD_FOR_TARGET" in
   ./collect-ld | ./collect-ld$build_exeext) ;;
diff --git a/gcc/configure.ac b/gcc/configure.ac
index cb743b5a875..a88d9a1295d 100644
--- gcc/configure.ac
+++ gcc/configure.ac
@@ -235,18 +235,17 @@ gcc_gxx_libcxx_include_dir=
 AC_ARG_WITH(gxx-libcxx-include-dir,
 [AS_HELP_STRING([--with-gxx-libcxx-include-dir=DIR],
                 [specifies directory to find libc++ header files])],
-[case "${withval}" in
-yes)	AC_MSG_ERROR(bad value ${withval} given for libc++ include directory) ;;
-*)	gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;;
-esac])
+[gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir])
 
 # --with-gxx-libcxx-include-dir controls the enabling of the -stdlib option.
 # if --with-gxx-libcxx-include-dir is 'no' we disable the stdlib option.
+# if --with-gxx-libcxx-include-dir is 'yes' we enable the stdlib option and use
+# the default path within the installation.
 # if --with-gxx-libcxx-include-dir is unset we enable the stdlib option
-# based on the platform (to be available on platform versions where it is the
+# based on the platform (to be available on platform versions where it is the
 # default for the system tools). We also use a default path within the compiler
-# install tree.
-# Otherwise, we use the path provided and enable the stdlib option.
+# install tree.
+# Otherwise, we use the path provided and enable the stdlib option.
 # If both --with-sysroot and --with-gxx-libcxx-include-dir are passed, we
 # check to see if the latter starts with the former and, upon success, compute
 # gcc_gxx_libcxx_include_dir as relative to the sysroot.
@@ -254,16 +253,20 @@ gcc_gxx_libcxx_include_dir_add_sysroot=0
 gcc_enable_stdlib_opt=0
 if test x${gcc_gxx_libcxx_include_dir} != x; then
   if test x${gcc_gxx_libcxx_include_dir} = xno; then
-    # set defaults for the dir, but the option is disabled anyway.
+    # set defaults for the dir, but the option is disabled anyway.
     gcc_gxx_libcxx_include_dir=
+  elif test x${gcc_gxx_libcxx_include_dir} = xyes; then
+    # set defaults for the dir, and enable.
+    gcc_gxx_libcxx_include_dir=
+    gcc_enable_stdlib_opt=1
   else
     gcc_enable_stdlib_opt=1
   fi
 else
   case $target in
     *-darwin1[[1-9]]* | *-darwin2*)
-       # Default this on for Darwin versions which default to libcxx,
-       # and embed the path in the compiler install so that we get a
+       # Default this on for Darwin versions which default to libcxx,
+       # and embed the path in the compiler install so that we get a
        # self-contained toolchain.
        gcc_enable_stdlib_opt=1
        ;;
@@ -2832,7 +2835,15 @@ fi
 AC_MSG_RESULT($gold_non_default)
 
 ORIGINAL_LD_FOR_TARGET=$gcc_cv_ld
+if test x"$ld64_flag" = x"yes"; then
+ORIGINAL_LLD_FOR_TARGET=${gcc_cv_ld}64.lld
+else
+ORIGINAL_LLD_FOR_TARGET=$gcc_cv_lld
+fi
+ORIGINAL_CLASSIC_LD_FOR_TARGET=$gcc_cv_ld-classic
 AC_SUBST(ORIGINAL_LD_FOR_TARGET)
+AC_SUBST(ORIGINAL_LLD_FOR_TARGET)
+AC_SUBST(ORIGINAL_CLASSIC_LD_FOR_TARGET)
 case "$ORIGINAL_LD_FOR_TARGET" in
   ./collect-ld | ./collect-ld$build_exeext) ;;
   *) AC_CONFIG_FILES(collect-ld:exec-tool.in, [chmod +x collect-ld]) ;;
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index b54364bebaf..6d5a7e608c6 100644
--- gcc/cp/decl2.cc
+++ gcc/cp/decl2.cc
@@ -3858,9 +3858,8 @@ get_tls_init_fn (tree var)
   if (!flag_extern_tls_init && DECL_EXTERNAL (var))
     return NULL_TREE;
 
-  /* If the variable is internal, or if we can't generate aliases,
-     call the local init function directly.  */
-  if (!TREE_PUBLIC (var) || !TARGET_SUPPORTS_ALIASES)
+  /* If the variable is internal call the local init function directly.  */
+  if (!TREE_PUBLIC (var))
     return get_local_tls_init_fn (DECL_SOURCE_LOCATION (var));
 
   tree sname = mangle_tls_init_fn (var);
@@ -4024,6 +4023,25 @@ generate_tls_wrapper (tree fn)
   expand_or_defer_fn (finish_function (/*inline_p=*/false));
 }
 
+/* A dummy init function to act as a weak placeholder for a (possibly non-
+   existent) dynamic init.  */
+static void
+generate_tls_dummy_init (tree fn)
+{
+  tree var = DECL_BEFRIENDING_CLASSES (fn);
+  tree init_fn = get_tls_init_fn (var);
+  /* If have no init fn, or it is non-weak, then we do not need to make a
+     dummy.  */
+  if (!init_fn || !lookup_attribute ("weak", DECL_ATTRIBUTES (init_fn)))
+    return;
+  start_preparsed_function (init_fn, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED);
+  tree body = begin_function_body ();
+  declare_weak (init_fn);
+  finish_return_stmt (NULL_TREE);
+  finish_function_body (body);
+  expand_or_defer_fn (finish_function (/*inline_p=*/false));
+}
+
 /* Start a global constructor or destructor function.  */
 
 static tree
@@ -4843,22 +4861,24 @@ handle_tls_init (void)
   finish_expr_stmt (cp_build_modify_expr (loc, guard, NOP_EXPR,
 					  boolean_true_node,
 					  tf_warning_or_error));
+  auto_vec<tree> direct_calls;
   for (; vars; vars = TREE_CHAIN (vars))
     {
       tree var = TREE_VALUE (vars);
       tree init = TREE_PURPOSE (vars);
       one_static_initialization_or_destruction (/*initp=*/true, var, init);
 
-      /* Output init aliases even with -fno-extern-tls-init.  */
-      if (TARGET_SUPPORTS_ALIASES && TREE_PUBLIC (var))
+      /* Output inits even with -fno-extern-tls-init.
+	We save the list here and output either an alias or a stub function
+	below.  */
+      if (TREE_PUBLIC (var))
 	{
-          tree single_init_fn = get_tls_init_fn (var);
+	  tree single_init_fn = get_tls_init_fn (var);
 	  if (single_init_fn == NULL_TREE)
 	    continue;
-	  cgraph_node *alias
-	    = cgraph_node::get_create (fn)->create_same_body_alias
-		(single_init_fn, fn);
-	  gcc_assert (alias != NULL);
+	  if (single_init_fn == fn)
+	    continue;
+	  direct_calls.safe_push (single_init_fn);
 	}
     }
 
@@ -4866,6 +4886,30 @@ handle_tls_init (void)
   finish_if_stmt (if_stmt);
   finish_function_body (body);
   expand_or_defer_fn (finish_function (/*inline_p=*/false));
+
+  /* For each TLS var that we have an init function, we either emit an alias
+     between that and the tls_init, or a stub function that just calls the
+     tls_init.  */
+  while (!direct_calls.is_empty())
+    {
+      tree single_init_fn = direct_calls.pop ();
+      if (TARGET_SUPPORTS_ALIASES)
+	{
+	  cgraph_node *alias
+	     = cgraph_node::get_create (fn)->create_same_body_alias
+		(single_init_fn, fn);
+	  gcc_assert (alias != NULL);
+	}
+      else
+	{
+	  start_preparsed_function (single_init_fn, NULL_TREE, SF_PRE_PARSED);
+	  tree body = begin_function_body ();
+	  tree r = build_call_expr (fn, 0);
+	  finish_expr_stmt (r);
+	  finish_function_body (body);
+	  expand_or_defer_fn (finish_function (/*inline_p=*/false));
+	}
+    }
 }
 
 /* We're at the end of compilation, so generate any mangling aliases that
@@ -5285,7 +5329,14 @@ c_parse_final_cleanups (void)
 	    }
 
 	  if (!DECL_INITIAL (decl) && decl_tls_wrapper_p (decl))
-	    generate_tls_wrapper (decl);
+	    {
+	      generate_tls_wrapper (decl);
+	      /* The wrapper might have a weak reference to an init, we provide
+		 a dummy function to satisfy that here.  The linker/dynamic
+		 loader will override this with the actual init, if one is
+		 required.  */
+	      generate_tls_dummy_init (decl);
+	    }
 
 	  if (!DECL_SAVED_TREE (decl))
 	    continue;
diff --git a/gcc/cp/lex.cc b/gcc/cp/lex.cc
index 1110db7f8d0..0c4f93a6787 100644
--- gcc/cp/lex.cc
+++ gcc/cp/lex.cc
@@ -267,6 +267,9 @@ init_reswords (void)
     {
       if (c_common_reswords[i].disable & D_CONLY)
 	continue;
+      if (!flag_allow_extra_keywords
+	  && c_common_reswords[i].disable & D_EXT_C_IN_CXX)
+	continue;
       id = get_identifier (c_common_reswords[i].word);
       C_SET_RID_CODE (id, c_common_reswords[i].rid);
       ridpointers [(int) c_common_reswords[i].rid] = id;
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 4a2c1f272a3..d917d01a50b 100644
--- gcc/cp/parser.cc
+++ gcc/cp/parser.cc
@@ -705,6 +705,91 @@ cp_lexer_handle_early_pragma (cp_lexer *lexer)
 static cp_parser *cp_parser_new (cp_lexer *);
 static GTY (()) cp_parser *the_parser;
 
+/* Context-sensitive parse-checking for clang-style attributes.  */
+
+enum clang_attr_state {
+  CA_NONE = 0,
+  CA_ATTR,
+  CA_BR1, CA_BR2,
+  CA_LIST,
+  CA_LIST_ARGS,
+  CA_IS_CA,
+  CA_CA_ARGS,
+  CA_LIST_CONT
+};
+
+/* State machine tracking context of attribute lexing.  */
+
+static enum clang_attr_state
+cp_lexer_attribute_state (cp_token& token, enum clang_attr_state attr_state)
+{
+  /* Implement a context-sensitive parser for clang attributes.
+     We detect __attribute__((clang_style_attribute (ARGS))) and lex the
+     args ARGS with the following differences from GNU attributes:
+	(a) number-like values are lexed as strings [this allows lexing XX.YY.ZZ
+	   version numbers].
+	(b) we concatenate strings, since clang attributes allow this too.  */
+  switch (attr_state)
+    {
+    case CA_NONE:
+      if (token.type == CPP_KEYWORD
+	  && token.keyword == RID_ATTRIBUTE)
+	attr_state = CA_ATTR;
+      break;
+    case CA_ATTR:
+      if (token.type == CPP_OPEN_PAREN)
+	attr_state = CA_BR1;
+      else
+	attr_state = CA_NONE;
+      break;
+    case CA_BR1:
+      if (token.type == CPP_OPEN_PAREN)
+	attr_state = CA_BR2;
+      else
+	attr_state = CA_NONE;
+      break;
+    case CA_BR2:
+      if (token.type == CPP_NAME)
+	{
+	  tree identifier = (token.type == CPP_KEYWORD)
+	    /* For keywords, use the canonical spelling, not the
+	       parsed identifier.  */
+	    ? ridpointers[(int) token.keyword]
+	    : token.u.value;
+	  identifier = canonicalize_attr_name (identifier);
+	  if (attribute_clang_form_p (identifier))
+	    attr_state = CA_IS_CA;
+	  else
+	    attr_state = CA_LIST;
+	}
+      else
+	attr_state = CA_NONE;
+      break;
+    case CA_IS_CA:
+    case CA_LIST:
+      if (token.type == CPP_COMMA)
+	attr_state = CA_BR2; /* Back to the list outer.  */
+      else if (token.type == CPP_OPEN_PAREN)
+	attr_state = attr_state == CA_IS_CA ? CA_CA_ARGS
+					    : CA_LIST_ARGS;
+      else
+	attr_state = CA_NONE;
+      break;
+    case CA_CA_ARGS: /* We will special-case args in this state.  */
+    case CA_LIST_ARGS:
+      if (token.type == CPP_CLOSE_PAREN)
+	attr_state = CA_LIST_CONT;
+      break;
+    case CA_LIST_CONT:
+      if (token.type == CPP_COMMA)
+	attr_state = CA_BR2; /* Back to the list outer.  */
+      else
+	attr_state = CA_NONE;
+      break;
+    }
+  return attr_state;
+}
+
 /* Create a new main C++ lexer, the lexer that gets tokens from the
    preprocessor, and also create the main parser.  */
 
@@ -721,6 +806,8 @@ cp_lexer_new_main (void)
   c_common_no_more_pch ();
 
   cp_lexer *lexer = cp_lexer_alloc ();
+  enum clang_attr_state attr_state = CA_NONE;
+
   /* Put the first token in the buffer.  */
   cp_token *tok = lexer->buffer->quick_push (token);
 
@@ -744,8 +831,14 @@ cp_lexer_new_main (void)
       if (tok->type == CPP_PRAGMA_EOL)
 	cp_lexer_handle_early_pragma (lexer);
 
+      attr_state = cp_lexer_attribute_state (*tok, attr_state);
       tok = vec_safe_push (lexer->buffer, cp_token ());
-      cp_lexer_get_preprocessor_token (C_LEX_STRING_NO_JOIN, tok);
+      unsigned int flags = C_LEX_STRING_NO_JOIN;
+      /* If we are processing clang-style attribute args, lex numbers as
+         potential version strings; NN .. NN.MM .. NN.MM.OO */
+      if (attr_state == CA_CA_ARGS)
+	flags |= C_LEX_NUMBER_AS_STRING;
+      cp_lexer_get_preprocessor_token (flags, tok);
     }
 
   lexer->next_token = lexer->buffer->address ();
@@ -962,7 +1055,7 @@ cp_lexer_get_preprocessor_token (unsigned flags, cp_token *token)
 {
   static int is_extern_c = 0;
 
-   /* Get a new token from the preprocessor.  */
+   /* Get a new token from the preprocessor. */
   token->type
     = c_lex_with_flags (&token->u.value, &token->location, &token->flags,
 			flags);
@@ -23390,9 +23483,16 @@ cp_parser_init_declarator (cp_parser* parser,
 		      "an %<asm%> specification is not allowed "
 		      "on a function-definition");
 	  if (attributes)
-	    error_at (attributes_start_token->location,
-		      "attributes are not allowed "
-		      "on a function-definition");
+	    {
+	      /* When we are allowing attributes in this position, then add
+		 them to the prefix ones.  */
+	      if (flag_allow_ext_attr_placement)
+		prefix_attributes = chainon (prefix_attributes, attributes);
+	      else
+		error_at (attributes_start_token->location,
+			  "attributes are not allowed "
+			  "on a function-definition");
+	    }
 	  /* This is a function-definition.  */
 	  *function_definition_p = true;
 
@@ -29781,6 +29881,91 @@ cp_parser_gnu_attributes_opt (cp_parser* parser)
   return attributes;
 }
 
+/* Parse the arguments list for a clang attribute.   */
+static tree
+cp_parser_clang_attribute (cp_parser *parser, tree/*attr_id*/)
+{
+  /* Each entry can be :
+     identifier
+     identifier=N.MM.Z
+     identifier="string"
+     followed by ',' or ) for the last entry*/
+
+  matching_parens parens;
+  if (!parens.require_open (parser))
+    return NULL;
+
+  bool save_translate_strings_p = parser->translate_strings_p;
+  parser->translate_strings_p = false;
+  tree attr_args = NULL_TREE;
+  cp_token *token;
+  do
+    {
+      tree name = NULL_TREE;
+      tree value = NULL_TREE;
+
+      token = cp_lexer_peek_token (parser->lexer);
+      if (token->type == CPP_NAME)
+	name = token->u.value;
+      else if (token->type == CPP_KEYWORD)
+	name = ridpointers[(int) token->keyword];
+      else if (token->flags & NAMED_OP)
+	name = get_identifier (cpp_type2name (token->type, token->flags));
+      else
+	{
+	  /* FIXME: context-sensitive for that attrib.  */
+	  error_at (token->location, "expected an attribute keyword");
+	  cp_parser_skip_to_closing_parenthesis (parser,
+						 /*recovering=*/true,
+						 /*or_comma=*/false,
+						 /*consume_paren=*/false);
+	  attr_args = error_mark_node;
+	  break;
+	}
+      cp_lexer_consume_token (parser->lexer);
+
+      if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+	{
+	  cp_lexer_consume_token (parser->lexer); /* eat the '=' */
+	  if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
+	      && cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
+	    {
+	      token = cp_lexer_peek_token (parser->lexer);
+	      if (token->type == CPP_STRING)
+		value = cp_parser_string_literal (parser, /*translate=*/false,
+					    /*wide_ok=*/false);
+	      else
+		{
+		  value = token->u.value;
+		  cp_lexer_consume_token (parser->lexer);
+		}
+	    }
+	  /* else value is missing.  */
+	}
+      else if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
+	       && cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
+	{
+	  error_at (token->location, "expected %<,%>, %<=%> or %<)%>");
+	  cp_parser_skip_to_closing_parenthesis (parser,
+						 /*recovering=*/true,
+						 /*or_comma=*/false,
+						 /*consume_paren=*/false);
+	  attr_args = error_mark_node;
+	  break;
+	}
+    if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+      cp_lexer_consume_token (parser->lexer);
+    tree t = tree_cons (value, name, NULL_TREE);
+    attr_args = chainon (attr_args, t);
+  } while (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN));
+
+  parser->translate_strings_p = save_translate_strings_p;
+  if (!parens.require_close (parser))
+    return error_mark_node;
+
+  return attr_args;
+}
+
 /* Parse a GNU attribute-list.
 
    attribute-list:
@@ -29840,9 +30025,12 @@ cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */)
 
 	  /* Peek at the next token.  */
 	  token = cp_lexer_peek_token (parser->lexer);
-	  /* If it's an `(', then parse the attribute arguments.  */
-	  if (token->type == CPP_OPEN_PAREN)
+	  if (token->type == CPP_OPEN_PAREN
+	      && attribute_clang_form_p (identifier))
+	    arguments = cp_parser_clang_attribute (parser, identifier);
+	  else if (token->type == CPP_OPEN_PAREN)
 	    {
+	      /* If it's an `(', then parse the attribute arguments.  */
 	      vec<tree, va_gc> *vec;
 	      int attr_flag = (attribute_takes_identifier_p (identifier)
 			       ? id_attr : normal_attr);
@@ -29859,12 +30047,12 @@ cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */)
 		  arguments = build_tree_list_vec (vec);
 		  release_tree_vector (vec);
 		}
-	      /* Save the arguments away.  */
-	      TREE_VALUE (attribute) = arguments;
 	    }
 
 	  if (arguments != error_mark_node)
 	    {
+	      /* Save the arguments away.  */
+	      TREE_VALUE (attribute) = arguments;
 	      /* Add this attribute to the list.  */
 	      TREE_CHAIN (attribute) = attribute_list;
 	      attribute_list = attribute;
diff --git a/gcc/cumulative-args.h b/gcc/cumulative-args.h
new file mode 100644
index 00000000000..b60928e37f9
--- /dev/null
+++ gcc/cumulative-args.h
@@ -0,0 +1,20 @@
+#ifndef GCC_CUMULATIVE_ARGS_H
+#define GCC_CUMULATIVE_ARGS_H
+
+#if CHECKING_P
+
+struct cumulative_args_t { void *magic; void *p; };
+
+#else /* !CHECKING_P */
+
+/* When using a GCC build compiler, we could use
+   __attribute__((transparent_union)) to get cumulative_args_t function
+   arguments passed like scalars where the ABI would mandate a less
+   efficient way of argument passing otherwise.  However, that would come
+   at the cost of less type-safe !CHECKING_P compilation.  */
+
+union cumulative_args_t { void *p; };
+
+#endif /* !CHECKING_P */
+
+#endif /* GCC_CUMULATIVE_ARGS_H */
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 64728fead51..1e93f92a4a3 100644
--- gcc/doc/invoke.texi
+++ gcc/doc/invoke.texi
@@ -732,7 +732,7 @@ Objective-C and Objective-C++ Dialects}.
 -freg-struct-return  -fshort-enums  -fshort-wchar
 -fverbose-asm  -fpack-struct[=@var{n}]
 -fleading-underscore  -ftls-model=@var{model}
--fstack-reuse=@var{reuse_level}
+-fstack-reuse=@var{reuse_level} -fstack-use-cumulative-args
 -ftrampolines -ftrampoline-impl=@r{[}stack@r{|}heap@r{]}
 -ftrapv  -fwrapv
 -fvisibility=@r{[}default@r{|}internal@r{|}hidden@r{|}protected@r{]}
@@ -954,7 +954,7 @@ Objective-C and Objective-C++ Dialects}.
 -twolevel_namespace  -umbrella  -undefined
 -unexported_symbols_list  -weak_reference_mismatches
 -whatsloaded  -F  -gused  -gfull  -mmacosx-version-min=@var{version}
--mkernel  -mone-byte-bool}
+-mkernel  -mone-byte-bool -munreachable-traps}
 
 @emph{DEC Alpha Options}
 @gccoptlist{-mno-fp-regs  -msoft-float
@@ -19134,6 +19134,17 @@ the behavior of older compilers in which temporaries' stack space is
 not reused, the aggressive stack reuse can lead to runtime errors. This
 option is used to control the temporary stack reuse optimization.
 
+@opindex fstack_use_cumulative_args
+@item -fstack-use-cumulative-args
+This option instructs the compiler to use the
+@code{cumulative_args_t}-based stack layout target hooks,
+@code{TARGET_FUNCTION_ARG_BOUNDARY_CA} and
+@code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY_CA}. If a given target does
+not define these hooks, the default behaviour is to fallback to using
+the standard non-@code{_CA} variants instead. Certain targets (such as
+AArch64 Darwin) require using the more advanced @code{_CA}-based
+hooks: For these targets this option should be enabled by default.
+
 @opindex ftrapv
 @item -ftrapv
 This option generates traps for signed overflow on addition, subtraction,
@@ -25239,6 +25250,11 @@ without that switch.  Using this switch may require recompiling all
 other modules in a program, including system libraries.  Use this
 switch to conform to a non-default data model.
 
+@opindex munreachable-traps
+@item -munreachable-traps
+Causes @code{__builtin_unreachable} to be rendered as a trap.  This is the
+default for all Darwin architectures.
+
 @opindex mfix-and-continue
 @opindex ffix-and-continue
 @opindex findirect-data
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index cd50078227d..00df8aeb6b4 100644
--- gcc/doc/tm.texi
+++ gcc/doc/tm.texi
@@ -1066,6 +1066,10 @@ also define the hook to @code{default_promote_function_mode_always_promote}
 if you would like to apply the same rules given by @code{PROMOTE_MODE}.
 @end deftypefn
 
+@deftypefn {Target Hook} machine_mode TARGET_PROMOTE_FUNCTION_MODE_CA (cumulative_args_t, @var{function_arg_info}, @var{const_tree}, int *@var{}, @var{int})
+Like @code{promote_function_mode}, but takes a cumulative_args pointer   and a current arg to supply the input.
+@end deftypefn
+
 @defmac PARM_BOUNDARY
 Normal alignment required for function parameters on the stack, in
 bits.  All stack parameters receive at least this much alignment
@@ -4471,6 +4475,16 @@ with the specified mode and type.  The default hook returns
 @code{PARM_BOUNDARY} for all arguments.
 @end deftypefn
 
+@deftypefn {Target Hook} {unsigned int} TARGET_FUNCTION_ARG_BOUNDARY_CA (machine_mode @var{mode}, const_tree @var{type}, cumulative_args_t @var{ca})
+This is the @code{cumulative_args_t}-based version of
+@code{TARGET_FUNCTION_ARG_BOUNDARY}. Define this hook if you need more
+fine-grained control over argument alignment, e.g. depending on whether
+it is a named argument or not, or any other criteria that you choose to
+place in the @var{ca} structure.
+
+The default hook will call @code{TARGET_FUNCTION_ARG_BOUNDARY}.
+@end deftypefn
+
 @deftypefn {Target Hook} {unsigned int} TARGET_FUNCTION_ARG_ROUND_BOUNDARY (machine_mode @var{mode}, const_tree @var{type})
 Normally, the size of an argument is rounded up to @code{PARM_BOUNDARY},
 which is the default value for this hook.  You can define this hook to
@@ -4478,6 +4492,16 @@ return a different value if an argument size must be rounded to a larger
 value.
 @end deftypefn
 
+@deftypefn {Target Hook} {unsigned int} TARGET_FUNCTION_ARG_ROUND_BOUNDARY_CA (machine_mode @var{mode}, const_tree @var{type}, cumulative_args_t @var{ca})
+This is the @code{cumulative_args_t}-based version of
+@code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY}. Define this hook if you need more
+fine-grained control over argument size rounding, e.g. depending on whether
+it is a named argument or not, or any other criteria that you choose to
+place in the @var{ca} structure.
+
+The default hook will call @code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY}.
+@end deftypefn
+
 @defmac FUNCTION_ARG_REGNO_P (@var{regno})
 A C expression that is nonzero if @var{regno} is the number of a hard
 register in which function arguments are sometimes passed.  This does
@@ -12709,6 +12733,11 @@ This target hook can be used to generate a target-specific code
 If selftests are enabled, run any selftests for this target.
 @end deftypefn
 
+@deftypefn {Target Hook} bool TARGET_UNREACHABLE_SHOULD_TRAP (void)
+This hook should return @code{true} if the target wants   @code{__builtin_unreachable} to expand to a trap or @code{abort ()}.
+  The default value is false.
+@end deftypefn
+
 @deftypefn {Target Hook} bool TARGET_MEMTAG_CAN_TAG_ADDRESSES ()
 True if the backend architecture naturally supports ignoring some region
 of pointers.  This feature means that @option{-fsanitize=hwaddress} can
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 058bd56487a..0ded0f992d4 100644
--- gcc/doc/tm.texi.in
+++ gcc/doc/tm.texi.in
@@ -949,6 +949,8 @@ applied.
 
 @hook TARGET_PROMOTE_FUNCTION_MODE
 
+@hook TARGET_PROMOTE_FUNCTION_MODE_CA
+
 @defmac PARM_BOUNDARY
 Normal alignment required for function parameters on the stack, in
 bits.  All stack parameters receive at least this much alignment
@@ -3441,8 +3443,12 @@ required.
 
 @hook TARGET_FUNCTION_ARG_BOUNDARY
 
+@hook TARGET_FUNCTION_ARG_BOUNDARY_CA
+
 @hook TARGET_FUNCTION_ARG_ROUND_BOUNDARY
 
+@hook TARGET_FUNCTION_ARG_ROUND_BOUNDARY_CA
+
 @defmac FUNCTION_ARG_REGNO_P (@var{regno})
 A C expression that is nonzero if @var{regno} is the number of a hard
 register in which function arguments are sometimes passed.  This does
@@ -8099,6 +8105,8 @@ maintainer is familiar with.
 
 @hook TARGET_RUN_TARGET_SELFTESTS
 
+@hook TARGET_UNREACHABLE_SHOULD_TRAP
+
 @hook TARGET_MEMTAG_CAN_TAG_ADDRESSES
 
 @hook TARGET_MEMTAG_TAG_SIZE
diff --git a/gcc/exec-tool.in b/gcc/exec-tool.in
index 7d152e083a7..ec1a144e415 100644
--- gcc/exec-tool.in
+++ gcc/exec-tool.in
@@ -23,6 +23,8 @@ ORIGINAL_AS_FOR_TARGET="@ORIGINAL_AS_FOR_TARGET@"
 ORIGINAL_LD_FOR_TARGET="@ORIGINAL_LD_FOR_TARGET@"
 ORIGINAL_LD_BFD_FOR_TARGET="@ORIGINAL_LD_BFD_FOR_TARGET@"
 ORIGINAL_LD_GOLD_FOR_TARGET="@ORIGINAL_LD_GOLD_FOR_TARGET@"
+ORIGINAL_LLD_FOR_TARGET="@ORIGINAL_LLD_FOR_TARGET@"
+ORIGINAL_CLASSIC_LD_FOR_TARGET="@ORIGINAL_CLASSIC_LD_FOR_TARGET@"
 ORIGINAL_PLUGIN_LD_FOR_TARGET="@ORIGINAL_PLUGIN_LD_FOR_TARGET@"
 ORIGINAL_NM_FOR_TARGET="@ORIGINAL_NM_FOR_TARGET@"
 ORIGINAL_DSYMUTIL_FOR_TARGET="@ORIGINAL_DSYMUTIL_FOR_TARGET@"
@@ -39,24 +41,41 @@ case "$invoked" in
     dir=gas
     ;;
   collect-ld)
-    # Check -fuse-ld=bfd and -fuse-ld=gold
-    case " $* " in
-      *\ -fuse-ld=bfd\ *)
-	original=$ORIGINAL_LD_BFD_FOR_TARGET
-	;;
-      *\ -fuse-ld=gold\ *)
-	original=$ORIGINAL_LD_GOLD_FOR_TARGET
-	;;
-      *)
-	# when using a linker plugin, gcc will always pass '-plugin' as the
-	# first or second option to the linker.
-	if test x"$1" = "x-plugin" || test x"$2" = "x-plugin"; then
-	  original=$ORIGINAL_PLUGIN_LD_FOR_TARGET
-	else
-	  original=$ORIGINAL_LD_FOR_TARGET
-	fi
-	;;
-    esac
+    # when using a linker plugin, gcc will always pass '-plugin' as the
+    # first or second option to the linker.
+    if test x"$1" = "x-plugin" || test x"$2" = "x-plugin"; then
+      original=$ORIGINAL_PLUGIN_LD_FOR_TARGET
+    else
+      original=$ORIGINAL_LD_FOR_TARGET
+    fi
+    # Check -fuse-ld=bfd, -fuse-ld=gold and -fuse-ld=classic
+    # Remove -fuse-ld=classic from the command line
+    for arg do
+        # temporarily, remove the arg.
+        shift
+        case $arg in
+          -fuse-ld=bfd)
+            original=$ORIGINAL_LD_BFD_FOR_TARGET
+            ;;
+          -fuse-ld=gold)
+            original=$ORIGINAL_LD_GOLD_FOR_TARGET
+            ;;
+          -fuse-ld=lld)
+            original=$ORIGINAL_LLD_FOR_TARGET
+            # We want to remove this from the command line; by the slightly
+            # obtuse mechanism of not putting it back.
+            continue
+            ;;
+          -fuse-ld=classic)
+            original=$ORIGINAL_CLASSIC_LD_FOR_TARGET
+            # As for lld.
+            continue
+            ;;
+          *) ;;
+        esac
+        # if we want to keep the arg, put it back.
+        set -- "$@" "$arg"
+    done
     prog=ld-new$exeext
     if test "$original" = ../gold/ld-new$exeext; then
       dir=gold
diff --git a/gcc/explow.cc b/gcc/explow.cc
index 2a91cf76ea6..d6981888b15 100644
--- gcc/explow.cc
+++ gcc/explow.cc
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "except.h"
 #include "dojump.h"
+#include "calls.h"
 #include "explow.h"
 #include "expr.h"
 #include "stringpool.h"
@@ -850,6 +851,16 @@ promote_function_mode (const_tree type, machine_mode mode, int *punsignedp,
       return mode;
     }
 }
+
+machine_mode
+promote_function_mode (cumulative_args_t args_so_far, function_arg_info arg,
+		       const_tree funtype, int *punsignedp , int for_return)
+{
+  return targetm.calls.promote_function_mode_ca (args_so_far, arg, funtype,
+						 punsignedp, for_return);
+//  return promote_function_mode (arg.type, arg.mode, punsignedp, funtype, for_return);
+}
+
 /* Return the mode to use to store a scalar of TYPE and MODE.
    PUNSIGNEDP points to the signedness of the type and may be adjusted
    to show what signedness to use on extension operations.  */
diff --git a/gcc/explow.h b/gcc/explow.h
index dd654649b06..da498430a21 100644
--- gcc/explow.h
+++ gcc/explow.h
@@ -20,6 +20,8 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_EXPLOW_H
 #define GCC_EXPLOW_H
 
+#include "calls.h" /* for cummulative args stuff.  */
+
 /* Return a memory reference like MEMREF, but which is known to have a
    valid address.  */
 extern rtx validize_mem (rtx);
@@ -50,8 +52,13 @@ extern rtx force_not_mem (rtx);
 
 /* Return mode and signedness to use when an argument or result in the
    given mode is promoted.  */
-extern machine_mode promote_function_mode (const_tree, machine_mode, int *,
-					        const_tree, int);
+machine_mode promote_function_mode (const_tree, machine_mode, int *,
+				    const_tree, int);
+
+/* Return mode and signedness to use when an argument or result in the
+   given mode is promoted.  */
+machine_mode promote_function_mode (cumulative_args_t, function_arg_info,
+				    const_tree, int *, int);
 
 /* Return mode and signedness to use when an object in the given mode
    is promoted.  */
diff --git a/gcc/function.cc b/gcc/function.cc
index 05aa52d8f6a..3e893b41a0f 100644
--- gcc/function.cc
+++ gcc/function.cc
@@ -58,8 +58,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "varasm.h"
 #include "except.h"
 #include "dojump.h"
-#include "explow.h"
 #include "calls.h"
+#include "explow.h"
 #include "expr.h"
 #include "optabs-tree.h"
 #include "output.h"
@@ -2449,7 +2449,10 @@ assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm,
   else if (DECL_CHAIN (parm))
     data->arg.named = 1;  /* Not the last non-variadic parm. */
   else if (targetm.calls.strict_argument_naming (all->args_so_far))
-    data->arg.named = 1;  /* Only variadic ones are unnamed.  */
+    {
+      data->arg.named = 1;  /* Only variadic ones are unnamed.  */
+      data->arg.last_named = 1;
+    }
   else
     data->arg.named = 0;  /* Treat as variadic.  */
 
@@ -2491,9 +2494,12 @@ assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm,
 
   /* Find mode as it is passed by the ABI.  */
   unsignedp = TYPE_UNSIGNED (data->arg.type);
-  data->arg.mode
-    = promote_function_mode (data->arg.type, data->arg.mode, &unsignedp,
-			     TREE_TYPE (current_function_decl), 0);
+//  data->arg.mode
+//    = promote_function_mode (data->arg.type, data->arg.mode, &unsignedp,
+//			     TREE_TYPE (current_function_decl), 0);
+  data->arg.mode = promote_function_mode (all->args_so_far, data->arg,
+					  TREE_TYPE (current_function_decl),
+					  &unsignedp, 0);
 }
 
 /* A subroutine of assign_parms.  Invoke setup_incoming_varargs.  */
@@ -2506,6 +2512,7 @@ assign_parms_setup_varargs (struct assign_parm_data_all *all,
 
   function_arg_info last_named_arg = data->arg;
   last_named_arg.named = true;
+  last_named_arg.last_named = true;
   targetm.calls.setup_incoming_varargs (all->args_so_far, last_named_arg,
 					&varargs_pretend_bytes, no_rtl);
 
@@ -2614,7 +2621,9 @@ assign_parm_find_entry_rtl (struct assign_parm_data_all *all,
 
   locate_and_pad_parm (data->arg.mode, data->arg.type, in_regs,
 		       all->reg_parm_stack_space,
-		       entry_parm ? data->partial : 0, current_function_decl,
+		       entry_parm ? data->partial : 0,
+		       all->args_so_far,
+		       current_function_decl,
 		       &all->stack_args_size, &data->locate);
 
   /* Update parm_stack_boundary if this parameter is passed in the
@@ -3923,7 +3932,8 @@ gimplify_parameters (gimple_seq *cleanup)
       if (data.arg.pass_by_reference)
 	{
 	  tree type = TREE_TYPE (data.arg.type);
-	  function_arg_info orig_arg (type, data.arg.named);
+	  function_arg_info orig_arg (type, data.arg.named,
+				      data.arg.last_named);
 	  if (reference_callee_copied (&all.args_so_far_v, orig_arg))
 	    {
 	      tree local, t;
@@ -4026,6 +4036,7 @@ gimplify_parameters (gimple_seq *cleanup)
 void
 locate_and_pad_parm (machine_mode passed_mode, tree type, int in_regs,
 		     int reg_parm_stack_space, int partial,
+		     cumulative_args_t ca,
 		     tree fndecl ATTRIBUTE_UNUSED,
 		     struct args_size *initial_offset_ptr,
 		     struct locate_and_pad_arg_data *locate)
@@ -4063,9 +4074,23 @@ locate_and_pad_parm (machine_mode passed_mode, tree type, int in_regs,
 	      ? arg_size_in_bytes (type)
 	      : size_int (GET_MODE_SIZE (passed_mode)));
   where_pad = targetm.calls.function_arg_padding (passed_mode, type);
-  boundary = targetm.calls.function_arg_boundary (passed_mode, type);
-  round_boundary = targetm.calls.function_arg_round_boundary (passed_mode,
-							      type);
+
+  if (flag_stack_use_cumulative_args)
+    {
+      boundary = targetm.calls.function_arg_boundary_ca (passed_mode,
+							 type,
+							 ca);
+      round_boundary = targetm.calls.function_arg_round_boundary_ca
+	(passed_mode, type, ca);
+    }
+  else
+    {
+      boundary = targetm.calls.function_arg_boundary (passed_mode,
+						      type);
+      round_boundary = targetm.calls.function_arg_round_boundary
+	(passed_mode, type);
+    }
+
   locate->where_pad = where_pad;
 
   /* Alignment can't exceed MAX_SUPPORTED_STACK_ALIGNMENT.  */
diff --git a/gcc/function.h b/gcc/function.h
index c0ba6cc1531..520fde7694c 100644
--- gcc/function.h
+++ gcc/function.h
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_FUNCTION_H
 #define GCC_FUNCTION_H
 
+#include "cumulative-args.h"
 
 /* Stack of pending (incomplete) sequences saved by `start_sequence'.
    Each element describes one pending sequence.
@@ -680,6 +681,7 @@ extern bool aggregate_value_p (const_tree, const_tree);
 extern bool use_register_for_decl (const_tree);
 extern gimple_seq gimplify_parameters (gimple_seq *);
 extern void locate_and_pad_parm (machine_mode, tree, int, int, int,
+				 cumulative_args_t,
 				 tree, struct args_size *,
 				 struct locate_and_pad_arg_data *);
 extern void generate_setjmp_warnings (void);
diff --git a/gcc/ginclude/stddef.h b/gcc/ginclude/stddef.h
index 244397b26c0..931cc5f531f 100644
--- gcc/ginclude/stddef.h
+++ gcc/ginclude/stddef.h
@@ -443,9 +443,8 @@ typedef struct {
   /* _Float128 is defined as a basic type, so max_align_t must be
      sufficiently aligned for it.  This code must work in C++, so we
      use __float128 here; that is only available on some
-     architectures, but only on i386 is extra alignment needed for
-     __float128.  */
-#ifdef __i386__
+     architectures.  */
+#if defined(__i386__) || (__APPLE__ && __aarch64__)
   __float128 __max_align_f128 __attribute__((__aligned__(__alignof(__float128))));
 #endif
 } max_align_t;
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 74e847b2dec..58d282046e8 100644
--- gcc/jit/libgccjit.h
+++ gcc/jit/libgccjit.h
@@ -21,6 +21,9 @@ along with GCC; see the file COPYING3.  If not see
 #define LIBGCCJIT_H
 
 #include <stdio.h>
+#ifdef __APPLE__
+# include <sys/types.h>  /* For ssize_t.  */
+#endif
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/gcc/opts.cc b/gcc/opts.cc
index 3333600e0ea..8355cc4b1de 100644
--- gcc/opts.cc
+++ gcc/opts.cc
@@ -3289,6 +3289,7 @@ common_handle_option (struct gcc_options *opts,
       break;
 
     case OPT_fuse_ld_bfd:
+    case OPT_fuse_ld_classic:
     case OPT_fuse_ld_gold:
     case OPT_fuse_ld_lld:
     case OPT_fuse_ld_mold:
diff --git a/gcc/target.def b/gcc/target.def
index c27df8095be..20561fc8060 100644
--- gcc/target.def
+++ gcc/target.def
@@ -4680,6 +4680,13 @@ if you would like to apply the same rules given by @code{PROMOTE_MODE}.",
 		     const_tree funtype, int for_return),
  default_promote_function_mode)
 
+DEFHOOK
+(promote_function_mode_ca,
+ "Like @code{promote_function_mode}, but takes a cumulative_args pointer \
+  and a current arg to supply the input.",
+ machine_mode, (cumulative_args_t, function_arg_info, const_tree, int *, int),
+ default_promote_function_mode_ca)
+
 DEFHOOK
 (promote_prototypes,
  "This target hook returns @code{true} if an argument declared in a\n\
@@ -5133,6 +5140,18 @@ with the specified mode and type.  The default hook returns\n\
  unsigned int, (machine_mode mode, const_tree type),
  default_function_arg_boundary)
 
+DEFHOOK
+(function_arg_boundary_ca,
+ "This is the @code{cumulative_args_t}-based version of\n\
+@code{TARGET_FUNCTION_ARG_BOUNDARY}. Define this hook if you need more\n\
+fine-grained control over argument alignment, e.g. depending on whether\n\
+it is a named argument or not, or any other criteria that you choose to\n\
+place in the @var{ca} structure.\n\
+\n\
+The default hook will call @code{TARGET_FUNCTION_ARG_BOUNDARY}.",
+ unsigned int, (machine_mode mode, const_tree type, cumulative_args_t ca),
+ default_function_arg_boundary_ca)
+
 DEFHOOK
 (function_arg_round_boundary,
  "Normally, the size of an argument is rounded up to @code{PARM_BOUNDARY},\n\
@@ -5142,6 +5161,18 @@ value.",
  unsigned int, (machine_mode mode, const_tree type),
  default_function_arg_round_boundary)
 
+DEFHOOK
+(function_arg_round_boundary_ca,
+ "This is the @code{cumulative_args_t}-based version of\n\
+@code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY}. Define this hook if you need more\n\
+fine-grained control over argument size rounding, e.g. depending on whether\n\
+it is a named argument or not, or any other criteria that you choose to\n\
+place in the @var{ca} structure.\n\
+\n\
+The default hook will call @code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY}.",
+ unsigned int, (machine_mode mode, const_tree type, cumulative_args_t ca),
+ default_function_arg_round_boundary_ca)
+
 /* Return the diagnostic message string if function without a prototype
    is not allowed for this 'val' argument; NULL otherwise. */
 DEFHOOK
@@ -7389,6 +7420,16 @@ DEFHOOKPOD
 libatomic.  The default value is false.",
  bool, false)
 
+/* This value represents whether __builtin_unreachable should be expanded
+   as a trap instruction (or an abort() if the trap is not available).  */
+DEFHOOK
+(unreachable_should_trap,
+ "This hook should return @code{true} if the target wants \
+  @code{__builtin_unreachable} to expand to a trap or @code{abort ()}.\n\
+  The default value is false.",
+ bool, (void),
+ hook_bool_void_false)
+
 /* Close the 'struct gcc_target' definition.  */
 HOOK_VECTOR_END (C90_EMPTY_HACK)
 
diff --git a/gcc/target.h b/gcc/target.h
index c1f99b97b86..b51630a9782 100644
--- gcc/target.h
+++ gcc/target.h
@@ -51,22 +51,8 @@
 #include "insn-codes.h"
 #include "tm.h"
 #include "hard-reg-set.h"
-
-#if CHECKING_P
-
-struct cumulative_args_t { void *magic; void *p; };
-
-#else /* !CHECKING_P */
-
-/* When using a GCC build compiler, we could use
-   __attribute__((transparent_union)) to get cumulative_args_t function
-   arguments passed like scalars where the ABI would mandate a less
-   efficient way of argument passing otherwise.  However, that would come
-   at the cost of less type-safe !CHECKING_P compilation.  */
-
-union cumulative_args_t { void *p; };
-
-#endif /* !CHECKING_P */
+#include "tree-core.h"
+#include "cumulative-args.h"
 
 /* Target properties of _BitInt(N) type.  _BitInt(N) is to be represented
    as series of abi_limb_mode CEIL (N, GET_MODE_PRECISION (abi_limb_mode))
diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
index fb339bf75dd..a529998f618 100644
--- gcc/targhooks.cc
+++ gcc/targhooks.cc
@@ -161,6 +161,15 @@ default_promote_function_mode_always_promote (const_tree type,
   return promote_mode (type, mode, punsignedp);
 }
 
+machine_mode
+default_promote_function_mode_ca (cumulative_args_t, function_arg_info arg,
+				  const_tree funtype, int *punsignedp,
+				  int for_return)
+{
+  return promote_function_mode (arg.type, arg.mode, punsignedp,
+				funtype, for_return);
+}
+
 machine_mode
 default_cc_modes_compatible (machine_mode m1, machine_mode m2)
 {
@@ -876,6 +885,14 @@ default_function_arg_boundary (machine_mode mode ATTRIBUTE_UNUSED,
   return PARM_BOUNDARY;
 }
 
+unsigned int
+default_function_arg_boundary_ca (machine_mode mode ATTRIBUTE_UNUSED,
+				  const_tree type ATTRIBUTE_UNUSED,
+				  cumulative_args_t ca ATTRIBUTE_UNUSED)
+{
+  return default_function_arg_boundary (mode, type);
+}
+
 unsigned int
 default_function_arg_round_boundary (machine_mode mode ATTRIBUTE_UNUSED,
 				     const_tree type ATTRIBUTE_UNUSED)
@@ -883,6 +900,14 @@ default_function_arg_round_boundary (machine_mode mode ATTRIBUTE_UNUSED,
   return PARM_BOUNDARY;
 }
 
+unsigned int
+default_function_arg_round_boundary_ca (machine_mode mode ATTRIBUTE_UNUSED,
+					const_tree type ATTRIBUTE_UNUSED,
+					cumulative_args_t ca ATTRIBUTE_UNUSED)
+{
+  return default_function_arg_round_boundary (mode, type);
+}
+
 void
 hook_void_bitmap (bitmap regs ATTRIBUTE_UNUSED)
 {
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 85f3817c176..392fd0d315e 100644
--- gcc/targhooks.h
+++ gcc/targhooks.h
@@ -34,6 +34,9 @@ extern machine_mode default_promote_function_mode (const_tree, machine_mode,
 extern machine_mode default_promote_function_mode_always_promote
 			(const_tree, machine_mode, int *, const_tree, int);
 
+extern machine_mode default_promote_function_mode_ca
+  (cumulative_args_t, function_arg_info, const_tree, int *, int);
+
 extern machine_mode default_cc_modes_compatible (machine_mode,
 						      machine_mode);
 
@@ -160,6 +163,12 @@ extern unsigned int default_function_arg_boundary (machine_mode,
 						   const_tree);
 extern unsigned int default_function_arg_round_boundary (machine_mode,
 							 const_tree);
+extern unsigned int default_function_arg_boundary_ca (machine_mode,
+						      const_tree,
+						      cumulative_args_t ca);
+extern unsigned int default_function_arg_round_boundary_ca (machine_mode,
+							    const_tree,
+							    cumulative_args_t ca);
 extern bool hook_bool_const_rtx_commutative_p (const_rtx, int);
 extern rtx default_function_value (const_tree, const_tree, bool);
 extern HARD_REG_SET default_zero_call_used_regs (HARD_REG_SET);
diff --git a/libgcc/config.host b/libgcc/config.host
index ee10e99b0a6..585d4ffa08b 100644
--- libgcc/config.host
+++ libgcc/config.host
@@ -82,7 +82,7 @@ m32c*-*-*)
         cpu_type=m32c
 	tmake_file=t-fdpbit
         ;;
-aarch64*-*-*)
+aarch64*-*-* | arm64*-*-*)
 	cpu_type=aarch64
 	;;
 alpha*-*-*)
@@ -236,11 +236,14 @@ case ${host} in
   esac
   tmake_file="$tmake_file t-slibgcc-darwin"
   case ${host} in
+    x86_64-*-darwin2[0-2]*)
+      tmake_file="t-darwin-min-11 t-darwin-libgccs1 $tmake_file"
+      ;;
     *-*-darwin2*)
       tmake_file="t-darwin-min-11 $tmake_file"
       ;;
     *-*-darwin1[89]*)
-      tmake_file="t-darwin-min-8 $tmake_file"
+      tmake_file="t-darwin-min-8 t-darwin-libgccs1 $tmake_file"
       ;;
     *-*-darwin1[67]]*)
       tmake_file="t-darwin-min-5 $tmake_file"
@@ -280,7 +283,7 @@ case ${host} in
   if test "x$enable_darwin_at_rpath" = "xyes"; then
     tmake_file="$tmake_file t-darwin-rpath "
   fi
-  extra_parts="crt3.o libd10-uwfef.a crttms.o crttme.o libemutls_w.a"
+  extra_parts="crt3.o crttms.o crttme.o libemutls_w.a "
   ;;
 *-*-dragonfly*)
   tmake_file="$tmake_file t-crtstuff-pic t-libgcc-pic t-eh-dw2-dip"
@@ -424,6 +427,15 @@ aarch64*-*-elf | aarch64*-*-rtems*)
 	tmake_file="${tmake_file} t-dfprules"
 	md_unwind_header=aarch64/aarch64-unwind.h
 	;;
+aarch64*-*-darwin*)
+	extra_parts="$extra_parts crtfastmath.o libheapt_w.a"
+	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
+	tmake_file="${tmake_file} ${cpu_type}/t-lse"
+	tmake_file="${tmake_file} t-crtfm t-dfprules"
+	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp"
+	tmake_file="${tmake_file} ${cpu_type}/t-heap-trampoline"
+	md_unwind_header=aarch64/aarch64-unwind.h
+	;;
 aarch64*-*-freebsd*)
 	extra_parts="$extra_parts crtfastmath.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
@@ -731,14 +743,14 @@ i[34567]86-*-darwin*)
 	tmake_file="$tmake_file i386/t-crtpc t-crtfm i386/t-msabi"
 	tm_file="$tm_file i386/darwin-lib.h"
 	extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o"
-	extra_parts="$extra_parts crtfastmath.o libheapt_w.a"
+	extra_parts="$extra_parts crtfastmath.o libd10-uwfef.a libheapt_w.a"
 	tmake_file="${tmake_file} i386/t-heap-trampoline"
 	;;
 x86_64-*-darwin*)
 	tmake_file="$tmake_file i386/t-crtpc t-crtfm i386/t-msabi"
 	tm_file="$tm_file i386/darwin-lib.h"
 	extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o"
-	extra_parts="$extra_parts crtfastmath.o libheapt_w.a"
+	extra_parts="$extra_parts crtfastmath.o libd10-uwfef.a libheapt_w.a"
 	tmake_file="${tmake_file} i386/t-heap-trampoline"
 	;;
 i[34567]86-*-elfiamcu)
@@ -1221,12 +1233,14 @@ powerpc-*-darwin*)
 	# We build the darwin10 EH shim for Rosetta (running on x86 machines).
 	tm_file="$tm_file i386/darwin-lib.h"
 	tmake_file="$tmake_file rs6000/t-ppc64-fp rs6000/t-ibm-ldouble"
+	extra_parts="$extra_parts libd10-uwfef.a "
 	extra_parts="$extra_parts crt2.o crt3_2.o libef_ppc.a dw_ppc.o"
 	;;
 powerpc64-*-darwin*)
 	# We build the darwin10 EH shim for Rosetta (running on x86 machines).
 	tm_file="$tm_file i386/darwin-lib.h"
 	tmake_file="$tmake_file rs6000/t-darwin64 rs6000/t-ibm-ldouble"
+	extra_parts="$extra_parts libd10-uwfef.a "
 	extra_parts="$extra_parts crt2.o crt3_2.o libef_ppc.a dw_ppc.o"
 	;;
 powerpc*-*-freebsd*)
diff --git a/libgcc/config/aarch64/__arm_sme_state.S b/libgcc/config/aarch64/__arm_sme_state.S
index 1fbb8c1ff53..b665769004f 100644
--- libgcc/config/aarch64/__arm_sme_state.S
+++ libgcc/config/aarch64/__arm_sme_state.S
@@ -30,14 +30,19 @@
    - Takes no argument.
    - Returns SME state in x0 and TPIDR2_EL0 in x1.  */
 
-HIDDEN (__aarch64_have_sme)
+HIDDEN (ASMNAME (__aarch64_have_sme))
 
-variant_pcs (__arm_sme_state)
+variant_pcs (ASMNAME (__arm_sme_state))
 
-ENTRY (__arm_sme_state)
+ENTRY (ASMNAME (__arm_sme_state))
 	/* Check if SME is available.  */
-	adrp	x1, __aarch64_have_sme
-	ldrb	w1, [x1, :lo12:__aarch64_have_sme]
+#ifdef __APPLE__
+	adrp	x1, ASMNAME (__aarch64_have_sme)@PAGE
+	ldrb	w1, [x1, ASMNAME (__aarch64_have_sme)@PAGEOFF]
+#else
+	adrp	x1, ASMNAME (__aarch64_have_sme)
+	ldrb	w1, [x1, :lo12:ASMNAME (__aarch64_have_sme)]
+#endif
 	cbz	w1, L(nosme)
 
 	/* Expose the bottom 2 bits of svcr (SM, ZA) in x0 and set the
@@ -52,4 +57,4 @@ L(nosme):
 	mov	x0, 0
 	mov	x1, 0
 	ret
-END (__arm_sme_state)
+ENDm ASMNAME(__arm_sme_state)
diff --git a/libgcc/config/aarch64/__arm_tpidr2_restore.S b/libgcc/config/aarch64/__arm_tpidr2_restore.S
index 5088c86df32..bcfb935bc96 100644
--- libgcc/config/aarch64/__arm_tpidr2_restore.S
+++ libgcc/config/aarch64/__arm_tpidr2_restore.S
@@ -31,9 +31,9 @@
    - Does not return a value.
    - Can abort on failure (then registers are not preserved).  */
 
-variant_pcs (__arm_tpidr2_restore)
+variant_pcs (ASMNAME (__arm_tpidr2_restore))
 
-ENTRY (__arm_tpidr2_restore)
+ENTRY (ASMNAME (__arm_tpidr2_restore))
 	.inst	0xd53bd0ae  /* mrs	x14, tpidr2_el0  */
 	cbnz	x14, L(fail)
 
@@ -85,5 +85,5 @@ L(fail):
 	str	x16, [sp, 16]
 	.cfi_rel_offset 46, 16
 	.inst	0xd503467f  /* smstop  */
-	bl	abort
-END (__arm_tpidr2_restore)
+	bl	ASMNAME (abort)
+ENDm ASMNAME (__arm_tpidr2_restore)
diff --git a/libgcc/config/aarch64/__arm_tpidr2_save.S b/libgcc/config/aarch64/__arm_tpidr2_save.S
index 2466b5863e4..28e75ade2d0 100644
--- libgcc/config/aarch64/__arm_tpidr2_save.S
+++ libgcc/config/aarch64/__arm_tpidr2_save.S
@@ -35,10 +35,15 @@ HIDDEN (__aarch64_have_sme)
 
 variant_pcs (__arm_tpidr2_save)
 
-ENTRY (__arm_tpidr2_save)
+ENTRY (ASMNAME (__arm_tpidr2_save))
 	/* Check if SME is available.  */
-	adrp	x14, __aarch64_have_sme
-	ldrb	w14, [x14, :lo12:__aarch64_have_sme]
+#if __APPLE__
+	adrp	x14, ASMNAME (__aarch64_have_sme)@PAGE
+	ldrb	w14, [x14, ASMNAME (__aarch64_have_sme)@PAGEOFF]
+#else
+	adrp	x14, ASMNAME (__aarch64_have_sme)
+	ldrb	w14, [x14, :lo12:ASMNAME (__aarch64_have_sme)]
+#endif
 	cbz	w14, L(end)
 
 	.inst	0xd53bd0ae  /* mrs	x14, tpidr2_el0  */
@@ -92,10 +97,18 @@ L(fail):
 	str	x16, [sp, 16]
 	.cfi_rel_offset 46, 16
 	.inst	0xd503467f  /* smstop  */
-	bl	abort
-END (__arm_tpidr2_save)
-
+	bl	ASMNAME (abort)
+ENDm ASMNAME (__arm_tpidr2_save)
+
+	GLOBAL(ASMNAME (__libgcc_arm_tpidr2_save))
+	HIDDEN (ASMNAME (__libgcc_arm_tpidr2_save))
+#if __APPLE__
+	.text
+	.p2align 4
+ASMNAME (__libgcc_arm_tpidr2_save):
+	b ASMNAME (__arm_tpidr2_save)
+#else
 /* Hidden alias used by __arm_za_disable.  */
-.global __libgcc_arm_tpidr2_save
-HIDDEN (__libgcc_arm_tpidr2_save)
-.set __libgcc_arm_tpidr2_save, __arm_tpidr2_save
+.set ASMNAME (__libgcc_arm_tpidr2_save), ASMNAME (__arm_tpidr2_save)
+#endif
+
diff --git a/libgcc/config/aarch64/__arm_za_disable.S b/libgcc/config/aarch64/__arm_za_disable.S
index c372fcffe18..9aefed6cde7 100644
--- libgcc/config/aarch64/__arm_za_disable.S
+++ libgcc/config/aarch64/__arm_za_disable.S
@@ -31,16 +31,33 @@
    - Does not return a value.
    - Can abort on failure (then registers are not preserved).  */
 
-HIDDEN (__aarch64_have_sme)
+HIDDEN (ASMNAME(__aarch64_have_sme))
 
-HIDDEN (__libgcc_arm_tpidr2_save)
+HIDDEN (ASMNAME(__libgcc_arm_tpidr2_save))
 
-variant_pcs (__arm_za_disable)
+variant_pcs (ASMNAME(__arm_za_disable))
 
-ENTRY (__arm_za_disable)
+GLOBAL (ASMNAME (__libgcc_arm_za_disable))
+HIDDEN (ASMNAME (__libgcc_arm_za_disable))
+#if __APPLE__
+	.text
+	.p2align 4
+ASMNAME (__libgcc_arm_za_disable):
+	b ASMNAME (__arm_za_disable)
+#else
+/* Hidden alias used by the unwinder.  */
+.set ASMNAME (__libgcc_arm_za_disable), ASMNAME (__arm_za_disable)
+#endif
+
+ENTRY (ASMNAME (__arm_za_disable))
 	/* Check if SME is available.  */
-	adrp	x14, __aarch64_have_sme
-	ldrb	w14, [x14, :lo12:__aarch64_have_sme]
+#if __APPLE__
+	adrp	x14, ASMNAME (__aarch64_have_sme)@PAGE
+	ldrb	w14, [x14, ASMNAME (__aarch64_have_sme)@PAGEOFF]
+#else
+	adrp	x14, ASMNAME (__aarch64_have_sme)
+	ldrb	w14, [x14, :lo12:ASMNAME (__aarch64_have_sme)]
+#endif
 	cbz	w14, L(end)
 
 	.inst	0xd53bd0ae  /* mrs	x14, tpidr2_el0  */
@@ -52,7 +69,7 @@ ENTRY (__arm_za_disable)
 	.cfi_rel_offset x29, 0
 	.cfi_rel_offset x30, 8
 	mov	x29, sp
-	bl	__libgcc_arm_tpidr2_save
+	bl	ASMNAME (__libgcc_arm_tpidr2_save)
 	.inst	0xd51bd0bf  /* msr	tpidr2_el0, xzr  */
 	.inst	0xd503447f  /* smstop	za  */
 	ldp	x29, x30, [sp], 16
@@ -62,9 +79,5 @@ ENTRY (__arm_za_disable)
 	AUTIASP
 L(end):
 	ret
-END (__arm_za_disable)
+ENDm ASMNAME(__arm_za_disable)
 
-/* Hidden alias used by the unwinder.  */
-.global __libgcc_arm_za_disable
-HIDDEN (__libgcc_arm_za_disable)
-.set __libgcc_arm_za_disable, __arm_za_disable
diff --git a/libgcc/config/aarch64/aarch64-asm.h b/libgcc/config/aarch64/aarch64-asm.h
index 83c2e5944b3..7e41e6eb082 100644
--- libgcc/config/aarch64/aarch64-asm.h
+++ libgcc/config/aarch64/aarch64-asm.h
@@ -24,8 +24,6 @@
 
 #include "auto-target.h"
 
-#define L(label) .L ## label
-
 /* Marking variant PCS symbol references is important for PLT calls
    otherwise it is for documenting the PCS in the symbol table.  */
 #ifdef HAVE_AS_VARIANT_PCS
@@ -58,12 +56,31 @@
 # define AUTIASP
 #endif
 
+#define PASTE2(a, b) PASTE2a(a, b)
+#define PASTE2a(a, b) a ## b
+
+#ifdef __USER_LABEL_PREFIX__
+# define ASMNAME(name) PASTE2(__USER_LABEL_PREFIX__, name)
+#else
+# define ASMNAME(name) name
+#endif
+
 #ifdef __ELF__
+#define L(label) .L ## label
 #define HIDDEN(name) .hidden name
+#define GLOBAL(name) .global name
 #define SYMBOL_SIZE(name) .size name, .-name
 #define SYMBOL_TYPE(name, _type) .type name, _type
+#elif __APPLE__
+#define L(label) L ## label
+#define HIDDEN(name) .private_extern name
+#define GLOBAL(name) .globl name
+#define SYMBOL_SIZE(name)
+#define SYMBOL_TYPE(name, _type)
 #else
+#define L(label) .L ## label
 #define HIDDEN(name)
+#define GLOBAL(name) .global name
 #define SYMBOL_SIZE(name)
 #define SYMBOL_TYPE(name, _type)
 #endif
@@ -93,16 +110,19 @@ GNU_PROPERTY (FEATURE_1_AND, BTI_FLAG|PAC_FLAG)
 # endif
 #endif
 
-#define ENTRY_ALIGN(name, align) \
-  .global name;		\
-  SYMBOL_TYPE(name, %function);		\
-  .balign align;	\
-  name:			\
-  .cfi_startproc;	\
-  BTI_C
-
-#define ENTRY(name) ENTRY_ALIGN(name, 16)
-
-#define END(name) \
-  .cfi_endproc;		\
-  SYMBOL_SIZE(name)
+.macro	ENTRY_ALIGNP2m, name, align
+	.text
+	.p2align \align
+	GLOBAL (\name)
+	SYMBOL_TYPE(\name, %function)
+\name:
+	.cfi_startproc
+	BTI_C
+.endm
+
+#define ENTRY(name) ENTRY_ALIGNP2m name, 4
+
+.macro	ENDm, name
+	.cfi_endproc
+	SYMBOL_SIZE (\name)
+.endm
diff --git a/libgcc/config/aarch64/lse.S b/libgcc/config/aarch64/lse.S
index ecef47086c6..54b85b5ad2a 100644
--- libgcc/config/aarch64/lse.S
+++ libgcc/config/aarch64/lse.S
@@ -62,7 +62,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #endif
 
 /* Declare the symbol gating the LSE implementations.  */
-	HIDDEN(__aarch64_have_lse_atomics)
+	HIDDEN (ASMNAME (__aarch64_have_lse_atomics))
 
 /* Turn size and memory model defines into mnemonic fragments.  */
 #if SIZE == 1
@@ -85,6 +85,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 # error
 #endif
 
+#undef L
 #if MODEL == 1
 # define SUFF  _relax
 # define A
@@ -167,32 +168,21 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define tmp3	14
 #define tmp4	13
 
-/* Start and end a function.  */
-.macro	STARTFN name
-	.text
-	.balign	16
-	.globl	\name
-	HIDDEN(\name)
-	SYMBOL_TYPE(\name, %function)
-	.cfi_startproc
-\name:
-.endm
-
-.macro	ENDFN name
-	.cfi_endproc
-	SYMBOL_SIZE(\name)
-.endm
-
 /* Branch to LABEL if LSE is disabled.  */
 .macro	JUMP_IF_NOT_LSE label
-	adrp	x(tmp0), __aarch64_have_lse_atomics
-	ldrb	w(tmp0), [x(tmp0), :lo12:__aarch64_have_lse_atomics]
+#if __APPLE__
+	adrp	x(tmp0), ASMNAME (__aarch64_have_lse_atomics)@PAGE
+	ldrb	w(tmp0), [x(tmp0), ASMNAME (__aarch64_have_lse_atomics)@PAGEOFF]
+#else
+	adrp	x(tmp0), ASMNAME (__aarch64_have_lse_atomics)
+	ldrb	w(tmp0), [x(tmp0), :lo12:ASMNAME (__aarch64_have_lse_atomics)]
+#endif
 	cbz	w(tmp0), \label
 .endm
 
 #ifdef L_cas
 
-STARTFN	NAME(cas)
+ENTRY (ASMNAME (NAME(cas)))
 	JUMP_IF_NOT_LSE	8f
 
 #if SIZE < 16
@@ -245,7 +235,7 @@ STARTFN	NAME(cas)
 
 #endif
 
-ENDFN	NAME(cas)
+ENDm ASMNAME (NAME(cas))
 #endif
 
 #ifdef L_swp
@@ -255,7 +245,7 @@ ENDFN	NAME(cas)
 # define SWP	.inst 0x38208020 + B + N
 #endif
 
-STARTFN	NAME(swp)
+ENTRY (ASMNAME (NAME (swp)))
 	JUMP_IF_NOT_LSE	8f
 
 	SWP		/* s(0), s(0), [x1] */
@@ -268,7 +258,7 @@ STARTFN	NAME(swp)
 	BARRIER
 	ret
 
-ENDFN	NAME(swp)
+ENDm ASMNAME (NAME (swp))
 #endif
 
 #if defined(L_ldadd) || defined(L_ldclr) \
@@ -299,7 +289,7 @@ ENDFN	NAME(swp)
 # define LDOP	.inst 0x38200020 + OPN + B + N
 #endif
 
-STARTFN	NAME(LDNM)
+ENTRY (ASMNAME (NAME (LDNM)))
 	JUMP_IF_NOT_LSE	8f
 
 	LDOP		/* s(0), s(0), [x1] */
@@ -313,5 +303,5 @@ STARTFN	NAME(LDNM)
 	BARRIER
 	ret
 
-ENDFN	NAME(LDNM)
+ENDm ASMNAME (NAME (LDNM))
 #endif
diff --git a/libgcc/config/aarch64/sfp-machine.h b/libgcc/config/aarch64/sfp-machine.h
index 7fbb2a4288a..3ebc1d5fe44 100644
--- libgcc/config/aarch64/sfp-machine.h
+++ libgcc/config/aarch64/sfp-machine.h
@@ -124,6 +124,27 @@ void __sfp_handle_exceptions (int);
 
 
 /* Define ALIASNAME as a strong alias for NAME.  */
+#if defined __APPLE__
+/* Mach-O doesn't support aliasing, so we build a secondary function for
+   the alias - we need to do a bit of a dance to find out what the type of
+   the arguments is and then apply that to the secondary function.
+   If these functions ever return anything but CMPtype we need to revisit
+   this... */
+typedef float alias_HFtype __attribute__ ((mode (HF)));
+typedef float alias_SFtype __attribute__ ((mode (SF)));
+typedef float alias_DFtype __attribute__ ((mode (DF)));
+typedef float alias_TFtype __attribute__ ((mode (TF)));
+#define ALIAS_SELECTOR \
+  CMPtype (*) (alias_HFtype, alias_HFtype): (alias_HFtype) 0, \
+  CMPtype (*) (alias_SFtype, alias_SFtype): (alias_SFtype) 0, \
+  CMPtype (*) (alias_DFtype, alias_DFtype): (alias_DFtype) 0, \
+  CMPtype (*) (alias_TFtype, alias_TFtype): (alias_TFtype) 0
+#define strong_alias(name, aliasname) \
+  CMPtype aliasname (__typeof (_Generic (name, ALIAS_SELECTOR)) a, \
+		     __typeof (_Generic (name, ALIAS_SELECTOR)) b) \
+		    { return name (a, b); }
+#else
 # define strong_alias(name, aliasname) _strong_alias(name, aliasname)
 # define _strong_alias(name, aliasname) \
   extern __typeof (name) aliasname __attribute__ ((alias (#name)));
+#endif
diff --git a/libgcc/config/aarch64/t-darwin b/libgcc/config/aarch64/t-darwin
new file mode 100644
index 00000000000..f6ecda7b608
--- /dev/null
+++ libgcc/config/aarch64/t-darwin
@@ -0,0 +1,7 @@
+# Ensure we have a suitable minimum OS version.
+
+HOST_LIBGCC2_CFLAGS += -mmacosx-version-min=11.0
+
+LIB2_SIDITI_CONV_FUNCS = yes
+
+BUILD_LIBGCCS1 =
diff --git a/libitm/config/aarch64/sjlj.S b/libitm/config/aarch64/sjlj.S
index 6b248f7c040..dd844e8c9d8 100644
--- libitm/config/aarch64/sjlj.S
+++ libitm/config/aarch64/sjlj.S
@@ -57,10 +57,19 @@
 
 	.text
 	.align	2
+#if __ELF__
 	.global	_ITM_beginTransaction
 	.type	_ITM_beginTransaction, %function
 
 _ITM_beginTransaction:
+
+#elif __MACH__
+	.global	__ITM_beginTransaction
+
+__ITM_beginTransaction:
+
+#endif
+
 	cfi_startproc
 	CFI_PAC_KEY
 	PAC_AND_BTI
@@ -84,8 +93,13 @@ _ITM_beginTransaction:
 
 	/* Invoke GTM_begin_transaction with the struct we just built.  */
 	mov	x1, sp
+#if __ELF__
 	bl	GTM_begin_transaction
-
+#elif __MACH__
+	bl	_GTM_begin_transaction
+#else
+#error "unexpected object format"
+#endif
 	/* Return; we don't need to restore any of the call-saved regs.  */
 	ldp	x29, x30, [sp], 11*16
 	cfi_adjust_cfa_offset(-11*16)
@@ -95,14 +109,23 @@ _ITM_beginTransaction:
 	CFI_PAC_TOGGLE
 	ret
 	cfi_endproc
+#if __ELF__
 	.size	_ITM_beginTransaction, . - _ITM_beginTransaction
+#endif
 
 	.align	2
+#if __ELF__
 	.global	GTM_longjmp
 	.hidden	GTM_longjmp
 	.type	GTM_longjmp, %function
 
 GTM_longjmp:
+
+#elif __MACH__
+	.private_extern _GTM_longjmp
+
+_GTM_longjmp:
+#endif
 	/* The first parameter becomes the return value (x0).
 	   The third parameter is ignored for now.  */
 	cfi_startproc
@@ -126,7 +149,9 @@ GTM_longjmp:
 	CFI_PAC_TOGGLE
 	br	x30
 	cfi_endproc
+#if __ELF__
 	.size	GTM_longjmp, . - GTM_longjmp
+#endif
 
 /* GNU_PROPERTY_AARCH64_* macros from elf.h for use in asm code.  */
 #define FEATURE_1_AND 0xc0000000
diff --git a/libitm/configure.tgt b/libitm/configure.tgt
index a8276f05d9b..6fad8534372 100644
--- libitm/configure.tgt
+++ libitm/configure.tgt
@@ -50,7 +50,7 @@ fi
 # Map the target cpu to an ARCH sub-directory.  At the same time,
 # work out any special compilation flags as necessary.
 case "${target_cpu}" in
-  aarch64*)		ARCH=aarch64 ;;
+  aarch64* | arm64*)	ARCH=aarch64 ;;
   alpha*)		ARCH=alpha ;;
   rs6000 | powerpc*)
 	XCFLAGS="${XCFLAGS} -mhtm"
diff --git a/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d b/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
index cb8df47507f..2b70a8cca2b 100644
--- libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
+++ libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d
@@ -30,8 +30,13 @@ module core.internal.gc.impl.conservative.gc;
 
 /***************************************************/
 version = COLLECT_PARALLEL;  // parallel scanning
-version (Posix)
-    version = COLLECT_FORK;
+version (GNU)
+{
+  version (linux)
+    version = COLLECT_FORK;  // uses clone(), battle tested and reliable
+}
+else version (Posix)
+  version = COLLECT_FORK;
 
 import core.internal.gc.bits;
 import core.internal.gc.os;
