IceCompileServer.cpp revision 67f8de9adf6439881a00d8e0f081918436c71f62
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
1467f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceCompileServer.h"
1544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
1667f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceClFlags.h"
1767f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceClFlagsExtra.h"
1867f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceELFStreamer.h"
1967f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceGlobalContext.h"
206f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf// Include code to handle converting textual bitcode records to binary (for
216f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf// INPUT_IS_TEXTUAL_BITCODE).
226f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf#include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h"
2344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/FileSystem.h"
2444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/raw_os_ostream.h"
25b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung#include "llvm/Support/Signals.h"
2644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/SourceMgr.h"
2744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/StreamingMemoryObject.h"
2844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
2967f8de9adf6439881a00d8e0f081918436c71f62John Porto#include <fstream>
3067f8de9adf6439881a00d8e0f081918436c71f62John Porto#include <iostream>
3167f8de9adf6439881a00d8e0f081918436c71f62John Porto#include <thread>
3244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
3344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voungnamespace Ice {
3444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
3544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voungnamespace {
3644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
3720b71f5890ee8651983b126c5978594a01e0af96Jim Stichnothstatic_assert(!(BuildDefs::textualBitcode() && PNACL_BROWSER_TRANSLATOR),
3820b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth              "Can not define INPUT_IS_TEXTUAL_BITCODE when building browswer "
3920b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth              "translator");
406f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf
416f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf// Define a SmallVector backed buffer as a data stream, so that it
426f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf// can hold the generated binary version of the textual bitcode in the
436f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf// input file.
446f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpfclass TextDataStreamer : public llvm::DataStreamer {
456f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpfpublic:
466f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  TextDataStreamer() = default;
476f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  ~TextDataStreamer() final = default;
486f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  static TextDataStreamer *create(const IceString &Filename, std::string *Err);
496f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  size_t GetBytes(unsigned char *Buf, size_t Len) final;
5020b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth
516f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpfprivate:
526f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  llvm::SmallVector<char, 1024> BitcodeBuffer;
536f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  size_t Cursor = 0;
546f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf};
556f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf
566f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl SchimpfTextDataStreamer *TextDataStreamer::create(const IceString &Filename,
576f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf                                           std::string *Err) {
586f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  TextDataStreamer *Streamer = new TextDataStreamer();
596f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  llvm::raw_string_ostream ErrStrm(*Err);
606f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  if (std::error_code EC = llvm::readNaClRecordTextAndBuildBitcode(
616f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf          Filename, Streamer->BitcodeBuffer, &ErrStrm)) {
6274cd883a0b3ccb0920e5990ed860b1862ac73090Karl Schimpf    ErrStrm << EC.message(); // << "\n";
636f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf    ErrStrm.flush();
646f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf    delete Streamer;
656f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf    return nullptr;
666f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  }
6774cd883a0b3ccb0920e5990ed860b1862ac73090Karl Schimpf  // ErrStrm.flush();
686f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  return Streamer;
696f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf}
706f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf
716f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpfsize_t TextDataStreamer::GetBytes(unsigned char *Buf, size_t Len) {
726f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  if (Cursor >= BitcodeBuffer.size())
736f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf    return 0;
746f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  size_t Remaining = BitcodeBuffer.size();
756f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  Len = std::min(Len, Remaining);
766f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  for (size_t i = 0; i < Len; ++i)
776f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf    Buf[i] = BitcodeBuffer[Cursor + i];
786f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  Cursor += Len;
796f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  return Len;
806f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf}
816f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf
82620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnothstd::unique_ptr<Ostream> makeStream(const IceString &Filename,
83620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth                                    std::error_code &EC) {
84620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth  if (Filename == "-") {
8544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    return std::unique_ptr<Ostream>(new llvm::raw_os_ostream(std::cout));
86620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth  } else {
87620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth    return std::unique_ptr<Ostream>(
88620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth        new llvm::raw_fd_ostream(Filename, EC, llvm::sys::fs::F_None));
8944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  }
9044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung}
9144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
9244c3a8046f4c81f9b4476f8c3c72723b584c312dJan VoungErrorCodes getReturnValue(const Ice::ClFlagsExtra &Flags, ErrorCodes Val) {
9344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  if (Flags.getAlwaysExitSuccess())
9444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    return EC_None;
9544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  return Val;
9644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung}
9744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
9844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung} // end of anonymous namespace
9944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
10044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voungvoid CLCompileServer::run() {
10120b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth  if (BuildDefs::dump()) {
102b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung    llvm::sys::PrintStackTraceOnErrorSignal();
103b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  }
10444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  ClFlags::parseFlags(argc, argv);
10544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  ClFlags Flags;
10644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  ClFlagsExtra ExtraFlags;
10744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  ClFlags::getParsedClFlags(Flags);
10844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  ClFlags::getParsedClFlagsExtra(ExtraFlags);
10944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
110620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth  std::error_code EC;
111620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth  std::unique_ptr<Ostream> Ls = makeStream(ExtraFlags.getLogFilename(), EC);
112620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth  if (EC) {
113620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth    llvm::report_fatal_error("Unable to open log file");
114620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth  }
11544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  Ls->SetUnbuffered();
11644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  std::unique_ptr<Ostream> Os;
11744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  std::unique_ptr<ELFStreamer> ELFStr;
11844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  switch (Flags.getOutFileType()) {
11944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  case FT_Elf: {
12044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    if (ExtraFlags.getOutputFilename() == "-") {
12144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung      *Ls << "Error: writing binary ELF to stdout is unsupported\n";
12244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung      return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args));
12344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    }
12444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    std::unique_ptr<llvm::raw_fd_ostream> FdOs(new llvm::raw_fd_ostream(
12544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung        ExtraFlags.getOutputFilename(), EC, llvm::sys::fs::F_None));
12644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    if (EC) {
12744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung      *Ls << "Failed to open output file: " << ExtraFlags.getOutputFilename()
12844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung          << ":\n" << EC.message() << "\n";
12944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung      return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args));
13044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    }
13144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    ELFStr.reset(new ELFStreamer(*FdOs.get()));
13244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    Os.reset(FdOs.release());
13344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    // NaCl sets st_blksize to 0, and LLVM uses that to pick the
13444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    // default preferred buffer size. Set to something non-zero.
13544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    Os->SetBufferSize(1 << 14);
13644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  } break;
13744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  case FT_Asm:
13844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  case FT_Iasm: {
139620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth    Os = makeStream(ExtraFlags.getOutputFilename(), EC);
140620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth    if (EC) {
141620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth      *Ls << "Failed to open output file: " << ExtraFlags.getOutputFilename()
142620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth          << ":\n" << EC.message() << "\n";
143620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth      return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args));
144620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth    }
14544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    Os->SetUnbuffered();
14644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  } break;
14744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  }
14844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
14944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  IceString StrError;
15044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  std::unique_ptr<llvm::DataStreamer> InputStream(
15120b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth      BuildDefs::textualBitcode()
15220b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth          ? TextDataStreamer::create(ExtraFlags.getIRFilename(), &StrError)
15320b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth          : llvm::getDataFileStreamer(ExtraFlags.getIRFilename(), &StrError));
15444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  if (!StrError.empty() || !InputStream) {
15544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    llvm::SMDiagnostic Err(ExtraFlags.getIRFilename(),
15644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung                           llvm::SourceMgr::DK_Error, StrError);
15744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    Err.print(ExtraFlags.getAppName().c_str(), *Ls);
15844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Bitcode));
15944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  }
16044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
161620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth  Ctx.reset(
162620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth      new GlobalContext(Ls.get(), Os.get(), Ls.get(), ELFStr.get(), Flags));
16344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  if (Ctx->getFlags().getNumTranslationThreads() != 0) {
16444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    std::thread CompileThread([this, &ExtraFlags, &InputStream]() {
16544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung      Ctx->initParserThread();
16644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung      getCompiler().run(ExtraFlags, *Ctx.get(), std::move(InputStream));
16744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    });
16844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    CompileThread.join();
16944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  } else {
17044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    getCompiler().run(ExtraFlags, *Ctx.get(), std::move(InputStream));
17144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  }
17244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  transferErrorCode(getReturnValue(
17344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung      ExtraFlags, static_cast<ErrorCodes>(Ctx->getErrorStatus()->value())));
17444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung}
17544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
17644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung} // end of namespace Ice
177