[PATCH] RISCV-V: Add new relocation type for global array accesses with non-constant indices
Jan Beulich
jbeulich@suse.com
Tue Mar 24 10:07:29 GMT 2026
On 24.03.2026 10:44, 翁丽琴 wrote:
> @@ -3089,6 +3107,30 @@ riscv_elf_relocate_section (bfd *output_bfd,
> break;
> }
>
> + case INTERNAL_R_RISCV_REGREL_LO12_I:
> + case INTERNAL_R_RISCV_REGREL_LO12_S:
> + {
> + bfd_vma gp = riscv_global_pointer_value (info);
> + if (VALID_ITYPE_IMM (relocation + rel->r_addend - gp))
> + {
> + bfd_vma insn = bfd_getl32 (contents + rel->r_offset);
> + rel->r_addend -= gp;
> + bfd_putl32 (insn, contents + rel->r_offset);
> + }
> + else
> + r = bfd_reloc_overflow;
> + break;
> + }
> +
> + case INTERNAL_R_RISCV_REGREL_ADD:
> + case INTERNAL_R_RISCV_REGREL_SHXADD:
> + {
> + bfd_vma insn = bfd_getl32 (contents + rel->r_offset);
> + insn = (insn & ~(OP_MASK_RS2 << OP_SH_RS2)) | (X_GP << OP_SH_RS2);
> + bfd_putl32 (insn, contents + rel->r_offset);
> + break;
> + }
Nit: Entirely bogus indentation.
> --- a/bfd/elfxx-riscv.c
> +++ b/bfd/elfxx-riscv.c
> @@ -876,7 +876,70 @@ static const reloc_howto_type howto_table[] =
> false, /* partial_inplace */
> 0, /* src_mask */
> ENCODE_ITYPE_IMM (-1U), /* dst_mask */
> - false) /* pcrel_offset */
> + false), /* pcrel_offset */
Why the fiddling with existing code?
> + /* Global array non-constant subscript addressing */
> + HOWTO (R_RISCV_REGREL_LO12_I, /* type */
> + 0, /* rightshift */
> + 4, /* size */
> + 32, /* bitsize */
I realize you copy what other, similar entries have, but are these bit
sizes (and perhaps also sizes) actually sensible? This is a 12-bit
reloc, isn't it?
> --- a/gas/config/tc-riscv.c
> +++ b/gas/config/tc-riscv.c
> @@ -1957,6 +1957,13 @@ riscv_apply_const_reloc (bfd_reloc_code_real_type reloc_type, bfd_vma value)
> case BFD_RELOC_RISCV_LO12_I:
> return ENCODE_ITYPE_IMM (value);
>
> +
Please don't introduce double blank lines.
> @@ -3631,16 +3644,25 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
> continue;
>
> case 'j': /* Sign-extended immediate. */
> - p = percent_op_itype;
> - *imm_reloc = BFD_RELOC_RISCV_LO12_I;
> + p = percent_op_itype;
> + if (strncmp(asarg, "%regrel_lo", 9) == 0)
> + *imm_reloc = BFD_RELOC_RISCV_REGREL_LO12_I;
> + else
> + *imm_reloc = BFD_RELOC_RISCV_LO12_I;
> goto alu_op;
> case 'q': /* Store displacement. */
> - p = percent_op_stype;
> - *imm_reloc = BFD_RELOC_RISCV_LO12_S;
> + p = percent_op_stype;
> + if (strncmp(asarg, "%regrel_lo", 9) == 0)
> + *imm_reloc = BFD_RELOC_RISCV_REGREL_LO12_S;
> + else
> + *imm_reloc = BFD_RELOC_RISCV_LO12_S;
> goto load_store;
> case 'o': /* Load displacement. */
> - p = percent_op_itype;
> - *imm_reloc = BFD_RELOC_RISCV_LO12_I;
> + p = percent_op_itype;
> + if (strncmp(asarg, "%regrel_lo", 9) == 0)
> + *imm_reloc = BFD_RELOC_RISCV_REGREL_LO12_I;
> + else
> + *imm_reloc = BFD_RELOC_RISCV_LO12_I;
> goto load_store;
Why all the re-indentation, causing extra churn? And then while causing extra
churn you don't even fix the style problem (using hard tabs for 8 leading
blanks).
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/regrel-add.d
> @@ -0,0 +1,3 @@
> +#as: -march=rv32ia
> +#source regrel-add.s
> +#error_output: regrel-add.l
> \ No newline at end of file
Please (throughout) can you avoid introduction of files without trailing
newlines?
> --- a/include/elf/riscv.h
> +++ b/include/elf/riscv.h
> @@ -95,6 +95,14 @@ START_RELOC_NUMBERS (elf_riscv_reloc_type)
> RELOC_NUMBER (R_RISCV_TLSDESC_LOAD_LO12, 63)
> RELOC_NUMBER (R_RISCV_TLSDESC_ADD_LO12, 64)
> RELOC_NUMBER (R_RISCV_TLSDESC_CALL, 65)
> + RELOC_NUMBER (R_RISCV_REGREL_LO12_I, 77)
> + RELOC_NUMBER (R_RISCV_REGREL_LO12_S, 78)
> + RELOC_NUMBER (R_RISCV_REGREL_ADD, 79)
> + RELOC_NUMBER (R_RISCV_REGREL_SHXADD, 80)
> + RELOC_NUMBER (INTERNAL_R_RISCV_REGREL_LO12_I, 81)
> + RELOC_NUMBER (INTERNAL_R_RISCV_REGREL_LO12_S, 82)
> + RELOC_NUMBER (INTERNAL_R_RISCV_REGREL_ADD, 83)
> + RELOC_NUMBER (INTERNAL_R_RISCV_REGREL_SHXADD, 84)
These last four don't appear in the spec (and the numbers used collide with
whatever the spec may assign later). Why do yu need them, when you have ...
> END_RELOC_NUMBERS (R_RISCV_max)
>
> /* Internal relocations used exclusively by the relaxation pass. */
> @@ -105,6 +113,10 @@ END_RELOC_NUMBERS (R_RISCV_max)
> #define R_RISCV_GPREL_S (R_RISCV_max + 4)
> #define R_RISCV_TPREL_I (R_RISCV_max + 5)
> #define R_RISCV_TPREL_S (R_RISCV_max + 6)
> +#define INTERNAL_R_RISCV_REGREL_LO12_I (R_RISCV_max + 7)
> +#define INTERNAL_R_RISCV_REGREL_LO12_S (R_RISCV_max + 8)
> +#define INTERNAL_R_RISCV_REGREL_ADD (R_RISCV_max + 9)
> +#define INTERNAL_R_RISCV_REGREL_SHXADD (R_RISCV_max + 10)
... these?
> --- a/opcodes/ChangeLog
> +++ b/opcodes/ChangeLog
> @@ -1,3 +1,7 @@
> +2026-03-24 wengliqin <liqin.weng@spacemit.com>
> +
> + * riscv-opc.c: Update relocation definitions for new REGREL types.
I don't think this adequately describes the changes being made. (Such patching
of ChangeLog files shouldn't be done anymore anyway, aiui. If you want ChangeLog
entries, make them part of the commit message.)
Jan
More information about the Binutils
mailing list