diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 7e6c0a9f52aa2..6c2785a3723d0 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -411,7 +411,8 @@ impl<'a> Builder<'a> { test::Bootstrap, // Run run-make last, since these won't pass without make on Windows test::RunMake, - test::RustdocUi + test::RustdocUi, + test::Assembly, ), Kind::Bench => describe!(test::Crate, test::CrateLibrustc), Kind::Doc => describe!( diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 51412f79c3d0c..9cd2f95d752e3 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -895,6 +895,12 @@ host_test!(RunMakeFullDeps { suite: "run-make-fulldeps" }); +default_test!(Assembly { + path: "src/test/assembly", + mode: "assembly", + suite: "assembly" +}); + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] struct Compiletest { compiler: Compiler, diff --git a/src/ci/docker/test-various/Dockerfile b/src/ci/docker/test-various/Dockerfile index 6c419e13c9f05..7891e9f625a6a 100644 --- a/src/ci/docker/test-various/Dockerfile +++ b/src/ci/docker/test-various/Dockerfile @@ -45,6 +45,7 @@ ENV WASM_SCRIPT python2.7 /checkout/x.py test --target $WASM_TARGETS \ ENV NVPTX_TARGETS=nvptx64-nvidia-cuda ENV NVPTX_SCRIPT python2.7 /checkout/x.py test --target $NVPTX_TARGETS \ - src/test/run-make + src/test/run-make \ + src/test/assembly ENV SCRIPT $WASM_SCRIPT && $NVPTX_SCRIPT diff --git a/src/test/assembly/auxiliary/breakpoint-panic-handler.rs b/src/test/assembly/auxiliary/breakpoint-panic-handler.rs new file mode 100644 index 0000000000000..d54c1181e1a0c --- /dev/null +++ b/src/test/assembly/auxiliary/breakpoint-panic-handler.rs @@ -0,0 +1,8 @@ +#![feature(core_intrinsics)] +#![no_std] + +#[panic_handler] +unsafe fn breakpoint_panic_handler(_: &::core::panic::PanicInfo) -> ! { + core::intrinsics::breakpoint(); + core::hint::unreachable_unchecked(); +} diff --git a/src/test/run-make/nvptx-dylib-crate/dep.rs b/src/test/assembly/auxiliary/non-inline-dependency.rs similarity index 100% rename from src/test/run-make/nvptx-dylib-crate/dep.rs rename to src/test/assembly/auxiliary/non-inline-dependency.rs diff --git a/src/test/assembly/nvptx-arch-default.rs b/src/test/assembly/nvptx-arch-default.rs new file mode 100644 index 0000000000000..7fe71c33521a2 --- /dev/null +++ b/src/test/assembly/nvptx-arch-default.rs @@ -0,0 +1,12 @@ +// assembly-output: ptx-linker +// compile-flags: --crate-type cdylib +// only-nvptx64 + +#![no_std] + +// aux-build: breakpoint-panic-handler.rs +extern crate breakpoint_panic_handler; + +// Verify default target arch with ptx-linker. +// CHECK: .target sm_30 +// CHECK: .address_size 64 diff --git a/src/test/assembly/nvptx-arch-emit-asm.rs b/src/test/assembly/nvptx-arch-emit-asm.rs new file mode 100644 index 0000000000000..0ca17729c0212 --- /dev/null +++ b/src/test/assembly/nvptx-arch-emit-asm.rs @@ -0,0 +1,9 @@ +// assembly-output: emit-asm +// compile-flags: --crate-type rlib +// only-nvptx64 + +#![no_std] + +// Verify default arch without ptx-linker involved. +// CHECK: .target sm_30 +// CHECK: .address_size 64 diff --git a/src/test/assembly/nvptx-arch-link-arg.rs b/src/test/assembly/nvptx-arch-link-arg.rs new file mode 100644 index 0000000000000..f6b6e8ccaa127 --- /dev/null +++ b/src/test/assembly/nvptx-arch-link-arg.rs @@ -0,0 +1,12 @@ +// assembly-output: ptx-linker +// compile-flags: --crate-type cdylib -C link-arg=--arch=sm_60 +// only-nvptx64 + +#![no_std] + +// aux-build: breakpoint-panic-handler.rs +extern crate breakpoint_panic_handler; + +// Verify target arch override via `link-arg`. +// CHECK: .target sm_60 +// CHECK: .address_size 64 diff --git a/src/test/assembly/nvptx-arch-target-cpu.rs b/src/test/assembly/nvptx-arch-target-cpu.rs new file mode 100644 index 0000000000000..08a7a193bbd88 --- /dev/null +++ b/src/test/assembly/nvptx-arch-target-cpu.rs @@ -0,0 +1,12 @@ +// assembly-output: ptx-linker +// compile-flags: --crate-type cdylib -C target-cpu=sm_50 +// only-nvptx64 + +#![no_std] + +// aux-build: breakpoint-panic-handler.rs +extern crate breakpoint_panic_handler; + +// Verify target arch override via `target-cpu`. +// CHECK: .target sm_50 +// CHECK: .address_size 64 diff --git a/src/test/assembly/nvptx-atomics.rs b/src/test/assembly/nvptx-atomics.rs new file mode 100644 index 0000000000000..3bbd7b3d12d2a --- /dev/null +++ b/src/test/assembly/nvptx-atomics.rs @@ -0,0 +1,85 @@ +// assembly-output: ptx-linker +// compile-flags: --crate-type cdylib +// only-nvptx64 + +#![feature(abi_ptx, core_intrinsics)] +#![no_std] + +use core::intrinsics::*; + +// aux-build: breakpoint-panic-handler.rs +extern crate breakpoint_panic_handler; + +// Currently, LLVM NVPTX backend can only emit atomic instructions with +// `relaxed` (PTX default) ordering. But it's also useful to make sure +// the backend won't fail with other orders. Apparently, the backend +// doesn't support fences as well. As a workaround `llvm.nvvm.membar.*` +// could work, and perhaps on the long run, all the atomic operations +// should rather be provided by `core::arch::nvptx`. + +// Also, PTX ISA doesn't have atomic `load`, `store` and `nand`. + +// FIXME(denzp): add tests for `core::sync::atomic::*`. + +#[no_mangle] +pub unsafe extern "ptx-kernel" fn atomics_kernel(a: *mut u32) { + // CHECK: atom.global.and.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1; + // CHECK: atom.global.and.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1; + atomic_and(a, 1); + atomic_and_relaxed(a, 1); + + // CHECK: atom.global.cas.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1, 2; + // CHECK: atom.global.cas.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1, 2; + atomic_cxchg(a, 1, 2); + atomic_cxchg_relaxed(a, 1, 2); + + // CHECK: atom.global.max.s32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1; + // CHECK: atom.global.max.s32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1; + atomic_max(a, 1); + atomic_max_relaxed(a, 1); + + // CHECK: atom.global.min.s32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1; + // CHECK: atom.global.min.s32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1; + atomic_min(a, 1); + atomic_min_relaxed(a, 1); + + // CHECK: atom.global.or.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1; + // CHECK: atom.global.or.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1; + atomic_or(a, 1); + atomic_or_relaxed(a, 1); + + // CHECK: atom.global.max.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1; + // CHECK: atom.global.max.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1; + atomic_umax(a, 1); + atomic_umax_relaxed(a, 1); + + // CHECK: atom.global.min.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1; + // CHECK: atom.global.min.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1; + atomic_umin(a, 1); + atomic_umin_relaxed(a, 1); + + // CHECK: atom.global.add.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1; + // CHECK: atom.global.add.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1; + atomic_xadd(a, 1); + atomic_xadd_relaxed(a, 1); + + // CHECK: atom.global.exch.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1; + // CHECK: atom.global.exch.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1; + atomic_xchg(a, 1); + atomic_xchg_relaxed(a, 1); + + // CHECK: atom.global.xor.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1; + // CHECK: atom.global.xor.b32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], 1; + atomic_xor(a, 1); + atomic_xor_relaxed(a, 1); + + // CHECK: mov.u32 %[[sub_0_arg:r[0-9]+]], 100; + // CHECK: neg.s32 temp, %[[sub_0_arg]]; + // CHECK: atom.global.add.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], temp; + atomic_xsub(a, 100); + + // CHECK: mov.u32 %[[sub_1_arg:r[0-9]+]], 200; + // CHECK: neg.s32 temp, %[[sub_1_arg]]; + // CHECK: atom.global.add.u32 %{{r[0-9]+}}, [%{{rd[0-9]+}}], temp; + atomic_xsub_relaxed(a, 200); +} diff --git a/src/test/assembly/nvptx-internalizing.rs b/src/test/assembly/nvptx-internalizing.rs new file mode 100644 index 0000000000000..db82264263226 --- /dev/null +++ b/src/test/assembly/nvptx-internalizing.rs @@ -0,0 +1,27 @@ +// assembly-output: ptx-linker +// compile-flags: --crate-type cdylib +// only-nvptx64 + +#![feature(abi_ptx)] +#![no_std] + +// aux-build: breakpoint-panic-handler.rs +extern crate breakpoint_panic_handler; + +// aux-build: non-inline-dependency.rs +extern crate non_inline_dependency as dep; + +// Verify that no extra function declarations are present. +// CHECK-NOT: .func + +// CHECK: .visible .entry top_kernel( +#[no_mangle] +pub unsafe extern "ptx-kernel" fn top_kernel(a: *const u32, b: *mut u32) { + // CHECK: add.s32 %{{r[0-9]+}}, %{{r[0-9]+}}, 5; + *b = *a + 5; +} + +// Verify that no extra function definitions are here. +// CHECK-NOT: .func +// CHECK-NOT: .entry + diff --git a/src/test/assembly/nvptx-linking-binary.rs b/src/test/assembly/nvptx-linking-binary.rs new file mode 100644 index 0000000000000..d88ed9139ca6a --- /dev/null +++ b/src/test/assembly/nvptx-linking-binary.rs @@ -0,0 +1,39 @@ +// assembly-output: ptx-linker +// compile-flags: --crate-type bin +// only-nvptx64 + +#![feature(abi_ptx)] +#![no_main] +#![no_std] + +// aux-build: breakpoint-panic-handler.rs +extern crate breakpoint_panic_handler; + +// aux-build: non-inline-dependency.rs +extern crate non_inline_dependency as dep; + +// Make sure declarations are there. +// CHECK: .func (.param .b32 func_retval0) wrapping_external_fn +// CHECK: .func (.param .b32 func_retval0) panicking_external_fn + +// CHECK-LABEL: .visible .entry top_kernel( +#[no_mangle] +pub unsafe extern "ptx-kernel" fn top_kernel(a: *const u32, b: *mut u32) { + // CHECK: call.uni (retval0), + // CHECK-NEXT: wrapping_external_fn + // CHECK: ld.param.b32 %[[LHS:r[0-9]+]], [retval0+0]; + let lhs = dep::wrapping_external_fn(*a); + + // CHECK: call.uni (retval0), + // CHECK-NEXT: panicking_external_fn + // CHECK: ld.param.b32 %[[RHS:r[0-9]+]], [retval0+0]; + let rhs = dep::panicking_external_fn(*a); + + // CHECK: add.s32 %[[RES:r[0-9]+]], %[[RHS]], %[[LHS]]; + // CHECK: st.global.u32 [%{{rd[0-9]+}}], %[[RES]]; + *b = lhs + rhs; +} + +// Verify that external function bodies are available. +// CHECK: .func (.param .b32 func_retval0) wrapping_external_fn +// CHECK: .func (.param .b32 func_retval0) panicking_external_fn diff --git a/src/test/assembly/nvptx-linking-cdylib.rs b/src/test/assembly/nvptx-linking-cdylib.rs new file mode 100644 index 0000000000000..1145f567d8c17 --- /dev/null +++ b/src/test/assembly/nvptx-linking-cdylib.rs @@ -0,0 +1,38 @@ +// assembly-output: ptx-linker +// compile-flags: --crate-type cdylib +// only-nvptx64 + +#![feature(abi_ptx)] +#![no_std] + +// aux-build: breakpoint-panic-handler.rs +extern crate breakpoint_panic_handler; + +// aux-build: non-inline-dependency.rs +extern crate non_inline_dependency as dep; + +// Make sure declarations are there. +// CHECK: .func (.param .b32 func_retval0) wrapping_external_fn +// CHECK: .func (.param .b32 func_retval0) panicking_external_fn + +// CHECK-LABEL: .visible .entry top_kernel( +#[no_mangle] +pub unsafe extern "ptx-kernel" fn top_kernel(a: *const u32, b: *mut u32) { + // CHECK: call.uni (retval0), + // CHECK-NEXT: wrapping_external_fn + // CHECK: ld.param.b32 %[[LHS:r[0-9]+]], [retval0+0]; + let lhs = dep::wrapping_external_fn(*a); + + // CHECK: call.uni (retval0), + // CHECK-NEXT: panicking_external_fn + // CHECK: ld.param.b32 %[[RHS:r[0-9]+]], [retval0+0]; + let rhs = dep::panicking_external_fn(*a); + + // CHECK: add.s32 %[[RES:r[0-9]+]], %[[RHS]], %[[LHS]]; + // CHECK: st.global.u32 [%{{rd[0-9]+}}], %[[RES]]; + *b = lhs + rhs; +} + +// Verify that external function bodies are available. +// CHECK: .func (.param .b32 func_retval0) wrapping_external_fn +// CHECK: .func (.param .b32 func_retval0) panicking_external_fn diff --git a/src/test/run-make/nvptx-emit-asm/kernel.rs b/src/test/assembly/nvptx-safe-naming.rs similarity index 63% rename from src/test/run-make/nvptx-emit-asm/kernel.rs rename to src/test/assembly/nvptx-safe-naming.rs index b71e18d910391..ab6f91423aad6 100644 --- a/src/test/run-make/nvptx-emit-asm/kernel.rs +++ b/src/test/assembly/nvptx-safe-naming.rs @@ -1,13 +1,15 @@ -#![no_std] -#![deny(warnings)] +// assembly-output: ptx-linker +// compile-flags: --crate-type cdylib +// only-nvptx64 + #![feature(abi_ptx)] +#![no_std] -// Verify the default CUDA arch. -// CHECK: .target sm_30 -// CHECK: .address_size 64 +// aux-build: breakpoint-panic-handler.rs +extern crate breakpoint_panic_handler; // Verify function name doesn't contain unacceaptable characters. -// CHECK: .func (.param .b32 func_retval0) [[IMPL_FN:_ZN[a-zA-Z0-9$_]+square[a-zA-Z0-9$_]+]] +// CHECK: .func (.param .b32 func_retval0) [[IMPL_FN:[a-zA-Z0-9$_]+square[a-zA-Z0-9$_]+]]( // CHECK-LABEL: .visible .entry top_kernel( #[no_mangle] @@ -33,9 +35,3 @@ pub mod deep { } } } - -// Verify that external function bodies are available. -// CHECK: .func (.param .b32 func_retval0) [[IMPL_FN]] -// CHECK: { -// CHECK: mul.lo.s32 %{{r[0-9]+}}, %{{r[0-9]+}}, %{{r[0-9]+}} -// CHECK: } diff --git a/src/test/run-make/nvptx-binary-crate/Makefile b/src/test/run-make/nvptx-binary-crate/Makefile deleted file mode 100644 index 2c211b5c78507..0000000000000 --- a/src/test/run-make/nvptx-binary-crate/Makefile +++ /dev/null @@ -1,12 +0,0 @@ --include ../../run-make-fulldeps/tools.mk - -ifeq ($(TARGET),nvptx64-nvidia-cuda) -all: - $(RUSTC) main.rs --crate-type="bin" --target $(TARGET) -O -C link-arg=--arch=sm_60 -o $(TMPDIR)/main.link_arg.ptx - $(RUSTC) main.rs --crate-type="bin" --target $(TARGET) -O -C target-cpu=sm_60 -o $(TMPDIR)/main.target_cpu.ptx - - FileCheck main.rs --input-file $(TMPDIR)/main.link_arg.ptx - FileCheck main.rs --input-file $(TMPDIR)/main.target_cpu.ptx -else -all: -endif diff --git a/src/test/run-make/nvptx-binary-crate/main.rs b/src/test/run-make/nvptx-binary-crate/main.rs deleted file mode 100644 index 826bc3a47bbd6..0000000000000 --- a/src/test/run-make/nvptx-binary-crate/main.rs +++ /dev/null @@ -1,28 +0,0 @@ -#![no_std] -#![no_main] -#![deny(warnings)] -#![feature(abi_ptx, core_intrinsics)] - -// Check the overriden CUDA arch. -// CHECK: .target sm_60 -// CHECK: .address_size 64 - -// Verify that no extra function declarations are present. -// CHECK-NOT: .func - -// CHECK-LABEL: .visible .entry top_kernel( -#[no_mangle] -pub unsafe extern "ptx-kernel" fn top_kernel(a: *const u32, b: *mut u32) { - // CHECK: add.s32 %{{r[0-9]+}}, %{{r[0-9]+}}, 5; - *b = *a + 5; -} - -// Verify that no extra function definitions are there. -// CHECK-NOT: .func -// CHECK-NOT: .entry - -#[panic_handler] -unsafe fn breakpoint_panic_handler(_: &::core::panic::PanicInfo) -> ! { - core::intrinsics::breakpoint(); - core::hint::unreachable_unchecked(); -} diff --git a/src/test/run-make/nvptx-dylib-crate/Makefile b/src/test/run-make/nvptx-dylib-crate/Makefile deleted file mode 100644 index 7284e9d1a7c99..0000000000000 --- a/src/test/run-make/nvptx-dylib-crate/Makefile +++ /dev/null @@ -1,10 +0,0 @@ --include ../../run-make-fulldeps/tools.mk - -ifeq ($(TARGET),nvptx64-nvidia-cuda) -all: - $(RUSTC) dep.rs --crate-type="rlib" --target $(TARGET) - $(RUSTC) kernel.rs --crate-type="cdylib" -O --target $(TARGET) - FileCheck kernel.rs --input-file $(TMPDIR)/kernel.ptx -else -all: -endif diff --git a/src/test/run-make/nvptx-dylib-crate/kernel.rs b/src/test/run-make/nvptx-dylib-crate/kernel.rs deleted file mode 100644 index 63fd6b063dd8c..0000000000000 --- a/src/test/run-make/nvptx-dylib-crate/kernel.rs +++ /dev/null @@ -1,59 +0,0 @@ -#![no_std] -#![deny(warnings)] -#![feature(abi_ptx, core_intrinsics)] - -extern crate dep; - -// Verify the default CUDA arch. -// CHECK: .target sm_30 -// CHECK: .address_size 64 - -// Make sure declarations are there. -// CHECK: .func (.param .b32 func_retval0) wrapping_external_fn -// CHECK: .func (.param .b32 func_retval0) panicking_external_fn -// CHECK: .func [[PANIC_HANDLER:_ZN4core9panicking5panic[a-zA-Z0-9]+]] - -// CHECK-LABEL: .visible .entry top_kernel( -#[no_mangle] -pub unsafe extern "ptx-kernel" fn top_kernel(a: *const u32, b: *mut u32) { - // CHECK: call.uni (retval0), - // CHECK-NEXT: wrapping_external_fn - // CHECK: ld.param.b32 %[[LHS:r[0-9]+]], [retval0+0]; - let lhs = dep::wrapping_external_fn(*a); - - // CHECK: call.uni (retval0), - // CHECK-NEXT: panicking_external_fn - // CHECK: ld.param.b32 %[[RHS:r[0-9]+]], [retval0+0]; - let rhs = dep::panicking_external_fn(*a); - - // CHECK: add.s32 %[[RES:r[0-9]+]], %[[RHS]], %[[LHS]]; - // CHECK: st.global.u32 [%{{rd[0-9]+}}], %[[RES]]; - *b = lhs + rhs; -} - -// Verify that external function bodies are available. -// CHECK-LABEL: .func (.param .b32 func_retval0) wrapping_external_fn -// CHECK: { -// CHECK: st.param.b32 [func_retval0+0], %{{r[0-9]+}}; -// CHECK: } - -// Also verify panic behavior. -// CHECK-LABEL: .func (.param .b32 func_retval0) panicking_external_fn -// CHECK: { -// CHECK: %{{p[0-9]+}} bra [[PANIC_LABEL:[a-zA-Z0-9_]+]]; -// CHECK: [[PANIC_LABEL]]: -// CHECK: call.uni -// CHECK: [[PANIC_HANDLER]] -// CHECK: } - -// Verify whether out dummy panic formatter has a correct body. -// CHECK: .func [[PANIC_FMT:_ZN4core9panicking9panic_fmt[a-zA-Z0-9]+]]() -// CHECK: { -// CHECK: trap; -// CHECK: } - -#[panic_handler] -unsafe fn breakpoint_panic_handler(_: &::core::panic::PanicInfo) -> ! { - core::intrinsics::breakpoint(); - core::hint::unreachable_unchecked(); -} diff --git a/src/test/run-make/nvptx-emit-asm/Makefile b/src/test/run-make/nvptx-emit-asm/Makefile deleted file mode 100644 index e03601878bdee..0000000000000 --- a/src/test/run-make/nvptx-emit-asm/Makefile +++ /dev/null @@ -1,9 +0,0 @@ --include ../../run-make-fulldeps/tools.mk - -ifeq ($(TARGET),nvptx64-nvidia-cuda) -all: - $(RUSTC) kernel.rs --crate-type="rlib" --emit asm,llvm-ir -O --target $(TARGET) - FileCheck kernel.rs --input-file $(TMPDIR)/kernel.s -else -all: -endif diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 6b3117a1f74f4..fea000738dfc9 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -25,6 +25,7 @@ pub enum Mode { RunMake, Ui, MirOpt, + Assembly, } impl Mode { @@ -60,6 +61,7 @@ impl FromStr for Mode { "run-make" => Ok(RunMake), "ui" => Ok(Ui), "mir-opt" => Ok(MirOpt), + "assembly" => Ok(Assembly), _ => Err(()), } } @@ -83,6 +85,7 @@ impl fmt::Display for Mode { RunMake => "run-make", Ui => "ui", MirOpt => "mir-opt", + Assembly => "assembly", }; fmt::Display::fmt(s, f) } diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index c2c4a6b69cca5..7bf56707478e3 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -335,6 +335,7 @@ pub struct TestProps { pub failure_status: i32, pub run_rustfix: bool, pub rustfix_only_machine_applicable: bool, + pub assembly_output: Option, } impl TestProps { @@ -370,6 +371,7 @@ impl TestProps { failure_status: -1, run_rustfix: false, rustfix_only_machine_applicable: false, + assembly_output: None, } } @@ -517,6 +519,10 @@ impl TestProps { self.rustfix_only_machine_applicable = config.parse_rustfix_only_machine_applicable(ln); } + + if self.assembly_output.is_none() { + self.assembly_output = config.parse_assembly_output(ln); + } }); if self.failure_status == -1 { @@ -594,6 +600,7 @@ impl Config { fn parse_aux_build(&self, line: &str) -> Option { self.parse_name_value_directive(line, "aux-build") + .map(|r| r.trim().to_string()) } fn parse_compile_flags(&self, line: &str) -> Option { @@ -676,6 +683,11 @@ impl Config { self.parse_name_directive(line, "skip-codegen") } + fn parse_assembly_output(&self, line: &str) -> Option { + self.parse_name_value_directive(line, "assembly-output") + .map(|r| r.trim().to_string()) + } + fn parse_env(&self, line: &str, name: &str) -> Option<(String, String)> { self.parse_name_value_directive(line, name).map(|nv| { // nv is either FOO or FOO=BAR diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index bac41a7c57904..85b700393a52b 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -4,7 +4,7 @@ use crate::common::{output_base_dir, output_base_name, output_testname_unique}; use crate::common::{Codegen, CodegenUnits, DebugInfoBoth, DebugInfoGdb, DebugInfoLldb, Rustdoc}; use crate::common::{CompileFail, Pretty, RunFail, RunPass, RunPassValgrind}; use crate::common::{Config, TestPaths}; -use crate::common::{Incremental, MirOpt, RunMake, Ui}; +use crate::common::{Incremental, MirOpt, RunMake, Ui, Assembly}; use diff; use crate::errors::{self, Error, ErrorKind}; use filetime::FileTime; @@ -275,6 +275,7 @@ impl<'test> TestCx<'test> { RunMake => self.run_rmake_test(), RunPass | Ui => self.run_ui_test(), MirOpt => self.run_mir_opt_test(), + Assembly => self.run_assembly_test(), } } @@ -1604,6 +1605,7 @@ impl<'test> TestCx<'test> { || self.config.target.contains("emscripten") || (self.config.target.contains("musl") && !aux_props.force_host) || self.config.target.contains("wasm32") + || self.config.target.contains("nvptx") { // We primarily compile all auxiliary libraries as dynamic libraries // to avoid code size bloat and large binaries as much as possible @@ -1802,7 +1804,7 @@ impl<'test> TestCx<'test> { rustc.arg(dir_opt); } RunFail | RunPassValgrind | Pretty | DebugInfoBoth | DebugInfoGdb | DebugInfoLldb - | Codegen | Rustdoc | RunMake | CodegenUnits => { + | Codegen | Rustdoc | RunMake | CodegenUnits | Assembly => { // do not use JSON output } } @@ -2097,12 +2099,37 @@ impl<'test> TestCx<'test> { self.compose_and_run_compiler(rustc, None) } - fn check_ir_with_filecheck(&self) -> ProcRes { - let irfile = self.output_base_name().with_extension("ll"); + fn compile_test_and_save_assembly(&self) -> (ProcRes, PathBuf) { + // This works with both `--emit asm` (as default output name for the assembly) + // and `ptx-linker` because the latter can write output at requested location. + let output_path = self.output_base_name().with_extension("s"); + + let output_file = TargetLocation::ThisFile(output_path.clone()); + let mut rustc = self.make_compile_args(&self.testpaths.file, output_file); + + rustc.arg("-L").arg(self.aux_output_dir_name()); + + match self.props.assembly_output.as_ref().map(AsRef::as_ref) { + Some("emit-asm") => { + rustc.arg("--emit=asm"); + } + + Some("ptx-linker") => { + // No extra flags needed. + } + + Some(_) => self.fatal("unknown 'assembly-output' header"), + None => self.fatal("missing 'assembly-output' header"), + } + + (self.compose_and_run_compiler(rustc, None), output_path) + } + + fn verify_with_filecheck(&self, output: &Path) -> ProcRes { let mut filecheck = Command::new(self.config.llvm_filecheck.as_ref().unwrap()); filecheck .arg("--input-file") - .arg(irfile) + .arg(output) .arg(&self.testpaths.file); // It would be more appropriate to make most of the arguments configurable through // a comment-attribute similar to `compile-flags`. For example, --check-prefixes is a very @@ -2121,12 +2148,29 @@ impl<'test> TestCx<'test> { self.fatal("missing --llvm-filecheck"); } - let mut proc_res = self.compile_test_and_save_ir(); + let proc_res = self.compile_test_and_save_ir(); + if !proc_res.status.success() { + self.fatal_proc_rec("compilation failed!", &proc_res); + } + + let output_path = self.output_base_name().with_extension("ll"); + let proc_res = self.verify_with_filecheck(&output_path); + if !proc_res.status.success() { + self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res); + } + } + + fn run_assembly_test(&self) { + if self.config.llvm_filecheck.is_none() { + self.fatal("missing --llvm-filecheck"); + } + + let (proc_res, output_path) = self.compile_test_and_save_assembly(); if !proc_res.status.success() { self.fatal_proc_rec("compilation failed!", &proc_res); } - proc_res = self.check_ir_with_filecheck(); + let proc_res = self.verify_with_filecheck(&output_path); if !proc_res.status.success() { self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res); } diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 240287fa248bd..c54035cdec510 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -41,7 +41,6 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[ ("armv7", "arm"), ("armv7s", "arm"), ("asmjs", "asmjs"), - ("cuda", "cuda"), ("hexagon", "hexagon"), ("i386", "x86"), ("i586", "x86"), @@ -51,6 +50,7 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[ ("mips64el", "mips64"), ("mipsel", "mips"), ("msp430", "msp430"), + ("nvptx64", "nvptx64"), ("powerpc", "powerpc"), ("powerpc64", "powerpc64"), ("powerpc64le", "powerpc64"), @@ -158,7 +158,7 @@ fn test_get_arch_failure() { fn test_get_arch() { assert_eq!("x86_64", get_arch("x86_64-unknown-linux-gnu")); assert_eq!("x86_64", get_arch("amd64")); - assert_eq!("cuda", get_arch("nvptx64-nvidia-cuda")); + assert_eq!("nvptx64", get_arch("nvptx64-nvidia-cuda")); } #[test]