void tools::SHAVE::Compiler::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { ArgStringList CmdArgs; assert(Inputs.size() == 1); const InputInfo &II = Inputs[0]; assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX || II.getType() == types::TY_PP_CXX); if (JA.getKind() == Action::PreprocessJobClass) { Args.ClaimAllArgs(); CmdArgs.push_back("-E"); } else { assert(Output.getType() == types::TY_PP_Asm); // Require preprocessed asm. CmdArgs.push_back("-S"); CmdArgs.push_back("-fno-exceptions"); // Always do this even if unspecified. } CmdArgs.push_back("-DMYRIAD2"); // Append all -I, -iquote, -isystem paths, defines/undefines, 'f' // flags, 'g' flags, 'M' flags, optimize flags, warning options, // mcpu flags, mllvm flags, and Xclang flags. // These are spelled the same way in clang and moviCompile. Args.AddAllArgsExcept( CmdArgs, {options::OPT_I_Group, options::OPT_clang_i_Group, options::OPT_std_EQ, options::OPT_D, options::OPT_U, options::OPT_f_Group, options::OPT_f_clang_Group, options::OPT_g_Group, options::OPT_M_Group, options::OPT_O_Group, options::OPT_W_Group, options::OPT_mcpu_EQ, options::OPT_mllvm, options::OPT_Xclang}, {options::OPT_fno_split_dwarf_inlining}); Args.hasArg(options::OPT_fno_split_dwarf_inlining); // Claim it if present. // If we're producing a dependency file, and assembly is the final action, // then the name of the target in the dependency file should be the '.o' // file, not the '.s' file produced by this step. For example, instead of // /tmp/mumble.s: mumble.c .../someheader.h // the filename on the lefthand side should be "mumble.o" if (Args.getLastArg(options::OPT_MF) && !Args.getLastArg(options::OPT_MT) && C.getActions().size() == 1 && C.getActions()[0]->getKind() == Action::AssembleJobClass) { Arg *A = Args.getLastArg(options::OPT_o); if (A) { CmdArgs.push_back("-MT"); CmdArgs.push_back(Args.MakeArgString(A->getValue())); } } CmdArgs.push_back(II.getFilename()); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); std::string Exec = Args.MakeArgString(getToolChain().GetProgramPath("moviCompile")); C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Exec), CmdArgs, Inputs)); }
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()); } } }
void Driver::PrintActions(const Compilation &C) const { std::map<Action*, unsigned> Ids; for (ActionList::const_iterator it = C.getActions().begin(), ie = C.getActions().end(); it != ie; ++it) PrintActions1(C, *it, Ids); }
Compilation *Driver::BuildCompilation(int argc, const char **argv) { llvm::PrettyStackTraceString CrashInfo("Compilation construction"); // FIXME: Handle environment options which effect driver behavior, // somewhere (client?). GCC_EXEC_PREFIX, COMPILER_PATH, // LIBRARY_PATH, LPATH, CC_PRINT_OPTIONS, QA_OVERRIDE_GCC3_OPTIONS. // FIXME: What are we going to do with -V and -b? // FIXME: This stuff needs to go into the Compilation, not the // driver. bool CCCPrintOptions = false, CCCPrintActions = false; const char **Start = argv + 1, **End = argv + argc; const char *HostTriple = DefaultHostTriple.c_str(); // Read -ccc args. // // FIXME: We need to figure out where this behavior should // live. Most of it should be outside in the client; the parts that // aren't should have proper options, either by introducing new ones // or by overloading gcc ones like -V or -b. for (; Start != End && memcmp(*Start, "-ccc-", 5) == 0; ++Start) { const char *Opt = *Start + 5; if (!strcmp(Opt, "print-options")) { CCCPrintOptions = true; } else if (!strcmp(Opt, "print-phases")) { CCCPrintActions = true; } else if (!strcmp(Opt, "print-bindings")) { CCCPrintBindings = true; } else if (!strcmp(Opt, "cxx")) { CCCIsCXX = true; } else if (!strcmp(Opt, "echo")) { CCCEcho = true; } else if (!strcmp(Opt, "gcc-name")) { assert(Start+1 < End && "FIXME: -ccc- argument handling."); CCCGenericGCCName = *++Start; } else if (!strcmp(Opt, "clang-cxx")) { CCCUseClangCXX = true; } else if (!strcmp(Opt, "no-clang-cxx")) { CCCUseClangCXX = false; } else if (!strcmp(Opt, "pch-is-pch")) { CCCUsePCH = true; } else if (!strcmp(Opt, "pch-is-pth")) { CCCUsePCH = false; } else if (!strcmp(Opt, "no-clang")) { CCCUseClang = false; } else if (!strcmp(Opt, "no-clang-cpp")) { CCCUseClangCPP = false; } else if (!strcmp(Opt, "clang-archs")) { assert(Start+1 < End && "FIXME: -ccc- argument handling."); const char *Cur = *++Start; CCCClangArchs.clear(); for (;;) { const char *Next = strchr(Cur, ','); if (Next) { if (Cur != Next) CCCClangArchs.insert(std::string(Cur, Next)); Cur = Next + 1; } else { if (*Cur != '\0') CCCClangArchs.insert(std::string(Cur)); break; } } } else if (!strcmp(Opt, "host-triple")) { assert(Start+1 < End && "FIXME: -ccc- argument handling."); HostTriple = *++Start; } else { // FIXME: Error handling. llvm::errs() << "invalid option: " << *Start << "\n"; exit(1); } } InputArgList *Args = ParseArgStrings(Start, End); Host = GetHostInfo(HostTriple); // The compilation takes ownership of Args. Compilation *C = new Compilation(*this, *Host->getToolChain(*Args), Args); // FIXME: This behavior shouldn't be here. if (CCCPrintOptions) { PrintOptions(C->getArgs()); return C; } if (!HandleImmediateArgs(*C)) return C; // Construct the list of abstract actions to perform for this // compilation. We avoid passing a Compilation here simply to // enforce the abstraction that pipelining is not host or toolchain // dependent (other than the driver driver test). if (Host->useDriverDriver()) BuildUniversalActions(C->getArgs(), C->getActions()); else BuildActions(C->getArgs(), C->getActions()); if (CCCPrintActions) { PrintActions(*C); return C; } BuildJobs(*C); return C; }
Compilation *Driver::BuildCompilation(int argc, const char **argv) { llvm::PrettyStackTraceString CrashInfo("Compilation construction"); // FIXME: Handle environment options which effect driver behavior, somewhere // (client?). GCC_EXEC_PREFIX, COMPILER_PATH, LIBRARY_PATH, LPATH, // CC_PRINT_OPTIONS. // FIXME: What are we going to do with -V and -b? // FIXME: This stuff needs to go into the Compilation, not the driver. bool CCCPrintOptions = false, CCCPrintActions = false; const char **Start = argv + 1, **End = argv + argc; const char *HostTriple = DefaultHostTriple.c_str(); InputArgList *Args = ParseArgStrings(Start, End); // -no-canonical-prefixes is used very early in main. Args->ClaimAllArgs(options::OPT_no_canonical_prefixes); // Extract -ccc args. // // FIXME: We need to figure out where this behavior should live. Most of it // should be outside in the client; the parts that aren't should have proper // options, either by introducing new ones or by overloading gcc ones like -V // or -b. CCCPrintOptions = Args->hasArg(options::OPT_ccc_print_options); CCCPrintActions = Args->hasArg(options::OPT_ccc_print_phases); CCCPrintBindings = Args->hasArg(options::OPT_ccc_print_bindings); CCCIsCXX = Args->hasArg(options::OPT_ccc_cxx) || CCCIsCXX; CCCEcho = Args->hasArg(options::OPT_ccc_echo); if (const Arg *A = Args->getLastArg(options::OPT_ccc_gcc_name)) CCCGenericGCCName = A->getValue(*Args); CCCUseClangCXX = Args->hasFlag(options::OPT_ccc_clang_cxx, options::OPT_ccc_no_clang_cxx, CCCUseClangCXX); CCCUsePCH = Args->hasFlag(options::OPT_ccc_pch_is_pch, options::OPT_ccc_pch_is_pth); CCCUseClang = !Args->hasArg(options::OPT_ccc_no_clang); CCCUseClangCPP = !Args->hasArg(options::OPT_ccc_no_clang_cpp); if (const Arg *A = Args->getLastArg(options::OPT_ccc_clang_archs)) { llvm::StringRef Cur = A->getValue(*Args); CCCClangArchs.clear(); while (!Cur.empty()) { std::pair<llvm::StringRef, llvm::StringRef> Split = Cur.split(','); if (!Split.first.empty()) { llvm::Triple::ArchType Arch = llvm::Triple(Split.first, "", "").getArch(); if (Arch == llvm::Triple::UnknownArch) Diag(clang::diag::err_drv_invalid_arch_name) << Split.first; CCCClangArchs.insert(Arch); } Cur = Split.second; } } if (const Arg *A = Args->getLastArg(options::OPT_ccc_host_triple)) HostTriple = A->getValue(*Args); if (const Arg *A = Args->getLastArg(options::OPT_ccc_install_dir)) Dir = A->getValue(*Args); Host = GetHostInfo(HostTriple); // The compilation takes ownership of Args. Compilation *C = new Compilation(*this, *Host->CreateToolChain(*Args), Args); // FIXME: This behavior shouldn't be here. if (CCCPrintOptions) { PrintOptions(C->getArgs()); return C; } if (!HandleImmediateArgs(*C)) return C; // Construct the list of abstract actions to perform for this compilation. We // avoid passing a Compilation here simply to enforce the abstraction that // pipelining is not host or toolchain dependent (other than the driver driver // test). if (Host->useDriverDriver()) BuildUniversalActions(C->getArgs(), C->getActions()); else BuildActions(C->getArgs(), C->getActions()); if (CCCPrintActions) { PrintActions(*C); return C; } BuildJobs(*C); return C; }