OSDN Git Service

Subzero: Reduce the amount of #ifdef'd code.
[android-x86/external-swiftshader.git] / src / IceCompileServer.cpp
1 //===- subzero/src/IceCompileServer.cpp - Compile server ------------------===//
2 //
3 //                        The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the basic commandline-based compile server.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include <fstream>
15 #include <iostream>
16 #include <thread>
17
18 // Include code to handle converting textual bitcode records to binary (for
19 // INPUT_IS_TEXTUAL_BITCODE).
20 #include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h"
21
22 #include "llvm/Support/FileSystem.h"
23 #include "llvm/Support/raw_os_ostream.h"
24 #include "llvm/Support/Signals.h"
25 #include "llvm/Support/SourceMgr.h"
26 #include "llvm/Support/StreamingMemoryObject.h"
27
28 #include "IceClFlags.h"
29 #include "IceClFlagsExtra.h"
30 #include "IceCompileServer.h"
31 #include "IceELFStreamer.h"
32 #include "IceGlobalContext.h"
33
34 namespace Ice {
35
36 namespace {
37
38 static_assert(!(BuildDefs::textualBitcode() && PNACL_BROWSER_TRANSLATOR),
39               "Can not define INPUT_IS_TEXTUAL_BITCODE when building browswer "
40               "translator");
41
42 // Define a SmallVector backed buffer as a data stream, so that it
43 // can hold the generated binary version of the textual bitcode in the
44 // input file.
45 class TextDataStreamer : public llvm::DataStreamer {
46 public:
47   TextDataStreamer() = default;
48   ~TextDataStreamer() final = default;
49   static TextDataStreamer *create(const IceString &Filename, std::string *Err);
50   size_t GetBytes(unsigned char *Buf, size_t Len) final;
51
52 private:
53   llvm::SmallVector<char, 1024> BitcodeBuffer;
54   size_t Cursor = 0;
55 };
56
57 TextDataStreamer *TextDataStreamer::create(const IceString &Filename,
58                                            std::string *Err) {
59   TextDataStreamer *Streamer = new TextDataStreamer();
60   llvm::raw_string_ostream ErrStrm(*Err);
61   if (std::error_code EC = llvm::readNaClRecordTextAndBuildBitcode(
62           Filename, Streamer->BitcodeBuffer, &ErrStrm)) {
63     ErrStrm << EC.message(); // << "\n";
64     ErrStrm.flush();
65     delete Streamer;
66     return nullptr;
67   }
68   // ErrStrm.flush();
69   return Streamer;
70 }
71
72 size_t TextDataStreamer::GetBytes(unsigned char *Buf, size_t Len) {
73   if (Cursor >= BitcodeBuffer.size())
74     return 0;
75   size_t Remaining = BitcodeBuffer.size();
76   Len = std::min(Len, Remaining);
77   for (size_t i = 0; i < Len; ++i)
78     Buf[i] = BitcodeBuffer[Cursor + i];
79   Cursor += Len;
80   return Len;
81 }
82
83 std::unique_ptr<Ostream> makeStream(const IceString &Filename,
84                                     std::error_code &EC) {
85   if (Filename == "-") {
86     return std::unique_ptr<Ostream>(new llvm::raw_os_ostream(std::cout));
87   } else {
88     return std::unique_ptr<Ostream>(
89         new llvm::raw_fd_ostream(Filename, EC, llvm::sys::fs::F_None));
90   }
91 }
92
93 ErrorCodes getReturnValue(const Ice::ClFlagsExtra &Flags, ErrorCodes Val) {
94   if (Flags.getAlwaysExitSuccess())
95     return EC_None;
96   return Val;
97 }
98
99 } // end of anonymous namespace
100
101 void CLCompileServer::run() {
102   if (BuildDefs::dump()) {
103     llvm::sys::PrintStackTraceOnErrorSignal();
104   }
105   ClFlags::parseFlags(argc, argv);
106   ClFlags Flags;
107   ClFlagsExtra ExtraFlags;
108   ClFlags::getParsedClFlags(Flags);
109   ClFlags::getParsedClFlagsExtra(ExtraFlags);
110
111   std::error_code EC;
112   std::unique_ptr<Ostream> Ls = makeStream(ExtraFlags.getLogFilename(), EC);
113   if (EC) {
114     llvm::report_fatal_error("Unable to open log file");
115   }
116   Ls->SetUnbuffered();
117   std::unique_ptr<Ostream> Os;
118   std::unique_ptr<ELFStreamer> ELFStr;
119   switch (Flags.getOutFileType()) {
120   case FT_Elf: {
121     if (ExtraFlags.getOutputFilename() == "-") {
122       *Ls << "Error: writing binary ELF to stdout is unsupported\n";
123       return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args));
124     }
125     std::unique_ptr<llvm::raw_fd_ostream> FdOs(new llvm::raw_fd_ostream(
126         ExtraFlags.getOutputFilename(), EC, llvm::sys::fs::F_None));
127     if (EC) {
128       *Ls << "Failed to open output file: " << ExtraFlags.getOutputFilename()
129           << ":\n" << EC.message() << "\n";
130       return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args));
131     }
132     ELFStr.reset(new ELFStreamer(*FdOs.get()));
133     Os.reset(FdOs.release());
134     // NaCl sets st_blksize to 0, and LLVM uses that to pick the
135     // default preferred buffer size. Set to something non-zero.
136     Os->SetBufferSize(1 << 14);
137   } break;
138   case FT_Asm:
139   case FT_Iasm: {
140     Os = makeStream(ExtraFlags.getOutputFilename(), EC);
141     if (EC) {
142       *Ls << "Failed to open output file: " << ExtraFlags.getOutputFilename()
143           << ":\n" << EC.message() << "\n";
144       return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args));
145     }
146     Os->SetUnbuffered();
147   } break;
148   }
149
150   IceString StrError;
151   std::unique_ptr<llvm::DataStreamer> InputStream(
152       BuildDefs::textualBitcode()
153           ? TextDataStreamer::create(ExtraFlags.getIRFilename(), &StrError)
154           : llvm::getDataFileStreamer(ExtraFlags.getIRFilename(), &StrError));
155   if (!StrError.empty() || !InputStream) {
156     llvm::SMDiagnostic Err(ExtraFlags.getIRFilename(),
157                            llvm::SourceMgr::DK_Error, StrError);
158     Err.print(ExtraFlags.getAppName().c_str(), *Ls);
159     return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Bitcode));
160   }
161
162   Ctx.reset(
163       new GlobalContext(Ls.get(), Os.get(), Ls.get(), ELFStr.get(), Flags));
164   if (Ctx->getFlags().getNumTranslationThreads() != 0) {
165     std::thread CompileThread([this, &ExtraFlags, &InputStream]() {
166       Ctx->initParserThread();
167       getCompiler().run(ExtraFlags, *Ctx.get(), std::move(InputStream));
168     });
169     CompileThread.join();
170   } else {
171     getCompiler().run(ExtraFlags, *Ctx.get(), std::move(InputStream));
172   }
173   transferErrorCode(getReturnValue(
174       ExtraFlags, static_cast<ErrorCodes>(Ctx->getErrorStatus()->value())));
175 }
176
177 } // end of namespace Ice