blob: 4123e40423c333fc5082168408414797df333127 [file] [log] [blame]
//===-- 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"
#include <sstream>
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::createFakeFileArtifact(Action *act)
{
std::stringstream s;
s << "/tmp/out." << act->getName() << "." << paths_.size();
std::string path(s.str());
paths_.push_back(std::string(path));
const char *fn = paths_.back().c_str();
ownedArtifacts_.push_back(std::unique_ptr<Artifact>(new Artifact(fn)));
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(std::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