blob: d4048e9464fafaa35c406517ed31f239422882b4 [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//===----------------------------------------------------------------------===//
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 "llvm/Support/FileSystem.h"
19#include "llvm/Support/raw_os_ostream.h"
Jan Voungb2d50842015-05-12 09:53:50 -070020#include "llvm/Support/Signals.h"
Jan Voung44c3a802015-03-27 16:29:08 -070021#include "llvm/Support/SourceMgr.h"
22#include "llvm/Support/StreamingMemoryObject.h"
23
24#include "IceClFlags.h"
25#include "IceClFlagsExtra.h"
26#include "IceCompileServer.h"
27#include "IceELFStreamer.h"
28#include "IceGlobalContext.h"
29
30namespace Ice {
31
32namespace {
33
Jim Stichnoth620ad732015-04-28 14:12:20 -070034std::unique_ptr<Ostream> makeStream(const IceString &Filename,
35 std::error_code &EC) {
36 if (Filename == "-") {
Jan Voung44c3a802015-03-27 16:29:08 -070037 return std::unique_ptr<Ostream>(new llvm::raw_os_ostream(std::cout));
Jim Stichnoth620ad732015-04-28 14:12:20 -070038 } else {
39 return std::unique_ptr<Ostream>(
40 new llvm::raw_fd_ostream(Filename, EC, llvm::sys::fs::F_None));
Jan Voung44c3a802015-03-27 16:29:08 -070041 }
42}
43
44ErrorCodes getReturnValue(const Ice::ClFlagsExtra &Flags, ErrorCodes Val) {
45 if (Flags.getAlwaysExitSuccess())
46 return EC_None;
47 return Val;
48}
49
50} // end of anonymous namespace
51
52void CLCompileServer::run() {
Jan Voungb2d50842015-05-12 09:53:50 -070053 if (ALLOW_DUMP) {
54 llvm::sys::PrintStackTraceOnErrorSignal();
55 }
Jan Voung44c3a802015-03-27 16:29:08 -070056 ClFlags::parseFlags(argc, argv);
57 ClFlags Flags;
58 ClFlagsExtra ExtraFlags;
59 ClFlags::getParsedClFlags(Flags);
60 ClFlags::getParsedClFlagsExtra(ExtraFlags);
61
Jim Stichnoth620ad732015-04-28 14:12:20 -070062 std::error_code EC;
63 std::unique_ptr<Ostream> Ls = makeStream(ExtraFlags.getLogFilename(), EC);
64 if (EC) {
65 llvm::report_fatal_error("Unable to open log file");
66 }
Jan Voung44c3a802015-03-27 16:29:08 -070067 Ls->SetUnbuffered();
68 std::unique_ptr<Ostream> Os;
69 std::unique_ptr<ELFStreamer> ELFStr;
70 switch (Flags.getOutFileType()) {
71 case FT_Elf: {
72 if (ExtraFlags.getOutputFilename() == "-") {
73 *Ls << "Error: writing binary ELF to stdout is unsupported\n";
74 return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args));
75 }
Jan Voung44c3a802015-03-27 16:29:08 -070076 std::unique_ptr<llvm::raw_fd_ostream> FdOs(new llvm::raw_fd_ostream(
77 ExtraFlags.getOutputFilename(), EC, llvm::sys::fs::F_None));
78 if (EC) {
79 *Ls << "Failed to open output file: " << ExtraFlags.getOutputFilename()
80 << ":\n" << EC.message() << "\n";
81 return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args));
82 }
83 ELFStr.reset(new ELFStreamer(*FdOs.get()));
84 Os.reset(FdOs.release());
85 // NaCl sets st_blksize to 0, and LLVM uses that to pick the
86 // default preferred buffer size. Set to something non-zero.
87 Os->SetBufferSize(1 << 14);
88 } break;
89 case FT_Asm:
90 case FT_Iasm: {
Jim Stichnoth620ad732015-04-28 14:12:20 -070091 Os = makeStream(ExtraFlags.getOutputFilename(), EC);
92 if (EC) {
93 *Ls << "Failed to open output file: " << ExtraFlags.getOutputFilename()
94 << ":\n" << EC.message() << "\n";
95 return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args));
96 }
Jan Voung44c3a802015-03-27 16:29:08 -070097 Os->SetUnbuffered();
98 } break;
99 }
100
101 IceString StrError;
102 std::unique_ptr<llvm::DataStreamer> InputStream(
103 llvm::getDataFileStreamer(ExtraFlags.getIRFilename(), &StrError));
104 if (!StrError.empty() || !InputStream) {
105 llvm::SMDiagnostic Err(ExtraFlags.getIRFilename(),
106 llvm::SourceMgr::DK_Error, StrError);
107 Err.print(ExtraFlags.getAppName().c_str(), *Ls);
108 return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Bitcode));
109 }
110
Jim Stichnoth620ad732015-04-28 14:12:20 -0700111 Ctx.reset(
112 new GlobalContext(Ls.get(), Os.get(), Ls.get(), ELFStr.get(), Flags));
Jan Voung44c3a802015-03-27 16:29:08 -0700113 if (Ctx->getFlags().getNumTranslationThreads() != 0) {
114 std::thread CompileThread([this, &ExtraFlags, &InputStream]() {
115 Ctx->initParserThread();
116 getCompiler().run(ExtraFlags, *Ctx.get(), std::move(InputStream));
117 });
118 CompileThread.join();
119 } else {
120 getCompiler().run(ExtraFlags, *Ctx.get(), std::move(InputStream));
121 }
122 transferErrorCode(getReturnValue(
123 ExtraFlags, static_cast<ErrorCodes>(Ctx->getErrorStatus()->value())));
124}
125
126} // end of namespace Ice