Exemplo n.º 1
0
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));
}
Exemplo n.º 2
0
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());
    }
  }
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
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;
}