1*67e74705SXin Li //===--- Compilation.cpp - Compilation Task Implementation ----------------===//
2*67e74705SXin Li //
3*67e74705SXin Li // The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li
10*67e74705SXin Li #include "clang/Driver/Compilation.h"
11*67e74705SXin Li #include "clang/Driver/Action.h"
12*67e74705SXin Li #include "clang/Driver/Driver.h"
13*67e74705SXin Li #include "clang/Driver/DriverDiagnostic.h"
14*67e74705SXin Li #include "clang/Driver/Options.h"
15*67e74705SXin Li #include "clang/Driver/ToolChain.h"
16*67e74705SXin Li #include "llvm/ADT/STLExtras.h"
17*67e74705SXin Li #include "llvm/Option/ArgList.h"
18*67e74705SXin Li #include "llvm/Support/FileSystem.h"
19*67e74705SXin Li #include "llvm/Support/raw_ostream.h"
20*67e74705SXin Li
21*67e74705SXin Li using namespace clang::driver;
22*67e74705SXin Li using namespace clang;
23*67e74705SXin Li using namespace llvm::opt;
24*67e74705SXin Li
Compilation(const Driver & D,const ToolChain & _DefaultToolChain,InputArgList * _Args,DerivedArgList * _TranslatedArgs)25*67e74705SXin Li Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
26*67e74705SXin Li InputArgList *_Args, DerivedArgList *_TranslatedArgs)
27*67e74705SXin Li : TheDriver(D), DefaultToolChain(_DefaultToolChain), ActiveOffloadMask(0u),
28*67e74705SXin Li Args(_Args), TranslatedArgs(_TranslatedArgs), Redirects(nullptr),
29*67e74705SXin Li ForDiagnostics(false) {
30*67e74705SXin Li // The offloading host toolchain is the default tool chain.
31*67e74705SXin Li OrderedOffloadingToolchains.insert(
32*67e74705SXin Li std::make_pair(Action::OFK_Host, &DefaultToolChain));
33*67e74705SXin Li }
34*67e74705SXin Li
~Compilation()35*67e74705SXin Li Compilation::~Compilation() {
36*67e74705SXin Li delete TranslatedArgs;
37*67e74705SXin Li delete Args;
38*67e74705SXin Li
39*67e74705SXin Li // Free any derived arg lists.
40*67e74705SXin Li for (llvm::DenseMap<std::pair<const ToolChain*, const char*>,
41*67e74705SXin Li DerivedArgList*>::iterator it = TCArgs.begin(),
42*67e74705SXin Li ie = TCArgs.end(); it != ie; ++it)
43*67e74705SXin Li if (it->second != TranslatedArgs)
44*67e74705SXin Li delete it->second;
45*67e74705SXin Li
46*67e74705SXin Li // Free redirections of stdout/stderr.
47*67e74705SXin Li if (Redirects) {
48*67e74705SXin Li delete Redirects[0];
49*67e74705SXin Li delete Redirects[1];
50*67e74705SXin Li delete Redirects[2];
51*67e74705SXin Li delete [] Redirects;
52*67e74705SXin Li }
53*67e74705SXin Li }
54*67e74705SXin Li
getArgsForToolChain(const ToolChain * TC,const char * BoundArch)55*67e74705SXin Li const DerivedArgList &Compilation::getArgsForToolChain(const ToolChain *TC,
56*67e74705SXin Li const char *BoundArch) {
57*67e74705SXin Li if (!TC)
58*67e74705SXin Li TC = &DefaultToolChain;
59*67e74705SXin Li
60*67e74705SXin Li DerivedArgList *&Entry = TCArgs[std::make_pair(TC, BoundArch)];
61*67e74705SXin Li if (!Entry) {
62*67e74705SXin Li Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch);
63*67e74705SXin Li if (!Entry)
64*67e74705SXin Li Entry = TranslatedArgs;
65*67e74705SXin Li }
66*67e74705SXin Li
67*67e74705SXin Li return *Entry;
68*67e74705SXin Li }
69*67e74705SXin Li
CleanupFile(const char * File,bool IssueErrors) const70*67e74705SXin Li bool Compilation::CleanupFile(const char *File, bool IssueErrors) const {
71*67e74705SXin Li // FIXME: Why are we trying to remove files that we have not created? For
72*67e74705SXin Li // example we should only try to remove a temporary assembly file if
73*67e74705SXin Li // "clang -cc1" succeed in writing it. Was this a workaround for when
74*67e74705SXin Li // clang was writing directly to a .s file and sometimes leaving it behind
75*67e74705SXin Li // during a failure?
76*67e74705SXin Li
77*67e74705SXin Li // FIXME: If this is necessary, we can still try to split
78*67e74705SXin Li // llvm::sys::fs::remove into a removeFile and a removeDir and avoid the
79*67e74705SXin Li // duplicated stat from is_regular_file.
80*67e74705SXin Li
81*67e74705SXin Li // Don't try to remove files which we don't have write access to (but may be
82*67e74705SXin Li // able to remove), or non-regular files. Underlying tools may have
83*67e74705SXin Li // intentionally not overwritten them.
84*67e74705SXin Li if (!llvm::sys::fs::can_write(File) || !llvm::sys::fs::is_regular_file(File))
85*67e74705SXin Li return true;
86*67e74705SXin Li
87*67e74705SXin Li if (std::error_code EC = llvm::sys::fs::remove(File)) {
88*67e74705SXin Li // Failure is only failure if the file exists and is "regular". We checked
89*67e74705SXin Li // for it being regular before, and llvm::sys::fs::remove ignores ENOENT,
90*67e74705SXin Li // so we don't need to check again.
91*67e74705SXin Li
92*67e74705SXin Li if (IssueErrors)
93*67e74705SXin Li getDriver().Diag(clang::diag::err_drv_unable_to_remove_file)
94*67e74705SXin Li << EC.message();
95*67e74705SXin Li return false;
96*67e74705SXin Li }
97*67e74705SXin Li return true;
98*67e74705SXin Li }
99*67e74705SXin Li
CleanupFileList(const ArgStringList & Files,bool IssueErrors) const100*67e74705SXin Li bool Compilation::CleanupFileList(const ArgStringList &Files,
101*67e74705SXin Li bool IssueErrors) const {
102*67e74705SXin Li bool Success = true;
103*67e74705SXin Li for (ArgStringList::const_iterator
104*67e74705SXin Li it = Files.begin(), ie = Files.end(); it != ie; ++it)
105*67e74705SXin Li Success &= CleanupFile(*it, IssueErrors);
106*67e74705SXin Li return Success;
107*67e74705SXin Li }
108*67e74705SXin Li
CleanupFileMap(const ArgStringMap & Files,const JobAction * JA,bool IssueErrors) const109*67e74705SXin Li bool Compilation::CleanupFileMap(const ArgStringMap &Files,
110*67e74705SXin Li const JobAction *JA,
111*67e74705SXin Li bool IssueErrors) const {
112*67e74705SXin Li bool Success = true;
113*67e74705SXin Li for (ArgStringMap::const_iterator
114*67e74705SXin Li it = Files.begin(), ie = Files.end(); it != ie; ++it) {
115*67e74705SXin Li
116*67e74705SXin Li // If specified, only delete the files associated with the JobAction.
117*67e74705SXin Li // Otherwise, delete all files in the map.
118*67e74705SXin Li if (JA && it->first != JA)
119*67e74705SXin Li continue;
120*67e74705SXin Li Success &= CleanupFile(it->second, IssueErrors);
121*67e74705SXin Li }
122*67e74705SXin Li return Success;
123*67e74705SXin Li }
124*67e74705SXin Li
ExecuteCommand(const Command & C,const Command * & FailingCommand) const125*67e74705SXin Li int Compilation::ExecuteCommand(const Command &C,
126*67e74705SXin Li const Command *&FailingCommand) const {
127*67e74705SXin Li if ((getDriver().CCPrintOptions ||
128*67e74705SXin Li getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) {
129*67e74705SXin Li raw_ostream *OS = &llvm::errs();
130*67e74705SXin Li
131*67e74705SXin Li // Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the
132*67e74705SXin Li // output stream.
133*67e74705SXin Li if (getDriver().CCPrintOptions && getDriver().CCPrintOptionsFilename) {
134*67e74705SXin Li std::error_code EC;
135*67e74705SXin Li OS = new llvm::raw_fd_ostream(getDriver().CCPrintOptionsFilename, EC,
136*67e74705SXin Li llvm::sys::fs::F_Append |
137*67e74705SXin Li llvm::sys::fs::F_Text);
138*67e74705SXin Li if (EC) {
139*67e74705SXin Li getDriver().Diag(clang::diag::err_drv_cc_print_options_failure)
140*67e74705SXin Li << EC.message();
141*67e74705SXin Li FailingCommand = &C;
142*67e74705SXin Li delete OS;
143*67e74705SXin Li return 1;
144*67e74705SXin Li }
145*67e74705SXin Li }
146*67e74705SXin Li
147*67e74705SXin Li if (getDriver().CCPrintOptions)
148*67e74705SXin Li *OS << "[Logging clang options]";
149*67e74705SXin Li
150*67e74705SXin Li C.Print(*OS, "\n", /*Quote=*/getDriver().CCPrintOptions);
151*67e74705SXin Li
152*67e74705SXin Li if (OS != &llvm::errs())
153*67e74705SXin Li delete OS;
154*67e74705SXin Li }
155*67e74705SXin Li
156*67e74705SXin Li std::string Error;
157*67e74705SXin Li bool ExecutionFailed;
158*67e74705SXin Li int Res = C.Execute(Redirects, &Error, &ExecutionFailed);
159*67e74705SXin Li if (!Error.empty()) {
160*67e74705SXin Li assert(Res && "Error string set with 0 result code!");
161*67e74705SXin Li getDriver().Diag(clang::diag::err_drv_command_failure) << Error;
162*67e74705SXin Li }
163*67e74705SXin Li
164*67e74705SXin Li if (Res)
165*67e74705SXin Li FailingCommand = &C;
166*67e74705SXin Li
167*67e74705SXin Li return ExecutionFailed ? 1 : Res;
168*67e74705SXin Li }
169*67e74705SXin Li
ExecuteJobs(const JobList & Jobs,SmallVectorImpl<std::pair<int,const Command * >> & FailingCommands) const170*67e74705SXin Li void Compilation::ExecuteJobs(
171*67e74705SXin Li const JobList &Jobs,
172*67e74705SXin Li SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) const {
173*67e74705SXin Li for (const auto &Job : Jobs) {
174*67e74705SXin Li const Command *FailingCommand = nullptr;
175*67e74705SXin Li if (int Res = ExecuteCommand(Job, FailingCommand)) {
176*67e74705SXin Li FailingCommands.push_back(std::make_pair(Res, FailingCommand));
177*67e74705SXin Li // Bail as soon as one command fails, so we don't output duplicate error
178*67e74705SXin Li // messages if we die on e.g. the same file.
179*67e74705SXin Li return;
180*67e74705SXin Li }
181*67e74705SXin Li }
182*67e74705SXin Li }
183*67e74705SXin Li
initCompilationForDiagnostics()184*67e74705SXin Li void Compilation::initCompilationForDiagnostics() {
185*67e74705SXin Li ForDiagnostics = true;
186*67e74705SXin Li
187*67e74705SXin Li // Free actions and jobs.
188*67e74705SXin Li Actions.clear();
189*67e74705SXin Li AllActions.clear();
190*67e74705SXin Li Jobs.clear();
191*67e74705SXin Li
192*67e74705SXin Li // Clear temporary/results file lists.
193*67e74705SXin Li TempFiles.clear();
194*67e74705SXin Li ResultFiles.clear();
195*67e74705SXin Li FailureResultFiles.clear();
196*67e74705SXin Li
197*67e74705SXin Li // Remove any user specified output. Claim any unclaimed arguments, so as
198*67e74705SXin Li // to avoid emitting warnings about unused args.
199*67e74705SXin Li OptSpecifier OutputOpts[] = { options::OPT_o, options::OPT_MD,
200*67e74705SXin Li options::OPT_MMD };
201*67e74705SXin Li for (unsigned i = 0, e = llvm::array_lengthof(OutputOpts); i != e; ++i) {
202*67e74705SXin Li if (TranslatedArgs->hasArg(OutputOpts[i]))
203*67e74705SXin Li TranslatedArgs->eraseArg(OutputOpts[i]);
204*67e74705SXin Li }
205*67e74705SXin Li TranslatedArgs->ClaimAllArgs();
206*67e74705SXin Li
207*67e74705SXin Li // Redirect stdout/stderr to /dev/null.
208*67e74705SXin Li Redirects = new const StringRef*[3]();
209*67e74705SXin Li Redirects[0] = nullptr;
210*67e74705SXin Li Redirects[1] = new StringRef();
211*67e74705SXin Li Redirects[2] = new StringRef();
212*67e74705SXin Li }
213*67e74705SXin Li
getSysRoot() const214*67e74705SXin Li StringRef Compilation::getSysRoot() const {
215*67e74705SXin Li return getDriver().SysRoot;
216*67e74705SXin Li }
217*67e74705SXin Li
Redirect(const StringRef ** Redirects)218*67e74705SXin Li void Compilation::Redirect(const StringRef** Redirects) {
219*67e74705SXin Li this->Redirects = Redirects;
220*67e74705SXin Li }
221