aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRui Ueyama <rui314@gmail.com>2023-09-20 17:31:26 +0900
committerNelson Chu <nelson@rivosinc.com>2023-12-12 17:33:31 +0800
commitbf69326fb74b73a4a4689d6368673de491819806 (patch)
treedd2505637cd7d72e7b0a11d31412bf17909792d8
parentdff565fcca8137954d6ad571ef39f6aec5c0429c (diff)
downloadgdb-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.c15
-rw-r--r--gas/config/tc-riscv.h8
-rw-r--r--gas/testsuite/gas/riscv/la-variants.d3
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\*