//===- subzero/src/IceBrowserCompileServer.cpp - Browser compile server ---===//
//
//                        The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the browser-based compile server.
//
//===----------------------------------------------------------------------===//

// Can only compile this with the NaCl compiler (needs irt.h, and the
// unsandboxed LLVM build using the trusted compiler does not have irt.h).
#if PNACL_BROWSER_TRANSLATOR

#include <cstring>
#include <irt.h>
#include <irt_dev.h>
#include <pthread.h>
#include <thread>

#include "llvm/Support/QueueStreamer.h"

#include "IceBrowserCompileServer.h"

namespace Ice {

// Create C wrappers around callback handlers for the IRT interface.
namespace {

BrowserCompileServer *gCompileServer;
struct nacl_irt_private_pnacl_translator_compile gIRTFuncs;

void getIRTInterfaces() {
  size_t QueryResult =
      nacl_interface_query(NACL_IRT_PRIVATE_PNACL_TRANSLATOR_COMPILE_v0_1,
                           &gIRTFuncs, sizeof(gIRTFuncs));
  if (QueryResult != sizeof(gIRTFuncs))
    llvm::report_fatal_error("Failed to get translator compile IRT interface");
}

char *onInitCallback(uint32_t NumThreads, int *ObjFileFDs,
                     size_t ObjFileFDCount, char **CLArgs, size_t CLArgsLen) {
  if (ObjFileFDCount < 1) {
    std::string Buffer;
    llvm::raw_string_ostream StrBuf(Buffer);
    StrBuf << "Invalid number of FDs for onInitCallback " << ObjFileFDCount
           << "\n";
    return strdup(StrBuf.str().c_str());
  }
  int ObjFileFD = ObjFileFDs[0];
  if (ObjFileFD < 0) {
    std::string Buffer;
    llvm::raw_string_ostream StrBuf(Buffer);
    StrBuf << "Invalid FD given for onInitCallback " << ObjFileFD << "\n";
    return strdup(StrBuf.str().c_str());
  }
  // CLArgs is almost an "argv", but is missing the argv[0] program name.
  std::vector<char *> Argv;
  char ProgramName[] = "pnacl-sz.nexe";
  Argv.reserve(CLArgsLen + 1);
  Argv.push_back(ProgramName);
  for (size_t i = 0; i < CLArgsLen; ++i) {
    Argv.push_back(CLArgs[i]);
  }
  // NOTE: strings pointed to by argv are owned by the caller, but we parse
  // here before returning and don't store them.
  gCompileServer->getParsedFlags(NumThreads, Argv.size(), Argv.data());
  gCompileServer->startCompileThread(ObjFileFD);
  return nullptr;
}

int onDataCallback(const void *Data, size_t NumBytes) {
  return gCompileServer->pushInputBytes(Data, NumBytes) ? 1 : 0;
}

char *onEndCallback() {
  gCompileServer->endInputStream();
  gCompileServer->waitForCompileThread();
  // TODO(jvoung): Also return UMA data.
  if (gCompileServer->getErrorCode().value()) {
    const std::string Error = gCompileServer->getErrorStream().getContents();
    return strdup(Error.empty() ? "Some error occurred" : Error.c_str());
  }
  return nullptr;
}

struct nacl_irt_pnacl_compile_funcs SubzeroCallbacks {
  &onInitCallback, &onDataCallback, &onEndCallback
};

std::unique_ptr<llvm::raw_fd_ostream> getOutputStream(int FD) {
  if (FD <= 0)
    llvm::report_fatal_error("Invalid output FD");
  const bool CloseOnDtor = true;
  const bool Unbuffered = false;
  return std::unique_ptr<llvm::raw_fd_ostream>(
      new llvm::raw_fd_ostream(FD, CloseOnDtor, Unbuffered));
}

void fatalErrorHandler(void *UserData, const std::string &Reason,
                       bool GenCrashDialog) {
  BrowserCompileServer *Server =
      reinterpret_cast<BrowserCompileServer *>(UserData);
  Server->setFatalError(Reason);
  // Only kill the current thread instead of the whole process.
  // We need the server thread to remain alive in order to respond with the
  // error message.
  // We could also try to pthread_kill all other worker threads, but
  // pthread_kill / raising signals is not supported by NaCl.
  // We'll have to assume that the worker/emitter threads will be well behaved
  // after a fatal error in other threads, and either get stuck waiting
  // on input from a previous stage, or also call report_fatal_error.
  pthread_exit(0);
}

} // end of anonymous namespace

BrowserCompileServer::~BrowserCompileServer() = default;

void BrowserCompileServer::run() {
  gCompileServer = this;
  getIRTInterfaces();
  gIRTFuncs.serve_translate_request(&SubzeroCallbacks);
}

void BrowserCompileServer::getParsedFlags(uint32_t NumThreads, int argc,
                                          char **argv) {
  ClFlags::parseFlags(argc, argv);
  ClFlags::getParsedClFlags(Flags);
  ClFlags::getParsedClFlagsExtra(ExtraFlags);
  // Set some defaults which aren't specified via the argv string.
  Flags.setNumTranslationThreads(NumThreads);
  Flags.setUseSandboxing(true);
  Flags.setOutFileType(FT_Elf);
  // TODO(jvoung): allow setting different target arches.
  Flags.setTargetArch(Target_X8632);
  ExtraFlags.setBuildOnRead(true);
  ExtraFlags.setInputFileFormat(llvm::PNaClFormat);
}

bool BrowserCompileServer::pushInputBytes(const void *Data, size_t NumBytes) {
  // If there was an earlier error, do not attempt to push bytes to
  // the QueueStreamer. Otherwise the thread could become blocked.
  if (HadError.load())
    return true;
  return InputStream->PutBytes(
             const_cast<unsigned char *>(
                 reinterpret_cast<const unsigned char *>(Data)),
             NumBytes) != NumBytes;
}

void BrowserCompileServer::setFatalError(const IceString &Reason) {
  HadError.store(true);
  Ctx->getStrError() << Reason;
  // Make sure that the QueueStreamer is not stuck by signaling an early end.
  InputStream->SetDone();
}

ErrorCode &BrowserCompileServer::getErrorCode() {
  if (HadError.load()) {
    // HadError means report_fatal_error is called. Make sure that the
    // LastError is not EC_None. We don't know the type of error so
    // just pick some error category.
    LastError.assign(EC_Translation);
  }
  return LastError;
}

void BrowserCompileServer::endInputStream() { InputStream->SetDone(); }

void BrowserCompileServer::startCompileThread(int ObjFD) {
  InputStream = new llvm::QueueStreamer();
  LogStream = getOutputStream(STDOUT_FILENO);
  LogStream->SetUnbuffered();
  EmitStream = getOutputStream(ObjFD);
  EmitStream->SetBufferSize(1 << 14);
  std::unique_ptr<StringStream> ErrStrm(new StringStream());
  ErrorStream = std::move(ErrStrm);
  ELFStream.reset(new ELFStreamer(*EmitStream.get()));
  Ctx.reset(new GlobalContext(LogStream.get(), EmitStream.get(),
                              &ErrorStream->getStream(), ELFStream.get(),
                              Flags));
  CompileThread = std::thread([this]() {
    llvm::install_fatal_error_handler(fatalErrorHandler, this);
    Ctx->initParserThread();
    this->getCompiler().run(ExtraFlags, *Ctx.get(),
                            // Retain original reference, but the compiler
                            // (LLVM's MemoryObject) wants to handle deletion.
                            std::unique_ptr<llvm::DataStreamer>(InputStream));
  });
}

} // end of namespace Ice

#endif // PNACL_BROWSER_TRANSLATOR
