diff -Naur gcc-14-20241221.orig/configure gcc-14-20241221/configure --- gcc-14-20241221.orig/configure 2024-12-21 23:34:15.000000000 +0100 +++ gcc-14-20241221/configure 2024-12-29 10:09:42.950642743 +0100 @@ -3518,6 +3518,8 @@ # Disable libffi for some systems. case "${target}" in + aarch64*-*-darwin2*) + ;; powerpc-*-darwin*) ;; i[3456789]86-*-darwin*) diff -Naur gcc-14-20241221.orig/configure.ac gcc-14-20241221/configure.ac --- gcc-14-20241221.orig/configure.ac 2024-12-21 23:32:25.000000000 +0100 +++ gcc-14-20241221/configure.ac 2024-12-29 10:09:42.952617012 +0100 @@ -747,6 +747,8 @@ # Disable libffi for some systems. case "${target}" in + aarch64*-*-darwin2*) + ;; powerpc-*-darwin*) ;; i[[3456789]]86-*-darwin*) diff -Naur gcc-14-20241221.orig/darwin.patch gcc-14-20241221/darwin.patch --- gcc-14-20241221.orig/darwin.patch 1970-01-01 01:00:00.000000000 +0100 +++ gcc-14-20241221/darwin.patch 2024-12-29 10:18:56.844756624 +0100 @@ -0,0 +1,24 @@ +diff -Naur gcc-14-20241221.orig/configure gcc-14-20241221/configure +--- gcc-14-20241221.orig/configure 2024-12-21 23:34:15.000000000 +0100 ++++ gcc-14-20241221/configure 2024-12-29 10:09:42.950642743 +0100 +@@ -3518,6 +3518,8 @@ + + # Disable libffi for some systems. + case "${target}" in ++ aarch64*-*-darwin2*) ++ ;; + powerpc-*-darwin*) + ;; + i[3456789]86-*-darwin*) +diff -Naur gcc-14-20241221.orig/configure.ac gcc-14-20241221/configure.ac +--- gcc-14-20241221.orig/configure.ac 2024-12-21 23:32:25.000000000 +0100 ++++ gcc-14-20241221/configure.ac 2024-12-29 10:09:42.952617012 +0100 +@@ -747,6 +747,8 @@ + + # Disable libffi for some systems. + case "${target}" in ++ aarch64*-*-darwin2*) ++ ;; + powerpc-*-darwin*) + ;; + i[[3456789]]86-*-darwin*) diff -Naur gcc-14-20241221.orig/fixincludes/fixincl.x gcc-14-20241221/fixincludes/fixincl.x --- gcc-14-20241221.orig/fixincludes/fixincl.x 2024-12-21 23:34:07.000000000 +0100 +++ gcc-14-20241221/fixincludes/fixincl.x 2024-12-29 10:09:42.956803589 +0100 @@ -269,56 +269,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * - * 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 */ tSCC zAab_Fd_Zero_Asm_Posix_Types_HName[] = @@ -2765,51 +2715,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * - * 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 */ tSCC zDarwin_9_Long_Double_Funcs_2Name[] = @@ -11169,9 +11074,9 @@ * * 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 @@ 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 @@ 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 @@ 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 @@ 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 -Naur gcc-14-20241221.orig/fixincludes/inclhack.def gcc-14-20241221/fixincludes/inclhack.def --- gcc-14-20241221.orig/fixincludes/inclhack.def 2024-12-21 23:32:25.000000000 +0100 +++ gcc-14-20241221/fixincludes/inclhack.def 2024-12-29 10:09:42.959351685 +0100 @@ -195,33 +195,6 @@ }; /* - * 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) */ fix = { @@ -1351,32 +1324,6 @@ }; /* - * macOS 10.12 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 -Naur gcc-14-20241221.orig/gcc/ada/init.c gcc-14-20241221/gcc/ada/init.c --- gcc-14-20241221.orig/gcc/ada/init.c 2024-12-21 23:32:25.000000000 +0100 +++ gcc-14-20241221/gcc/ada/init.c 2024-12-29 10:09:42.961333996 +0100 @@ -2479,7 +2479,10 @@ /* 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 -Naur gcc-14-20241221.orig/gcc/builtins.cc gcc-14-20241221/gcc/builtins.cc --- gcc-14-20241221.orig/gcc/builtins.cc 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/builtins.cc 2024-12-29 10:09:42.965077495 +0100 @@ -5929,6 +5929,13 @@ 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 -Naur gcc-14-20241221.orig/gcc/c/c-parser.cc gcc-14-20241221/gcc/c/c-parser.cc --- gcc-14-20241221.orig/gcc/c/c-parser.cc 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/c/c-parser.cc 2024-12-29 10:09:42.977722768 +0100 @@ -217,6 +217,9 @@ 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 @@ 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; @@ -5213,6 +5216,88 @@ 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 +5463,13 @@ 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 -Naur gcc-14-20241221.orig/gcc/c-family/c-attribs.cc gcc-14-20241221/gcc/c-family/c-attribs.cc --- gcc-14-20241221.orig/gcc/c-family/c-attribs.cc 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/c-family/c-attribs.cc 2024-12-29 10:09:42.967729673 +0100 @@ -665,6 +665,18 @@ 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 -Naur gcc-14-20241221.orig/gcc/c-family/c-common.h gcc-14-20241221/gcc/c-family/c-common.h --- gcc-14-20241221.orig/gcc/c-family/c-common.h 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/c-family/c-common.h 2024-12-29 10:09:42.969019950 +0100 @@ -1628,6 +1628,7 @@ /* 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 -Naur gcc-14-20241221.orig/gcc/c-family/c-lex.cc gcc-14-20241221/gcc/c-family/c-lex.cc --- gcc-14-20241221.orig/gcc/c-family/c-lex.cc 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/c-family/c-lex.cc 2024-12-29 10:09:42.970351394 +0100 @@ -584,6 +584,21 @@ 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 -Naur gcc-14-20241221.orig/gcc/c-family/c-opts.cc gcc-14-20241221/gcc/c-family/c-opts.cc --- gcc-14-20241221.orig/gcc/c-family/c-opts.cc 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/c-family/c-opts.cc 2024-12-29 10:09:42.971485214 +0100 @@ -1119,7 +1119,7 @@ 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 -Naur gcc-14-20241221.orig/gcc/c-family/c-pragma.h gcc-14-20241221/gcc/c-family/c-pragma.h --- gcc-14-20241221.orig/gcc/c-family/c-pragma.h 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/c-family/c-pragma.h 2024-12-29 10:09:42.971917834 +0100 @@ -276,6 +276,9 @@ #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 -Naur gcc-14-20241221.orig/gcc/calls.cc gcc-14-20241221/gcc/calls.cc --- gcc-14-20241221.orig/gcc/calls.cc 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/calls.cc 2024-12-29 10:09:42.979919535 +0100 @@ -1376,7 +1376,8 @@ 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 @@ 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 @@ #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 @@ 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 @@ 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 @@ 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 @@ 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 -Naur gcc-14-20241221.orig/gcc/calls.h gcc-14-20241221/gcc/calls.h --- gcc-14-20241221.orig/gcc/calls.h 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/calls.h 2024-12-29 10:09:42.981261019 +0100 @@ -35,24 +35,43 @@ { 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 @@ "..."). 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 -Naur gcc-14-20241221.orig/gcc/collect2.cc gcc-14-20241221/gcc/collect2.cc --- gcc-14-20241221.orig/gcc/collect2.cc 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/collect2.cc 2024-12-29 10:09:42.982697878 +0100 @@ -73,7 +73,7 @@ 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 @@ #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 @@ 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 @@ } } +#if defined (OBJECT_FORMAT_MACHO) +# define LLD_NAME "ld64.lld" +#else +# define LLD_NAME "ld.lld" +#endif + /* Main program. */ int @@ -777,16 +783,19 @@ 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 @@ #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 @@ 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 @@ 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 @@ } #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 -Naur gcc-14-20241221.orig/gcc/common/config/aarch64/aarch64-common.cc gcc-14-20241221/gcc/common/config/aarch64/aarch64-common.cc --- gcc-14-20241221.orig/gcc/common/config/aarch64/aarch64-common.cc 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/common/config/aarch64/aarch64-common.cc 2024-12-29 10:09:42.984650314 +0100 @@ -298,8 +298,12 @@ 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 @@ 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 @@ { current_flags &= ~opt.flags_off; outstr += "+no"; - outstr += opt.name; + if (startswith (opt.name, "rdm")) + outstr += "rdm"; + else + outstr += opt.name; } } diff -Naur gcc-14-20241221.orig/gcc/common.opt gcc-14-20241221/gcc/common.opt --- gcc-14-20241221.orig/gcc/common.opt 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/common.opt 2024-12-29 10:09:42.983969280 +0100 @@ -2919,6 +2919,10 @@ 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 @@ 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 -Naur gcc-14-20241221.orig/gcc/config/aarch64/aarch64-builtins.cc gcc-14-20241221/gcc/config/aarch64/aarch64-builtins.cc --- gcc-14-20241221.orig/gcc/config/aarch64/aarch64-builtins.cc 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/config/aarch64/aarch64-builtins.cc 2024-12-29 10:09:42.988526645 +0100 @@ -788,6 +788,8 @@ AARCH64_PLDX, AARCH64_PLI, AARCH64_PLIX, + /* OS-specific */ + AARCH64_BUILTIN_CFSTRING, AARCH64_BUILTIN_MAX }; @@ -887,6 +889,9 @@ /* 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_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_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 @@ 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 -Naur gcc-14-20241221.orig/gcc/config/aarch64/aarch64-c.cc gcc-14-20241221/gcc/config/aarch64/aarch64-c.cc --- gcc-14-20241221.orig/gcc/config/aarch64/aarch64-c.cc 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/config/aarch64/aarch64-c.cc 2024-12-29 10:09:42.988966224 +0100 @@ -285,6 +285,16 @@ { 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 @@ 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 -Naur gcc-14-20241221.orig/gcc/config/aarch64/aarch64-cores.def gcc-14-20241221/gcc/config/aarch64/aarch64-cores.def --- gcc-14-20241221.orig/gcc/config/aarch64/aarch64-cores.def 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/config/aarch64/aarch64-cores.def 2024-12-29 10:09:42.989341386 +0100 @@ -167,6 +167,17 @@ /* 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 -Naur gcc-14-20241221.orig/gcc/config/aarch64/aarch64-protos.h gcc-14-20241221/gcc/config/aarch64/aarch64-protos.h --- gcc-14-20241221.orig/gcc/config/aarch64/aarch64-protos.h 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/config/aarch64/aarch64-protos.h 2024-12-29 10:09:42.989983462 +0100 @@ -109,6 +109,14 @@ 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 @@ 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_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 @@ 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 -Naur gcc-14-20241221.orig/gcc/config/aarch64/aarch64-tune.md gcc-14-20241221/gcc/config/aarch64/aarch64-tune.md --- gcc-14-20241221.orig/gcc/config/aarch64/aarch64-tune.md 2024-12-21 23:34:08.000000000 +0100 +++ gcc-14-20241221/gcc/config/aarch64/aarch64-tune.md 2024-12-29 10:18:01.201435440 +0100 @@ -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 -Naur gcc-14-20241221.orig/gcc/config/aarch64/aarch64.cc gcc-14-20241221/gcc/config/aarch64/aarch64.cc --- gcc-14-20241221.orig/gcc/config/aarch64/aarch64.cc 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/config/aarch64/aarch64.cc 2024-12-29 10:09:42.998034454 +0100 @@ -329,8 +329,10 @@ 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 @@ { /* { 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ return; } + case SYMBOL_MO_SMALL_GOT: case SYMBOL_SMALL_GOT_4G: emit_insn (gen_rtx_SET (dest, imm)); return; @@ -6028,6 +6052,7 @@ 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 @@ /* FALLTHRU */ case SYMBOL_SMALL_ABSOLUTE: + case SYMBOL_MO_SMALL_PCR: case SYMBOL_TINY_ABSOLUTE: case SYMBOL_TLSLE12: case SYMBOL_TLSLE24: @@ -6630,6 +6656,7 @@ 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 @@ &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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ } pcum->aapcs_reg = par; } + pcum->darwinpcs_stack_bytes = 0; return; } else @@ -7005,14 +7064,24 @@ /* 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 @@ } pcum->aapcs_reg = par; } - pcum->aapcs_nextncrn = ncrn + nregs; + pcum->darwinpcs_stack_bytes = 0; return; } @@ -7093,7 +7162,81 @@ /* 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 @@ 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 @@ 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 @@ || 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 @@ 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 @@ || (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 @@ &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. */ @@ -10700,6 +10977,7 @@ /* 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) @@ -10707,6 +10985,7 @@ { 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) @@ -10724,10 +11003,13 @@ 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; @@ -10777,6 +11059,55 @@ 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; } @@ -11910,6 +12241,144 @@ } } +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 # @@ -11983,6 +12452,12 @@ } 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); @@ -12315,7 +12790,7 @@ 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: @@ -12346,9 +12821,26 @@ 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: @@ -12386,10 +12878,12 @@ 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: @@ -12398,6 +12892,7 @@ default: break; } +#endif output_addr_const (asm_out_file, x); break; @@ -12563,8 +13058,13 @@ 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; @@ -12872,7 +13372,23 @@ { /* 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 @@ -13100,6 +13616,8 @@ asm_fprintf (f, "%U%s", name); } +#if !TARGET_MACHO + static void aarch64_elf_asm_constructor (rtx symbol, int priority) { @@ -13139,6 +13657,7 @@ assemble_aligned_integer (POINTER_BYTES, symbol); } } +#endif const char* aarch64_output_casesi (rtx *operands) @@ -13291,7 +13810,11 @@ 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. */ @@ -15561,15 +16084,17 @@ { 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)); @@ -18981,10 +19506,14 @@ } 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: @@ -20908,7 +21437,9 @@ 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 (); @@ -20944,10 +21475,22 @@ 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 @@ -20959,7 +21502,8 @@ || 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 @@ -21089,7 +21633,10 @@ 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) @@ -21097,6 +21644,13 @@ 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. */ @@ -21168,6 +21722,13 @@ 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, @@ -21258,6 +21819,9 @@ 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); @@ -21462,8 +22026,18 @@ 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; @@ -21546,6 +22120,9 @@ 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. */ @@ -22389,6 +22966,12 @@ 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)) @@ -22405,6 +22988,12 @@ 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) @@ -23102,7 +23691,8 @@ /* 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)) @@ -24439,12 +25029,8 @@ 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); @@ -24483,15 +25069,60 @@ 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. */ @@ -24548,12 +25179,17 @@ /* 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 @@ -24599,6 +25235,9 @@ aarch64_last_printed_arch_string.c_str ()); default_file_start (); +#if TARGET_MACHO + darwin_file_start (); +#endif } /* Emit load exclusive. */ @@ -25178,6 +25817,16 @@ } 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) { @@ -25186,16 +25835,16 @@ ? "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 { @@ -25204,12 +25853,12 @@ 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; } @@ -28446,7 +29095,8 @@ } /* 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) @@ -28454,7 +29104,7 @@ 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)); } @@ -29271,19 +29921,37 @@ 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 } } @@ -30375,6 +31043,60 @@ 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 @@ -30580,6 +31302,15 @@ #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 @@ -30682,6 +31413,12 @@ #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 @@ -31022,7 +31759,7 @@ /* 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 -Naur gcc-14-20241221.orig/gcc/config/aarch64/aarch64.h gcc-14-20241221/gcc/config/aarch64/aarch64.h --- gcc-14-20241221.orig/gcc/config/aarch64/aarch64.h 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/config/aarch64/aarch64.h 2024-12-29 10:09:42.998962776 +0100 @@ -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 @@ 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 @@ #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 @@ 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 -Naur gcc-14-20241221.orig/gcc/config/aarch64/aarch64.md gcc-14-20241221/gcc/config/aarch64/aarch64.md --- gcc-14-20241221.orig/gcc/config/aarch64/aarch64.md 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/config/aarch64/aarch64.md 2024-12-29 10:09:43.001178793 +0100 @@ -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 @@ -7387,7 +7419,10 @@ (lo_sum:P (match_operand:P 1 "register_operand" "r") (match_operand 2 "aarch64_valid_symref" "S")))] "" - "add\\t%0, %1, :lo12:%c2" + { return TARGET_MACHO + ? "add\\t%0, %1, %J2;" + : "add\\t%0, %1, :lo12:%c2"; + } [(set_attr "type" "alu_imm")] ) diff -Naur gcc-14-20241221.orig/gcc/config/aarch64/aarch64.opt gcc-14-20241221/gcc/config/aarch64/aarch64.opt --- gcc-14-20241221.orig/gcc/config/aarch64/aarch64.opt 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/config/aarch64/aarch64.opt 2024-12-29 10:09:43.001702287 +0100 @@ -193,6 +193,13 @@ 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 -Naur gcc-14-20241221.orig/gcc/config/aarch64/constraints.md gcc-14-20241221/gcc/config/aarch64/constraints.md --- gcc-14-20241221.orig/gcc/config/aarch64/constraints.md 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/config/aarch64/constraints.md 2024-12-29 10:09:43.002111991 +0100 @@ -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 -Naur gcc-14-20241221.orig/gcc/config/aarch64/darwin.h gcc-14-20241221/gcc/config/aarch64/darwin.h --- gcc-14-20241221.orig/gcc/config/aarch64/darwin.h 1970-01-01 01:00:00.000000000 +0100 +++ gcc-14-20241221/gcc/config/aarch64/darwin.h 2024-12-29 10:09:43.002511486 +0100 @@ -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 +. */ + +/* 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 \ +" % +# include +#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; @@ -477,3 +545,4 @@ } } +#endif diff -Naur gcc-14-20241221.orig/gcc/config/aarch64/predicates.md gcc-14-20241221/gcc/config/aarch64/predicates.md --- gcc-14-20241221.orig/gcc/config/aarch64/predicates.md 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/config/aarch64/predicates.md 2024-12-29 10:09:43.003593974 +0100 @@ -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 -Naur gcc-14-20241221.orig/gcc/config/aarch64/t-aarch64-darwin gcc-14-20241221/gcc/config/aarch64/t-aarch64-darwin --- gcc-14-20241221.orig/gcc/config/aarch64/t-aarch64-darwin 1970-01-01 01:00:00.000000000 +0100 +++ gcc-14-20241221/gcc/config/aarch64/t-aarch64-darwin 2024-12-29 10:09:43.003754930 +0100 @@ -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 +# . + +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 -Naur gcc-14-20241221.orig/gcc/config/darwin-driver.cc gcc-14-20241221/gcc/config/darwin-driver.cc --- gcc-14-20241221.orig/gcc/config/darwin-driver.cc 2024-12-21 23:32:27.000000000 +0100 +++ gcc-14-20241221/gcc/config/darwin-driver.cc 2024-12-29 10:09:43.004604795 +0100 @@ -268,10 +268,13 @@ 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 @@ 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 @@ --i; --*decoded_options_count; break; - +#if !DARWIN_ARM64 case OPT_m32: seenM32 = true; break; @@ -317,6 +326,7 @@ case OPT_m64: seenM64 = true; break; +#endif case OPT_mmacosx_version_min_: seen_version_min = true; @@ -366,6 +376,9 @@ 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 @@ 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 @@ 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 @@ generate_option (appendM32 ? OPT_m32 : OPT_m64, NULL, 1, CL_DRIVER, &(*decoded_options)[*decoded_options_count - 1]); } +#endif if (!seen_sysroot_p) { diff -Naur gcc-14-20241221.orig/gcc/config/darwin-protos.h gcc-14-20241221/gcc/config/darwin-protos.h --- gcc-14-20241221.orig/gcc/config/darwin-protos.h 2024-12-21 23:32:27.000000000 +0100 +++ gcc-14-20241221/gcc/config/darwin-protos.h 2024-12-29 10:09:43.004929667 +0100 @@ -86,9 +86,12 @@ 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_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 -Naur gcc-14-20241221.orig/gcc/config/darwin.cc gcc-14-20241221/gcc/config/darwin.cc --- gcc-14-20241221.orig/gcc/config/darwin.cc 2024-12-21 23:32:27.000000000 +0100 +++ gcc-14-20241221/gcc/config/darwin.cc 2024-12-29 10:09:43.006362734 +0100 @@ -29,6 +29,7 @@ #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 @@ #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 @@ /* 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 @@ 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 @@ 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_indirections->traverse_noresize (out_file); } +#endif int machopic_operand_p (rtx op) @@ -2194,6 +2199,122 @@ 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 @@ 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 % " + "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 % " + "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 @@ 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 @@ 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 @@ 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 @@ 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. */ diff -Naur gcc-14-20241221.orig/gcc/config/darwin.h gcc-14-20241221/gcc/config/darwin.h --- gcc-14-20241221.orig/gcc/config/darwin.h 2024-12-21 23:32:27.000000000 +0100 +++ gcc-14-20241221/gcc/config/darwin.h 2024-12-29 10:09:43.007023893 +0100 @@ -42,6 +42,7 @@ #define DARWIN_X86 0 #define DARWIN_PPC 0 +#define DARWIN_ARM64 0 #define OBJECT_FORMAT_MACHO 1 @@ -373,7 +374,8 @@ */ #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 @@ -397,7 +399,8 @@ LINK_PLUGIN_SPEC \ "%{flto*:% Specify that ld64 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 @@ -383,6 +387,10 @@ weak_framework Driver RejectNegative Separate +-weak_framework Make a weak link to the specified framework. + +weak_framework +Driver RejectNegative Separate -weak_framework Make a weak link to the specified framework. weak_reference_mismatches diff -Naur gcc-14-20241221.orig/gcc/config.gcc gcc-14-20241221/gcc/config.gcc --- gcc-14-20241221.orig/gcc/config.gcc 2024-12-21 23:32:26.000000000 +0100 +++ gcc-14-20241221/gcc/config.gcc 2024-12-29 10:09:42.986386003 +0100 @@ -1177,13 +1177,22 @@ ;; 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 @@ 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 -Naur gcc-14-20241221.orig/gcc/configure gcc-14-20241221/gcc/configure --- gcc-14-20241221.orig/gcc/configure 2024-12-21 23:34:08.000000000 +0100 +++ gcc-14-20241221/gcc/configure 2024-12-29 10:09:43.013074366 +0100 @@ -740,6 +740,8 @@ 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 @@ # 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_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 ;; @@ -25306,6 +25311,14 @@ $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 -Naur gcc-14-20241221.orig/gcc/configure.ac gcc-14-20241221/gcc/configure.ac --- gcc-14-20241221.orig/gcc/configure.ac 2024-12-21 23:32:27.000000000 +0100 +++ gcc-14-20241221/gcc/configure.ac 2024-12-29 10:09:43.014757763 +0100 @@ -235,18 +235,17 @@ 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_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 ;; @@ -2817,7 +2820,15 @@ 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 -Naur gcc-14-20241221.orig/gcc/cp/decl2.cc gcc-14-20241221/gcc/cp/decl2.cc --- gcc-14-20241221.orig/gcc/cp/decl2.cc 2024-12-21 23:32:27.000000000 +0100 +++ gcc-14-20241221/gcc/cp/decl2.cc 2024-12-29 10:09:43.016098498 +0100 @@ -3840,9 +3840,8 @@ 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); @@ -4006,6 +4005,25 @@ 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 @@ -4824,22 +4842,24 @@ finish_expr_stmt (cp_build_modify_expr (loc, guard, NOP_EXPR, boolean_true_node, tf_warning_or_error)); + auto_vec 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); } } @@ -4847,6 +4867,30 @@ 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 @@ -5266,7 +5310,14 @@ } 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 -Naur gcc-14-20241221.orig/gcc/cp/parser.cc gcc-14-20241221/gcc/cp/parser.cc --- gcc-14-20241221.orig/gcc/cp/parser.cc 2024-12-21 23:32:27.000000000 +0100 +++ gcc-14-20241221/gcc/cp/parser.cc 2024-12-29 10:09:43.022793922 +0100 @@ -705,6 +705,91 @@ 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 @@ 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 @@ 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 (); @@ -29716,6 +29809,91 @@ 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: @@ -29775,9 +29953,12 @@ /* 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 *vec; int attr_flag = (attribute_takes_identifier_p (identifier) ? id_attr : normal_attr); @@ -29794,12 +29975,12 @@ 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 -Naur gcc-14-20241221.orig/gcc/cumulative-args.h gcc-14-20241221/gcc/cumulative-args.h --- gcc-14-20241221.orig/gcc/cumulative-args.h 1970-01-01 01:00:00.000000000 +0100 +++ gcc-14-20241221/gcc/cumulative-args.h 2024-12-29 10:09:43.023322041 +0100 @@ -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 -Naur gcc-14-20241221.orig/gcc/doc/invoke.texi gcc-14-20241221/gcc/doc/invoke.texi --- gcc-14-20241221.orig/gcc/doc/invoke.texi 2024-12-21 23:32:27.000000000 +0100 +++ gcc-14-20241221/gcc/doc/invoke.texi 2024-12-29 10:09:43.030819622 +0100 @@ -732,7 +732,7 @@ -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 @@ -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 @@ -19132,6 +19132,17 @@ 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, @@ -25150,6 +25161,11 @@ 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 -Naur gcc-14-20241221.orig/gcc/doc/tm.texi gcc-14-20241221/gcc/doc/tm.texi --- gcc-14-20241221.orig/gcc/doc/tm.texi 2024-12-21 23:32:27.000000000 +0100 +++ gcc-14-20241221/gcc/doc/tm.texi 2024-12-29 10:09:43.033169221 +0100 @@ -1066,6 +1066,10 @@ 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 @@ @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 @@ 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 @@ 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 -Naur gcc-14-20241221.orig/gcc/doc/tm.texi.in gcc-14-20241221/gcc/doc/tm.texi.in --- gcc-14-20241221.orig/gcc/doc/tm.texi.in 2024-12-21 23:32:27.000000000 +0100 +++ gcc-14-20241221/gcc/doc/tm.texi.in 2024-12-29 10:09:43.034749203 +0100 @@ -949,6 +949,8 @@ @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 @@ @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 @@ @hook TARGET_RUN_TARGET_SELFTESTS +@hook TARGET_UNREACHABLE_SHOULD_TRAP + @hook TARGET_MEMTAG_CAN_TAG_ADDRESSES @hook TARGET_MEMTAG_TAG_SIZE diff -Naur gcc-14-20241221.orig/gcc/exec-tool.in gcc-14-20241221/gcc/exec-tool.in --- gcc-14-20241221.orig/gcc/exec-tool.in 2024-12-21 23:32:27.000000000 +0100 +++ gcc-14-20241221/gcc/exec-tool.in 2024-12-29 10:09:43.035398529 +0100 @@ -23,6 +23,8 @@ 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 @@ 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 -Naur gcc-14-20241221.orig/gcc/explow.cc gcc-14-20241221/gcc/explow.cc --- gcc-14-20241221.orig/gcc/explow.cc 2024-12-21 23:32:27.000000000 +0100 +++ gcc-14-20241221/gcc/explow.cc 2024-12-29 10:09:43.037238424 +0100 @@ -37,6 +37,7 @@ #include "langhooks.h" #include "except.h" #include "dojump.h" +#include "calls.h" #include "explow.h" #include "expr.h" #include "stringpool.h" @@ -832,6 +833,16 @@ 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 -Naur gcc-14-20241221.orig/gcc/explow.h gcc-14-20241221/gcc/explow.h --- gcc-14-20241221.orig/gcc/explow.h 2024-12-21 23:32:27.000000000 +0100 +++ gcc-14-20241221/gcc/explow.h 2024-12-29 10:09:43.038049707 +0100 @@ -20,6 +20,8 @@ #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); @@ -49,8 +51,13 @@ /* 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 -Naur gcc-14-20241221.orig/gcc/function.cc gcc-14-20241221/gcc/function.cc --- gcc-14-20241221.orig/gcc/function.cc 2024-12-21 23:32:27.000000000 +0100 +++ gcc-14-20241221/gcc/function.cc 2024-12-29 10:09:43.039356692 +0100 @@ -58,8 +58,8 @@ #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 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ ? 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 -Naur gcc-14-20241221.orig/gcc/function.h gcc-14-20241221/gcc/function.h --- gcc-14-20241221.orig/gcc/function.h 2024-12-21 23:32:27.000000000 +0100 +++ gcc-14-20241221/gcc/function.h 2024-12-29 10:09:43.039982310 +0100 @@ -20,6 +20,7 @@ #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 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 -Naur gcc-14-20241221.orig/gcc/ginclude/stddef.h gcc-14-20241221/gcc/ginclude/stddef.h --- gcc-14-20241221.orig/gcc/ginclude/stddef.h 2024-12-21 23:32:27.000000000 +0100 +++ gcc-14-20241221/gcc/ginclude/stddef.h 2024-12-29 10:09:43.041121839 +0100 @@ -428,9 +428,8 @@ /* _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 -Naur gcc-14-20241221.orig/gcc/jit/libgccjit.h gcc-14-20241221/gcc/jit/libgccjit.h --- gcc-14-20241221.orig/gcc/jit/libgccjit.h 2024-12-21 23:32:27.000000000 +0100 +++ gcc-14-20241221/gcc/jit/libgccjit.h 2024-12-29 10:09:43.041919204 +0100 @@ -21,6 +21,9 @@ #define LIBGCCJIT_H #include +#ifdef __APPLE__ +# include /* For ssize_t. */ +#endif #ifdef __cplusplus extern "C" { diff -Naur gcc-14-20241221.orig/gcc/opts.cc gcc-14-20241221/gcc/opts.cc --- gcc-14-20241221.orig/gcc/opts.cc 2024-12-21 23:32:28.000000000 +0100 +++ gcc-14-20241221/gcc/opts.cc 2024-12-29 10:09:43.042774903 +0100 @@ -3289,6 +3289,7 @@ 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 -Naur gcc-14-20241221.orig/gcc/target.def gcc-14-20241221/gcc/target.def --- gcc-14-20241221.orig/gcc/target.def 2024-12-21 23:32:28.000000000 +0100 +++ gcc-14-20241221/gcc/target.def 2024-12-29 10:09:43.044261386 +0100 @@ -4681,6 +4681,13 @@ 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\ prototype as an integral type smaller than @code{int} should actually be\n\ @@ -5134,6 +5141,18 @@ 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\ which is the default value for this hook. You can define this hook to\n\ @@ -5142,6 +5161,18 @@ 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 @@ 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 -Naur gcc-14-20241221.orig/gcc/target.h gcc-14-20241221/gcc/target.h --- gcc-14-20241221.orig/gcc/target.h 2024-12-21 23:32:28.000000000 +0100 +++ gcc-14-20241221/gcc/target.h 2024-12-29 10:09:43.044623799 +0100 @@ -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 -Naur gcc-14-20241221.orig/gcc/targhooks.cc gcc-14-20241221/gcc/targhooks.cc --- gcc-14-20241221.orig/gcc/targhooks.cc 2024-12-21 23:32:28.000000000 +0100 +++ gcc-14-20241221/gcc/targhooks.cc 2024-12-29 10:09:43.045249167 +0100 @@ -162,6 +162,15 @@ } 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) { if (m1 == m2) @@ -877,12 +886,28 @@ } 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) { 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 -Naur gcc-14-20241221.orig/gcc/targhooks.h gcc-14-20241221/gcc/targhooks.h --- gcc-14-20241221.orig/gcc/targhooks.h 2024-12-21 23:32:28.000000000 +0100 +++ gcc-14-20241221/gcc/targhooks.h 2024-12-29 10:09:43.045633162 +0100 @@ -34,6 +34,9 @@ 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 @@ 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 -Naur gcc-14-20241221.orig/gcc/testsuite/g++.dg/cpp0x/pr106435-b.cc gcc-14-20241221/gcc/testsuite/g++.dg/cpp0x/pr106435-b.cc --- gcc-14-20241221.orig/gcc/testsuite/g++.dg/cpp0x/pr106435-b.cc 1970-01-01 01:00:00.000000000 +0100 +++ gcc-14-20241221/gcc/testsuite/g++.dg/cpp0x/pr106435-b.cc 2024-12-29 10:09:43.046337904 +0100 @@ -0,0 +1,17 @@ +// PR c++/106435 +#include "pr106435.h" + +//#include + +Foo::Foo() { + ++num_calls; +// std::cout << "Foo::Foo(this=" << this << ")\n"; +} + +int Foo::func() { +// std::cout << "Foo::func(this=" << this << ")\n"; + return num_calls; +} + +thread_local Foo Bar::foo; +thread_local Foo Bar::baz; diff -Naur gcc-14-20241221.orig/gcc/testsuite/g++.dg/cpp0x/pr106435.C gcc-14-20241221/gcc/testsuite/g++.dg/cpp0x/pr106435.C --- gcc-14-20241221.orig/gcc/testsuite/g++.dg/cpp0x/pr106435.C 1970-01-01 01:00:00.000000000 +0100 +++ gcc-14-20241221/gcc/testsuite/g++.dg/cpp0x/pr106435.C 2024-12-29 10:09:43.047006897 +0100 @@ -0,0 +1,20 @@ +// PR c++/106435 +// { dg-do run { target c++11 } } +// { dg-additional-sources "pr106435-b.cc" } + +#include "pr106435.h" + +int num_calls = 0; + +extern "C" __attribute__((__noreturn__)) void abort(); + +thread_local Foo Bar::bat; + +int main() { + int v = Bar::foo.func(); + if (v != 2) + abort(); + v = Bar::bat.func(); + if (v != 3) + abort(); +} diff -Naur gcc-14-20241221.orig/gcc/testsuite/g++.dg/cpp0x/pr106435.h gcc-14-20241221/gcc/testsuite/g++.dg/cpp0x/pr106435.h --- gcc-14-20241221.orig/gcc/testsuite/g++.dg/cpp0x/pr106435.h 1970-01-01 01:00:00.000000000 +0100 +++ gcc-14-20241221/gcc/testsuite/g++.dg/cpp0x/pr106435.h 2024-12-29 10:09:43.047333393 +0100 @@ -0,0 +1,14 @@ +// PR c++/106435 +#pragma once + +extern int num_calls; +struct Foo { + Foo(); + int func(); +}; + +struct Bar { + thread_local static Foo foo; + thread_local static Foo baz; + thread_local static Foo bat; +}; diff -Naur gcc-14-20241221.orig/gcc/testsuite/g++.target/aarch64/float128-darwin-1.C gcc-14-20241221/gcc/testsuite/g++.target/aarch64/float128-darwin-1.C --- gcc-14-20241221.orig/gcc/testsuite/g++.target/aarch64/float128-darwin-1.C 1970-01-01 01:00:00.000000000 +0100 +++ gcc-14-20241221/gcc/testsuite/g++.target/aarch64/float128-darwin-1.C 2024-12-29 10:09:43.048055218 +0100 @@ -0,0 +1,41 @@ +/* { dg-do run { target { aarch64*-*-darwin* } } } */ +/* { dg-options "-std=c++11 -std=gnu++98" } */ + +#include +#include +#include + +void foo () +{ + float x1 = 1.0q; + double x2 = 1.0q; + long double x3 = 1.0q; + + _Float128 w1 = 0; + __float128 w2 = 0; + + float y1 = w1; // { dg-warning "with greater conversion rank" } + double y2 = w1; // { dg-warning "with greater conversion rank" } + long double y3 = w1; // { dg-warning "with greater conversion rank" } + + float z1 = w2; + double z2 = w2; + long double z3 = w2; +} + +int main () +{ + // Check the correct mangling of floating-point types + if (typeid(float).name() != std::string("f")) + __builtin_abort(); + if (typeid(double).name() != std::string("d")) + __builtin_abort(); + if (typeid(long double).name() != std::string("e")) + __builtin_abort(); + if (typeid(__float128).name() != std::string("g")) + __builtin_abort(); + if (typeid(_Float128).name() != std::string("DF128_")) + __builtin_abort(); + if (typeid(1.0q).name() != std::string("g")) + __builtin_abort(); +} diff -Naur gcc-14-20241221.orig/gcc/testsuite/gcc.target/aarch64/darwin/float128-01.c gcc-14-20241221/gcc/testsuite/gcc.target/aarch64/darwin/float128-01.c --- gcc-14-20241221.orig/gcc/testsuite/gcc.target/aarch64/darwin/float128-01.c 1970-01-01 01:00:00.000000000 +0100 +++ gcc-14-20241221/gcc/testsuite/gcc.target/aarch64/darwin/float128-01.c 2024-12-29 10:09:43.049001457 +0100 @@ -0,0 +1,48 @@ +/* { dg-do run } */ +/* we need this for _Float128. */ +/* { dg-options "-std=gnu99 " } */ +/* { dg-additional-options "-Wfloat-conversion" } */ + +float f1 (__float128 z1, _Float128 z2) +{ + float x, y; + x = z1; /* { dg-warning "conversion from '_Float128' to 'float'" } */ + y = z2; /* { dg-warning "conversion from '_Float128' to 'float'" } */ + return x + y; +} + +__float128 f2 () { + float f = 0.q; + return f; +} + +_Float128 f3 () { + float f = 0.q; + return f; +} + +int main () +{ + __float128 x1 = __builtin_huge_valq (); + __float128 x2 = __builtin_infq (); + + _Float128 y1 = __builtin_huge_valq (); + _Float128 y2 = __builtin_infq (); + + if (!__builtin_isinf (x1)) + __builtin_abort(); + if (!__builtin_isinf (x2)) + __builtin_abort(); + + if (!__builtin_isinf (y1)) + __builtin_abort(); + if (!__builtin_isinf (y2)) + __builtin_abort(); + + if (x1 != x2) + __builtin_abort(); + if (y1 != y2) + __builtin_abort(); + + return 0; +} diff -Naur gcc-14-20241221.orig/gcc/testsuite/gcc.target/aarch64/darwin/float128-02.c gcc-14-20241221/gcc/testsuite/gcc.target/aarch64/darwin/float128-02.c --- gcc-14-20241221.orig/gcc/testsuite/gcc.target/aarch64/darwin/float128-02.c 1970-01-01 01:00:00.000000000 +0100 +++ gcc-14-20241221/gcc/testsuite/gcc.target/aarch64/darwin/float128-02.c 2024-12-29 10:09:43.049215622 +0100 @@ -0,0 +1,101 @@ +/* { dg-do run } */ +/* we need this for _Float128. */ +/* { dg-options "-std=gnu99 " } */ + +void test (__float128 z1, __float128 z2, __float128 z3, __float128 z4) +{ + __float128 w; + + if (!__builtin_isinf (z1)) + __builtin_abort(); + if (__builtin_isnan (z1)) + __builtin_abort(); + if (__builtin_isfinite (z1)) + __builtin_abort(); + if (__builtin_isnormal (z1)) + __builtin_abort(); + if (__builtin_signbit (z1)) + __builtin_abort(); + + if (__builtin_isinf (z2)) + __builtin_abort(); + if (!__builtin_isnan (z2)) + __builtin_abort(); + if (__builtin_isfinite (z2)) + __builtin_abort(); + if (__builtin_isnormal (z2)) + __builtin_abort(); + if (__builtin_signbit (z2)) + __builtin_abort(); + + if (__builtin_isinf (z3)) + __builtin_abort(); + if (!__builtin_isnan (z3)) + __builtin_abort(); + if (__builtin_isfinite (z3)) + __builtin_abort(); + if (__builtin_isnormal (z3)) + __builtin_abort(); + if (__builtin_signbit (z3)) + __builtin_abort(); + + if (__builtin_isinf (z4)) + __builtin_abort(); + if (__builtin_isnan (z4)) + __builtin_abort(); + if (!__builtin_isfinite (z4)) + __builtin_abort(); + if (!__builtin_isnormal (z4)) + __builtin_abort(); + if (__builtin_signbit (z4)) + __builtin_abort(); + + w = __builtin_copysignq (z1, -z4); + if (!__builtin_signbit (w)) + __builtin_abort(); + + w = __builtin_copysignq (z2, -z4); + if (!__builtin_signbit (w)) + __builtin_abort(); + + w = __builtin_copysignq (z3, -z4); + if (!__builtin_signbit (w)) + __builtin_abort(); + + w = __builtin_copysignq (z4, -z4); + if (!__builtin_signbit (w)) + __builtin_abort(); + + w = __builtin_copysignq (z1, -z4); + w = __builtin_fabsq (w); + if (__builtin_signbit (w)) + __builtin_abort(); + + w = __builtin_copysignq (z2, -z4); + w = __builtin_fabsq (w); + if (__builtin_signbit (w)) + __builtin_abort(); + + w = __builtin_copysignq (z3, -z4); + w = __builtin_fabsq (w); + if (__builtin_signbit (w)) + __builtin_abort(); + + w = __builtin_copysignq (z4, -z4); + w = __builtin_fabsq (w); + if (__builtin_signbit (w)) + __builtin_abort(); + +} + +int main () +{ + __float128 x1 = __builtin_infq (); + __float128 x2 = __builtin_nanq (""); + __float128 x3 = __builtin_nansq (""); + __float128 x4 = 41.1094721q; + + test (x1, x2, x3, x4); + + return 0; +} diff -Naur gcc-14-20241221.orig/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp gcc-14-20241221/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp --- gcc-14-20241221.orig/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp 2024-12-21 23:32:37.000000000 +0100 +++ gcc-14-20241221/gcc/testsuite/gcc.target/aarch64/sme/aarch64-sme.exp 2024-12-29 10:09:43.049836240 +0100 @@ -24,6 +24,11 @@ return } +# Exit immediately if this is Darwin (for now). +if {[istarget *-*-darwin*] } { + return +} + # Load support procs. load_lib gcc-dg.exp diff -Naur gcc-14-20241221.orig/libgcc/config/aarch64/__arm_sme_state.S gcc-14-20241221/libgcc/config/aarch64/__arm_sme_state.S --- gcc-14-20241221.orig/libgcc/config/aarch64/__arm_sme_state.S 2024-12-21 23:33:00.000000000 +0100 +++ gcc-14-20241221/libgcc/config/aarch64/__arm_sme_state.S 2024-12-29 10:09:43.051232890 +0100 @@ -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 @@ mov x0, 0 mov x1, 0 ret -END (__arm_sme_state) +ENDm ASMNAME(__arm_sme_state) diff -Naur gcc-14-20241221.orig/libgcc/config/aarch64/__arm_tpidr2_restore.S gcc-14-20241221/libgcc/config/aarch64/__arm_tpidr2_restore.S --- gcc-14-20241221.orig/libgcc/config/aarch64/__arm_tpidr2_restore.S 2024-12-21 23:33:00.000000000 +0100 +++ gcc-14-20241221/libgcc/config/aarch64/__arm_tpidr2_restore.S 2024-12-29 10:09:43.051384597 +0100 @@ -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 @@ 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 -Naur gcc-14-20241221.orig/libgcc/config/aarch64/__arm_tpidr2_save.S gcc-14-20241221/libgcc/config/aarch64/__arm_tpidr2_save.S --- gcc-14-20241221.orig/libgcc/config/aarch64/__arm_tpidr2_save.S 2024-12-21 23:33:00.000000000 +0100 +++ gcc-14-20241221/libgcc/config/aarch64/__arm_tpidr2_save.S 2024-12-29 10:09:43.051613844 +0100 @@ -35,10 +35,15 @@ 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 @@ 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 -Naur gcc-14-20241221.orig/libgcc/config/aarch64/__arm_za_disable.S gcc-14-20241221/libgcc/config/aarch64/__arm_za_disable.S --- gcc-14-20241221.orig/libgcc/config/aarch64/__arm_za_disable.S 2024-12-21 23:33:00.000000000 +0100 +++ gcc-14-20241221/libgcc/config/aarch64/__arm_za_disable.S 2024-12-29 10:09:43.051793092 +0100 @@ -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 @@ .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 @@ 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 -Naur gcc-14-20241221.orig/libgcc/config/aarch64/aarch64-asm.h gcc-14-20241221/libgcc/config/aarch64/aarch64-asm.h --- gcc-14-20241221.orig/libgcc/config/aarch64/aarch64-asm.h 2024-12-21 23:33:00.000000000 +0100 +++ gcc-14-20241221/libgcc/config/aarch64/aarch64-asm.h 2024-12-29 10:09:43.051971465 +0100 @@ -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 @@ # 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 -Naur gcc-14-20241221.orig/libgcc/config/aarch64/lse.S gcc-14-20241221/libgcc/config/aarch64/lse.S --- gcc-14-20241221.orig/libgcc/config/aarch64/lse.S 2024-12-21 23:33:00.000000000 +0100 +++ gcc-14-20241221/libgcc/config/aarch64/lse.S 2024-12-29 10:09:43.052215129 +0100 @@ -62,7 +62,7 @@ #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 @@ # error #endif +#undef L #if MODEL == 1 # define SUFF _relax # define A @@ -167,32 +168,21 @@ #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 @@ #endif -ENDFN NAME(cas) +ENDm ASMNAME (NAME(cas)) #endif #ifdef L_swp @@ -255,7 +245,7 @@ # 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 @@ BARRIER ret -ENDFN NAME(swp) +ENDm ASMNAME (NAME (swp)) #endif #if defined(L_ldadd) || defined(L_ldclr) \ @@ -299,7 +289,7 @@ # 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 @@ BARRIER ret -ENDFN NAME(LDNM) +ENDm ASMNAME (NAME (LDNM)) #endif diff -Naur gcc-14-20241221.orig/libgcc/config/aarch64/sfp-machine.h gcc-14-20241221/libgcc/config/aarch64/sfp-machine.h --- gcc-14-20241221.orig/libgcc/config/aarch64/sfp-machine.h 2024-12-21 23:33:00.000000000 +0100 +++ gcc-14-20241221/libgcc/config/aarch64/sfp-machine.h 2024-12-29 10:09:43.052507584 +0100 @@ -124,6 +124,27 @@ /* 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 -Naur gcc-14-20241221.orig/libgcc/config/aarch64/t-darwin gcc-14-20241221/libgcc/config/aarch64/t-darwin --- gcc-14-20241221.orig/libgcc/config/aarch64/t-darwin 1970-01-01 01:00:00.000000000 +0100 +++ gcc-14-20241221/libgcc/config/aarch64/t-darwin 2024-12-29 10:09:43.052653707 +0100 @@ -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 -Naur gcc-14-20241221.orig/libgcc/config.host gcc-14-20241221/libgcc/config.host --- gcc-14-20241221.orig/libgcc/config.host 2024-12-21 23:33:00.000000000 +0100 +++ gcc-14-20241221/libgcc/config.host 2024-12-29 10:09:43.050739229 +0100 @@ -82,7 +82,7 @@ cpu_type=m32c tmake_file=t-fdpbit ;; -aarch64*-*-*) +aarch64*-*-* | arm64*-*-*) cpu_type=aarch64 ;; alpha*-*-*) @@ -277,7 +277,7 @@ 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" @@ -421,6 +421,15 @@ 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" @@ -728,14 +737,14 @@ 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) @@ -1218,12 +1227,14 @@ # 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 -Naur gcc-14-20241221.orig/libitm/config/aarch64/sjlj.S gcc-14-20241221/libitm/config/aarch64/sjlj.S --- gcc-14-20241221.orig/libitm/config/aarch64/sjlj.S 2024-12-21 23:33:23.000000000 +0100 +++ gcc-14-20241221/libitm/config/aarch64/sjlj.S 2024-12-29 10:09:50.499102063 +0100 @@ -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 @@ /* 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 @@ 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 @@ 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 -Naur gcc-14-20241221.orig/libitm/configure.tgt gcc-14-20241221/libitm/configure.tgt --- gcc-14-20241221.orig/libitm/configure.tgt 2024-12-21 23:33:23.000000000 +0100 +++ gcc-14-20241221/libitm/configure.tgt 2024-12-29 10:09:50.500553422 +0100 @@ -50,7 +50,7 @@ # 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 -Naur gcc-14-20241221.orig/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d gcc-14-20241221/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d --- gcc-14-20241221.orig/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d 2024-12-21 23:33:23.000000000 +0100 +++ gcc-14-20241221/libphobos/libdruntime/core/internal/gc/impl/conservative/gc.d 2024-12-29 10:09:50.503744052 +0100 @@ -30,8 +30,13 @@ /***************************************************/ 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;