blob: 59f18d26bf0d0ec27198b9c9a057a00a634d3172 [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"
31#include "llvm/IR/LLVMContext.h"
32#include "llvm/IR/Module.h"
33#include "llvm/IRReader/IRReader.h"
34#include "llvm/Support/SourceMgr.h"
35#include "llvm/Support/StreamingMemoryObject.h"
Jim Stichnoth98da9662015-06-27 06:38:08 -070036#pragma clang diagnostic pop
Jan Voung44c3a802015-03-27 16:29:08 -070037
Jan Voung44c3a802015-03-27 16:29:08 -070038namespace Ice {
39
40namespace {
41
42struct {
43 const char *FlagName;
44 int FlagValue;
Jim Stichnoth20b71f52015-06-24 15:52:24 -070045} ConditionalBuildAttributes[] = {
46 {"dump", BuildDefs::dump()},
47 {"disable_ir_gen", BuildDefs::disableIrGen()},
48 {"llvm_cl", BuildDefs::llvmCl()},
49 {"llvm_ir", BuildDefs::llvmIr()},
50 {"llvm_ir_as_input", BuildDefs::llvmIrAsInput()},
51 {"minimal_build", BuildDefs::minimal()},
52 {"browser_mode", PNACL_BROWSER_TRANSLATOR}};
Jan Voung44c3a802015-03-27 16:29:08 -070053
54// Validates values of build attributes. Prints them to Stream if
55// Stream is non-null.
Jim Stichnoth07692992015-06-01 13:39:24 -070056void validateAndGenerateBuildAttributes(Ostream *Stream) {
Jan Voung33492e72015-05-15 17:02:52 -070057 // List the supported targets.
Jan Voungb36ad9b2015-04-21 17:01:49 -070058 if (Stream) {
Jan Voungb36ad9b2015-04-21 17:01:49 -070059#define SUBZERO_TARGET(TARGET) *Stream << "target_" #TARGET << "\n";
60#include "llvm/Config/SZTargets.def"
61 }
62
Jan Voung44c3a802015-03-27 16:29:08 -070063 for (size_t i = 0; i < llvm::array_lengthof(ConditionalBuildAttributes);
64 ++i) {
65 switch (ConditionalBuildAttributes[i].FlagValue) {
66 case 0:
67 if (Stream)
68 *Stream << "no_" << ConditionalBuildAttributes[i].FlagName << "\n";
69 break;
70 case 1:
71 if (Stream)
72 *Stream << "allow_" << ConditionalBuildAttributes[i].FlagName << "\n";
73 break;
74 default: {
75 std::string Buffer;
76 llvm::raw_string_ostream StrBuf(Buffer);
77 StrBuf << "Flag " << ConditionalBuildAttributes[i].FlagName
78 << " must be defined as 0/1. Found: "
79 << ConditionalBuildAttributes[i].FlagValue;
80 llvm::report_fatal_error(StrBuf.str());
81 }
82 }
83 }
84}
85
86} // end of anonymous namespace
87
88void Compiler::run(const Ice::ClFlagsExtra &ExtraFlags, GlobalContext &Ctx,
89 std::unique_ptr<llvm::DataStreamer> &&InputStream) {
Jim Stichnoth07692992015-06-01 13:39:24 -070090 validateAndGenerateBuildAttributes(
Jan Voung44c3a802015-03-27 16:29:08 -070091 ExtraFlags.getGenerateBuildAtts() ? &Ctx.getStrDump() : nullptr);
92 if (ExtraFlags.getGenerateBuildAtts())
93 return Ctx.getErrorStatus()->assign(EC_None);
94
Jim Stichnoth20b71f52015-06-24 15:52:24 -070095 if (!BuildDefs::disableIrGen() && Ctx.getFlags().getDisableIRGeneration()) {
Jan Voung44c3a802015-03-27 16:29:08 -070096 Ctx.getStrDump() << "Error: Build doesn't allow --no-ir-gen when not "
97 << "ALLOW_DISABLE_IR_GEN!\n";
98 return Ctx.getErrorStatus()->assign(EC_Args);
99 }
100
101 // Force -build-on-read=0 for .ll files.
102 const std::string LLSuffix = ".ll";
103 const IceString &IRFilename = ExtraFlags.getIRFilename();
104 bool BuildOnRead = ExtraFlags.getBuildOnRead();
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700105 if (BuildDefs::llvmIrAsInput() && IRFilename.length() >= LLSuffix.length() &&
Jan Voung44c3a802015-03-27 16:29:08 -0700106 IRFilename.compare(IRFilename.length() - LLSuffix.length(),
107 LLSuffix.length(), LLSuffix) == 0)
108 BuildOnRead = false;
109
110 TimerMarker T(Ice::TimerStack::TT_szmain, &Ctx);
111
Jan Voungfb792842015-06-11 15:27:50 -0700112 Ctx.emitFileHeader();
Jan Voung44c3a802015-03-27 16:29:08 -0700113 Ctx.startWorkerThreads();
114
115 std::unique_ptr<Translator> Translator;
116 if (BuildOnRead) {
117 std::unique_ptr<PNaClTranslator> PTranslator(new PNaClTranslator(&Ctx));
118 std::unique_ptr<llvm::StreamingMemoryObject> MemObj(
119 new llvm::StreamingMemoryObjectImpl(InputStream.release()));
120 PTranslator->translate(IRFilename, std::move(MemObj));
121 Translator.reset(PTranslator.release());
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700122 } else if (BuildDefs::llvmIr()) {
Jan Voung44c3a802015-03-27 16:29:08 -0700123 if (PNACL_BROWSER_TRANSLATOR) {
124 Ctx.getStrDump()
125 << "non BuildOnRead is not supported w/ PNACL_BROWSER_TRANSLATOR\n";
126 return Ctx.getErrorStatus()->assign(EC_Args);
127 }
128 // Parse the input LLVM IR file into a module.
129 llvm::SMDiagnostic Err;
130 TimerMarker T1(Ice::TimerStack::TT_parse, &Ctx);
131 llvm::raw_ostream *Verbose =
132 ExtraFlags.getLLVMVerboseErrors() ? &llvm::errs() : nullptr;
133 std::unique_ptr<llvm::Module> Mod =
134 NaClParseIRFile(IRFilename, ExtraFlags.getInputFileFormat(), Err,
135 Verbose, llvm::getGlobalContext());
136 if (!Mod) {
137 Err.print(ExtraFlags.getAppName().c_str(), llvm::errs());
138 return Ctx.getErrorStatus()->assign(EC_Bitcode);
139 }
140
141 std::unique_ptr<Converter> Converter(new class Converter(Mod.get(), &Ctx));
142 Converter->convertToIce();
143 Translator.reset(Converter.release());
144 } else {
145 Ctx.getStrDump() << "Error: Build doesn't allow LLVM IR, "
146 << "--build-on-read=0 not allowed\n";
147 return Ctx.getErrorStatus()->assign(EC_Args);
148 }
149
150 Ctx.waitForWorkerThreads();
John Porto8b1a7052015-06-17 13:20:08 -0700151 if (Translator->getErrorStatus()) {
152 Ctx.getErrorStatus()->assign(Translator->getErrorStatus().value());
153 } else {
154 Ctx.lowerGlobals("last");
155 Ctx.lowerProfileData();
156 Ctx.lowerConstants();
Jan Voung44c3a802015-03-27 16:29:08 -0700157
John Porto8b1a7052015-06-17 13:20:08 -0700158 if (Ctx.getFlags().getOutFileType() == FT_Elf) {
159 TimerMarker T1(Ice::TimerStack::TT_emit, &Ctx);
160 Ctx.getObjectWriter()->setUndefinedSyms(Ctx.getConstantExternSyms());
161 Ctx.getObjectWriter()->writeNonUserSections();
162 }
Jan Voung44c3a802015-03-27 16:29:08 -0700163 }
John Porto8b1a7052015-06-17 13:20:08 -0700164
Jan Voung44c3a802015-03-27 16:29:08 -0700165 if (Ctx.getFlags().getSubzeroTimingEnabled())
166 Ctx.dumpTimers();
John Porto8b1a7052015-06-17 13:20:08 -0700167
Jan Voung44c3a802015-03-27 16:29:08 -0700168 if (Ctx.getFlags().getTimeEachFunction()) {
169 const bool DumpCumulative = false;
170 Ctx.dumpTimers(GlobalContext::TSK_Funcs, DumpCumulative);
171 }
John Porto8b1a7052015-06-17 13:20:08 -0700172 constexpr bool FinalStats = true;
Jan Voung44c3a802015-03-27 16:29:08 -0700173 Ctx.dumpStats("_FINAL_", FinalStats);
174}
175
176} // end of namespace Ice