Skip to content

Commit 69ba28d

Browse files
authored
Merge pull request #225 from alessandrod/assembly-tests
Add support for assembly tests
2 parents 5fd13ff + 427508e commit 69ba28d

File tree

7 files changed

+86
-7
lines changed

7 files changed

+86
-7
lines changed

src/common.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ pub enum Mode {
3737
RunMake,
3838
Ui,
3939
MirOpt,
40+
Assembly,
4041
}
4142

4243
impl Mode {
@@ -72,6 +73,7 @@ impl FromStr for Mode {
7273
"run-make" => Ok(RunMake),
7374
"ui" => Ok(Ui),
7475
"mir-opt" => Ok(MirOpt),
76+
"assembly" => Ok(Assembly),
7577
_ => Err(()),
7678
}
7779
}
@@ -95,6 +97,7 @@ impl fmt::Display for Mode {
9597
RunMake => "run-make",
9698
Ui => "ui",
9799
MirOpt => "mir-opt",
100+
Assembly => "assembly",
98101
},
99102
f)
100103
}

src/header.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ pub struct TestProps {
224224
pub normalize_stderr: Vec<(String, String)>,
225225
pub run_rustfix: bool,
226226
pub rustfix_only_machine_applicable: bool,
227+
pub assembly_output: Option<String>,
227228
}
228229

229230
impl TestProps {
@@ -254,6 +255,7 @@ impl TestProps {
254255
normalize_stderr: vec![],
255256
run_rustfix: false,
256257
rustfix_only_machine_applicable: false,
258+
assembly_output: None,
257259
}
258260
}
259261

@@ -388,6 +390,10 @@ impl TestProps {
388390
self.rustfix_only_machine_applicable =
389391
config.parse_rustfix_only_machine_applicable(ln);
390392
}
393+
394+
if self.assembly_output.is_none() {
395+
self.assembly_output = config.parse_assembly_output(ln);
396+
}
391397
});
392398

393399
for key in &["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] {
@@ -446,6 +452,7 @@ impl Config {
446452

447453
fn parse_aux_build(&self, line: &str) -> Option<String> {
448454
self.parse_name_value_directive(line, "aux-build")
455+
.map(|r| r.trim().to_string())
449456
}
450457

451458
fn parse_compile_flags(&self, line: &str) -> Option<String> {
@@ -505,6 +512,11 @@ impl Config {
505512
self.parse_name_directive(line, "run-pass")
506513
}
507514

515+
fn parse_assembly_output(&self, line: &str) -> Option<String> {
516+
self.parse_name_value_directive(line, "assembly-output")
517+
.map(|r| r.trim().to_string())
518+
}
519+
508520
fn parse_env(&self, line: &str, name: &str) -> Option<(String, String)> {
509521
self.parse_name_value_directive(line, name).map(|nv| {
510522
// nv is either FOO or FOO=BAR

src/runtest.rs

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use common::{Config, TestPaths};
1212
use common::{expected_output_path, UI_FIXED, UI_STDERR, UI_STDOUT};
1313
use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind};
1414
use common::{Codegen, DebugInfoLldb, DebugInfoGdb, Rustdoc, CodegenUnits};
15-
use common::{Incremental, RunMake, Ui, MirOpt};
15+
use common::{Incremental, RunMake, Ui, MirOpt, Assembly};
1616
use diff;
1717
use errors::{self, ErrorKind, Error};
1818
use filetime::FileTime;
@@ -142,6 +142,7 @@ impl<'test> TestCx<'test> {
142142
RunMake => self.run_rmake_test(),
143143
Ui => self.run_ui_test(),
144144
MirOpt => self.run_mir_opt_test(),
145+
Assembly => self.run_assembly_test(),
145146
}
146147
}
147148

@@ -1441,7 +1442,8 @@ actual:\n\
14411442
Codegen |
14421443
Rustdoc |
14431444
RunMake |
1444-
CodegenUnits => {
1445+
CodegenUnits |
1446+
Assembly => {
14451447
// do not use JSON output
14461448
}
14471449
}
@@ -1712,10 +1714,35 @@ actual:\n\
17121714
self.compose_and_run_compiler(rustc, None)
17131715
}
17141716

1715-
fn check_ir_with_filecheck(&self) -> ProcRes {
1716-
let irfile = self.output_base_name().with_extension("ll");
1717+
fn compile_test_and_save_assembly(&self) -> (ProcRes, PathBuf) {
1718+
// This works with both `--emit asm` (as default output name for the assembly)
1719+
// and `ptx-linker` because the latter can write output at requested location.
1720+
let output_path = self.output_base_name().with_extension("s");
1721+
1722+
let output_file = TargetLocation::ThisFile(output_path.clone());
1723+
let mut rustc = self.make_compile_args(&self.testpaths.file, output_file, AllowUnused::No);
1724+
1725+
rustc.arg("-L").arg(self.aux_output_dir_name());
1726+
1727+
match self.props.assembly_output.as_ref().map(AsRef::as_ref) {
1728+
Some("emit-asm") => {
1729+
rustc.arg("--emit=asm");
1730+
}
1731+
1732+
Some("ptx-linker") => {
1733+
// No extra flags needed.
1734+
}
1735+
1736+
Some(_) => self.fatal("unknown 'assembly-output' header"),
1737+
None => self.fatal("missing 'assembly-output' header"),
1738+
}
1739+
1740+
(self.compose_and_run_compiler(rustc, None), output_path)
1741+
}
1742+
1743+
fn verify_with_filecheck(&self, output: &Path) -> ProcRes {
17171744
let mut filecheck = Command::new(self.config.llvm_filecheck.as_ref().unwrap());
1718-
filecheck.arg("--input-file").arg(irfile)
1745+
filecheck.arg("--input-file").arg(output)
17191746
.arg(&self.testpaths.file);
17201747
self.compose_and_run(filecheck, "", None, None)
17211748
}
@@ -1727,12 +1754,29 @@ actual:\n\
17271754
self.fatal("missing --llvm-filecheck");
17281755
}
17291756

1730-
let mut proc_res = self.compile_test_and_save_ir();
1757+
let proc_res = self.compile_test_and_save_ir();
1758+
if !proc_res.status.success() {
1759+
self.fatal_proc_rec("compilation failed!", &proc_res);
1760+
}
1761+
1762+
let output_path = self.output_base_name().with_extension("ll");
1763+
let proc_res = self.verify_with_filecheck(&output_path);
1764+
if !proc_res.status.success() {
1765+
self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res);
1766+
}
1767+
}
1768+
1769+
fn run_assembly_test(&self) {
1770+
if self.config.llvm_filecheck.is_none() {
1771+
self.fatal("missing --llvm-filecheck");
1772+
}
1773+
1774+
let (proc_res, output_path) = self.compile_test_and_save_assembly();
17311775
if !proc_res.status.success() {
17321776
self.fatal_proc_rec("compilation failed!", &proc_res);
17331777
}
17341778

1735-
proc_res = self.check_ir_with_filecheck();
1779+
let proc_res = self.verify_with_filecheck(&output_path);
17361780
if !proc_res.status.success() {
17371781
self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res);
17381782
}

src/util.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
4343
("i686", "x86"),
4444
("mips", "mips"),
4545
("msp430", "msp430"),
46+
("nvptx64", "nvptx64"),
4647
("powerpc", "powerpc"),
4748
("powerpc64", "powerpc64"),
4849
("s390x", "s390x"),

test-project/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ features = ["tmp"]
1111

1212
[features]
1313
rustc = ["compiletest_rs/rustc"]
14+
assembly = []

test-project/tests/assembly/panic.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// assembly-output: emit-asm
2+
// compile-flags: --crate-type rlib
3+
#![no_std]
4+
5+
#[no_mangle]
6+
fn panic_fun() -> u32 {
7+
// CHECK-LABEL: panic_fun:
8+
// CHECK: ud2
9+
panic!();
10+
}

test-project/tests/tests.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
extern crate compiletest_rs as compiletest;
22

3+
use std::env;
34
use std::path::PathBuf;
45

56
fn run_mode(mode: &'static str, custom_dir: Option<&'static str>) {
@@ -11,6 +12,11 @@ fn run_mode(mode: &'static str, custom_dir: Option<&'static str>) {
1112
let dir = custom_dir.unwrap_or(mode);
1213
config.src_base = PathBuf::from(format!("tests/{}", dir));
1314
config.target_rustcflags = Some("-L target/debug -L target/debug/deps".to_string());
15+
config.llvm_filecheck = Some(
16+
env::var("FILECHECK")
17+
.unwrap_or("FileCheck".to_string())
18+
.into(),
19+
);
1420
config.clean_rmeta();
1521

1622
compiletest::run_tests(&config);
@@ -21,6 +27,8 @@ fn compile_test() {
2127
run_mode("compile-fail", None);
2228
run_mode("run-pass", None);
2329
run_mode("ui", None);
30+
#[cfg(feature = "assembly")]
31+
run_mode("assembly", None);
2432

2533
#[cfg(feature = "rustc")]
2634
run_mode("pretty", None);

0 commit comments

Comments
 (0)