blob: fb116e6762e2e326a58b940e97cfa63f3f1aa34c [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//===----------------------------------------------------------------------===//
9//
10// This file defines a driver for translating PNaCl bitcode into native code.
11// It can either directly parse the binary bitcode file, or use LLVM routines to
12// parse a textual bitcode file into LLVM IR and then convert LLVM IR into ICE.
13// In either case, the high-level ICE is then compiled down to native code, as
14// either an ELF object file or a textual asm file.
15//
16//===----------------------------------------------------------------------===//
17
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/IR/LLVMContext.h"
20#include "llvm/IR/Module.h"
21#include "llvm/IRReader/IRReader.h"
22#include "llvm/Support/SourceMgr.h"
23#include "llvm/Support/StreamingMemoryObject.h"
24
25#include "IceCfg.h"
26#include "IceClFlags.h"
27#include "IceClFlagsExtra.h"
28#include "IceCompiler.h"
29#include "IceConverter.h"
30#include "IceELFObjectWriter.h"
31#include "PNaClTranslator.h"
32namespace Ice {
33
34namespace {
35
36struct {
37 const char *FlagName;
38 int FlagValue;
Jim Stichnoth20b71f52015-06-24 15:52:24 -070039} ConditionalBuildAttributes[] = {
40 {"dump", BuildDefs::dump()},
41 {"disable_ir_gen", BuildDefs::disableIrGen()},
42 {"llvm_cl", BuildDefs::llvmCl()},
43 {"llvm_ir", BuildDefs::llvmIr()},
44 {"llvm_ir_as_input", BuildDefs::llvmIrAsInput()},
45 {"minimal_build", BuildDefs::minimal()},
46 {"browser_mode", PNACL_BROWSER_TRANSLATOR}};
Jan Voung44c3a802015-03-27 16:29:08 -070047
48// Validates values of build attributes. Prints them to Stream if
49// Stream is non-null.
Jim Stichnoth07692992015-06-01 13:39:24 -070050void validateAndGenerateBuildAttributes(Ostream *Stream) {
Jan Voung33492e72015-05-15 17:02:52 -070051 // List the supported targets.
Jan Voungb36ad9b2015-04-21 17:01:49 -070052 if (Stream) {
Jan Voungb36ad9b2015-04-21 17:01:49 -070053#define SUBZERO_TARGET(TARGET) *Stream << "target_" #TARGET << "\n";
54#include "llvm/Config/SZTargets.def"
55 }
56
Jan Voung44c3a802015-03-27 16:29:08 -070057 for (size_t i = 0; i < llvm::array_lengthof(ConditionalBuildAttributes);
58 ++i) {
59 switch (ConditionalBuildAttributes[i].FlagValue) {
60 case 0:
61 if (Stream)
62 *Stream << "no_" << ConditionalBuildAttributes[i].FlagName << "\n";
63 break;
64 case 1:
65 if (Stream)
66 *Stream << "allow_" << ConditionalBuildAttributes[i].FlagName << "\n";
67 break;
68 default: {
69 std::string Buffer;
70 llvm::raw_string_ostream StrBuf(Buffer);
71 StrBuf << "Flag " << ConditionalBuildAttributes[i].FlagName
72 << " must be defined as 0/1. Found: "
73 << ConditionalBuildAttributes[i].FlagValue;
74 llvm::report_fatal_error(StrBuf.str());
75 }
76 }
77 }
78}
79
80} // end of anonymous namespace
81
82void Compiler::run(const Ice::ClFlagsExtra &ExtraFlags, GlobalContext &Ctx,
83 std::unique_ptr<llvm::DataStreamer> &&InputStream) {
Jim Stichnoth07692992015-06-01 13:39:24 -070084 validateAndGenerateBuildAttributes(
Jan Voung44c3a802015-03-27 16:29:08 -070085 ExtraFlags.getGenerateBuildAtts() ? &Ctx.getStrDump() : nullptr);
86 if (ExtraFlags.getGenerateBuildAtts())
87 return Ctx.getErrorStatus()->assign(EC_None);
88
Jim Stichnoth20b71f52015-06-24 15:52:24 -070089 if (!BuildDefs::disableIrGen() && Ctx.getFlags().getDisableIRGeneration()) {
Jan Voung44c3a802015-03-27 16:29:08 -070090 Ctx.getStrDump() << "Error: Build doesn't allow --no-ir-gen when not "
91 << "ALLOW_DISABLE_IR_GEN!\n";
92 return Ctx.getErrorStatus()->assign(EC_Args);
93 }
94
95 // Force -build-on-read=0 for .ll files.
96 const std::string LLSuffix = ".ll";
97 const IceString &IRFilename = ExtraFlags.getIRFilename();
98 bool BuildOnRead = ExtraFlags.getBuildOnRead();
Jim Stichnoth20b71f52015-06-24 15:52:24 -070099 if (BuildDefs::llvmIrAsInput() && IRFilename.length() >= LLSuffix.length() &&
Jan Voung44c3a802015-03-27 16:29:08 -0700100 IRFilename.compare(IRFilename.length() - LLSuffix.length(),
101 LLSuffix.length(), LLSuffix) == 0)
102 BuildOnRead = false;
103
104 TimerMarker T(Ice::TimerStack::TT_szmain, &Ctx);
105
Jan Voungfb792842015-06-11 15:27:50 -0700106 Ctx.emitFileHeader();
Jan Voung44c3a802015-03-27 16:29:08 -0700107 Ctx.startWorkerThreads();
108
109 std::unique_ptr<Translator> Translator;
110 if (BuildOnRead) {
111 std::unique_ptr<PNaClTranslator> PTranslator(new PNaClTranslator(&Ctx));
112 std::unique_ptr<llvm::StreamingMemoryObject> MemObj(
113 new llvm::StreamingMemoryObjectImpl(InputStream.release()));
114 PTranslator->translate(IRFilename, std::move(MemObj));
115 Translator.reset(PTranslator.release());
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700116 } else if (BuildDefs::llvmIr()) {
Jan Voung44c3a802015-03-27 16:29:08 -0700117 if (PNACL_BROWSER_TRANSLATOR) {
118 Ctx.getStrDump()
119 << "non BuildOnRead is not supported w/ PNACL_BROWSER_TRANSLATOR\n";
120 return Ctx.getErrorStatus()->assign(EC_Args);
121 }
122 // Parse the input LLVM IR file into a module.
123 llvm::SMDiagnostic Err;
124 TimerMarker T1(Ice::TimerStack::TT_parse, &Ctx);
125 llvm::raw_ostream *Verbose =
126 ExtraFlags.getLLVMVerboseErrors() ? &llvm::errs() : nullptr;
127 std::unique_ptr<llvm::Module> Mod =
128 NaClParseIRFile(IRFilename, ExtraFlags.getInputFileFormat(), Err,
129 Verbose, llvm::getGlobalContext());
130 if (!Mod) {
131 Err.print(ExtraFlags.getAppName().c_str(), llvm::errs());
132 return Ctx.getErrorStatus()->assign(EC_Bitcode);
133 }
134
135 std::unique_ptr<Converter> Converter(new class Converter(Mod.get(), &Ctx));
136 Converter->convertToIce();
137 Translator.reset(Converter.release());
138 } else {
139 Ctx.getStrDump() << "Error: Build doesn't allow LLVM IR, "
140 << "--build-on-read=0 not allowed\n";
141 return Ctx.getErrorStatus()->assign(EC_Args);
142 }
143
144 Ctx.waitForWorkerThreads();
John Porto8b1a7052015-06-17 13:20:08 -0700145 if (Translator->getErrorStatus()) {
146 Ctx.getErrorStatus()->assign(Translator->getErrorStatus().value());
147 } else {
148 Ctx.lowerGlobals("last");
149 Ctx.lowerProfileData();
150 Ctx.lowerConstants();
Jan Voung44c3a802015-03-27 16:29:08 -0700151
John Porto8b1a7052015-06-17 13:20:08 -0700152 if (Ctx.getFlags().getOutFileType() == FT_Elf) {
153 TimerMarker T1(Ice::TimerStack::TT_emit, &Ctx);
154 Ctx.getObjectWriter()->setUndefinedSyms(Ctx.getConstantExternSyms());
155 Ctx.getObjectWriter()->writeNonUserSections();
156 }
Jan Voung44c3a802015-03-27 16:29:08 -0700157 }
John Porto8b1a7052015-06-17 13:20:08 -0700158
Jan Voung44c3a802015-03-27 16:29:08 -0700159 if (Ctx.getFlags().getSubzeroTimingEnabled())
160 Ctx.dumpTimers();
John Porto8b1a7052015-06-17 13:20:08 -0700161
Jan Voung44c3a802015-03-27 16:29:08 -0700162 if (Ctx.getFlags().getTimeEachFunction()) {
163 const bool DumpCumulative = false;
164 Ctx.dumpTimers(GlobalContext::TSK_Funcs, DumpCumulative);
165 }
John Porto8b1a7052015-06-17 13:20:08 -0700166 constexpr bool FinalStats = true;
Jan Voung44c3a802015-03-27 16:29:08 -0700167 Ctx.dumpStats("_FINAL_", FinalStats);
168}
169
170} // end of namespace Ice