Compilation.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  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. if (!OpenMPArgs) {
  71. Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch, DeviceOffloadKind);
  72. if (!Entry)
  73. Entry = TranslatedArgs;
  74. } else {
  75. Entry = TC->TranslateArgs(*OpenMPArgs, BoundArch, DeviceOffloadKind);
  76. if (!Entry)
  77. Entry = OpenMPArgs;
  78. else
  79. delete OpenMPArgs;
  80. }
  81. // Add allocated arguments to the final DAL.
  82. for (auto ArgPtr : AllocatedArgs)
  83. Entry->AddSynthesizedArg(ArgPtr);
  84. }
  85. return *Entry;
  86. }
  87. bool Compilation::CleanupFile(const char *File, bool IssueErrors) const {
  88. // FIXME: Why are we trying to remove files that we have not created? For
  89. // example we should only try to remove a temporary assembly file if
  90. // "clang -cc1" succeed in writing it. Was this a workaround for when
  91. // clang was writing directly to a .s file and sometimes leaving it behind
  92. // during a failure?
  93. // FIXME: If this is necessary, we can still try to split
  94. // llvm::sys::fs::remove into a removeFile and a removeDir and avoid the
  95. // duplicated stat from is_regular_file.
  96. // Don't try to remove files which we don't have write access to (but may be
  97. // able to remove), or non-regular files. Underlying tools may have
  98. // intentionally not overwritten them.
  99. if (!llvm::sys::fs::can_write(File) || !llvm::sys::fs::is_regular_file(File))
  100. return true;
  101. if (std::error_code EC = llvm::sys::fs::remove(File)) {
  102. // Failure is only failure if the file exists and is "regular". We checked
  103. // for it being regular before, and llvm::sys::fs::remove ignores ENOENT,
  104. // so we don't need to check again.
  105. if (IssueErrors)
  106. getDriver().Diag(diag::err_drv_unable_to_remove_file)
  107. << EC.message();
  108. return false;
  109. }
  110. return true;
  111. }
  112. bool Compilation::CleanupFileList(const llvm::opt::ArgStringList &Files,
  113. bool IssueErrors) const {
  114. bool Success = true;
  115. for (const auto &File: Files)
  116. Success &= CleanupFile(File, IssueErrors);
  117. return Success;
  118. }
  119. bool Compilation::CleanupFileMap(const ArgStringMap &Files,
  120. const JobAction *JA,
  121. bool IssueErrors) const {
  122. bool Success = true;
  123. for (const auto &File : Files) {
  124. // If specified, only delete the files associated with the JobAction.
  125. // Otherwise, delete all files in the map.
  126. if (JA && File.first != JA)
  127. continue;
  128. Success &= CleanupFile(File.second, IssueErrors);
  129. }
  130. return Success;
  131. }
  132. int Compilation::ExecuteCommand(const Command &C,
  133. const Command *&FailingCommand) const {
  134. if ((getDriver().CCPrintOptions ||
  135. getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) {
  136. raw_ostream *OS = &llvm::errs();
  137. std::unique_ptr<llvm::raw_fd_ostream> OwnedStream;
  138. // Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the
  139. // output stream.
  140. if (getDriver().CCPrintOptions && getDriver().CCPrintOptionsFilename) {
  141. std::error_code EC;
  142. OwnedStream.reset(new llvm::raw_fd_ostream(
  143. getDriver().CCPrintOptionsFilename, EC,
  144. llvm::sys::fs::F_Append | llvm::sys::fs::F_Text));
  145. if (EC) {
  146. getDriver().Diag(diag::err_drv_cc_print_options_failure)
  147. << EC.message();
  148. FailingCommand = &C;
  149. return 1;
  150. }
  151. OS = OwnedStream.get();
  152. }
  153. if (getDriver().CCPrintOptions)
  154. *OS << "[Logging clang options]";
  155. C.Print(*OS, "\n", /*Quote=*/getDriver().CCPrintOptions);
  156. }
  157. std::string Error;
  158. bool ExecutionFailed;
  159. int Res = C.Execute(Redirects, &Error, &ExecutionFailed);
  160. if (!Error.empty()) {
  161. assert(Res && "Error string set with 0 result code!");
  162. getDriver().Diag(diag::err_drv_command_failure) << Error;
  163. }
  164. if (Res)
  165. FailingCommand = &C;
  166. return ExecutionFailed ? 1 : Res;
  167. }
  168. using FailingCommandList = SmallVectorImpl<std::pair<int, const Command *>>;
  169. static bool ActionFailed(const Action *A,
  170. const FailingCommandList &FailingCommands) {
  171. if (FailingCommands.empty())
  172. return false;
  173. // CUDA/HIP can have the same input source code compiled multiple times so do
  174. // not compiled again if there are already failures. It is OK to abort the
  175. // CUDA pipeline on errors.
  176. if (A->isOffloading(Action::OFK_Cuda) || A->isOffloading(Action::OFK_HIP))
  177. return true;
  178. for (const auto &CI : FailingCommands)
  179. if (A == &(CI.second->getSource()))
  180. return true;
  181. for (const auto *AI : A->inputs())
  182. if (ActionFailed(AI, FailingCommands))
  183. return true;
  184. return false;
  185. }
  186. static bool InputsOk(const Command &C,
  187. const FailingCommandList &FailingCommands) {
  188. return !ActionFailed(&C.getSource(), FailingCommands);
  189. }
  190. void Compilation::ExecuteJobs(const JobList &Jobs,
  191. FailingCommandList &FailingCommands) const {
  192. // According to UNIX standard, driver need to continue compiling all the
  193. // inputs on the command line even one of them failed.
  194. // In all but CLMode, execute all the jobs unless the necessary inputs for the
  195. // job is missing due to previous failures.
  196. for (const auto &Job : Jobs) {
  197. if (!InputsOk(Job, FailingCommands))
  198. continue;
  199. const Command *FailingCommand = nullptr;
  200. if (int Res = ExecuteCommand(Job, FailingCommand)) {
  201. FailingCommands.push_back(std::make_pair(Res, FailingCommand));
  202. // Bail as soon as one command fails in cl driver mode.
  203. if (TheDriver.IsCLMode())
  204. return;
  205. }
  206. }
  207. }
  208. void Compilation::initCompilationForDiagnostics() {
  209. ForDiagnostics = true;
  210. // Free actions and jobs.
  211. Actions.clear();
  212. AllActions.clear();
  213. Jobs.clear();
  214. // Remove temporary files.
  215. if (!TheDriver.isSaveTempsEnabled() && !ForceKeepTempFiles)
  216. CleanupFileList(TempFiles);
  217. // Clear temporary/results file lists.
  218. TempFiles.clear();
  219. ResultFiles.clear();
  220. FailureResultFiles.clear();
  221. // Remove any user specified output. Claim any unclaimed arguments, so as
  222. // to avoid emitting warnings about unused args.
  223. OptSpecifier OutputOpts[] = { options::OPT_o, options::OPT_MD,
  224. options::OPT_MMD };
  225. for (unsigned i = 0, e = llvm::array_lengthof(OutputOpts); i != e; ++i) {
  226. if (TranslatedArgs->hasArg(OutputOpts[i]))
  227. TranslatedArgs->eraseArg(OutputOpts[i]);
  228. }
  229. TranslatedArgs->ClaimAllArgs();
  230. // Redirect stdout/stderr to /dev/null.
  231. Redirects = {None, {""}, {""}};
  232. // Temporary files added by diagnostics should be kept.
  233. ForceKeepTempFiles = true;
  234. }
  235. StringRef Compilation::getSysRoot() const {
  236. return getDriver().SysRoot;
  237. }
  238. void Compilation::Redirect(ArrayRef<Optional<StringRef>> Redirects) {
  239. this->Redirects = Redirects;
  240. }