Skip to content

Commit 60c1ee7

Browse files
committedAug 2, 2018
Auto merge of #52787 - riscv-rust:riscv-rust-pr, r=alexcrichton
Enable RISCV - Enable LLVM backend. - Implement call abi. - Add built-in target riscv32imac-unknown-none. - Enable CI.
2 parents 1d9405f + d974dc9 commit 60c1ee7

File tree

11 files changed

+139
-4
lines changed

11 files changed

+139
-4
lines changed
 

‎config.toml.example

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@
6161
# the same format as above, but since these targets are experimental, they are
6262
# not built by default and the experimental Rust compilation targets that depend
6363
# on them will not work unless the user opts in to building them. By default the
64-
# `WebAssembly` target is enabled when compiling LLVM from scratch.
65-
#experimental-targets = "WebAssembly"
64+
# `WebAssembly` and `RISCV` targets are enabled when compiling LLVM from scratch.
65+
#experimental-targets = "WebAssembly;RISCV"
6666

6767
# Cap the number of parallel linker invocations when compiling LLVM.
6868
# This can be useful when building LLVM with debug info, which significantly

‎src/bootstrap/config.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ impl Config {
507507
set(&mut config.llvm_link_shared, llvm.link_shared);
508508
config.llvm_targets = llvm.targets.clone();
509509
config.llvm_experimental_targets = llvm.experimental_targets.clone()
510-
.unwrap_or("WebAssembly".to_string());
510+
.unwrap_or("WebAssembly;RISCV".to_string());
511511
config.llvm_link_jobs = llvm.link_jobs;
512512
config.llvm_clang_cl = llvm.clang_cl.clone();
513513
}

‎src/ci/docker/dist-various-1/Dockerfile

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ ENV TARGETS=$TARGETS,thumbv6m-none-eabi
102102
ENV TARGETS=$TARGETS,thumbv7m-none-eabi
103103
ENV TARGETS=$TARGETS,thumbv7em-none-eabi
104104
ENV TARGETS=$TARGETS,thumbv7em-none-eabihf
105+
ENV TARGETS=$TARGETS,riscv32imac-unknown-none-elf
105106

106107
ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
107108
CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \

‎src/librustc_llvm/build.rs

+4
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ fn main() {
100100
optional_components.push("hexagon");
101101
}
102102

103+
if major > 6 {
104+
optional_components.push("riscv");
105+
}
106+
103107
// FIXME: surely we don't need all these components, right? Stuff like mcjit
104108
// or interpreter the compiler itself never uses.
105109
let required_components = &["ipo",

‎src/librustc_llvm/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ pub fn initialize_available_targets() {
9090
LLVMInitializeMSP430Target,
9191
LLVMInitializeMSP430TargetMC,
9292
LLVMInitializeMSP430AsmPrinter);
93+
init_target!(llvm_component = "riscv",
94+
LLVMInitializeRISCVTargetInfo,
95+
LLVMInitializeRISCVTarget,
96+
LLVMInitializeRISCVTargetMC,
97+
LLVMInitializeRISCVAsmPrinter,
98+
LLVMInitializeRISCVAsmParser);
9399
init_target!(llvm_component = "sparc",
94100
LLVMInitializeSparcTargetInfo,
95101
LLVMInitializeSparcTarget,

‎src/librustc_target/abi/call/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ mod nvptx;
2323
mod nvptx64;
2424
mod powerpc;
2525
mod powerpc64;
26+
mod riscv;
2627
mod s390x;
2728
mod sparc;
2829
mod sparc64;
@@ -500,6 +501,8 @@ impl<'a, Ty> FnType<'a, Ty> {
500501
"nvptx" => nvptx::compute_abi_info(self),
501502
"nvptx64" => nvptx64::compute_abi_info(self),
502503
"hexagon" => hexagon::compute_abi_info(self),
504+
"riscv32" => riscv::compute_abi_info(self, 32),
505+
"riscv64" => riscv::compute_abi_info(self, 64),
503506
a => return Err(format!("unrecognized arch \"{}\" in target specification", a))
504507
}
505508

‎src/librustc_target/abi/call/riscv.rs

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Reference: RISC-V ELF psABI specification
12+
// https://github.com/riscv/riscv-elf-psabi-doc
13+
14+
use abi::call::{ArgType, FnType};
15+
16+
fn classify_ret_ty<Ty>(arg: &mut ArgType<Ty>, xlen: u64) {
17+
// "Scalars wider than 2✕XLEN are passed by reference and are replaced in
18+
// the argument list with the address."
19+
// "Aggregates larger than 2✕XLEN bits are passed by reference and are
20+
// replaced in the argument list with the address, as are C++ aggregates
21+
// with nontrivial copy constructors, destructors, or vtables."
22+
if arg.layout.size.bits() > 2 * xlen {
23+
arg.make_indirect();
24+
}
25+
26+
// "When passed in registers, scalars narrower than XLEN bits are widened
27+
// according to the sign of their type up to 32 bits, then sign-extended to
28+
// XLEN bits."
29+
arg.extend_integer_width_to(xlen); // this method only affects integer scalars
30+
}
31+
32+
fn classify_arg_ty<Ty>(arg: &mut ArgType<Ty>, xlen: u64) {
33+
// "Scalars wider than 2✕XLEN are passed by reference and are replaced in
34+
// the argument list with the address."
35+
// "Aggregates larger than 2✕XLEN bits are passed by reference and are
36+
// replaced in the argument list with the address, as are C++ aggregates
37+
// with nontrivial copy constructors, destructors, or vtables."
38+
if arg.layout.size.bits() > 2 * xlen {
39+
arg.make_indirect();
40+
}
41+
42+
// "When passed in registers, scalars narrower than XLEN bits are widened
43+
// according to the sign of their type up to 32 bits, then sign-extended to
44+
// XLEN bits."
45+
arg.extend_integer_width_to(xlen); // this method only affects integer scalars
46+
}
47+
48+
pub fn compute_abi_info<Ty>(fty: &mut FnType<Ty>, xlen: u64) {
49+
if !fty.ret.is_ignore() {
50+
classify_ret_ty(&mut fty.ret, xlen);
51+
}
52+
53+
for arg in &mut fty.args {
54+
if arg.is_ignore() {
55+
continue;
56+
}
57+
classify_arg_ty(arg, xlen);
58+
}
59+
}

‎src/librustc_target/spec/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,8 @@ supported_targets! {
377377

378378
("aarch64-unknown-hermit", aarch64_unknown_hermit),
379379
("x86_64-unknown-hermit", x86_64_unknown_hermit),
380+
381+
("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
380382
}
381383

382384
/// Everything `rustc` knows about how to compile for a specific target.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
12+
use spec::abi::{Abi};
13+
14+
pub fn target() -> TargetResult {
15+
Ok(Target {
16+
data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
17+
llvm_target: "riscv32".to_string(),
18+
target_endian: "little".to_string(),
19+
target_pointer_width: "32".to_string(),
20+
target_c_int_width: "32".to_string(),
21+
target_os: "none".to_string(),
22+
target_env: "".to_string(),
23+
target_vendor: "unknown".to_string(),
24+
arch: "riscv32".to_string(),
25+
linker_flavor: LinkerFlavor::Ld,
26+
27+
options: TargetOptions {
28+
linker: Some("riscv32-unknown-elf-ld".to_string()),
29+
cpu: "generic-rv32".to_string(),
30+
max_atomic_width: Some(32),
31+
atomic_cas: false, // incomplete +a extension
32+
features: "+m,+a".to_string(), // disable +c extension
33+
executables: true,
34+
panic_strategy: PanicStrategy::Abort,
35+
relocation_model: "static".to_string(),
36+
abi_blacklist: vec![
37+
Abi::Cdecl,
38+
Abi::Stdcall,
39+
Abi::Fastcall,
40+
Abi::Vectorcall,
41+
Abi::Thiscall,
42+
Abi::Aapcs,
43+
Abi::Win64,
44+
Abi::SysV64,
45+
Abi::PtxKernel,
46+
Abi::Msp430Interrupt,
47+
Abi::X86Interrupt,
48+
],
49+
.. Default::default()
50+
},
51+
})
52+
}

‎src/rustllvm/PassWrapper.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,12 @@ bool LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
171171
#define SUBTARGET_MSP430
172172
#endif
173173

174+
#ifdef LLVM_COMPONENT_RISCV
175+
#define SUBTARGET_RISCV SUBTARGET(RISCV)
176+
#else
177+
#define SUBTARGET_RISCV
178+
#endif
179+
174180
#ifdef LLVM_COMPONENT_SPARC
175181
#define SUBTARGET_SPARC SUBTARGET(Sparc)
176182
#else
@@ -192,7 +198,8 @@ bool LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
192198
SUBTARGET_SYSTEMZ \
193199
SUBTARGET_MSP430 \
194200
SUBTARGET_SPARC \
195-
SUBTARGET_HEXAGON
201+
SUBTARGET_HEXAGON \
202+
SUBTARGET_RISCV \
196203

197204
#define SUBTARGET(x) \
198205
namespace llvm { \

‎src/tools/build-manifest/src/main.rs

+1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ static TARGETS: &'static [&'static str] = &[
8989
"powerpc64-unknown-linux-gnu",
9090
"powerpc64le-unknown-linux-gnu",
9191
"powerpc64le-unknown-linux-musl",
92+
"riscv32imac-unknown-none-elf",
9293
"s390x-unknown-linux-gnu",
9394
"sparc-unknown-linux-gnu",
9495
"sparc64-unknown-linux-gnu",

0 commit comments

Comments
 (0)
Please sign in to comment.