diff options
author | Rui Ueyama <rui314@gmail.com> | 2023-09-20 17:31:26 +0900 |
---|---|---|
committer | Nelson Chu <nelson@rivosinc.com> | 2023-12-12 17:33:31 +0800 |
commit | bf69326fb74b73a4a4689d6368673de491819806 (patch) | |
tree | dd2505637cd7d72e7b0a11d31412bf17909792d8 | |
parent | dff565fcca8137954d6ad571ef39f6aec5c0429c (diff) | |
download | gdb-bf69326fb74b73a4a4689d6368673de491819806.zip gdb-bf69326fb74b73a4a4689d6368673de491819806.tar.gz gdb-bf69326fb74b73a4a4689d6368673de491819806.tar.bz2 |
RISC-V: Emit R_RISCV_RELAX for the la/lga pseudo instruction
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.
-rw-r--r-- | gas/config/tc-riscv.c | 15 | ||||
-rw-r--r-- | gas/config/tc-riscv.h | 8 | ||||
-rw-r--r-- | gas/testsuite/gas/riscv/la-variants.d | 3 |
3 files changed, 26 insertions, 0 deletions
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index 10f1ac7..a46a6a4 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -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: diff --git a/gas/config/tc-riscv.h b/gas/config/tc-riscv.h index 9d2f05a..ff1c719 100644 --- a/gas/config/tc-riscv.h +++ b/gas/config/tc-riscv.h @@ -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 () diff --git a/gas/testsuite/gas/riscv/la-variants.d b/gas/testsuite/gas/riscv/la-variants.d index b1d3169..e8ac09c 100644 --- a/gas/testsuite/gas/riscv/la-variants.d +++ b/gas/testsuite/gas/riscv/la-variants.d @@ -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\* |