Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Side by Side Diff: src/llvm2ice.cpp

Issue 956123002: Subzero: Change the name llvm2ice to the more appropriate pnacl-sz. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Make comment correct Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« README.rst ('K') | « src/Makefile ('k') | src/main.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 //===- subzero/src/llvm2ice.cpp - Driver for testing ----------------------===//
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 that uses LLVM capabilities to parse a
11 // bitcode file and build the LLVM IR, and then convert the LLVM basic
12 // blocks, instructions, and operands into their Subzero equivalents.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include <fstream>
17 #include <iostream>
18
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/IR/LLVMContext.h"
21 #include "llvm/IRReader/IRReader.h"
22 #include "llvm/Support/CommandLine.h"
23 #include "llvm/Support/FileSystem.h"
24 #include "llvm/Support/raw_os_ostream.h"
25 #include "llvm/Support/SourceMgr.h"
26
27 #include "IceCfg.h"
28 #include "IceClFlags.h"
29 #include "IceConverter.h"
30 #include "IceELFObjectWriter.h"
31 #include "IceELFStreamer.h"
32 #include "PNaClTranslator.h"
33
34 using namespace llvm;
35
36 static cl::list<Ice::VerboseItem> VerboseList(
37 "verbose", cl::CommaSeparated,
38 cl::desc("Verbose options (can be comma-separated):"),
39 cl::values(
40 clEnumValN(Ice::IceV_Instructions, "inst", "Print basic instructions"),
41 clEnumValN(Ice::IceV_Deleted, "del", "Include deleted instructions"),
42 clEnumValN(Ice::IceV_InstNumbers, "instnum",
43 "Print instruction numbers"),
44 clEnumValN(Ice::IceV_Preds, "pred", "Show predecessors"),
45 clEnumValN(Ice::IceV_Succs, "succ", "Show successors"),
46 clEnumValN(Ice::IceV_Liveness, "live", "Liveness information"),
47 clEnumValN(Ice::IceV_RegOrigins, "orig", "Physical register origins"),
48 clEnumValN(Ice::IceV_LinearScan, "regalloc", "Linear scan details"),
49 clEnumValN(Ice::IceV_Frame, "frame", "Stack frame layout details"),
50 clEnumValN(Ice::IceV_AddrOpt, "addropt", "Address mode optimization"),
51 clEnumValN(Ice::IceV_Random, "random", "Randomization details"),
52 clEnumValN(Ice::IceV_All, "all", "Use all verbose options"),
53 clEnumValN(Ice::IceV_Most, "most",
54 "Use all verbose options except 'regalloc' and 'time'"),
55 clEnumValN(Ice::IceV_None, "none", "No verbosity"), clEnumValEnd));
56 static cl::opt<Ice::TargetArch> TargetArch(
57 "target", cl::desc("Target architecture:"), cl::init(Ice::Target_X8632),
58 cl::values(
59 clEnumValN(Ice::Target_X8632, "x8632", "x86-32"),
60 clEnumValN(Ice::Target_X8632, "x86-32", "x86-32 (same as x8632)"),
61 clEnumValN(Ice::Target_X8632, "x86_32", "x86-32 (same as x8632)"),
62 clEnumValN(Ice::Target_X8664, "x8664", "x86-64"),
63 clEnumValN(Ice::Target_X8664, "x86-64", "x86-64 (same as x8664)"),
64 clEnumValN(Ice::Target_X8664, "x86_64", "x86-64 (same as x8664)"),
65 clEnumValN(Ice::Target_ARM32, "arm", "arm32"),
66 clEnumValN(Ice::Target_ARM32, "arm32", "arm32 (same as arm)"),
67 clEnumValN(Ice::Target_ARM64, "arm64", "arm64"), clEnumValEnd));
68 static cl::opt<bool> UseSandboxing("sandbox", cl::desc("Use sandboxing"));
69 static cl::opt<bool>
70 FunctionSections("ffunction-sections",
71 cl::desc("Emit functions into separate sections"));
72 static cl::opt<bool>
73 DataSections("fdata-sections",
74 cl::desc("Emit (global) data into separate sections"));
75 static cl::opt<Ice::OptLevel>
76 OptLevel(cl::desc("Optimization level"), cl::init(Ice::Opt_m1),
77 cl::value_desc("level"),
78 cl::values(clEnumValN(Ice::Opt_m1, "Om1", "-1"),
79 clEnumValN(Ice::Opt_m1, "O-1", "-1"),
80 clEnumValN(Ice::Opt_0, "O0", "0"),
81 clEnumValN(Ice::Opt_1, "O1", "1"),
82 clEnumValN(Ice::Opt_2, "O2", "2"), clEnumValEnd));
83 static cl::opt<std::string> IRFilename(cl::Positional, cl::desc("<IR file>"),
84 cl::init("-"));
85 static cl::opt<std::string> OutputFilename("o",
86 cl::desc("Override output filename"),
87 cl::init("-"),
88 cl::value_desc("filename"));
89 static cl::opt<std::string> LogFilename("log", cl::desc("Set log filename"),
90 cl::init("-"),
91 cl::value_desc("filename"));
92 static cl::opt<std::string>
93 TestPrefix("prefix",
94 cl::desc("Prepend a prefix to symbol names for testing"),
95 cl::init(""), cl::value_desc("prefix"));
96 static cl::opt<bool> DisableInternal("externalize",
97 cl::desc("Externalize all symbols"));
98 static cl::opt<bool>
99 DisableTranslation("notranslate", cl::desc("Disable Subzero translation"));
100 // Note: Modifiable only if ALLOW_DISABLE_IR_GEN.
101 static cl::opt<bool>
102 DisableIRGeneration("no-ir-gen",
103 cl::desc("Disable generating Subzero IR."));
104 static cl::opt<std::string>
105 TranslateOnly("translate-only",
106 cl::desc("Translate only the given function"), cl::init(""));
107
108 static cl::opt<bool> SubzeroTimingEnabled(
109 "timing", cl::desc("Enable breakdown timing of Subzero translation"));
110
111 static cl::opt<bool> TimeEachFunction(
112 "timing-funcs", cl::desc("Print total translation time for each function"));
113
114 static cl::opt<std::string> TimingFocusOn(
115 "timing-focus",
116 cl::desc("Break down timing for a specific function (use '*' for all)"),
117 cl::init(""));
118
119 static cl::opt<std::string> VerboseFocusOn(
120 "verbose-focus",
121 cl::desc("Temporarily enable full verbosity for a specific function"),
122 cl::init(""));
123
124 static cl::opt<bool>
125 EnablePhiEdgeSplit("phi-edge-split",
126 cl::desc("Enable edge splitting for Phi lowering"),
127 cl::init(true));
128
129 static cl::opt<bool> DecorateAsm(
130 "asm-verbose",
131 cl::desc("Decorate textual asm output with register liveness info"));
132
133 static cl::opt<bool>
134 DumpStats("szstats",
135 cl::desc("Print statistics after translating each function"));
136
137 // This is currently needed by crosstest.py.
138 static cl::opt<bool> AllowUninitializedGlobals(
139 "allow-uninitialized-globals",
140 cl::desc("Allow global variables to be uninitialized"));
141
142 static cl::opt<NaClFileFormat> InputFileFormat(
143 "bitcode-format", cl::desc("Define format of input file:"),
144 cl::values(clEnumValN(LLVMFormat, "llvm", "LLVM file (default)"),
145 clEnumValN(PNaClFormat, "pnacl", "PNaCl bitcode file"),
146 clEnumValEnd),
147 cl::init(LLVMFormat));
148
149 static cl::opt<std::string>
150 DefaultGlobalPrefix("default-global-prefix",
151 cl::desc("Define default global prefix for naming "
152 "unnamed globals"),
153 cl::init("Global"));
154
155 static cl::opt<std::string>
156 DefaultFunctionPrefix("default-function-prefix",
157 cl::desc("Define default function prefix for naming "
158 "unnamed functions"),
159 cl::init("Function"));
160
161 // Note: While this flag isn't used in the minimal build, we keep this
162 // flag so that tests can set this command-line flag without concern
163 // to the type of build. We double check that this flag at runtime
164 // to make sure the consistency is maintained.
165 static cl::opt<bool>
166 BuildOnRead("build-on-read",
167 cl::desc("Build ICE instructions when reading bitcode"),
168 cl::init(true));
169
170 static cl::opt<bool> AllowErrorRecovery(
171 "allow-pnacl-reader-error-recovery",
172 cl::desc("Allow error recovery when reading PNaCl bitcode."),
173 cl::init(false));
174
175 // TODO(kschimpf) Remove once the emitter handles these cases.
176 static cl::opt<bool>
177 StubConstantCalls("stub-const-calls",
178 cl::desc("Stub indirect calls to constants."),
179 cl::init(false));
180
181 static cl::opt<bool> LLVMVerboseErrors(
182 "verbose-llvm-parse-errors",
183 cl::desc("Print out more descriptive PNaCl bitcode parse errors when "
184 "building LLVM IR first"),
185 cl::init(false));
186
187 static cl::opt<Ice::FileType> OutFileType(
188 "filetype", cl::desc("Output file type"), cl::init(Ice::FT_Iasm),
189 cl::values(clEnumValN(Ice::FT_Elf, "obj", "Native ELF object ('.o') file"),
190 clEnumValN(Ice::FT_Asm, "asm", "Assembly ('.s') file"),
191 clEnumValN(Ice::FT_Iasm, "iasm",
192 "Low-level integrated assembly ('.s') file"),
193 clEnumValEnd));
194
195 static cl::opt<bool> AlwaysExitSuccess(
196 "exit-success", cl::desc("Exit with success status, even if errors found"),
197 cl::init(false));
198
199 static cl::opt<bool> GenerateBuildAtts(
200 "build-atts", cl::desc("Generate list of build attributes associated with "
201 "this executable."),
202 cl::init(false));
203
204 // Number of translation threads (in addition to the parser thread and
205 // the emitter thread). The special case of 0 means purely
206 // sequential, i.e. parser, translator, and emitter all within the
207 // same single thread. (This may need a slight rework if we expand to
208 // multiple parser or emitter threads.)
209 static cl::opt<uint32_t> NumThreads(
210 "threads",
211 cl::desc("Number of translation threads (0 for purely sequential)"),
212 // TODO(stichnot): Settle on a good default. Consider
213 // something related to std::thread::hardware_concurrency().
214 cl::init(2));
215
216 static int GetReturnValue(int Val) {
217 if (AlwaysExitSuccess)
218 return 0;
219 return Val;
220 }
221
222 static struct {
223 const char *FlagName;
224 int FlagValue;
225 } ConditionalBuildAttributes[] = {{"dump", ALLOW_DUMP},
226 {"disable_ir_gen", ALLOW_DISABLE_IR_GEN},
227 {"llvm_cl", ALLOW_LLVM_CL},
228 {"llvm_ir", ALLOW_LLVM_IR},
229 {"llvm_ir_as_input", ALLOW_LLVM_IR_AS_INPUT},
230 {"minimal_build", ALLOW_MINIMAL_BUILD}};
231
232 // Validates values of build attributes. Prints them to Stream if
233 // Stream is non-null.
234 static void ValidateAndGenerateBuildAttributes(Ice::Ostream *Stream) {
235
236 if (Stream)
237 *Stream << TargetArch << "\n";
238
239 for (size_t i = 0; i < array_lengthof(ConditionalBuildAttributes); ++i) {
240 switch (ConditionalBuildAttributes[i].FlagValue) {
241 case 0:
242 if (Stream)
243 *Stream << "no_" << ConditionalBuildAttributes[i].FlagName << "\n";
244 break;
245 case 1:
246 if (Stream)
247 *Stream << "allow_" << ConditionalBuildAttributes[i].FlagName << "\n";
248 break;
249 default: {
250 std::string Buffer;
251 raw_string_ostream StrBuf(Buffer);
252 StrBuf << "Flag " << ConditionalBuildAttributes[i].FlagName
253 << " must be defined as 0/1. Found: "
254 << ConditionalBuildAttributes[i].FlagValue;
255 report_fatal_error(StrBuf.str());
256 }
257 }
258 }
259 }
260
261 int main(int argc, char **argv) {
262
263 cl::ParseCommandLineOptions(argc, argv);
264
265 if (DisableIRGeneration)
266 DisableTranslation = true;
267
268 Ice::VerboseMask VMask = Ice::IceV_None;
269 // Don't generate verbose messages if routines
270 // to dump messages are not available.
271 if (ALLOW_DUMP) {
272 for (unsigned i = 0; i != VerboseList.size(); ++i)
273 VMask |= VerboseList[i];
274 }
275
276 std::ofstream Lfs;
277 std::unique_ptr<Ice::Ostream> Ls;
278 if (LogFilename != "-") {
279 Lfs.open(LogFilename.c_str(), std::ofstream::out);
280 Ls.reset(new raw_os_ostream(Lfs));
281 } else {
282 Ls.reset(new raw_os_ostream(std::cout));
283 }
284 Ls->SetUnbuffered();
285
286 ValidateAndGenerateBuildAttributes(GenerateBuildAtts ? Ls.get() : nullptr);
287 if (GenerateBuildAtts)
288 return GetReturnValue(Ice::EC_None);
289
290 if (!ALLOW_DISABLE_IR_GEN && DisableIRGeneration) {
291 *Ls << "Error: Build doesn't allow --no-ir-gen when not "
292 << "ALLOW_DISABLE_IR_GEN!\n";
293 return GetReturnValue(Ice::EC_Args);
294 }
295
296 Ice::ClFlags Flags;
297 Flags.setAllowErrorRecovery(AllowErrorRecovery);
298 Flags.setAllowUninitializedGlobals(AllowUninitializedGlobals);
299 Flags.setDataSections(DataSections);
300 Flags.setDecorateAsm(DecorateAsm);
301 Flags.setDefaultFunctionPrefix(DefaultFunctionPrefix);
302 Flags.setDefaultGlobalPrefix(DefaultGlobalPrefix);
303 Flags.setDisableInternal(DisableInternal);
304 Flags.setDisableIRGeneration(DisableIRGeneration);
305 Flags.setDisableTranslation(DisableTranslation);
306 Flags.setDumpStats(DumpStats);
307 Flags.setFunctionSections(FunctionSections);
308 Flags.setNumTranslationThreads(NumThreads);
309 Flags.setPhiEdgeSplit(EnablePhiEdgeSplit);
310 Flags.setStubConstantCalls(StubConstantCalls);
311 Flags.setSubzeroTimingEnabled(SubzeroTimingEnabled);
312 Flags.setTimeEachFunction(TimeEachFunction);
313 Flags.setTimingFocusOn(TimingFocusOn);
314 Flags.setTranslateOnly(TranslateOnly);
315 Flags.setUseSandboxing(UseSandboxing);
316 Flags.setVerboseFocusOn(VerboseFocusOn);
317 Flags.setOutFileType(OutFileType);
318
319 // Force -build-on-read=0 for .ll files.
320 const std::string LLSuffix = ".ll";
321 if (IRFilename.length() >= LLSuffix.length() &&
322 IRFilename.compare(IRFilename.length() - LLSuffix.length(),
323 LLSuffix.length(), LLSuffix) == 0)
324 BuildOnRead = false;
325
326 // With the ELF writer, use a raw_fd_ostream to allow seeking.
327 // Also don't buffer, otherwise it gets pretty slow.
328 std::unique_ptr<Ice::Ostream> Os;
329 std::unique_ptr<Ice::ELFStreamer> ELFStr;
330 std::ofstream Ofs;
331 switch (OutFileType) {
332 case Ice::FT_Elf: {
333 if (OutputFilename == "-") {
334 *Ls << "Error: writing binary ELF to stdout is unsupported\n";
335 return GetReturnValue(Ice::EC_Args);
336 }
337 std::string ErrorInfo;
338 raw_fd_ostream *FdOs =
339 new raw_fd_ostream(OutputFilename.c_str(), ErrorInfo, sys::fs::F_None);
340 Os.reset(FdOs);
341 if (!ErrorInfo.empty()) {
342 *Ls << "Failed to open output file: " << OutputFilename << ":\n"
343 << ErrorInfo << "\n";
344 return GetReturnValue(Ice::EC_Args);
345 }
346 ELFStr.reset(new Ice::ELFStreamer(*FdOs));
347 } break;
348 case Ice::FT_Asm:
349 case Ice::FT_Iasm: {
350 if (OutputFilename != "-") {
351 Ofs.open(OutputFilename.c_str(), std::ofstream::out);
352 Os.reset(new raw_os_ostream(Ofs));
353 } else {
354 Os.reset(new raw_os_ostream(std::cout));
355 }
356 Os->SetUnbuffered();
357 } break;
358 }
359
360 Ice::GlobalContext Ctx(Ls.get(), Os.get(), ELFStr.get(), VMask, TargetArch,
361 OptLevel, TestPrefix, Flags);
362
363 Ice::TimerMarker T(Ice::TimerStack::TT_szmain, &Ctx);
364
365 if (OutFileType == Ice::FT_Elf) {
366 Ice::TimerMarker T1(Ice::TimerStack::TT_emit, &Ctx);
367 Ctx.getObjectWriter()->writeInitialELFHeader();
368 }
369
370 Ctx.startWorkerThreads();
371
372 std::unique_ptr<Ice::Translator> Translator;
373 if (BuildOnRead) {
374 std::unique_ptr<Ice::PNaClTranslator> PTranslator(
375 new Ice::PNaClTranslator(&Ctx));
376 PTranslator->translate(IRFilename);
377 Translator.reset(PTranslator.release());
378 } else if (ALLOW_LLVM_IR) {
379 // Parse the input LLVM IR file into a module.
380 SMDiagnostic Err;
381 Ice::TimerMarker T1(Ice::TimerStack::TT_parse, &Ctx);
382 raw_ostream *Verbose = LLVMVerboseErrors ? &errs() : nullptr;
383 Module *Mod = NaClParseIRFile(IRFilename, InputFileFormat, Err, Verbose,
384 getGlobalContext());
385
386 if (!Mod) {
387 Err.print(argv[0], errs());
388 return GetReturnValue(Ice::EC_Bitcode);
389 }
390
391 std::unique_ptr<Ice::Converter> Converter(new Ice::Converter(Mod, &Ctx));
392 Converter->convertToIce();
393 Translator.reset(Converter.release());
394 } else {
395 *Ls << "Error: Build doesn't allow LLVM IR, "
396 << "--build-on-read=0 not allowed\n";
397 return GetReturnValue(Ice::EC_Args);
398 }
399
400 Ctx.waitForWorkerThreads();
401 Translator->transferErrorCode();
402 Translator->emitConstants();
403
404 if (OutFileType == Ice::FT_Elf) {
405 Ice::TimerMarker T1(Ice::TimerStack::TT_emit, &Ctx);
406 Ctx.getObjectWriter()->setUndefinedSyms(Ctx.getConstantExternSyms());
407 Ctx.getObjectWriter()->writeNonUserSections();
408 }
409 if (SubzeroTimingEnabled)
410 Ctx.dumpTimers();
411 if (TimeEachFunction) {
412 const bool DumpCumulative = false;
413 Ctx.dumpTimers(Ice::GlobalContext::TSK_Funcs, DumpCumulative);
414 }
415 const bool FinalStats = true;
416 Ctx.dumpStats("_FINAL_", FinalStats);
417 return GetReturnValue(Ctx.getErrorStatus()->value());
418 }
OLDNEW
« README.rst ('K') | « src/Makefile ('k') | src/main.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698