about summary refs log tree commit diff
path: root/src/tools
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-01-26 07:08:18 +0000
committerbors <bors@rust-lang.org>2019-01-26 07:08:18 +0000
commit42eb5ff4042236ec3635035332e059afa7d63f9d (patch)
tree2add28d90e48f64c036bf3dd0b37f454979e44e2 /src/tools
parent9df043b543bb9bc3e50bc243811c58d52a3aefea (diff)
parentce289c6c9911c7ea55b7f30b125d3c38ed359da4 (diff)
downloadrust-42eb5ff4042236ec3635035332e059afa7d63f9d.tar.gz
rust-42eb5ff4042236ec3635035332e059afa7d63f9d.zip
Auto merge of #55641 - nagisa:optimize-attr, r=pnkfelix
Implement optimize(size) and optimize(speed) attributes

This PR implements both `optimize(size)` and `optimize(speed)` attributes.

While the functionality itself works fine now, this PR is not yet complete: the code might be messy in places and, most importantly, the compiletest must be improved with functionality to run tests with custom optimization levels. Otherwise the new attribute cannot be tested properly. Oh, and not all of the RFC is implemented – attribute propagation is not implemented for example.

# TODO

* [x] Improve compiletest so that tests can be written;
* [x] Assign a proper error number (E9999 currently, no idea how to allocate a number properly);
* [ ] Perhaps reduce the duplication in LLVM attribute assignment code…
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/compiletest/src/header.rs2
-rw-r--r--src/tools/compiletest/src/runtest.rs72
2 files changed, 59 insertions, 15 deletions
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 5eb1f5ec5ff..394e408e415 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -542,6 +542,8 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut dyn FnMut(&str)) {
         "#"
     };
 
+    // FIXME: would be nice to allow some whitespace between comment and brace :)
+    // It took me like 2 days to debug why compile-flags weren’t taken into account for my test :)
     let comment_with_brace = comment.to_string() + "[";
 
     let rdr = BufReader::new(File::open(testfile).unwrap());
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 400c205d44b..375dc1c1283 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -552,9 +552,10 @@ impl<'test> TestCx<'test> {
             .args(&["--target", &self.config.target])
             .arg("-L")
             .arg(&aux_dir)
-            .args(self.split_maybe_args(&self.config.target_rustcflags))
             .args(&self.props.compile_flags)
             .envs(self.props.exec_env.clone());
+        self.maybe_add_external_args(&mut rustc,
+                                     self.split_maybe_args(&self.config.target_rustcflags));
 
         let src = match read_from {
             ReadFrom::Stdin(src) => Some(src),
@@ -587,6 +588,15 @@ impl<'test> TestCx<'test> {
         }
     }
 
+    fn set_revision_flags(&self, cmd: &mut Command) {
+        if let Some(revision) = self.revision {
+            // Normalize revisions to be lowercase and replace `-`s with `_`s.
+            // Otherwise the `--cfg` flag is not valid.
+            let normalized_revision = revision.to_lowercase().replace("-", "_");
+            cmd.args(&["--cfg", &normalized_revision]);
+        }
+    }
+
     fn typecheck_source(&self, src: String) -> ProcRes {
         let mut rustc = Command::new(&self.config.rustc_path);
 
@@ -612,12 +622,9 @@ impl<'test> TestCx<'test> {
             .arg(&self.config.build_base)
             .arg("-L")
             .arg(aux_dir);
-
-        if let Some(revision) = self.revision {
-            rustc.args(&["--cfg", revision]);
-        }
-
-        rustc.args(self.split_maybe_args(&self.config.target_rustcflags));
+        self.set_revision_flags(&mut rustc);
+        self.maybe_add_external_args(&mut rustc,
+                                     self.split_maybe_args(&self.config.target_rustcflags));
         rustc.args(&self.props.compile_flags);
 
         self.compose_and_run_compiler(rustc, Some(src))
@@ -1119,6 +1126,35 @@ impl<'test> TestCx<'test> {
         Some(new_options.join(" "))
     }
 
+    fn maybe_add_external_args(&self, cmd: &mut Command, args: Vec<String>) {
+        // Filter out the arguments that should not be added by runtest here.
+        //
+        // Notable use-cases are: do not add our optimisation flag if
+        // `compile-flags: -Copt-level=x` and similar for debug-info level as well.
+        const OPT_FLAGS: &[&str] = &["-O", "-Copt-level=", /*-C<space>*/"opt-level="];
+        const DEBUG_FLAGS: &[&str] = &["-g", "-Cdebuginfo=", /*-C<space>*/"debuginfo="];
+
+        // FIXME: ideally we would "just" check the `cmd` itself, but it does not allow inspecting
+        // its arguments. They need to be collected separately. For now I cannot be bothered to
+        // implement this the "right" way.
+        let have_opt_flag = self.props.compile_flags.iter().any(|arg| {
+            OPT_FLAGS.iter().any(|f| arg.starts_with(f))
+        });
+        let have_debug_flag = self.props.compile_flags.iter().any(|arg| {
+            DEBUG_FLAGS.iter().any(|f| arg.starts_with(f))
+        });
+
+        for arg in args {
+            if OPT_FLAGS.iter().any(|f| arg.starts_with(f)) && have_opt_flag {
+                continue;
+            }
+            if DEBUG_FLAGS.iter().any(|f| arg.starts_with(f)) && have_debug_flag {
+                continue;
+            }
+            cmd.arg(arg);
+        }
+    }
+
     fn check_debugger_output(&self, debugger_run_result: &ProcRes, check_lines: &[String]) {
         let num_check_lines = check_lines.len();
 
@@ -1707,10 +1743,7 @@ impl<'test> TestCx<'test> {
 
             rustc.arg(&format!("--target={}", target));
         }
-
-        if let Some(revision) = self.revision {
-            rustc.args(&["--cfg", revision]);
-        }
+        self.set_revision_flags(&mut rustc);
 
         if !is_rustdoc {
             if let Some(ref incremental_dir) = self.props.incremental_dir {
@@ -1810,9 +1843,11 @@ impl<'test> TestCx<'test> {
         }
 
         if self.props.force_host {
-            rustc.args(self.split_maybe_args(&self.config.host_rustcflags));
+            self.maybe_add_external_args(&mut rustc,
+                                         self.split_maybe_args(&self.config.host_rustcflags));
         } else {
-            rustc.args(self.split_maybe_args(&self.config.target_rustcflags));
+            self.maybe_add_external_args(&mut rustc,
+                                         self.split_maybe_args(&self.config.target_rustcflags));
             if !is_rustdoc {
                 if let Some(ref linker) = self.config.linker {
                     rustc.arg(format!("-Clinker={}", linker));
@@ -2065,12 +2100,19 @@ impl<'test> TestCx<'test> {
             .arg("--input-file")
             .arg(irfile)
             .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
+        // useful flag.
+        //
+        // For now, though…
+        if let Some(rev) = self.revision {
+            let prefixes = format!("CHECK,{}", rev);
+            filecheck.args(&["--check-prefixes", &prefixes]);
+        }
         self.compose_and_run(filecheck, "", None, None)
     }
 
     fn run_codegen_test(&self) {
-        assert!(self.revision.is_none(), "revisions not relevant here");
-
         if self.config.llvm_filecheck.is_none() {
             self.fatal("missing --llvm-filecheck");
         }