From bc07f9c3bd99ddf07ba967a9037c99c8f05e6a7d Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Mon, 3 Aug 2020 22:46:40 +0100 Subject: [PATCH] aarch64, Darwin: Initial port including D.2, D.4. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Base build changes to Darwin common code. It seems that the arm64 port will not make use of traditional mach-o pic but instead use a GOT - as such, the target-dependent parts of darwin.c are made NOP for this. We still expect to apply other Mach-O constraints. Most of the change is about the support for giving the user an error message when they try to invoke the compiler with multiple -arch flags. There is no provision in the initial port to handle the arm64_32 variant. This is (understood to be) only used in watchOS which we are not supporting initially. + No machopic indirections for Arm64 personality/LSDA entries. As for x86-64 (64bit code), the personality and LSDA .cfi_xxx entries do not require an indirection in the compiler code. + Accept arm64 in arch flags, for aarch64 compilers. We were checking for this and complaining if it was present for an X86 or PPC compiler, but we also need to accept (and ignore it) for an aarch64 / Arm64 compiler. This is enough to make a buildable cross-compiler on x86_64 Darwin and compile trivial codes. Although the link phase might not succeed - one can link objects manually and get an exe that works. There's an initial implementation of the rule changes for darwinpcs. There's an initial (pretty hacky) set of changes to deal with the post-fix assembly notation for Mach-O relocs. There are a few places where ELF was assumed, and we need to prevent incompatible output for Mach-O (probably there are other ways to do this). + Pick up atomic builtins from the libgcc.a CHECKME: should these be exported from the shared lib? (at present, that doesn't seem to be ideal). Look at what's done for the clang toolchain. + long double is DF not TF :( We will need to figure out what to do about supporting XXX*16 a some point. + Fix ptrdiff type. This was wrong (the size needs to track the 64-bitness and was failing to do so. + Add in driver sef-specs. Ensure that we issue the Darwin driver self specs and set the mabi and little-endian flags. clang accepts -mabi=darwinpcs so we allow that (but it means the same as lp64 at present since the target is determined at configuration time). + Fix an other build error for Darwin. Since we don't emit ELF function decorations this means that some of the variables are unused. + Initial implementation for EH without .cfi_xxxx While we can (most likely) make the .cfi_ codegen work, there are comments in the Ada code that suggest the capabilities of the unwinder are somewhat restricted. At least this option allows for the case of using libgcc_eh when an exe is self-contained. + Just whitespace fixes NFC. + We don't yet support TF, so reject 'q' suffix. The floating point literal suffix 'q' is specifically stated to be used for _float128, which we don't yet support. + Connect up the subtarget builtins i.e. __builtin_cfstring. The idea of OS-specific subtarget builtins doesn't fit too well with the general organisation of the aarch64 ones. What this does is to add it into the "GENERAL" class (but the darwin-specific code has no idea that the builtin code number has subfields). + Build fix for subtarget builtins. One either needs to define SUBTARGET_INIT_BUILTINS to empty or conditionalize its use + Connect up the sub-target attribute table. Darwin has some Mach-O / OS attributes, add these to the end of the aarch64 set.. + Connect up the pragma table. Darwin has some Mach-O / OS-specific pragmas, connected these to the end of the aarch64 table. gcc/ChangeLog: * config.gcc: Handle aarch64 and arm64 darwin. * config/aarch64/aarch64-protos.h (enum aarch64_symbol_type): Provide for symbol classifications for Mach-O. * config/aarch64/aarch64.c (aarch64_elf_asm_destructor): Don't define these for Mach-O (it's not ELF!). (handle_aarch64_vector_pcs_attribute): Handle darwinpcs. (aarch64_reg_save_mode): Likewise. (aarch64_load_symref_appropriately): Handle Mach-O. (aarch64_expand_mov_immediate): Likewise. (aarch64_layout_arg): Handle darwinpcs rules. (aarch64_function_arg): Likewise. (aarch64_init_cumulative_args): Likewise. (aarch64_function_arg_advance): Likewise. (aarch64_print_operand): Likewise (we can probably do better). (aarch64_print_address_internal): Likewise. (aarch64_asm_output_labelref): Likewise. (initialize_aarch64_code_model): Accept large PIC for Mach-O - of course, that doesn't mean it works. (aarch64_classify_symbol): Only emit ELF directives if they are available. (aarch64_declare_function_name): Likewise. (aarch64_asm_output_alias): Likewise. (aarch64_sls_emit_shared_blr_thunks): Likewise. (TARGET_ASM_UNALIGNED_HI_OP): New. (TARGET_ASM_UNALIGNED_SI_OP): New. (TARGET_ASM_UNALIGNED_DI_OP): New. * config/aarch64/aarch64.h (TARGET_MACHO): Declare as 0. (enum arm_pcs): Add darwinpcs. (SUBTARGET_EXTRA_SPECS): New. (EXTRA_SPECS): Allow for sub-target specs. * config/aarch64/aarch64.md (unspec enum): Add UNSPEC_MACHOPIC_OFFSET. (ldr_got_small_): Allow for postfix assembler syntax. (ldr_got_small_): Likewise. * config/aarch64/darwin.h: New file. * config/aarch64/t-aarch64-darwin: New file. Darwin, Arm64: Adjust NO_PIE spec for aarch64. Since aarch64 Darwin does not permit no-PIE, the linker warns that the option is ignored. Adjust the spec so that we do not send the option to the linker. gcc/ChangLog: * config/aarch64/darwin.h (DARWIN_NOPIE_SPEC): Revise for the aarch64 port. Signed-off-by: Iain Sandoe Darwin, Arm64 : Allow m64 on the command line. It seems that some people have makefiles etc. that put '-m64' for arm64 Darwin. This is allowed by clang. For the GCC version we make it an alias of -mabi=darwinpcs. aarch64, Darwin: Enable section anchors on -fsection-anchor. This is an experimental feature and might well require amendment to cater for constraints of the ld64 atom model. TODO: in supprot of that comment: 1. make the anchor base linker-visible 2. ensure that all offsets from that are local symbols. Signed-off-by: Iain Sandoe gcc/ChangeLog: * config/aarch64/darwin.h (TARGET_ASM_OUTPUT_ANCHOR, TARGET_USE_ANCHORS_FOR_SYMBOL_P, DARWIN_SECTION_ANCHORS): New. * config/aarch64/aarch64.c (aarch64_darwin_use_anchor_for_sym_p): Delete. (TARGET_USE_ANCHORS_FOR_SYMBOL_P): Delete. aarch64, Darwin: Ignore mdynamic-no-pic. Match the behaviour of clang in ignoring the setting of mdynamic-no-pic either on the command line or as an option to cc1. Signed-off-by: Iain Sandoe Darwin, Arm64 : Assign a register for the static chain. At present, we do not have a workable solution for trampolines for the Darwin Arm64 port. Executable stack is not an option and the advice from Arm is not to use any lower address bits to signal that we have a descriptor. It is possible that we might be able to load some remappable object (e.g. a dylib) - but the details there still have to be resolved. In any case, we need a usable static chain - and the port has that assigned to R18 by default - which is the platform register in darwinpcs. It's uncertain whether R16/R17 are actually used in the darwinpcs in the role of support for branch islanding. The AAPCS64 use as IP0/1 is conditional on ELF relocations, so perhaps irrelevant to Darwin. Using R16 does not conflict with the existing (non-functional) trampoline code. lots of TODOs here. aarch64, Darwin: Use darwin_binds_local_p for the target. We dind locally for PIC code (the default) on Darwin so that the default implementations will not work as expected. Signed-off-by: Iain Sandoe gcc/ChangeLog: * config/aarch64/darwin.h (TARGET_BINDS_LOCAL_P): New. Use darwin_bind_local_p() for this. aarhc64, Darwin: Do not give file-scope variables extra alignment. At lest, not until we determine the consequences of inter-operating with clang. Addresses Issue #68 Signed-off-by: Iain Sandoe gcc/ChangeLog: * config/aarch64/darwin.h (DATA_ALIGNMENT): Just use the alignment of the underlying object for now. aarch64 : Cast print value per format description. Fixes a build fail. Darwin, Arm64 : Truncate char immediates in vector initializers to mode size. Darwin has signed chars, so that 8b immediates > 127 appear to be negative which produce large positive (out of assembler range) values when inspected by UINTVAL (). This patch truncates the values to the bitrange of the mode of the input. Fixes github issue 15. Darwin, Arm64 : Implement darwinpcs mangling for va_list. The darwinpcs says this must be mangled as char * (Pc) and not presented in the std:: namespace. aarch64, Darwin: Implement darwinpcs D.2 This allows us to pass items smaller than 8 bytes with their natural alignment packed as appropriate into the stack. This means that multiple args can use one AAPCS64 stack slot. We continue to account the stack in terms of words, but for darwinpcs the last word in the cumulative arguments is filled incrementally. So the allocation will remain 8-byte-wise, but the filling can be 1-byte aligned. This also means that darwinpcs needs to override the standard hook for TARGET_FUNCTION_ARG_ROUND_BOUNDARY. It turns out that trying to implement the Darwin PCS as CC variation is a can of worms and, since the target is chosen at configure time, not actually doing anything useful. Fallout from this included clobbering of callee saved regs etc. So - for now at least - back out of this and use the AAPCS64 as the darwinpcs, with the TARGET_MACHO flag chosing the variant. It is likely that we need to separate things more, since we haven't fully dealt with the variadic functions issue properly. Darwin, Arm64 : Additional change for darwincpcs D.4. We are allowed to pass 16bytes in regs even if the starting reg is not even-numbered. aarch64, Darwin: Adapt shared blr thunks for Darwin ABI. For Darwin we just emit the thunks as wek defintions. TODO: really we should emit this stuff before debug. Signed-off-by: Iain Sandoe gcc/ChangeLog: * config/aarch64/aarch64.c: Emit shared blr thunks as weak definitions. aarch64, Darwin: Initial support for relocations and asm syntax. At present, we are generating _foo+123@PAGE and we should have _foo@PAGE+123 etc. This can probably be fixed better with symbol flags and use of ASM_OUTPUT_SYMBOL_REF but that needs more work. Right now we're also stuck with GCC producing _foo@PAGE-1 as an example ... and the assmbler doesn't like it. Darwin, Arm64 : Make code label references use PAGE relocs We need to be able to refer to Lxxxx labels in libgnat. Darwin, Arm64 : Avoid negative offsets in PAGE relocs. It's not clear to me whether this is a mistake in the LLVM backend or a genuine restriction in the relocation (the wording of the addend reloc says neither 'signed' nor 'unsigned'. This works around this by making known negative offsets non-legitimate and composing the address by: ardp foo@PAGE add dest, temp, foo@PAGEOFF add dest, dest, neg_offset + We are now handling negative addends. Part of the code attempting to deal with the "PAGE-N" issue was to reject negative offsets in the legitimizers - actually, this wasn't effective anyway. We've now got code catching the cases and using a separate sum instruction, so delete these. aarch64, Darwin: Constrain page offset values to fit in the relocation. This fixes issue #52. We need to constrain the offsets in the @PAGE/@PAGEOFFS relocations to fit in a 24bit field - +/- 8Mb. Signed-off-by: Iain Sandoe gcc/ * config/aarch64/aarch64.c (aarch64_load_symref_appropriately): If the offset will not fit into the relocation, then rewrite it as an addition. aarch64, Darwin: Account for UNSPEC_SALT_ADDR in symbol output. We were omitting the postfix relocation indicator because the code was falling back to the default output when a symbol was wrapped in an unspec SALT_ADDR. fixes issue #54. Signed-off-by: Iain Sandoe aarch64, Darwin: Allow for indexed address forms for PAGE+offset. We have been generating code like: adrp x0, sym@PAGE add x0, x0, sym@PAGEOFFS ld d0, [x0] now we generate: adrp x0, sym@PAGE ld d0 [x0, #sym@PAGEOFFS] and simmilarly for GOT accesses. Signed-off-by: Iain Sandoe gcc/ChangeLog: * config/aarch64/aarch64.c (aarch64_classify_address): Allow Mach-O PC relative accesses to constant pool and other defined objects. (aarch64_classify_symbol): Check for constant pool SYMREFs and only if it is not one check the Mach-O SYMBOL flags. aarch64, Darwin: Initial support for variadic function differences. These use the simpler char * version - but it remains to be seen if we need a non-standard rendition to cater for any amusing platform differences. Darwin, Arm64 : Adjust cases where stack spills pack differently. + Temporary handling for complex values. Complex values with a total size less than one stack slot might conceivably be packed in the same manner as other small values. However, this is not done - and we need to override the process for them. + Don't pack small structs either. Darwinpcs doesn't mention some things - and one is small structs. These are put into regs - but, when they spill to the stack, they don't pack in the manner of char, int et. al. + Handle HFA cases that have packed stack layout. bleah! (not sure this is complete). + Exclude unions from packing rule. + Hide an unused function. We are not using aarch64_vfp_is_call_candidate so wrap it in an #ifdef. + Fix a build error. Drop an unused var. Darwin, Arm64 : Account for stack addresses less aligned than DI. darwinpcs, packs some stack items, which means that one cannot guarantee that they are aligned to DI. Check for these cases and reject PRFM instructions then. Note, that this generally results in use of an extra temporary reg. clang uses 'PRFUM' instructions in those cases, so we have a missed optimisation opportunity (low priority). fixes issue #16. aarch64, Darwin: Handle prfm/prufm to support LLVM assemblers. 1. aarch64, Darwin : Restrict offsets for prfm. The current LLVM-based assemblers reject offsets that are not suitable for prfm as written in the local section. However, there is advice elsewhere that says that this category of instruction should attempt to use the 9bit unscaled version before falling back to the scaled one. In the short-term reject values that the assembler will not accept. This partially addresses Issue #43 gcc/ * config/aarch64/aarch64.c (aarch64_address_valid_for_prefetch_p): Reject values incompatible with pfrum and out of range for pfrm. For Mach-O, reject values that require prfum. 2. aarch64, Darwin : Match conditions for a PRFUM insn. This unpessimizes the prefetch cases for Darwin where the assembler is not able to substitute the prfum instructions automagically. This improves the fix for Issue #43. * config/aarch64/aarch64-protos.h * config/aarch64/aarch64.c * config/aarch64/aarch64.md * config/aarch64/constraints.md * config/aarch64/predicates.md Darwin, aarch64: Document the ABI (darwinpcs) and changes from that. Darwin,aarch64: Limit PAGE offsets to positive values for Darwin. Because of an assembler/linker bug, we cannot currently accept negative offset values for PAGEOFF relocations. While we were already catching this in expansion, there are cases where combine can produce values that need to be excluded. So reject symbol_refs with negative offsets. --- gcc/config.gcc | 5 + gcc/config/aarch64/aarch64-builtins.cc | 10 + gcc/config/aarch64/aarch64-c.cc | 4 + gcc/config/aarch64/aarch64-protos.h | 10 + gcc/config/aarch64/aarch64.cc | 543 ++++++++++++++++-- gcc/config/aarch64/aarch64.h | 17 +- gcc/config/aarch64/aarch64.md | 41 +- gcc/config/aarch64/aarch64.opt | 7 + gcc/config/aarch64/constraints.md | 9 +- gcc/config/aarch64/darwin.h | 270 +++++++++ gcc/config/aarch64/darwinpcs.md | 455 +++++++++++++++ .../aarch64/falkor-tag-collision-avoidance.cc | 2 +- gcc/config/aarch64/predicates.md | 15 + gcc/config/aarch64/t-aarch64-darwin | 25 + gcc/config/darwin-driver.cc | 27 +- gcc/config/darwin.cc | 11 +- gcc/config/darwin.h | 1 + 17 files changed, 1408 insertions(+), 44 deletions(-) create mode 100644 gcc/config/aarch64/darwin.h create mode 100644 gcc/config/aarch64/darwinpcs.md create mode 100644 gcc/config/aarch64/t-aarch64-darwin diff --git a/gcc/config.gcc b/gcc/config.gcc index 8fb9f8565968..3ac0125e9dc5 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -1134,6 +1134,11 @@ aarch64*-*-elf | aarch64*-*-fuchsia* | aarch64*-*-rtems*) done TM_MULTILIB_CONFIG=`echo $TM_MULTILIB_CONFIG | sed 's/^,//'` ;; +aarch64-*-darwin* | arm64-*-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" + ;; aarch64*-*-freebsd*) tm_file="${tm_file} elfos.h ${fbsd_tm_file}" tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-freebsd.h" diff --git a/gcc/config/aarch64/aarch64-builtins.cc b/gcc/config/aarch64/aarch64-builtins.cc index b53308259282..df247939a727 100644 --- a/gcc/config/aarch64/aarch64-builtins.cc +++ b/gcc/config/aarch64/aarch64-builtins.cc @@ -785,6 +785,8 @@ enum aarch64_builtins AARCH64_RBIT, AARCH64_RBITL, AARCH64_RBITLL, + /* OS-specific */ + AARCH64_BUILTIN_CFSTRING, AARCH64_BUILTIN_MAX }; @@ -2013,6 +2015,14 @@ aarch64_general_init_builtins (void) aarch64_init_memtag_builtins (); } +void +aarch64_init_subtarget_builtins (void) +{ +#ifdef SUBTARGET_INIT_BUILTINS + SUBTARGET_INIT_BUILTINS; +#endif +} + /* Implement TARGET_BUILTIN_DECL for the AARCH64_BUILTIN_GENERAL group. */ tree aarch64_general_builtin_decl (unsigned code, bool) diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc index e296c73350f1..82a88f33d94e 100644 --- a/gcc/config/aarch64/aarch64-c.cc +++ b/gcc/config/aarch64/aarch64-c.cc @@ -357,4 +357,8 @@ aarch64_register_pragmas (void) targetm.check_builtin_call = aarch64_check_builtin_call; c_register_pragma ("GCC", "aarch64", aarch64_pragma_aarch64); + +#ifdef REGISTER_SUBTARGET_PRAGMAS + REGISTER_SUBTARGET_PRAGMAS (); +#endif } diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 1a71f0228413..0abf61d58de7 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -108,6 +108,14 @@ enum aarch64_symbol_type SYMBOL_TLSLE24, SYMBOL_TLSLE32, SYMBOL_TLSLE48, + SYMBOL_MO_SMALL_ABS, + SYMBOL_MO_SMALL_PCR, + SYMBOL_MO_SMALL_GOT, + SYMBOL_MO_SMALL_TLS, + SYMBOL_MO_LARGE_ABS, + SYMBOL_MO_LARGE_PCR, + SYMBOL_MO_LARGE_GOT, + SYMBOL_MO_LARGE_TLS, SYMBOL_FORCE_TO_MEM }; @@ -755,6 +763,7 @@ void aarch64_post_cfi_startproc (void); poly_int64 aarch64_initial_elimination_offset (unsigned, unsigned); int aarch64_get_condition_code (rtx); bool aarch64_address_valid_for_prefetch_p (rtx, bool); +bool aarch64_address_valid_for_unscaled_prefetch_p (rtx, bool); bool aarch64_bitmask_imm (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); @@ -979,6 +988,7 @@ void aarch64_override_options_internal (struct gcc_options *); const char *aarch64_general_mangle_builtin_type (const_tree); void aarch64_general_init_builtins (void); +void aarch64_init_subtarget_builtins (void); tree aarch64_general_fold_builtin (unsigned int, tree, unsigned int, tree *); gimple *aarch64_general_gimple_fold_builtin (unsigned int, gcall *, gimple_stmt_iterator *); diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index a8845a55b9e7..6e88cfe4254f 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -293,8 +293,10 @@ static bool aarch64_vfp_is_call_or_return_candidate (machine_mode, const_tree, machine_mode *, int *, bool *, bool); +#if !TARGET_MACHO static void aarch64_elf_asm_constructor (rtx, int) ATTRIBUTE_UNUSED; static void aarch64_elf_asm_destructor (rtx, int) ATTRIBUTE_UNUSED; +#endif static void aarch64_override_options_after_change (void); static bool aarch64_vector_mode_supported_p (machine_mode); static int aarch64_address_cost (rtx, machine_mode, addr_space_t, bool); @@ -2745,6 +2747,9 @@ static const struct attribute_spec aarch64_attribute_table[] = { "Advanced SIMD type", 1, 1, false, true, false, true, NULL, NULL }, { "SVE type", 3, 3, false, true, false, true, NULL, NULL }, { "SVE sizeless type", 0, 0, false, true, false, true, NULL, NULL }, +#ifdef SUBTARGET_ATTRIBUTE_TABLE + SUBTARGET_ATTRIBUTE_TABLE, +#endif { NULL, 0, 0, false, false, false, false, NULL, NULL } }; @@ -3960,7 +3965,7 @@ aarch64_hard_regno_mode_ok (unsigned regno, machine_mode mode) if (known_le (GET_MODE_SIZE (mode), 8)) return true; if (known_le (GET_MODE_SIZE (mode), 16)) - return (regno & 1) == 0; + return (regno & 1) == 0 || TARGET_MACHO; /* darwinpcs D.4 */ } else if (FP_REGNUM_P (regno)) { @@ -4492,6 +4497,7 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm, switch (type) { case SYMBOL_SMALL_ABSOLUTE: + case SYMBOL_MO_SMALL_PCR: { /* In ILP32, the mode of dest can be either SImode or DImode. */ rtx tmp_reg = dest; @@ -4502,6 +4508,21 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm, if (can_create_pseudo_p ()) tmp_reg = gen_reg_rtx (mode); + if (TARGET_MACHO) + { + rtx sym, off; + split_const (imm, &sym, &off); + /* Negative offsets don't work, whether by intention is TBD. */ + if (INTVAL (off) < 0 || INTVAL (off) > 8 * 1024 * 1024) + { + emit_move_insn (tmp_reg, gen_rtx_HIGH (mode, sym)); + emit_insn (gen_add_losym (dest, tmp_reg, sym)); + /* FIXME: add the SI option if/when we support ilp32. */ + emit_insn (gen_adddi3 (dest, dest, off)); + return; + } + /* else small enough positive offset is OK. */ + } emit_move_insn (tmp_reg, gen_rtx_HIGH (mode, copy_rtx (imm))); emit_insn (gen_add_losym (dest, tmp_reg, imm)); return; @@ -4585,6 +4606,7 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm, return; } + case SYMBOL_MO_SMALL_GOT: case SYMBOL_SMALL_GOT_4G: emit_insn (gen_rtx_SET (dest, imm)); return; @@ -6646,6 +6668,7 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm) case SYMBOL_SMALL_TLSIE: case SYMBOL_SMALL_GOT_28K: case SYMBOL_SMALL_GOT_4G: + case SYMBOL_MO_SMALL_GOT: case SYMBOL_TINY_GOT: case SYMBOL_TINY_TLSIE: if (const_offset != 0) @@ -6659,6 +6682,7 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm) /* FALLTHRU */ case SYMBOL_SMALL_ABSOLUTE: + case SYMBOL_MO_SMALL_PCR: case SYMBOL_TINY_ABSOLUTE: case SYMBOL_TLSLE12: case SYMBOL_TLSLE24: @@ -7238,6 +7262,7 @@ aarch64_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED) gcc_unreachable (); } +#if !TARGET_MACHO static bool aarch64_vfp_is_call_candidate (cumulative_args_t pcum_v, machine_mode mode, const_tree type, int *nregs) @@ -7247,6 +7272,7 @@ aarch64_vfp_is_call_candidate (cumulative_args_t pcum_v, machine_mode mode, &pcum->aapcs_vfp_rmode, nregs, NULL, pcum->silent_p); } +#endif /* Given MODE and TYPE of a function argument, return the alignment in bits. The idea is to suppress any stronger alignment requested by @@ -7386,13 +7412,25 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg) /* No frontends can create types with variable-sized modes, so we shouldn't be asked to pass or return them. */ size = GET_MODE_SIZE (mode).to_constant (); + 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); /* allocate_ncrn may be false-positive, but allocate_nvrn is quite reliable. @@ -7407,7 +7445,13 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg) if (!pcum->silent_p && !TARGET_FLOAT) aarch64_err_no_fpadvsimd (mode); - if (nvrn + nregs <= NUM_FP_ARG_REGS) + if (TARGET_MACHO + && !arg.named) + { + pcum->aapcs_nextnvrn = NUM_FP_ARG_REGS; + goto on_stack; + } + else if (nvrn + nregs <= NUM_FP_ARG_REGS) { pcum->aapcs_nextnvrn = nvrn + nregs; if (!aarch64_composite_type_p (type, mode)) @@ -7453,10 +7497,18 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg) /* C6 - C9. though the sign and zero extension semantics are handled elsewhere. This is the case where the argument fits entirely general registers. */ + if (allocate_ncrn && (ncrn + nregs <= NUM_ARG_REGS)) { gcc_assert (nregs == 0 || nregs == 1 || nregs == 2); + if (TARGET_MACHO + && !arg.named) + { + pcum->aapcs_nextncrn = NUM_ARG_REGS; + goto on_stack; + } + /* C.8 if the argument has an alignment of 16 then the NGRN is rounded up to the next even number. */ if (nregs == 2 @@ -7466,7 +7518,9 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg) alignment nregs should be > 2 and therefore it should be passed by reference rather than value. */ && (aarch64_function_arg_alignment (mode, type, &abi_break) - == 16 * BITS_PER_UNIT)) + == 16 * BITS_PER_UNIT) + /* Darwin PCS deletes rule C.8. */ + && !TARGET_MACHO) { if (abi_break && warn_psabi && currently_expanding_gimple_stmt) inform (input_location, "parameter passing for argument of type " @@ -7523,10 +7577,60 @@ aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg) /* The argument is passed on stack; record the needed number of words for this argument and align the total size if necessary. */ on_stack: - pcum->aapcs_stack_words = size / UNITS_PER_WORD; - if (aarch64_function_arg_alignment (mode, type, &abi_break) - == 16 * BITS_PER_UNIT) + unsigned int align = aarch64_function_arg_alignment (mode, type, &abi_break); + + if (TARGET_MACHO) + { + /* Darwin does not round up the allocation for smaller entities to 8 + bytes. It only requires the natural alignment for these. There + was no darwinpcs for GCC 9, so neither the implementation change + nor the warning should fire here. + + size is rounded up to 8 bytes, so will account for enough slots to + accommodate the entire argument - potentially, with some padding + at the end. When the current position is 0 - any allocation needs + a stack slot. CHECKME: do we need to align 16byte entities? + + but we don't do this for: + * unnamed parms in variadic functions + * complex types smaller than 4 bytes + each get their own slot. */ + if (!arg.named + || 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; + /* We skip the re-alignment for 16byte things, since we currently + assume that the darwinpcs doesn't force such alignment. */ + return; + } + + if (pcum->darwinpcs_sub_word_pos == 0) + pcum->aapcs_stack_words = size / UNITS_PER_WORD; + + int new_pos + = ROUND_UP (pcum->darwinpcs_sub_word_pos, align / BITS_PER_UNIT); + if (new_pos >= UNITS_PER_WORD) + { + /* We are not catering for the possible 16byte alignment bump. */ + pcum->aapcs_stack_words += 1; + new_pos = 0; + } + pcum->darwinpcs_sub_word_offset = new_pos; + new_pos += pcum->darwinpcs_stack_bytes; + if (new_pos > UNITS_PER_WORD) + pcum->aapcs_stack_words += new_pos / UNITS_PER_WORD; + pcum->darwinpcs_sub_word_pos = new_pos % UNITS_PER_WORD; + return; + } + + pcum->aapcs_stack_words = size / UNITS_PER_WORD; + if (align == 16 * BITS_PER_UNIT) { int new_size = ROUND_UP (pcum->aapcs_stack_size, 16 / UNITS_PER_WORD); if (pcum->aapcs_stack_size != new_size) @@ -7579,7 +7683,11 @@ aarch64_init_cumulative_args (CUMULATIVE_ARGS *pcum, pcum->aapcs_arg_processed = false; pcum->aapcs_stack_words = 0; pcum->aapcs_stack_size = 0; + pcum->darwinpcs_stack_bytes = 0; + pcum->darwinpcs_sub_word_offset = 0; + pcum->darwinpcs_sub_word_pos = 0; pcum->silent_p = silent_p; + pcum->aapcs_vfp_rmode = VOIDmode; if (!silent_p && !TARGET_FLOAT @@ -7618,8 +7726,9 @@ aarch64_function_arg_advance (cumulative_args_t pcum_v, || pcum->pcs_variant == ARM_PCS_SVE) { aarch64_layout_arg (pcum_v, arg); - gcc_assert ((pcum->aapcs_reg != NULL_RTX) - != (pcum->aapcs_stack_words != 0)); + gcc_assert (TARGET_MACHO + || (pcum->aapcs_reg != NULL_RTX) + != (pcum->aapcs_stack_words != 0)); pcum->aapcs_arg_processed = false; pcum->aapcs_ncrn = pcum->aapcs_nextncrn; pcum->aapcs_nvrn = pcum->aapcs_nextnvrn; @@ -7637,12 +7746,17 @@ aarch64_function_arg_regno_p (unsigned regno) || (FP_REGNUM_P (regno) && regno < V0_REGNUM + NUM_FP_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, parameters get their natural alignment (up to the + STACK_BOUNDARY). Therefore, the stack can be aligned less than 8 + bytes after a smaller aligned type is placed. However, the stack will + always be counted in PARM_BOUNDARY chunks, darwinpcs will just fill + the last allocated chunk with several args, potentially. */ static unsigned int aarch64_function_arg_boundary (machine_mode mode, const_tree type) @@ -7650,6 +7764,20 @@ aarch64_function_arg_boundary (machine_mode mode, const_tree type) unsigned int abi_break; unsigned int alignment = aarch64_function_arg_alignment (mode, type, &abi_break); +#if TARGET_MACHO + /* Temporary fudge to put some non-scalar types in distinct stack slots. */ + 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); if (abi_break & warn_psabi) { @@ -7660,8 +7788,21 @@ aarch64_function_arg_boundary (machine_mode mode, const_tree type) } return alignment; +#endif } +#if TARGET_MACHO +/* Implement TARGET_FUNCTION_ARG_ROUND_BOUNDARY for darwinpcs which allows + non-standard passing of byte-aligned items [D.2]. + TODO: check if this extends to packed aggregates. */ + +static unsigned int +aarch64_function_arg_round_boundary (machine_mode, const_tree) +{ + return BITS_PER_UNIT; +} +#endif + /* Implement TARGET_GET_RAW_RESULT_MODE and TARGET_GET_RAW_ARG_MODE. */ static fixed_size_mode @@ -10840,6 +10981,7 @@ aarch64_classify_address (struct aarch64_address_info *info, /* load literal: pc-relative constant pool entry. Only supported for SI mode or larger. */ info->type = ADDRESS_SYMBOLIC; + info->offset = NULL_RTX; if (!load_store_pair_p && GET_MODE_SIZE (mode).is_constant (&const_size) @@ -10847,6 +10989,7 @@ aarch64_classify_address (struct aarch64_address_info *info, { poly_int64 offset; rtx sym = strip_offset_and_salt (x, &offset); + return ((LABEL_REF_P (sym) || (SYMBOL_REF_P (sym) && CONSTANT_POOL_ADDRESS_P (sym) @@ -10864,10 +11007,13 @@ aarch64_classify_address (struct aarch64_address_info *info, poly_int64 offset; HOST_WIDE_INT const_offset; rtx sym = strip_offset_and_salt (info->offset, &offset); + if (SYMBOL_REF_P (sym) && offset.is_constant (&const_offset) && (aarch64_classify_symbol (sym, const_offset) - == SYMBOL_SMALL_ABSOLUTE)) + == SYMBOL_SMALL_ABSOLUTE + || aarch64_classify_symbol (sym, const_offset) + == SYMBOL_MO_SMALL_PCR)) { /* The symbol and offset must be aligned to the access size. */ unsigned int align; @@ -10917,6 +11063,55 @@ aarch64_address_valid_for_prefetch_p (rtx x, bool strict_p) if (!res) return false; + /* For ELF targets using GAS, we emit prfm unconditionally; GAS will alter + the instruction to pick the prfum form where possible (i.e. when the + offset is in the range -256..255) and fall back to prfm otherwise. + We can reject cases where the offset exceeds the range usable by both + insns [-256..32760], or for offsets > 255 when the value is not divisible + by 8. + For Mach-O (Darwin) where the assembler uses the LLVM back end, that does + not yet do the substitution, so we must reject all prfum cases. */ + if (addr.offset) + { + HOST_WIDE_INT offs = INTVAL (addr.offset); + if (offs < -256) /* Out of range for both prfum and prfm. */ + return false; + if (offs > 32760) /* Out of range for prfm. */ + return false; + if (offs & 0x07) /* We cannot use prfm. */ + { + if (offs > 255) /* Out of range for prfum. */ + return false; + if (TARGET_MACHO) + return false; + } + if (TARGET_MACHO && offs < 0) + return false; + } + + /* ... except writeback forms. */ + return addr.type != ADDRESS_REG_WB; +} + +/* Return true if the address X is valid for a PRFUM instruction. + STRICT_P is true if we should do strict checking with + aarch64_classify_address. */ + +bool +aarch64_address_valid_for_unscaled_prefetch_p (rtx x, bool strict_p) +{ + struct aarch64_address_info addr; + + /* PRFUM accepts the same addresses as DImode, but constrained to a range + -256..255. */ + bool res = aarch64_classify_address (&addr, x, DImode, strict_p); + if (!res) + return false; + + if (addr.offset && ((INTVAL (addr.offset) > 255) + || (INTVAL (addr.offset) < -256))) + return false; + /* ... except writeback forms. */ return addr.type != ADDRESS_REG_WB; } @@ -11605,6 +11800,144 @@ sizetochar (int size) } } +static void +output_macho_postfix_expr (FILE *file, rtx x, const char *postfix) +{ + char buf[256]; + + restart: + switch (GET_CODE (x)) + { + case PC: + putc ('.', file); + break; + + case SYMBOL_REF: + if (SYMBOL_REF_DECL (x)) + assemble_external (SYMBOL_REF_DECL (x)); + assemble_name (file, XSTR (x, 0)); + fprintf (file, "@%s", postfix); + break; + + case LABEL_REF: + x = label_ref_label (x); + /* Fall through. */ + case CODE_LABEL: + ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x)); + assemble_name (file, buf); + fprintf (file, "@%s", postfix); + break; + + case CONST_INT: + fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x)); + break; + + case CONST: + /* This used to output parentheses around the expression, + but that does not work on the 386 (either ATT or BSD assembler). */ + output_macho_postfix_expr (file, XEXP (x, 0), postfix); + break; + + case CONST_WIDE_INT: + /* We do not know the mode here so we have to use a round about + way to build a wide-int to get it printed properly. */ + { + wide_int w = wide_int::from_array (&CONST_WIDE_INT_ELT (x, 0), + CONST_WIDE_INT_NUNITS (x), + CONST_WIDE_INT_NUNITS (x) + * HOST_BITS_PER_WIDE_INT, + false); + print_decs (w, file); + } + break; + + case CONST_DOUBLE: + if (CONST_DOUBLE_AS_INT_P (x)) + { + /* We can use %d if the number is one word and positive. */ + if (CONST_DOUBLE_HIGH (x)) + fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX, + (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (x), + (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x)); + else if (CONST_DOUBLE_LOW (x) < 0) + fprintf (file, HOST_WIDE_INT_PRINT_HEX, + (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x)); + else + fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x)); + } + else + /* We can't handle floating point constants; + PRINT_OPERAND must handle them. */ + output_operand_lossage ("floating constant misused"); + break; + + case CONST_FIXED: + fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_FIXED_VALUE_LOW (x)); + break; + + case PLUS: + /* Some assemblers need integer constants to appear last (eg masm). */ + if (CONST_INT_P (XEXP (x, 0))) + { + output_macho_postfix_expr (file, XEXP (x, 1), postfix); + if (INTVAL (XEXP (x, 0)) >= 0) + fprintf (file, "+"); + output_addr_const (file, XEXP (x, 0)); + } + else + { + output_macho_postfix_expr (file, XEXP (x, 0), postfix); + if (!CONST_INT_P (XEXP (x, 1)) + || INTVAL (XEXP (x, 1)) >= 0) + fprintf (file, "+"); + output_addr_const (file, XEXP (x, 1)); + } + break; + + case MINUS: + /* Avoid outputting things like x-x or x+5-x, + since some assemblers can't handle that. */ + x = simplify_subtraction (x); + if (GET_CODE (x) != MINUS) + goto restart; + + output_macho_postfix_expr (file, XEXP (x, 0), postfix); + fprintf (file, "-"); + if ((CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) >= 0) + || GET_CODE (XEXP (x, 1)) == PC + || GET_CODE (XEXP (x, 1)) == SYMBOL_REF) + output_addr_const (file, XEXP (x, 1)); + else + { + fputs (targetm.asm_out.open_paren, file); + output_addr_const (file, XEXP (x, 1)); + fputs (targetm.asm_out.close_paren, file); + } + break; + + case ZERO_EXTEND: + case SIGN_EXTEND: + case SUBREG: + case TRUNCATE: + output_addr_const (file, XEXP (x, 0)); + break; + + case UNSPEC: + if (XINT (x, 1) == UNSPEC_SALT_ADDR) + { + output_macho_postfix_expr (file, XVECEXP (x, 0, 0), postfix); + break; + } + /* FALLTHROUGH */ + default: + if (targetm.asm_out.output_addr_const_extra (file, x)) + break; + + output_operand_lossage ("invalid expression as operand"); + } + +} + /* Print operand X to file F in a target specific manner according to CODE. The acceptable formatting commands given by CODE are: 'c': An integer or symbol address without a preceding # @@ -11673,6 +12006,12 @@ aarch64_print_operand (FILE *f, rtx x, int code) } break; + case 'K': + 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); @@ -11996,7 +12335,7 @@ aarch64_print_operand (FILE *f, rtx x, int code) case 'A': if (GET_CODE (x) == HIGH) x = XEXP (x, 0); - +#if !TARGET_MACHO switch (aarch64_classify_symbolic_expression (x)) { case SYMBOL_SMALL_GOT_4G: @@ -12027,9 +12366,29 @@ aarch64_print_operand (FILE *f, rtx x, int code) break; } output_addr_const (asm_out_file, x); +#endif +#if TARGET_MACHO + // FIXME update classify symbolic expression to handle macho. + switch (aarch64_classify_symbolic_expression (x)) + { + case SYMBOL_MO_SMALL_PCR: + output_macho_postfix_expr (asm_out_file, x, "PAGE"); +// asm_fprintf (asm_out_file, "@PAGE;mopcr"); + break; + case SYMBOL_MO_SMALL_GOT: + output_macho_postfix_expr (asm_out_file, x, "GOTPAGE"); +// asm_fprintf (asm_out_file, "@GOTPAGE;mosg"); + break; + default: + output_macho_postfix_expr (asm_out_file, x, "BLEAH"); +// asm_fprintf (asm_out_file, "@BLEAH"); + break; + } +#endif break; case 'L': +#if !TARGET_MACHO switch (aarch64_classify_symbolic_expression (x)) { case SYMBOL_SMALL_GOT_4G: @@ -12067,10 +12426,12 @@ aarch64_print_operand (FILE *f, rtx x, int code) default: break; } +#endif output_addr_const (asm_out_file, x); break; case 'G': +#if !TARGET_MACHO switch (aarch64_classify_symbolic_expression (x)) { case SYMBOL_TLSLE24: @@ -12079,6 +12440,7 @@ aarch64_print_operand (FILE *f, rtx x, int code) default: break; } +#endif output_addr_const (asm_out_file, x); break; @@ -12228,8 +12590,14 @@ aarch64_print_address_internal (FILE *f, machine_mode mode, rtx x, break; case ADDRESS_LO_SUM: +#if TARGET_MACHO + asm_fprintf (f, "[%s, #", reg_names [REGNO (addr.base)]); + output_macho_postfix_expr (f, addr.offset, "PAGEOFF"); +// output_addr_const (f, addr.offset); +#else asm_fprintf (f, "[%s, #:lo12:", reg_names [REGNO (addr.base)]); output_addr_const (f, addr.offset); +#endif asm_fprintf (f, "]"); return true; @@ -12727,6 +13095,8 @@ aarch64_asm_output_labelref (FILE* f, const char *name) asm_fprintf (f, "%U%s", name); } +#if !TARGET_MACHO + static void aarch64_elf_asm_constructor (rtx symbol, int priority) { @@ -12766,6 +13136,7 @@ aarch64_elf_asm_destructor (rtx symbol, int priority) assemble_aligned_integer (POINTER_BYTES, symbol); } } +#endif const char* aarch64_output_casesi (rtx *operands) @@ -15084,15 +15455,17 @@ aarch64_init_builtins () { aarch64_general_init_builtins (); aarch64_sve::init_builtins (); -#ifdef SUBTARGET_INIT_BUILTINS - SUBTARGET_INIT_BUILTINS; -#endif + aarch64_init_subtarget_builtins (); } /* Implement TARGET_FOLD_BUILTIN. */ static tree aarch64_fold_builtin (tree fndecl, int nargs, tree *args, bool) { +#ifdef SUBTARGET_FOLD_BUILTIN + if (tree res = SUBTARGET_FOLD_BUILTIN (fndecl, nargs, args, false)) + return res; +#endif unsigned int code = DECL_MD_FUNCTION_CODE (fndecl); unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT; tree type = TREE_TYPE (TREE_TYPE (fndecl)); @@ -18318,10 +18691,14 @@ initialize_aarch64_code_model (struct gcc_options *opts) } break; case AARCH64_CMODEL_LARGE: - if (opts->x_flag_pic) + if (TARGET_MACHO) + /* We need to implement fPIC here (arm64_32 also accepts the large + model). */ + ; + 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: @@ -19207,7 +19584,9 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset) case AARCH64_CMODEL_SMALL_SPIC: case AARCH64_CMODEL_SMALL_PIC: case AARCH64_CMODEL_SMALL: - return SYMBOL_SMALL_ABSOLUTE; + return TARGET_MACHO + ? SYMBOL_MO_SMALL_PCR + : SYMBOL_SMALL_ABSOLUTE; default: gcc_unreachable (); @@ -19243,10 +19622,22 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset) return SYMBOL_TINY_ABSOLUTE; - case AARCH64_CMODEL_SMALL_SPIC: case AARCH64_CMODEL_SMALL_PIC: case AARCH64_CMODEL_SMALL: +#if TARGET_MACHO + if (TARGET_MACHO) + { + /* Constant pool addresses are always TU-local and PC- + relative. We indirect common, external and weak + symbols (but weak only if not hidden). */ + if (!CONSTANT_POOL_ADDRESS_P (x) + && (MACHO_SYMBOL_MUST_INDIRECT_P (x) + || !aarch64_symbol_binds_local_p (x))) + return SYMBOL_MO_SMALL_GOT; + } + else +#endif if ((flag_pic || SYMBOL_REF_WEAK (x)) && !aarch64_symbol_binds_local_p (x)) return aarch64_cmodel == AARCH64_CMODEL_SMALL_SPIC @@ -19258,7 +19649,8 @@ aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset) || offset_within_block_p (x, offset))) return SYMBOL_FORCE_TO_MEM; - return SYMBOL_SMALL_ABSOLUTE; + return TARGET_MACHO ? SYMBOL_MO_SMALL_PCR + : SYMBOL_SMALL_ABSOLUTE; case AARCH64_CMODEL_LARGE: /* This is alright even in PIC code as the constant @@ -19388,7 +19780,10 @@ static GTY(()) tree va_list_type; void *__vr_top; int __gr_offs; int __vr_offs; - }; */ + }; + + darwinpcs uses 'char *' for the va_list (in common with other platform + ports). */ static tree aarch64_build_builtin_va_list (void) @@ -19396,6 +19791,13 @@ aarch64_build_builtin_va_list (void) tree va_list_name; tree f_stack, f_grtop, f_vrtop, f_groff, f_vroff; + /* darwinpcs uses a simple char * for this. */ + if (TARGET_MACHO) + { + va_list_type = build_pointer_type (char_type_node); + return va_list_type; + } + /* Create the type. */ va_list_type = lang_hooks.types.make_type (RECORD_TYPE); /* Give it the required name. */ @@ -19467,6 +19869,13 @@ aarch64_expand_builtin_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED) int vr_save_area_size = cfun->va_list_fpr_size; int vr_offset; + /* darwinpcs uses the default, char * va_list impl. */ + if (TARGET_MACHO) + { + std_expand_builtin_va_start (valist, nextarg); + return; + } + cum = &crtl->args.info; if (cfun->va_list_gpr_size) gr_save_area_size = MIN ((NUM_ARG_REGS - cum->aapcs_ncrn) * UNITS_PER_WORD, @@ -19557,6 +19966,9 @@ aarch64_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, HOST_WIDE_INT size, rsize, adjust, align; tree t, u, cond1, cond2; + if (TARGET_MACHO) + return std_gimplify_va_arg_expr (valist, type, pre_p, post_p); + indirect_p = pass_va_arg_by_reference (type); if (indirect_p) type = build_pointer_type (type); @@ -19825,6 +20237,9 @@ aarch64_setup_incoming_varargs (cumulative_args_t cum_v, int gr_saved = cfun->va_list_gpr_size; int vr_saved = cfun->va_list_fpr_size; + if (TARGET_MACHO) + return; + /* 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. */ @@ -20656,6 +21071,12 @@ aarch64_autovectorize_vector_modes (vector_modes *modes, bool) static const char * aarch64_mangle_type (const_tree type) { + /* The darwinpcs ABI documents say that "__va_list" has to be + mangled as char *. */ + if (TARGET_MACHO + && lang_hooks.types_compatible_p (CONST_CAST_TREE (type), va_list_type)) + return "Pc"; + /* The AArch64 ABI documents say that "__va_list" has to be mangled as if it is in the "std" namespace. */ if (lang_hooks.types_compatible_p (CONST_CAST_TREE (type), va_list_type)) @@ -21365,7 +21786,8 @@ aarch64_mov_operand_p (rtx x, machine_mode mode) /* GOT accesses are valid moves. */ if (SYMBOL_REF_P (x) - && aarch64_classify_symbolic_expression (x) == SYMBOL_SMALL_GOT_4G) + && (aarch64_classify_symbolic_expression (x) == SYMBOL_SMALL_GOT_4G + || aarch64_classify_symbolic_expression (x) == SYMBOL_MO_SMALL_GOT)) return true; if (SYMBOL_REF_P (x) && mode == DImode && CONSTANT_ADDRESS_P (x)) @@ -22525,7 +22947,9 @@ aarch64_declare_function_name (FILE *stream, const char* name, 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_LABEL (stream, name); cfun->machine->label_is_assembled = true; @@ -22560,12 +22984,17 @@ aarch64_print_patchable_function_entry (FILE *file, /* 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 @@ -23038,7 +23467,7 @@ aarch64_init_libfuncs (void) static machine_mode aarch64_c_mode_for_suffix (char suffix) { - if (suffix == 'q') + if (suffix == 'q' && !TARGET_MACHO) return TFmode; return VOIDmode; @@ -23189,6 +23618,16 @@ aarch64_output_simd_mov_immediate (rtx const_vector, unsigned width, } gcc_assert (CONST_INT_P (info.u.mov.value)); + unsigned HOST_WIDE_INT value = UINTVAL (info.u.mov.value); + + /* We have signed chars which can result in a sign-extended 8bit value + which is then emitted as an unsigned hex value, and the LLVM back end + assembler rejects that as being too big. */ + if (TARGET_MACHO && (known_eq (GET_MODE_BITSIZE (info.elt_mode), 8))) + { + unsigned HOST_WIDE_INT mask = (1U << GET_MODE_BITSIZE (info.elt_mode))-1; + value &= mask; + } if (which == AARCH64_CHECK_MOV) { @@ -23197,16 +23636,16 @@ aarch64_output_simd_mov_immediate (rtx const_vector, unsigned width, ? "msl" : "lsl"); if (lane_count == 1) snprintf (templ, sizeof (templ), "%s\t%%d0, " HOST_WIDE_INT_PRINT_HEX, - mnemonic, UINTVAL (info.u.mov.value)); + mnemonic, value); else if (info.u.mov.shift) snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, " HOST_WIDE_INT_PRINT_HEX ", %s %d", mnemonic, lane_count, - element_char, UINTVAL (info.u.mov.value), shift_op, + element_char, value, shift_op, info.u.mov.shift); else snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, " HOST_WIDE_INT_PRINT_HEX, mnemonic, lane_count, - element_char, UINTVAL (info.u.mov.value)); + element_char, value); } else { @@ -23215,12 +23654,12 @@ aarch64_output_simd_mov_immediate (rtx const_vector, unsigned width, if (info.u.mov.shift) snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, #" HOST_WIDE_INT_PRINT_DEC ", %s #%d", mnemonic, lane_count, - element_char, UINTVAL (info.u.mov.value), "lsl", + element_char, value, "lsl", info.u.mov.shift); else snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, #" HOST_WIDE_INT_PRINT_DEC, mnemonic, lane_count, - element_char, UINTVAL (info.u.mov.value)); + element_char, value); } return templ; } @@ -27142,19 +27581,37 @@ aarch64_sls_emit_shared_blr_thunks (FILE *out_file) continue; const char *name = indirect_symbol_names[regnum]; - switch_to_section (get_named_section (decl, NULL, 0)); + /* If the target uses a unique section for this switch to it. */ + if (DECL_SECTION_NAME (decl)) + switch_to_section (get_named_section (decl, NULL, 0)); + else + switch_to_section (text_section); ASM_OUTPUT_ALIGN (out_file, 2); - targetm.asm_out.globalize_label (out_file, name); + if (!TARGET_MACHO) + targetm.asm_out.globalize_label (out_file, name); +#ifdef ASM_OUTPUT_TYPE_DIRECTIVE + ASM_OUTPUT_TYPE_DIRECTIVE (out_file, name, "function"); +#endif + if (TARGET_MACHO) + { +#ifdef ASM_WEAKEN_DECL + if (DECL_WEAK (decl)) + ASM_WEAKEN_DECL (out_file, decl, name, 0); + else +#endif + targetm.asm_out.globalize_decl_name (out_file, decl); + } /* Only emits if the compiler is configured for an assembler that can handle visibility directives. */ targetm.asm_out.assemble_visibility (decl, VISIBILITY_HIDDEN); - ASM_OUTPUT_TYPE_DIRECTIVE (out_file, name, "function"); ASM_OUTPUT_LABEL (out_file, name); aarch64_sls_emit_function_stub (out_file, regnum); /* Use the most conservative target to ensure it can always be used by any function in the translation unit. */ asm_fprintf (out_file, "\tdsb\tsy\n\tisb\n"); +#ifdef ASM_DECLARE_FUNCTION_SIZE ASM_DECLARE_FUNCTION_SIZE (out_file, name, decl); +#endif } } @@ -27347,6 +27804,15 @@ aarch64_run_selftests (void) #undef TARGET_ASM_ALIGNED_SI_OP #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t" +#if TARGET_MACHO +#undef TARGET_ASM_UNALIGNED_HI_OP +#define TARGET_ASM_UNALIGNED_HI_OP "\t.short\t" +#undef TARGET_ASM_UNALIGNED_SI_OP +#define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t" +#undef TARGET_ASM_UNALIGNED_DI_OP +#define TARGET_ASM_UNALIGNED_DI_OP "\t.quad\t" +#endif + #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \ hook_bool_const_tree_hwi_hwi_const_tree_true @@ -27433,6 +27899,11 @@ aarch64_run_selftests (void) #undef TARGET_FUNCTION_ARG_BOUNDARY #define TARGET_FUNCTION_ARG_BOUNDARY aarch64_function_arg_boundary +#if TARGET_MACHO +#undef TARGET_FUNCTION_ARG_ROUND_BOUNDARY +#define TARGET_FUNCTION_ARG_ROUND_BOUNDARY aarch64_function_arg_round_boundary +#endif + #undef TARGET_FUNCTION_ARG_PADDING #define TARGET_FUNCTION_ARG_PADDING aarch64_function_arg_padding diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index 05da9af03679..36a8f302e4a5 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -65,6 +65,10 @@ #define TARGET_SIMD (AARCH64_ISA_SIMD) #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 @@ -916,6 +920,12 @@ typedef struct aapcs_reg == NULL_RTX. */ int aapcs_stack_size; /* The total size (in words, per 8 byte) of the stack arg area so far. */ + 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. */ bool silent_p; /* True if we should act silently, rather than raise an error for invalid calls. */ } CUMULATIVE_ARGS; @@ -1214,8 +1224,13 @@ extern const char *aarch64_rewrite_mcpu (int argc, const char **argv); #define ASM_CPU_SPEC \ MCPU_TO_MARCH_SPEC +#ifndef SUBTARGET_EXTRA_SPECS +#define SUBTARGET_EXTRA_SPECS +#endif + #define EXTRA_SPECS \ - { "asm_cpu_spec", ASM_CPU_SPEC } + { "asm_cpu_spec", ASM_CPU_SPEC }, \ + SUBTARGET_EXTRA_SPECS #define ASM_OUTPUT_POOL_EPILOGUE aarch64_asm_output_pool_epilogue diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 0a7633e5dd6d..1ba40703a5ee 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -303,6 +303,7 @@ UNSPEC_TAG_SPACE ; Translate address to MTE tag address space. UNSPEC_LD1RO UNSPEC_SALT_ADDR + UNSPEC_MACHOPIC_OFFSET ]) (define_c_enum "unspecv" [ @@ -849,6 +850,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))] "" @@ -1286,7 +1318,7 @@ ldr\\t%s0, %1 str\\t%w1, %0 str\\t%s1, %0 - adrp\\t%x0, %A1\;ldr\\t%w0, [%x0, %L1] + * return TARGET_MACHO ? \"adrp\\t%x0, %A1\;ldr\\t%w0, [%x0, %O1]\" : \"adrp\\t%x0, %A1\;ldr\\t%w0, [%x0, %L1]\"; adr\\t%x0, %c1 adrp\\t%x0, %A1 fmov\\t%s0, %w1 @@ -1325,7 +1357,7 @@ ldr\\t%d0, %1 str\\t%x1, %0 str\\t%d1, %0 - * return TARGET_ILP32 ? \"adrp\\t%0, %A1\;ldr\\t%w0, [%0, %L1]\" : \"adrp\\t%0, %A1\;ldr\\t%0, [%0, %L1]\"; + * return 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]\"); adr\\t%x0, %c1 adrp\\t%x0, %A1 fmov\\t%d0, %x1 @@ -6916,7 +6948,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, %K2;momd" + : "add\\t%0, %1, :lo12:%c2"; + } [(set_attr "type" "alu_imm")] ) diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt index b89b20450710..1e7eed025be8 100644 --- a/gcc/config/aarch64/aarch64.opt +++ b/gcc/config/aarch64/aarch64.opt @@ -155,6 +155,13 @@ Enum(aarch64_abi) String(ilp32) Value(AARCH64_ABI_ILP32) EnumValue Enum(aarch64_abi) String(lp64) Value(AARCH64_ABI_LP64) +EnumValue +Enum(aarch64_abi) String(darwinpcs) Value(AARCH64_ABI_LP64) + +m64 +Target RejectNegative Alias(mabi=, darwinpcs) +On Darwin for compatibility with other platform variants. + mpc-relative-literal-loads Target Save Var(pcrelative_literal_loads) Init(2) Save PC relative literal loads. diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md index ee7587cca167..cb73a2daae89 100644 --- a/gcc/config/aarch64/constraints.md +++ b/gcc/config/aarch64/constraints.md @@ -158,7 +158,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 @@ -490,6 +492,11 @@ An address valid for a prefetch instruction." (match_test "aarch64_address_valid_for_prefetch_p (op, true)")) +(define_address_constraint "Du" + "@internal + An address valid for a prefetch instruction with an unscaled offset." + (match_test "aarch64_address_valid_for_unscaled_prefetch_p (op, true)")) + (define_constraint "vgb" "@internal A constraint that matches an immediate offset valid for SVE LD1B diff --git a/gcc/config/aarch64/darwin.h b/gcc/config/aarch64/darwin.h new file mode 100644 index 000000000000..4a3608014b86 --- /dev/null +++ b/gcc/config/aarch64/darwin.h @@ -0,0 +1,270 @@ +/* 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 + +/* FIXME FIXME FIXME - these are mostly guesses right now. */ + +/* FIXME: this is only used in generic code in darwin.c. */ +#undef TARGET_64BIT +#define TARGET_64BIT 1 + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "long int" + +/* 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, for consistency with other Darwin + architectures. */ + +#undef DEFAULT_SIGNED_CHAR +#define DEFAULT_SIGNED_CHAR 1 + +#undef LONG_DOUBLE_TYPE_SIZE +#define LONG_DOUBLE_TYPE_SIZE 64 + +/* Non-PIE executables are forbidden by the aarch64-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 \ +" % 10years). Any symbol that is not 'global' and does not begin + with 'L' (the local symbol designation) is counted as 'linker visible'. + * does _not_ support 'static' code in the user space + + Everything needs to be invoked using the dynamic linker (`dyld`). There is + neither crt0.o nor a static edition of libc. + +Some versions of Darwin have used 'static' code for kernel modules. +FIXME: ??? what is the kernel model here. + +### Darwin Relocations and Assembler syntax + +* `Mach-O` for `Arm64` uses a reduced set of relocations c.f. the ELF set. + + There are only 11 entries but the relocation format allows for multiple sizes +(1, 2, 4, 8) where that's appropriate, and for ancillary data (e.g. a scale), +so the actual number of permutations is larger. + +* Generally, Darwin supports relocations of the form A - B + signed const + + A must be known (i.e. defined in the current TU). + +* `Mach-O` for `Arm64` has postfix assembler syntax. + + Where there's an assembly language representation for the relocation type + it appears after the name (e.g. `foo@PAGE` in contrast to the ELF + `:got:foo`). + +#### Relocs list + +For pointers (no source representation). + +`ARM64_RELOC_UNSIGNED = 0` + +Must be followed by an `ARM64_RELOC_UNSIGNED` + +`ARM64_RELOC_SUBTRACTOR = 1` + +A B/BL instruction with 26-bit displacement. +(no source representation) + +`ARM64_RELOC_BRANCH26 = 2` + +PC-rel distance to page of target [adrp]. + +`foo@PAGE` + +`ARM64_RELOC_PAGE21 = 3` + +Offset within page, scaled by r_length [add imm, ld/st]. + +`foo@PAGEOFF` + +`ARM64_RELOC_PAGEOFF12 = 4` + +PC-rel distance to page of GOT slot [adrp]. + +`foo@GOTPAGE` +`ARM64_RELOC_GOT_LOAD_PAGE21 = 5` + +Offset within page of GOT slot, scaled by r_length [add imm, ld/st]. + +`foo@GOTPAGEOFF` + +`ARM64_RELOC_GOT_LOAD_PAGEOFF12 = 6` + + +For pointers to GOT slots. +(4 and 8 byte versions) + +`foo@GOT` + +`ARM64_RELOC_POINTER_TO_GOT = 7` + + +PC-rel distance to page of TLVP slot [adrp]. + +`foo@TVLPPAGE` + +`ARM64_RELOC_TLVP_LOAD_PAGE21 = 8` + +Offset within page of TLVP slot, scaled by r_length [add imm, ld/st]. + +`foo@TVLPPAGEOFF` + +`ARM64_RELOC_TLVP_LOAD_PAGEOFF12 = 9` + +Must be followed by `ARM64_RELOC_PAGE21` or `ARM64_RELOC_PAGEOFF12`. +(no source representation) + +The addend is a signed 24bit quantity (+/- 8M range). + +`ARM64_RELOC_ADDEND = 10` + +## PART 2 - GCC-12 deviations from the PCS and supporting information. + +### D.3 is not yet supported (github issue #74) + + GCC promotes in the callee not the caller. + +### Support for nested functions + + GCC provides nested functions which are used overtly from C but also to + implement some parts of Ada and Fortran. + + This requires assigning a register to act as the STATIC CHAIN. + For GCC-12 this is X16 + + Support for nested function trampolines is provided by a heap-based table. + +### Support for __float128 + + The darwinpcs has no provision for a 128bit float type. + GCC-12 supports IEEE741 128bit float values by sof-float. + The ABI used for __float128 matches that for AAPCS64 + +## End. diff --git a/gcc/config/aarch64/falkor-tag-collision-avoidance.cc b/gcc/config/aarch64/falkor-tag-collision-avoidance.cc index 5f1982905688..610838049e56 100644 --- a/gcc/config/aarch64/falkor-tag-collision-avoidance.cc +++ b/gcc/config/aarch64/falkor-tag-collision-avoidance.cc @@ -740,7 +740,7 @@ dump_insn_list (const rtx &t, const insn_info_list_t &insn_info, void *unused ATTRIBUTE_UNUSED) { gcc_assert (dump_file); - fprintf (dump_file, "Tag 0x%lx ::\n", INTVAL (t)); + fprintf (dump_file, "Tag 0x%lx ::\n", (long unsigned int)INTVAL (t)); for (unsigned i = 0; i < insn_info.length (); i++) dump_insn_slim (dump_file, insn_info[i]->insn); diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md index c308015ac2c1..cd88f93ca2d3 100644 --- a/gcc/config/aarch64/predicates.md +++ b/gcc/config/aarch64/predicates.md @@ -261,9 +261,24 @@ (define_predicate "aarch64_prefetch_operand" (match_test "aarch64_address_valid_for_prefetch_p (op, false)")) +(define_predicate "aarch64_unscaled_prefetch_operand" + (match_test "aarch64_address_valid_for_unscaled_prefetch_p (op, false)")) + (define_predicate "aarch64_valid_symref" (match_code "const, symbol_ref, label_ref") { + if (TARGET_MACHO) + { + rtx x = op; + rtx offset; + split_const (x, &x, &offset); + if (GET_CODE (x) == CONST) + x = XEXP (x, 0); + if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_SALT_ADDR) + x = XVECEXP (x, 0, 0); + if (SYMBOL_REF_P (x) && INTVAL (offset) < 0) + return false; + } return (aarch64_classify_symbolic_expression (op) != SYMBOL_FORCE_TO_MEM); }) diff --git a/gcc/config/aarch64/t-aarch64-darwin b/gcc/config/aarch64/t-aarch64-darwin new file mode 100644 index 000000000000..9754e87ebcf0 --- /dev/null +++ b/gcc/config/aarch64/t-aarch64-darwin @@ -0,0 +1,25 @@ +# Machine description for AArch64 architecture. +# Copyright (C) 2020 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +LIB1ASMSRC = aarch64/lib1funcs.asm +LIB1ASMFUNCS = _aarch64_sync_cache_range + +# FIXME - figure out what multilib provisions we should make for +# a) arm64e +# b) arm64_32 diff --git a/gcc/config/darwin-driver.cc b/gcc/config/darwin-driver.cc index 335dff150c20..6df85f57bb44 100644 --- a/gcc/config/darwin-driver.cc +++ b/gcc/config/darwin-driver.cc @@ -268,10 +268,13 @@ darwin_driver_init (unsigned int *decoded_options_count, bool seenX86_64 = false; bool seenPPC = false; bool seenPPC64 = false; +#if !DARWIN_ARM64 + bool seenArm64 = false; bool seenM32 = false; bool seenM64 = false; bool appendM32 = false; bool appendM64 = false; +#endif const char *vers_string = NULL; bool seen_version_min = false; bool seen_sysroot_p = false; @@ -300,6 +303,12 @@ darwin_driver_init (unsigned int *decoded_options_count, seenPPC = true; else if (!strcmp ((*decoded_options)[i].arg, "ppc64")) seenPPC64 = true; + else if (!strcmp ((*decoded_options)[i].arg, "arm64")) +#if !DARWIN_ARM64 + seenArm64 = true; +#else + ; /* We accept the option, but don't need to act on it. */ +#endif else error ("this compiler does not support %qs", (*decoded_options)[i].arg); @@ -313,7 +322,7 @@ darwin_driver_init (unsigned int *decoded_options_count, --i; --*decoded_options_count; break; - +#if !DARWIN_ARM64 case OPT_m32: seenM32 = true; break; @@ -321,6 +330,7 @@ darwin_driver_init (unsigned int *decoded_options_count, case OPT_m64: seenM64 = true; break; +#endif case OPT_mmacosx_version_min_: seen_version_min = true; @@ -378,6 +388,9 @@ darwin_driver_init (unsigned int *decoded_options_count, if (seenPPC || seenPPC64) warning (0, "this compiler does not support PowerPC" " (%<-arch%> option ignored)"); + else if (seenArm64) + warning (0, "this compiler does not support Arm64" + " (%<-arch%> option ignored)"); if (seenX86) { if (seenX86_64 || seenM64) @@ -401,6 +414,9 @@ darwin_driver_init (unsigned int *decoded_options_count, if (seenX86 || seenX86_64) warning (0, "this compiler does not support x86" " (%<-arch%> option ignored)"); + else if (seenArm64) + warning (0, "this compiler does not support Arm64" + " (%<-arch%> option ignored)"); if (seenPPC) { if (seenPPC64 || seenM64) @@ -420,12 +436,20 @@ darwin_driver_init (unsigned int *decoded_options_count, if (! seenM64) /* Add -m64 if the User didn't. */ appendM64 = true; } +#elif DARWIN_ARM64 + if (seenPPC || seenPPC64) + warning (0, "this compiler does not support PowerPC" + " (%<-arch%> option ignored)"); + if (seenX86 || seenX86_64) + warning (0, "this compiler does not support x86" + " (%<-arch%> option ignored)"); #endif /* If there is nothing else on the command line, do not add sysroot etc. */ if (*decoded_options_count <= 1) return; +#if !DARWIN_ARM64 if (appendM32 || appendM64) { ++*decoded_options_count; @@ -435,6 +459,7 @@ darwin_driver_init (unsigned int *decoded_options_count, generate_option (appendM32 ? OPT_m32 : OPT_m64, NULL, 1, CL_DRIVER, &(*decoded_options)[*decoded_options_count - 1]); } +#endif if (!seen_sysroot_p) { diff --git a/gcc/config/darwin.cc b/gcc/config/darwin.cc index 1b3de338926d..7cd684c6abe4 100644 --- a/gcc/config/darwin.cc +++ b/gcc/config/darwin.cc @@ -118,7 +118,7 @@ static bool ld_init_term_start_labels = false; 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 @@ -1052,6 +1052,7 @@ machopic_legitimize_pic_address (rtx orig, machine_mode mode, rtx reg) return pic_ref; } +#if !DARWIN_ARM64 /* Callbacks to output the stub or non-lazy pointers. Each works on the item in *SLOT,if it has been used. DATA is the FILE* for assembly output. @@ -1207,6 +1208,7 @@ machopic_finish (FILE *out_file) machopic_indirections->traverse_noresize (out_file); } +#endif int machopic_operand_p (rtx op) @@ -2240,6 +2242,8 @@ darwin_emit_except_table_label (FILE *file) rtx darwin_make_eh_symbol_indirect (rtx orig, bool ARG_UNUSED (pubvis)) { + if (DARWIN_ARM64) + return orig; if (DARWIN_PPC == 0 && TARGET_64BIT) return orig; @@ -3060,7 +3064,12 @@ darwin_file_end (void) fprintf (asm_out_file, "\t.long\t0\n\t.long\t%u\n", flags); } +#if !DARWIN_ARM64 machopic_finish (asm_out_file); +#else + gcc_checking_assert (!machopic_indirections); +#endif + if (flag_apple_kext) { /* These sections are only used for kernel code. */ diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h index 4ef156fb2a73..ddea891d0915 100644 --- a/gcc/config/darwin.h +++ b/gcc/config/darwin.h @@ -42,6 +42,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define DARWIN_X86 0 #define DARWIN_PPC 0 +#define DARWIN_ARM64 0 #define OBJECT_FORMAT_MACHO 1