blob: b7bc72b7ba15eefc937e8d657955ddbaa3eefb63 [file] [log] [blame]
Jan Voung44c3a802015-03-27 16:29:08 -07001//===- 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//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
11/// This file defines the basic commandline-based compile server.
12///
Jan Voung44c3a802015-03-27 16:29:08 -070013//===----------------------------------------------------------------------===//
14
John Porto67f8de92015-06-25 10:14:17 -070015#include "IceCompileServer.h"
Jan Voung44c3a802015-03-27 16:29:08 -070016
John Porto67f8de92015-06-25 10:14:17 -070017#include "IceClFlags.h"
18#include "IceClFlagsExtra.h"
19#include "IceELFStreamer.h"
20#include "IceGlobalContext.h"
Jim Stichnoth98da9662015-06-27 06:38:08 -070021
22#pragma clang diagnostic push
23#pragma clang diagnostic ignored "-Wunused-parameter"
Karl Schimpf6f9ba112015-06-22 13:20:23 -070024#include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h"
Jan Voung44c3a802015-03-27 16:29:08 -070025#include "llvm/Support/FileSystem.h"
26#include "llvm/Support/raw_os_ostream.h"
Jan Voungb2d50842015-05-12 09:53:50 -070027#include "llvm/Support/Signals.h"
Jan Voung44c3a802015-03-27 16:29:08 -070028#include "llvm/Support/SourceMgr.h"
29#include "llvm/Support/StreamingMemoryObject.h"
Jim Stichnoth98da9662015-06-27 06:38:08 -070030#pragma clang diagnostic pop
Jan Voung44c3a802015-03-27 16:29:08 -070031
John Porto67f8de92015-06-25 10:14:17 -070032#include <fstream>
33#include <iostream>
34#include <thread>
Jan Voung44c3a802015-03-27 16:29:08 -070035
36namespace Ice {
37
38namespace {
39
Karl Schimpf6f9ba112015-06-22 13:20:23 -070040// Define a SmallVector backed buffer as a data stream, so that it
41// can hold the generated binary version of the textual bitcode in the
42// input file.
43class TextDataStreamer : public llvm::DataStreamer {
44public:
45 TextDataStreamer() = default;
46 ~TextDataStreamer() final = default;
47 static TextDataStreamer *create(const IceString &Filename, std::string *Err);
48 size_t GetBytes(unsigned char *Buf, size_t Len) final;
Jim Stichnoth20b71f52015-06-24 15:52:24 -070049
Karl Schimpf6f9ba112015-06-22 13:20:23 -070050private:
51 llvm::SmallVector<char, 1024> BitcodeBuffer;
52 size_t Cursor = 0;
53};
54
55TextDataStreamer *TextDataStreamer::create(const IceString &Filename,
56 std::string *Err) {
57 TextDataStreamer *Streamer = new TextDataStreamer();
58 llvm::raw_string_ostream ErrStrm(*Err);
59 if (std::error_code EC = llvm::readNaClRecordTextAndBuildBitcode(
60 Filename, Streamer->BitcodeBuffer, &ErrStrm)) {
Karl Schimpfcb6e95a2015-07-23 09:10:03 -070061 ErrStrm << EC.message();
Karl Schimpf6f9ba112015-06-22 13:20:23 -070062 ErrStrm.flush();
63 delete Streamer;
64 return nullptr;
65 }
Karl Schimpfcb6e95a2015-07-23 09:10:03 -070066 ErrStrm.flush();
Karl Schimpf6f9ba112015-06-22 13:20:23 -070067 return Streamer;
68}
69
70size_t TextDataStreamer::GetBytes(unsigned char *Buf, size_t Len) {
71 if (Cursor >= BitcodeBuffer.size())
72 return 0;
73 size_t Remaining = BitcodeBuffer.size();
74 Len = std::min(Len, Remaining);
75 for (size_t i = 0; i < Len; ++i)
76 Buf[i] = BitcodeBuffer[Cursor + i];
77 Cursor += Len;
78 return Len;
79}
80
Jim Stichnoth620ad732015-04-28 14:12:20 -070081std::unique_ptr<Ostream> makeStream(const IceString &Filename,
82 std::error_code &EC) {
83 if (Filename == "-") {
Jan Voung44c3a802015-03-27 16:29:08 -070084 return std::unique_ptr<Ostream>(new llvm::raw_os_ostream(std::cout));
Jim Stichnoth620ad732015-04-28 14:12:20 -070085 } else {
86 return std::unique_ptr<Ostream>(
87 new llvm::raw_fd_ostream(Filename, EC, llvm::sys::fs::F_None));
Jan Voung44c3a802015-03-27 16:29:08 -070088 }
89}
90
91ErrorCodes getReturnValue(const Ice::ClFlagsExtra &Flags, ErrorCodes Val) {
92 if (Flags.getAlwaysExitSuccess())
93 return EC_None;
94 return Val;
95}
96
97} // end of anonymous namespace
98
99void CLCompileServer::run() {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700100 if (BuildDefs::dump()) {
Jan Voungb2d50842015-05-12 09:53:50 -0700101 llvm::sys::PrintStackTraceOnErrorSignal();
102 }
Jan Voung44c3a802015-03-27 16:29:08 -0700103 ClFlags::parseFlags(argc, argv);
104 ClFlags Flags;
105 ClFlagsExtra ExtraFlags;
106 ClFlags::getParsedClFlags(Flags);
107 ClFlags::getParsedClFlagsExtra(ExtraFlags);
108
Jim Stichnoth620ad732015-04-28 14:12:20 -0700109 std::error_code EC;
110 std::unique_ptr<Ostream> Ls = makeStream(ExtraFlags.getLogFilename(), EC);
111 if (EC) {
112 llvm::report_fatal_error("Unable to open log file");
113 }
Jan Voung44c3a802015-03-27 16:29:08 -0700114 Ls->SetUnbuffered();
115 std::unique_ptr<Ostream> Os;
116 std::unique_ptr<ELFStreamer> ELFStr;
117 switch (Flags.getOutFileType()) {
118 case FT_Elf: {
119 if (ExtraFlags.getOutputFilename() == "-") {
120 *Ls << "Error: writing binary ELF to stdout is unsupported\n";
121 return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args));
122 }
Jan Voung44c3a802015-03-27 16:29:08 -0700123 std::unique_ptr<llvm::raw_fd_ostream> FdOs(new llvm::raw_fd_ostream(
124 ExtraFlags.getOutputFilename(), EC, llvm::sys::fs::F_None));
125 if (EC) {
126 *Ls << "Failed to open output file: " << ExtraFlags.getOutputFilename()
127 << ":\n" << EC.message() << "\n";
128 return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args));
129 }
130 ELFStr.reset(new ELFStreamer(*FdOs.get()));
131 Os.reset(FdOs.release());
132 // NaCl sets st_blksize to 0, and LLVM uses that to pick the
133 // default preferred buffer size. Set to something non-zero.
134 Os->SetBufferSize(1 << 14);
135 } break;
136 case FT_Asm:
137 case FT_Iasm: {
Jim Stichnoth620ad732015-04-28 14:12:20 -0700138 Os = makeStream(ExtraFlags.getOutputFilename(), EC);
139 if (EC) {
140 *Ls << "Failed to open output file: " << ExtraFlags.getOutputFilename()
141 << ":\n" << EC.message() << "\n";
142 return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args));
143 }
Jan Voung44c3a802015-03-27 16:29:08 -0700144 Os->SetUnbuffered();
145 } break;
146 }
147
Karl Schimpfcb6e95a2015-07-23 09:10:03 -0700148 if (BuildDefs::minimal() && ExtraFlags.getBitcodeAsText())
149 llvm::report_fatal_error("Can't specify 'bitcode-as-text' flag in "
150 "minimal build");
151
Jan Voung44c3a802015-03-27 16:29:08 -0700152 IceString StrError;
153 std::unique_ptr<llvm::DataStreamer> InputStream(
Karl Schimpfcb6e95a2015-07-23 09:10:03 -0700154 (!BuildDefs::minimal() && ExtraFlags.getBitcodeAsText())
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700155 ? TextDataStreamer::create(ExtraFlags.getIRFilename(), &StrError)
156 : llvm::getDataFileStreamer(ExtraFlags.getIRFilename(), &StrError));
Jan Voung44c3a802015-03-27 16:29:08 -0700157 if (!StrError.empty() || !InputStream) {
158 llvm::SMDiagnostic Err(ExtraFlags.getIRFilename(),
159 llvm::SourceMgr::DK_Error, StrError);
160 Err.print(ExtraFlags.getAppName().c_str(), *Ls);
161 return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Bitcode));
162 }
163
Jim Stichnoth620ad732015-04-28 14:12:20 -0700164 Ctx.reset(
165 new GlobalContext(Ls.get(), Os.get(), Ls.get(), ELFStr.get(), Flags));
Jan Voung44c3a802015-03-27 16:29:08 -0700166 if (Ctx->getFlags().getNumTranslationThreads() != 0) {
167 std::thread CompileThread([this, &ExtraFlags, &InputStream]() {
168 Ctx->initParserThread();
169 getCompiler().run(ExtraFlags, *Ctx.get(), std::move(InputStream));
170 });
171 CompileThread.join();
172 } else {
173 getCompiler().run(ExtraFlags, *Ctx.get(), std::move(InputStream));
174 }
175 transferErrorCode(getReturnValue(
176 ExtraFlags, static_cast<ErrorCodes>(Ctx->getErrorStatus()->value())));
177}
178
179} // end of namespace Ice