Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial support for loongarch64-unknown-linux-gnu #96971

Merged
merged 11 commits into from
Apr 12, 2023
1 change: 1 addition & 0 deletions compiler/rustc_codegen_gcc/example/alloc_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"))]
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,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,
};
Expand Down Expand Up @@ -191,6 +192,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`
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_llvm/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const OPTIONAL_COMPONENTS: &[&str] = &[
"aarch64",
"amdgpu",
"avr",
"loongarch",
"m68k",
"mips",
"powerpc",
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand All @@ -159,6 +165,7 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) {
SUBTARGET_SPARC \
SUBTARGET_HEXAGON \
SUBTARGET_RISCV \
SUBTARGET_LOONGARCH \

#define SUBTARGET(x) \
namespace llvm { \
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ pub fn initialize_available_targets() {
LLVMInitializeM68kAsmPrinter,
LLVMInitializeM68kAsmParser
);
init_target!(
llvm_component = "loongarch",
LLVMInitializeLoongArchTargetInfo,
LLVMInitializeLoongArchTarget,
LLVMInitializeLoongArchTargetMC,
LLVMInitializeLoongArchAsmPrinter,
LLVMInitializeLoongArchAsmParser
);
init_target!(
llvm_component = "mips",
LLVMInitializeMipsTargetInfo,
Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs
Original file line number Diff line number Diff line change
@@ -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(),
wesleywiser marked this conversation as resolved.
Show resolved Hide resolved
llvm_abiname: "lp64d".into(),
max_atomic_width: Some(64),
..super::linux_gnu_base::opts()
},
}
}
1 change: 1 addition & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1021,6 +1021,7 @@ supported_targets! {
("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),
Expand Down
2 changes: 1 addition & 1 deletion config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions library/std/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -895,6 +895,7 @@ pub mod consts {
/// - x86_64
/// - arm
/// - aarch64
/// - loongarch64
/// - m68k
/// - mips
/// - mips64
Expand Down
1 change: 1 addition & 0 deletions library/std/src/os/linux/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ mod arch {
}

#[cfg(any(
target_arch = "loongarch64",
target_arch = "mips64",
target_arch = "s390x",
target_arch = "sparc64",
Expand Down
3 changes: 3 additions & 0 deletions library/std/src/personality/gcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1
#[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
Expand Down
1 change: 1 addition & 0 deletions library/std/src/sys/common/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub 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",
Expand Down
3 changes: 3 additions & 0 deletions library/unwind/src/libunwind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ pub const unwinder_private_data_size: usize = 20;
#[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,
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ def default_build_triple(verbose):
'i486': 'i686',
'i686': 'i686',
'i786': 'i686',
'loongarch64': 'loongarch64',
'm68k': 'm68k',
'powerpc': 'powerpc',
'powerpc64': 'powerpc64',
Expand Down
3 changes: 2 additions & 1 deletion src/bootstrap/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)]
/* 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
wesleywiser marked this conversation as resolved.
Show resolved Hide resolved
(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),
Expand Down
2 changes: 1 addition & 1 deletion src/bootstrap/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ impl Step for Llvm {
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"
}
};
Expand Down
1 change: 1 addition & 0 deletions src/doc/rustc/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
- [\*-android and \*-androideabi](platform-support/android.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)
Expand Down
1 change: 1 addition & 0 deletions src/doc/rustc/src/platform-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,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
Expand Down
92 changes: 92 additions & 0 deletions src/doc/rustc/src/platform-support/loongarch-linux.md
Original file line number Diff line number Diff line change
@@ -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.
wesleywiser marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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.
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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, Is it better to fix this PR or a new one? thanks

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A new PR works better I think given that this PR is already included in a rollup.

While the integer base ABI is implied by the machine field, 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
```
1 change: 1 addition & 0 deletions src/librustdoc/clean/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@ impl<'a> fmt::Display for Display<'a> {
"aarch64" => "AArch64",
"arm" => "ARM",
"asmjs" => "JavaScript",
"loongarch64" => "LoongArch LA64",
"m68k" => "M68k",
"mips" => "MIPS",
"mips64" => "MIPS-64",
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/check-cfg/compact-values.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down