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//===----------------------------------------------------------------------===//
99612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
109612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// \file
1192a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// \brief Defines the basic commandline-based compile server.
129612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
1344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung//===----------------------------------------------------------------------===//
1444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
1567f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceCompileServer.h"
1644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
173f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively#include "IceASanInstrumentation.h"
1867f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceClFlags.h"
1967f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceELFStreamer.h"
2067f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceGlobalContext.h"
2154cf1a2f5a2e6c05e6a94c6f0d685b5381ed7261Jim Stichnoth#include "IceRevision.h"
224c16ac0f4f184128060f3b8c3db519f1a6293dfaDavid Sehr#include "LinuxMallocProfiling.h"
2398da96678bc2705d4a37e17b87bbb3c031be9ae0Jim Stichnoth
24b0051dfaca6e957fa62ab61c0ef2a42df7964d37Jim Stichnoth#ifdef __clang__
2598da96678bc2705d4a37e17b87bbb3c031be9ae0Jim Stichnoth#pragma clang diagnostic push
2698da96678bc2705d4a37e17b87bbb3c031be9ae0Jim Stichnoth#pragma clang diagnostic ignored "-Wunused-parameter"
27b0051dfaca6e957fa62ab61c0ef2a42df7964d37Jim Stichnoth#endif // __clang__
28b0051dfaca6e957fa62ab61c0ef2a42df7964d37Jim Stichnoth
29a5b16abfebb1d33fa4b4448f1bda1bf02cc0bd58Jim Stichnoth#ifdef PNACL_LLVM
306f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf#include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h"
31a5b16abfebb1d33fa4b4448f1bda1bf02cc0bd58Jim Stichnoth#endif // PNACL_LLVM
3244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/FileSystem.h"
3344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/raw_os_ostream.h"
34b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung#include "llvm/Support/Signals.h"
3544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/SourceMgr.h"
3644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/StreamingMemoryObject.h"
37b0051dfaca6e957fa62ab61c0ef2a42df7964d37Jim Stichnoth
38b0051dfaca6e957fa62ab61c0ef2a42df7964d37Jim Stichnoth#ifdef __clang__
3998da96678bc2705d4a37e17b87bbb3c031be9ae0Jim Stichnoth#pragma clang diagnostic pop
40b0051dfaca6e957fa62ab61c0ef2a42df7964d37Jim Stichnoth#endif // __clang__
4144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
427e64eaaadcbd40c94deba3f03a571abfaa2fc086Karl Schimpf#include <cstdio>
4367f8de9adf6439881a00d8e0f081918436c71f62John Porto#include <fstream>
4467f8de9adf6439881a00d8e0f081918436c71f62John Porto#include <iostream>
4567f8de9adf6439881a00d8e0f081918436c71f62John Porto#include <thread>
4644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
4744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voungnamespace Ice {
4844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
4944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voungnamespace {
5044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
5157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// Define a SmallVector backed buffer as a data stream, so that it can hold the
5257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// generated binary version of the textual bitcode in the input file.
536f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpfclass TextDataStreamer : public llvm::DataStreamer {
546f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpfpublic:
556f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  TextDataStreamer() = default;
566f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  ~TextDataStreamer() final = default;
57f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth#ifdef PNACL_LLVM
58f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth  using CreateType = TextDataStreamer *;
59a5b16abfebb1d33fa4b4448f1bda1bf02cc0bd58Jim Stichnoth#else  // !PNACL_LLVM
60f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth  using CreateType = std::unique_ptr<TextDataStreamer>;
61f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth#endif // !PNACL_LLVM
62a5b16abfebb1d33fa4b4448f1bda1bf02cc0bd58Jim Stichnoth  static CreateType create(const std::string &Filename, std::string *Err);
636f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  size_t GetBytes(unsigned char *Buf, size_t Len) final;
6420b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth
656f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpfprivate:
666f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  llvm::SmallVector<char, 1024> BitcodeBuffer;
676f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  size_t Cursor = 0;
686f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf};
696f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf
70a5b16abfebb1d33fa4b4448f1bda1bf02cc0bd58Jim StichnothTextDataStreamer::CreateType
71a5b16abfebb1d33fa4b4448f1bda1bf02cc0bd58Jim StichnothTextDataStreamer::create(const std::string &Filename, std::string *Err) {
72f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth#ifdef PNACL_LLVM
736f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  TextDataStreamer *Streamer = new TextDataStreamer();
746f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  llvm::raw_string_ostream ErrStrm(*Err);
756f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  if (std::error_code EC = llvm::readNaClRecordTextAndBuildBitcode(
766f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf          Filename, Streamer->BitcodeBuffer, &ErrStrm)) {
77cb6e95aac252a35c66705fb5e30d3c5e9ba4c1dcKarl Schimpf    ErrStrm << EC.message();
786f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf    ErrStrm.flush();
796f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf    delete Streamer;
806f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf    return nullptr;
816f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  }
82cb6e95aac252a35c66705fb5e30d3c5e9ba4c1dcKarl Schimpf  ErrStrm.flush();
836f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  return Streamer;
84a5b16abfebb1d33fa4b4448f1bda1bf02cc0bd58Jim Stichnoth#else  // !PNACL_LLVM
85f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth  return CreateType();
86f5fdd2360751122d30280173e0d6c9a3ecf2f72eJim Stichnoth#endif // !PNACL_LLVM
876f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf}
886f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf
896f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpfsize_t TextDataStreamer::GetBytes(unsigned char *Buf, size_t Len) {
906f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  if (Cursor >= BitcodeBuffer.size())
916f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf    return 0;
926f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  size_t Remaining = BitcodeBuffer.size();
936f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  Len = std::min(Len, Remaining);
946f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  for (size_t i = 0; i < Len; ++i)
956f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf    Buf[i] = BitcodeBuffer[Cursor + i];
966f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  Cursor += Len;
976f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf  return Len;
986f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf}
996f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf
100467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnothstd::unique_ptr<Ostream> makeStream(const std::string &Filename,
101620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth                                    std::error_code &EC) {
102620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth  if (Filename == "-") {
10344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    return std::unique_ptr<Ostream>(new llvm::raw_os_ostream(std::cout));
104fd07ad08190cbb7c9818e79fab9059eb3ed329d7Jim Stichnoth  } else if (Filename == "/dev/stderr") {
105fd07ad08190cbb7c9818e79fab9059eb3ed329d7Jim Stichnoth    return std::unique_ptr<Ostream>(new llvm::raw_os_ostream(std::cerr));
106620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth  } else {
107620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth    return std::unique_ptr<Ostream>(
108620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth        new llvm::raw_fd_ostream(Filename, EC, llvm::sys::fs::F_None));
10944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  }
11044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung}
11144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
11298ba00666271be1bdcd45b72b3dec04419efe61bJim StichnothErrorCodes getReturnValue(ErrorCodes Val) {
113d46999474d2b4a388e1d8a7c71f06cd4cec51bfcKarl Schimpf  if (getFlags().getAlwaysExitSuccess())
11444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    return EC_None;
11544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  return Val;
11644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung}
11744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
118db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf// Reports fatal error message, and then exits with success status 0.
11948e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnothvoid reportFatalErrorThenExitSuccess(void *UserData, const std::string &Reason,
120db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf                                     bool GenCrashDag) {
121db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf  (void)UserData;
122db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf  (void)GenCrashDag;
123db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf
124db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf  // Note: This code is (mostly) copied from llvm/lib/Support/ErrorHandling.cpp
125db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf
126db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf  // Blast the result out to stderr.  We don't try hard to make sure this
127db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf  // succeeds (e.g. handling EINTR) and we can't use errs() here because
128db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf  // raw ostreams can call report_fatal_error.
129db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf  llvm::SmallVector<char, 64> Buffer;
130db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf  llvm::raw_svector_ostream OS(Buffer);
131db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf  OS << "LLVM ERROR: " << Reason << "\n";
132db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf  llvm::StringRef MessageStr = OS.str();
1334e6ea83aecbae8725af6f8498847ce4cbecbe33bKarl Schimpf  ssize_t Written =
1344e6ea83aecbae8725af6f8498847ce4cbecbe33bKarl Schimpf      std::fwrite(MessageStr.data(), sizeof(char), MessageStr.size(), stderr);
1354e6ea83aecbae8725af6f8498847ce4cbecbe33bKarl Schimpf  (void)Written; // If something went wrong, we deliberately just give up.
136db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf
137db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf  // If we reached here, we are failing ungracefully. Run the interrupt handlers
138db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf  // to make sure any special cleanups get done, in particular that we remove
139db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf  // files registered with RemoveFileOnSignal.
140db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf  llvm::sys::RunInterruptHandlers();
141db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf
142db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf  exit(0);
143db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf}
144db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf
145686f35e569f7fac14d357550faed542de261415bJim Stichnothstruct {
146686f35e569f7fac14d357550faed542de261415bJim Stichnoth  const char *FlagName;
147686f35e569f7fac14d357550faed542de261415bJim Stichnoth  bool FlagValue;
148686f35e569f7fac14d357550faed542de261415bJim Stichnoth} ConditionalBuildAttributes[] = {
149686f35e569f7fac14d357550faed542de261415bJim Stichnoth    {"dump", BuildDefs::dump()},
150686f35e569f7fac14d357550faed542de261415bJim Stichnoth    {"llvm_cl", BuildDefs::llvmCl()},
151686f35e569f7fac14d357550faed542de261415bJim Stichnoth    {"llvm_ir", BuildDefs::llvmIr()},
152686f35e569f7fac14d357550faed542de261415bJim Stichnoth    {"llvm_ir_as_input", BuildDefs::llvmIrAsInput()},
153686f35e569f7fac14d357550faed542de261415bJim Stichnoth    {"minimal_build", BuildDefs::minimal()},
154686f35e569f7fac14d357550faed542de261415bJim Stichnoth    {"browser_mode", BuildDefs::browser()}};
155686f35e569f7fac14d357550faed542de261415bJim Stichnoth
156686f35e569f7fac14d357550faed542de261415bJim Stichnoth/// Dumps values of build attributes to Stream if Stream is non-null.
157686f35e569f7fac14d357550faed542de261415bJim Stichnothvoid dumpBuildAttributes(Ostream &Str) {
158686f35e569f7fac14d357550faed542de261415bJim Stichnoth// List the supported targets.
15984ea9a70bc14ec528d8d377462317fd46660f3deJim Stichnoth#define SUBZERO_TARGET(TARGET) Str << "target_" XSTRINGIFY(TARGET) "\n";
160999a22f0bbd828c9fc711b6100194f0678d1a08cJim Stichnoth#include "SZTargets.def"
161686f35e569f7fac14d357550faed542de261415bJim Stichnoth  const char *Prefix[2] = {"no", "allow"};
162686f35e569f7fac14d357550faed542de261415bJim Stichnoth  for (size_t i = 0; i < llvm::array_lengthof(ConditionalBuildAttributes);
163686f35e569f7fac14d357550faed542de261415bJim Stichnoth       ++i) {
164686f35e569f7fac14d357550faed542de261415bJim Stichnoth    const auto &A = ConditionalBuildAttributes[i];
165686f35e569f7fac14d357550faed542de261415bJim Stichnoth    Str << Prefix[A.FlagValue] << "_" << A.FlagName << "\n";
166686f35e569f7fac14d357550faed542de261415bJim Stichnoth  }
16754cf1a2f5a2e6c05e6a94c6f0d685b5381ed7261Jim Stichnoth  Str << "revision_" << getSubzeroRevision() << "\n";
168686f35e569f7fac14d357550faed542de261415bJim Stichnoth}
169686f35e569f7fac14d357550faed542de261415bJim Stichnoth
17044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung} // end of anonymous namespace
17144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
17244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voungvoid CLCompileServer::run() {
17320b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth  if (BuildDefs::dump()) {
174efdf412032f7622a0663696896708d75b82e92f6Jim Stichnoth#ifdef PNACL_LLVM
175b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung    llvm::sys::PrintStackTraceOnErrorSignal();
176efdf412032f7622a0663696896708d75b82e92f6Jim Stichnoth#else  // !PNACL_LLVM
177efdf412032f7622a0663696896708d75b82e92f6Jim Stichnoth    llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
178efdf412032f7622a0663696896708d75b82e92f6Jim Stichnoth#endif // !PNACL_LLVM
179b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung  }
18044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  ClFlags::parseFlags(argc, argv);
181d46999474d2b4a388e1d8a7c71f06cd4cec51bfcKarl Schimpf  ClFlags &Flags = ClFlags::Flags;
18244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  ClFlags::getParsedClFlags(Flags);
18344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
184db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf  // Override report_fatal_error if we want to exit with 0 status.
185c5bc5cb33580557062574416794244a09ba99130John Porto  if (Flags.getAlwaysExitSuccess())
186db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf    llvm::install_fatal_error_handler(reportFatalErrorThenExitSuccess, this);
187db2fd9c0c3e5cad4c5a99497e226f3ec970cbcadKarl Schimpf
188620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth  std::error_code EC;
189c5bc5cb33580557062574416794244a09ba99130John Porto  std::unique_ptr<Ostream> Ls = makeStream(Flags.getLogFilename(), EC);
190620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth  if (EC) {
191620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth    llvm::report_fatal_error("Unable to open log file");
192620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth  }
19344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  Ls->SetUnbuffered();
1944c16ac0f4f184128060f3b8c3db519f1a6293dfaDavid Sehr  Ice::LinuxMallocProfiling _(Flags.getNumTranslationThreads(), Ls.get());
1954c16ac0f4f184128060f3b8c3db519f1a6293dfaDavid Sehr
19644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  std::unique_ptr<Ostream> Os;
19744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  std::unique_ptr<ELFStreamer> ELFStr;
19844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  switch (Flags.getOutFileType()) {
19944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  case FT_Elf: {
200c5bc5cb33580557062574416794244a09ba99130John Porto    if (Flags.getOutputFilename() == "-" && !Flags.getGenerateBuildAtts()) {
20144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung      *Ls << "Error: writing binary ELF to stdout is unsupported\n";
20298ba00666271be1bdcd45b72b3dec04419efe61bJim Stichnoth      return transferErrorCode(getReturnValue(Ice::EC_Args));
20344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    }
20444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    std::unique_ptr<llvm::raw_fd_ostream> FdOs(new llvm::raw_fd_ostream(
205c5bc5cb33580557062574416794244a09ba99130John Porto        Flags.getOutputFilename(), EC, llvm::sys::fs::F_None));
20644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    if (EC) {
207c5bc5cb33580557062574416794244a09ba99130John Porto      *Ls << "Failed to open output file: " << Flags.getOutputFilename()
20844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung          << ":\n" << EC.message() << "\n";
20998ba00666271be1bdcd45b72b3dec04419efe61bJim Stichnoth      return transferErrorCode(getReturnValue(Ice::EC_Args));
21044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    }
2113e376471fcd706be0e224a4f69fc31b7b7e4ee58Nicolas Capens    ELFStr.reset(new ELFFileStreamer(*FdOs.get()));
21244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    Os.reset(FdOs.release());
21357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull    // NaCl sets st_blksize to 0, and LLVM uses that to pick the default
21457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull    // preferred buffer size. Set to something non-zero.
21544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    Os->SetBufferSize(1 << 14);
21644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  } break;
21744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  case FT_Asm:
21844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  case FT_Iasm: {
219c5bc5cb33580557062574416794244a09ba99130John Porto    Os = makeStream(Flags.getOutputFilename(), EC);
220620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth    if (EC) {
221c5bc5cb33580557062574416794244a09ba99130John Porto      *Ls << "Failed to open output file: " << Flags.getOutputFilename()
222620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth          << ":\n" << EC.message() << "\n";
22398ba00666271be1bdcd45b72b3dec04419efe61bJim Stichnoth      return transferErrorCode(getReturnValue(Ice::EC_Args));
224620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth    }
22544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    Os->SetUnbuffered();
22644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  } break;
22744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  }
22844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
229c5bc5cb33580557062574416794244a09ba99130John Porto  if (BuildDefs::minimal() && Flags.getBitcodeAsText())
230cb6e95aac252a35c66705fb5e30d3c5e9ba4c1dcKarl Schimpf    llvm::report_fatal_error("Can't specify 'bitcode-as-text' flag in "
231cb6e95aac252a35c66705fb5e30d3c5e9ba4c1dcKarl Schimpf                             "minimal build");
232cb6e95aac252a35c66705fb5e30d3c5e9ba4c1dcKarl Schimpf
233467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth  std::string StrError;
23444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  std::unique_ptr<llvm::DataStreamer> InputStream(
235c5bc5cb33580557062574416794244a09ba99130John Porto      (!BuildDefs::minimal() && Flags.getBitcodeAsText())
236c5bc5cb33580557062574416794244a09ba99130John Porto          ? TextDataStreamer::create(Flags.getIRFilename(), &StrError)
237c5bc5cb33580557062574416794244a09ba99130John Porto          : llvm::getDataFileStreamer(Flags.getIRFilename(), &StrError));
23844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  if (!StrError.empty() || !InputStream) {
239c5bc5cb33580557062574416794244a09ba99130John Porto    llvm::SMDiagnostic Err(Flags.getIRFilename(), llvm::SourceMgr::DK_Error,
240c5bc5cb33580557062574416794244a09ba99130John Porto                           StrError);
241c5bc5cb33580557062574416794244a09ba99130John Porto    Err.print(Flags.getAppName().c_str(), *Ls);
24298ba00666271be1bdcd45b72b3dec04419efe61bJim Stichnoth    return transferErrorCode(getReturnValue(Ice::EC_Bitcode));
24344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  }
24444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
245c5bc5cb33580557062574416794244a09ba99130John Porto  if (Flags.getGenerateBuildAtts()) {
246686f35e569f7fac14d357550faed542de261415bJim Stichnoth    dumpBuildAttributes(*Os.get());
24798ba00666271be1bdcd45b72b3dec04419efe61bJim Stichnoth    return transferErrorCode(getReturnValue(Ice::EC_None));
248686f35e569f7fac14d357550faed542de261415bJim Stichnoth  }
249686f35e569f7fac14d357550faed542de261415bJim Stichnoth
25098ba00666271be1bdcd45b72b3dec04419efe61bJim Stichnoth  Ctx.reset(new GlobalContext(Ls.get(), Os.get(), Ls.get(), ELFStr.get()));
251aab7099ee8e86bdadff39106fec0a970b773a535Thomas Lively
252aab7099ee8e86bdadff39106fec0a970b773a535Thomas Lively  if (!BuildDefs::minimal() && getFlags().getSanitizeAddresses()) {
2533f5cb6f3ea08dae995108130ffe8af8ec1bcbcd2Thomas Lively    std::unique_ptr<Instrumentation> Instr(new ASanInstrumentation(Ctx.get()));
254aab7099ee8e86bdadff39106fec0a970b773a535Thomas Lively    Ctx->setInstrumentation(std::move(Instr));
255aab7099ee8e86bdadff39106fec0a970b773a535Thomas Lively  }
256aab7099ee8e86bdadff39106fec0a970b773a535Thomas Lively
257d46999474d2b4a388e1d8a7c71f06cd4cec51bfcKarl Schimpf  if (getFlags().getNumTranslationThreads() != 0) {
258c5bc5cb33580557062574416794244a09ba99130John Porto    std::thread CompileThread([this, &Flags, &InputStream]() {
25944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung      Ctx->initParserThread();
260c5bc5cb33580557062574416794244a09ba99130John Porto      getCompiler().run(Flags, *Ctx.get(), std::move(InputStream));
26144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    });
26244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung    CompileThread.join();
26344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  } else {
264c5bc5cb33580557062574416794244a09ba99130John Porto    getCompiler().run(Flags, *Ctx.get(), std::move(InputStream));
26544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung  }
26698ba00666271be1bdcd45b72b3dec04419efe61bJim Stichnoth  transferErrorCode(
26798ba00666271be1bdcd45b72b3dec04419efe61bJim Stichnoth      getReturnValue(static_cast<ErrorCodes>(Ctx->getErrorStatus()->value())));
2689f9aa2c1953db5253dab1216cf44a9cbcb7cb176Jim Stichnoth  Ctx->dumpConstantLookupCounts();
269467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth  Ctx->dumpStrings();
27044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung}
27144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung
27244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung} // end of namespace Ice
273