//===-- Compilation.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 Compilation methods.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"

#include "Compilation.h"

#include "Artifact.h"
#include "Command.h"
#include "Driver.h"

namespace gollvm {
namespace driver {

Compilation::Compilation(Driver &driver,
                         ToolChain &toolchain)
    : driver_(driver),
      toolchain_(toolchain)
{
}

Compilation::~Compilation()
{
  // Clean temp files unless -save-temps is in effect
  if (driver_.args().hasArg(gollvm::options::OPT_save_temps))
    return;
  for (auto tf : tempFileNames_)
    llvm::sys::fs::remove(tf);
}

llvm::opt::OptTable &Compilation::opts() {
  return driver_.opts();
}

llvm::opt::InputArgList &Compilation::args()
{
  return driver_.args();
}

std::string Compilation::firstFileBase()
{
  for (llvm::opt::Arg *arg : driver_.args()) {
    if (arg->getOption().getKind() == llvm::opt::Option::InputClass) {
      if (!strcmp(arg->getValue(), "-"))
        return "-";
      std::string firstFile(arg->getValue());
      size_t dotindex = firstFile.find_last_of(".");
      if (dotindex == std::string::npos)
        continue;
      return firstFile.substr(0, dotindex);
    }
  }
  assert(false);
  return "internal_error";
}

Artifact *Compilation::newArgArtifact(llvm::opt::Arg *arg)
{
  ownedArtifacts_.push_back(std::unique_ptr<Artifact>(new Artifact(arg)));
  return ownedArtifacts_.back().get();
}

Artifact *Compilation::newFileArtifact(const char *path, bool isTempFile)
{
  paths_.push_back(std::string(path));
  const char *fn = paths_.back().c_str();
  if (isTempFile)
    tempFileNames_.push_back(fn);
  ownedArtifacts_.push_back(std::unique_ptr<Artifact>(new Artifact(fn)));
  return ownedArtifacts_.back().get();
}

Artifact *Compilation::createOutputFileArtifact(Action *act)
{
  llvm::opt::InputArgList &args = driver_.args();

  // Honor -o if present
  llvm::opt::Arg *outf = args.getLastArg(gollvm::options::OPT_o);
  if (outf)
    return newArgArtifact(outf);

  // No -o: construct output file name.
  std::string ofn;
  if (act->type() == Action::A_Link) {
    assert(! args.hasArg(gollvm::options::OPT_emit_llvm));
    ofn = "a.out";
  } else {
    ofn = firstFileBase();
    if (args.hasArg(gollvm::options::OPT_emit_llvm)) {
      if (args.hasArg(gollvm::options::OPT_S))
        ofn += ".ll";
      else
        ofn += ".bc";
    } else {
      if (args.hasArg(gollvm::options::OPT_S))
        ofn += ".s";
      else
        ofn += ".o";
    }
  }

  outFileName_ = ofn;
  return newFileArtifact(ofn.c_str(), false);
}

llvm::Optional<Artifact*> Compilation::createTemporaryFileArtifact(Action *act)
{
  llvm::SmallString<128> tempFileName;
  std::error_code tfcEC =
      llvm::sys::fs::createTemporaryFile(act->getName(),
                                         act->resultFileSuffix(),
                                         tempFileName);
  if (tfcEC) {
    llvm::errs() << driver_.progname() << ": error: "
                 << tfcEC.message() << "\n";
    return llvm::None;
  }
  return newFileArtifact(tempFileName.c_str(), true);
}

void Compilation::addCommand(const Action &srcAction,
                             const Tool &creatingTool,
                             const char *executable,
                             llvm::opt::ArgStringList &args)
{
  ownedCommands_.push_back(llvm::make_unique<Command>(srcAction,
                                                      creatingTool,
                                                      executable,
                                                      args));
  commands_.push_back(ownedCommands_.back().get());
}

bool Compilation::executeCommands()
{
  llvm::opt::ArgList &args = driver().args();

  bool hashHashHash = args.hasArg(gollvm::options::OPT__HASH_HASH_HASH);
  for (auto cmd : commands_) {

    // Support -v and/or -###
    if (hashHashHash || args.hasArg(gollvm::options::OPT_v))
      cmd->print(llvm::errs(), hashHashHash);

    // Support -###
    if (hashHashHash)
      continue;

    // Execute.
    std::string errMsg;
    int rc = cmd->execute(&errMsg);
    if (rc != 0) {
      if (!errMsg.empty())
        llvm::errs() << errMsg << "\n";
      return false;
    }
  }

  return true;
}

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