From 32cf2dcd4a39e6e039c4eedccd7aba7c4837d310 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Tue, 25 Aug 2020 19:33:49 +0100 Subject: [PATCH] Darwin, Arm64 : Temporary proof-of-principle for relocs+addends. 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. (cherry picked from commit 36767eccb8a65b6b57eedca4907100e702b3b829) Signed-off-by: Kirill A. Korinsky --- gcc/config/aarch64/aarch64.c | 153 ++++++++++++++++++++++++++++++++-- gcc/config/aarch64/aarch64.md | 4 +- 2 files changed, 148 insertions(+), 9 deletions(-) diff --git gcc/config/aarch64/aarch64.c gcc/config/aarch64/aarch64.c index bde27d7d361..0a43cefc270 100644 --- gcc/config/aarch64/aarch64.c +++ gcc/config/aarch64/aarch64.c @@ -10409,6 +10409,136 @@ 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); + 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; + + 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 # @@ -10477,6 +10607,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); @@ -10827,20 +10963,23 @@ aarch64_print_operand (FILE *f, rtx x, int code) default: break; } -#endif 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: - asm_fprintf (asm_out_file, "@PAGE;mopcr"); + output_macho_postfix_expr (asm_out_file, x, "PAGE"); +// asm_fprintf (asm_out_file, "@PAGE;mopcr"); break; case SYMBOL_MO_SMALL_GOT: - asm_fprintf (asm_out_file, "@GOTPAGE;mosg"); + output_macho_postfix_expr (asm_out_file, x, "GOTPAGE"); +// asm_fprintf (asm_out_file, "@GOTPAGE;mosg"); break; default: - asm_fprintf (asm_out_file, "@BLEAH"); + output_macho_postfix_expr (asm_out_file, x, "BLEAH"); +// asm_fprintf (asm_out_file, "@BLEAH"); break; } #endif @@ -11049,13 +11188,13 @@ aarch64_print_address_internal (FILE *f, machine_mode mode, rtx x, case ADDRESS_LO_SUM: #if TARGET_MACHO asm_fprintf (f, "[%s, #", reg_names [REGNO (addr.base)]); - output_addr_const (f, addr.offset); - asm_fprintf (f, "@PAGEOFF]"); + 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); - asm_fprintf (f, "]"); #endif + asm_fprintf (f, "]"); return true; case ADDRESS_SYMBOLIC: diff --git gcc/config/aarch64/aarch64.md gcc/config/aarch64/aarch64.md index 38666010e52..25200a8b5a6 100644 --- gcc/config/aarch64/aarch64.md +++ gcc/config/aarch64/aarch64.md @@ -6506,7 +6506,7 @@ (define_insn "add_losym_" (match_operand 2 "aarch64_valid_symref" "S")))] "" { return TARGET_MACHO - ? "add\\t%0, %1, %c2@PAGEOFF;momd" + ? "add\\t%0, %1, %K2;momd" : "add\\t%0, %1, :lo12:%c2"; } [(set_attr "type" "alu_imm")] @@ -6520,7 +6520,7 @@ (define_insn "ldr_got_small_" UNSPEC_GOTSMALLPIC))] "" { return TARGET_MACHO - ? "ldr\\t%0, [%1, %c2@GOTPAGEOFF];momd" + ? "ldr\\t%0, [%1, %O2];momd" : "ldr\\t%0, [%1, #:got_lo12:%c2]"; } [(set_attr "type" "load_")] -- 2.42.1