clang  6.0.0svn
Compilation.cpp
Go to the documentation of this file.
1 //===--- Compilation.cpp - Compilation Task Implementation ----------------===//
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 
11 #include "clang/Driver/Action.h"
12 #include "clang/Driver/Driver.h"
14 #include "clang/Driver/Options.h"
15 #include "clang/Driver/ToolChain.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/Option/ArgList.h"
18 #include "llvm/Support/FileSystem.h"
19 #include "llvm/Support/raw_ostream.h"
20 
21 using namespace clang::driver;
22 using namespace clang;
23 using namespace llvm::opt;
24 
25 Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
26  InputArgList *_Args, DerivedArgList *_TranslatedArgs,
27  bool ContainsError)
28  : TheDriver(D), DefaultToolChain(_DefaultToolChain), ActiveOffloadMask(0u),
29  Args(_Args), TranslatedArgs(_TranslatedArgs), ForDiagnostics(false),
30  ContainsError(ContainsError) {
31  // The offloading host toolchain is the default toolchain.
32  OrderedOffloadingToolchains.insert(
33  std::make_pair(Action::OFK_Host, &DefaultToolChain));
34 }
35 
37  delete TranslatedArgs;
38  delete Args;
39 
40  // Free any derived arg lists.
41  for (auto Arg : TCArgs)
42  if (Arg.second != TranslatedArgs)
43  delete Arg.second;
44 }
45 
46 const DerivedArgList &
47 Compilation::getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
48  Action::OffloadKind DeviceOffloadKind) {
49  if (!TC)
50  TC = &DefaultToolChain;
51 
52  DerivedArgList *&Entry = TCArgs[{TC, BoundArch, DeviceOffloadKind}];
53  if (!Entry) {
54  SmallVector<Arg *, 4> AllocatedArgs;
55  DerivedArgList *OpenMPArgs = nullptr;
56  // Translate OpenMP toolchain arguments provided via the -Xopenmp-target flags.
57  if (DeviceOffloadKind == Action::OFK_OpenMP) {
58  const ToolChain *HostTC = getSingleOffloadToolChain<Action::OFK_Host>();
59  bool SameTripleAsHost = (TC->getTriple() == HostTC->getTriple());
60  OpenMPArgs = TC->TranslateOpenMPTargetArgs(
61  *TranslatedArgs, SameTripleAsHost, AllocatedArgs);
62  }
63 
64  if (!OpenMPArgs) {
65  Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch, DeviceOffloadKind);
66  if (!Entry)
67  Entry = TranslatedArgs;
68  } else {
69  Entry = TC->TranslateArgs(*OpenMPArgs, BoundArch, DeviceOffloadKind);
70  if (!Entry)
71  Entry = OpenMPArgs;
72  else
73  delete OpenMPArgs;
74  }
75 
76  // Add allocated arguments to the final DAL.
77  for (auto ArgPtr : AllocatedArgs) {
78  Entry->AddSynthesizedArg(ArgPtr);
79  }
80  }
81 
82  return *Entry;
83 }
84 
85 bool Compilation::CleanupFile(const char *File, bool IssueErrors) const {
86  // FIXME: Why are we trying to remove files that we have not created? For
87  // example we should only try to remove a temporary assembly file if
88  // "clang -cc1" succeed in writing it. Was this a workaround for when
89  // clang was writing directly to a .s file and sometimes leaving it behind
90  // during a failure?
91 
92  // FIXME: If this is necessary, we can still try to split
93  // llvm::sys::fs::remove into a removeFile and a removeDir and avoid the
94  // duplicated stat from is_regular_file.
95 
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 
102  if (std::error_code EC = llvm::sys::fs::remove(File)) {
103  // Failure is only failure if the file exists and is "regular". We checked
104  // for it being regular before, and llvm::sys::fs::remove ignores ENOENT,
105  // so we don't need to check again.
106 
107  if (IssueErrors)
108  getDriver().Diag(clang::diag::err_drv_unable_to_remove_file)
109  << EC.message();
110  return false;
111  }
112  return true;
113 }
114 
115 bool Compilation::CleanupFileList(const ArgStringList &Files,
116  bool IssueErrors) const {
117  bool Success = true;
118  for (ArgStringList::const_iterator
119  it = Files.begin(), ie = Files.end(); it != ie; ++it)
120  Success &= CleanupFile(*it, IssueErrors);
121  return Success;
122 }
123 
125  const JobAction *JA,
126  bool IssueErrors) const {
127  bool Success = true;
128  for (ArgStringMap::const_iterator
129  it = Files.begin(), ie = Files.end(); it != ie; ++it) {
130 
131  // If specified, only delete the files associated with the JobAction.
132  // Otherwise, delete all files in the map.
133  if (JA && it->first != JA)
134  continue;
135  Success &= CleanupFile(it->second, IssueErrors);
136  }
137  return Success;
138 }
139 
141  const Command *&FailingCommand) const {
142  if ((getDriver().CCPrintOptions ||
143  getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) {
144  raw_ostream *OS = &llvm::errs();
145 
146  // Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the
147  // output stream.
148  if (getDriver().CCPrintOptions && getDriver().CCPrintOptionsFilename) {
149  std::error_code EC;
150  OS = new llvm::raw_fd_ostream(getDriver().CCPrintOptionsFilename, EC,
151  llvm::sys::fs::F_Append |
152  llvm::sys::fs::F_Text);
153  if (EC) {
154  getDriver().Diag(clang::diag::err_drv_cc_print_options_failure)
155  << EC.message();
156  FailingCommand = &C;
157  delete OS;
158  return 1;
159  }
160  }
161 
162  if (getDriver().CCPrintOptions)
163  *OS << "[Logging clang options]";
164 
165  C.Print(*OS, "\n", /*Quote=*/getDriver().CCPrintOptions);
166 
167  if (OS != &llvm::errs())
168  delete OS;
169  }
170 
171  std::string Error;
172  bool ExecutionFailed;
173  int Res = C.Execute(Redirects, &Error, &ExecutionFailed);
174  if (!Error.empty()) {
175  assert(Res && "Error string set with 0 result code!");
176  getDriver().Diag(clang::diag::err_drv_command_failure) << Error;
177  }
178 
179  if (Res)
180  FailingCommand = &C;
181 
182  return ExecutionFailed ? 1 : Res;
183 }
184 
185 using FailingCommandList = SmallVectorImpl<std::pair<int, const Command *>>;
186 
187 static bool ActionFailed(const Action *A,
188  const FailingCommandList &FailingCommands) {
189 
190  if (FailingCommands.empty())
191  return false;
192 
193  // CUDA can have the same input source code compiled multiple times so do not
194  // compiled again if there are already failures. It is OK to abort the CUDA
195  // pipeline on errors.
197  return true;
198 
199  for (const auto &CI : FailingCommands)
200  if (A == &(CI.second->getSource()))
201  return true;
202 
203  for (const Action *AI : A->inputs())
204  if (ActionFailed(AI, FailingCommands))
205  return true;
206 
207  return false;
208 }
209 
210 static bool InputsOk(const Command &C,
211  const FailingCommandList &FailingCommands) {
212  return !ActionFailed(&C.getSource(), FailingCommands);
213 }
214 
216  FailingCommandList &FailingCommands) const {
217  // According to UNIX standard, driver need to continue compiling all the
218  // inputs on the command line even one of them failed.
219  // In all but CLMode, execute all the jobs unless the necessary inputs for the
220  // job is missing due to previous failures.
221  for (const auto &Job : Jobs) {
222  if (!InputsOk(Job, FailingCommands))
223  continue;
224  const Command *FailingCommand = nullptr;
225  if (int Res = ExecuteCommand(Job, FailingCommand)) {
226  FailingCommands.push_back(std::make_pair(Res, FailingCommand));
227  // Bail as soon as one command fails in cl driver mode.
228  if (TheDriver.IsCLMode())
229  return;
230  }
231  }
232 }
233 
235  ForDiagnostics = true;
236 
237  // Free actions and jobs.
238  Actions.clear();
239  AllActions.clear();
240  Jobs.clear();
241 
242  // Clear temporary/results file lists.
243  TempFiles.clear();
244  ResultFiles.clear();
245  FailureResultFiles.clear();
246 
247  // Remove any user specified output. Claim any unclaimed arguments, so as
248  // to avoid emitting warnings about unused args.
249  OptSpecifier OutputOpts[] = { options::OPT_o, options::OPT_MD,
250  options::OPT_MMD };
251  for (unsigned i = 0, e = llvm::array_lengthof(OutputOpts); i != e; ++i) {
252  if (TranslatedArgs->hasArg(OutputOpts[i]))
253  TranslatedArgs->eraseArg(OutputOpts[i]);
254  }
255  TranslatedArgs->ClaimAllArgs();
256 
257  // Redirect stdout/stderr to /dev/null.
258  Redirects = {None, {""}, {""}};
259 }
260 
261 StringRef Compilation::getSysRoot() const {
262  return getDriver().SysRoot;
263 }
264 
266  this->Redirects = Redirects;
267 }
StringRef getSysRoot() const
Returns the sysroot path.
input_range inputs()
Definition: Action.h:141
DiagnosticBuilder Diag(unsigned DiagID) const
Definition: Driver.h:116
static bool InputsOk(const Command &C, const FailingCommandList &FailingCommands)
const llvm::opt::DerivedArgList & getArgsForToolChain(const ToolChain *TC, StringRef BoundArch, Action::OffloadKind DeviceOffloadKind)
getArgsForToolChain - Return the derived argument list for the tool chain TC (or the default tool cha...
Definition: Compilation.cpp:47
bool CleanupFileList(const llvm::opt::ArgStringList &Files, bool IssueErrors=false) const
CleanupFileList - Remove the files in the given list.
bool isOffloading(OffloadKind OKind) const
Definition: Action.h:193
Action - Represent an abstract compilation step to perform.
Definition: Action.h:45
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:65
virtual llvm::opt::DerivedArgList * TranslateOpenMPTargetArgs(const llvm::opt::DerivedArgList &Args, bool SameTripleAsHost, SmallVectorImpl< llvm::opt::Arg *> &AllocatedArgs) const
TranslateOpenMPTargetArgs - Create a new derived argument list for that contains the OpenMP target sp...
Definition: ToolChain.cpp:853
bool IsCLMode() const
Whether the driver should follow cl.exe like behavior.
Definition: Driver.h:183
JobList - A sequence of jobs to perform.
Definition: Job.h:166
llvm::DenseMap< const JobAction *, const char * > ArgStringMap
ArgStringMap - Type used to map a JobAction to its result file.
Definition: Util.h:21
bool CleanupFile(const char *File, bool IssueErrors=false) const
CleanupFile - Delete a given file.
Definition: Compilation.cpp:85
#define false
Definition: stdbool.h:33
void clear()
Clear the job list.
Definition: Job.cpp:430
const llvm::opt::DerivedArgList & getArgs() const
Definition: Compilation.h:170
void Redirect(ArrayRef< Optional< StringRef >> Redirects)
Redirect - Redirect output of this compilation.
Command - An executable path/name and argument vector to execute.
Definition: Job.h:44
int ExecuteCommand(const Command &C, const Command *&FailingCommand) const
ExecuteCommand - Execute an actual command.
Compilation(const Driver &D, const ToolChain &DefaultToolChain, llvm::opt::InputArgList *Args, llvm::opt::DerivedArgList *TranslatedArgs, bool ContainsError)
Definition: Compilation.cpp:25
void ExecuteJobs(const JobList &Jobs, SmallVectorImpl< std::pair< int, const Command *>> &FailingCommands) const
ExecuteJob - Execute a single job.
const Action & getSource() const
getSource - Return the Action which caused the creation of this job.
Definition: Job.h:104
Dataflow Directional Tag Classes.
static bool ActionFailed(const Action *A, const FailingCommandList &FailingCommands)
std::string SysRoot
sysroot, if present
Definition: Driver.h:149
const Driver & getDriver() const
Definition: Compilation.h:117
const llvm::Triple & getTriple() const
Definition: ToolChain.h:169
bool CleanupFileMap(const ArgStringMap &Files, const JobAction *JA, bool IssueErrors=false) const
CleanupFileMap - Remove the files in the given map.
SmallVectorImpl< std::pair< int, const Command * > > FailingCommandList
virtual llvm::opt::DerivedArgList * TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const
TranslateArgs - Create a new derived argument list for any argument translations this ToolChain may w...
Definition: ToolChain.h:248
void initCompilationForDiagnostics()
initCompilationForDiagnostics - Remove stale state and suppress output so compilation can be reexecut...
virtual void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, CrashReportInfo *CrashInfo=nullptr) const
Definition: Job.cpp:209
virtual int Execute(ArrayRef< Optional< StringRef >> Redirects, std::string *ErrMsg, bool *ExecutionFailed) const
Definition: Job.cpp:311
ToolChain - Access to tools for a single platform.
Definition: ToolChain.h:73