Refactor Subzero initialization and add a browser callback handler.

Handlers are represented as a "compile server" even though
right now it can really only handle a single
compile request.

Then there can be a commandline-based server and a
browser-based server. This server takes over the main
thread. In the browser-based case the server can block,
waiting on bytes to be pushed. This becomes a producer of
bitcode bytes.

The original main thread which did bitcode reading is now
shifted to yet another worker thread, which is then the
consumer of bitcode bytes.

This uses an IRT interface for listening to messages
from the browser:
https://codereview.chromium.org/984713003/

TEST=Build the IRT core nexe w/ the above patch and compile w/ something like:

echo """
readwrite_file objfile /tmp/temp.nexe---gcc.opt.stripped.pexe---.o
rpc StreamInitWithSplit i(4) h(objfile) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) C(4,-O2\x00) * s()
stream_file /usr/local/google/home/jvoung/pexe_tests/gcc.opt.stripped.pexe 65536 1000000000
rpc StreamEnd * i() s() s() s()
echo "pnacl-sz complete"
""" | scons-out/opt-linux-x86-32/staging/sel_universal \
    -a -B scons-out/nacl_irt-x86-32/staging/irt_core.nexe \
    --abort_on_error \
    -- toolchain/linux_x86/pnacl_translator/translator/x86-32/bin/pnacl-sz.nexe

echo """
readwrite_file nexefile /tmp/temp.nexe.tmp
readonly_file objfile0 /tmp/temp.nexe---gcc.opt.stripped.pexe---.o
rpc RunWithSplit i(1) h(objfile0) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(invalid) h(nexefile) *
echo "ld complete"
""" | /usr/local/google/home/nacl3/native_client/scons-out/opt-linux-x86-32/staging/sel_universal \
    --abort_on_error \
    -a -B \
    scons-out/nacl_irt-x86-32/staging/irt_core.nexe \
    -E NACL_IRT_OPEN_RESOURCE_BASE=toolchain/linux_x86/pnacl_translator/translator/x86-32/lib/ \
    -E NACL_IRT_OPEN_RESOURCE_REMAP=libpnacl_irt_shim.a:libpnacl_irt_shim_dummy.a \
    -- toolchain/linux_x86/pnacl_translator/translator/x86-32/bin/ld.nexe

BUG= https://code.google.com/p/nativeclient/issues/detail?id=4091
R=kschimpf@google.com, stichnot@chromium.org

Review URL: https://codereview.chromium.org/997773002
diff --git a/src/IceCompileServer.h b/src/IceCompileServer.h
new file mode 100644
index 0000000..a0a0e7a
--- /dev/null
+++ b/src/IceCompileServer.h
@@ -0,0 +1,84 @@
+//===- subzero/src/IceCompileServer.h - Compile server ----------*- C++ -*-===//
+//
+//                        The Subzero Code Generator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the compile server. Given a compiler implementation,
+// it dispatches compile requests to the implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SUBZERO_SRC_ICECOMPILESERVER_H
+#define SUBZERO_SRC_ICECOMPILESERVER_H
+
+#include "IceCompiler.h"
+#include "IceDefs.h"
+#include "IceGlobalContext.h"
+
+namespace llvm {
+class DataStreamer;
+class raw_fd_ostream;
+};
+
+namespace Ice {
+
+// A CompileServer awaits compile requests, and dispatches the requests
+// to a given Compiler. Each request is paired with an input stream,
+// a context (which has the output stream), and a set of arguments.
+// The CompileServer takes over the current thread to listen to requests,
+// and compile requests are handled on separate threads.
+//
+// Currently, this only handles a single request.
+//
+// When run on the commandline, it receives and therefore dispatches
+// the request immediately.  When run in the browser, it blocks waiting
+// for a request.
+class CompileServer {
+  CompileServer() = delete;
+  CompileServer(const CompileServer &) = delete;
+  CompileServer &operator=(const CompileServer &) = delete;
+
+public:
+  explicit CompileServer(Compiler &Comp) : Comp(Comp) {}
+
+  virtual ~CompileServer() {}
+
+  virtual void run() = 0;
+
+  ErrorCode &getErrorCode() { return LastError; }
+  void transferErrorCode(ErrorCodes Code) { LastError.assign(Code); }
+
+protected:
+  Compiler &getCompiler() const { return Comp; }
+
+  Compiler &Comp;
+  ErrorCode LastError;
+};
+
+// Commandline variant of the compile server.
+class CLCompileServer : public CompileServer {
+  CLCompileServer() = delete;
+  CLCompileServer(const CLCompileServer &) = delete;
+  CLCompileServer &operator=(const CLCompileServer &) = delete;
+
+public:
+  CLCompileServer(Compiler &Comp, int argc, char **argv)
+      : CompileServer(Comp), argc(argc), argv(argv) {}
+
+  ~CLCompileServer() final {}
+
+  void run() final;
+
+private:
+  int argc;
+  char **argv;
+  std::unique_ptr<GlobalContext> Ctx;
+};
+
+} // end of namespace Ice
+
+#endif // SUBZERO_SRC_ICECOMPILESERVER_H