Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
From 3c4bff73592e8fba5ffc56f8857ea6231405b73b Mon Sep 17 00:00:00 2001
From: Michael Forney <mforney@mforney.org>
Date: Tue, 2 Jun 2026 10:57:06 -0700
Subject: [PATCH] rv64: use pc-relative addressing for globals

When extern was added, the rv64 code switched regular globals from
using la (a pseudo-instruction that uses pc-relative addressing
with auipc + addi) to lui + addi (absolute addressing). Presumably,
this was done to match gcc's output with -fPIC and -fno-PIC
respectively. However, the key difference here is actually the
directive `%option pic` vs `%option nopic`, which determines whether
la uses the GOT or not.

This broke linking as PIE (for instance in compilers with
--enable-default-pie), even when there are no global references
outside the executable. The other architectures always use pc-relative
addressing, so rv64 should do the same.

It turns out there are more specific pseudo-instructions lla and
lga we can use instead. lla uses auipc+addi, and lga uses auipc+ld
from the GOT.

lga does not allow an offset. If you try to use one, it will assemble
without error, but fail at link time with

(.text+0x10): dangerous relocation: The addend isn't allowed for R_RISCV_GOT_HI20

For now, just add a check for this. A proper fix involves some
changes to rv64/isel like is done for amd64.
---
rv64/emit.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/rv64/emit.c b/rv64/emit.c
index f4b3236..f82a1e2 100644
--- a/rv64/emit.c
+++ b/rv64/emit.c
@@ -133,8 +133,12 @@ emitaddr(Con *c, FILE *f)
{
assert((c->sym.type & ~SExt) == SGlo);
fputs(str(c->sym.id), f);
- if (c->bits.i)
+ if (c->bits.i) {
+ /* TODO: fix isel to ensure no offset for SGlo */
+ if (c->sym.type & SExt)
+ die("extern with offset is not supported");
fprintf(f, "+%"PRIi64, c->bits.i);
+ }
}

static void
@@ -233,14 +237,8 @@ loadaddr(Con *c, char *rn, FILE *f)

switch (c->sym.type) {
case SGlo:
- fprintf(f, "\tlui %s, %%hi(", rn);
- emitaddr(c, f);
- fprintf(f, ")\n\taddi %s, %s, %%lo(", rn, rn);
- emitaddr(c, f);
- fputs(")\n", f);
- break;
case SExt:
- fprintf(f, "\tla %s, ", rn);
+ fprintf(f, "\t%s %s, ", c->sym.type == SExt ? "lga" : "lla", rn);
emitaddr(c, f);
fputc('\n', f);
break;
--
2.55.0

6 changes: 3 additions & 3 deletions srcpkgs/qbe/template
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# Template file for 'qbe'
pkgname=qbe
version=1.2
version=1.3
revision=1
build_style=gnu-makefile
make_use_env=yes
short_desc="Small embeddable C compiler backend"
maintainer="Orphaned <orphan@voidlinux.org>"
maintainer="kurth4cker <kurth4cker@disroot.org>"
license="MIT"
homepage="https://c9x.me/compile/"
distfiles="https://c9x.me/compile/release/qbe-${version}.tar.xz"
checksum=a6d50eb952525a234bf76ba151861f73b7a382ac952d985f2b9af1df5368225d
checksum=d587905d620dc5e1d2bfa7c2cc642b9b837aa89a3188c6e37b53d756cf66e320

# Currently only riscv64, aarch64 and x86_64 targets are supported and the checks
# test the compiled binaries.
Expand Down