blob: 4d3bbd4967a0301eda978ef402f5e7ff811828bb [file] [log] [blame]
Jan Voung44c3a802015-03-27 16:29:08 -07001//===- subzero/src/IceCompiler.cpp - Driver for bitcode translation -------===//
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 a driver for translating PNaCl bitcode into native code.
12/// It can either directly parse the binary bitcode file, or use LLVM routines
13/// to parse a textual bitcode file into LLVM IR and then convert LLVM IR into
14/// ICE. In either case, the high-level ICE is then compiled down to native
15/// code, as either an ELF object file or a textual asm file.
16///
Jan Voung44c3a802015-03-27 16:29:08 -070017//===----------------------------------------------------------------------===//
18
John Porto67f8de92015-06-25 10:14:17 -070019#include "IceCompiler.h"
20
21#include "IceCfg.h"
22#include "IceClFlags.h"
23#include "IceClFlagsExtra.h"
24#include "IceConverter.h"
25#include "IceELFObjectWriter.h"
26#include "PNaClTranslator.h"
Jim Stichnoth98da9662015-06-27 06:38:08 -070027
28#pragma clang diagnostic push
29#pragma clang diagnostic ignored "-Wunused-parameter"
Jan Voung44c3a802015-03-27 16:29:08 -070030#include "llvm/ADT/STLExtras.h"
Karl Schimpf25529f72015-08-25 13:47:27 -070031#include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
Jan Voung44c3a802015-03-27 16:29:08 -070032#include "llvm/IR/LLVMContext.h"
33#include "llvm/IR/Module.h"
34#include "llvm/IRReader/IRReader.h"
35#include "llvm/Support/SourceMgr.h"
36#include "llvm/Support/StreamingMemoryObject.h"
Jim Stichnoth98da9662015-06-27 06:38:08 -070037#pragma clang diagnostic pop
Jan Voung44c3a802015-03-27 16:29:08 -070038
Jan Voung44c3a802015-03-27 16:29:08 -070039namespace Ice {
40
41namespace {
42
43struct {
44 const char *FlagName;
45 int FlagValue;
Jim Stichnoth20b71f52015-06-24 15:52:24 -070046} ConditionalBuildAttributes[] = {
47 {"dump", BuildDefs::dump()},
48 {"disable_ir_gen", BuildDefs::disableIrGen()},
49 {"llvm_cl", BuildDefs::llvmCl()},
50 {"llvm_ir", BuildDefs::llvmIr()},
51 {"llvm_ir_as_input", BuildDefs::llvmIrAsInput()},
52 {"minimal_build", BuildDefs::minimal()},
53 {"browser_mode", PNACL_BROWSER_TRANSLATOR}};
Jan Voung44c3a802015-03-27 16:29:08 -070054
55// Validates values of build attributes. Prints them to Stream if
56// Stream is non-null.
Jim Stichnoth07692992015-06-01 13:39:24 -070057void validateAndGenerateBuildAttributes(Ostream *Stream) {
Jan Voung33492e72015-05-15 17:02:52 -070058 // List the supported targets.
Jan Voungb36ad9b2015-04-21 17:01:49 -070059 if (Stream) {
Jan Voungb36ad9b2015-04-21 17:01:49 -070060#define SUBZERO_TARGET(TARGET) *Stream << "target_" #TARGET << "\n";
61#include "llvm/Config/SZTargets.def"
62 }
63
Jan Voung44c3a802015-03-27 16:29:08 -070064 for (size_t i = 0; i < llvm::array_lengthof(ConditionalBuildAttributes);
65 ++i) {
66 switch (ConditionalBuildAttributes[i].FlagValue) {
67 case 0:
68 if (Stream)
69 *Stream << "no_" << ConditionalBuildAttributes[i].FlagName << "\n";
70 break;
71 case 1:
72 if (Stream)
73 *Stream << "allow_" << ConditionalBuildAttributes[i].FlagName << "\n";
74 break;
75 default: {
76 std::string Buffer;
77 llvm::raw_string_ostream StrBuf(Buffer);
78 StrBuf << "Flag " << ConditionalBuildAttributes[i].FlagName
79 << " must be defined as 0/1. Found: "
80 << ConditionalBuildAttributes[i].FlagValue;
81 llvm::report_fatal_error(StrBuf.str());
82 }
83 }
84 }
85}
86
87} // end of anonymous namespace
88
89void Compiler::run(const Ice::ClFlagsExtra &ExtraFlags, GlobalContext &Ctx,
90 std::unique_ptr<llvm::DataStreamer> &&InputStream) {
Jim Stichnoth07692992015-06-01 13:39:24 -070091 validateAndGenerateBuildAttributes(
Jan Voung44c3a802015-03-27 16:29:08 -070092 ExtraFlags.getGenerateBuildAtts() ? &Ctx.getStrDump() : nullptr);
93 if (ExtraFlags.getGenerateBuildAtts())
94 return Ctx.getErrorStatus()->assign(EC_None);
95
Jim Stichnoth20b71f52015-06-24 15:52:24 -070096 if (!BuildDefs::disableIrGen() && Ctx.getFlags().getDisableIRGeneration()) {
Jim Stichnoth992f91d2015-08-10 11:18:38 -070097 Ctx.getStrError() << "Error: Build doesn't allow --no-ir-gen when not "
98 << "ALLOW_DISABLE_IR_GEN!\n";
99 return Ctx.getErrorStatus()->assign(EC_Args);
100 }
101
102 // The Minimal build (specifically, when dump()/emit() are not implemented)
103 // allows only --filetype=obj. Check here to avoid cryptic error messages
104 // downstream.
105 if (!BuildDefs::dump() && Ctx.getFlags().getOutFileType() != FT_Elf) {
106 // TODO(stichnot): Access the actual command-line argument via
107 // llvm::Option.ArgStr and .ValueStr .
108 Ctx.getStrError()
109 << "Error: only --filetype=obj is supported in this build.\n";
Jan Voung44c3a802015-03-27 16:29:08 -0700110 return Ctx.getErrorStatus()->assign(EC_Args);
111 }
112
113 // Force -build-on-read=0 for .ll files.
114 const std::string LLSuffix = ".ll";
115 const IceString &IRFilename = ExtraFlags.getIRFilename();
116 bool BuildOnRead = ExtraFlags.getBuildOnRead();
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700117 if (BuildDefs::llvmIrAsInput() && IRFilename.length() >= LLSuffix.length() &&
Jan Voung44c3a802015-03-27 16:29:08 -0700118 IRFilename.compare(IRFilename.length() - LLSuffix.length(),
119 LLSuffix.length(), LLSuffix) == 0)
120 BuildOnRead = false;
121
122 TimerMarker T(Ice::TimerStack::TT_szmain, &Ctx);
123
Jan Voungfb792842015-06-11 15:27:50 -0700124 Ctx.emitFileHeader();
Jan Voung44c3a802015-03-27 16:29:08 -0700125 Ctx.startWorkerThreads();
126
127 std::unique_ptr<Translator> Translator;
128 if (BuildOnRead) {
129 std::unique_ptr<PNaClTranslator> PTranslator(new PNaClTranslator(&Ctx));
130 std::unique_ptr<llvm::StreamingMemoryObject> MemObj(
131 new llvm::StreamingMemoryObjectImpl(InputStream.release()));
132 PTranslator->translate(IRFilename, std::move(MemObj));
133 Translator.reset(PTranslator.release());
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700134 } else if (BuildDefs::llvmIr()) {
Jan Voung44c3a802015-03-27 16:29:08 -0700135 if (PNACL_BROWSER_TRANSLATOR) {
Jim Stichnoth992f91d2015-08-10 11:18:38 -0700136 Ctx.getStrError()
Jan Voung44c3a802015-03-27 16:29:08 -0700137 << "non BuildOnRead is not supported w/ PNACL_BROWSER_TRANSLATOR\n";
138 return Ctx.getErrorStatus()->assign(EC_Args);
139 }
140 // Parse the input LLVM IR file into a module.
141 llvm::SMDiagnostic Err;
142 TimerMarker T1(Ice::TimerStack::TT_parse, &Ctx);
Karl Schimpf25529f72015-08-25 13:47:27 -0700143 llvm::DiagnosticHandlerFunction DiagnosticHandler =
144 ExtraFlags.getLLVMVerboseErrors()
145 ? redirectNaClDiagnosticToStream(llvm::errs())
146 : nullptr;
Jan Voung44c3a802015-03-27 16:29:08 -0700147 std::unique_ptr<llvm::Module> Mod =
148 NaClParseIRFile(IRFilename, ExtraFlags.getInputFileFormat(), Err,
Karl Schimpf25529f72015-08-25 13:47:27 -0700149 llvm::getGlobalContext(), DiagnosticHandler);
Jan Voung44c3a802015-03-27 16:29:08 -0700150 if (!Mod) {
151 Err.print(ExtraFlags.getAppName().c_str(), llvm::errs());
152 return Ctx.getErrorStatus()->assign(EC_Bitcode);
153 }
154
155 std::unique_ptr<Converter> Converter(new class Converter(Mod.get(), &Ctx));
156 Converter->convertToIce();
157 Translator.reset(Converter.release());
158 } else {
Jim Stichnoth992f91d2015-08-10 11:18:38 -0700159 Ctx.getStrError() << "Error: Build doesn't allow LLVM IR, "
160 << "--build-on-read=0 not allowed\n";
Jan Voung44c3a802015-03-27 16:29:08 -0700161 return Ctx.getErrorStatus()->assign(EC_Args);
162 }
163
164 Ctx.waitForWorkerThreads();
John Porto8b1a7052015-06-17 13:20:08 -0700165 if (Translator->getErrorStatus()) {
166 Ctx.getErrorStatus()->assign(Translator->getErrorStatus().value());
167 } else {
168 Ctx.lowerGlobals("last");
169 Ctx.lowerProfileData();
170 Ctx.lowerConstants();
Andrew Scull86df4e92015-07-30 13:54:44 -0700171 Ctx.lowerJumpTables();
Jan Voung44c3a802015-03-27 16:29:08 -0700172
John Porto8b1a7052015-06-17 13:20:08 -0700173 if (Ctx.getFlags().getOutFileType() == FT_Elf) {
174 TimerMarker T1(Ice::TimerStack::TT_emit, &Ctx);
175 Ctx.getObjectWriter()->setUndefinedSyms(Ctx.getConstantExternSyms());
176 Ctx.getObjectWriter()->writeNonUserSections();
177 }
Jan Voung44c3a802015-03-27 16:29:08 -0700178 }
John Porto8b1a7052015-06-17 13:20:08 -0700179
Jan Voung44c3a802015-03-27 16:29:08 -0700180 if (Ctx.getFlags().getSubzeroTimingEnabled())
181 Ctx.dumpTimers();
John Porto8b1a7052015-06-17 13:20:08 -0700182
Jan Voung44c3a802015-03-27 16:29:08 -0700183 if (Ctx.getFlags().getTimeEachFunction()) {
184 const bool DumpCumulative = false;
185 Ctx.dumpTimers(GlobalContext::TSK_Funcs, DumpCumulative);
186 }
John Porto8b1a7052015-06-17 13:20:08 -0700187 constexpr bool FinalStats = true;
Jan Voung44c3a802015-03-27 16:29:08 -0700188 Ctx.dumpStats("_FINAL_", FinalStats);
189}
190
191} // end of namespace Ice