Home | History | Annotate | Download | only in Driver
      1 //===--- Compilation.h - Compilation Task Data Structure --------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #ifndef LLVM_CLANG_DRIVER_COMPILATION_H
     11 #define LLVM_CLANG_DRIVER_COMPILATION_H
     12 
     13 #include "clang/Driver/Action.h"
     14 #include "clang/Driver/Job.h"
     15 #include "clang/Driver/Util.h"
     16 #include "llvm/ADT/DenseMap.h"
     17 #include <map>
     18 
     19 namespace llvm {
     20 namespace opt {
     21   class DerivedArgList;
     22   class InputArgList;
     23 }
     24 }
     25 
     26 namespace clang {
     27 namespace driver {
     28   class Driver;
     29   class JobList;
     30   class ToolChain;
     31 
     32 /// Compilation - A set of tasks to perform for a single driver
     33 /// invocation.
     34 class Compilation {
     35   /// The driver we were created by.
     36   const Driver &TheDriver;
     37 
     38   /// The default tool chain.
     39   const ToolChain &DefaultToolChain;
     40 
     41   /// A mask of all the programming models the host has to support in the
     42   /// current compilation.
     43   unsigned ActiveOffloadMask;
     44 
     45   /// Array with the toolchains of offloading host and devices in the order they
     46   /// were requested by the user. We are preserving that order in case the code
     47   /// generation needs to derive a programming-model-specific semantic out of
     48   /// it.
     49   std::multimap<Action::OffloadKind, const ToolChain *>
     50       OrderedOffloadingToolchains;
     51 
     52   /// The original (untranslated) input argument list.
     53   llvm::opt::InputArgList *Args;
     54 
     55   /// The driver translated arguments. Note that toolchains may perform their
     56   /// own argument translation.
     57   llvm::opt::DerivedArgList *TranslatedArgs;
     58 
     59   /// The list of actions we've created via MakeAction.  This is not accessible
     60   /// to consumers; it's here just to manage ownership.
     61   std::vector<std::unique_ptr<Action>> AllActions;
     62 
     63   /// The list of actions.  This is maintained and modified by consumers, via
     64   /// getActions().
     65   ActionList Actions;
     66 
     67   /// The root list of jobs.
     68   JobList Jobs;
     69 
     70   /// Cache of translated arguments for a particular tool chain, bound
     71   /// architecture, and device offload kind.
     72   struct TCArgsKey final {
     73     const ToolChain *TC = nullptr;
     74     StringRef BoundArch;
     75     Action::OffloadKind DeviceOffloadKind = Action::OFK_None;
     76     bool operator<(const TCArgsKey &K) const {
     77       if (TC < K.TC)
     78         return true;
     79       else if (TC == K.TC && BoundArch < K.BoundArch)
     80         return true;
     81       else if (TC == K.TC && BoundArch == K.BoundArch &&
     82                DeviceOffloadKind < K.DeviceOffloadKind)
     83         return true;
     84       return false;
     85     }
     86     TCArgsKey(const ToolChain *TC, StringRef BoundArch,
     87               Action::OffloadKind DeviceOffloadKind)
     88         : TC(TC), BoundArch(BoundArch), DeviceOffloadKind(DeviceOffloadKind) {}
     89   };
     90   std::map<TCArgsKey, llvm::opt::DerivedArgList *> TCArgs;
     91 
     92   /// Temporary files which should be removed on exit.
     93   llvm::opt::ArgStringList TempFiles;
     94 
     95   /// Result files which should be removed on failure.
     96   ArgStringMap ResultFiles;
     97 
     98   /// Result files which are generated correctly on failure, and which should
     99   /// only be removed if we crash.
    100   ArgStringMap FailureResultFiles;
    101 
    102   /// Redirection for stdout, stderr, etc.
    103   const StringRef **Redirects;
    104 
    105   /// Whether we're compiling for diagnostic purposes.
    106   bool ForDiagnostics;
    107 
    108 public:
    109   Compilation(const Driver &D, const ToolChain &DefaultToolChain,
    110               llvm::opt::InputArgList *Args,
    111               llvm::opt::DerivedArgList *TranslatedArgs);
    112   ~Compilation();
    113 
    114   const Driver &getDriver() const { return TheDriver; }
    115 
    116   const ToolChain &getDefaultToolChain() const { return DefaultToolChain; }
    117 
    118   unsigned isOffloadingHostKind(Action::OffloadKind Kind) const {
    119     return ActiveOffloadMask & Kind;
    120   }
    121 
    122   /// Iterator that visits device toolchains of a given kind.
    123   typedef const std::multimap<Action::OffloadKind,
    124                               const ToolChain *>::const_iterator
    125       const_offload_toolchains_iterator;
    126   typedef std::pair<const_offload_toolchains_iterator,
    127                     const_offload_toolchains_iterator>
    128       const_offload_toolchains_range;
    129 
    130   template <Action::OffloadKind Kind>
    131   const_offload_toolchains_range getOffloadToolChains() const {
    132     return OrderedOffloadingToolchains.equal_range(Kind);
    133   }
    134 
    135   /// Return true if an offloading tool chain of a given kind exists.
    136   template <Action::OffloadKind Kind> bool hasOffloadToolChain() const {
    137     return OrderedOffloadingToolchains.find(Kind) !=
    138            OrderedOffloadingToolchains.end();
    139   }
    140 
    141   /// Return an offload toolchain of the provided kind. Only one is expected to
    142   /// exist.
    143   template <Action::OffloadKind Kind>
    144   const ToolChain *getSingleOffloadToolChain() const {
    145     auto TCs = getOffloadToolChains<Kind>();
    146 
    147     assert(TCs.first != TCs.second &&
    148            "No tool chains of the selected kind exist!");
    149     assert(std::next(TCs.first) == TCs.second &&
    150            "More than one tool chain of the this kind exist.");
    151     return TCs.first->second;
    152   }
    153 
    154   void addOffloadDeviceToolChain(const ToolChain *DeviceToolChain,
    155                                  Action::OffloadKind OffloadKind) {
    156     assert(OffloadKind != Action::OFK_Host && OffloadKind != Action::OFK_None &&
    157            "This is not a device tool chain!");
    158 
    159     // Update the host offload kind to also contain this kind.
    160     ActiveOffloadMask |= OffloadKind;
    161     OrderedOffloadingToolchains.insert(
    162         std::make_pair(OffloadKind, DeviceToolChain));
    163   }
    164 
    165   const llvm::opt::InputArgList &getInputArgs() const { return *Args; }
    166 
    167   const llvm::opt::DerivedArgList &getArgs() const { return *TranslatedArgs; }
    168 
    169   llvm::opt::DerivedArgList &getArgs() { return *TranslatedArgs; }
    170 
    171   ActionList &getActions() { return Actions; }
    172   const ActionList &getActions() const { return Actions; }
    173 
    174   /// Creates a new Action owned by this Compilation.
    175   ///
    176   /// The new Action is *not* added to the list returned by getActions().
    177   template <typename T, typename... Args> T *MakeAction(Args &&... Arg) {
    178     T *RawPtr = new T(std::forward<Args>(Arg)...);
    179     AllActions.push_back(std::unique_ptr<Action>(RawPtr));
    180     return RawPtr;
    181   }
    182 
    183   JobList &getJobs() { return Jobs; }
    184   const JobList &getJobs() const { return Jobs; }
    185 
    186   void addCommand(std::unique_ptr<Command> C) { Jobs.addJob(std::move(C)); }
    187 
    188   const llvm::opt::ArgStringList &getTempFiles() const { return TempFiles; }
    189 
    190   const ArgStringMap &getResultFiles() const { return ResultFiles; }
    191 
    192   const ArgStringMap &getFailureResultFiles() const {
    193     return FailureResultFiles;
    194   }
    195 
    196   /// Returns the sysroot path.
    197   StringRef getSysRoot() const;
    198 
    199   /// getArgsForToolChain - Return the derived argument list for the
    200   /// tool chain \p TC (or the default tool chain, if TC is not specified).
    201   /// If a device offloading kind is specified, a translation specific for that
    202   /// kind is performed, if any.
    203   ///
    204   /// \param BoundArch - The bound architecture name, or 0.
    205   /// \param DeviceOffloadKind - The offload device kind that should be used in
    206   /// the translation, if any.
    207   const llvm::opt::DerivedArgList &
    208   getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
    209                       Action::OffloadKind DeviceOffloadKind);
    210 
    211   /// addTempFile - Add a file to remove on exit, and returns its
    212   /// argument.
    213   const char *addTempFile(const char *Name) {
    214     TempFiles.push_back(Name);
    215     return Name;
    216   }
    217 
    218   /// addResultFile - Add a file to remove on failure, and returns its
    219   /// argument.
    220   const char *addResultFile(const char *Name, const JobAction *JA) {
    221     ResultFiles[JA] = Name;
    222     return Name;
    223   }
    224 
    225   /// addFailureResultFile - Add a file to remove if we crash, and returns its
    226   /// argument.
    227   const char *addFailureResultFile(const char *Name, const JobAction *JA) {
    228     FailureResultFiles[JA] = Name;
    229     return Name;
    230   }
    231 
    232   /// CleanupFile - Delete a given file.
    233   ///
    234   /// \param IssueErrors - Report failures as errors.
    235   /// \return Whether the file was removed successfully.
    236   bool CleanupFile(const char *File, bool IssueErrors = false) const;
    237 
    238   /// CleanupFileList - Remove the files in the given list.
    239   ///
    240   /// \param IssueErrors - Report failures as errors.
    241   /// \return Whether all files were removed successfully.
    242   bool CleanupFileList(const llvm::opt::ArgStringList &Files,
    243                        bool IssueErrors = false) const;
    244 
    245   /// CleanupFileMap - Remove the files in the given map.
    246   ///
    247   /// \param JA - If specified, only delete the files associated with this
    248   /// JobAction.  Otherwise, delete all files in the map.
    249   /// \param IssueErrors - Report failures as errors.
    250   /// \return Whether all files were removed successfully.
    251   bool CleanupFileMap(const ArgStringMap &Files,
    252                       const JobAction *JA,
    253                       bool IssueErrors = false) const;
    254 
    255   /// ExecuteCommand - Execute an actual command.
    256   ///
    257   /// \param FailingCommand - For non-zero results, this will be set to the
    258   /// Command which failed, if any.
    259   /// \return The result code of the subprocess.
    260   int ExecuteCommand(const Command &C, const Command *&FailingCommand) const;
    261 
    262   /// ExecuteJob - Execute a single job.
    263   ///
    264   /// \param FailingCommands - For non-zero results, this will be a vector of
    265   /// failing commands and their associated result code.
    266   void ExecuteJobs(
    267       const JobList &Jobs,
    268       SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) const;
    269 
    270   /// initCompilationForDiagnostics - Remove stale state and suppress output
    271   /// so compilation can be reexecuted to generate additional diagnostic
    272   /// information (e.g., preprocessed source(s)).
    273   void initCompilationForDiagnostics();
    274 
    275   /// Return true if we're compiling for diagnostics.
    276   bool isForDiagnostics() const { return ForDiagnostics; }
    277 
    278   /// Redirect - Redirect output of this compilation. Can only be done once.
    279   ///
    280   /// \param Redirects - array of pointers to paths. The array
    281   /// should have a size of three. The inferior process's
    282   /// stdin(0), stdout(1), and stderr(2) will be redirected to the
    283   /// corresponding paths. This compilation instance becomes
    284   /// the owner of Redirects and will delete the array and StringRef's.
    285   void Redirect(const StringRef** Redirects);
    286 };
    287 
    288 } // end namespace driver
    289 } // end namespace clang
    290 
    291 #endif
    292