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