Rollup merge of #96971 - zhaixiaojuan:master, r=wesleywiser

Initial support for loongarch64-unknown-linux-gnu

Hi, We hope to add a new port in rust for LoongArch.

LoongArch intro
LoongArch is a RISC style ISA which is independently designed by Loongson
Technology in China. It is divided into two versions, the 32-bit version (LA32)
and the 64-bit version (LA64). LA64 applications have application-level
backward binary compatibility with LA32 applications. LoongArch is composed of
a basic part (Loongson Base) and an expanded part. The expansion part includes
Loongson Binary Translation (LBT), Loongson VirtualiZation (LVZ), Loongson SIMD
EXtension (LSX) and Loongson Advanced SIMD EXtension(LASX).

Currently the LA464 processor core supports LoongArch ISA and the Loongson
3A5000 processor integrates 4 64-bit LA464 cores. LA464 is a four-issue 64-bit
high-performance processor core. It can be used as a single core for high-end
embedded and desktop applications, or as a basic processor core to form an
on-chip multi-core system for server and high-performance machine applications.

Documentations:
ISA:
https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html
ABI:
https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html
More docs can be found at:
https://loongson.github.io/LoongArch-Documentation/README-EN.html

Since last year, we have locally adapted two versions of rust, rust1.41 and rust1.57, and completed the test locally.
I'm not sure if I'm submitting all the patches at once, so I split up the patches and here's one of the commits
This commit is contained in:
Michael Goulet 2023-04-11 20:28:45 -07:00 committed by GitHub
commit 4a24aab220
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 150 additions and 4 deletions

View file

@ -15,6 +15,7 @@
const MIN_ALIGN: usize = 8;
#[cfg(any(target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "loongarch64",
target_arch = "mips64",
target_arch = "s390x",
target_arch = "sparc64"))]

View file

@ -127,6 +127,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
"msp430" => Architecture::Msp430,
"hexagon" => Architecture::Hexagon,
"bpf" => Architecture::Bpf,
"loongarch64" => Architecture::LoongArch64,
// Unsupported architecture.
_ => return None,
};
@ -190,6 +191,10 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
}
e_flags
}
Architecture::LoongArch64 => {
// Source: https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html#_e_flags_identifies_abi_type_and_version
elf::EF_LARCH_OBJABI_V1 | elf::EF_LARCH_ABI_DOUBLE_FLOAT
}
_ => 0,
};
// adapted from LLVM's `MCELFObjectTargetWriter::getOSABI`

View file

@ -10,6 +10,7 @@
"aarch64",
"amdgpu",
"avr",
"loongarch",
"m68k",
"mips",
"powerpc",

View file

@ -146,6 +146,12 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) {
#define SUBTARGET_HEXAGON
#endif
#ifdef LLVM_COMPONENT_LOONGARCH
#define SUBTARGET_LOONGARCH SUBTARGET(LoongArch)
#else
#define SUBTARGET_LOONGARCH
#endif
#define GEN_SUBTARGETS \
SUBTARGET_X86 \
SUBTARGET_ARM \
@ -159,6 +165,7 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) {
SUBTARGET_SPARC \
SUBTARGET_HEXAGON \
SUBTARGET_RISCV \
SUBTARGET_LOONGARCH \
#define SUBTARGET(x) \
namespace llvm { \

View file

@ -102,6 +102,14 @@ fn init() { }
LLVMInitializeM68kAsmPrinter,
LLVMInitializeM68kAsmParser
);
init_target!(
llvm_component = "loongarch",
LLVMInitializeLoongArchTargetInfo,
LLVMInitializeLoongArchTarget,
LLVMInitializeLoongArchTargetMC,
LLVMInitializeLoongArchAsmPrinter,
LLVMInitializeLoongArchAsmParser
);
init_target!(
llvm_component = "mips",
LLVMInitializeMipsTargetInfo,

View file

@ -0,0 +1,17 @@
use crate::spec::{Target, TargetOptions};
pub fn target() -> Target {
Target {
llvm_target: "loongarch64-unknown-linux-gnu".into(),
pointer_width: 64,
data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
arch: "loongarch64".into(),
options: TargetOptions {
cpu: "generic".into(),
features: "+f,+d".into(),
llvm_abiname: "lp64d".into(),
max_atomic_width: Some(64),
..super::linux_gnu_base::opts()
},
}
}

View file

@ -1021,6 +1021,7 @@ fn $module() {
("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
("loongarch64-unknown-linux-gnu", loongarch64_unknown_linux_gnu),
("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu),
("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),

View file

@ -88,7 +88,7 @@ changelog-seen = 2
# the resulting rustc being unable to compile for the disabled architectures.
#
# To add support for new targets, see https://rustc-dev-guide.rust-lang.org/building/new-target.html.
#targets = "AArch64;ARM;BPF;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;Sparc;SystemZ;WebAssembly;X86"
#targets = "AArch64;ARM;BPF;Hexagon;LoongArch;MSP430;Mips;NVPTX;PowerPC;RISCV;Sparc;SystemZ;WebAssembly;X86"
# LLVM experimental targets to build support for. These targets are specified in
# the same format as above, but since these targets are experimental, they are

View file

@ -895,6 +895,7 @@ pub mod consts {
/// - x86_64
/// - arm
/// - aarch64
/// - loongarch64
/// - m68k
/// - mips
/// - mips64

View file

@ -231,6 +231,7 @@ pub struct stat {
}
#[cfg(any(
target_arch = "loongarch64",
target_arch = "mips64",
target_arch = "s390x",
target_arch = "sparc64",

View file

@ -77,6 +77,9 @@
#[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))]
const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11
#[cfg(target_arch = "loongarch64")]
const UNWIND_DATA_REG: (i32, i32) = (4, 5); // a0, a1
// The following code is based on GCC's C and C++ personality routines. For reference, see:
// https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c

View file

@ -22,6 +22,7 @@
#[cfg(any(
target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "loongarch64",
target_arch = "mips64",
target_arch = "s390x",
target_arch = "sparc64",

View file

@ -75,6 +75,9 @@ pub enum _Unwind_Reason_Code {
#[cfg(all(target_arch = "hexagon", target_os = "linux"))]
pub const unwinder_private_data_size: usize = 35;
#[cfg(target_arch = "loongarch64")]
pub const unwinder_private_data_size: usize = 2;
#[repr(C)]
pub struct _Unwind_Exception {
pub exception_class: _Unwind_Exception_Class,

View file

@ -304,6 +304,7 @@ def default_build_triple(verbose):
'i486': 'i686',
'i686': 'i686',
'i786': 'i686',
'loongarch64': 'loongarch64',
'm68k': 'm68k',
'powerpc': 'powerpc',
'powerpc64': 'powerpc64',

View file

@ -129,7 +129,8 @@ pub unsafe fn setup(_build: &mut crate::Build) {}
/* Extra values not defined in the built-in targets yet, but used in std */
(Some(Mode::Std), "target_env", Some(&["libnx"])),
// (Some(Mode::Std), "target_os", Some(&[])),
(Some(Mode::Std), "target_arch", Some(&["asmjs", "spirv", "nvptx", "xtensa"])),
// #[cfg(bootstrap)] loongarch64
(Some(Mode::Std), "target_arch", Some(&["asmjs", "spirv", "nvptx", "xtensa", "loongarch64"])),
/* Extra names used by dependencies */
// FIXME: Used by serde_json, but we should not be triggering on external dependencies.
(Some(Mode::Rustc), "no_btreemap_remove_entry", None),

View file

@ -291,7 +291,7 @@ fn run(self, builder: &Builder<'_>) -> LlvmResult {
let llvm_targets = match &builder.config.llvm_targets {
Some(s) => s,
None => {
"AArch64;ARM;BPF;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;\
"AArch64;ARM;BPF;Hexagon;LoongArch;MSP430;Mips;NVPTX;PowerPC;RISCV;\
Sparc;SystemZ;WebAssembly;X86"
}
};

View file

@ -29,6 +29,7 @@
- [\*-linux-ohos](platform-support/openharmony.md)
- [\*-unknown-fuchsia](platform-support/fuchsia.md)
- [\*-kmc-solid_\*](platform-support/kmc-solid.md)
- [loongarch\*-unknown-linux-\*](platform-support/loongarch-linux.md)
- [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md)
- [mips64-openwrt-linux-musl](platform-support/mips64-openwrt-linux-musl.md)
- [mipsel-sony-psx](platform-support/mipsel-sony-psx.md)

View file

@ -266,6 +266,7 @@ target | std | host | notes
`i686-uwp-windows-gnu` | ? | |
`i686-uwp-windows-msvc` | ? | |
`i686-wrs-vxworks` | ? | |
[`loongarch64-unknown-linux-gnu`](platform-support/loongarch-linux.md) | ? | | LoongArch64 Linux (LP64D ABI)
[`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? | | Motorola 680x0 Linux
`mips-unknown-linux-uclibc` | ✓ | | MIPS Linux with uClibc
[`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? | | MIPS64 for OpenWrt Linux MUSL

View file

@ -0,0 +1,92 @@
# loongarch\*-unknown-linux-\*
**Tier: 3**
[LoongArch] is a new RISC ISA developed by Loongson Technology Corporation Limited.
[LoongArch]: https://loongson.github.io/LoongArch-Documentation/README-EN.html
The target name follow this format: `<machine>-<vendor>-<os><fabi_suffix>, where `<machine>` specifies the CPU family/model, `<vendor>` specifies the vendor and `<os>` the operating system name.
While the integer base ABI is implied by themachinefield, the floating point base ABI type is encoded into the os field of the specifier using the string suffix `<fabi-suffix>`.
| `<fabi-suffix>` | `Description` |
|------------------------|--------------------------------------------------------------------|
| f64 | The base ABI use 64-bits FPRs for parameter passing.(lp64d)|
| f32 | The base ABI uses 32-bit FPRs for parameter passing. (lp64f)|
| sf | The base ABI uses no FPR for parameter passing. (lp64s) |
|`ABI type(Base ABI/ABI extension)`| `C library` | `kernel` | `target tuple` |
|----------------------------------|-------------|----------|----------------------------------|
| lp64d/base | glibc | linux | loongarch64-unknown-linux-gnu |
| lp64f/base | glibc | linux | loongarch64-unknown-linux-gnuf32 |
| lp64s/base | glibc | linux | loongarch64-unknown-linux-gnusf |
| lp64d/base | musl libc | linux | loongarch64-unknown-linux-musl|
| lp64f/base | musl libc | linux | loongarch64-unknown-linux-muslf32|
| lp64s/base | musl libc | linux | loongarch64-unknown-linux-muslsf |
## Target maintainers
- [ZHAI xiaojuan](https://github.com/zhaixiaojuan) `zhaixiaojuan@loongson.cn`
- [WANG rui](https://github.com/heiher) `wangrui@loongson.cn`
- [ZHAI xiang](https://github.com/xiangzhai) `zhaixiang@loongson.cn`
- [WANG Xuerui](https://github.com/xen0n) `git@xen0n.name`
## Requirements
This target is cross-compiled.
A GNU toolchain for LoongArch target is required. It can be downloaded from https://github.com/loongson/build-tools/releases, or built from the source code of GCC (12.1.0 or later) and Binutils (2.40 or later).
## Building the target
The target can be built by enabling it for a `rustc` build.
```toml
[build]
target = ["loongarch64-unknown-linux-gnu"]
```
Make sure `loongarch64-unknown-linux-gnu-gcc` can be searched from the directories specified in`$PATH`. Alternatively, you can use GNU LoongArch Toolchain by adding the following to `config.toml`:
```toml
[target.loongarch64-unknown-linux-gnu]
# ADJUST THIS PATH TO POINT AT YOUR TOOLCHAIN
cc = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc"
cxx = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-g++"
ar = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-ar"
ranlib = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-ranlib"
linker = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc"
```
## Cross-compilation
This target can be cross-compiled on a `x86_64-unknown-linux-gnu` host. Cross-compilation on other hosts may work but is not tested.
## Testing
To test a cross-compiled binary on your build system, install the qemu binary that supports the LoongArch architecture and execute the following commands.
```text
CC_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc \
CXX_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-g++ \
AR_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc-ar \
CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNUN_LINKER=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc \
# SET TARGET SYSTEM LIBRARY PATH
CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNUN_RUNNER="qemu-loongarch64 -L /TOOLCHAIN_PATH/TARGET_LIBRAY_PATH" \
cargo run --target loongarch64-unknown-linux-gnu --release
```
Tested on x86 architecture, other architectures not tested.
## Building Rust programs
Rust does not yet ship pre-compiled artifacts for this target. To compile for this target, you will either need to build Rust with the target enabled (see "Building the target" above), or build your own copy of `std` by using `build-std` or similar.
If `rustc` has support for that target and the library artifacts are available, then Rust static libraries can be built for that target:
```shell
$ rustc --target loongarch64-unknown-linux-gnu your-code.rs --crate-type staticlib
$ ls libyour_code.a
```
On Rust Nightly it's possible to build without the target artifacts available:
```text
cargo build -Z build-std --target loongarch64-unknown-linux-gnu
```

View file

@ -517,6 +517,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
"aarch64" => "AArch64",
"arm" => "ARM",
"asmjs" => "JavaScript",
"loongarch64" => "LoongArch LA64",
"m68k" => "M68k",
"mips" => "MIPS",
"mips64" => "MIPS-64",

View file

@ -4,7 +4,7 @@ warning: unexpected `cfg` condition value
LL | #[cfg(target(os = "linux", arch = "X"))]
| ^^^^^^^^^^
|
= note: expected values for `target_arch` are: aarch64, arm, avr, bpf, hexagon, m68k, mips, mips64, msp430, nvptx64, powerpc, powerpc64, riscv32, riscv64, s390x, sparc, sparc64, wasm32, wasm64, x86, x86_64
= note: expected values for `target_arch` are: aarch64, arm, avr, bpf, hexagon, loongarch64, m68k, mips, mips64, msp430, nvptx64, powerpc, powerpc64, riscv32, riscv64, s390x, sparc, sparc64, wasm32, wasm64, x86, x86_64
= note: `#[warn(unexpected_cfgs)]` on by default
warning: 1 warning emitted