OLD | NEW |
---|---|
1 //===-- pnacl-llc.cpp - PNaCl-specific llc: pexe ---> nexe ---------------===// | 1 //===-- pnacl-llc.cpp - PNaCl-specific llc: pexe ---> nexe ---------------===// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // pnacl-llc: the core of the PNaCl translator, compiling a pexe into a nexe. | 10 // pnacl-llc: the core of the PNaCl translator, compiling a pexe into a nexe. |
11 // | 11 // |
12 //===----------------------------------------------------------------------===// | 12 //===----------------------------------------------------------------------===// |
13 | 13 |
14 #include "llvm/ADT/Triple.h" | 14 #include "llvm/ADT/Triple.h" |
15 #include "llvm/Analysis/NaCl.h" | 15 #include "llvm/Analysis/NaCl.h" |
16 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h" | 16 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h" |
17 #include "llvm/Bitcode/ReaderWriter.h" | 17 #include "llvm/Bitcode/ReaderWriter.h" |
18 #include "llvm/CodeGen/CommandFlags.h" | 18 #include "llvm/CodeGen/CommandFlags.h" |
19 #include "llvm/CodeGen/LinkAllAsmWriterComponents.h" | |
20 #include "llvm/CodeGen/LinkAllCodegenComponents.h" | 19 #include "llvm/CodeGen/LinkAllCodegenComponents.h" |
21 #include "llvm/IR/DataLayout.h" | 20 #include "llvm/IR/DataLayout.h" |
22 #include "llvm/IR/LLVMContext.h" | 21 #include "llvm/IR/LLVMContext.h" |
23 #include "llvm/IR/Module.h" | 22 #include "llvm/IR/Module.h" |
24 #include "llvm/IR/Verifier.h" | 23 #include "llvm/IR/Verifier.h" |
25 #include "llvm/IRReader/IRReader.h" | 24 #include "llvm/IRReader/IRReader.h" |
26 #include "llvm/MC/SubtargetFeature.h" | 25 #include "llvm/MC/SubtargetFeature.h" |
27 #include "llvm/Pass.h" | 26 #include "llvm/Pass.h" |
28 #include "llvm/PassManager.h" | 27 #include "llvm/PassManager.h" |
29 #include "llvm/Support/CommandLine.h" | 28 #include "llvm/Support/CommandLine.h" |
30 #include "llvm/Support/DataStream.h" | 29 #include "llvm/Support/DataStream.h" |
31 #include "llvm/Support/Debug.h" | 30 #include "llvm/Support/Debug.h" |
32 #include "llvm/Support/ErrorHandling.h" | 31 #include "llvm/Support/ErrorHandling.h" |
33 #include "llvm/Support/FileSystem.h" | 32 #include "llvm/Support/FileSystem.h" |
34 #include "llvm/Support/FormattedStream.h" | 33 #include "llvm/Support/FormattedStream.h" |
35 #include "llvm/Support/Host.h" | 34 #include "llvm/Support/Host.h" |
36 #include "llvm/Support/ManagedStatic.h" | 35 #include "llvm/Support/ManagedStatic.h" |
37 #include "llvm/Support/Mutex.h" | |
38 #include "llvm/Support/PrettyStackTrace.h" | 36 #include "llvm/Support/PrettyStackTrace.h" |
39 #include "llvm/Support/Signals.h" | 37 #include "llvm/Support/Signals.h" |
40 #include "llvm/Support/SourceMgr.h" | 38 #include "llvm/Support/SourceMgr.h" |
41 #include "llvm/Support/StreamableMemoryObject.h" | 39 #include "llvm/Support/StreamingMemoryObject.h" |
42 #include "llvm/Support/TargetRegistry.h" | 40 #include "llvm/Support/TargetRegistry.h" |
43 #include "llvm/Support/TargetSelect.h" | 41 #include "llvm/Support/TargetSelect.h" |
44 #include "llvm/Support/ToolOutputFile.h" | 42 #include "llvm/Support/ToolOutputFile.h" |
45 #include "llvm/Target/TargetLibraryInfo.h" | 43 #include "llvm/Target/TargetLibraryInfo.h" |
46 #include "llvm/Target/TargetMachine.h" | 44 #include "llvm/Target/TargetMachine.h" |
45 #include "llvm/Target/TargetSubtargetInfo.h" | |
47 #include "llvm/Transforms/NaCl.h" | 46 #include "llvm/Transforms/NaCl.h" |
48 | 47 |
49 #include "ThreadedFunctionQueue.h" | 48 #include "ThreadedFunctionQueue.h" |
50 #include "ThreadedStreamingCache.h" | 49 #include "ThreadedStreamingCache.h" |
51 | 50 |
52 #include <pthread.h> | 51 #include <pthread.h> |
53 #include <memory> | 52 #include <memory> |
54 | 53 |
55 using namespace llvm; | 54 using namespace llvm; |
56 | 55 |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
219 switch (FileType) { | 218 switch (FileType) { |
220 case TargetMachine::CGFT_AssemblyFile: | 219 case TargetMachine::CGFT_AssemblyFile: |
221 break; | 220 break; |
222 case TargetMachine::CGFT_ObjectFile: | 221 case TargetMachine::CGFT_ObjectFile: |
223 case TargetMachine::CGFT_Null: | 222 case TargetMachine::CGFT_Null: |
224 Binary = true; | 223 Binary = true; |
225 break; | 224 break; |
226 } | 225 } |
227 | 226 |
228 // Open the file. | 227 // Open the file. |
229 std::string error; | 228 std::error_code EC; |
230 sys::fs::OpenFlags OpenFlags = sys::fs::F_None; | 229 sys::fs::OpenFlags OpenFlags = sys::fs::F_None; |
231 if (!Binary) | 230 if (!Binary) |
232 OpenFlags |= sys::fs::F_Text; | 231 OpenFlags |= sys::fs::F_Text; |
233 tool_output_file *FDOut = | 232 tool_output_file *FDOut = new tool_output_file(Filename, EC, OpenFlags); |
234 new tool_output_file(Filename.c_str(), error, OpenFlags); | 233 if (EC) { |
235 if (!error.empty()) { | 234 errs() << EC.message() << '\n'; |
236 errs() << error << '\n'; | |
237 delete FDOut; | 235 delete FDOut; |
238 return nullptr; | 236 return nullptr; |
239 } | 237 } |
240 | 238 |
241 return FDOut; | 239 return FDOut; |
242 } | 240 } |
243 #endif // !defined(PNACL_BROWSER_TRANSLATOR) | 241 #endif // !defined(PNACL_BROWSER_TRANSLATOR) |
244 | 242 |
245 // main - Entry point for the llc compiler. | 243 // main - Entry point for the llc compiler. |
246 // | 244 // |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
312 os << Name << " is not valid PNaCl bitcode:\n"; | 310 os << Name << " is not valid PNaCl bitcode:\n"; |
313 Reporter.printErrors(os); | 311 Reporter.printErrors(os); |
314 if (PNaClABIVerifyFatalErrors) { | 312 if (PNaClABIVerifyFatalErrors) { |
315 report_fatal_error(os.str()); | 313 report_fatal_error(os.str()); |
316 } | 314 } |
317 errs() << os.str(); | 315 errs() << os.str(); |
318 } | 316 } |
319 Reporter.reset(); | 317 Reporter.reset(); |
320 } | 318 } |
321 | 319 |
322 static Module* getModule(StringRef ProgramName, LLVMContext &Context, | 320 static std::unique_ptr<Module> getModule( |
323 StreamingMemoryObject *StreamingObject) { | 321 StringRef ProgramName, LLVMContext &Context, |
324 Module *M = nullptr; | 322 StreamingMemoryObject *StreamingObject) { |
323 std::unique_ptr<Module> M; | |
325 SMDiagnostic Err; | 324 SMDiagnostic Err; |
326 std::string VerboseBuffer; | 325 std::string VerboseBuffer; |
327 raw_string_ostream VerboseStrm(VerboseBuffer); | 326 raw_string_ostream VerboseStrm(VerboseBuffer); |
328 if (LazyBitcode) { | 327 if (LazyBitcode) { |
329 std::string StrError; | 328 std::string StrError; |
330 switch (InputFileFormat) { | 329 switch (InputFileFormat) { |
331 case PNaClFormat: | 330 case PNaClFormat: |
332 M = getNaClStreamedBitcodeModule( | 331 M.reset(getNaClStreamedBitcodeModule( |
333 InputFilename, | 332 InputFilename, |
334 new ThreadedStreamingCache(StreamingObject), Context, &VerboseStrm, | 333 new ThreadedStreamingCache(StreamingObject), Context, &VerboseStrm, |
335 &StrError); | 334 &StrError)); |
336 break; | 335 break; |
337 case LLVMFormat: | 336 case LLVMFormat: |
338 M = getStreamedBitcodeModule( | 337 M.reset(getStreamedBitcodeModule( |
339 InputFilename, | 338 InputFilename, |
340 new ThreadedStreamingCache(StreamingObject), Context, &StrError); | 339 new ThreadedStreamingCache(StreamingObject), Context, &StrError)); |
341 break; | 340 break; |
342 case AutodetectFileFormat: | 341 case AutodetectFileFormat: |
343 report_fatal_error("Command can't autodetect file format!"); | 342 report_fatal_error("Command can't autodetect file format!"); |
344 } | 343 } |
345 if (!StrError.empty()) | 344 if (!StrError.empty()) |
346 Err = SMDiagnostic(InputFilename, SourceMgr::DK_Error, StrError); | 345 Err = SMDiagnostic(InputFilename, SourceMgr::DK_Error, StrError); |
347 } else { | 346 } else { |
348 #if defined(PNACL_BROWSER_TRANSLATOR) | 347 #if defined(PNACL_BROWSER_TRANSLATOR) |
349 llvm_unreachable("native client SRPC only supports streaming"); | 348 llvm_unreachable("native client SRPC only supports streaming"); |
350 #else | 349 #else |
351 // Parses binary bitcode as well as textual assembly | 350 // Parses binary bitcode as well as textual assembly |
352 // (so pulls in more code into pnacl-llc). | 351 // (so pulls in more code into pnacl-llc). |
353 M = NaClParseIRFile(InputFilename, InputFileFormat, Err, &VerboseStrm, | 352 M = NaClParseIRFile(InputFilename, InputFileFormat, Err, &VerboseStrm, |
354 Context); | 353 Context); |
355 #endif | 354 #endif |
356 } | 355 } |
357 if (!M) { | 356 if (!M) { |
358 #if defined(PNACL_BROWSER_TRANSLATOR) | 357 #if defined(PNACL_BROWSER_TRANSLATOR) |
359 report_fatal_error(VerboseStrm.str() + Err.getMessage()); | 358 report_fatal_error(VerboseStrm.str() + Err.getMessage()); |
360 #else | 359 #else |
361 // Err.print is prettier, so use it for the non-sandboxed translator. | 360 // Err.print is prettier, so use it for the non-sandboxed translator. |
362 Err.print(ProgramName.data(), errs()); | 361 Err.print(ProgramName.data(), errs()); |
363 errs() << VerboseStrm.str(); | 362 errs() << VerboseStrm.str(); |
364 return nullptr; | 363 return nullptr; |
365 #endif | 364 #endif |
366 } | 365 } |
367 return M; | 366 return std::move(M); |
368 } | 367 } |
369 | 368 |
370 static cl::opt<bool> | 369 static cl::opt<bool> |
371 ExternalizeAll("externalize", | 370 ExternalizeAll("externalize", |
372 cl::desc("Externalize all symbols"), | 371 cl::desc("Externalize all symbols"), |
373 cl::init(false)); | 372 cl::init(false)); |
374 | 373 |
375 static int runCompilePasses(Module *mod, | 374 static int runCompilePasses(Module *ModuleRef, |
jvoung (off chromium)
2015/02/24 18:38:48
Went ahead and capitalized the variable name for c
| |
376 unsigned ModuleIndex, | 375 unsigned ModuleIndex, |
377 ThreadedFunctionQueue *FuncQueue, | 376 ThreadedFunctionQueue *FuncQueue, |
378 const Triple &TheTriple, | 377 const Triple &TheTriple, |
379 TargetMachine &Target, | 378 TargetMachine &Target, |
380 StringRef ProgramName, | 379 StringRef ProgramName, |
381 formatted_raw_ostream &FOS){ | 380 formatted_raw_ostream &FOS){ |
382 PNaClABIErrorReporter ABIErrorReporter; | 381 PNaClABIErrorReporter ABIErrorReporter; |
383 | 382 |
384 if (SplitModuleCount > 1 || ExternalizeAll) { | 383 if (SplitModuleCount > 1 || ExternalizeAll) { |
385 // Add function and global names, and give them external linkage. | 384 // Add function and global names, and give them external linkage. |
386 // This relies on LLVM's consistent auto-generation of names, we could | 385 // This relies on LLVM's consistent auto-generation of names, we could |
387 // maybe do our own in case something changes there. | 386 // maybe do our own in case something changes there. |
388 for (Module::iterator I = mod->begin(), E = mod->end(); I != E; ++I) { | 387 for (Function &F : *ModuleRef) { |
389 if (!I->hasName()) | 388 if (!F.hasName()) |
390 I->setName("Function"); | 389 F.setName("Function"); |
391 if (I->hasInternalLinkage()) | 390 if (F.hasInternalLinkage()) |
392 I->setLinkage(GlobalValue::ExternalLinkage); | 391 F.setLinkage(GlobalValue::ExternalLinkage); |
393 } | 392 } |
394 for (Module::global_iterator GI = mod->global_begin(), | 393 for (Module::global_iterator GI = ModuleRef->global_begin(), |
395 GE = mod->global_end(); | 394 GE = ModuleRef->global_end(); |
396 GI != GE; ++GI) { | 395 GI != GE; ++GI) { |
397 if (!GI->hasName()) | 396 if (!GI->hasName()) |
398 GI->setName("Global"); | 397 GI->setName("Global"); |
399 if (GI->hasInternalLinkage()) | 398 if (GI->hasInternalLinkage()) |
400 GI->setLinkage(GlobalValue::ExternalLinkage); | 399 GI->setLinkage(GlobalValue::ExternalLinkage); |
401 } | 400 } |
402 if (ModuleIndex > 0) { | 401 if (ModuleIndex > 0) { |
403 // Remove the initializers for all global variables, turning them into | 402 // Remove the initializers for all global variables, turning them into |
404 // declarations. | 403 // declarations. |
405 for (Module::global_iterator GI = mod->global_begin(), | 404 for (Module::global_iterator GI = ModuleRef->global_begin(), |
406 GE = mod->global_end(); | 405 GE = ModuleRef->global_end(); |
407 GI != GE; ++GI) { | 406 GI != GE; ++GI) { |
408 assert(GI->hasInitializer() && "Global variable missing initializer"); | 407 assert(GI->hasInitializer() && "Global variable missing initializer"); |
409 Constant *Init = GI->getInitializer(); | 408 Constant *Init = GI->getInitializer(); |
410 GI->setInitializer(nullptr); | 409 GI->setInitializer(nullptr); |
411 if (Init->getNumUses() == 0) | 410 if (Init->getNumUses() == 0) |
412 Init->destroyConstant(); | 411 Init->destroyConstant(); |
413 } | 412 } |
414 } | 413 } |
415 } | 414 } |
416 | 415 |
417 // Make all non-weak symbols hidden for better code. We cannot do | 416 // Make all non-weak symbols hidden for better code. We cannot do |
418 // this for weak symbols. The linker complains when some weak | 417 // this for weak symbols. The linker complains when some weak |
419 // symbols are not resolved. | 418 // symbols are not resolved. |
420 for (Module::iterator I = mod->begin(), E = mod->end(); I != E; ++I) { | 419 for (Function &F : *ModuleRef) { |
421 if (!I->isWeakForLinker() && !I->hasLocalLinkage()) | 420 if (!F.isWeakForLinker() && !F.hasLocalLinkage()) |
422 I->setVisibility(GlobalValue::HiddenVisibility); | 421 F.setVisibility(GlobalValue::HiddenVisibility); |
423 } | 422 } |
424 for (Module::global_iterator GI = mod->global_begin(), | 423 for (Module::global_iterator GI = ModuleRef->global_begin(), |
425 GE = mod->global_end(); | 424 GE = ModuleRef->global_end(); |
426 GI != GE; ++GI) { | 425 GI != GE; ++GI) { |
427 if (!GI->isWeakForLinker() && !GI->hasLocalLinkage()) | 426 if (!GI->isWeakForLinker() && !GI->hasLocalLinkage()) |
428 GI->setVisibility(GlobalValue::HiddenVisibility); | 427 GI->setVisibility(GlobalValue::HiddenVisibility); |
429 } | 428 } |
430 | 429 |
431 // Build up all of the passes that we want to do to the module. | 430 // Build up all of the passes that we want to do to the module. |
432 std::unique_ptr<PassManagerBase> PM; | 431 std::unique_ptr<PassManagerBase> PM; |
433 if (LazyBitcode) | 432 if (LazyBitcode) |
434 PM.reset(new FunctionPassManager(mod)); | 433 PM.reset(new FunctionPassManager(ModuleRef)); |
435 else | 434 else |
436 PM.reset(new PassManager()); | 435 PM.reset(new PassManager()); |
437 | 436 |
438 // Add the target data from the target machine, if it exists, or the module. | 437 // Add the target data from the target machine, if it exists, or the module. |
439 if (const DataLayout *DL = Target.getDataLayout()) | 438 if (const DataLayout *DL = Target.getSubtargetImpl()->getDataLayout()) |
440 mod->setDataLayout(DL); | 439 ModuleRef->setDataLayout(DL); |
441 PM->add(new DataLayoutPass(mod)); | 440 PM->add(new DataLayoutPass()); |
442 | 441 |
443 // For conformance with llc, we let the user disable LLVM IR verification with | 442 // For conformance with llc, we let the user disable LLVM IR verification with |
444 // -disable-verify. Unlike llc, when LLVM IR verification is enabled we only | 443 // -disable-verify. Unlike llc, when LLVM IR verification is enabled we only |
445 // run it once, before PNaCl ABI verification. | 444 // run it once, before PNaCl ABI verification. |
446 if (!NoVerify) | 445 if (!NoVerify) |
447 PM->add(createVerifierPass()); | 446 PM->add(createVerifierPass()); |
448 | 447 |
449 // Add the ABI verifier pass before the analysis and code emission passes. | 448 // Add the ABI verifier pass before the analysis and code emission passes. |
450 if (PNaClABIVerify) | 449 if (PNaClABIVerify) |
451 PM->add(createPNaClABIVerifyFunctionsPass(&ABIErrorReporter)); | 450 PM->add(createPNaClABIVerifyFunctionsPass(&ABIErrorReporter)); |
(...skipping 23 matching lines...) Expand all Loading... | |
475 << ": target does not support generation of this file type!\n"; | 474 << ": target does not support generation of this file type!\n"; |
476 return 1; | 475 return 1; |
477 } | 476 } |
478 | 477 |
479 if (LazyBitcode) { | 478 if (LazyBitcode) { |
480 auto FPM = static_cast<FunctionPassManager *>(PM.get()); | 479 auto FPM = static_cast<FunctionPassManager *>(PM.get()); |
481 FPM->doInitialization(); | 480 FPM->doInitialization(); |
482 unsigned FuncIndex = 0; | 481 unsigned FuncIndex = 0; |
483 switch (SplitModuleSched) { | 482 switch (SplitModuleSched) { |
484 case SplitModuleStatic: | 483 case SplitModuleStatic: |
485 for (Module::iterator I = mod->begin(), E = mod->end(); I != E; ++I) { | 484 for (Function &F : *ModuleRef) { |
486 if (FuncQueue->GrabFunctionStatic(FuncIndex, ModuleIndex)) { | 485 if (FuncQueue->GrabFunctionStatic(FuncIndex, ModuleIndex)) { |
487 FPM->run(*I); | 486 FPM->run(F); |
488 CheckABIVerifyErrors(ABIErrorReporter, "Function " + I->getName()); | 487 CheckABIVerifyErrors(ABIErrorReporter, "Function " + F.getName()); |
489 I->Dematerialize(); | 488 F.Dematerialize(); |
490 } | 489 } |
491 ++FuncIndex; | 490 ++FuncIndex; |
492 } | 491 } |
493 break; | 492 break; |
494 case SplitModuleDynamic: | 493 case SplitModuleDynamic: |
495 unsigned ChunkSize = 0; | 494 unsigned ChunkSize = 0; |
496 unsigned NumFunctions = FuncQueue->Size(); | 495 unsigned NumFunctions = FuncQueue->Size(); |
497 Module::iterator I = mod->begin(); | 496 Module::iterator I = ModuleRef->begin(); |
498 while (FuncIndex < NumFunctions) { | 497 while (FuncIndex < NumFunctions) { |
499 ChunkSize = FuncQueue->RecommendedChunkSize(); | 498 ChunkSize = FuncQueue->RecommendedChunkSize(); |
500 unsigned NextIndex; | 499 unsigned NextIndex; |
501 bool grabbed = FuncQueue->GrabFunctionDynamic(FuncIndex, ChunkSize, | 500 bool grabbed = FuncQueue->GrabFunctionDynamic(FuncIndex, ChunkSize, |
502 NextIndex); | 501 NextIndex); |
503 if (grabbed) { | 502 if (grabbed) { |
504 while (FuncIndex < NextIndex) { | 503 while (FuncIndex < NextIndex) { |
505 if (!I->isMaterializable() && I->isDeclaration()) { | 504 if (!I->isMaterializable() && I->isDeclaration()) { |
506 ++I; | 505 ++I; |
507 continue; | 506 continue; |
(...skipping 12 matching lines...) Expand all Loading... | |
520 } | 519 } |
521 ++FuncIndex; | 520 ++FuncIndex; |
522 ++I; | 521 ++I; |
523 } | 522 } |
524 } | 523 } |
525 } | 524 } |
526 break; | 525 break; |
527 } | 526 } |
528 FPM->doFinalization(); | 527 FPM->doFinalization(); |
529 } else | 528 } else |
530 static_cast<PassManager *>(PM.get())->run(*mod); | 529 static_cast<PassManager *>(PM.get())->run(*ModuleRef); |
531 | 530 |
532 return 0; | 531 return 0; |
533 } | 532 } |
534 | 533 |
535 static int compileSplitModule(const TargetOptions &Options, | 534 static int compileSplitModule(const TargetOptions &Options, |
536 const Triple &TheTriple, | 535 const Triple &TheTriple, |
537 const Target *TheTarget, | 536 const Target *TheTarget, |
538 const std::string &FeaturesStr, | 537 const std::string &FeaturesStr, |
539 CodeGenOpt::Level OLvl, | 538 CodeGenOpt::Level OLvl, |
540 const StringRef &ProgramName, | 539 const StringRef &ProgramName, |
541 Module *GlobalModule, | 540 Module *GlobalModuleRef, |
542 StreamingMemoryObject *StreamingObject, | 541 StreamingMemoryObject *StreamingObject, |
543 unsigned ModuleIndex, | 542 unsigned ModuleIndex, |
544 ThreadedFunctionQueue *FuncQueue) { | 543 ThreadedFunctionQueue *FuncQueue) { |
545 std::auto_ptr<TargetMachine> | 544 std::auto_ptr<TargetMachine> |
546 target(TheTarget->createTargetMachine(TheTriple.getTriple(), | 545 target(TheTarget->createTargetMachine(TheTriple.getTriple(), |
547 MCPU, FeaturesStr, Options, | 546 MCPU, FeaturesStr, Options, |
548 RelocModel, CMModel, OLvl)); | 547 RelocModel, CMModel, OLvl)); |
549 assert(target.get() && "Could not allocate target machine!"); | 548 assert(target.get() && "Could not allocate target machine!"); |
550 TargetMachine &Target = *target.get(); | 549 TargetMachine &Target = *target.get(); |
551 // Override default to generate verbose assembly. | 550 // Override default to generate verbose assembly. |
552 Target.setAsmVerbosityDefault(true); | 551 Target.setAsmVerbosityDefault(true); |
553 if (RelaxAll.getNumOccurrences() > 0 && | 552 if (RelaxAll.getNumOccurrences() > 0 && |
554 FileType != TargetMachine::CGFT_ObjectFile) | 553 FileType != TargetMachine::CGFT_ObjectFile) |
555 errs() << ProgramName | 554 errs() << ProgramName |
556 << ": warning: ignoring -mc-relax-all because filetype != obj"; | 555 << ": warning: ignoring -mc-relax-all because filetype != obj"; |
557 // The OwningPtrs are only used if we are not the primary module. | 556 // The OwningPtrs are only used if we are not the primary module. |
558 std::unique_ptr<LLVMContext> C; | 557 std::unique_ptr<LLVMContext> C; |
559 std::unique_ptr<Module> M; | 558 std::unique_ptr<Module> M; |
560 Module *mod(nullptr); | 559 Module *ModuleRef = nullptr; |
561 | 560 |
562 if (ModuleIndex == 0) { | 561 if (ModuleIndex == 0) { |
563 mod = GlobalModule; | 562 ModuleRef = GlobalModuleRef; |
564 } else { | 563 } else { |
565 C.reset(new LLVMContext()); | 564 C.reset(new LLVMContext()); |
566 mod = getModule(ProgramName, *C, StreamingObject); | 565 M = getModule(ProgramName, *C, StreamingObject); |
567 if (!mod) | 566 if (!M) |
568 return 1; | 567 return 1; |
569 M.reset(mod); | 568 // M owns the temporary module, but use a reference through ModuleRef |
569 // to also work in the case we are using GlobalModuleRef. | |
570 ModuleRef = M.get(); | |
570 | 571 |
571 // Add declarations for external functions required by PNaCl. The | 572 // Add declarations for external functions required by PNaCl. The |
572 // ResolvePNaClIntrinsics function pass running during streaming | 573 // ResolvePNaClIntrinsics function pass running during streaming |
573 // depends on these declarations being in the module. | 574 // depends on these declarations being in the module. |
574 std::unique_ptr<ModulePass> AddPNaClExternalDeclsPass( | 575 std::unique_ptr<ModulePass> AddPNaClExternalDeclsPass( |
575 createAddPNaClExternalDeclsPass()); | 576 createAddPNaClExternalDeclsPass()); |
576 AddPNaClExternalDeclsPass->runOnModule(*M); | 577 AddPNaClExternalDeclsPass->runOnModule(*ModuleRef); |
577 AddPNaClExternalDeclsPass.reset(); | 578 AddPNaClExternalDeclsPass.reset(); |
578 } | 579 } |
579 | 580 |
580 mod->setTargetTriple(Triple::normalize(UserDefinedTriple)); | 581 ModuleRef->setTargetTriple(Triple::normalize(UserDefinedTriple)); |
581 | 582 |
582 { | 583 { |
583 #if !defined(PNACL_BROWSER_TRANSLATOR) | 584 #if !defined(PNACL_BROWSER_TRANSLATOR) |
584 // Figure out where we are going to send the output. | 585 // Figure out where we are going to send the output. |
585 std::string N(OutputFilename); | 586 std::string N(OutputFilename); |
586 raw_string_ostream OutFileName(N); | 587 raw_string_ostream OutFileName(N); |
587 if (ModuleIndex > 0) | 588 if (ModuleIndex > 0) |
588 OutFileName << ".module" << ModuleIndex; | 589 OutFileName << ".module" << ModuleIndex; |
589 std::unique_ptr<tool_output_file> Out | 590 std::unique_ptr<tool_output_file> Out |
590 (GetOutputStream(TheTarget->getName(), TheTriple.getOS(), | 591 (GetOutputStream(TheTarget->getName(), TheTriple.getOS(), |
591 OutFileName.str())); | 592 OutFileName.str())); |
592 if (!Out) return 1; | 593 if (!Out) return 1; |
593 formatted_raw_ostream FOS(Out->os()); | 594 formatted_raw_ostream FOS(Out->os()); |
594 #else | 595 #else |
595 raw_fd_ostream ROS(getObjectFileFD(ModuleIndex), true, sys::fs::F_None); | 596 raw_fd_ostream ROS(getObjectFileFD(ModuleIndex), /* ShouldClose */ true); |
596 ROS.SetBufferSize(1 << 20); | 597 ROS.SetBufferSize(1 << 20); |
597 formatted_raw_ostream FOS(ROS); | 598 formatted_raw_ostream FOS(ROS); |
598 #endif | 599 #endif |
599 int ret = runCompilePasses(mod, ModuleIndex, FuncQueue, | 600 int ret = runCompilePasses(ModuleRef, ModuleIndex, FuncQueue, |
600 TheTriple, Target, ProgramName, | 601 TheTriple, Target, ProgramName, |
601 FOS); | 602 FOS); |
602 if (ret) | 603 if (ret) |
603 return ret; | 604 return ret; |
604 #if defined(PNACL_BROWSER_TRANSLATOR) | 605 #if defined(PNACL_BROWSER_TRANSLATOR) |
605 FOS.flush(); | 606 FOS.flush(); |
606 ROS.flush(); | 607 ROS.flush(); |
607 #else | 608 #else |
608 // Declare success. | 609 // Declare success. |
609 Out->keep(); | 610 Out->keep(); |
610 #endif // PNACL_BROWSER_TRANSLATOR | 611 #endif // PNACL_BROWSER_TRANSLATOR |
611 } | 612 } |
612 return 0; | 613 return 0; |
613 } | 614 } |
614 | 615 |
615 struct ThreadData { | 616 struct ThreadData { |
616 const TargetOptions *Options; | 617 const TargetOptions *Options; |
617 const Triple *TheTriple; | 618 const Triple *TheTriple; |
618 const Target *TheTarget; | 619 const Target *TheTarget; |
619 std::string FeaturesStr; | 620 std::string FeaturesStr; |
620 CodeGenOpt::Level OLvl; | 621 CodeGenOpt::Level OLvl; |
621 std::string ProgramName; | 622 std::string ProgramName; |
622 Module *GlobalModule; | 623 Module *GlobalModuleRef; |
623 StreamingMemoryObject *StreamingObject; | 624 StreamingMemoryObject *StreamingObject; |
624 unsigned ModuleIndex; | 625 unsigned ModuleIndex; |
625 ThreadedFunctionQueue *FuncQueue; | 626 ThreadedFunctionQueue *FuncQueue; |
626 }; | 627 }; |
627 | 628 |
628 | 629 |
629 static void *runCompileThread(void *arg) { | 630 static void *runCompileThread(void *arg) { |
630 struct ThreadData *Data = static_cast<ThreadData *>(arg); | 631 struct ThreadData *Data = static_cast<ThreadData *>(arg); |
631 int ret = compileSplitModule(*Data->Options, | 632 int ret = compileSplitModule(*Data->Options, |
632 *Data->TheTriple, | 633 *Data->TheTriple, |
633 Data->TheTarget, | 634 Data->TheTarget, |
634 Data->FeaturesStr, | 635 Data->FeaturesStr, |
635 Data->OLvl, | 636 Data->OLvl, |
636 Data->ProgramName, | 637 Data->ProgramName, |
637 Data->GlobalModule, | 638 Data->GlobalModuleRef, |
638 Data->StreamingObject, | 639 Data->StreamingObject, |
639 Data->ModuleIndex, | 640 Data->ModuleIndex, |
640 Data->FuncQueue); | 641 Data->FuncQueue); |
641 return reinterpret_cast<void *>(static_cast<intptr_t>(ret)); | 642 return reinterpret_cast<void *>(static_cast<intptr_t>(ret)); |
642 } | 643 } |
643 | 644 |
644 static int compileModule(StringRef ProgramName) { | 645 static int compileModule(StringRef ProgramName) { |
645 // Use a new context instead of the global context for the main module. It mus t | 646 // Use a new context instead of the global context for the main module. It mus t |
646 // outlive the module object, declared below. We do this because | 647 // outlive the module object, declared below. We do this because |
647 // lib/CodeGen/PseudoSourceValue.cpp gets a type from the global context and | 648 // lib/CodeGen/PseudoSourceValue.cpp gets a type from the global context and |
648 // races with any other use of the context. Rather than doing an invasive | 649 // races with any other use of the context. Rather than doing an invasive |
649 // plumbing change to fix it, we work around it by using a new context here | 650 // plumbing change to fix it, we work around it by using a new context here |
650 // and leaving PseudoSourceValue as the only user of the global context. | 651 // and leaving PseudoSourceValue as the only user of the global context. |
651 std::unique_ptr<LLVMContext> MainContext(new LLVMContext()); | 652 std::unique_ptr<LLVMContext> MainContext(new LLVMContext()); |
652 std::unique_ptr<Module> mod; | 653 std::unique_ptr<Module> MainMod; |
653 Triple TheTriple; | 654 Triple TheTriple; |
654 PNaClABIErrorReporter ABIErrorReporter; | 655 PNaClABIErrorReporter ABIErrorReporter; |
655 std::unique_ptr<StreamingMemoryObject> StreamingObject; | 656 std::unique_ptr<StreamingMemoryObject> StreamingObject; |
656 | 657 |
657 if (!MainContext) return 1; | 658 if (!MainContext) return 1; |
658 | 659 |
659 #if defined(PNACL_BROWSER_TRANSLATOR) | 660 #if defined(PNACL_BROWSER_TRANSLATOR) |
660 StreamingObject.reset( | 661 StreamingObject.reset( |
661 new StreamingMemoryObjectImpl(getNaClBitcodeStreamer())); | 662 new StreamingMemoryObjectImpl(getNaClBitcodeStreamer())); |
662 #else | 663 #else |
663 if (LazyBitcode) { | 664 if (LazyBitcode) { |
664 std::string StrError; | 665 std::string StrError; |
665 DataStreamer* FileStreamer(getDataFileStreamer(InputFilename, &StrError)); | 666 DataStreamer* FileStreamer(getDataFileStreamer(InputFilename, &StrError)); |
666 if (!StrError.empty()) { | 667 if (!StrError.empty()) { |
667 SMDiagnostic Err(InputFilename, SourceMgr::DK_Error, StrError); | 668 SMDiagnostic Err(InputFilename, SourceMgr::DK_Error, StrError); |
668 Err.print(ProgramName.data(), errs()); | 669 Err.print(ProgramName.data(), errs()); |
669 } | 670 } |
670 if (!FileStreamer) | 671 if (!FileStreamer) |
671 return 1; | 672 return 1; |
672 StreamingObject.reset(new StreamingMemoryObjectImpl(FileStreamer)); | 673 StreamingObject.reset(new StreamingMemoryObjectImpl(FileStreamer)); |
673 } | 674 } |
674 #endif | 675 #endif |
675 mod.reset(getModule(ProgramName, *MainContext.get(), StreamingObject.get())); | 676 MainMod = getModule(ProgramName, *MainContext.get(), StreamingObject.get()); |
676 | 677 |
677 if (!mod) return 1; | 678 if (!MainMod) return 1; |
678 | 679 |
679 if (PNaClABIVerify) { | 680 if (PNaClABIVerify) { |
680 // Verify the module (but not the functions yet) | 681 // Verify the module (but not the functions yet) |
681 std::unique_ptr<ModulePass> VerifyPass( | 682 std::unique_ptr<ModulePass> VerifyPass( |
682 createPNaClABIVerifyModulePass(&ABIErrorReporter, LazyBitcode)); | 683 createPNaClABIVerifyModulePass(&ABIErrorReporter, LazyBitcode)); |
683 VerifyPass->runOnModule(*mod); | 684 VerifyPass->runOnModule(*MainMod); |
684 CheckABIVerifyErrors(ABIErrorReporter, "Module"); | 685 CheckABIVerifyErrors(ABIErrorReporter, "Module"); |
685 VerifyPass.reset(); | 686 VerifyPass.reset(); |
686 } | 687 } |
687 | 688 |
688 // Add declarations for external functions required by PNaCl. The | 689 // Add declarations for external functions required by PNaCl. The |
689 // ResolvePNaClIntrinsics function pass running during streaming | 690 // ResolvePNaClIntrinsics function pass running during streaming |
690 // depends on these declarations being in the module. | 691 // depends on these declarations being in the module. |
691 std::unique_ptr<ModulePass> AddPNaClExternalDeclsPass( | 692 std::unique_ptr<ModulePass> AddPNaClExternalDeclsPass( |
692 createAddPNaClExternalDeclsPass()); | 693 createAddPNaClExternalDeclsPass()); |
693 AddPNaClExternalDeclsPass->runOnModule(*mod); | 694 AddPNaClExternalDeclsPass->runOnModule(*MainMod); |
694 AddPNaClExternalDeclsPass.reset(); | 695 AddPNaClExternalDeclsPass.reset(); |
695 | 696 |
696 if (UserDefinedTriple.empty()) { | 697 if (UserDefinedTriple.empty()) { |
697 report_fatal_error("-mtriple must be set to a target triple for pnacl-llc"); | 698 report_fatal_error("-mtriple must be set to a target triple for pnacl-llc"); |
698 } else { | 699 } else { |
699 mod->setTargetTriple(Triple::normalize(UserDefinedTriple)); | 700 MainMod->setTargetTriple(Triple::normalize(UserDefinedTriple)); |
700 TheTriple = Triple(mod->getTargetTriple()); | 701 TheTriple = Triple(MainMod->getTargetTriple()); |
701 } | 702 } |
702 | 703 |
703 // Get the target specific parser. | 704 // Get the target specific parser. |
704 std::string Error; | 705 std::string Error; |
705 const Target *TheTarget = TargetRegistry::lookupTarget(MArch, TheTriple, | 706 const Target *TheTarget = TargetRegistry::lookupTarget(MArch, TheTriple, |
706 Error); | 707 Error); |
707 if (!TheTarget) { | 708 if (!TheTarget) { |
708 errs() << ProgramName << ": " << Error; | 709 errs() << ProgramName << ": " << Error; |
709 return 1; | 710 return 1; |
710 } | 711 } |
(...skipping 20 matching lines...) Expand all Loading... | |
731 return 1; | 732 return 1; |
732 case ' ': break; | 733 case ' ': break; |
733 case '0': OLvl = CodeGenOpt::None; break; | 734 case '0': OLvl = CodeGenOpt::None; break; |
734 case '1': OLvl = CodeGenOpt::Less; break; | 735 case '1': OLvl = CodeGenOpt::Less; break; |
735 case '2': OLvl = CodeGenOpt::Default; break; | 736 case '2': OLvl = CodeGenOpt::Default; break; |
736 case '3': OLvl = CodeGenOpt::Aggressive; break; | 737 case '3': OLvl = CodeGenOpt::Aggressive; break; |
737 } | 738 } |
738 | 739 |
739 SmallVector<pthread_t, 4> Pthreads(SplitModuleCount); | 740 SmallVector<pthread_t, 4> Pthreads(SplitModuleCount); |
740 SmallVector<ThreadData, 4> ThreadDatas(SplitModuleCount); | 741 SmallVector<ThreadData, 4> ThreadDatas(SplitModuleCount); |
741 ThreadedFunctionQueue FuncQueue(mod.get(), SplitModuleCount); | 742 ThreadedFunctionQueue FuncQueue(MainMod.get(), SplitModuleCount); |
742 | 743 |
743 if (SplitModuleCount == 1) { | 744 if (SplitModuleCount == 1) { |
744 // No need for dynamic scheduling with one thread. | 745 // No need for dynamic scheduling with one thread. |
745 SplitModuleSched = SplitModuleStatic; | 746 SplitModuleSched = SplitModuleStatic; |
746 return compileSplitModule(Options, TheTriple, TheTarget, FeaturesStr, | 747 return compileSplitModule(Options, TheTriple, TheTarget, FeaturesStr, |
747 OLvl, ProgramName, mod.get(), nullptr, 0, | 748 OLvl, ProgramName, MainMod.get(), nullptr, 0, |
748 &FuncQueue); | 749 &FuncQueue); |
749 } | 750 } |
750 | 751 |
751 for(unsigned ModuleIndex = 0; ModuleIndex < SplitModuleCount; ++ModuleIndex) { | 752 for(unsigned ModuleIndex = 0; ModuleIndex < SplitModuleCount; ++ModuleIndex) { |
752 ThreadDatas[ModuleIndex].Options = &Options; | 753 ThreadDatas[ModuleIndex].Options = &Options; |
753 ThreadDatas[ModuleIndex].TheTriple = &TheTriple; | 754 ThreadDatas[ModuleIndex].TheTriple = &TheTriple; |
754 ThreadDatas[ModuleIndex].TheTarget = TheTarget; | 755 ThreadDatas[ModuleIndex].TheTarget = TheTarget; |
755 ThreadDatas[ModuleIndex].FeaturesStr = FeaturesStr; | 756 ThreadDatas[ModuleIndex].FeaturesStr = FeaturesStr; |
756 ThreadDatas[ModuleIndex].OLvl = OLvl; | 757 ThreadDatas[ModuleIndex].OLvl = OLvl; |
757 ThreadDatas[ModuleIndex].ProgramName = ProgramName.str(); | 758 ThreadDatas[ModuleIndex].ProgramName = ProgramName.str(); |
758 ThreadDatas[ModuleIndex].GlobalModule = mod.get(); | 759 ThreadDatas[ModuleIndex].GlobalModuleRef = MainMod.get(); |
759 ThreadDatas[ModuleIndex].StreamingObject = StreamingObject.get(); | 760 ThreadDatas[ModuleIndex].StreamingObject = StreamingObject.get(); |
760 ThreadDatas[ModuleIndex].ModuleIndex = ModuleIndex; | 761 ThreadDatas[ModuleIndex].ModuleIndex = ModuleIndex; |
761 ThreadDatas[ModuleIndex].FuncQueue = &FuncQueue; | 762 ThreadDatas[ModuleIndex].FuncQueue = &FuncQueue; |
762 if (pthread_create(&Pthreads[ModuleIndex], nullptr, runCompileThread, | 763 if (pthread_create(&Pthreads[ModuleIndex], nullptr, runCompileThread, |
763 &ThreadDatas[ModuleIndex])) { | 764 &ThreadDatas[ModuleIndex])) { |
764 report_fatal_error("Failed to create thread"); | 765 report_fatal_error("Failed to create thread"); |
765 } | 766 } |
766 } | 767 } |
767 for(unsigned ModuleIndex = 0; ModuleIndex < SplitModuleCount; ++ModuleIndex) { | 768 for(unsigned ModuleIndex = 0; ModuleIndex < SplitModuleCount; ++ModuleIndex) { |
768 void *retval; | 769 void *retval; |
769 if (pthread_join(Pthreads[ModuleIndex], &retval)) | 770 if (pthread_join(Pthreads[ModuleIndex], &retval)) |
770 report_fatal_error("Failed to join thread"); | 771 report_fatal_error("Failed to join thread"); |
771 intptr_t ret = reinterpret_cast<intptr_t>(retval); | 772 intptr_t ret = reinterpret_cast<intptr_t>(retval); |
772 if (ret != 0) | 773 if (ret != 0) |
773 report_fatal_error("Thread returned nonzero"); | 774 report_fatal_error("Thread returned nonzero"); |
774 } | 775 } |
775 return 0; | 776 return 0; |
776 } | 777 } |
777 | 778 |
778 int main(int argc, char **argv) { | 779 int main(int argc, char **argv) { |
779 #if defined(PNACL_BROWSER_TRANSLATOR) | 780 #if defined(PNACL_BROWSER_TRANSLATOR) |
780 return srpc_main(argc, argv); | 781 return srpc_main(argc, argv); |
781 #else | 782 #else |
782 return llc_main(argc, argv); | 783 return llc_main(argc, argv); |
783 #endif // PNACL_BROWSER_TRANSLATOR | 784 #endif // PNACL_BROWSER_TRANSLATOR |
784 } | 785 } |
OLD | NEW |