From f34c4dd762dd92023dc30d1abbbe8526f3615707 Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Fri, 20 Nov 2020 08:29:42 +0000 Subject: [PATCH] Add support for assembly tests This is a port of https://github.com/rust-lang/rust/pull/58791 --- src/common.rs | 3 +++ src/header.rs | 12 +++++++++++ src/runtest.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++------ src/util.rs | 1 + 4 files changed, 67 insertions(+), 7 deletions(-) diff --git a/src/common.rs b/src/common.rs index 7e3bc73..54d861d 100644 --- a/src/common.rs +++ b/src/common.rs @@ -37,6 +37,7 @@ pub enum Mode { RunMake, Ui, MirOpt, + Assembly, } impl Mode { @@ -72,6 +73,7 @@ impl FromStr for Mode { "run-make" => Ok(RunMake), "ui" => Ok(Ui), "mir-opt" => Ok(MirOpt), + "assembly" => Ok(Assembly), _ => Err(()), } } @@ -95,6 +97,7 @@ impl fmt::Display for Mode { RunMake => "run-make", Ui => "ui", MirOpt => "mir-opt", + Assembly => "assembly", }, f) } diff --git a/src/header.rs b/src/header.rs index 5b2a65c..2bce29a 100644 --- a/src/header.rs +++ b/src/header.rs @@ -224,6 +224,7 @@ pub struct TestProps { pub normalize_stderr: Vec<(String, String)>, pub run_rustfix: bool, pub rustfix_only_machine_applicable: bool, + pub assembly_output: Option, } impl TestProps { @@ -254,6 +255,7 @@ impl TestProps { normalize_stderr: vec![], run_rustfix: false, rustfix_only_machine_applicable: false, + assembly_output: None, } } @@ -388,6 +390,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); + } }); for key in &["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] { @@ -446,6 +452,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 { @@ -505,6 +512,11 @@ impl Config { self.parse_name_directive(line, "run-pass") } + 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/runtest.rs b/src/runtest.rs index 8ed7cb6..a3afe8d 100644 --- a/src/runtest.rs +++ b/src/runtest.rs @@ -12,7 +12,7 @@ use common::{Config, TestPaths}; use common::{UI_FIXED, UI_STDERR, UI_STDOUT}; use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind}; use common::{Codegen, DebugInfoLldb, DebugInfoGdb, Rustdoc, CodegenUnits}; -use common::{Incremental, RunMake, Ui, MirOpt}; +use common::{Incremental, RunMake, Ui, MirOpt, Assembly}; use diff; use errors::{self, ErrorKind, Error}; use filetime::FileTime; @@ -142,6 +142,7 @@ impl<'test> TestCx<'test> { RunMake => self.run_rmake_test(), Ui => self.run_ui_test(), MirOpt => self.run_mir_opt_test(), + Assembly => self.run_assembly_test(), } } @@ -1441,7 +1442,8 @@ actual:\n\ Codegen | Rustdoc | RunMake | - CodegenUnits => { + CodegenUnits | + Assembly => { // do not use JSON output } } @@ -1712,10 +1714,35 @@ actual:\n\ 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, AllowUnused::No); + + 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) + filecheck.arg("--input-file").arg(output) .arg(&self.testpaths.file); self.compose_and_run(filecheck, "", None, None) } @@ -1727,12 +1754,29 @@ actual:\n\ 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/util.rs b/src/util.rs index c00f28e..9f386b5 100644 --- a/src/util.rs +++ b/src/util.rs @@ -41,6 +41,7 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[ ("i686", "x86"), ("mips", "mips"), ("msp430", "msp430"), + ("nvptx64", "nvptx64"), ("powerpc", "powerpc"), ("powerpc64", "powerpc64"), ("s390x", "s390x"),