Chromium Code Reviews| 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 |