IceCompileServer.cpp revision 44c3a8046f4c81f9b4476f8c3c72723b584c312d
144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung//===- subzero/src/IceCompileServer.cpp - Compile server ------------------===//
244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung//
344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung//                        The Subzero Code Generator
444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung//
544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung// This file is distributed under the University of Illinois Open Source
644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung// License. See LICENSE.TXT for details.
744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung//
844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung//===----------------------------------------------------------------------===//
944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung//
1044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung// This file defines the basic commandline-based compile server.
1144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung//
1244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung//===----------------------------------------------------------------------===//
1344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
1444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include <fstream>
1544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include <iostream>
1644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include <thread>
1744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
1844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/FileSystem.h"
1944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/raw_os_ostream.h"
2044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/SourceMgr.h"
2144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/StreamingMemoryObject.h"
2244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
2344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "IceClFlags.h"
2444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "IceClFlagsExtra.h"
2544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "IceCompileServer.h"
2644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "IceELFStreamer.h"
2744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "IceGlobalContext.h"
2844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
2944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voungnamespace Ice {
3044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
3144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voungnamespace {
3244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
3344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voungstd::unique_ptr<Ostream> getStream(const IceString &Filename) {
3444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  std::ofstream Ofs;
3544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  if (Filename != "-") {
3644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    Ofs.open(Filename.c_str(), std::ofstream::out);
3744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    return std::unique_ptr<Ostream>(new llvm::raw_os_ostream(Ofs));
3844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  } else {
3944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    return std::unique_ptr<Ostream>(new llvm::raw_os_ostream(std::cout));
4044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  }
4144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung}
4244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
4344c3a8046f4c81f9b4476f8c3c72723b584c312dJan VoungErrorCodes getReturnValue(const Ice::ClFlagsExtra &Flags, ErrorCodes Val) {
4444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  if (Flags.getAlwaysExitSuccess())
4544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    return EC_None;
4644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  return Val;
4744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung}
4844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
4944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung} // end of anonymous namespace
5044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
5144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voungvoid CLCompileServer::run() {
5244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  ClFlags::parseFlags(argc, argv);
5344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  ClFlags Flags;
5444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  ClFlagsExtra ExtraFlags;
5544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  ClFlags::getParsedClFlags(Flags);
5644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  ClFlags::getParsedClFlagsExtra(ExtraFlags);
5744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
5844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  std::unique_ptr<Ostream> Ls = getStream(ExtraFlags.getLogFilename());
5944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  Ls->SetUnbuffered();
6044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  std::unique_ptr<Ostream> Os;
6144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  std::unique_ptr<ELFStreamer> ELFStr;
6244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  switch (Flags.getOutFileType()) {
6344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  case FT_Elf: {
6444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    if (ExtraFlags.getOutputFilename() == "-") {
6544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung      *Ls << "Error: writing binary ELF to stdout is unsupported\n";
6644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung      return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args));
6744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    }
6844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    std::error_code EC;
6944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    std::unique_ptr<llvm::raw_fd_ostream> FdOs(new llvm::raw_fd_ostream(
7044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung        ExtraFlags.getOutputFilename(), EC, llvm::sys::fs::F_None));
7144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    if (EC) {
7244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung      *Ls << "Failed to open output file: " << ExtraFlags.getOutputFilename()
7344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung          << ":\n" << EC.message() << "\n";
7444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung      return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args));
7544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    }
7644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    ELFStr.reset(new ELFStreamer(*FdOs.get()));
7744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    Os.reset(FdOs.release());
7844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    // NaCl sets st_blksize to 0, and LLVM uses that to pick the
7944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    // default preferred buffer size. Set to something non-zero.
8044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    Os->SetBufferSize(1 << 14);
8144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  } break;
8244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  case FT_Asm:
8344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  case FT_Iasm: {
8444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    Os = getStream(ExtraFlags.getOutputFilename());
8544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    Os->SetUnbuffered();
8644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  } break;
8744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  }
8844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
8944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  IceString StrError;
9044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  std::unique_ptr<llvm::DataStreamer> InputStream(
9144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung      llvm::getDataFileStreamer(ExtraFlags.getIRFilename(), &StrError));
9244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  if (!StrError.empty() || !InputStream) {
9344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    llvm::SMDiagnostic Err(ExtraFlags.getIRFilename(),
9444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung                           llvm::SourceMgr::DK_Error, StrError);
9544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    Err.print(ExtraFlags.getAppName().c_str(), *Ls);
9644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Bitcode));
9744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  }
9844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
9944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  Ctx.reset(new GlobalContext(Ls.get(), Os.get(), ELFStr.get(), Flags));
10044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  if (Ctx->getFlags().getNumTranslationThreads() != 0) {
10144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    std::thread CompileThread([this, &ExtraFlags, &InputStream]() {
10244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung      Ctx->initParserThread();
10344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung      getCompiler().run(ExtraFlags, *Ctx.get(), std::move(InputStream));
10444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    });
10544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    CompileThread.join();
10644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  } else {
10744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    getCompiler().run(ExtraFlags, *Ctx.get(), std::move(InputStream));
10844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  }
10944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  transferErrorCode(getReturnValue(
11044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung      ExtraFlags, static_cast<ErrorCodes>(Ctx->getErrorStatus()->value())));
11144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung}
11244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
11344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung} // end of namespace Ice
114