[cfe-commits] r66885 - in /cfe/trunk: include/clang/Basic/DiagnosticDriverKinds.def include/clang/Driver/Driver.h lib/Driver/Driver.cpp

Daniel Dunbar daniel at zuster.org
Fri Mar 13 04:38:43 PDT 2009


Author: ddunbar
Date: Fri Mar 13 06:38:42 2009
New Revision: 66885

URL: http://llvm.org/viewvc/llvm-project?rev=66885&view=rev
Log:
Driver: Complete "pipelining" (building the list of abstract actions
to perform). Still doesn't do anything interesting.
 - This code came out much cleaner than in ccc with the reworked
   phases & mapping of types to lists of compilation steps (phases) to
   perform.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.def
    cfe/trunk/include/clang/Driver/Driver.h
    cfe/trunk/lib/Driver/Driver.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.def?rev=66885&r1=66884&r2=66885&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.def Fri Mar 13 06:38:42 2009
@@ -28,3 +28,6 @@
      "no input files")
 DIAG(err_drv_use_of_Z_option, ERROR,
      "unsupported use of internal gcc -Z option '%0'")
+
+DIAG(warn_drv_input_file_unused, WARNING,
+     "%0: '%1' input file unused when '%2' is present")

Modified: cfe/trunk/include/clang/Driver/Driver.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Driver.h?rev=66885&r1=66884&r2=66885&view=diff

==============================================================================
--- cfe/trunk/include/clang/Driver/Driver.h (original)
+++ cfe/trunk/include/clang/Driver/Driver.h Fri Mar 13 06:38:42 2009
@@ -12,6 +12,7 @@
 
 #include "clang/Basic/Diagnostic.h"
 
+#include "clang/Driver/Phases.h"
 #include "clang/Driver/Util.h"
 
 #include "llvm/System/Path.h" // FIXME: Kill when CompilationInfo
@@ -32,25 +33,6 @@
 /// Driver - Encapsulate logic for constructing compilation processes
 /// from a set of gcc-driver-like command line arguments.
 class Driver {
-  /// PhaseOrder - Ordered values for successive stages in the
-  /// compilation process which interact with user options.
-  enum PhaseOrder {
-    /// Nothing.
-    NoPhaseOrder = 0,
-
-    /// Only run the preprocessor.
-    PreprocessPhaseOrder,
-
-    /// Only run the preprocessor and compiler.
-    CompilePhaseOrder,
-
-    /// Only run the preprocessor, compiler, and assembler.
-    AssemblePhaseOrder,
-
-    /// Run everything.
-    PostAssemblePhaseOrder
-  };
-
   OptTable *Opts;
 
   Diagnostic &Diags;
@@ -184,6 +166,12 @@
   /// invocation.
   bool HandleImmediateArgs(const ArgList &Args);
 
+  /// ConstructAction - Construct the appropriate action to do for
+  /// \arg Phase on the \arg Input, taking in to account arguments
+  /// like -fsyntax-only or --analyze.
+  Action *ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
+                               Action *Input) const;
+
   /// GetHostInfo - Construct a new host info object for the given
   /// host triple.
   static HostInfo *GetHostInfo(const char *HostTriple);

Modified: cfe/trunk/lib/Driver/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Driver.cpp?rev=66885&r1=66884&r2=66885&view=diff

==============================================================================
--- cfe/trunk/lib/Driver/Driver.cpp (original)
+++ cfe/trunk/lib/Driver/Driver.cpp Fri Mar 13 06:38:42 2009
@@ -43,6 +43,8 @@
 ArgList *Driver::ParseArgStrings(const char **ArgBegin, const char **ArgEnd) {
   ArgList *Args = new ArgList(ArgBegin, ArgEnd);
   
+  // FIXME: Handle '@' args (or at least error on them).
+
   unsigned Index = 0, End = ArgEnd - ArgBegin;
   while (Index < End) {
     // gcc's handling of empty arguments doesn't make
@@ -393,43 +395,122 @@
   // Determine which compilation mode we are in. We look for options
   // which affect the phase, starting with the earliest phases, and
   // record which option we used to determine the final phase.
-  Arg *FinalPhaseOpt = 0;
-  PhaseOrder FinalPhase;
+  Arg *FinalPhaseArg = 0;
+  phases::ID FinalPhase;
 
   // -{E,M,MM} only run the preprocessor.
-  if ((FinalPhaseOpt = Args.getLastArg(options::OPT_E)) ||
-      (FinalPhaseOpt = Args.getLastArg(options::OPT_M)) ||
-      (FinalPhaseOpt = Args.getLastArg(options::OPT_MM))) {
-    FinalPhase = PreprocessPhaseOrder;
+  if ((FinalPhaseArg = Args.getLastArg(options::OPT_E)) ||
+      (FinalPhaseArg = Args.getLastArg(options::OPT_M)) ||
+      (FinalPhaseArg = Args.getLastArg(options::OPT_MM))) {
+    FinalPhase = phases::Preprocess;
     
     // -{-analyze,fsyntax-only,S} only run up to the compiler.
-  } else if ((FinalPhaseOpt = Args.getLastArg(options::OPT__analyze)) ||
-             (FinalPhaseOpt = Args.getLastArg(options::OPT_fsyntax_only)) ||
-             (FinalPhaseOpt = Args.getLastArg(options::OPT_S))) {
-    FinalPhase = CompilePhaseOrder;
+  } else if ((FinalPhaseArg = Args.getLastArg(options::OPT__analyze)) ||
+             (FinalPhaseArg = Args.getLastArg(options::OPT_fsyntax_only)) ||
+             (FinalPhaseArg = Args.getLastArg(options::OPT_S))) {
+    FinalPhase = phases::Compile;
 
     // -c only runs up to the assembler.
-  } else if ((FinalPhaseOpt = Args.getLastArg(options::OPT_c))) {
-    FinalPhase = AssemblePhaseOrder;
+  } else if ((FinalPhaseArg = Args.getLastArg(options::OPT_c))) {
+    FinalPhase = phases::Assemble;
     
     // Otherwise do everything.
   } else
-    FinalPhase = PostAssemblePhaseOrder;
+    FinalPhase = phases::Link;
 
-  if (FinalPhaseOpt)
-    FinalPhaseOpt->claim();
+  if (FinalPhaseArg)
+    FinalPhaseArg->claim();
 
   // Reject -Z* at the top level, these options should never have been
   // exposed by gcc.
   if (Arg *A = Args.getLastArg(options::OPT_Z))
     Diag(clang::diag::err_drv_use_of_Z_option) << A->getValue(Args);
 
-  // FIXME: This is just debugging code.
+  // Construct the actions to perform.
+  ActionList LinkerInputs;
   for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
-    llvm::errs() << "input " << i << ": " 
-                 << Inputs[i].second->getValue(Args) << "\n";
+    types::ID InputType = Inputs[i].first;
+    const Arg *InputArg = Inputs[i].second;
+
+    unsigned NumSteps = types::getNumCompilationPhases(InputType);
+    assert(NumSteps && "Invalid number of steps!");
+
+    // If the first step comes after the final phase we are doing as
+    // part of this compilation, warn the user about it.
+    phases::ID InitialPhase = types::getCompilationPhase(InputType, 0);
+    if (InitialPhase > FinalPhase) {
+      Diag(clang::diag::warn_drv_input_file_unused) 
+        << InputArg->getValue(Args)
+        << getPhaseName(InitialPhase)
+        << FinalPhaseArg->getOption().getName();
+      continue;
+    }
+    
+    // Build the pipeline for this file.
+    Action *Current = new InputAction(*InputArg, InputType);
+    for (unsigned i = 0; i != NumSteps; ++i) {
+      phases::ID Phase = types::getCompilationPhase(InputType, i);
+
+      // We are done if this step is past what the user requested.
+      if (Phase > FinalPhase)
+        break;
+
+      // Queue linker inputs.
+      if (Phase == phases::Link) {
+        assert(i + 1 == NumSteps && "linking must be final compilation step.");
+        LinkerInputs.push_back(Current);
+        Current = 0;
+        break;
+      }
+
+      // Otherwise construct the appropriate action.
+      Current = ConstructPhaseAction(Args, Phase, Current);
+      if (Current->getType() == types::TY_Nothing)
+        break;
+    }
+
+    // If we ended with something, add to the output list.
+    if (Current)
+      Actions.push_back(Current);
+  }
+
+  // Add a link action if necessary.
+  if (!LinkerInputs.empty())
+    Actions.push_back(new LinkJobAction(LinkerInputs, types::TY_Image));
+}
+
+Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
+                                     Action *Input) const {
+  // Build the appropriate action.
+  switch (Phase) {
+  case phases::Link: assert(0 && "link action invalid here.");
+  case phases::Preprocess: {
+    types::ID OutputTy = types::getPreprocessedType(Input->getType());
+    assert(OutputTy != types::TY_INVALID &&
+           "Cannot preprocess this input type!");
+    return new PreprocessJobAction(Input, OutputTy);
+  }
+  case phases::Precompile:
+    return new PrecompileJobAction(Input, types::TY_PCH);    
+  case phases::Compile: {
+    if (Args.hasArg(options::OPT_fsyntax_only)) {
+      return new CompileJobAction(Input, types::TY_Nothing);
+    } else if (Args.hasArg(options::OPT__analyze)) {
+      return new AnalyzeJobAction(Input, types::TY_Plist);
+    } else if (Args.hasArg(options::OPT_emit_llvm)) {
+      types::ID Output = 
+        Args.hasArg(options::OPT_S) ? types::TY_LLVMAsm : types::TY_LLVMBC;
+      return new CompileJobAction(Input, Output);
+    } else {
+      return new CompileJobAction(Input, types::TY_PP_Asm);
+    }
+  }
+  case phases::Assemble:
+    return new AssembleJobAction(Input, types::TY_Object);
   }
-  exit(0);
+
+  assert(0 && "invalid phase in ConstructPhaseAction");
+  return 0;
 }
 
 llvm::sys::Path Driver::GetFilePath(const char *Name) const {





More information about the cfe-commits mailing list