]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: rust: Add -frust-compile-until option
authorArthur Cohen <arthur.cohen@embecosm.com>
Wed, 31 Aug 2022 11:53:28 +0000 (13:53 +0200)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 31 Jan 2023 13:16:52 +0000 (14:16 +0100)
This option helps ensure that we do not introduce regressions on various
parts of the compilation pipeline. For example, a testcase (or testsuite
from the `testing` project) might pass attribute checking, expansion and
lowering, but fail during typechecking. Should a change suddenly make
that testcase fail expansion, we would not be able to notice it. By
generating tests that run up until expansion, typechecking, compilation
and so forth we ensure that no regressions are added accidentally to
already failing tests/testsuites.

gcc/rust/ChangeLog:

* lang.opt: Add new ``-frust-compile-until` option.
* rust-session-manager.cc (Session::compile_crate): Add stops around
various compilation steps in the pipeline.
* rust-session-manager.h (struct CompileOptions): Add `CompileStep` enum
and field.

gcc/testsuite/ChangeLog:

* rust/compile/frust-compile-until.rs: New test.

gcc/rust/lang.opt
gcc/rust/rust-session-manager.cc
gcc/rust/rust-session-manager.h
gcc/testsuite/rust/compile/frust-compile-until.rs [new file with mode: 0644]

index 3e6826954dac5a298ef2fc0eddd67f865b20f76e..40aafaf34d22362d2fd4c61d9ce9a16627b5eb58 100644 (file)
@@ -117,6 +117,48 @@ Rust Joined RejectNegative
 
 o
 Rust Joined Separate
+
+frust-compile-until=
+Rust Joined RejectNegative Enum(frust_compile_until) Var(flag_rust_compile_until)
+-frust-compile-until=[ast|attributecheck|expansion|nameresolution|lowering|typecheck|privacy|unsafety|const|copimlation|end]             When to stop in the pipeline when compiling Rust code
+
+Enum
+Name(frust_compile_until) Type(int) UnknownError(unknown rust compile-until %qs)
+
+EnumValue
+Enum(frust_compile_until) String(ast) Value(0)
+
+EnumValue
+Enum(frust_compile_until) String(attributecheck) Value(1)
+
+EnumValue
+Enum(frust_compile_until) String(expansion) Value(2)
+
+EnumValue
+Enum(frust_compile_until) String(nameresolution) Value(3)
+
+EnumValue
+Enum(frust_compile_until) String(lowering) Value(4)
+
+EnumValue
+Enum(frust_compile_until) String(typecheck) Value(5)
+
+EnumValue
+Enum(frust_compile_until) String(privacy) Value(6)
+
+EnumValue
+Enum(frust_compile_until) String(unsafety) Value(7)
+
+EnumValue
+Enum(frust_compile_until) String(const) Value(8)
+
+EnumValue
+Enum(frust_compile_until) String(compilation) Value(9)
+
+EnumValue
+Enum(frust_compile_until) String(end) Value(10)
+
+
 ; Documented in common.opt
 
 ; This comment is to ensure we retain the blank line above.
index 157f509915592695d394e8b8bb4daf90a2dac9a9..4ee7175b48b5f572089602faa98eb5987f2f2c65 100644 (file)
@@ -223,7 +223,9 @@ Session::handle_option (
     case OPT_frust_edition_:
       options.set_edition (flag_rust_edition);
       break;
-
+    case OPT_frust_compile_until_:
+      options.set_compile_step (flag_rust_compile_until);
+      break;
     case OPT_frust_metadata_output_:
       options.set_metadata_output (arg);
       break;
@@ -447,6 +449,8 @@ Session::compile_crate (const char *filename)
       return;
     }
 
+  auto last_step = options.get_compile_until ();
+
   // parse file here
   /* create lexer and parser - these are file-specific and so aren't instance
    * variables */
@@ -503,7 +507,7 @@ Session::compile_crate (const char *filename)
 
   // If -fsyntax-only was passed, we can just skip the remaining passes.
   // Parsing errors are already emitted in `parse_crate()`
-  if (flag_syntax_only)
+  if (flag_syntax_only || last_step == CompileOptions::CompileStep::Ast)
     return;
 
   // register plugins pipeline stage
@@ -522,8 +526,14 @@ Session::compile_crate (const char *filename)
       // TODO: what do I dump here? injected crate names?
     }
 
+  if (last_step == CompileOptions::CompileStep::AttributeCheck)
+    return;
+
   Analysis::AttributeChecker ().go (parsed_crate);
 
+  if (last_step == CompileOptions::CompileStep::Expansion)
+    return;
+
   // expansion pipeline stage
   expansion (parsed_crate);
   rust_debug ("\033[0;31mSUCCESSFULLY FINISHED EXPANSION \033[0m");
@@ -536,6 +546,9 @@ Session::compile_crate (const char *filename)
       rust_debug ("END POST-EXPANSION AST DUMP");
     }
 
+  if (last_step == CompileOptions::CompileStep::NameResolution)
+    return;
+
   // resolution pipeline stage
   Resolver::NameResolution::Resolve (parsed_crate);
   if (options.dump_option_enabled (CompileOptions::RESOLUTION_DUMP))
@@ -546,6 +559,9 @@ Session::compile_crate (const char *filename)
   if (saw_errors ())
     return;
 
+  if (last_step == CompileOptions::CompileStep::Lowering)
+    return;
+
   // lower AST to HIR
   std::unique_ptr<HIR::Crate> lowered
     = HIR::ASTLowering::Resolve (parsed_crate);
@@ -563,6 +579,9 @@ Session::compile_crate (const char *filename)
       dump_hir_pretty (hir);
     }
 
+  if (last_step == CompileOptions::CompileStep::TypeCheck)
+    return;
+
   // type resolve
   Resolver::TypeResolution::Resolve (hir);
   if (options.dump_option_enabled (CompileOptions::TYPE_RESOLUTION_DUMP))
@@ -573,17 +592,30 @@ Session::compile_crate (const char *filename)
   if (saw_errors ())
     return;
 
+  if (last_step == CompileOptions::CompileStep::Privacy)
+    return;
+
   // Various HIR error passes. The privacy pass happens before the unsafe checks
   Privacy::Resolver::resolve (hir);
   if (saw_errors ())
     return;
 
+  if (last_step == CompileOptions::CompileStep::Unsafety)
+    return;
+
   HIR::UnsafeChecker ().go (hir);
+
+  if (last_step == CompileOptions::CompileStep::Const)
+    return;
+
   HIR::ConstChecker ().go (hir);
 
   if (saw_errors ())
     return;
 
+  if (last_step == CompileOptions::CompileStep::Compilation)
+    return;
+
   // do compile to gcc generic
   Compile::Context ctx (backend);
   Compile::CompileCrate::Compile (hir, &ctx);
index db9159918096ddb9c11bc230079108d8b26f372f..43f9ba4c72f79aa2191f785fc7d58fac60489671 100644 (file)
@@ -199,6 +199,22 @@ struct CompileOptions
   } edition
     = Edition::E2015;
 
+  enum class CompileStep
+  {
+    Ast,
+    AttributeCheck,
+    Expansion,
+    NameResolution,
+    Lowering,
+    TypeCheck,
+    Privacy,
+    Unsafety,
+    Const,
+    Compilation,
+    End,
+  } compile_until
+    = CompileStep::End;
+
   bool dump_option_enabled (DumpOption option) const
   {
     return dump_options.find (option) != dump_options.end ();
@@ -239,7 +255,14 @@ struct CompileOptions
     edition = static_cast<Edition> (raw_edition);
   }
 
-  const Edition &get_edition () { return edition; }
+  const Edition &get_edition () const { return edition; }
+
+  void set_compile_step (int raw_step)
+  {
+    compile_until = static_cast<CompileStep> (raw_step);
+  }
+
+  const CompileStep &get_compile_until () const { return compile_until; }
 
   void set_metadata_output (const std::string &path)
   {
diff --git a/gcc/testsuite/rust/compile/frust-compile-until.rs b/gcc/testsuite/rust/compile/frust-compile-until.rs
new file mode 100644 (file)
index 0000000..7bb3932
--- /dev/null
@@ -0,0 +1,7 @@
+// { dg-additional-options "-frust-compile-until=unsafety" }
+
+unsafe fn foo() {}
+
+fn main() {
+    foo()
+}