Skip to content

Commit

Permalink
RISC-V: Emit R_RISCV_RELAX for the la/lga pseudo instruction
Browse files Browse the repository at this point in the history
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:
riscv-non-isa/riscv-elf-psabi-doc#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.
  • Loading branch information
rui314 authored and Nelson Chu committed Dec 12, 2023
1 parent dff565f commit bf69326
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 0 deletions.
15 changes: 15 additions & 0 deletions gas/config/tc-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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[] =
Expand Down Expand Up @@ -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:
Expand Down
8 changes: 8 additions & 0 deletions gas/config/tc-riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 ()

Expand Down
3 changes: 3 additions & 0 deletions gas/testsuite/gas/riscv/la-variants.d
Original file line number Diff line number Diff line change
Expand Up @@ -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\*
Expand All @@ -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\*

0 comments on commit bf69326

Please sign in to comment.