static unsigned PrintActions1(const Compilation &C, Action *A, std::map<Action*, unsigned> &Ids) { if (Ids.count(A)) return Ids[A]; std::string str; llvm::raw_string_ostream os(str); os << Action::getClassName(A->getKind()) << ", "; if (InputAction *IA = dyn_cast<InputAction>(A)) { os << "\"" << IA->getInputArg().getValue(C.getArgs()) << "\""; } else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) { os << '"' << (BIA->getArchName() ? BIA->getArchName() : C.getDefaultToolChain().getArchName()) << '"' << ", {" << PrintActions1(C, *BIA->begin(), Ids) << "}"; } else { os << "{"; for (Action::iterator it = A->begin(), ie = A->end(); it != ie;) { os << PrintActions1(C, *it, Ids); ++it; if (it != ie) os << ", "; } os << "}"; } unsigned Id = Ids.size(); Ids[A] = Id; llvm::errs() << Id << ": " << os.str() << ", " << types::getTypeName(A->getType()) << "\n"; return Id; }
void Driver::PrintVersion(const Compilation &C, llvm::raw_ostream &OS) const { static char buf[] = "$URL: https://llvm.org/svn/llvm-project/cfe/branches/release_26/lib/Driver/Driver.cpp $"; char *zap = strstr(buf, "/lib/Driver"); if (zap) *zap = 0; zap = strstr(buf, "/clang/tools/clang"); if (zap) *zap = 0; const char *vers = buf+6; // FIXME: Add cmake support and remove #ifdef #ifdef SVN_REVISION const char *revision = SVN_REVISION; #else const char *revision = ""; #endif // FIXME: The following handlers should use a callback mechanism, we // don't know what the client would like to do. OS << "clang version " CLANG_VERSION_STRING " (" << vers << " " << revision << ")" << '\n'; const ToolChain &TC = C.getDefaultToolChain(); OS << "Target: " << TC.getTripleString() << '\n'; // Print the threading model. // // FIXME: Implement correctly. OS << "Thread model: " << "posix" << '\n'; }
void Driver::PrintVersion(const Compilation &C, llvm::raw_ostream &OS) const { // FIXME: The following handlers should use a callback mechanism, we don't // know what the client would like to do. OS << getClangFullVersion() << '\n'; const ToolChain &TC = C.getDefaultToolChain(); OS << "Target: " << TC.getTripleString() << '\n'; // Print the threading model. // // FIXME: Implement correctly. OS << "Thread model: " << "posix" << '\n'; }
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); } }
void Driver::BuildJobs(Compilation &C) const { llvm::PrettyStackTraceString CrashInfo("Building compilation jobs"); bool SaveTemps = C.getArgs().hasArg(options::OPT_save_temps); bool UsePipes = C.getArgs().hasArg(options::OPT_pipe); // FIXME: Pipes are forcibly disabled until we support executing // them. if (!CCCPrintBindings) UsePipes = false; // -save-temps inhibits pipes. if (SaveTemps && UsePipes) { Diag(clang::diag::warn_drv_pipe_ignored_with_save_temps); UsePipes = true; } Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o); // It is an error to provide a -o option if we are making multiple // output files. if (FinalOutput) { unsigned NumOutputs = 0; for (ActionList::const_iterator it = C.getActions().begin(), ie = C.getActions().end(); it != ie; ++it) if ((*it)->getType() != types::TY_Nothing) ++NumOutputs; if (NumOutputs > 1) { Diag(clang::diag::err_drv_output_argument_with_multiple_files); FinalOutput = 0; } } for (ActionList::const_iterator it = C.getActions().begin(), ie = C.getActions().end(); it != ie; ++it) { Action *A = *it; // If we are linking an image for multiple archs then the linker // wants -arch_multiple and -final_output <final image // name>. Unfortunately, this doesn't fit in cleanly because we // have to pass this information down. // // FIXME: This is a hack; find a cleaner way to integrate this // into the process. const char *LinkingOutput = 0; if (isa<LipoJobAction>(A)) { if (FinalOutput) LinkingOutput = FinalOutput->getValue(C.getArgs()); else LinkingOutput = DefaultImageName.c_str(); } InputInfo II; BuildJobsForAction(C, A, &C.getDefaultToolChain(), /*CanAcceptPipe*/ true, /*AtTopLevel*/ true, /*LinkingOutput*/ LinkingOutput, II); } // If the user passed -Qunused-arguments or there were errors, don't // warn about any unused arguments. if (Diags.getNumErrors() || C.getArgs().hasArg(options::OPT_Qunused_arguments)) return; // Claim -### here. (void) C.getArgs().hasArg(options::OPT__HASH_HASH_HASH); for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end(); it != ie; ++it) { Arg *A = *it; // FIXME: It would be nice to be able to send the argument to the // Diagnostic, so that extra values, position, and so on could be // printed. if (!A->isClaimed()) { if (A->getOption().hasNoArgumentUnused()) continue; // Suppress the warning automatically if this is just a flag, // and it is an instance of an argument we already claimed. const Option &Opt = A->getOption(); if (isa<FlagOption>(Opt)) { bool DuplicateClaimed = false; // FIXME: Use iterator. for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end(); it != ie; ++it) { if ((*it)->isClaimed() && (*it)->getOption().matches(Opt.getId())) { DuplicateClaimed = true; break; } } if (DuplicateClaimed) continue; } Diag(clang::diag::warn_drv_unused_argument) << A->getAsString(C.getArgs()); } } }
bool Driver::HandleImmediateArgs(const Compilation &C) { // The order these options are handled in in gcc is all over the // place, but we don't expect inconsistencies w.r.t. that to matter // in practice. if (C.getArgs().hasArg(options::OPT_dumpversion)) { llvm::outs() << CLANG_VERSION_STRING "\n"; return false; } if (C.getArgs().hasArg(options::OPT__help) || C.getArgs().hasArg(options::OPT__help_hidden)) { PrintHelp(C.getArgs().hasArg(options::OPT__help_hidden)); return false; } if (C.getArgs().hasArg(options::OPT__version)) { // Follow gcc behavior and use stdout for --version and stderr for -v PrintVersion(C, llvm::outs()); return false; } if (C.getArgs().hasArg(options::OPT_v) || C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) { PrintVersion(C, llvm::errs()); SuppressMissingInputWarning = true; } const ToolChain &TC = C.getDefaultToolChain(); if (C.getArgs().hasArg(options::OPT_print_search_dirs)) { llvm::outs() << "programs: ="; for (ToolChain::path_list::const_iterator it = TC.getProgramPaths().begin(), ie = TC.getProgramPaths().end(); it != ie; ++it) { if (it != TC.getProgramPaths().begin()) llvm::outs() << ':'; llvm::outs() << *it; } llvm::outs() << "\n"; llvm::outs() << "libraries: ="; for (ToolChain::path_list::const_iterator it = TC.getFilePaths().begin(), ie = TC.getFilePaths().end(); it != ie; ++it) { if (it != TC.getFilePaths().begin()) llvm::outs() << ':'; llvm::outs() << *it; } llvm::outs() << "\n"; return false; } // FIXME: The following handlers should use a callback mechanism, we // don't know what the client would like to do. if (Arg *A = C.getArgs().getLastArg(options::OPT_print_file_name_EQ)) { llvm::outs() << GetFilePath(A->getValue(C.getArgs()), TC).toString() << "\n"; return false; } if (Arg *A = C.getArgs().getLastArg(options::OPT_print_prog_name_EQ)) { llvm::outs() << GetProgramPath(A->getValue(C.getArgs()), TC).toString() << "\n"; return false; } if (C.getArgs().hasArg(options::OPT_print_libgcc_file_name)) { llvm::outs() << GetFilePath("libgcc.a", TC).toString() << "\n"; return false; } if (C.getArgs().hasArg(options::OPT_print_multi_lib)) { // FIXME: We need tool chain support for this. llvm::outs() << ".;\n"; switch (C.getDefaultToolChain().getTriple().getArch()) { default: break; case llvm::Triple::x86_64: llvm::outs() << "x86_64;@m64" << "\n"; break; case llvm::Triple::ppc64: llvm::outs() << "ppc64;@m64" << "\n"; break; } return false; } // FIXME: What is the difference between print-multi-directory and // print-multi-os-directory? if (C.getArgs().hasArg(options::OPT_print_multi_directory) || C.getArgs().hasArg(options::OPT_print_multi_os_directory)) { switch (C.getDefaultToolChain().getTriple().getArch()) { default: case llvm::Triple::x86: case llvm::Triple::ppc: llvm::outs() << "." << "\n"; break; case llvm::Triple::x86_64: llvm::outs() << "x86_64" << "\n"; break; case llvm::Triple::ppc64: llvm::outs() << "ppc64" << "\n"; break; } return false; } return true; }