//===-- Compilation.cpp ---------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// 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
