https://github.com/Mintsuki updated 
https://github.com/llvm/llvm-project/pull/223703

>From 80473a6fe404c741d7832383e214e3d44ff12ef5 Mon Sep 17 00:00:00 2001
From: Mintsuki <[email protected]>
Date: Tue, 15 Sep 2026 14:51:23 +0200
Subject: [PATCH] [clang][Driver] Use the bare-metal toolchain for LoongArch

Clang did not handle loongarch32-*-none-elf and loongarch64-*-none-elf
in the bare-metal toolchain, so these targets fell back to the generic
ELF toolchain, which links by running gcc. Any -fuse-ld or --ld-path
option is forwarded to gcc, and linking fails when there is no gcc. On
a host whose gcc does not target LoongArch, which is the usual case when
cross compiling, gcc drives the linker for the host, and the link fails
with errors such as "a.o is incompatible with elf_x86_64". The generic
ELF toolchain also searches /usr/local/include and /usr/include of the
host.

The other bare-metal targets, Arm, AArch64, RISC-V, PowerPC, and x86
since 25f0d08bafa4, use the bare-metal toolchain, which runs the
selected linker directly and does not search host include directories.

Handle LoongArch there as well. As the GNU toolchain does for LoongArch,
and the bare-metal toolchain already does for RISC-V, pass -X to the
linker, and --no-relax with -mno-relax.

Assisted-by: Claude Code (Claude Opus 5)
Signed-off-by: Mintsuki <[email protected]>
---
 clang/docs/ReleaseNotes.md                |  5 ++++
 clang/lib/Driver/ToolChains/BareMetal.cpp | 11 +++++++--
 clang/test/Driver/baremetal.cpp           | 30 +++++++++++++++++++++++
 clang/test/Driver/loongarch-toolchain.c   |  4 +++
 4 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 043a0ddae2a6cd..1a052ff8b7db98 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -769,6 +769,11 @@ features cannot lower the translation-unit ABI level;
 
 #### LoongArch Support
 
+- `loongarch32-*-none-elf` and `loongarch64-*-none-elf` targets now use the
+  bare-metal toolchain, like other bare-metal targets. The linker is run
+  directly instead of through `gcc`, and host include directories are no
+  longer searched.
+
 #### RISC-V Support
 
 - Fixed a bug where the `interrupt` attribute did not accept `machine` together
diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp 
b/clang/lib/Driver/ToolChains/BareMetal.cpp
index 19fbb6b07cebec..619a7fb9746159 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -55,6 +55,12 @@ static bool isX86BareMetal(const llvm::Triple &Triple) {
          Triple.getEnvironmentName() == "elf";
 }
 
+/// Is the triple loongarch{32,64}-*-none-elf?
+static bool isLoongArchBareMetal(const llvm::Triple &Triple) {
+  return Triple.isLoongArch() && Triple.getOS() == llvm::Triple::UnknownOS &&
+         Triple.getEnvironmentName() == "elf";
+}
+
 static bool findRISCVMultilibs(const Driver &D,
                                const llvm::Triple &TargetTriple,
                                const ArgList &Args, DetectedMultilibs &Result) 
{
@@ -281,7 +287,8 @@ void BareMetal::findMultilibs(const Driver &D, const 
llvm::Triple &Triple,
 bool BareMetal::handlesTarget(const llvm::Triple &Triple) {
   return arm::isARMEABIBareMetal(Triple) ||
          aarch64::isAArch64BareMetal(Triple) || isRISCVBareMetal(Triple) ||
-         isPPCBareMetal(Triple) || isX86BareMetal(Triple);
+         isPPCBareMetal(Triple) || isX86BareMetal(Triple) ||
+         isLoongArchBareMetal(Triple);
 }
 
 Tool *BareMetal::buildLinker() const {
@@ -547,7 +554,7 @@ void baremetal::Linker::ConstructJob(Compilation &C, const 
JobAction &JA,
     return;
   }
 
-  if (Triple.isRISCV()) {
+  if (Triple.isLoongArch() || Triple.isRISCV()) {
     CmdArgs.push_back("-X");
     if (Args.hasArg(options::OPT_mno_relax))
       CmdArgs.push_back("--no-relax");
diff --git a/clang/test/Driver/baremetal.cpp b/clang/test/Driver/baremetal.cpp
index aa2aa9696c08e0..89e40d4fd26e5e 100644
--- a/clang/test/Driver/baremetal.cpp
+++ b/clang/test/Driver/baremetal.cpp
@@ -646,6 +646,36 @@
 // CHECK-PCX86_64ELF-SAME: "-lc"
 // CHECK-PCX86_64ELF-SAME: "-o" "a.out"
 
+// RUN: %clang -no-canonical-prefixes %s -### --target=loongarch32-unknown-elf 
2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-LA32ELF %s
+// CHECK-LA32ELF: InstalledDir: [[INSTALLEDDIR:.+]]
+// CHECK-LA32ELF: "-nostdsysteminc"
+// CHECK-LA32ELF-SAME: "-resource-dir" "[[RESOURCE:[^"]+]]"
+// CHECK-LA32ELF-SAME: "-internal-isystem" 
"[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include{{[/\\]+}}c++{{[/\\]+}}v1"
+// CHECK-LA32ELF-SAME: "-internal-isystem" "[[RESOURCE]]{{[/\\]+}}include"
+// CHECK-LA32ELF-SAME: "-internal-isystem" 
"[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include"
+// CHECK-LA32ELF-NEXT: ld{{(.exe)?}}" "-Bstatic" "-m" "elf32loongarch" "-X"
+// CHECK-LA32ELF-SAME: 
"-L[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}lib"
+// CHECK-LA32ELF-SAME:"{{.*}}.o"
+// CHECK-LA32ELF-SAME: "{{[^"]*}}libclang_rt.builtins.a"
+// CHECK-LA32ELF-SAME: "-lc"
+// CHECK-LA32ELF-SAME: "-o" "a.out"
+
+// RUN: %clang -no-canonical-prefixes %s -### --target=loongarch64-unknown-elf 
2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-LA64ELF %s
+// CHECK-LA64ELF: InstalledDir: [[INSTALLEDDIR:.+]]
+// CHECK-LA64ELF: "-nostdsysteminc"
+// CHECK-LA64ELF-SAME: "-resource-dir" "[[RESOURCE:[^"]+]]"
+// CHECK-LA64ELF-SAME: "-internal-isystem" 
"[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include{{[/\\]+}}c++{{[/\\]+}}v1"
+// CHECK-LA64ELF-SAME: "-internal-isystem" "[[RESOURCE]]{{[/\\]+}}include"
+// CHECK-LA64ELF-SAME: "-internal-isystem" 
"[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include"
+// CHECK-LA64ELF-NEXT: ld{{(.exe)?}}" "-Bstatic" "-m" "elf64loongarch" "-X"
+// CHECK-LA64ELF-SAME: 
"-L[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}lib"
+// CHECK-LA64ELF-SAME:"{{.*}}.o"
+// CHECK-LA64ELF-SAME: "{{[^"]*}}libclang_rt.builtins.a"
+// CHECK-LA64ELF-SAME: "-lc"
+// CHECK-LA64ELF-SAME: "-o" "a.out"
+
 // Check that compiler-rt library without the arch filename suffix will
 // be used if present.
 // RUN: rm -rf %t.dir/baremetal_clang_rt_noarch
diff --git a/clang/test/Driver/loongarch-toolchain.c 
b/clang/test/Driver/loongarch-toolchain.c
index 54a2519e0a70df..de7720b34ea533 100644
--- a/clang/test/Driver/loongarch-toolchain.c
+++ b/clang/test/Driver/loongarch-toolchain.c
@@ -31,6 +31,10 @@
 // RUN:   FileCheck --check-prefix=LA64-RELAX %s
 // RUN: %clang --target=loongarch64-unknown-linux-gnu -mno-relax -### %s 2>&1 
| \
 // RUN:   FileCheck --check-prefix=LA64-NORELAX %s
+// RUN: %clang --target=loongarch64-unknown-elf -### %s 2>&1 | \
+// RUN:   FileCheck --check-prefix=LA64-RELAX %s
+// RUN: %clang --target=loongarch64-unknown-elf -mno-relax -### %s 2>&1 | \
+// RUN:   FileCheck --check-prefix=LA64-NORELAX %s
 // LA64-RELAX:     "-X"
 // LA64-RELAX-NOT: "--no-relax"
 // LA64-NORELAX:   "-X" "--no-relax"

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to