int Driver::ExecuteCompilation(const Compilation &C) const { // Just print if -### was present. if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) { C.PrintJob(llvm::errs(), C.getJobs(), "\n", true); return 0; } // If there were errors building the compilation, quit now. if (getDiags().getNumErrors()) return 1; const Command *FailingCommand = 0; int Res = C.ExecuteJob(C.getJobs(), FailingCommand); // Remove temp files. C.CleanupFileList(C.getTempFiles()); // If the compilation failed, remove result files as well. if (Res != 0 && !C.getArgs().hasArg(options::OPT_save_temps)) C.CleanupFileList(C.getResultFiles(), true); // Print extra information about abnormal failures, if possible. if (Res) { // This is ad-hoc, but we don't want to be excessively noisy. If the result // status was 1, assume the command failed normally. In particular, if it // was the compiler then assume it gave a reasonable error code. Failures in // other tools are less common, and they generally have worse diagnostics, // so always print the diagnostic there. const Action &Source = FailingCommand->getSource(); bool IsFriendlyTool = (isa<PreprocessJobAction>(Source) || isa<PrecompileJobAction>(Source) || isa<AnalyzeJobAction>(Source) || isa<CompileJobAction>(Source)); if (!IsFriendlyTool || Res != 1) { // FIXME: See FIXME above regarding result code interpretation. if (Res < 0) Diag(clang::diag::err_drv_command_signalled) << Source.getClassName() << -Res; else Diag(clang::diag::err_drv_command_failed) << Source.getClassName() << Res; } } return Res; }
void Driver::BuildJobsForAction(Compilation &C, const Action *A, const ToolChain *TC, bool CanAcceptPipe, bool AtTopLevel, const char *LinkingOutput, InputInfo &Result) const { llvm::PrettyStackTraceString CrashInfo("Building compilation jobs for action"); bool UsePipes = C.getArgs().hasArg(options::OPT_pipe); // FIXME: Pipes are forcibly disabled until we support executing // them. if (!CCCPrintBindings) UsePipes = false; if (const InputAction *IA = dyn_cast<InputAction>(A)) { // FIXME: It would be nice to not claim this here; maybe the old // scheme of just using Args was better? const Arg &Input = IA->getInputArg(); Input.claim(); if (isa<PositionalArg>(Input)) { const char *Name = Input.getValue(C.getArgs()); Result = InputInfo(Name, A->getType(), Name); } else Result = InputInfo(&Input, A->getType(), ""); return; } if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) { const char *ArchName = BAA->getArchName(); std::string Arch; if (!ArchName) { Arch = C.getDefaultToolChain().getArchName(); ArchName = Arch.c_str(); } BuildJobsForAction(C, *BAA->begin(), Host->getToolChain(C.getArgs(), ArchName), CanAcceptPipe, AtTopLevel, LinkingOutput, Result); return; } const JobAction *JA = cast<JobAction>(A); const Tool &T = TC->SelectTool(C, *JA); // See if we should use an integrated preprocessor. We do so when we // have exactly one input, since this is the only use case we care // about (irrelevant since we don't support combine yet). bool UseIntegratedCPP = false; const ActionList *Inputs = &A->getInputs(); if (Inputs->size() == 1 && isa<PreprocessJobAction>(*Inputs->begin())) { if (!C.getArgs().hasArg(options::OPT_no_integrated_cpp) && !C.getArgs().hasArg(options::OPT_traditional_cpp) && !C.getArgs().hasArg(options::OPT_save_temps) && T.hasIntegratedCPP()) { UseIntegratedCPP = true; Inputs = &(*Inputs)[0]->getInputs(); } } // Only use pipes when there is exactly one input. bool TryToUsePipeInput = Inputs->size() == 1 && T.acceptsPipedInput(); InputInfoList InputInfos; for (ActionList::const_iterator it = Inputs->begin(), ie = Inputs->end(); it != ie; ++it) { InputInfo II; BuildJobsForAction(C, *it, TC, TryToUsePipeInput, /*AtTopLevel*/false, LinkingOutput, II); InputInfos.push_back(II); } // Determine if we should output to a pipe. bool OutputToPipe = false; if (CanAcceptPipe && T.canPipeOutput()) { // Some actions default to writing to a pipe if they are the top // level phase and there was no user override. // // FIXME: Is there a better way to handle this? if (AtTopLevel) { if (isa<PreprocessJobAction>(A) && !C.getArgs().hasArg(options::OPT_o)) OutputToPipe = true; } else if (UsePipes) OutputToPipe = true; } // Figure out where to put the job (pipes). Job *Dest = &C.getJobs(); if (InputInfos[0].isPipe()) { assert(TryToUsePipeInput && "Unrequested pipe!"); assert(InputInfos.size() == 1 && "Unexpected pipe with multiple inputs."); Dest = &InputInfos[0].getPipe(); } // Always use the first input as the base input. const char *BaseInput = InputInfos[0].getBaseInput(); // Determine the place to write output to (nothing, pipe, or // filename) and where to put the new job. if (JA->getType() == types::TY_Nothing) { Result = InputInfo(A->getType(), BaseInput); } else if (OutputToPipe) { // Append to current piped job or create a new one as appropriate. PipedJob *PJ = dyn_cast<PipedJob>(Dest); if (!PJ) { PJ = new PipedJob(); // FIXME: Temporary hack so that -ccc-print-bindings work until // we have pipe support. Please remove later. if (!CCCPrintBindings) cast<JobList>(Dest)->addJob(PJ); Dest = PJ; } Result = InputInfo(PJ, A->getType(), BaseInput); } else { Result = InputInfo(GetNamedOutputPath(C, *JA, BaseInput, AtTopLevel), A->getType(), BaseInput); } if (CCCPrintBindings) { llvm::errs() << "# \"" << T.getToolChain().getTripleString() << '"' << " - \"" << T.getName() << "\", inputs: ["; for (unsigned i = 0, e = InputInfos.size(); i != e; ++i) { llvm::errs() << InputInfos[i].getAsString(); if (i + 1 != e) llvm::errs() << ", "; } llvm::errs() << "], output: " << Result.getAsString() << "\n"; } else { T.ConstructJob(C, *JA, *Dest, Result, InputInfos, C.getArgsForToolChain(TC), LinkingOutput); } }