]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
RISC-V: Emit R_RISCV_RELAX for the la/lga pseudo instruction
authorRui Ueyama <rui314@gmail.com>
Wed, 20 Sep 2023 08:31:26 +0000 (17:31 +0900)
committerNelson Chu <nelson@rivosinc.com>
Tue, 12 Dec 2023 09:33:31 +0000 (17:33 +0800)
Some psABIs define a relaxation to turn a GOT load into a PC-relative
address materialization.  For example, the AArch64's psABI allows
adrp+ldr to be rewritten to nop+adr to eliminate the memory load.
This patch is part of the effort to make such optimization possible
for RISC-V.

For RISC-V, we use the la assembly pseudo instruction to load a symbol
address from the GOT. The pseudo instruction is expanded to auipc+ld.
If the address loaded by the instruction pair is actually a PC-relative
link-time constant, we want the linker to rewrite the instruction pair
with auipc+addi.

We can't rewrite all existing auipc+ld pairs with auipc+addi in the
linker because there might be code that jumps to the middle of the
instruction pair.  That should be extremely rare, if ever exists, but
you can at least in theory write a program in assembly that jumps to
the ld instruction of the instruction pair.  We need a marker to
identify that an auipc+ld can be safely relaxed (i.e. they are emitted
for la).

This patch is to annotate R_RISCV_GOT_HI20 with R_RISCV_RELAX only
when the relocation is emitted for the la pseudo instruction.  The
linker will use it as a signal that the instruction pair can be safely
relaxed.

Proposal to the RISC-V psABI:
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/397

gas/
* config/tc-riscv.c (source_macro): New static int variable.
The identifier of the assembler macro we are expanding, if any.
(append_insn): Updated source_macro to tc_fix_data, to record
which macro expands, if any.
(macro): Record which macro expands into source_macro.  Reset
source_macro to -1 at the end.
(md_apply_fix): Apply R_RISCV_RELAX if pcrel_got_hi is expanded
from macro LA/LGA.
* config/tc-riscv.h (struct riscv_fix, TC_FIX_TYPE, TC_INIT_FIX_DATA):
Defined to record source_macro into fixups for riscv target.
* testsuite/gas/riscv/la-variants.d: Updated.

gas/config/tc-riscv.c
gas/config/tc-riscv.h
gas/testsuite/gas/riscv/la-variants.d

index 10f1ac7de3ce7389a6d9a733a4d68079781d19e6..a46a6a4ec48442c6d798bcd526e62330664ea2ee 100644 (file)
@@ -59,6 +59,9 @@ struct riscv_cl_insn
   fixS *fixp;
 };
 
+/* The identifier of the assembler macro we are expanding, if any. */
+static int source_macro = -1;
+
 /* All RISC-V CSR belong to one of these classes.  */
 enum riscv_csr_class
 {
@@ -1749,6 +1752,7 @@ append_insn (struct riscv_cl_insn *ip, expressionS *address_expr,
                                  address_expr, false, reloc_type);
 
          ip->fixp->fx_tcbit = riscv_opts.relax;
+         ip->fixp->tc_fix_data.source_macro = source_macro;
        }
     }
 
@@ -2103,6 +2107,8 @@ macro (struct riscv_cl_insn *ip, expressionS *imm_expr,
   int rs2 = (ip->insn_opcode >> OP_SH_RS2) & OP_MASK_RS2;
   int mask = ip->insn_mo->mask;
 
+  source_macro = mask;
+
   switch (mask)
     {
     case M_LI:
@@ -2178,6 +2184,8 @@ macro (struct riscv_cl_insn *ip, expressionS *imm_expr,
       as_bad (_("internal: macro %s not implemented"), ip->insn_mo->name);
       break;
     }
+
+  source_macro = -1;
 }
 
 static const struct percent_op_match percent_op_utype[] =
@@ -4139,6 +4147,13 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
       break;
 
     case BFD_RELOC_RISCV_GOT_HI20:
+      /* R_RISCV_GOT_HI20 and the following R_RISCV_LO12_I are relaxable
+        only if it is created as a result of la or lga assembler macros. */
+      if (fixP->tc_fix_data.source_macro == M_LA
+         || fixP->tc_fix_data.source_macro == M_LGA)
+       relaxable = true;
+      break;
+
     case BFD_RELOC_RISCV_ADD8:
     case BFD_RELOC_RISCV_ADD16:
     case BFD_RELOC_RISCV_ADD32:
index 9d2f05a424136d16471a858013904c1a4906017d..ff1c719d11c32a2ca02e41afb81eddefc03ba720 100644 (file)
@@ -104,6 +104,14 @@ extern void riscv_md_end (void);
 #define TC_FORCE_RELOCATION_LOCAL(FIX) 1
 #define DIFF_EXPR_OK 1
 
+struct riscv_fix
+{
+  int source_macro;
+};
+
+#define TC_FIX_TYPE struct riscv_fix
+#define TC_INIT_FIX_DATA(FIX) (FIX)->tc_fix_data.source_macro = -1
+
 extern void riscv_pop_insert (void);
 #define md_pop_insert()                riscv_pop_insert ()
 
index b1d316983b7ee1221edb6759dfa2bac79d8c9aca..e8ac09c2af2bfe4b16e91547186f5786ca78f054 100644 (file)
@@ -21,11 +21,13 @@ Disassembly of section .text:
 [      ]+[0-9a-f]+:[   ]+R_RISCV_RELAX[        ]+\*ABS\*
 [      ]+[0-9a-f]+:[   ]+00000617[     ]+auipc[        ]+a2,0x0
 [      ]+[0-9a-f]+:[   ]+R_RISCV_GOT_HI20[     ]+a
+[      ]+[0-9a-f]+:[   ]+R_RISCV_RELAX[        ]+\*ABS\*
 [      ]+[0-9a-f]+:[   ]+(00062603|00063603)[  ]+(lw|ld)[      ]+a2,0\(a2\).*
 [      ]+[0-9a-f]+:[   ]+R_RISCV_PCREL_LO12_I[         ]+\.L0[ ]+
 [      ]+[0-9a-f]+:[   ]+R_RISCV_RELAX[        ]+\*ABS\*
 [      ]+[0-9a-f]+:[   ]+00000697[     ]+auipc[        ]+a3,0x0
 [      ]+[0-9a-f]+:[   ]+R_RISCV_GOT_HI20[     ]+a
+[      ]+[0-9a-f]+:[   ]+R_RISCV_RELAX[        ]+\*ABS\*
 [      ]+[0-9a-f]+:[   ]+(0006a683|0006b683)[  ]+(lw|ld)[      ]+a3,0\(a3\).*
 [      ]+[0-9a-f]+:[   ]+R_RISCV_PCREL_LO12_I[         ]+\.L0[ ]+
 [      ]+[0-9a-f]+:[   ]+R_RISCV_RELAX[        ]+\*ABS\*
@@ -37,6 +39,7 @@ Disassembly of section .text:
 [      ]+[0-9a-f]+:[   ]+R_RISCV_RELAX[        ]+\*ABS\*
 [      ]+[0-9a-f]+:[   ]+00000797[     ]+auipc[        ]+a5,0x0
 [      ]+[0-9a-f]+:[   ]+R_RISCV_GOT_HI20[     ]+a
+[      ]+[0-9a-f]+:[   ]+R_RISCV_RELAX[        ]+\*ABS\*
 [      ]+[0-9a-f]+:[   ]+(0007a783|0007b783)[  ]+(lw|ld)[      ]+a5,0\(a5\).*
 [      ]+[0-9a-f]+:[   ]+R_RISCV_PCREL_LO12_I[         ]+\.L0[ ]+
 [      ]+[0-9a-f]+:[   ]+R_RISCV_RELAX[        ]+\*ABS\*