Compilation.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. //===- Compilation.cpp - Compilation Task Implementation ------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "clang/Driver/Compilation.h"
  9. #include "clang/Basic/LLVM.h"
  10. #include "clang/Driver/Action.h"
  11. #include "clang/Driver/Driver.h"
  12. #include "clang/Driver/DriverDiagnostic.h"
  13. #include "clang/Driver/Job.h"
  14. #include "clang/Driver/Options.h"
  15. #include "clang/Driver/ToolChain.h"
  16. #include "clang/Driver/Util.h"
  17. #include "llvm/ADT/None.h"
  18. #include "llvm/ADT/STLExtras.h"
  19. #include "llvm/ADT/SmallVector.h"
  20. #include "llvm/ADT/Triple.h"
  21. #include "llvm/Option/ArgList.h"
  22. #include "llvm/Option/OptSpecifier.h"
  23. #include "llvm/Option/Option.h"
  24. #include "llvm/Support/FileSystem.h"
  25. #include "llvm/Support/raw_ostream.h"
  26. #include <cassert>
  27. #include <string>
  28. #include <system_error>
  29. #include <utility>
  30. using namespace clang;
  31. using namespace driver;
  32. using namespace llvm::opt;
  33. Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
  34. InputArgList *_Args, DerivedArgList *_TranslatedArgs,
  35. bool ContainsError)
  36. : TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args),
  37. TranslatedArgs(_TranslatedArgs), ContainsError(ContainsError) {
  38. // The offloading host toolchain is the default toolchain.
  39. OrderedOffloadingToolchains.insert(
  40. std::make_pair(Action::OFK_Host, &DefaultToolChain));
  41. }
  42. Compilation::~Compilation() {
  43. // Remove temporary files. This must be done before arguments are freed, as
  44. // the file names might be derived from the input arguments.
  45. if (!TheDriver.isSaveTempsEnabled() && !ForceKeepTempFiles)
  46. CleanupFileList(TempFiles);
  47. delete TranslatedArgs;
  48. delete Args;
  49. // Free any derived arg lists.
  50. for (auto Arg : TCArgs)
  51. if (Arg.second != TranslatedArgs)
  52. delete Arg.second;
  53. }
  54. const DerivedArgList &
  55. Compilation::getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
  56. Action::OffloadKind DeviceOffloadKind) {
  57. if (!TC)
  58. TC = &DefaultToolChain;
  59. DerivedArgList *&Entry = TCArgs[{TC, BoundArch, DeviceOffloadKind}];
  60. if (!Entry) {
  61. SmallVector<Arg *, 4> AllocatedArgs;
  62. DerivedArgList *OpenMPArgs = nullptr;
  63. // Translate OpenMP toolchain arguments provided via the -Xopenmp-target flags.
  64. if (DeviceOffloadKind == Action::OFK_OpenMP) {
  65. const ToolChain *HostTC = getSingleOffloadToolChain<Action::OFK_Host>();
  66. bool SameTripleAsHost = (TC->getTriple() == HostTC->getTriple());
  67. OpenMPArgs = TC->TranslateOpenMPTargetArgs(
  68. *TranslatedArgs, SameTripleAsHost, AllocatedArgs);
  69. }
  70. DerivedArgList *NewDAL = nullptr;
  71. if (!OpenMPArgs) {
  72. NewDAL = TC->TranslateXarchArgs(*TranslatedArgs, BoundArch,
  73. DeviceOffloadKind, &AllocatedArgs);
  74. } else {
  75. NewDAL = TC->TranslateXarchArgs(*OpenMPArgs, BoundArch, DeviceOffloadKind,
  76. &AllocatedArgs);
  77. if (!NewDAL)
  78. NewDAL = OpenMPArgs;
  79. else
  80. delete OpenMPArgs;
  81. }
  82. if (!NewDAL) {
  83. Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch, DeviceOffloadKind);
  84. if (!Entry)
  85. Entry = TranslatedArgs;
  86. } else {
  87. Entry = TC->TranslateArgs(*NewDAL, BoundArch, DeviceOffloadKind);
  88. if (!Entry)
  89. Entry = NewDAL;
  90. else
  91. delete NewDAL;
  92. }
  93. // Add allocated arguments to the final DAL.
  94. for (auto ArgPtr : AllocatedArgs)
  95. Entry->AddSynthesizedArg(ArgPtr);
  96. }
  97. return *Entry;
  98. }
  99. bool Compilation::CleanupFile(const char *File, bool IssueErrors) const {
  100. // FIXME: Why are we trying to remove files that we have not created? For
  101. // example we should only try to remove a temporary assembly file if
  102. // "clang -cc1" succeed in writing it. Was this a workaround for when
  103. // clang was writing directly to a .s file and sometimes leaving it behind
  104. // during a failure?
  105. // FIXME: If this is necessary, we can still try to split
  106. // llvm::sys::fs::remove into a removeFile and a removeDir and avoid the
  107. // duplicated stat from is_regular_file.
  108. // Don't try to remove files which we don't have write access to (but may be
  109. // able to remove), or non-regular files. Underlying tools may have
  110. // intentionally not overwritten them.
  111. if (!llvm::sys::fs::can_write(File) || !llvm::sys::fs::is_regular_file(File))
  112. return true;
  113. if (std::error_code EC = llvm::sys::fs::remove(File)) {
  114. // Failure is only failure if the file exists and is "regular". We checked
  115. // for it being regular before, and llvm::sys::fs::remove ignores ENOENT,
  116. // so we don't need to check again.
  117. if (IssueErrors)
  118. getDriver().Diag(diag::err_drv_unable_to_remove_file)
  119. << EC.message();
  120. return false;
  121. }
  122. return true;
  123. }
  124. bool Compilation::CleanupFileList(const llvm::opt::ArgStringList &Files,
  125. bool IssueErrors) const {
  126. bool Success = true;
  127. for (const auto &File: Files)
  128. Success &= CleanupFile(File, IssueErrors);
  129. return Success;
  130. }
  131. bool Compilation::CleanupFileMap(const ArgStringMap &Files,
  132. const JobAction *JA,
  133. bool IssueErrors) const {
  134. bool Success = true;
  135. for (const auto &File : Files) {
  136. // If specified, only delete the files associated with the JobAction.
  137. // Otherwise, delete all files in the map.
  138. if (JA && File.first != JA)
  139. continue;
  140. Success &= CleanupFile(File.second, IssueErrors);
  141. }
  142. return Success;
  143. }
  144. int Compilation::ExecuteCommand(const Command &C,
  145. const Command *&FailingCommand) const {
  146. if ((getDriver().CCPrintOptions ||
  147. getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) {
  148. raw_ostream *OS = &llvm::errs();
  149. std::unique_ptr<llvm::raw_fd_ostream> OwnedStream;
  150. // Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the
  151. // output stream.
  152. if (getDriver().CCPrintOptions &&
  153. !getDriver().CCPrintOptionsFilename.empty()) {
  154. std::error_code EC;
  155. OwnedStream.reset(new llvm::raw_fd_ostream(
  156. getDriver().CCPrintOptionsFilename, EC,
  157. llvm::sys::fs::OF_Append | llvm::sys::fs::OF_TextWithCRLF));
  158. if (EC) {
  159. getDriver().Diag(diag::err_drv_cc_print_options_failure)
  160. << EC.message();
  161. FailingCommand = &C;
  162. return 1;
  163. }
  164. OS = OwnedStream.get();
  165. }
  166. if (getDriver().CCPrintOptions)
  167. *OS << "[Logging clang options]\n";
  168. C.Print(*OS, "\n", /*Quote=*/getDriver().CCPrintOptions);
  169. }
  170. std::string Error;
  171. bool ExecutionFailed;
  172. int Res = C.Execute(Redirects, &Error, &ExecutionFailed);
  173. if (PostCallback)
  174. PostCallback(C, Res);
  175. if (!Error.empty()) {
  176. assert(Res && "Error string set with 0 result code!");
  177. getDriver().Diag(diag::err_drv_command_failure) << Error;
  178. }
  179. if (Res)
  180. FailingCommand = &C;
  181. return ExecutionFailed ? 1 : Res;
  182. }
  183. using FailingCommandList = SmallVectorImpl<std::pair<int, const Command *>>;
  184. static bool ActionFailed(const Action *A,
  185. const FailingCommandList &FailingCommands) {
  186. if (FailingCommands.empty())
  187. return false;
  188. // CUDA/HIP can have the same input source code compiled multiple times so do
  189. // not compiled again if there are already failures. It is OK to abort the
  190. // CUDA pipeline on errors.
  191. if (A->isOffloading(Action::OFK_Cuda) || A->isOffloading(Action::OFK_HIP))
  192. return true;
  193. for (const auto &CI : FailingCommands)
  194. if (A == &(CI.second->getSource()))
  195. return true;
  196. for (const auto *AI : A->inputs())
  197. if (ActionFailed(AI, FailingCommands))
  198. return true;
  199. return false;
  200. }
  201. static bool InputsOk(const Command &C,
  202. const FailingCommandList &FailingCommands) {
  203. return !ActionFailed(&C.getSource(), FailingCommands);
  204. }
  205. void Compilation::ExecuteJobs(const JobList &Jobs,
  206. FailingCommandList &FailingCommands) const {
  207. // According to UNIX standard, driver need to continue compiling all the
  208. // inputs on the command line even one of them failed.
  209. // In all but CLMode, execute all the jobs unless the necessary inputs for the
  210. // job is missing due to previous failures.
  211. for (const auto &Job : Jobs) {
  212. if (!InputsOk(Job, FailingCommands))
  213. continue;
  214. const Command *FailingCommand = nullptr;
  215. if (int Res = ExecuteCommand(Job, FailingCommand)) {
  216. FailingCommands.push_back(std::make_pair(Res, FailingCommand));
  217. // Bail as soon as one command fails in cl driver mode.
  218. if (TheDriver.IsCLMode())
  219. return;
  220. }
  221. }
  222. }
  223. void Compilation::initCompilationForDiagnostics() {
  224. ForDiagnostics = true;
  225. // Free actions and jobs.
  226. Actions.clear();
  227. AllActions.clear();
  228. Jobs.clear();
  229. // Remove temporary files.
  230. if (!TheDriver.isSaveTempsEnabled() && !ForceKeepTempFiles)
  231. CleanupFileList(TempFiles);
  232. // Clear temporary/results file lists.
  233. TempFiles.clear();
  234. ResultFiles.clear();
  235. FailureResultFiles.clear();
  236. // Remove any user specified output. Claim any unclaimed arguments, so as
  237. // to avoid emitting warnings about unused args.
  238. OptSpecifier OutputOpts[] = {
  239. options::OPT_o, options::OPT_MD, options::OPT_MMD, options::OPT_M,
  240. options::OPT_MM, options::OPT_MF, options::OPT_MG, options::OPT_MJ,
  241. options::OPT_MQ, options::OPT_MT, options::OPT_MV};
  242. for (unsigned i = 0, e = llvm::array_lengthof(OutputOpts); i != e; ++i) {
  243. if (TranslatedArgs->hasArg(OutputOpts[i]))
  244. TranslatedArgs->eraseArg(OutputOpts[i]);
  245. }
  246. TranslatedArgs->ClaimAllArgs();
  247. // Force re-creation of the toolchain Args, otherwise our modifications just
  248. // above will have no effect.
  249. for (auto Arg : TCArgs)
  250. if (Arg.second != TranslatedArgs)
  251. delete Arg.second;
  252. TCArgs.clear();
  253. // Redirect stdout/stderr to /dev/null.
  254. Redirects = {None, {""}, {""}};
  255. // Temporary files added by diagnostics should be kept.
  256. ForceKeepTempFiles = true;
  257. }
  258. StringRef Compilation::getSysRoot() const {
  259. return getDriver().SysRoot;
  260. }
  261. void Compilation::Redirect(ArrayRef<Optional<StringRef>> Redirects) {
  262. this->Redirects = Redirects;
  263. }