Skip to content

Commit

Permalink
Auto merge of #57937 - denzp:nvptx, r=nagisa
Browse files Browse the repository at this point in the history
NVPTX target specification

This change adds a built-in `nvptx64-nvidia-cuda` GPGPU no-std target specification and a basic PTX assembly smoke tests.

The approach is taken here and the target spec is based on `ptx-linker`, a project started about 1.5 years ago. Key feature: bitcode object files being linked with LTO into the final module on the linker's side.

Prior to this change, the linker used a `ld` linker-flavor, but I think, having the special CLI convention is a more reliable way.

Questions about further progress on reliable CUDA workflow with Rust:
1. Is it possible to create a test suite `codegen-asm` to verify end-to-end integration with LLVM backend?
1. How would it be better to organise no-std `compile-fail` tests: add `#![no_std]` where possible and mark others as `ignore-nvptx` directive, or alternatively, introduce `compile-fail-no-std` test suite?
1. Can we have the `ptx-linker` eventually be integrated as `rls` or `clippy`? Hopefully, this should allow to statically link against LLVM used in Rust and get rid of the [current hacky solution](https://github.com/denzp/rustc-llvm-proxy).
1. Am I missing some methods from `rustc_codegen_ssa::back::linker::Linker` that can be useful for bitcode-only linking?

Currently, there are no major public CUDA projects written in Rust I'm aware of, but I'm expecting to have a built-in target will create a solid foundation for further experiments and awesome crates.

Related to #38789
Fixes #38787
Fixes #38786
  • Loading branch information
bors committed Feb 1, 2019
2 parents 852701a + 49931fd commit 2efa31b
Show file tree
Hide file tree
Showing 19 changed files with 483 additions and 61 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -168,7 +168,7 @@ matrix:
if: branch = auto
- env: IMAGE=i686-gnu-nopt
if: branch = auto
- env: IMAGE=wasm32-unknown
- env: IMAGE=test-various
if: branch = auto
- env: IMAGE=x86_64-gnu
if: branch = auto
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/lib.rs
Expand Up @@ -831,6 +831,7 @@ impl Build {
!target.contains("msvc") &&
!target.contains("emscripten") &&
!target.contains("wasm32") &&
!target.contains("nvptx") &&
!target.contains("fuchsia") {
Some(self.cc(target))
} else {
Expand Down
4 changes: 2 additions & 2 deletions src/bootstrap/sanity.rs
Expand Up @@ -156,7 +156,7 @@ pub fn check(build: &mut Build) {
panic!("the iOS target is only supported on macOS");
}

if target.contains("-none-") {
if target.contains("-none-") || target.contains("nvptx") {
if build.no_std(*target).is_none() {
let target = build.config.target_config.entry(target.clone())
.or_default();
Expand All @@ -165,7 +165,7 @@ pub fn check(build: &mut Build) {
}

if build.no_std(*target) == Some(false) {
panic!("All the *-none-* targets are no-std targets")
panic!("All the *-none-* and nvptx* targets are no-std targets")
}
}

Expand Down
1 change: 1 addition & 0 deletions src/ci/docker/dist-various-2/Dockerfile
Expand Up @@ -70,6 +70,7 @@ ENV TARGETS=$TARGETS,x86_64-sun-solaris
ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32
ENV TARGETS=$TARGETS,x86_64-unknown-cloudabi
ENV TARGETS=$TARGETS,x86_64-fortanix-unknown-sgx
ENV TARGETS=$TARGETS,nvptx64-nvidia-cuda

ENV X86_FORTANIX_SGX_LIBS="/x86_64-fortanix-unknown-sgx/lib/"

Expand Down
Expand Up @@ -13,14 +13,16 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
gdb \
xz-utils

# FIXME: build the `ptx-linker` instead.
RUN curl -sL https://github.com/denzp/rust-ptx-linker/releases/download/v0.9.0-alpha.2/rust-ptx-linker.linux64.tar.gz | \
tar -xzvC /usr/bin

RUN curl -sL https://nodejs.org/dist/v9.2.0/node-v9.2.0-linux-x64.tar.xz | \
tar -xJ
tar -xJ

COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh

ENV TARGETS=wasm32-unknown-unknown

ENV RUST_CONFIGURE_ARGS \
--set build.nodejs=/node-v9.2.0-linux-x64/bin/node \
--set rust.lld
Expand All @@ -31,11 +33,18 @@ ENV RUST_CONFIGURE_ARGS \
# other contexts as well
ENV NO_DEBUG_ASSERTIONS=1

ENV SCRIPT python2.7 /checkout/x.py test --target $TARGETS \
ENV WASM_TARGETS=wasm32-unknown-unknown
ENV WASM_SCRIPT python2.7 /checkout/x.py test --target $WASM_TARGETS \
src/test/run-make \
src/test/ui \
src/test/run-pass \
src/test/compile-fail \
src/test/mir-opt \
src/test/codegen-units \
src/libcore \
src/libcore

ENV NVPTX_TARGETS=nvptx64-nvidia-cuda
ENV NVPTX_SCRIPT python2.7 /checkout/x.py test --target $NVPTX_TARGETS \
src/test/run-make

ENV SCRIPT $WASM_SCRIPT && $NVPTX_SCRIPT
6 changes: 6 additions & 0 deletions src/librustc/ty/context.rs
Expand Up @@ -1675,6 +1675,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
false
}

/// Determine whether identifiers in the assembly have strict naming rules.
/// Currently, only NVPTX* targets need it.
pub fn has_strict_asm_symbol_naming(&self) -> bool {
self.gcx.sess.target.target.arch.contains("nvptx")
}
}

impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
Expand Down
1 change: 1 addition & 0 deletions src/librustc_codegen_ssa/back/link.rs
Expand Up @@ -149,6 +149,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
LinkerFlavor::Ld => "ld",
LinkerFlavor::Msvc => "link.exe",
LinkerFlavor::Lld(_) => "lld",
LinkerFlavor::PtxLinker => "rust-ptx-linker",
}), flavor)),
(Some(linker), None) => {
let stem = if linker.extension().and_then(|ext| ext.to_str()) == Some("exe") {
Expand Down
132 changes: 131 additions & 1 deletion src/librustc_codegen_ssa/back/linker.rs
Expand Up @@ -13,7 +13,7 @@ use rustc::hir::def_id::{LOCAL_CRATE, CrateNum};
use rustc::middle::dependency_format::Linkage;
use rustc::session::Session;
use rustc::session::config::{self, CrateType, OptLevel, DebugInfo,
CrossLangLto};
CrossLangLto, Lto};
use rustc::ty::TyCtxt;
use rustc_target::spec::{LinkerFlavor, LldFlavor};
use serialize::{json, Encoder};
Expand Down Expand Up @@ -83,6 +83,10 @@ impl LinkerInfo {
LinkerFlavor::Lld(LldFlavor::Wasm) => {
Box::new(WasmLd::new(cmd, sess, self)) as Box<dyn Linker>
}

LinkerFlavor::PtxLinker => {
Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>
}
}
}
}
Expand Down Expand Up @@ -1080,3 +1084,129 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {

symbols
}

/// Much simplified and explicit CLI for the NVPTX linker. The linker operates
/// with bitcode and uses LLVM backend to generate a PTX assembly.
pub struct PtxLinker<'a> {
cmd: Command,
sess: &'a Session,
}

impl<'a> Linker for PtxLinker<'a> {
fn link_rlib(&mut self, path: &Path) {
self.cmd.arg("--rlib").arg(path);
}

fn link_whole_rlib(&mut self, path: &Path) {
self.cmd.arg("--rlib").arg(path);
}

fn include_path(&mut self, path: &Path) {
self.cmd.arg("-L").arg(path);
}

fn debuginfo(&mut self) {
self.cmd.arg("--debug");
}

fn add_object(&mut self, path: &Path) {
self.cmd.arg("--bitcode").arg(path);
}

fn args(&mut self, args: &[String]) {
self.cmd.args(args);
}

fn optimize(&mut self) {
match self.sess.lto() {
Lto::Thin | Lto::Fat | Lto::ThinLocal => {
self.cmd.arg("-Olto");
},

Lto::No => { },
};
}

fn output_filename(&mut self, path: &Path) {
self.cmd.arg("-o").arg(path);
}

fn finalize(&mut self) -> Command {
// Provide the linker with fallback to internal `target-cpu`.
self.cmd.arg("--fallback-arch").arg(match self.sess.opts.cg.target_cpu {
Some(ref s) => s,
None => &self.sess.target.target.options.cpu
});

::std::mem::replace(&mut self.cmd, Command::new(""))
}

fn link_dylib(&mut self, _lib: &str) {
panic!("external dylibs not supported")
}

fn link_rust_dylib(&mut self, _lib: &str, _path: &Path) {
panic!("external dylibs not supported")
}

fn link_staticlib(&mut self, _lib: &str) {
panic!("staticlibs not supported")
}

fn link_whole_staticlib(&mut self, _lib: &str, _search_path: &[PathBuf]) {
panic!("staticlibs not supported")
}

fn framework_path(&mut self, _path: &Path) {
panic!("frameworks not supported")
}

fn link_framework(&mut self, _framework: &str) {
panic!("frameworks not supported")
}

fn position_independent_executable(&mut self) {
}

fn full_relro(&mut self) {
}

fn partial_relro(&mut self) {
}

fn no_relro(&mut self) {
}

fn build_static_executable(&mut self) {
}

fn gc_sections(&mut self, _keep_metadata: bool) {
}

fn pgo_gen(&mut self) {
}

fn no_default_libraries(&mut self) {
}

fn build_dylib(&mut self, _out_filename: &Path) {
}

fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType) {
}

fn subsystem(&mut self, _subsystem: &str) {
}

fn no_position_independent_executable(&mut self) {
}

fn group_start(&mut self) {
}

fn group_end(&mut self) {
}

fn cross_lang_lto(&mut self) {
}
}
1 change: 1 addition & 0 deletions src/librustc_codegen_utils/lib.rs
Expand Up @@ -12,6 +12,7 @@
#![feature(nll)]
#![allow(unused_attributes)]
#![feature(rustc_diagnostic_macros)]
#![feature(in_band_lifetimes)]

#![recursion_limit="256"]

Expand Down

0 comments on commit 2efa31b

Please sign in to comment.