diff --git a/config.toml.example b/config.toml.example index 99073416334f5..eb7cd61a1b07e 100644 --- a/config.toml.example +++ b/config.toml.example @@ -61,8 +61,8 @@ # the same format as above, but since these targets are experimental, they are # not built by default and the experimental Rust compilation targets that depend # on them will not work unless the user opts in to building them. By default the -# `WebAssembly` target is enabled when compiling LLVM from scratch. -#experimental-targets = "WebAssembly" +# `WebAssembly` and `RISCV` targets are enabled when compiling LLVM from scratch. +#experimental-targets = "WebAssembly;RISCV" # Cap the number of parallel linker invocations when compiling LLVM. # This can be useful when building LLVM with debug info, which significantly diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 0a8a5c87d0da1..1a94d597ef895 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -507,7 +507,7 @@ impl Config { set(&mut config.llvm_link_shared, llvm.link_shared); config.llvm_targets = llvm.targets.clone(); config.llvm_experimental_targets = llvm.experimental_targets.clone() - .unwrap_or("WebAssembly".to_string()); + .unwrap_or("WebAssembly;RISCV".to_string()); config.llvm_link_jobs = llvm.link_jobs; config.llvm_clang_cl = llvm.clang_cl.clone(); } diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile index 6302f550091ad..bfc5e712f76c3 100644 --- a/src/ci/docker/dist-various-1/Dockerfile +++ b/src/ci/docker/dist-various-1/Dockerfile @@ -102,6 +102,7 @@ ENV TARGETS=$TARGETS,thumbv6m-none-eabi ENV TARGETS=$TARGETS,thumbv7m-none-eabi ENV TARGETS=$TARGETS,thumbv7em-none-eabi ENV TARGETS=$TARGETS,thumbv7em-none-eabihf +ENV TARGETS=$TARGETS,riscv32imac-unknown-none-elf ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \ diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 5910e55def396..4e24a26983d48 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -100,6 +100,10 @@ fn main() { optional_components.push("hexagon"); } + if major > 6 { + optional_components.push("riscv"); + } + // FIXME: surely we don't need all these components, right? Stuff like mcjit // or interpreter the compiler itself never uses. let required_components = &["ipo", diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 05f6b5b5fbd28..ffa97bd6fa59d 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -90,6 +90,12 @@ pub fn initialize_available_targets() { LLVMInitializeMSP430Target, LLVMInitializeMSP430TargetMC, LLVMInitializeMSP430AsmPrinter); + init_target!(llvm_component = "riscv", + LLVMInitializeRISCVTargetInfo, + LLVMInitializeRISCVTarget, + LLVMInitializeRISCVTargetMC, + LLVMInitializeRISCVAsmPrinter, + LLVMInitializeRISCVAsmParser); init_target!(llvm_component = "sparc", LLVMInitializeSparcTargetInfo, LLVMInitializeSparcTarget, diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs index ca5aba5b6420a..f65fa341231e3 100644 --- a/src/librustc_target/abi/call/mod.rs +++ b/src/librustc_target/abi/call/mod.rs @@ -23,6 +23,7 @@ mod nvptx; mod nvptx64; mod powerpc; mod powerpc64; +mod riscv; mod s390x; mod sparc; mod sparc64; @@ -500,6 +501,8 @@ impl<'a, Ty> FnType<'a, Ty> { "nvptx" => nvptx::compute_abi_info(self), "nvptx64" => nvptx64::compute_abi_info(self), "hexagon" => hexagon::compute_abi_info(self), + "riscv32" => riscv::compute_abi_info(self, 32), + "riscv64" => riscv::compute_abi_info(self, 64), a => return Err(format!("unrecognized arch \"{}\" in target specification", a)) } diff --git a/src/librustc_target/abi/call/riscv.rs b/src/librustc_target/abi/call/riscv.rs new file mode 100644 index 0000000000000..fe0d7485c158b --- /dev/null +++ b/src/librustc_target/abi/call/riscv.rs @@ -0,0 +1,59 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Reference: RISC-V ELF psABI specification +// https://github.com/riscv/riscv-elf-psabi-doc + +use abi::call::{ArgType, FnType}; + +fn classify_ret_ty(arg: &mut ArgType, xlen: u64) { + // "Scalars wider than 2✕XLEN are passed by reference and are replaced in + // the argument list with the address." + // "Aggregates larger than 2✕XLEN bits are passed by reference and are + // replaced in the argument list with the address, as are C++ aggregates + // with nontrivial copy constructors, destructors, or vtables." + if arg.layout.size.bits() > 2 * xlen { + arg.make_indirect(); + } + + // "When passed in registers, scalars narrower than XLEN bits are widened + // according to the sign of their type up to 32 bits, then sign-extended to + // XLEN bits." + arg.extend_integer_width_to(xlen); // this method only affects integer scalars +} + +fn classify_arg_ty(arg: &mut ArgType, xlen: u64) { + // "Scalars wider than 2✕XLEN are passed by reference and are replaced in + // the argument list with the address." + // "Aggregates larger than 2✕XLEN bits are passed by reference and are + // replaced in the argument list with the address, as are C++ aggregates + // with nontrivial copy constructors, destructors, or vtables." + if arg.layout.size.bits() > 2 * xlen { + arg.make_indirect(); + } + + // "When passed in registers, scalars narrower than XLEN bits are widened + // according to the sign of their type up to 32 bits, then sign-extended to + // XLEN bits." + arg.extend_integer_width_to(xlen); // this method only affects integer scalars +} + +pub fn compute_abi_info(fty: &mut FnType, xlen: u64) { + if !fty.ret.is_ignore() { + classify_ret_ty(&mut fty.ret, xlen); + } + + for arg in &mut fty.args { + if arg.is_ignore() { + continue; + } + classify_arg_ty(arg, xlen); + } +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 6c2d16d6a17eb..6faab77d7709f 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -377,6 +377,8 @@ supported_targets! { ("aarch64-unknown-hermit", aarch64_unknown_hermit), ("x86_64-unknown-hermit", x86_64_unknown_hermit), + + ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf), } /// Everything `rustc` knows about how to compile for a specific target. diff --git a/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs b/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs new file mode 100644 index 0000000000000..cfd73e371ddac --- /dev/null +++ b/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs @@ -0,0 +1,52 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult}; +use spec::abi::{Abi}; + +pub fn target() -> TargetResult { + Ok(Target { + data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(), + llvm_target: "riscv32".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + target_os: "none".to_string(), + target_env: "".to_string(), + target_vendor: "unknown".to_string(), + arch: "riscv32".to_string(), + linker_flavor: LinkerFlavor::Ld, + + options: TargetOptions { + linker: Some("riscv32-unknown-elf-ld".to_string()), + cpu: "generic-rv32".to_string(), + max_atomic_width: Some(32), + atomic_cas: false, // incomplete +a extension + features: "+m,+a".to_string(), // disable +c extension + executables: true, + panic_strategy: PanicStrategy::Abort, + relocation_model: "static".to_string(), + abi_blacklist: vec![ + Abi::Cdecl, + Abi::Stdcall, + Abi::Fastcall, + Abi::Vectorcall, + Abi::Thiscall, + Abi::Aapcs, + Abi::Win64, + Abi::SysV64, + Abi::PtxKernel, + Abi::Msp430Interrupt, + Abi::X86Interrupt, + ], + .. Default::default() + }, + }) +} diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index a13e4ffa8f829..7305dc71cbf63 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -171,6 +171,12 @@ bool LLVMRustPassManagerBuilderPopulateThinLTOPassManager( #define SUBTARGET_MSP430 #endif +#ifdef LLVM_COMPONENT_RISCV +#define SUBTARGET_RISCV SUBTARGET(RISCV) +#else +#define SUBTARGET_RISCV +#endif + #ifdef LLVM_COMPONENT_SPARC #define SUBTARGET_SPARC SUBTARGET(Sparc) #else @@ -192,7 +198,8 @@ bool LLVMRustPassManagerBuilderPopulateThinLTOPassManager( SUBTARGET_SYSTEMZ \ SUBTARGET_MSP430 \ SUBTARGET_SPARC \ - SUBTARGET_HEXAGON + SUBTARGET_HEXAGON \ + SUBTARGET_RISCV \ #define SUBTARGET(x) \ namespace llvm { \ diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index bbce87a7c9adf..fd8fb54503a6f 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -89,6 +89,7 @@ static TARGETS: &'static [&'static str] = &[ "powerpc64-unknown-linux-gnu", "powerpc64le-unknown-linux-gnu", "powerpc64le-unknown-linux-musl", + "riscv32imac-unknown-none-elf", "s390x-unknown-linux-gnu", "sparc-unknown-linux-gnu", "sparc64-unknown-linux-gnu",