//===-- CompileGo.cpp -----------------------------------------------------===//
//
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
//===----------------------------------------------------------------------===//
//
// Gollvm driver helper class "CompileGo" methods.
//
//===----------------------------------------------------------------------===//

#include "CompileGo.h"

#include "go-llvm-linemap.h"
#include "go-llvm-diagnostics.h"
#include "go-llvm.h"
#include "go-c.h"
#include "mpfr.h"
#include "GollvmOptions.h"
#include "GollvmConfig.h"
#include "GollvmPasses.h"

#include "Action.h"
#include "Artifact.h"
#include "Driver.h"
#include "ToolChain.h"

namespace gollvm { namespace arch {
#include "ArchCpusAttrs.h"
} }

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/RemarkStreamer.h"
#include "llvm/IR/Verifier.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/Utils.h"

#include <sstream>

using namespace llvm;

namespace gollvm {
namespace driver {

// For keeping track of info on -Rpass=<regex> and related options.
class RemarkCtl {
 public:
  std::shared_ptr<llvm::Regex> optimizationRemarkPattern_;
  std::shared_ptr<llvm::Regex> optimizationRemarkMissedPattern_;
  std::shared_ptr<llvm::Regex> optimizationRemarkAnalysisPattern_;
};

class CompileGoImpl {
 public:
  CompileGoImpl(ToolChain &tc, const std::string &executablePath);

  // Perform compilation.
  bool performAction(Compilation &compilation,
                     const Action &jobAction,
                     const ArtifactList &inputArtifacts,
                     const Artifact &output);

 private:
  Triple triple_;
  const ToolChain &toolchain_;
  Driver &driver_;
  LLVMContext context_;
  const char *progname_;
  std::string executablePath_;
  opt::InputArgList &args_;
  CodeGenOpt::Level cgolvl_;
  unsigned olvl_;
  bool hasError_;
  std::unique_ptr<Llvm_backend> bridge_;
  std::unique_ptr<TargetMachine> target_;
  std::unique_ptr<Llvm_linemap> linemap_;
  std::unique_ptr<Module> module_;
  std::vector<std::string> inputFileNames_;
  std::string asmOutFileName_;
  std::unique_ptr<ToolOutputFile> asmout_;
  std::unique_ptr<ToolOutputFile> optRecordFile_;
  RemarkCtl remarkCtl_;
  std::unique_ptr<TargetLibraryInfoImpl> tlii_;
  std::string targetCpuAttr_;
  std::string targetFeaturesAttr_;
  std::string sampleProfileFile_;
  bool enable_gc_;

  void createPasses(legacy::PassManager &MPM,
                    legacy::FunctionPassManager &FPM);
  void setupGoSearchPath();

  // This routine emits output for -### and/or -v, then returns TRUE
  // of the compilation should be stubbed out (-###) or FALSE otherwise.
  bool preamble(const Artifact &output);

  // The routines below return TRUE for success, FALSE for failure/error/
  bool setup();
  bool initBridge();
  bool invokeFrontEnd();
  bool invokeBridge();
  bool invokeBackEnd();
  bool resolveInputOutput(const Action &jobAction,
                          const ArtifactList &inputArtifacts,
                          const Artifact &output);

  // Helpers for -### output
  void dumpArg(opt::Arg &arg, bool doquote);
  void quoteDump(const std::string &str, bool doquote);

  // Misc
  bool enableVectorization(bool slp);
};

CompileGoImpl::CompileGoImpl(ToolChain &tc, const std::string &executablePath)
    : triple_(tc.driver().triple()),
      toolchain_(tc),
      driver_(tc.driver()),
      progname_(tc.driver().progname()),
      executablePath_(executablePath),
      args_(tc.driver().args()),
      cgolvl_(CodeGenOpt::Default),
      olvl_(2),
      hasError_(false),
      enable_gc_(false)
{
  InitializeAllTargets();
  InitializeAllTargetMCs();
  InitializeAllAsmPrinters();
  InitializeAllAsmParsers();
}

bool CompileGoImpl::performAction(Compilation &compilation,
                                  const Action &jobAction,
                                  const ArtifactList &inputArtifacts,
                                  const Artifact &output)
{
  if (preamble(output))
    return true;

  // Resolve input/output files.
  if (!resolveInputOutput(jobAction, inputArtifacts, output))
    return false;

  // Setup
  if (!setup())
    return false;

  // Set up the bridge
  if (!initBridge())
    return false;

  // Invoke front end
  if (!invokeFrontEnd())
    return false;

  // Invoke back end
  if (!invokeBackEnd())
    return false;

  return true;
}

class BEDiagnosticHandler : public DiagnosticHandler {
  bool *error_;
 public:
  BEDiagnosticHandler(bool *errorPtr, RemarkCtl &remarkCtl)
    : error_(errorPtr), r_(remarkCtl) {}
  bool handleDiagnostics(const DiagnosticInfo &DI) override {
    if (DI.getSeverity() == DS_Error)
      *error_ = true;
    if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI))
      if (!Remark->isEnabled())
        return true;
    DiagnosticPrinterRawOStream DP(errs());
    errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";
    DI.print(DP);
    errs() << "\n";
    return true;
  }

  // Overrides of parent class methods.
  bool isAnalysisRemarkEnabled(StringRef passName) const override {
    return (r_.optimizationRemarkAnalysisPattern_ &&
            r_.optimizationRemarkAnalysisPattern_->match(passName));
  }
  bool isMissedOptRemarkEnabled(StringRef passName) const override {
    return (r_.optimizationRemarkMissedPattern_ &&
            r_.optimizationRemarkMissedPattern_->match(passName));
  }
  bool isPassedOptRemarkEnabled(StringRef passName) const override {
    return (r_.optimizationRemarkPattern_ &&
            r_.optimizationRemarkPattern_->match(passName));
  }
  bool isAnyRemarkEnabled() const override {
    return (r_.optimizationRemarkPattern_ ||
            r_.optimizationRemarkMissedPattern_ ||
            r_.optimizationRemarkAnalysisPattern_);
  }

 private:
  RemarkCtl &r_;
};

void CompileGoImpl::quoteDump(const std::string &str, bool doquote)
{
  Regex qureg("^[-_/A-Za-z0-9_\\.]+$");
  errs() << " ";
  if (doquote)
    doquote = !qureg.match(str);
  errs() << (doquote ? "\"" : "") << str << (doquote ? "\"" : "");
}

void CompileGoImpl::dumpArg(opt::Arg &arg, bool doquote)
{
  if (arg.getOption().getKind() != opt::Option::InputClass)
    quoteDump(arg.getSpelling(), doquote);
  for (auto &val : arg.getValues())
    quoteDump(val, doquote);
}

bool CompileGoImpl::preamble(const Artifact &output)
{
  // If -v is in effect, print something to show the effect of the
  // compilation. This is in some sense a fiction, because the top
  // level driver is not invoking an external tool to perform the
  // compile, but there is an expectation with compilers that if you
  // take the "-v" output and then execute each command shown by hand,
  // you'll get the same effect as the original command that produced
  // the "-v" output.
  bool hashHashHash = args_.hasArg(gollvm::options::OPT__HASH_HASH_HASH);
  if (args_.hasArg(gollvm::options::OPT_v) || hashHashHash) {
    errs() << "Target: " << triple_.str() << "\n";
    errs() << " " << executablePath_;
    if (!args_.hasArg(gollvm::options::OPT_S) &&
        !args_.hasArg(gollvm::options::OPT_emit_llvm))
      errs() << " " << "-S";
    for (auto arg : args_) {
      // Special case for -L. Here even if the user said "-L /x"
      // we render it as -L/x so as to be compatible with existing
      // code in the imported that expects the former and not the latter.
      if (arg->getOption().matches(gollvm::options::OPT_L))
        errs() << " -L" << arg->getValue();
      if (arg->getOption().getGroup().isValid() &&
          (arg->getOption().getGroup().getID() ==
           gollvm::options::OPT_Link_Group))
        continue;
      if (arg->getOption().matches(gollvm::options::OPT_v) ||
          arg->getOption().matches(gollvm::options::OPT_c) ||
          arg->getOption().matches(gollvm::options::OPT_o) ||
          arg->getOption().matches(gollvm::options::OPT__HASH_HASH_HASH) ||
          arg->getOption().matches(gollvm::options::OPT_save_temps))
        continue;
      dumpArg(*arg, hashHashHash);
    }

    errs() << " " << "-L" << driver_.installedLibDir() << " " << "-o";
    quoteDump(output.file(), hashHashHash);
    errs() << "\n";
  }

  return hashHashHash;
}

bool CompileGoImpl::resolveInputOutput(const Action &jobAction,
                                       const ArtifactList &inputArtifacts,
                                       const Artifact &output)
{
  // Collect input files
  for (auto inp : inputArtifacts)
    inputFileNames_.push_back(inp->file());
  assert(! inputFileNames_.empty());
  asmOutFileName_ = output.file();

  // Open output file.
  std::error_code EC;
  sys::fs::OpenFlags OpenFlags = sys::fs::F_Text;
  auto FDOut = llvm::make_unique<ToolOutputFile>(asmOutFileName_, EC,
                                                 OpenFlags);
  if (EC) {
    errs() << progname_ << ": error opening " << asmOutFileName_ << ": "
           << EC.message() << '\n';
    return false;
  }

  asmout_.reset(FDOut.release());
  asmout_->keep();
  return true;
}

static std::shared_ptr<llvm::Regex>
generateOptimizationRemarkRegex(opt::ArgList &args, opt::Arg *rpassArg)
{
  llvm::StringRef val = rpassArg->getValue();
  std::string regexError;
  std::shared_ptr<llvm::Regex> pattern = std::make_shared<llvm::Regex>(val);
  if (!pattern->isValid(regexError)) {
    errs() << "error: invalid regex for '"
           << rpassArg->getAsString(args) << "' option: "
           << regexError << "\n";
    pattern.reset();
  }
  return pattern;
}

bool CompileGoImpl::setup()
{
  // Set triple.
  triple_ = driver_.triple();

  // Get the target specific parser.
  std::string Error;
  const Target *TheTarget =
      TargetRegistry::lookupTarget("", triple_, Error);
  if (!TheTarget) {
    errs() << progname_ << Error;
    return false;
  }

  // optimization level
  opt::Arg *oarg = args_.getLastArg(gollvm::options::OPT_O_Group);
  if (oarg != nullptr) {
    StringRef lev(oarg->getValue());
    if (lev.size() != 1) {
      errs() << progname_ << ": invalid argument to -O flag: "
             << lev << "\n";
      return false;
    }
    switch (lev[0]) {
      case '0':
        olvl_ = 0;
        cgolvl_ = CodeGenOpt::None;
        break;
      case '1':
        olvl_ = 1;
        cgolvl_ = CodeGenOpt::Less;
        break;
      case 's': // TODO: -Os same as -O for now.
      case '2':
        olvl_ = 2;
        cgolvl_ = CodeGenOpt::Default;
        break;
      case '3':
        olvl_ = 3;
        cgolvl_ = CodeGenOpt::Aggressive;
        break;
      default:
        errs() << progname_ << ": invalid optimization level.\n";
        return false;
    }
  }

  go_no_warn = args_.hasArg(gollvm::options::OPT_w);
  go_loc_show_column =
      driver_.reconcileOptionPair(gollvm::options::OPT_fshow_column,
                                  gollvm::options::OPT_fno_show_column,
                                  true);

  // AutoFDO.
  opt::Arg *sprofarg =
      args_.getLastArg(gollvm::options::OPT_fprofile_sample_use,
                       gollvm::options::OPT_fno_profile_sample_use,
                       gollvm::options::OPT_fprofile_sample_use_EQ);
  if (sprofarg) {
    opt::Arg *fnamearg =
        args_.getLastArg(gollvm::options::OPT_fprofile_sample_use_EQ);
    if (fnamearg == nullptr) {
      // Using -fsample-profile-use / -fno-sample-profile-use without
      // also using -fprofile-sample-use=XXXX doesn't make sense
      errs() << progname_ << ": warning: "
             << "-fprofile-sample-use / -fno-profile-sample-use "
             << "flags ignored (since no -fprofile-sample-use=<file> "
             << "specified).\n";
    } else if (!sprofarg->getOption().matches(
        gollvm::options::OPT_fno_profile_sample_use)) {
      StringRef fname = fnamearg->getValue();
      if (!llvm::sys::fs::exists(fname)) {
        errs() << progname_ << ": unable to access file: " << fname << "\n";
        return false;
      }
      sampleProfileFile_ = fname;
    }
  }

  // Capture optimization record.
  opt::Arg *optrecordarg =
      args_.getLastArg(gollvm::options::OPT_fsave_optimization_record,
                       gollvm::options::OPT_fno_save_optimization_record,
                       gollvm::options::OPT_foptimization_record_file_EQ);
  if (optrecordarg && !optrecordarg->getOption().matches(
          gollvm::options::OPT_fno_save_optimization_record)) {
    opt::Arg *fnamearg =
        args_.getLastArg(gollvm::options::OPT_foptimization_record_file_EQ);
    if (fnamearg != nullptr) {
      StringRef fname = fnamearg->getValue();
      std::error_code EC;
      optRecordFile_ = llvm::make_unique<llvm::ToolOutputFile>(
          fname, EC, llvm::sys::fs::F_None);
      if (EC) {
        errs() << "error: unable to open file '"
               << fname << "' to emit optimization remarks\n";
        return false;
      }
      context_.setRemarkStreamer(llvm::make_unique<llvm::RemarkStreamer>(
          fname,
          llvm::make_unique<llvm::remarks::YAMLSerializer>(optRecordFile_->os())));
      if (! sampleProfileFile_.empty())
        context_.setDiagnosticsHotnessRequested(true);
      optRecordFile_->keep();
    }
  }

  // Vet/honor -Rpass= and friends.
  if (opt::Arg *arg = args_.getLastArg(gollvm::options::OPT_Rpass_EQ)) {
    remarkCtl_.optimizationRemarkPattern_ =
        generateOptimizationRemarkRegex(args_, arg);
  }
  if (opt::Arg *arg = args_.getLastArg(gollvm::options::OPT_Rpass_missed_EQ)) {
    remarkCtl_.optimizationRemarkMissedPattern_ =
        generateOptimizationRemarkRegex(args_, arg);
  }
  if (opt::Arg *arg = args_.getLastArg(gollvm::options::OPT_Rpass_analysis_EQ)) {
    remarkCtl_.optimizationRemarkAnalysisPattern_ =
        generateOptimizationRemarkRegex(args_, arg);
  }

  TargetOptions Options;

  // FIXME: turn off integrated assembler for now.
  Options.DisableIntegratedAS = true;

  // FIXME: this hard-wires on the equivalent of -ffunction-sections
  // and -fdata-sections, since there doesn't seem to be a high-level
  // hook for selecting a separate section for a specific variable or
  // function (other than forcing it into a comdat, which is not
  // always what we want).
  Options.FunctionSections = true;
  Options.DataSections = true;
  Options.UniqueSectionNames = true;

  // FIXME: this needs to be dependent on target triple
  Options.EABIVersion = llvm::EABI::Default;

  // init array use
  Options.UseInitArray =
      driver_.reconcileOptionPair(gollvm::options::OPT_fuse_init_array,
                                  gollvm::options::OPT_fno_use_init_array,
                                  true);

  // FP trapping mode
  Options.NoTrappingFPMath =
      driver_.reconcileOptionPair(gollvm::options::OPT_ftrapping_math,
                                  gollvm::options::OPT_fno_trapping_math,
                                  false);


  // The -fno-math-errno option is essentially a no-op when compiling
  // Go code, but -fmath-errno does not make sense, since 'errno' is
  // not exposed in any meaningful way as part of the math package.
  // Allow users to set -fno-math-errno for compatibility reasons, but
  // issue an error if -fmath-errno is set.
  bool mathErrno =
      driver_.reconcileOptionPair(gollvm::options::OPT_fmath_errno,
                                  gollvm::options::OPT_fno_math_errno,
                                  false);
  if (mathErrno) {
    errs() << "error: -fmath-errno unsupported for Go code\n";
    return false;
  }

  // FP contract settings.
  auto dofuse = driver_.getFPOpFusionMode();
  if (!dofuse)
    return false;
  Options.AllowFPOpFusion = *dofuse;

  // Support -march
  std::string cpuStr;
  opt::Arg *cpuarg = args_.getLastArg(gollvm::options::OPT_march_EQ);
  if (cpuarg != nullptr) {
    std::string val(cpuarg->getValue());
    if (val == "native")
      cpuStr = sys::getHostCPUName();
    else
      cpuStr = cpuarg->getValue();
  }

  // Locate correct entry in architectures table for this triple
  const gollvm::arch::CpuAttrs *cpuAttrs = nullptr;
  for (unsigned i = 0; gollvm::arch::triples[i].cpuattrs != nullptr; i += 1) {
    if (!strcmp(triple_.str().c_str(), gollvm::arch::triples[i].triple)) {
      cpuAttrs = gollvm::arch::triples[i].cpuattrs;
      break;
    }
  }
  if (cpuAttrs == nullptr) {
    errs() << progname_ << ": unable to determine target CPU features for "
           << "target " << triple_.str() << "\n";
    return false;
  }

  // If no CPU specified, use first entry. Otherwise look for CPU name.
  if (!cpuStr.empty()) {
    bool found = false;
    while (strlen(cpuAttrs->cpu) != 0) {
      if (!strcmp(cpuAttrs->cpu, cpuStr.c_str())) {
        // found
        found = true;
        break;
      }
      cpuAttrs++;
    }
    if (!found) {
      errs() << progname_ << ": invalid setting for -march:"
             << " -- unable to identify CPU '" << cpuStr << "'\n";
      return false;
    }
  }
  targetCpuAttr_ = cpuAttrs->cpu;
  targetFeaturesAttr_ = cpuAttrs->attrs;

  // Create target machine
  Optional<llvm::CodeModel::Model> CM = None;
  target_.reset(
      TheTarget->createTargetMachine(triple_.getTriple(),
                                     targetCpuAttr_, targetFeaturesAttr_,
                                     Options, driver_.reconcileRelocModel(),
                                     CM, cgolvl_));
  assert(target_.get() && "Could not allocate target machine!");

  return true;
}

// This helper performs the various initial steps needed to set up the
// compilation, including prepping the LLVM context, creating an LLVM
// module, creating the bridge itself (Llvm_backend object) and
// setting up the Go frontend via a call to go_create_gogo(). At the
// end of this routine things should be ready to kick off the front end.

bool CompileGoImpl::initBridge()
{
  // Set up the LLVM context
  context_.setDiagnosticHandler(
      llvm::make_unique<BEDiagnosticHandler>(&this->hasError_, this->remarkCtl_));

  llvm::Optional<unsigned> enable_gc =
      driver_.getLastArgAsInteger(gollvm::options::OPT_enable_gc_EQ, 0u);
  enable_gc_ = enable_gc && *enable_gc;

  // Construct linemap and module
  linemap_.reset(new Llvm_linemap());
  module_.reset(new llvm::Module("gomodule", context_));

  // Add the target data from the target machine, if it exists
  module_->setTargetTriple(triple_.getTriple());

  // Data layout.
  std::string dlstr = target_->createDataLayout().getStringRepresentation();
  if (enable_gc_)
    dlstr += "-ni:1"; // non-integral pointer in address space 1
  module_->setDataLayout(dlstr);

  module_->setPICLevel(driver_.getPicLevel());
  if (driver_.picIsPIE())
    module_->setPIELevel(driver_.getPieLevel());

  // Now construct Llvm_backend helper.
  unsigned addrspace = enable_gc_ ? 1 : 0;
  bridge_.reset(new Llvm_backend(context_, module_.get(), linemap_.get(), addrspace));

  // Honor inline, tracelevel cmd line options
  llvm::Optional<unsigned> tl =
      driver_.getLastArgAsInteger(gollvm::options::OPT_tracelevel_EQ, 0u);
  if (!tl)
    return false;
  bridge_->setTraceLevel(*tl);
  bridge_->setNoInline(args_.hasArg(gollvm::options::OPT_fno_inline));
  bridge_->setTargetCpuAttr(targetCpuAttr_);
  bridge_->setTargetFeaturesAttr(targetFeaturesAttr_);
  if (!sampleProfileFile_.empty())
    bridge_->setEnableAutoFDO();

  // -f[no-]omit-frame-pointer
  bool omitFp =
      driver_.reconcileOptionPair(gollvm::options::OPT_fomit_frame_pointer,
                                  gollvm::options::OPT_fno_omit_frame_pointer,
                                  true);
  bridge_->setNoFpElim(!omitFp);

  // -f[no-]split-stack
  bool useSplitStack =
      driver_.reconcileOptionPair(gollvm::options::OPT_fsplit_stack,
                                  gollvm::options::OPT_fno_split_stack,
                                  true);
  bridge_->setUseSplitStack(useSplitStack);

  // Honor -fdebug-prefix=... option.
  for (const auto &arg : driver_.args().getAllArgValues(gollvm::options::OPT_fdebug_prefix_map_EQ))
    bridge_->addDebugPrefix(llvm::StringRef(arg).split('='));

  // GC support.
  if (enable_gc_) {
    bridge_->setGCStrategy("go");
    linkGoGC();
    linkGoGCPrinter();
  }

  // Support -fgo-dump-ast
  if (args_.hasArg(gollvm::options::OPT_fgo_dump_ast))
    go_enable_dump("ast");

  // Populate 'args' struct with various bits of information needed by
  // the front end, then pass it to the front end via go_create_gogo().
  struct go_create_gogo_args args;
  unsigned bpi = target_->getPointerSize(0) * 8;
  args.int_type_size = bpi;
  args.pointer_size = bpi;
  opt::Arg *pkpa = args_.getLastArg(gollvm::options::OPT_fgo_pkgpath_EQ);
  args.pkgpath = (pkpa == nullptr ? NULL : pkpa->getValue());
  opt::Arg *pkpp = args_.getLastArg(gollvm::options::OPT_fgo_prefix_EQ);
  args.prefix = (pkpp == nullptr ? NULL : pkpp->getValue());
  opt::Arg *relimp =
      args_.getLastArg(gollvm::options::OPT_fgo_relative_import_path_EQ);
  args.relative_import_path =
      (relimp == nullptr ? NULL : relimp->getValue());
  opt::Arg *chdr =
      args_.getLastArg(gollvm::options::OPT_fgo_c_header_EQ);
  args.c_header = (chdr == nullptr ? NULL : chdr->getValue());
  args.check_divide_by_zero =
      driver_.reconcileOptionPair(gollvm::options::OPT_fgo_check_divide_zero,
                                  gollvm::options::OPT_fno_go_check_divide_zero,
                                  true);
  args.check_divide_overflow =
      driver_.reconcileOptionPair(gollvm::options::OPT_fgo_check_divide_overflow,
                                  gollvm::options::OPT_fno_go_check_divide_overflow,
                                  true);
  args.compiling_runtime =
      args_.hasArg(gollvm::options::OPT_fgo_compiling_runtime);
  llvm::Optional<int> del =
      driver_.getLastArgAsInteger(gollvm::options::OPT_fgo_debug_escape_EQ, 0);
  if (!del)
    return false;
  args.debug_escape_level = *del;
  opt::Arg *hasharg =
      args_.getLastArg(gollvm::options::OPT_fgo_debug_escape_hash_EQ);
  args.debug_escape_hash = (hasharg != nullptr ? hasharg->getValue() : NULL);
  args.debug_optimization =
      driver_.reconcileOptionPair(gollvm::options::OPT_fgo_debug_optimization,
                                  gollvm::options::OPT_fno_go_debug_optimization,
                                  false);
  args.nil_check_size_threshold =
      (args.compiling_runtime && args.pkgpath && strcmp(args.pkgpath, "runtime") == 0 ?
       4096 : -1);
  args.linemap = linemap_.get();
  args.backend = bridge_.get();
  go_create_gogo (&args);

  /* The default precision for floating point numbers.  This is used
     for floating point constants with abstract type.  This may
     eventually be controllable by a command line option.  */
  mpfr_set_default_prec (256);

  // Escape analysis
  bool enableEscapeAnalysis =
      driver_.reconcileOptionPair(gollvm::options::OPT_fgo_optimize_allocs,
                                  gollvm::options::OPT_fno_go_optimize_allocs,
                                  true);
  go_enable_optimize("allocs", enableEscapeAnalysis ? 1 : 0);

  // Set up the search path to use for locating Go packages.
  setupGoSearchPath();

  return true;
}

// The Go search path (dirs in which to search for package objects,
// *.gox files, archives, etc) is populated based on command line
// options (-L, -B, -I) and on the installation directory/prefix. For
// an example command line of the form
//
//    <compiler> mumble.go -c -I /I1 -I /I2 -L /L1 -B /B1
//
// the Go package search path will start out with the include dirs
// (/I1 and /I2). We then walk through each of the remaining dirs (-L
// args, -B args, and system install dirs) and if the dir D in
// question contains a "go" subdir we add D/go/<version> and
// D/go/<version>/<triple>. Finally we add each of the -L/-I/install
// dirs directly to the search path.
//
// With this in mind, assuming that the install dir is /install,
// version is 7.0.0, and the target triple x86_64-pc-linux-gnu, for
// the args above we would get a search path of
//
//       /I1
//       /I2
//       /L1/go/7.0.0
//       /L1/go/7.0.0/x86_64-pc-linux-gnu
//       /B1/go/7.0.0
//       /B1/go/7.0.0/x86_64-pc-linux-gnu
//       /install/go/7.0.0
//       /install/go/7.0.0/x86_64-pc-linux-gnu
//       /L1
//       /B1
//       /install

void CompileGoImpl::setupGoSearchPath()
{
  // Include dirs
  std::vector<std::string> incargs =
      args_.getAllArgValues(gollvm::options::OPT_I);
  for (auto &dir : incargs) {
    if (sys::fs::is_directory(dir))
      go_add_search_path(dir.c_str());
  }

  // Make up a list of dirs starting with -L args, then -B args,
  // and finally the installation dir.
  std::vector<std::string> dirs;

  // First -L args.
  for (auto &dir : args_.getAllArgValues(gollvm::options::OPT_L)) {
    if (!sys::fs::is_directory(dir))
      continue;
    dirs.push_back(dir);
  }

  // Add in -B args.
  for (const std::string &pdir : driver_.prefixes()) {
    if (!sys::fs::is_directory(pdir))
      continue;
    dirs.push_back(pdir);
  }

  // Finish up with the library dir from the install.
  dirs.push_back(driver_.installedLibDir());

  // First pass to add go/<version> and go/<version>/triple variants
  for (auto &dir : dirs) {
    std::stringstream b1;
    b1 << dir << sys::path::get_separator().str() << "go"
       << sys::path::get_separator().str() << GOLLVM_LIBVERSION;
    if (sys::fs::is_directory(b1.str())) {
      go_add_search_path(b1.str().c_str());
      std::stringstream b2;
      b2 << b1.str() << sys::path::get_separator().str() << triple_.str();
      if (sys::fs::is_directory(b2.str()))
        go_add_search_path(b2.str().c_str());
    }
  }

  // Second pass with raw dir.
  for (auto &dir : dirs)
    go_add_search_path(dir.c_str());
}

bool CompileGoImpl::invokeFrontEnd()
{
  // Collect the input files and kick off the front end
  // Kick off the front end
  unsigned nfiles = inputFileNames_.size();
  std::unique_ptr<const char *> filenames(new const char *[nfiles]);
  const char **fns = filenames.get();
  unsigned idx = 0;
  for (auto &fn : inputFileNames_)
    fns[idx++] = fn.c_str();
  go_parse_input_files(fns, nfiles, false, true);
  if (!args_.hasArg(gollvm::options::OPT_nobackend))
    go_write_globals();
  if (args_.hasArg(gollvm::options::OPT_dump_ir))
    bridge_->dumpModule();
  if (!args_.hasArg(gollvm::options::OPT_noverify) && !go_be_saw_errors())
    bridge_->verifyModule();
  llvm::Optional<unsigned> tl =
      driver_.getLastArgAsInteger(gollvm::options::OPT_tracelevel_EQ, 0u);
  if (*tl)
    std::cerr << "linemap stats:" << linemap_->statistics() << "\n";

  // Delete the bridge at this point. In the case that there were
  // errors, this will help clean up any unreachable LLVM Instructions
  // (which would otherwise trigger asserts); in the non-error case it
  // will help to free up bridge-related memory prior to kicking off
  // the pass manager.
  bridge_.reset(nullptr);

  // Early exit at this point if we've seen errors
  if (go_be_saw_errors())
    return false;

  return true;
}

bool CompileGoImpl::enableVectorization(bool slp)
{
  bool enable = (olvl_ > 1);
  if (slp)
    return driver_.reconcileOptionPair(gollvm::options::OPT_fslp_vectorize,
                                       gollvm::options::OPT_fno_slp_vectorize,
                                       enable);
  else
    return driver_.reconcileOptionPair(gollvm::options::OPT_fvectorize,
                                       gollvm::options::OPT_fno_vectorize,
                                       enable);
}

static void addAddDiscriminatorsPass(const llvm::PassManagerBuilder &Builder,
                                     llvm::legacy::PassManagerBase &PM) {
  PM.add(createAddDiscriminatorsPass());
}

void CompileGoImpl::createPasses(legacy::PassManager &MPM,
                                 legacy::FunctionPassManager &FPM)
{
  if (args_.hasArg(gollvm::options::OPT_disable_llvm_passes))
    return;

  // FIXME: support LTO, ThinLTO, PGO

  PassManagerBuilder pmb;

  // Configure the inliner
  if (args_.hasArg(gollvm::options::OPT_fno_inline) || olvl_ == 0) {
    // Nothing here at the moment. There is go:noinline, but no equivalent
    // of go:alwaysinline.
  } else {
    bool disableInlineHotCallSite = false; // for autofdo, not yet supported
    pmb.Inliner =
        createFunctionInliningPass(olvl_, 2, disableInlineHotCallSite);
  }

  pmb.OptLevel = olvl_;
  pmb.SizeLevel = 0; // TODO: decide on right value here
  pmb.PrepareForThinLTO = false;
  pmb.PrepareForLTO = false;
  pmb.SLPVectorize = enableVectorization(true);
  pmb.LoopVectorize = enableVectorization(false);

  bool needDwarfDiscr = false;
  if (! sampleProfileFile_.empty()) {
    pmb.PGOSampleUse = sampleProfileFile_;
    needDwarfDiscr = true;
  }
  opt::Arg *dbgprofarg =
      args_.getLastArg(gollvm::options::OPT_fdebug_info_for_profiling,
                       gollvm::options::OPT_fno_debug_info_for_profiling);
  if (dbgprofarg) {
    if (dbgprofarg->getOption().matches(gollvm::options::OPT_fdebug_info_for_profiling))
      needDwarfDiscr = true;
    else
      needDwarfDiscr = false;
  }
  if (needDwarfDiscr)
    pmb.addExtension(llvm::PassManagerBuilder::EP_EarlyAsPossible,
                           addAddDiscriminatorsPass);


  FPM.add(new TargetLibraryInfoWrapperPass(*tlii_));
  if (! args_.hasArg(gollvm::options::OPT_noverify))
    FPM.add(createVerifierPass());

  pmb.populateFunctionPassManager(FPM);
  pmb.populateModulePassManager(MPM);
}

bool CompileGoImpl::invokeBackEnd()
{
  tlii_.reset(new TargetLibraryInfoImpl(triple_));

  // Set up module and function passes
  legacy::PassManager modulePasses;
  modulePasses.add(
      createTargetTransformInfoWrapperPass(target_->getTargetIRAnalysis()));
  legacy::FunctionPassManager functionPasses(module_.get());
  functionPasses.add(
      createTargetTransformInfoWrapperPass(target_->getTargetIRAnalysis()));
  createPasses(modulePasses, functionPasses);

  // Add statepoint insertion pass to the end of optimization pipeline,
  // right before lowering to machine IR.
  if (enable_gc_) {
    modulePasses.add(createGoStatepointsLegacyPass());
    modulePasses.add(createRemoveAddrSpacePass(target_->createDataLayout()));
  }

  legacy::PassManager codeGenPasses;
  bool noverify = args_.hasArg(gollvm::options::OPT_noverify);
  TargetMachine::CodeGenFileType ft = TargetMachine::CGFT_AssemblyFile;

  // Add passes to emit bitcode or LLVM IR as appropriate. Here we mimic
  // clang behavior, which is to emit bitcode when "-emit-llvm" is specified
  // but an LLVM IR dump of "-S -emit-llvm" is used.
  raw_pwrite_stream *OS = &asmout_->os();
  if (args_.hasArg(gollvm::options::OPT_emit_llvm)) {
    bool bitcode = !args_.hasArg(gollvm::options::OPT_S);
    bool preserveUseLists =
        driver_.reconcileOptionPair(gollvm::options::OPT_emit_llvm_uselists,
                                    gollvm::options::OPT_no_emit_llvm_uselists,
                                    false);
    modulePasses.add(bitcode ?
                     createBitcodeWriterPass(*OS, preserveUseLists) :
                     createPrintModulePass(*OS, "", preserveUseLists));
    goto run;
  }

  // Set up codegen passes
  codeGenPasses.add(
      createTargetTransformInfoWrapperPass(target_->getTargetIRAnalysis()));

  // Codegen setup
  codeGenPasses.add(new TargetLibraryInfoWrapperPass(*tlii_));

  // Add stackmap machine IR pass to the end of the machine passes,
  // right before AsmPrinter.
  // FIXME: the code below is essentially duplicate of
  // LLVMTargetMachine::addPassesToEmitFile (and its callee).
  // TODO: error check.
  {
    LLVMTargetMachine *lltm = (LLVMTargetMachine*)(target_.get()); // FIXME: TargetMachine doesn't support llvm::cast?
    TargetPassConfig *passConfig = lltm->createPassConfig(codeGenPasses);
    // Set PassConfig options provided by TargetMachine.
    passConfig->setDisableVerify(noverify);
    codeGenPasses.add(passConfig);
    MachineModuleInfo *MMI = new MachineModuleInfo(lltm);
    codeGenPasses.add(MMI);
    passConfig->addISelPasses();
    passConfig->addMachinePasses();
    passConfig->setInitialized();

    codeGenPasses.add(createGoNilChecksPass());
    codeGenPasses.add(createGoWrappersPass());

    if (enable_gc_)
      codeGenPasses.add(createGoAnnotationPass());

    lltm->addAsmPrinter(codeGenPasses, *OS, nullptr, ft, MMI->getContext());

    codeGenPasses.add(createFreeMachineFunctionPass());
  }

run:
  // Here we go... first function passes
  functionPasses.doInitialization();
  for (Function &F : *module_.get())
    if (!F.isDeclaration())
      functionPasses.run(F);
  functionPasses.doFinalization();

  // ... then module passes
  modulePasses.run(*module_.get());

  // ... and finally code generation
  if (!args_.hasArg(gollvm::options::OPT_emit_llvm))
    codeGenPasses.run(*module_.get());

  if (hasError_)
    return false;

  return true;
}

//......................................................................

CompileGo::CompileGo(ToolChain &tc, const std::string &executablePath)
    : InternalTool("gocompiler", tc),
      impl_(new CompileGoImpl(tc, executablePath))
{
}

CompileGo::~CompileGo()
{
}

bool CompileGo::performAction(Compilation &compilation,
                              const Action &jobAction,
                              const ArtifactList &inputArtifacts,
                              const Artifact &output)
{
  return impl_->performAction(compilation, jobAction, inputArtifacts, output);
}

} // end namespace driver
} // end namespace gollvm
