diff mbox series

[v2,7/7] rust-target-config.bbclass: Update for new riscv TUNE_FEATURES

Message ID 1750203584-32065-8-git-send-email-mark.hatle@kernel.crashing.org
State Accepted, archived
Commit 88b59db87d2c65e5be0f3fee1ebf4ee64ef05f18
Headers show
Series ISA based RISC-V tune implementation | expand

Commit Message

Mark Hatle June 17, 2025, 11:39 p.m. UTC
From: Mark Hatle <mark.hatle@amd.com>

Add the new TUNE_FEATURES to the 'features:' list, based on matching output
with:

   rustc --target=riscv32i-unknown-none-elf -Ctarget-feature=help

Use the TUNE_RISCV_ABI instead of guessing for the ABI.

Pass the arch "as-is", since it should now be riscv32 or riscv64.

Signed-off-by: Mark Hatle <mark.hatle@amd.com>
---
 .../classes-recipe/rust-target-config.bbclass | 65 ++++++++++++-------
 meta/lib/oe/rust.py                           |  2 -
 2 files changed, 41 insertions(+), 26 deletions(-)

Comments

Alexander Kanavin Jan. 14, 2026, 10:16 a.m. UTC | #1
On Wed, 18 Jun 2025 at 01:39, Mark Hatle via lists.openembedded.org
<mark.hatle=kernel.crashing.org@lists.openembedded.org> wrote:
> -        tspec['llvm-abiname'] = "lp64d"
> +        tspec['llvm-abiname'] = d.getVar('TUNE_RISCV_ABI')
>      if "riscv32" in tspec['llvm-target']:
> -        tspec['llvm-abiname'] = "ilp32d"
> +        tspec['llvm-abiname'] = d.getVar('TUNE_RISCV_ABI')

Unfortunately this adds a dependency on TUNE_RISCV_ABI (which is set
only if the target is a risc-v machine) to rust-native's
rust_gen_targets task, breaking sstate reuse for it between risc-v and
any other target. I can imagine other native pieces written in rust
will have the same issue.

It's not immediately obvious to me how to address this, so I'd really
appreciate suggestions. The code is hairy.

Ticket: https://bugzilla.yoctoproject.org/show_bug.cgi?id=16132

Alex
Richard Purdie Jan. 14, 2026, 10:33 a.m. UTC | #2
On Wed, 2026-01-14 at 11:16 +0100, Alexander Kanavin wrote:
> On Wed, 18 Jun 2025 at 01:39, Mark Hatle via lists.openembedded.org
> <mark.hatle=kernel.crashing.org@lists.openembedded.org> wrote:
> > -        tspec['llvm-abiname'] = "lp64d"
> > +        tspec['llvm-abiname'] = d.getVar('TUNE_RISCV_ABI')
> >      if "riscv32" in tspec['llvm-target']:
> > -        tspec['llvm-abiname'] = "ilp32d"
> > +        tspec['llvm-abiname'] = d.getVar('TUNE_RISCV_ABI')
> 
> Unfortunately this adds a dependency on TUNE_RISCV_ABI (which is set
> only if the target is a risc-v machine) to rust-native's
> rust_gen_targets task, breaking sstate reuse for it between risc-v and
> any other target. I can imagine other native pieces written in rust
> will have the same issue.
> 
> It's not immediately obvious to me how to address this, so I'd really
> appreciate suggestions. The code is hairy.
> 
> Ticket: https://bugzilla.yoctoproject.org/show_bug.cgi?id=16132

Nice find. I worry about our sstate tests not covering this. We might need to do:

-rust_gen_target[vardepsexclude] += "ABIEXTENSION llvm_cpu"
+rust_gen_target[vardepsexclude] += "ABIEXTENSION llvm_cpu TUNE_RISCV_ABI"

Cheers,

Richard
Alexander Kanavin Jan. 14, 2026, 10:50 a.m. UTC | #3
On Wed, 14 Jan 2026 at 11:33, Richard Purdie
<richard.purdie@linuxfoundation.org> wrote:

> Nice find. I worry about our sstate tests not covering this. We might need to do:
>
> -rust_gen_target[vardepsexclude] += "ABIEXTENSION llvm_cpu"
> +rust_gen_target[vardepsexclude] += "ABIEXTENSION llvm_cpu TUNE_RISCV_ABI"

I thought of that, but would this rebuild correctly if someone first
builds for one TUNE_RISCV_ABI, then for another? I just don't know
enough about it to run experiments. It probably would, as that
variable feeds into TUNE_CCARGS.

Alex
Richard Purdie Jan. 14, 2026, 10:57 a.m. UTC | #4
On Wed, 2026-01-14 at 11:50 +0100, Alexander Kanavin wrote:
> On Wed, 14 Jan 2026 at 11:33, Richard Purdie
> <richard.purdie@linuxfoundation.org> wrote:
> 
> > Nice find. I worry about our sstate tests not covering this. We
> > might need to do:
> > 
> > -rust_gen_target[vardepsexclude] += "ABIEXTENSION llvm_cpu"
> > +rust_gen_target[vardepsexclude] += "ABIEXTENSION llvm_cpu
> > TUNE_RISCV_ABI"
> 
> I thought of that, but would this rebuild correctly if someone first
> builds for one TUNE_RISCV_ABI, then for another? I just don't know
> enough about it to run experiments. It probably would, as that
> variable feeds into TUNE_CCARGS.

The comment above this line says:

# These are accounted for in tmpdir path names so don't need to be in the task sig

so in theory this would handle changes to different machines with
different ABIs fine, as long as those ABIs have different tmpdir paths
which they should.

It doesn't guard against the value of TUNE_RISCV_ABI changing for a
given target as that wouldn't rebuild correctly.

I guess if we wanted to be really clear, we could probably do something
like:

RUSTCONFIG_EXCLUDEVARS = ""
RUSTCONFIG_EXCLUDEVARS:class-native = "ABIEXTENSION llvm_cpu TUNE_RISCV_ABI"
RUSTCONFIG_EXCLUDEVARS:class-nativesdk = "ABIEXTENSION llvm_cpu TUNE_RISCV_ABI"
rust_gen_target[vardepsexclude] += "${RUSTCONFIG_EXCLUDEVARS}"

but I guess we've not thought that was worth the effort in the past...

Cheers,

Richard
diff mbox series

Patch

diff --git a/meta/classes-recipe/rust-target-config.bbclass b/meta/classes-recipe/rust-target-config.bbclass
index c04940ce54..906a5083d7 100644
--- a/meta/classes-recipe/rust-target-config.bbclass
+++ b/meta/classes-recipe/rust-target-config.bbclass
@@ -77,8 +77,33 @@  def llvm_features_from_tune(d):
         f.append("+a15")
     if 'cortexa17' in feat:
         f.append("+a17")
-    if ('riscv64' in feat) or ('riscv32' in feat):
-        f.append("+a,+c,+d,+f,+m")
+    if 'rv' in feat:
+        if 'm' in feat:
+            f.append("+m")
+        if 'a' in feat:
+            f.append("+a")
+        if 'f' in feat:
+            f.append("+f")
+        if 'd' in feat:
+            f.append("+d")
+        if 'c' in feat:
+            f.append("+c")
+        if 'v' in feat:
+            f.append("+v")
+        if 'zicbom' in feat:
+            f.append("+zicbom")
+        if 'zicsr' in feat:
+            f.append("+zicsr")
+        if 'zifencei' in feat:
+            f.append("+zifencei")
+        if 'zba' in feat:
+            f.append("+zba")
+        if 'zbb' in feat:
+            f.append("+zbb")
+        if 'zbc' in feat:
+            f.append("+zbc")
+        if 'zbs' in feat:
+            f.append("+zbs")
     return f
 llvm_features_from_tune[vardepvalue] = "${@llvm_features_from_tune(d)}"
 
@@ -236,19 +261,19 @@  TARGET_POINTER_WIDTH[powerpc64le] = "64"
 TARGET_C_INT_WIDTH[powerpc64le] = "32"
 MAX_ATOMIC_WIDTH[powerpc64le] = "64"
 
-## riscv32gc-unknown-linux-{gnu, musl}
-DATA_LAYOUT[riscv32gc] = "e-m:e-p:32:32-i64:64-n32-S128"
-TARGET_ENDIAN[riscv32gc] = "little"
-TARGET_POINTER_WIDTH[riscv32gc] = "32"
-TARGET_C_INT_WIDTH[riscv32gc] = "32"
-MAX_ATOMIC_WIDTH[riscv32gc] = "32"
+## riscv32-unknown-linux-{gnu, musl}
+DATA_LAYOUT[riscv32] = "e-m:e-p:32:32-i64:64-n32-S128"
+TARGET_ENDIAN[riscv32] = "little"
+TARGET_POINTER_WIDTH[riscv32] = "32"
+TARGET_C_INT_WIDTH[riscv32] = "32"
+MAX_ATOMIC_WIDTH[riscv32] = "32"
 
-## riscv64gc-unknown-linux-{gnu, musl}
-DATA_LAYOUT[riscv64gc] = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
-TARGET_ENDIAN[riscv64gc] = "little"
-TARGET_POINTER_WIDTH[riscv64gc] = "64"
-TARGET_C_INT_WIDTH[riscv64gc] = "32"
-MAX_ATOMIC_WIDTH[riscv64gc] = "64"
+## riscv64-unknown-linux-{gnu, musl}
+DATA_LAYOUT[riscv64] = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
+TARGET_ENDIAN[riscv64] = "little"
+TARGET_POINTER_WIDTH[riscv64] = "64"
+TARGET_C_INT_WIDTH[riscv64] = "32"
+MAX_ATOMIC_WIDTH[riscv64] = "64"
 
 ## loongarch64-unknown-linux-{gnu, musl}
 DATA_LAYOUT[loongarch64] = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
@@ -271,19 +296,11 @@  def arch_to_rust_target_arch(arch):
         return "arm"
     elif arch == "powerpc64le":
         return "powerpc64"
-    elif arch == "riscv32gc":
-        return "riscv32"
-    elif arch == "riscv64gc":
-        return "riscv64"
     else:
         return arch
 
 # Convert a rust target string to a llvm-compatible triplet
 def rust_sys_to_llvm_target(sys):
-    if sys.startswith('riscv32gc-'):
-        return sys.replace('riscv32gc-', 'riscv32-', 1)
-    if sys.startswith('riscv64gc-'):
-        return sys.replace('riscv64gc-', 'riscv64-', 1)
     return sys
 
 # generates our target CPU value
@@ -380,9 +397,9 @@  def rust_gen_target(d, thing, wd, arch):
     else:
         tspec['env'] = "gnu"
     if "riscv64" in tspec['llvm-target']:
-        tspec['llvm-abiname'] = "lp64d"
+        tspec['llvm-abiname'] = d.getVar('TUNE_RISCV_ABI')
     if "riscv32" in tspec['llvm-target']:
-        tspec['llvm-abiname'] = "ilp32d"
+        tspec['llvm-abiname'] = d.getVar('TUNE_RISCV_ABI')
     if "loongarch64" in tspec['llvm-target']:
         tspec['llvm-abiname'] = "lp64d"
     tspec['vendor'] = "unknown"
diff --git a/meta/lib/oe/rust.py b/meta/lib/oe/rust.py
index 185553eeeb..1dc9cf150d 100644
--- a/meta/lib/oe/rust.py
+++ b/meta/lib/oe/rust.py
@@ -8,6 +8,4 @@ 
 def arch_to_rust_arch(arch):
     if arch == "ppc64le":
         return "powerpc64le"
-    if arch in ('riscv32', 'riscv64'):
-        return arch + 'gc'
     return arch