int main(int argc, const char **argv) { sys::PrintStackTraceOnErrorSignal(argv[0]); cl::HideUnrelatedOptions(ClangOffloadBundlerCategory); cl::SetVersionPrinter(PrintVersion); cl::ParseCommandLineOptions( argc, argv, "A tool to bundle several input files of the specified type <type> \n" "referring to the same source file but different targets into a single \n" "one. The resulting file can also be unbundled into different files by \n" "this tool if -unbundle is provided.\n"); if (Help) { cl::PrintHelpMessage(); return 0; } bool Error = false; if (Unbundle) { if (InputFileNames.size() != 1) { Error = true; errs() << "error: only one input file supported in unbundling mode.\n"; } if (OutputFileNames.size() != TargetNames.size()) { Error = true; errs() << "error: number of output files and targets should match in " "unbundling mode.\n"; } } else { if (OutputFileNames.size() != 1) { Error = true; errs() << "error: only one output file supported in bundling mode.\n"; } if (InputFileNames.size() != TargetNames.size()) { Error = true; errs() << "error: number of input files and targets should match in " "bundling mode.\n"; } } // Verify that the offload kinds and triples are known. We also check that we // have exactly one host target. unsigned Index = 0u; unsigned HostTargetNum = 0u; for (StringRef Target : TargetNames) { StringRef Kind; StringRef Triple; getOffloadKindAndTriple(Target, Kind, Triple); bool KindIsValid = !Kind.empty(); KindIsValid = KindIsValid && StringSwitch<bool>(Kind) .Case("host", true) .Case("openmp", true) .Case("hip", true) .Default(false); bool TripleIsValid = !Triple.empty(); llvm::Triple T(Triple); TripleIsValid &= T.getArch() != Triple::UnknownArch; if (!KindIsValid || !TripleIsValid) { Error = true; errs() << "error: invalid target '" << Target << "'"; if (!KindIsValid) errs() << ", unknown offloading kind '" << Kind << "'"; if (!TripleIsValid) errs() << ", unknown target triple '" << Triple << "'"; errs() << ".\n"; } if (KindIsValid && Kind == "host") { ++HostTargetNum; // Save the index of the input that refers to the host. HostInputIndex = Index; } ++Index; } if (HostTargetNum != 1) { Error = true; errs() << "error: expecting exactly one host target but got " << HostTargetNum << ".\n"; } if (Error) return 1; // Save the current executable directory as it will be useful to find other // tools. BundlerExecutable = sys::fs::getMainExecutable(argv[0], &BundlerExecutable); return Unbundle ? UnbundleFiles() : BundleFiles(); }
//===----------------------------------------------------------------------===// // main for opt // int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); // Enable debug stream buffering. EnableDebugBuffering = true; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. LLVMContext &Context = getGlobalContext(); InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); // Initialize passes PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); initializeScalarOpts(Registry); initializeObjCARCOpts(Registry); initializeVectorization(Registry); initializeIPO(Registry); initializeAnalysis(Registry); initializeIPA(Registry); initializeTransformUtils(Registry); initializeInstCombine(Registry); initializeInstrumentation(Registry); initializeTarget(Registry); // For codegen passes, only passes that do IR to IR transformation are // supported. initializeCodeGenPreparePass(Registry); initializeAtomicExpandPass(Registry); initializeRewriteSymbolsPass(Registry); initializeWinEHPreparePass(Registry); initializeDwarfEHPreparePass(Registry); #ifdef LINK_POLLY_INTO_TOOLS polly::initializePollyPasses(Registry); #endif // @LOCALMOD-BEGIN initializeAddPNaClExternalDeclsPass(Registry); initializeAllocateDataSegmentPass(Registry); initializeBackendCanonicalizePass(Registry); initializeCanonicalizeMemIntrinsicsPass(Registry); initializeCleanupUsedGlobalsMetadataPass(Registry); initializeConstantInsertExtractElementIndexPass(Registry); initializeExpandAllocasPass(Registry); initializeExpandArithWithOverflowPass(Registry); initializeExpandByValPass(Registry); initializeExpandConstantExprPass(Registry); initializeExpandCtorsPass(Registry); initializeExpandGetElementPtrPass(Registry); initializeExpandIndirectBrPass(Registry); initializeExpandLargeIntegersPass(Registry); initializeExpandShuffleVectorPass(Registry); initializeExpandSmallArgumentsPass(Registry); initializeExpandStructRegsPass(Registry); initializeExpandTlsConstantExprPass(Registry); initializeExpandTlsPass(Registry); initializeExpandVarArgsPass(Registry); initializeFixVectorLoadStoreAlignmentPass(Registry); initializeFlattenGlobalsPass(Registry); initializeGlobalCleanupPass(Registry); initializeGlobalizeConstantVectorsPass(Registry); initializeInsertDivideCheckPass(Registry); initializeInternalizeUsedGlobalsPass(Registry); initializeNormalizeAlignmentPass(Registry); initializePNaClABIVerifyFunctionsPass(Registry); initializePNaClABIVerifyModulePass(Registry); initializePNaClSjLjEHPass(Registry); initializePromoteI1OpsPass(Registry); initializePromoteIntegersPass(Registry); initializeRemoveAsmMemoryPass(Registry); initializeRenameEntryPointPass(Registry); initializeReplacePtrsWithIntsPass(Registry); initializeResolveAliasesPass(Registry); initializeResolvePNaClIntrinsicsPass(Registry); initializeRewriteAtomicsPass(Registry); initializeRewriteLLVMIntrinsicsPass(Registry); initializeRewritePNaClLibraryCallsPass(Registry); initializeSandboxIndirectCallsPass(Registry); initializeSandboxMemoryAccessesPass(Registry); initializeSimplifyAllocasPass(Registry); initializeSimplifyStructRegSignaturesPass(Registry); initializeStripAttributesPass(Registry); initializeStripMetadataPass(Registry); initializeStripModuleFlagsPass(Registry); initializeStripTlsPass(Registry); initializeSubstituteUndefsPass(Registry); // Emscripten passes: initializeExpandI64Pass(Registry); initializeExpandInsertExtractElementPass(Registry); initializeLowerEmAsyncifyPass(Registry); initializeLowerEmExceptionsPass(Registry); initializeLowerEmSetjmpPass(Registry); initializeNoExitRuntimePass(Registry); // Emscripten passes end. // @LOCALMOD-END cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .bc modular optimizer and analysis printer\n"); if (AnalyzeOnly && NoOutput) { errs() << argv[0] << ": analyze mode conflicts with no-output mode.\n"; return 1; } SMDiagnostic Err; // Load the input module... std::unique_ptr<Module> M; // XXX EMSCRIPTEN: support for multiple files if (InputFilenames.size() == 0) M = parseIRFile("-", Err, Context); else if (InputFilenames.size() == 1) M = parseIRFile(InputFilenames[0], Err, Context); else { // link them in M = nullptr; std::unique_ptr<Linker> L; for (unsigned i = 0; i < InputFilenames.size(); ++i) { std::unique_ptr<Module> MM = parseIRFile(InputFilenames[i], Err, Context); if (!MM.get()) { errs() << argv[0] << ": error loading file '" <<InputFilenames[i]<< "'\n"; return 1; } if (!NoVerify && verifyModule(*MM, &errs())) { errs() << argv[0] << ": " << InputFilenames[i] << ": error: input module is broken!\n"; return 1; } if (i == 0) { M.swap(MM); L = make_unique<Linker>(M.get()); } else { if (L->linkInModule(MM.get())) return 1; } } } if (!M) { Err.print(argv[0], errs()); return 1; } // Strip debug info before running the verifier. if (StripDebug) StripDebugInfo(*M); // Immediately run the verifier to catch any problems before starting up the // pass pipelines. Otherwise we can crash on broken code during // doInitialization(). if (!NoVerify && verifyModule(*M, &errs())) { errs() << argv[0] << ": " << ": error: input module is broken!\n"; return 1; } // If we are supposed to override the target triple, do so now. if (!TargetTriple.empty()) M->setTargetTriple(Triple::normalize(TargetTriple)); // Figure out what stream we are supposed to write to... std::unique_ptr<tool_output_file> Out; if (NoOutput) { if (!OutputFilename.empty()) errs() << "WARNING: The -o (output filename) option is ignored when\n" "the --disable-output option is used.\n"; } else { // Default to standard output. if (OutputFilename.empty()) OutputFilename = "-"; std::error_code EC; Out.reset(new tool_output_file(OutputFilename, EC, sys::fs::F_None)); if (EC) { errs() << EC.message() << '\n'; return 1; } } Triple ModuleTriple(M->getTargetTriple()); TargetMachine *Machine = nullptr; if (ModuleTriple.getArch()) Machine = GetTargetMachine(ModuleTriple); std::unique_ptr<TargetMachine> TM(Machine); // If the output is set to be emitted to standard out, and standard out is a // console, print out a warning message and refuse to do it. We don't // impress anyone by spewing tons of binary goo to a terminal. if (!Force && !NoOutput && !AnalyzeOnly && !OutputAssembly) if (CheckBitcodeOutputToConsole(Out->os(), !Quiet)) NoOutput = true; if (PassPipeline.getNumOccurrences() > 0) { OutputKind OK = OK_NoOutput; if (!NoOutput) OK = OutputAssembly ? OK_OutputAssembly : OK_OutputBitcode; VerifierKind VK = VK_VerifyInAndOut; if (NoVerify) VK = VK_NoVerifier; else if (VerifyEach) VK = VK_VerifyEachPass; // The user has asked to use the new pass manager and provided a pipeline // string. Hand off the rest of the functionality to the new code for that // layer. return runPassPipeline(argv[0], Context, *M, TM.get(), Out.get(), PassPipeline, OK, VK, PreserveAssemblyUseListOrder, PreserveBitcodeUseListOrder) ? 0 : 1; } // Create a PassManager to hold and optimize the collection of passes we are // about to build. // legacy::PassManager Passes; // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfoImpl TLII(ModuleTriple); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (DisableSimplifyLibCalls) TLII.disableAllFunctions(); Passes.add(new TargetLibraryInfoWrapperPass(TLII)); // Add an appropriate DataLayout instance for this module. const DataLayout &DL = M->getDataLayout(); if (DL.isDefault() && !DefaultDataLayout.empty()) { M->setDataLayout(DefaultDataLayout); } // Add internal analysis passes from the target machine. Passes.add(createTargetTransformInfoWrapperPass(TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis())); std::unique_ptr<legacy::FunctionPassManager> FPasses; if (OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) { FPasses.reset(new legacy::FunctionPassManager(M.get())); FPasses->add(createTargetTransformInfoWrapperPass( TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis())); } if (PrintBreakpoints) { // Default to standard output. if (!Out) { if (OutputFilename.empty()) OutputFilename = "-"; std::error_code EC; Out = llvm::make_unique<tool_output_file>(OutputFilename, EC, sys::fs::F_None); if (EC) { errs() << EC.message() << '\n'; return 1; } } Passes.add(createBreakpointPrinter(Out->os())); NoOutput = true; } // Create a new optimization pass for each one specified on the command line for (unsigned i = 0; i < PassList.size(); ++i) { // @LOCALMOD-BEGIN if (PNaClABISimplifyPreOpt && PNaClABISimplifyPreOpt.getPosition() < PassList.getPosition(i)) { PNaClABISimplifyAddPreOptPasses(&ModuleTriple, Passes); PNaClABISimplifyPreOpt = false; } // @LOCALMOD-END if (StandardLinkOpts && StandardLinkOpts.getPosition() < PassList.getPosition(i)) { AddStandardLinkPasses(Passes); StandardLinkOpts = false; } if (OptLevelO1 && OptLevelO1.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 1, 0); OptLevelO1 = false; } if (OptLevelO2 && OptLevelO2.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 2, 0); OptLevelO2 = false; } if (OptLevelOs && OptLevelOs.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 2, 1); OptLevelOs = false; } if (OptLevelOz && OptLevelOz.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 2, 2); OptLevelOz = false; } if (OptLevelO3 && OptLevelO3.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 3, 0); OptLevelO3 = false; } // @LOCALMOD-BEGIN if (PNaClABISimplifyPostOpt && PNaClABISimplifyPostOpt.getPosition() < PassList.getPosition(i)) { PNaClABISimplifyAddPostOptPasses(&ModuleTriple, Passes); PNaClABISimplifyPostOpt = false; } if (MinSFI && MinSFI.getPosition() < PassList.getPosition(i)) { MinSFIPasses(Passes); MinSFI = false; } // @LOCALMOD-END const PassInfo *PassInf = PassList[i]; Pass *P = nullptr; if (PassInf->getTargetMachineCtor()) P = PassInf->getTargetMachineCtor()(TM.get()); else if (PassInf->getNormalCtor()) P = PassInf->getNormalCtor()(); else errs() << argv[0] << ": cannot create pass: "******"\n"; if (P) { PassKind Kind = P->getPassKind(); addPass(Passes, P); if (AnalyzeOnly) { switch (Kind) { case PT_BasicBlock: Passes.add(createBasicBlockPassPrinter(PassInf, Out->os(), Quiet)); break; case PT_Region: Passes.add(createRegionPassPrinter(PassInf, Out->os(), Quiet)); break; case PT_Loop: Passes.add(createLoopPassPrinter(PassInf, Out->os(), Quiet)); break; case PT_Function: Passes.add(createFunctionPassPrinter(PassInf, Out->os(), Quiet)); break; case PT_CallGraphSCC: Passes.add(createCallGraphPassPrinter(PassInf, Out->os(), Quiet)); break; default: Passes.add(createModulePassPrinter(PassInf, Out->os(), Quiet)); break; } } } if (PrintEachXForm) Passes.add( createPrintModulePass(errs(), "", PreserveAssemblyUseListOrder)); } // @LOCALMOD-BEGIN if (PNaClABISimplifyPreOpt) PNaClABISimplifyAddPreOptPasses(&ModuleTriple, Passes); // @LOCALMOD-END if (StandardLinkOpts) { AddStandardLinkPasses(Passes); StandardLinkOpts = false; } if (OptLevelO1) AddOptimizationPasses(Passes, *FPasses, 1, 0); if (OptLevelO2) AddOptimizationPasses(Passes, *FPasses, 2, 0); if (OptLevelOs) AddOptimizationPasses(Passes, *FPasses, 2, 1); if (OptLevelOz) AddOptimizationPasses(Passes, *FPasses, 2, 2); if (OptLevelO3) AddOptimizationPasses(Passes, *FPasses, 3, 0); if (OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) { FPasses->doInitialization(); for (Function &F : *M) FPasses->run(F); FPasses->doFinalization(); } // @LOCALMOD-BEGIN if (PNaClABISimplifyPostOpt) PNaClABISimplifyAddPostOptPasses(&ModuleTriple, Passes); if (MinSFI) MinSFIPasses(Passes); // @LOCALMOD-END // Check that the module is well formed on completion of optimization if (!NoVerify && !VerifyEach) Passes.add(createVerifierPass()); // Write bitcode or assembly to the output as the last step... if (!NoOutput && !AnalyzeOnly) { if (OutputAssembly) Passes.add( createPrintModulePass(Out->os(), "", PreserveAssemblyUseListOrder)); else // @LOCALMOD-START switch (OutputFileFormat) { case LLVMFormat: Passes.add(createBitcodeWriterPass(Out->os(), PreserveBitcodeUseListOrder)); break; case PNaClFormat: Passes.add(createNaClBitcodeWriterPass(Out->os())); break; case AutodetectFileFormat: report_fatal_error("Command can't autodetect file format!"); break; } // @LOCALMOD-END } // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); // Now that we have all of the passes ready, run them. Passes.run(*M); // Declare success. if (!NoOutput || PrintBreakpoints) Out->keep(); return 0; }
/// runPasses - Run the specified passes on Program, outputting a bitcode file /// and writing the filename into OutputFile if successful. If the /// optimizations fail for some reason (optimizer crashes), return true, /// otherwise return false. If DeleteOutput is set to true, the bitcode is /// deleted on success, and the filename string is undefined. This prints to /// outs() a single line message indicating whether compilation was successful /// or failed. /// bool BugDriver::runPasses(Module *Program, const std::vector<std::string> &Passes, std::string &OutputFilename, bool DeleteOutput, bool Quiet, unsigned NumExtraArgs, const char * const *ExtraArgs) const { // setup the output file name outs().flush(); SmallString<128> UniqueFilename; std::error_code EC = sys::fs::createUniqueFile( OutputPrefix + "-output-%%%%%%%.bc", UniqueFilename); if (EC) { errs() << getToolName() << ": Error making unique filename: " << EC.message() << "\n"; return 1; } OutputFilename = UniqueFilename.str(); // set up the input file name SmallString<128> InputFilename; int InputFD; EC = sys::fs::createUniqueFile(OutputPrefix + "-input-%%%%%%%.bc", InputFD, InputFilename); if (EC) { errs() << getToolName() << ": Error making unique filename: " << EC.message() << "\n"; return 1; } tool_output_file InFile(InputFilename, InputFD); WriteBitcodeToFile(Program, InFile.os(), PreserveBitcodeUseListOrder); InFile.os().close(); if (InFile.os().has_error()) { errs() << "Error writing bitcode file: " << InputFilename << "\n"; InFile.os().clear_error(); return 1; } std::string tool = OptCmd; if (OptCmd.empty()) { if (ErrorOr<std::string> Path = sys::findProgramByName("opt")) tool = *Path; else errs() << Path.getError().message() << "\n"; } if (tool.empty()) { errs() << "Cannot find `opt' in PATH!\n"; return 1; } std::string Prog; if (UseValgrind) { if (ErrorOr<std::string> Path = sys::findProgramByName("valgrind")) Prog = *Path; else errs() << Path.getError().message() << "\n"; } else Prog = tool; if (Prog.empty()) { errs() << "Cannot find `valgrind' in PATH!\n"; return 1; } // Ok, everything that could go wrong before running opt is done. InFile.keep(); // setup the child process' arguments SmallVector<const char*, 8> Args; if (UseValgrind) { Args.push_back("valgrind"); Args.push_back("--error-exitcode=1"); Args.push_back("-q"); Args.push_back(tool.c_str()); } else Args.push_back(tool.c_str()); Args.push_back("-o"); Args.push_back(OutputFilename.c_str()); for (unsigned i = 0, e = OptArgs.size(); i != e; ++i) Args.push_back(OptArgs[i].c_str()); std::vector<std::string> pass_args; for (unsigned i = 0, e = PluginLoader::getNumPlugins(); i != e; ++i) { pass_args.push_back( std::string("-load")); pass_args.push_back( PluginLoader::getPlugin(i)); } for (std::vector<std::string>::const_iterator I = Passes.begin(), E = Passes.end(); I != E; ++I ) pass_args.push_back( std::string("-") + (*I) ); for (std::vector<std::string>::const_iterator I = pass_args.begin(), E = pass_args.end(); I != E; ++I ) Args.push_back(I->c_str()); Args.push_back(InputFilename.c_str()); for (unsigned i = 0; i < NumExtraArgs; ++i) Args.push_back(*ExtraArgs); Args.push_back(nullptr); DEBUG(errs() << "\nAbout to run:\t"; for (unsigned i = 0, e = Args.size()-1; i != e; ++i) errs() << " " << Args[i]; errs() << "\n"; );
// Returns true on error. static bool format(StringRef FileName) { ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr = MemoryBuffer::getFileOrSTDIN(FileName); if (std::error_code EC = CodeOrErr.getError()) { llvm::errs() << EC.message() << "\n"; return true; } std::unique_ptr<llvm::MemoryBuffer> Code = std::move(CodeOrErr.get()); if (Code->getBufferSize() == 0) return false; // Empty files are formatted correctly. FormatterDocument Doc(std::move(Code)); if (!Offsets.empty() || !Lengths.empty()) { if (Offsets.size() != Lengths.size()) { llvm::errs() << "error: number of offsets not equal to number of lengths.\n"; return true; } for ( unsigned i=0 ; i < Offsets.size() ; i++ ) { unsigned FromLine = Doc.getLineAndColumn(Offsets[i]).first; unsigned ToLine = Doc.getLineAndColumn(Offsets[i] + Lengths[i]).first; if (ToLine == 0) { llvm::errs() << "error: offset + length after end of file\n"; return true; } std::ostringstream s; s << FromLine << ":" << ToLine; LineRanges.push_back(s.str()); } } if (LineRanges.empty()) LineRanges.push_back("1:999999"); std::string Output = Doc.memBuffer().getBuffer(); Replacements Replaces; for ( unsigned Range = 0 ; Range < LineRanges.size() ; Range++ ) { unsigned FromLine, ToLine; if (parseLineRange(LineRanges[Range], FromLine, ToLine)) { llvm::errs() << "error: invalid <start line>:<end line> pair\n"; return true; } if (FromLine > ToLine) { llvm::errs() << "error: start line should be less than end line\n"; return true; } for ( unsigned Line = FromLine ; Line<=ToLine ; Line++ ) { size_t Offset = getOffsetOfLine(Line,Output); ssize_t Length = getOffsetOfLine(Line+1,Output)-1-Offset; if (Length < 0) break; std::string Formatted = Doc.reformat(LineRange(Line,1), FormatOptions).second; if (Formatted.find_first_not_of(" \t\v\f", 0) == StringRef::npos) Formatted = ""; if (Formatted == Output.substr(Offset, Length)) continue; Output.replace(Offset, Length, Formatted); Doc.updateCode(std::move(MemoryBuffer::getMemBuffer(Output))); Replaces.insert(clang::tooling::Replacement(FileName, Offset, Length, Formatted)); } } if (OutputXML) { llvm::outs() << "<?xml version='1.0'?>\n<replacements>\n"; outputReplacementsXML(Replaces); llvm::outs() << "</replacements>\n"; } else { if (Inplace) { if (FileName == "-") { llvm::errs() << "error: cannot use -i when reading from stdin.\n"; return true; } else { std::error_code EC; raw_fd_ostream writer(FileName, EC, llvm::sys::fs::F_None); if (EC) { llvm::errs() << "error: writing " << FileName << ": " << EC.message() << "\n"; return true; } writer << Output; } } else { llvm::outs() << Output; } } return false; }
int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. // Initialize targets and assembly printers/parsers. llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargetMCs(); llvm::InitializeAllAsmParsers(); llvm::InitializeAllDisassemblers(); // Register the target printer for --version. cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n"); TripleName = Triple::normalize(TripleName); setDwarfDebugFlags(argc, argv); setDwarfDebugProducer(); const char *ProgName = argv[0]; const Target *TheTarget = GetTarget(ProgName); if (!TheTarget) return 1; OwningPtr<MemoryBuffer> BufferPtr; if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr)) { errs() << ProgName << ": " << ec.message() << '\n'; return 1; } MemoryBuffer *Buffer = BufferPtr.take(); SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what the parser will pick up. SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); // Record the location of the include directories so that the lexer can find // it later. SrcMgr.setIncludeDirs(IncludeDirs); llvm::OwningPtr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); assert(MRI && "Unable to create target register info!"); llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName)); assert(MAI && "Unable to create target asm info!"); // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and // MCObjectFileInfo needs a MCContext reference in order to initialize itself. OwningPtr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr); MOFI->InitMCObjectFileInfo(TripleName, RelocModel, CMModel, Ctx); if (SaveTempLabels) Ctx.setAllowTemporaryLabels(false); Ctx.setGenDwarfForAssembly(GenDwarfForAssembly); if (!DwarfDebugFlags.empty()) Ctx.setDwarfDebugFlags(StringRef(DwarfDebugFlags)); if (!DwarfDebugProducer.empty()) Ctx.setDwarfDebugProducer(StringRef(DwarfDebugProducer)); if (!DebugCompilationDir.empty()) Ctx.setCompilationDir(DebugCompilationDir); if (!MainFileName.empty()) Ctx.setMainFileName(MainFileName); // Package up features to be passed to target/subtarget std::string FeaturesStr; if (MAttrs.size()) { SubtargetFeatures Features; for (unsigned i = 0; i != MAttrs.size(); ++i) Features.AddFeature(MAttrs[i]); FeaturesStr = Features.getString(); } OwningPtr<tool_output_file> Out(GetOutputStream()); if (!Out) return 1; formatted_raw_ostream FOS(Out->os()); OwningPtr<MCStreamer> Str; OwningPtr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); OwningPtr<MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); MCInstPrinter *IP = NULL; if (FileType == OFT_AssemblyFile) { IP = TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI); MCCodeEmitter *CE = 0; MCAsmBackend *MAB = 0; if (ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); } bool UseCFI = !DisableCFI; Str.reset(TheTarget->createAsmStreamer( Ctx, FOS, /*asmverbose*/ true, UseCFI, /*useDwarfDirectory*/ true, IP, CE, MAB, ShowInst)); } else if (FileType == OFT_Null) { Str.reset(createNullStreamer(Ctx)); } else { assert(FileType == OFT_ObjectFile && "Invalid file type!"); MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx); MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU); Str.reset(TheTarget->createMCObjectStreamer(TripleName, Ctx, *MAB, FOS, CE, *STI, RelaxAll, NoExecStack)); } int Res = 1; bool disassemble = false; switch (Action) { case AC_AsLex: Res = AsLexInput(SrcMgr, *MAI, Out.get()); break; case AC_Assemble: Res = AssembleInput(ProgName, TheTarget, SrcMgr, Ctx, *Str, *MAI, *STI, *MCII); break; case AC_MDisassemble: assert(IP && "Expected assembly output"); IP->setUseMarkup(1); disassemble = true; break; case AC_HDisassemble: assert(IP && "Expected assembly output"); IP->setPrintImmHex(1); disassemble = true; break; case AC_Disassemble: disassemble = true; break; } if (disassemble) Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str, *Buffer, SrcMgr, Out->os()); // Keep output if no errors. if (Res == 0) Out->keep(); return Res; }
static int printLineInfoForInput() { // Load any dylibs requested on the command line. loadDylibs(); // If we don't have any input files, read from stdin. if (!InputFileList.size()) InputFileList.push_back("-"); for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) { // Instantiate a dynamic linker. TrivialMemoryManager MemMgr; RuntimeDyld Dyld(MemMgr, MemMgr); // Load the input memory buffer. ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer = MemoryBuffer::getFileOrSTDIN(InputFileList[i]); if (std::error_code EC = InputBuffer.getError()) return Error("unable to read input: '" + EC.message() + "'"); ErrorOr<std::unique_ptr<ObjectFile>> MaybeObj( ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef())); if (std::error_code EC = MaybeObj.getError()) return Error("unable to create object file: '" + EC.message() + "'"); ObjectFile &Obj = **MaybeObj; // Load the object file std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo = Dyld.loadObject(Obj); if (Dyld.hasError()) return Error(Dyld.getErrorString()); // Resolve all the relocations we can. Dyld.resolveRelocations(); OwningBinary<ObjectFile> DebugObj = LoadedObjInfo->getObjectForDebug(Obj); std::unique_ptr<DIContext> Context( DIContext::getDWARFContext(*DebugObj.getBinary())); // Use symbol info to iterate functions in the object. for (object::symbol_iterator I = DebugObj.getBinary()->symbol_begin(), E = DebugObj.getBinary()->symbol_end(); I != E; ++I) { object::SymbolRef::Type SymType; if (I->getType(SymType)) continue; if (SymType == object::SymbolRef::ST_Function) { StringRef Name; uint64_t Addr; uint64_t Size; if (I->getName(Name)) continue; if (I->getAddress(Addr)) continue; if (I->getSize(Size)) continue; outs() << "Function: " << Name << ", Size = " << Size << "\n"; DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size); DILineInfoTable::iterator Begin = Lines.begin(); DILineInfoTable::iterator End = Lines.end(); for (DILineInfoTable::iterator It = Begin; It != End; ++It) { outs() << " Line info @ " << It->first - Addr << ": " << It->second.FileName << ", line:" << It->second.Line << "\n"; } } } } return 0; }
// Load and link the objects specified on the command line, but do not execute // anything. Instead, attach a RuntimeDyldChecker instance and call it to // verify the correctness of the linked memory. static int linkAndVerify() { // Check for missing triple. if (TripleName == "") { llvm::errs() << "Error: -triple required when running in -verify mode.\n"; return 1; } // Look up the target and build the disassembler. Triple TheTriple(Triple::normalize(TripleName)); std::string ErrorStr; const Target *TheTarget = TargetRegistry::lookupTarget("", TheTriple, ErrorStr); if (!TheTarget) { llvm::errs() << "Error accessing target '" << TripleName << "': " << ErrorStr << "\n"; return 1; } TripleName = TheTriple.getTriple(); std::unique_ptr<MCSubtargetInfo> STI( TheTarget->createMCSubtargetInfo(TripleName, "", "")); assert(STI && "Unable to create subtarget info!"); std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); assert(MRI && "Unable to create target register info!"); std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName)); assert(MAI && "Unable to create target asm info!"); MCContext Ctx(MAI.get(), MRI.get(), nullptr); std::unique_ptr<MCDisassembler> Disassembler( TheTarget->createMCDisassembler(*STI, Ctx)); assert(Disassembler && "Unable to create disassembler!"); std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo()); std::unique_ptr<MCInstPrinter> InstPrinter( TheTarget->createMCInstPrinter(Triple(TripleName), 0, *MAI, *MII, *MRI)); // Load any dylibs requested on the command line. loadDylibs(); // Instantiate a dynamic linker. TrivialMemoryManager MemMgr; RuntimeDyld Dyld(MemMgr, MemMgr); Dyld.setProcessAllSections(true); RuntimeDyldChecker Checker(Dyld, Disassembler.get(), InstPrinter.get(), llvm::dbgs()); // FIXME: Preserve buffers until resolveRelocations time to work around a bug // in RuntimeDyldELF. // This fixme should be fixed ASAP. This is a very brittle workaround. std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers; // If we don't have any input files, read from stdin. if (!InputFileList.size()) InputFileList.push_back("-"); for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) { // Load the input memory buffer. ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer = MemoryBuffer::getFileOrSTDIN(InputFileList[i]); if (std::error_code EC = InputBuffer.getError()) return Error("unable to read input: '" + EC.message() + "'"); ErrorOr<std::unique_ptr<ObjectFile>> MaybeObj( ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef())); if (std::error_code EC = MaybeObj.getError()) return Error("unable to create object file: '" + EC.message() + "'"); ObjectFile &Obj = **MaybeObj; InputBuffers.push_back(std::move(*InputBuffer)); // Load the object file Dyld.loadObject(Obj); if (Dyld.hasError()) { return Error(Dyld.getErrorString()); } } // Re-map the section addresses into the phony target address space. remapSections(TheTriple, MemMgr, Checker); // Resolve all the relocations we can. Dyld.resolveRelocations(); // Register EH frames. Dyld.registerEHFrames(); int ErrorCode = checkAllExpressions(Checker); if (Dyld.hasError()) { errs() << "RTDyld reported an error applying relocations:\n " << Dyld.getErrorString() << "\n"; ErrorCode = 1; } return ErrorCode; }
int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(argv[0]); PrettyStackTraceProgram X(argc, argv); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. // Initialize targets and assembly printers/parsers. llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargetMCs(); llvm::InitializeAllAsmParsers(); llvm::InitializeAllDisassemblers(); // Register the target printer for --version. cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n"); MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags(); TripleName = Triple::normalize(TripleName); setDwarfDebugFlags(argc, argv); setDwarfDebugProducer(); const char *ProgName = argv[0]; const Target *TheTarget = GetTarget(ProgName); if (!TheTarget) return 1; // Now that GetTarget() has (potentially) replaced TripleName, it's safe to // construct the Triple object. Triple TheTriple(TripleName); ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr = MemoryBuffer::getFileOrSTDIN(InputFilename); if (std::error_code EC = BufferPtr.getError()) { errs() << InputFilename << ": " << EC.message() << '\n'; return 1; } MemoryBuffer *Buffer = BufferPtr->get(); SourceMgr SrcMgr; // Tell SrcMgr about this buffer, which is what the parser will pick up. SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc()); // Record the location of the include directories so that the lexer can find // it later. SrcMgr.setIncludeDirs(IncludeDirs); std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); assert(MRI && "Unable to create target register info!"); std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName)); assert(MAI && "Unable to create target asm info!"); MAI->setRelaxELFRelocations(RelaxELFRel); if (CompressDebugSections != DebugCompressionType::None) { if (!zlib::isAvailable()) { errs() << ProgName << ": build tools with zlib to enable -compress-debug-sections"; return 1; } MAI->setCompressDebugSections(CompressDebugSections); } MAI->setPreserveAsmComments(PreserveComments); // FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and // MCObjectFileInfo needs a MCContext reference in order to initialize itself. MCObjectFileInfo MOFI; MCContext Ctx(MAI.get(), MRI.get(), &MOFI, &SrcMgr); MOFI.InitMCObjectFileInfo(TheTriple, PIC, CMModel, Ctx); if (SaveTempLabels) Ctx.setAllowTemporaryLabels(false); Ctx.setGenDwarfForAssembly(GenDwarfForAssembly); // Default to 4 for dwarf version. unsigned DwarfVersion = MCOptions.DwarfVersion ? MCOptions.DwarfVersion : 4; if (DwarfVersion < 2 || DwarfVersion > 5) { errs() << ProgName << ": Dwarf version " << DwarfVersion << " is not supported." << '\n'; return 1; } Ctx.setDwarfVersion(DwarfVersion); if (!DwarfDebugFlags.empty()) Ctx.setDwarfDebugFlags(StringRef(DwarfDebugFlags)); if (!DwarfDebugProducer.empty()) Ctx.setDwarfDebugProducer(StringRef(DwarfDebugProducer)); if (!DebugCompilationDir.empty()) Ctx.setCompilationDir(DebugCompilationDir); else { // If no compilation dir is set, try to use the current directory. SmallString<128> CWD; if (!sys::fs::current_path(CWD)) Ctx.setCompilationDir(CWD); } if (!MainFileName.empty()) Ctx.setMainFileName(MainFileName); // Package up features to be passed to target/subtarget std::string FeaturesStr; if (MAttrs.size()) { SubtargetFeatures Features; for (unsigned i = 0; i != MAttrs.size(); ++i) Features.AddFeature(MAttrs[i]); FeaturesStr = Features.getString(); } std::unique_ptr<tool_output_file> Out = GetOutputStream(); if (!Out) return 1; std::unique_ptr<buffer_ostream> BOS; raw_pwrite_stream *OS = &Out->os(); std::unique_ptr<MCStreamer> Str; std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); std::unique_ptr<MCSubtargetInfo> STI( TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); MCInstPrinter *IP = nullptr; if (FileType == OFT_AssemblyFile) { IP = TheTarget->createMCInstPrinter(Triple(TripleName), OutputAsmVariant, *MAI, *MCII, *MRI); if (!IP) { errs() << "error: unable to create instruction printer for target triple '" << TheTriple.normalize() << "' with assembly variant " << OutputAsmVariant << ".\n"; return 1; } // Set the display preference for hex vs. decimal immediates. IP->setPrintImmHex(PrintImmHex); // Set up the AsmStreamer. MCCodeEmitter *CE = nullptr; MCAsmBackend *MAB = nullptr; if (ShowEncoding) { CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx); MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU, MCOptions); } auto FOut = llvm::make_unique<formatted_raw_ostream>(*OS); Str.reset(TheTarget->createAsmStreamer( Ctx, std::move(FOut), /*asmverbose*/ true, /*useDwarfDirectory*/ true, IP, CE, MAB, ShowInst)); } else if (FileType == OFT_Null) { Str.reset(TheTarget->createNullStreamer(Ctx)); } else { assert(FileType == OFT_ObjectFile && "Invalid file type!"); // Don't waste memory on names of temp labels. Ctx.setUseNamesOnTempLabels(false); if (!Out->os().supportsSeeking()) { BOS = make_unique<buffer_ostream>(Out->os()); OS = BOS.get(); } MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx); MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU, MCOptions); Str.reset(TheTarget->createMCObjectStreamer( TheTriple, Ctx, *MAB, *OS, CE, *STI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible, /*DWARFMustBeAtTheEnd*/ false)); if (NoExecStack) Str->InitSections(true); } int Res = 1; bool disassemble = false; switch (Action) { case AC_AsLex: Res = AsLexInput(SrcMgr, *MAI, Out->os()); break; case AC_Assemble: Res = AssembleInput(ProgName, TheTarget, SrcMgr, Ctx, *Str, *MAI, *STI, *MCII, MCOptions); break; case AC_MDisassemble: assert(IP && "Expected assembly output"); IP->setUseMarkup(1); disassemble = true; break; case AC_Disassemble: disassemble = true; break; } if (disassemble) Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str, *Buffer, SrcMgr, Out->os()); // Keep output if no errors. if (Res == 0) Out->keep(); return Res; }
int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); LLVMContext &Context = getGlobalContext(); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n"); // Use lazy loading, since we only care about selected global values. SMDiagnostic Err; std::unique_ptr<Module> M = getLazyIRFileModule(InputFilename, Err, Context); if (!M.get()) { Err.print(argv[0], errs()); return 1; } // Use SetVector to avoid duplicates. SetVector<GlobalValue *> GVs; // Figure out which aliases we should extract. for (size_t i = 0, e = ExtractAliases.size(); i != e; ++i) { GlobalAlias *GA = M->getNamedAlias(ExtractAliases[i]); if (!GA) { errs() << argv[0] << ": program doesn't contain alias named '" << ExtractAliases[i] << "'!\n"; return 1; } GVs.insert(GA); } // Extract aliases via regular expression matching. for (size_t i = 0, e = ExtractRegExpAliases.size(); i != e; ++i) { std::string Error; Regex RegEx(ExtractRegExpAliases[i]); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpAliases[i] << "' " "invalid regex: " << Error; } bool match = false; for (Module::alias_iterator GA = M->alias_begin(), E = M->alias_end(); GA != E; GA++) { if (RegEx.match(GA->getName())) { GVs.insert(&*GA); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpAliases[i] << "'!\n"; return 1; } } // Figure out which globals we should extract. for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) { GlobalValue *GV = M->getNamedGlobal(ExtractGlobals[i]); if (!GV) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractGlobals[i] << "'!\n"; return 1; } GVs.insert(GV); } // Extract globals via regular expression matching. for (size_t i = 0, e = ExtractRegExpGlobals.size(); i != e; ++i) { std::string Error; Regex RegEx(ExtractRegExpGlobals[i]); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpGlobals[i] << "' " "invalid regex: " << Error; } bool match = false; for (auto &GV : M->globals()) { if (RegEx.match(GV.getName())) { GVs.insert(&GV); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpGlobals[i] << "'!\n"; return 1; } } // Figure out which functions we should extract. for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) { GlobalValue *GV = M->getFunction(ExtractFuncs[i]); if (!GV) { errs() << argv[0] << ": program doesn't contain function named '" << ExtractFuncs[i] << "'!\n"; return 1; } GVs.insert(GV); } // Extract functions via regular expression matching. for (size_t i = 0, e = ExtractRegExpFuncs.size(); i != e; ++i) { std::string Error; StringRef RegExStr = ExtractRegExpFuncs[i]; Regex RegEx(RegExStr); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpFuncs[i] << "' " "invalid regex: " << Error; } bool match = false; for (Module::iterator F = M->begin(), E = M->end(); F != E; F++) { if (RegEx.match(F->getName())) { GVs.insert(&*F); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpFuncs[i] << "'!\n"; return 1; } } // Materialize requisite global values. if (!DeleteFn) for (size_t i = 0, e = GVs.size(); i != e; ++i) { GlobalValue *GV = GVs[i]; if (GV->isMaterializable()) { std::string ErrInfo; if (GV->Materialize(&ErrInfo)) { errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; return 1; } } } else { // Deleting. Materialize every GV that's *not* in GVs. SmallPtrSet<GlobalValue *, 8> GVSet(GVs.begin(), GVs.end()); for (auto &G : M->globals()) { if (!GVSet.count(&G) && G.isMaterializable()) { std::string ErrInfo; if (G.Materialize(&ErrInfo)) { errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; return 1; } } } for (auto &F : *M) { if (!GVSet.count(&F) && F.isMaterializable()) { std::string ErrInfo; if (F.Materialize(&ErrInfo)) { errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; return 1; } } } } // In addition to deleting all other functions, we also want to spiff it // up a little bit. Do this now. PassManager Passes; Passes.add(new DataLayoutPass(M.get())); // Use correct DataLayout std::vector<GlobalValue*> Gvs(GVs.begin(), GVs.end()); Passes.add(createGVExtractionPass(Gvs, DeleteFn)); if (!DeleteFn) Passes.add(createGlobalDCEPass()); // Delete unreachable globals Passes.add(createStripDeadDebugInfoPass()); // Remove dead debug info Passes.add(createStripDeadPrototypesPass()); // Remove dead func decls std::error_code EC; tool_output_file Out(OutputFilename, EC, sys::fs::F_None); if (EC) { errs() << EC.message() << '\n'; return 1; } if (OutputAssembly) Passes.add(createPrintModulePass(Out.os())); else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true)) Passes.add(createBitcodeWriterPass(Out.os())); Passes.run(*M.get()); // Declare success. Out.keep(); return 0; }
int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); LLVMContext &Context = getGlobalContext(); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm linker\n"); unsigned BaseArg = 0; std::string ErrorMessage; OwningPtr<Module> Composite(LoadFile(argv[0], InputFilenames[BaseArg], Context)); if (Composite.get() == 0) { errs() << argv[0] << ": error loading file '" << InputFilenames[BaseArg] << "'\n"; return 1; } Linker L(Composite.get(), SuppressWarnings); for (unsigned i = BaseArg+1; i < InputFilenames.size(); ++i) { OwningPtr<Module> M(LoadFile(argv[0], InputFilenames[i], Context)); if (M.get() == 0) { errs() << argv[0] << ": error loading file '" <<InputFilenames[i]<< "'\n"; return 1; } if (Verbose) errs() << "Linking in '" << InputFilenames[i] << "'\n"; if (L.linkInModule(M.get(), &ErrorMessage)) { errs() << argv[0] << ": link error in '" << InputFilenames[i] << "': " << ErrorMessage << "\n"; return 1; } } if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite; std::string ErrorInfo; tool_output_file Out(OutputFilename.c_str(), ErrorInfo, sys::fs::F_None); if (!ErrorInfo.empty()) { errs() << ErrorInfo << '\n'; return 1; } if (verifyModule(*Composite)) { errs() << argv[0] << ": linked module is broken!\n"; return 1; } if (Verbose) errs() << "Writing bitcode...\n"; if (OutputAssembly) { Out.os() << *Composite; } else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true)) WriteBitcodeToFile(Composite.get(), Out.os()); // Declare success. Out.keep(); return 0; }
/// runPasses - Run the specified passes on Program, outputting a bitcode file /// and writing the filename into OutputFile if successful. If the /// optimizations fail for some reason (optimizer crashes), return true, /// otherwise return false. If DeleteOutput is set to true, the bitcode is /// deleted on success, and the filename string is undefined. This prints to /// outs() a single line message indicating whether compilation was successful /// or failed. /// bool BugDriver::runPasses(Module &Program, const std::vector<std::string> &Passes, std::string &OutputFilename, bool DeleteOutput, bool Quiet, unsigned NumExtraArgs, const char *const *ExtraArgs) const { // setup the output file name outs().flush(); SmallString<128> UniqueFilename; std::error_code EC = sys::fs::createUniqueFile( OutputPrefix + "-output-%%%%%%%.bc", UniqueFilename); if (EC) { errs() << getToolName() << ": Error making unique filename: " << EC.message() << "\n"; return 1; } OutputFilename = UniqueFilename.str(); // set up the input file name Expected<sys::fs::TempFile> Temp = sys::fs::TempFile::create(OutputPrefix + "-input-%%%%%%%.bc"); if (!Temp) { errs() << getToolName() << ": Error making unique filename: " << toString(Temp.takeError()) << "\n"; return 1; } DiscardTemp Discard{*Temp}; raw_fd_ostream OS(Temp->FD, /*shouldClose*/ false); WriteBitcodeToFile(Program, OS, PreserveBitcodeUseListOrder); OS.flush(); if (OS.has_error()) { errs() << "Error writing bitcode file: " << Temp->TmpName << "\n"; OS.clear_error(); return 1; } std::string tool = OptCmd; if (OptCmd.empty()) { if (ErrorOr<std::string> Path = sys::findProgramByName("opt")) tool = *Path; else errs() << Path.getError().message() << "\n"; } if (tool.empty()) { errs() << "Cannot find `opt' in PATH!\n"; return 1; } if (!sys::fs::exists(tool)) { errs() << "Specified `opt' binary does not exist: " << tool << "\n"; return 1; } std::string Prog; if (UseValgrind) { if (ErrorOr<std::string> Path = sys::findProgramByName("valgrind")) Prog = *Path; else errs() << Path.getError().message() << "\n"; } else Prog = tool; if (Prog.empty()) { errs() << "Cannot find `valgrind' in PATH!\n"; return 1; } // setup the child process' arguments SmallVector<StringRef, 8> Args; if (UseValgrind) { Args.push_back("valgrind"); Args.push_back("--error-exitcode=1"); Args.push_back("-q"); Args.push_back(tool); } else Args.push_back(tool); for (unsigned i = 0, e = OptArgs.size(); i != e; ++i) Args.push_back(OptArgs[i]); Args.push_back("-disable-symbolication"); Args.push_back("-o"); Args.push_back(OutputFilename); std::vector<std::string> pass_args; for (unsigned i = 0, e = PluginLoader::getNumPlugins(); i != e; ++i) { pass_args.push_back(std::string("-load")); pass_args.push_back(PluginLoader::getPlugin(i)); } for (std::vector<std::string>::const_iterator I = Passes.begin(), E = Passes.end(); I != E; ++I) pass_args.push_back(std::string("-") + (*I)); for (std::vector<std::string>::const_iterator I = pass_args.begin(), E = pass_args.end(); I != E; ++I) Args.push_back(I->c_str()); Args.push_back(Temp->TmpName.c_str()); for (unsigned i = 0; i < NumExtraArgs; ++i) Args.push_back(*ExtraArgs); LLVM_DEBUG(errs() << "\nAbout to run:\t"; for (unsigned i = 0, e = Args.size() - 1; i != e; ++i) errs() << " " << Args[i]; errs() << "\n";);
// main - Entry point for the llc compiler. // int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); // Enable debug stream buffering. EnableDebugBuffering = true; LLVMContext &Context = getGlobalContext(); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. // Initialize targets first, so that --version shows registered targets. InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); InitializeAllAsmParsers(); // Register the target printer for --version. cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n"); // Load the module to be compiled... SMDiagnostic Err; std::auto_ptr<Module> M; M.reset(ParseIRFile(InputFilename, Err, Context)); if (M.get() == 0) { Err.print(argv[0], errs()); return 1; } Module &mod = *M.get(); // If we are supposed to override the target triple, do so now. if (!TargetTriple.empty()) mod.setTargetTriple(Triple::normalize(TargetTriple)); Triple TheTriple(mod.getTargetTriple()); if (TheTriple.getTriple().empty()) TheTriple.setTriple(sys::getDefaultTargetTriple()); // Allocate target machine. First, check whether the user has explicitly // specified an architecture to compile for. If so we have to look it up by // name, because it might be a backend that has no mapping to a target triple. const Target *TheTarget = 0; if (!MArch.empty()) { for (TargetRegistry::iterator it = TargetRegistry::begin(), ie = TargetRegistry::end(); it != ie; ++it) { if (MArch == it->getName()) { TheTarget = &*it; break; } } if (!TheTarget) { errs() << argv[0] << ": error: invalid target '" << MArch << "'.\n"; return 1; } // Adjust the triple to match (if known), otherwise stick with the // module/host triple. Triple::ArchType Type = Triple::getArchTypeForLLVMName(MArch); if (Type != Triple::UnknownArch) TheTriple.setArch(Type); } else { std::string Err; TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), Err); if (TheTarget == 0) { errs() << argv[0] << ": error auto-selecting target for module '" << Err << "'. Please use the -march option to explicitly " << "pick a target.\n"; return 1; } } // Package up features to be passed to target/subtarget std::string FeaturesStr; if (MAttrs.size()) { SubtargetFeatures Features; for (unsigned i = 0; i != MAttrs.size(); ++i) Features.AddFeature(MAttrs[i]); FeaturesStr = Features.getString(); } CodeGenOpt::Level OLvl = CodeGenOpt::Default; switch (OptLevel) { default: errs() << argv[0] << ": invalid optimization level.\n"; return 1; case ' ': break; case '0': OLvl = CodeGenOpt::None; break; case '1': OLvl = CodeGenOpt::Less; break; case '2': OLvl = CodeGenOpt::Default; break; case '3': OLvl = CodeGenOpt::Aggressive; break; } TargetOptions Options; Options.LessPreciseFPMADOption = EnableFPMAD; Options.PrintMachineCode = PrintCode; Options.NoFramePointerElim = DisableFPElim; Options.NoFramePointerElimNonLeaf = DisableFPElimNonLeaf; Options.NoExcessFPPrecision = DisableExcessPrecision; Options.UnsafeFPMath = EnableUnsafeFPMath; Options.NoInfsFPMath = EnableNoInfsFPMath; Options.NoNaNsFPMath = EnableNoNaNsFPMath; Options.HonorSignDependentRoundingFPMathOption = EnableHonorSignDependentRoundingFPMath; Options.UseSoftFloat = GenerateSoftFloatCalls; if (FloatABIForCalls != FloatABI::Default) Options.FloatABIType = FloatABIForCalls; Options.NoZerosInBSS = DontPlaceZerosInBSS; Options.JITExceptionHandling = EnableJITExceptionHandling; Options.JITEmitDebugInfo = EmitJitDebugInfo; Options.JITEmitDebugInfoToDisk = EmitJitDebugInfoToDisk; Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt; Options.StackAlignmentOverride = OverrideStackAlignment; Options.RealignStack = EnableRealignStack; Options.DisableJumpTables = DisableSwitchTables; Options.TrapFuncName = TrapFuncName; Options.EnableSegmentedStacks = SegmentedStacks; std::auto_ptr<TargetMachine> target(TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, FeaturesStr, Options, RelocModel, CMModel, OLvl)); assert(target.get() && "Could not allocate target machine!"); TargetMachine &Target = *target.get(); if (DisableDotLoc) Target.setMCUseLoc(false); if (DisableCFI) Target.setMCUseCFI(false); if (EnableDwarfDirectory) Target.setMCUseDwarfDirectory(true); if (GenerateSoftFloatCalls) FloatABIForCalls = FloatABI::Soft; // Disable .loc support for older OS X versions. if (TheTriple.isMacOSX() && TheTriple.isMacOSXVersionLT(10, 6)) Target.setMCUseLoc(false); // Figure out where we are going to send the output... OwningPtr<tool_output_file> Out (GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0])); if (!Out) return 1; // Build up all of the passes that we want to do to the module. PassManager PM; // Add the target data from the target machine, if it exists, or the module. if (const TargetData *TD = Target.getTargetData()) PM.add(new TargetData(*TD)); else PM.add(new TargetData(&mod)); // Override default to generate verbose assembly. Target.setAsmVerbosityDefault(true); if (RelaxAll) { if (FileType != TargetMachine::CGFT_ObjectFile) errs() << argv[0] << ": warning: ignoring -mc-relax-all because filetype != obj"; else Target.setMCRelaxAll(true); } { formatted_raw_ostream FOS(Out->os()); // Ask the target to add backend passes as necessary. if (Target.addPassesToEmitFile(PM, FOS, FileType, NoVerify)) { errs() << argv[0] << ": target does not support generation of this" << " file type!\n"; return 1; } // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); PM.run(mod); } // Declare success. Out->keep(); return 0; }
//===----------------------------------------------------------------------===// // main for opt // int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); if (AnalyzeOnly && NoOutput) { errs() << argv[0] << ": analyze mode conflicts with no-output mode.\n"; return 1; } // Enable debug stream buffering. EnableDebugBuffering = true; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. LLVMContext &Context = getGlobalContext(); cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .bc modular optimizer and analysis printer\n"); // Allocate a full target machine description only if necessary. // FIXME: The choice of target should be controllable on the command line. std::auto_ptr<TargetMachine> target; SMDiagnostic Err; // Load the input module... std::auto_ptr<Module> M; M.reset(ParseIRFile(InputFilename, Err, Context)); if (M.get() == 0) { Err.Print(argv[0], errs()); return 1; } // Figure out what stream we are supposed to write to... OwningPtr<tool_output_file> Out; if (NoOutput) { if (!OutputFilename.empty()) errs() << "WARNING: The -o (output filename) option is ignored when\n" "the --disable-output option is used.\n"; } else { // Default to standard output. if (OutputFilename.empty()) OutputFilename = "-"; std::string ErrorInfo; Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo, raw_fd_ostream::F_Binary)); if (!ErrorInfo.empty()) { errs() << ErrorInfo << '\n'; return 1; } } // If the output is set to be emitted to standard out, and standard out is a // console, print out a warning message and refuse to do it. We don't // impress anyone by spewing tons of binary goo to a terminal. if (!Force && !NoOutput && !AnalyzeOnly && !OutputAssembly) if (CheckBitcodeOutputToConsole(Out->os(), !Quiet)) NoOutput = true; // Create a PassManager to hold and optimize the collection of passes we are // about to build... // PassManager Passes; // Add an appropriate TargetData instance for this module... TargetData *TD = 0; const std::string &ModuleDataLayout = M.get()->getDataLayout(); if (!ModuleDataLayout.empty()) TD = new TargetData(ModuleDataLayout); else if (!DefaultDataLayout.empty()) TD = new TargetData(DefaultDataLayout); if (TD) Passes.add(TD); OwningPtr<PassManager> FPasses; if (OptLevelO1 || OptLevelO2 || OptLevelO3) { FPasses.reset(new PassManager()); if (TD) FPasses->add(new TargetData(*TD)); } // If the -strip-debug command line option was specified, add it. If // -std-compile-opts was also specified, it will handle StripDebug. if (StripDebug && !StandardCompileOpts) addPass(Passes, createStripSymbolsPass(true)); // Create a new optimization pass for each one specified on the command line for (unsigned i = 0; i < PassList.size(); ++i) { // Check to see if -std-compile-opts was specified before this option. If // so, handle it. if (StandardCompileOpts && StandardCompileOpts.getPosition() < PassList.getPosition(i)) { AddStandardCompilePasses(Passes); StandardCompileOpts = false; } if (StandardLinkOpts && StandardLinkOpts.getPosition() < PassList.getPosition(i)) { AddStandardLinkPasses(Passes); StandardLinkOpts = false; } if (OptLevelO1 && OptLevelO1.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 1); OptLevelO1 = false; } if (OptLevelO2 && OptLevelO2.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 2); OptLevelO2 = false; } if (OptLevelO3 && OptLevelO3.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 3); OptLevelO3 = false; } const PassInfo *PassInf = PassList[i]; Pass *P = 0; if (PassInf->getNormalCtor()) P = PassInf->getNormalCtor()(); else errs() << argv[0] << ": cannot create pass: "******"\n"; if (P) { PassKind Kind = P->getPassKind(); addPass(Passes, P); if (AnalyzeOnly) { switch (Kind) { case PT_BasicBlock: Passes.add(new BasicBlockPassPrinter(PassInf, Out->os())); break; case PT_Loop: Passes.add(new LoopPassPrinter(PassInf, Out->os())); break; case PT_Function: Passes.add(new FunctionPassPrinter(PassInf, Out->os())); break; case PT_CallGraphSCC: Passes.add(new CallGraphSCCPassPrinter(PassInf, Out->os())); break; default: Passes.add(new ModulePassPrinter(PassInf, Out->os())); break; } } } if (PrintEachXForm) Passes.add(createPrintModulePass(&errs())); } // If -std-compile-opts was specified at the end of the pass list, add them. if (StandardCompileOpts) { AddStandardCompilePasses(Passes); StandardCompileOpts = false; } if (StandardLinkOpts) { AddStandardLinkPasses(Passes); StandardLinkOpts = false; } if (OptLevelO1) AddOptimizationPasses(Passes, *FPasses, 1); if (OptLevelO2) AddOptimizationPasses(Passes, *FPasses, 2); if (OptLevelO3) AddOptimizationPasses(Passes, *FPasses, 3); if (OptLevelO1 || OptLevelO2 || OptLevelO3) FPasses->run(*M.get()); // Check that the module is well formed on completion of optimization if (!NoVerify && !VerifyEach) Passes.add(createVerifierPass()); // Write bitcode or assembly to the output as the last step... if (!NoOutput && !AnalyzeOnly) { if (OutputAssembly) Passes.add(createPrintModulePass(&Out->os())); else Passes.add(createBitcodeWriterPass(Out->os())); } // Now that we have all of the passes ready, run them. Passes.run(*M.get()); // Declare success. if (!NoOutput) Out->keep(); return 0; }
static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) { assert(LoadObjects || !UseDebugObj); // Load any dylibs requested on the command line. loadDylibs(); // If we don't have any input files, read from stdin. if (!InputFileList.size()) InputFileList.push_back("-"); for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) { // Instantiate a dynamic linker. TrivialMemoryManager MemMgr; RuntimeDyld Dyld(MemMgr, MemMgr); // Load the input memory buffer. ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer = MemoryBuffer::getFileOrSTDIN(InputFileList[i]); if (std::error_code EC = InputBuffer.getError()) return Error("unable to read input: '" + EC.message() + "'"); ErrorOr<std::unique_ptr<ObjectFile>> MaybeObj( ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef())); if (std::error_code EC = MaybeObj.getError()) return Error("unable to create object file: '" + EC.message() + "'"); ObjectFile &Obj = **MaybeObj; OwningBinary<ObjectFile> DebugObj; std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo = nullptr; ObjectFile *SymbolObj = &Obj; if (LoadObjects) { // Load the object file LoadedObjInfo = Dyld.loadObject(Obj); if (Dyld.hasError()) return Error(Dyld.getErrorString()); // Resolve all the relocations we can. Dyld.resolveRelocations(); if (UseDebugObj) { DebugObj = LoadedObjInfo->getObjectForDebug(Obj); SymbolObj = DebugObj.getBinary(); LoadedObjInfo.reset(); } } std::unique_ptr<DIContext> Context( new DWARFContextInMemory(*SymbolObj,LoadedObjInfo.get())); std::vector<std::pair<SymbolRef, uint64_t>> SymAddr = object::computeSymbolSizes(*SymbolObj); // Use symbol info to iterate functions in the object. for (const auto &P : SymAddr) { object::SymbolRef Sym = P.first; if (Sym.getType() == object::SymbolRef::ST_Function) { ErrorOr<StringRef> Name = Sym.getName(); if (!Name) continue; ErrorOr<uint64_t> AddrOrErr = Sym.getAddress(); if (!AddrOrErr) continue; uint64_t Addr = *AddrOrErr; uint64_t Size = P.second; // If we're not using the debug object, compute the address of the // symbol in memory (rather than that in the unrelocated object file) // and use that to query the DWARFContext. if (!UseDebugObj && LoadObjects) { object::section_iterator Sec(SymbolObj->section_end()); Sym.getSection(Sec); StringRef SecName; Sec->getName(SecName); uint64_t SectionLoadAddress = LoadedObjInfo->getSectionLoadAddress(*Sec); if (SectionLoadAddress != 0) Addr += SectionLoadAddress - Sec->getAddress(); } outs() << "Function: " << *Name << ", Size = " << Size << ", Addr = " << Addr << "\n"; DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size); DILineInfoTable::iterator Begin = Lines.begin(); DILineInfoTable::iterator End = Lines.end(); for (DILineInfoTable::iterator It = Begin; It != End; ++It) { outs() << " Line info @ " << It->first - Addr << ": " << It->second.FileName << ", line:" << It->second.Line << "\n"; } } } } return 0; }
////////////////////////////////////////////////////////////////////////////////////////// // This function runs optimization passes based on command line arguments. // Returns true if any optimization passes were invoked. bool ldc_optimize_module(llvm::Module* m) { // Create a PassManager to hold and optimize the collection of // per-module passes we are about to build. PassManager mpm; // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfo *tli = new TargetLibraryInfo(Triple(m->getTargetTriple())); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (disableSimplifyLibCalls) tli->disableAllFunctions(); mpm.add(tli); // Add an appropriate TargetData instance for this module. #if LDC_LLVM_VER >= 302 mpm.add(new DataLayout(m)); #else mpm.add(new TargetData(m)); #endif // Also set up a manager for the per-function passes. FunctionPassManager fpm(m); #if LDC_LLVM_VER >= 302 fpm.add(new DataLayout(m)); #else fpm.add(new TargetData(m)); #endif // If the -strip-debug command line option was specified, add it before // anything else. if (stripDebug) mpm.add(createStripSymbolsPass(true)); bool defaultsAdded = false; // Create a new optimization pass for each one specified on the command line for (unsigned i = 0; i < passList.size(); ++i) { if (optimizeLevel && optimizeLevel.getPosition() < passList.getPosition(i)) { addOptimizationPasses(mpm, fpm, optLevel(), sizeLevel()); defaultsAdded = true; } const PassInfo *passInf = passList[i]; Pass *pass = 0; if (passInf->getNormalCtor()) pass = passInf->getNormalCtor()(); else { const char* arg = passInf->getPassArgument(); // may return null if (arg) error("Can't create pass '-%s' (%s)", arg, pass->getPassName()); else error("Can't create pass (%s)", pass->getPassName()); llvm_unreachable("pass creation failed"); } if (pass) { addPass(mpm, pass); } } // Add the default passes for the specified optimization level. if (!defaultsAdded) addOptimizationPasses(mpm, fpm, optLevel(), sizeLevel()); // Run per-function passes. fpm.doInitialization(); for (llvm::Module::iterator F = m->begin(), E = m->end(); F != E; ++F) fpm.run(*F); fpm.doFinalization(); // Run per-module passes. mpm.run(*m); // Verify the resulting module. verifyModule(m); // Report that we run some passes. return true; }
// getRelPos - Extract the member filename from the command line for // the [relpos] argument associated with a, b, and i modifiers static void getRelPos() { if(RestOfArgs.size() == 0) show_help("Expected [relpos] for a, b, or i modifier"); RelPos = RestOfArgs[0]; RestOfArgs.erase(RestOfArgs.begin()); }
//===----------------------------------------------------------------------===// // main for opt // int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); // Enable debug stream buffering. EnableDebugBuffering = true; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. LLVMContext &Context = getGlobalContext(); InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); // Initialize passes PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); initializeScalarOpts(Registry); initializeObjCARCOpts(Registry); initializeVectorization(Registry); initializeIPO(Registry); initializeAnalysis(Registry); initializeIPA(Registry); initializeTransformUtils(Registry); initializeInstCombine(Registry); initializeInstrumentation(Registry); initializeTarget(Registry); // For codegen passes, only passes that do IR to IR transformation are // supported. initializeCodeGenPreparePass(Registry); initializeAtomicExpandPass(Registry); initializeRewriteSymbolsPass(Registry); initializeWinEHPreparePass(Registry); initializeDwarfEHPreparePass(Registry); #ifdef LINK_POLLY_INTO_TOOLS polly::initializePollyPasses(Registry); #endif cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .bc modular optimizer and analysis printer\n"); if (AnalyzeOnly && NoOutput) { errs() << argv[0] << ": analyze mode conflicts with no-output mode.\n"; return 1; } SMDiagnostic Err; // Load the input module... std::unique_ptr<Module> M = parseIRFile(InputFilename, Err, Context); if (!M) { Err.print(argv[0], errs()); return 1; } // If we are supposed to override the target triple, do so now. if (!TargetTriple.empty()) M->setTargetTriple(Triple::normalize(TargetTriple)); // Figure out what stream we are supposed to write to... std::unique_ptr<tool_output_file> Out; if (NoOutput) { if (!OutputFilename.empty()) errs() << "WARNING: The -o (output filename) option is ignored when\n" "the --disable-output option is used.\n"; } else { // Default to standard output. if (OutputFilename.empty()) OutputFilename = "-"; std::error_code EC; Out.reset(new tool_output_file(OutputFilename, EC, sys::fs::F_None)); if (EC) { errs() << EC.message() << '\n'; return 1; } } Triple ModuleTriple(M->getTargetTriple()); TargetMachine *Machine = nullptr; if (ModuleTriple.getArch()) Machine = GetTargetMachine(ModuleTriple); std::unique_ptr<TargetMachine> TM(Machine); // If the output is set to be emitted to standard out, and standard out is a // console, print out a warning message and refuse to do it. We don't // impress anyone by spewing tons of binary goo to a terminal. if (!Force && !NoOutput && !AnalyzeOnly && !OutputAssembly) if (CheckBitcodeOutputToConsole(Out->os(), !Quiet)) NoOutput = true; if (PassPipeline.getNumOccurrences() > 0) { OutputKind OK = OK_NoOutput; if (!NoOutput) OK = OutputAssembly ? OK_OutputAssembly : OK_OutputBitcode; VerifierKind VK = VK_VerifyInAndOut; if (NoVerify) VK = VK_NoVerifier; else if (VerifyEach) VK = VK_VerifyEachPass; // The user has asked to use the new pass manager and provided a pipeline // string. Hand off the rest of the functionality to the new code for that // layer. return runPassPipeline(argv[0], Context, *M, TM.get(), Out.get(), PassPipeline, OK, VK) ? 0 : 1; } // Create a PassManager to hold and optimize the collection of passes we are // about to build. // legacy::PassManager Passes; // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfoImpl TLII(ModuleTriple); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (DisableSimplifyLibCalls) TLII.disableAllFunctions(); Passes.add(new TargetLibraryInfoWrapperPass(TLII)); // Add an appropriate DataLayout instance for this module. const DataLayout &DL = M->getDataLayout(); if (DL.isDefault() && !DefaultDataLayout.empty()) { M->setDataLayout(DefaultDataLayout); } // Add internal analysis passes from the target machine. Passes.add(createTargetTransformInfoWrapperPass(TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis())); std::unique_ptr<legacy::FunctionPassManager> FPasses; if (OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) { FPasses.reset(new legacy::FunctionPassManager(M.get())); FPasses->add(createTargetTransformInfoWrapperPass( TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis())); } if (PrintBreakpoints) { // Default to standard output. if (!Out) { if (OutputFilename.empty()) OutputFilename = "-"; std::error_code EC; Out = llvm::make_unique<tool_output_file>(OutputFilename, EC, sys::fs::F_None); if (EC) { errs() << EC.message() << '\n'; return 1; } } Passes.add(createBreakpointPrinter(Out->os())); NoOutput = true; } // If the -strip-debug command line option was specified, add it. if (StripDebug) addPass(Passes, createStripSymbolsPass(true)); // Create a new optimization pass for each one specified on the command line for (unsigned i = 0; i < PassList.size(); ++i) { if (StandardLinkOpts && StandardLinkOpts.getPosition() < PassList.getPosition(i)) { AddStandardLinkPasses(Passes); StandardLinkOpts = false; } if (OptLevelO1 && OptLevelO1.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 1, 0); OptLevelO1 = false; } if (OptLevelO2 && OptLevelO2.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 2, 0); OptLevelO2 = false; } if (OptLevelOs && OptLevelOs.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 2, 1); OptLevelOs = false; } if (OptLevelOz && OptLevelOz.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 2, 2); OptLevelOz = false; } if (OptLevelO3 && OptLevelO3.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 3, 0); OptLevelO3 = false; } const PassInfo *PassInf = PassList[i]; Pass *P = nullptr; if (PassInf->getTargetMachineCtor()) P = PassInf->getTargetMachineCtor()(TM.get()); else if (PassInf->getNormalCtor()) P = PassInf->getNormalCtor()(); else errs() << argv[0] << ": cannot create pass: "******"\n"; if (P) { PassKind Kind = P->getPassKind(); addPass(Passes, P); if (AnalyzeOnly) { switch (Kind) { case PT_BasicBlock: Passes.add(createBasicBlockPassPrinter(PassInf, Out->os(), Quiet)); break; case PT_Region: Passes.add(createRegionPassPrinter(PassInf, Out->os(), Quiet)); break; case PT_Loop: Passes.add(createLoopPassPrinter(PassInf, Out->os(), Quiet)); break; case PT_Function: Passes.add(createFunctionPassPrinter(PassInf, Out->os(), Quiet)); break; case PT_CallGraphSCC: Passes.add(createCallGraphPassPrinter(PassInf, Out->os(), Quiet)); break; default: Passes.add(createModulePassPrinter(PassInf, Out->os(), Quiet)); break; } } } if (PrintEachXForm) Passes.add(createPrintModulePass(errs())); } if (StandardLinkOpts) { AddStandardLinkPasses(Passes); StandardLinkOpts = false; } if (OptLevelO1) AddOptimizationPasses(Passes, *FPasses, 1, 0); if (OptLevelO2) AddOptimizationPasses(Passes, *FPasses, 2, 0); if (OptLevelOs) AddOptimizationPasses(Passes, *FPasses, 2, 1); if (OptLevelOz) AddOptimizationPasses(Passes, *FPasses, 2, 2); if (OptLevelO3) AddOptimizationPasses(Passes, *FPasses, 3, 0); if (OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) { FPasses->doInitialization(); for (Function &F : *M) FPasses->run(F); FPasses->doFinalization(); } // Check that the module is well formed on completion of optimization if (!NoVerify && !VerifyEach) { Passes.add(createVerifierPass()); Passes.add(createDebugInfoVerifierPass()); } // Write bitcode or assembly to the output as the last step... if (!NoOutput && !AnalyzeOnly) { if (OutputAssembly) Passes.add(createPrintModulePass(Out->os())); else Passes.add(createBitcodeWriterPass(Out->os())); } // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); // Now that we have all of the passes ready, run them. Passes.run(*M); // Declare success. if (!NoOutput || PrintBreakpoints) Out->keep(); return 0; }
static void getOptions() { if(RestOfArgs.size() == 0) show_help("Expected options"); Options = RestOfArgs[0]; RestOfArgs.erase(RestOfArgs.begin()); }
static int executeInput() { // Load any dylibs requested on the command line. loadDylibs(); // Instantiate a dynamic linker. TrivialMemoryManager MemMgr; RuntimeDyld Dyld(MemMgr, MemMgr); // FIXME: Preserve buffers until resolveRelocations time to work around a bug // in RuntimeDyldELF. // This fixme should be fixed ASAP. This is a very brittle workaround. std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers; // If we don't have any input files, read from stdin. if (!InputFileList.size()) InputFileList.push_back("-"); for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) { // Load the input memory buffer. ErrorOr<std::unique_ptr<MemoryBuffer>> InputBuffer = MemoryBuffer::getFileOrSTDIN(InputFileList[i]); if (std::error_code EC = InputBuffer.getError()) return Error("unable to read input: '" + EC.message() + "'"); ErrorOr<std::unique_ptr<ObjectFile>> MaybeObj( ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef())); if (std::error_code EC = MaybeObj.getError()) return Error("unable to create object file: '" + EC.message() + "'"); ObjectFile &Obj = **MaybeObj; InputBuffers.push_back(std::move(*InputBuffer)); // Load the object file Dyld.loadObject(Obj); if (Dyld.hasError()) { return Error(Dyld.getErrorString()); } } // Resolve all the relocations we can. Dyld.resolveRelocations(); // Clear instruction cache before code will be executed. MemMgr.invalidateInstructionCache(); // FIXME: Error out if there are unresolved relocations. // Get the address of the entry point (_main by default). void *MainAddress = Dyld.getSymbolLocalAddress(EntryPoint); if (!MainAddress) return Error("no definition for '" + EntryPoint + "'"); // Invalidate the instruction cache for each loaded function. for (unsigned i = 0, e = MemMgr.FunctionMemory.size(); i != e; ++i) { sys::MemoryBlock &Data = MemMgr.FunctionMemory[i]; // Make sure the memory is executable. std::string ErrorStr; sys::Memory::InvalidateInstructionCache(Data.base(), Data.size()); if (!sys::Memory::setExecutable(Data, &ErrorStr)) return Error("unable to mark function executable: '" + ErrorStr + "'"); } // Dispatch to _main(). errs() << "loaded '" << EntryPoint << "' at: " << (void*)MainAddress << "\n"; int (*Main)(int, const char**) = (int(*)(int,const char**)) uintptr_t(MainAddress); const char **Argv = new const char*[2]; // Use the name of the first input object module as argv[0] for the target. Argv[0] = InputFileList[0].c_str(); Argv[1] = nullptr; return Main(1, Argv); }
// getArchive - Get the archive file name from the command line static void getArchive() { if(RestOfArgs.size() == 0) show_help("An archive name must be specified"); ArchiveName = RestOfArgs[0]; RestOfArgs.erase(RestOfArgs.begin()); }
// This function handles the high level operations of GNU objcopy including // handling command line options. It's important to outline certain properties // we expect to hold of the command line operations. Any operation that "keeps" // should keep regardless of a remove. Additionally any removal should respect // any previous removals. Lastly whether or not something is removed shouldn't // depend a) on the order the options occur in or b) on some opaque priority // system. The only priority is that keeps/copies overrule removes. void HandleArgs(Object &Obj, const Reader &Reader) { if (!SplitDWO.empty()) { SplitDWOToFile(Reader, SplitDWO); } // Localize: if (LocalizeHidden) { Obj.SymbolTable->localize([](const Symbol &Sym) { return Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL; }); } SectionPred RemovePred = [](const SectionBase &) { return false; }; // Removes: if (!ToRemove.empty()) { RemovePred = [&](const SectionBase &Sec) { return std::find(std::begin(ToRemove), std::end(ToRemove), Sec.Name) != std::end(ToRemove); }; } if (StripDWO || !SplitDWO.empty()) RemovePred = [RemovePred](const SectionBase &Sec) { return IsDWOSection(Sec) || RemovePred(Sec); }; if (ExtractDWO) RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { return OnlyKeepDWOPred(Obj, Sec) || RemovePred(Sec); }; if (StripAllGNU) RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { if (RemovePred(Sec)) return true; if ((Sec.Flags & SHF_ALLOC) != 0) return false; if (&Sec == Obj.SectionNames) return false; switch (Sec.Type) { case SHT_SYMTAB: case SHT_REL: case SHT_RELA: case SHT_STRTAB: return true; } return Sec.Name.startswith(".debug"); }; if (StripSections) { RemovePred = [RemovePred](const SectionBase &Sec) { return RemovePred(Sec) || (Sec.Flags & SHF_ALLOC) == 0; }; } if (StripDebug) { RemovePred = [RemovePred](const SectionBase &Sec) { return RemovePred(Sec) || Sec.Name.startswith(".debug"); }; } if (StripNonAlloc) RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { if (RemovePred(Sec)) return true; if (&Sec == Obj.SectionNames) return false; return (Sec.Flags & SHF_ALLOC) == 0; }; if (StripAll) RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { if (RemovePred(Sec)) return true; if (&Sec == Obj.SectionNames) return false; if (Sec.Name.startswith(".gnu.warning")) return false; return (Sec.Flags & SHF_ALLOC) == 0; }; // Explicit copies: if (!OnlyKeep.empty()) { RemovePred = [RemovePred, &Obj](const SectionBase &Sec) { // Explicitly keep these sections regardless of previous removes. if (std::find(std::begin(OnlyKeep), std::end(OnlyKeep), Sec.Name) != std::end(OnlyKeep)) return false; // Allow all implicit removes. if (RemovePred(Sec)) return true; // Keep special sections. if (Obj.SectionNames == &Sec) return false; if (Obj.SymbolTable == &Sec || Obj.SymbolTable->getStrTab() == &Sec) return false; // Remove everything else. return true; }; } if (!Keep.empty()) { RemovePred = [RemovePred](const SectionBase &Sec) { // Explicitly keep these sections regardless of previous removes. if (std::find(std::begin(Keep), std::end(Keep), Sec.Name) != std::end(Keep)) return false; // Otherwise defer to RemovePred. return RemovePred(Sec); }; } Obj.removeSections(RemovePred); if (!AddSection.empty()) { for (const auto &Flag : AddSection) { auto SecPair = StringRef(Flag).split("="); auto SecName = SecPair.first; auto File = SecPair.second; auto BufOrErr = MemoryBuffer::getFile(File); if (!BufOrErr) reportError(File, BufOrErr.getError()); auto Buf = std::move(*BufOrErr); auto BufPtr = reinterpret_cast<const uint8_t *>(Buf->getBufferStart()); auto BufSize = Buf->getBufferSize(); Obj.addSection<OwnedDataSection>(SecName, ArrayRef<uint8_t>(BufPtr, BufSize)); } } if (!AddGnuDebugLink.empty()) { Obj.addSection<GnuDebugLinkSection>(StringRef(AddGnuDebugLink)); } }
// getMembers - Copy over remaining items in RestOfArgs to our Members vector // This is just for clarity. static void getMembers() { if(RestOfArgs.size() > 0) Members = std::vector<std::string>(RestOfArgs); }
namespace format { static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden); // Mark all our options with this category, everything else (except for -version // and -help) will be hidden. static cl::OptionCategory SwiftFormatCategory("Swift-format options"); static cl::list<unsigned> Offsets("offset", cl::desc("Format a range starting at this byte offset.\n" "Multiple ranges can be formatted by specifying\n" "several -offset and -length pairs.\n" "Can only be used with one input file."), cl::cat(SwiftFormatCategory)); static cl::list<unsigned> Lengths("length", cl::desc("Format a range of this length (in bytes).\n" "Multiple ranges can be formatted by specifying\n" "several -offset and -length pairs.\n" "When only a single -offset is specified without\n" "-length, clang-format will format up to the end\n" "of the file.\n" "Can only be used with one input file."), cl::cat(SwiftFormatCategory)); static cl::list<std::string> LineRanges("lines", cl::desc("<start line>:<end line> - format a range of\n" "lines (both 1-based).\n" "Multiple ranges can be formatted by specifying\n" "several -lines arguments.\n" "Can't be used with -offset and -length.\n" "Can only be used with one input file."), cl::cat(SwiftFormatCategory)); static llvm::cl::opt<bool> UseTabs("usetabs", llvm::cl::desc("Use tabs for indentation"), cl::cat(SwiftFormatCategory)); static llvm::cl::opt<unsigned> TabWidth("tabwidth", llvm::cl::desc("Assumed width of tab character"), cl::cat(SwiftFormatCategory)); static llvm::cl::opt<unsigned> IndentWidth("indentwidth", llvm::cl::desc("Characters to indent"), cl::cat(SwiftFormatCategory)); static cl::opt<std::string> AssumeFileName("assume-filename", cl::desc("When reading from stdin, clang-format assumes this\n" "filename to look for a style config file (with\n" "-style=file) and to determine the language."), cl::init("<stdin>"), cl::cat(SwiftFormatCategory)); static cl::opt<bool> Inplace("i", cl::desc("Inplace edit <file>s, if specified."), cl::cat(SwiftFormatCategory)); static cl::opt<bool> OutputXML("output-replacements-xml", cl::desc("Output replacements as XML."), cl::cat(SwiftFormatCategory)); static cl::list<std::string> FileNames(cl::Positional, cl::desc("[<file> ...]"), cl::cat(SwiftFormatCategory)); CodeFormatOptions FormatOptions; class FormatterDocument { SourceManager SM; unsigned BufferID; CompilerInvocation CompInv; std::unique_ptr<ParserUnit> Parser; class FormatterDiagConsumer: public swift::DiagnosticConsumer { void handleDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind, StringRef Text, const DiagnosticInfo &Info) override { llvm::errs() << "Parse error: " << Text << "\n"; } } DiagConsumer; public: FormatterDocument(std::unique_ptr<llvm::MemoryBuffer> Buffer) { updateCode(std::move(Buffer)); } void updateCode( std::unique_ptr<llvm::MemoryBuffer> buff ) { BufferID = SM.addNewSourceBuffer(std::move(buff)); Parser.reset( new ParserUnit(SM, BufferID, CompInv.getLangOptions(), CompInv.getModuleName()) ); Parser->getDiagnosticEngine().addConsumer(DiagConsumer); auto &P = Parser->getParser(); bool Done = false; while (!Done) { P.parseTopLevel(); Done = P.Tok.is(tok::eof); } } std::pair<LineRange, std::string> reformat(LineRange Range, CodeFormatOptions Options) { return swift::ide::reformat(Range, FormatOptions, SM, Parser->getSourceFile()); } const MemoryBuffer &memBuffer() const { return *SM.getLLVMSourceMgr().getMemoryBuffer(BufferID); } std::pair<unsigned, unsigned> getLineAndColumn(unsigned ByteOffset) const { auto &Buf = memBuffer(); if (ByteOffset > Buf.getBufferSize()) return std::make_pair(0, 0); SMLoc Loc = SMLoc::getFromPointer(Buf.getBufferStart() + ByteOffset); return SM.getLLVMSourceMgr().getLineAndColumn(Loc, BufferID); } }; // Parses <start line>:<end line> input to a pair of line numbers. // Returns true on error. static bool parseLineRange(StringRef Input, unsigned &FromLine, unsigned &ToLine) { std::pair<StringRef, StringRef> LineRange = Input.split(':'); return LineRange.first.getAsInteger(0, FromLine) || LineRange.second.getAsInteger(0, ToLine); } static void outputReplacementXML(StringRef Text) { // FIXME: When we sort includes, we need to make sure the stream is correct // utf-8. size_t From = 0; size_t Index; while ((Index = Text.find_first_of("\n\r<&", From)) != StringRef::npos) { llvm::outs() << Text.substr(From, Index - From); switch (Text[Index]) { case '\n': llvm::outs() << " "; break; case '\r': llvm::outs() << " "; break; case '<': llvm::outs() << "<"; break; case '&': llvm::outs() << "&"; break; default: llvm_unreachable("Unexpected character encountered!"); } From = Index + 1; } llvm::outs() << Text.substr(From); } static void outputReplacementsXML(const Replacements &Replaces) { for (const auto &R : Replaces) { outs() << "<replacement " << "offset='" << R.getOffset() << "' " << "length='" << R.getLength() << "'>"; outputReplacementXML(R.getReplacementText()); outs() << "</replacement>\n"; } } // Returns true on error. static bool format(StringRef FileName) { ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr = MemoryBuffer::getFileOrSTDIN(FileName); if (std::error_code EC = CodeOrErr.getError()) { llvm::errs() << EC.message() << "\n"; return true; } std::unique_ptr<llvm::MemoryBuffer> Code = std::move(CodeOrErr.get()); if (Code->getBufferSize() == 0) return false; // Empty files are formatted correctly. FormatterDocument Doc(std::move(Code)); if (!Offsets.empty() || !Lengths.empty()) { if (Offsets.size() != Lengths.size()) { llvm::errs() << "error: number of offsets not equal to number of lengths.\n"; return true; } for ( unsigned i=0 ; i < Offsets.size() ; i++ ) { unsigned FromLine = Doc.getLineAndColumn(Offsets[i]).first; unsigned ToLine = Doc.getLineAndColumn(Offsets[i] + Lengths[i]).first; if (ToLine == 0) { llvm::errs() << "error: offset + length after end of file\n"; return true; } std::ostringstream s; s << FromLine << ":" << ToLine; LineRanges.push_back(s.str()); } } if (LineRanges.empty()) LineRanges.push_back("1:999999"); std::string Output = Doc.memBuffer().getBuffer(); Replacements Replaces; for ( unsigned Range = 0 ; Range < LineRanges.size() ; Range++ ) { unsigned FromLine, ToLine; if (parseLineRange(LineRanges[Range], FromLine, ToLine)) { llvm::errs() << "error: invalid <start line>:<end line> pair\n"; return true; } if (FromLine > ToLine) { llvm::errs() << "error: start line should be less than end line\n"; return true; } for ( unsigned Line = FromLine ; Line<=ToLine ; Line++ ) { size_t Offset = getOffsetOfLine(Line,Output); ssize_t Length = getOffsetOfLine(Line+1,Output)-1-Offset; if (Length < 0) break; std::string Formatted = Doc.reformat(LineRange(Line,1), FormatOptions).second; if (Formatted.find_first_not_of(" \t\v\f", 0) == StringRef::npos) Formatted = ""; if (Formatted == Output.substr(Offset, Length)) continue; Output.replace(Offset, Length, Formatted); Doc.updateCode(std::move(MemoryBuffer::getMemBuffer(Output))); Replaces.insert(clang::tooling::Replacement(FileName, Offset, Length, Formatted)); } } if (OutputXML) { llvm::outs() << "<?xml version='1.0'?>\n<replacements>\n"; outputReplacementsXML(Replaces); llvm::outs() << "</replacements>\n"; } else { if (Inplace) { if (FileName == "-") { llvm::errs() << "error: cannot use -i when reading from stdin.\n"; return true; } else { std::error_code EC; raw_fd_ostream writer(FileName, EC, llvm::sys::fs::F_None); if (EC) { llvm::errs() << "error: writing " << FileName << ": " << EC.message() << "\n"; return true; } writer << Output; } } else { llvm::outs() << Output; } } return false; } } // namespace format
int ranlib_main() { if (RestOfArgs.size() != 1) fail(ToolName + "takes just one archive as argument"); ArchiveName = RestOfArgs[0]; return performOperation(CreateSymTab); }
//===----------------------------------------------------------------------===// // main for opt // int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); // Enable debug stream buffering. EnableDebugBuffering = true; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. LLVMContext Context; InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); // Initialize passes PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); initializeScalarOpts(Registry); initializeObjCARCOpts(Registry); initializeVectorization(Registry); initializeIPO(Registry); initializeAnalysis(Registry); initializeTransformUtils(Registry); initializeInstCombine(Registry); initializeInstrumentation(Registry); initializeTarget(Registry); // For codegen passes, only passes that do IR to IR transformation are // supported. initializeCodeGenPreparePass(Registry); initializeAtomicExpandPass(Registry); initializeRewriteSymbolsPass(Registry); initializeWinEHPreparePass(Registry); initializeDwarfEHPreparePass(Registry); initializeSafeStackPass(Registry); initializeSjLjEHPreparePass(Registry); #ifdef LINK_POLLY_INTO_TOOLS polly::initializePollyPasses(Registry); #endif cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .bc modular optimizer and analysis printer\n"); if (AnalyzeOnly && NoOutput) { errs() << argv[0] << ": analyze mode conflicts with no-output mode.\n"; return 1; } SMDiagnostic Err; Context.setDiscardValueNames(DiscardValueNames); if (!DisableDITypeMap) Context.enableDebugTypeODRUniquing(); // Load the input module... std::unique_ptr<Module> M = parseIRFile(InputFilename, Err, Context); if (!M) { Err.print(argv[0], errs()); return 1; } // Strip debug info before running the verifier. if (StripDebug) StripDebugInfo(*M); // Immediately run the verifier to catch any problems before starting up the // pass pipelines. Otherwise we can crash on broken code during // doInitialization(). if (!NoVerify && verifyModule(*M, &errs())) { errs() << argv[0] << ": " << InputFilename << ": error: input module is broken!\n"; return 1; } // If we are supposed to override the target triple, do so now. if (!TargetTriple.empty()) M->setTargetTriple(Triple::normalize(TargetTriple)); // Figure out what stream we are supposed to write to... std::unique_ptr<tool_output_file> Out; if (NoOutput) { if (!OutputFilename.empty()) errs() << "WARNING: The -o (output filename) option is ignored when\n" "the --disable-output option is used.\n"; } else { // Default to standard output. if (OutputFilename.empty()) OutputFilename = "-"; std::error_code EC; Out.reset(new tool_output_file(OutputFilename, EC, sys::fs::F_None)); if (EC) { errs() << EC.message() << '\n'; return 1; } } Triple ModuleTriple(M->getTargetTriple()); std::string CPUStr, FeaturesStr; TargetMachine *Machine = nullptr; const TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); if (ModuleTriple.getArch()) { CPUStr = getCPUStr(); FeaturesStr = getFeaturesStr(); Machine = GetTargetMachine(ModuleTriple, CPUStr, FeaturesStr, Options); } std::unique_ptr<TargetMachine> TM(Machine); // Override function attributes based on CPUStr, FeaturesStr, and command line // flags. setFunctionAttributes(CPUStr, FeaturesStr, *M); // If the output is set to be emitted to standard out, and standard out is a // console, print out a warning message and refuse to do it. We don't // impress anyone by spewing tons of binary goo to a terminal. if (!Force && !NoOutput && !AnalyzeOnly && !OutputAssembly) if (CheckBitcodeOutputToConsole(Out->os(), !Quiet)) NoOutput = true; if (PassPipeline.getNumOccurrences() > 0) { OutputKind OK = OK_NoOutput; if (!NoOutput) OK = OutputAssembly ? OK_OutputAssembly : OK_OutputBitcode; VerifierKind VK = VK_VerifyInAndOut; if (NoVerify) VK = VK_NoVerifier; else if (VerifyEach) VK = VK_VerifyEachPass; // The user has asked to use the new pass manager and provided a pipeline // string. Hand off the rest of the functionality to the new code for that // layer. return runPassPipeline(argv[0], Context, *M, TM.get(), Out.get(), PassPipeline, OK, VK, PreserveAssemblyUseListOrder, PreserveBitcodeUseListOrder) ? 0 : 1; } // Create a PassManager to hold and optimize the collection of passes we are // about to build. // legacy::PassManager Passes; // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfoImpl TLII(ModuleTriple); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (DisableSimplifyLibCalls) TLII.disableAllFunctions(); Passes.add(new TargetLibraryInfoWrapperPass(TLII)); // Add an appropriate DataLayout instance for this module. const DataLayout &DL = M->getDataLayout(); if (DL.isDefault() && !DefaultDataLayout.empty()) { M->setDataLayout(DefaultDataLayout); } // Add internal analysis passes from the target machine. Passes.add(createTargetTransformInfoWrapperPass(TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis())); std::unique_ptr<legacy::FunctionPassManager> FPasses; if (OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) { FPasses.reset(new legacy::FunctionPassManager(M.get())); FPasses->add(createTargetTransformInfoWrapperPass( TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis())); } if (PrintBreakpoints) { // Default to standard output. if (!Out) { if (OutputFilename.empty()) OutputFilename = "-"; std::error_code EC; Out = llvm::make_unique<tool_output_file>(OutputFilename, EC, sys::fs::F_None); if (EC) { errs() << EC.message() << '\n'; return 1; } } Passes.add(createBreakpointPrinter(Out->os())); NoOutput = true; } // Create a new optimization pass for each one specified on the command line for (unsigned i = 0; i < PassList.size(); ++i) { if (StandardLinkOpts && StandardLinkOpts.getPosition() < PassList.getPosition(i)) { AddStandardLinkPasses(Passes); StandardLinkOpts = false; } if (OptLevelO1 && OptLevelO1.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 1, 0); OptLevelO1 = false; } if (OptLevelO2 && OptLevelO2.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 2, 0); OptLevelO2 = false; } if (OptLevelOs && OptLevelOs.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 2, 1); OptLevelOs = false; } if (OptLevelOz && OptLevelOz.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 2, 2); OptLevelOz = false; } if (OptLevelO3 && OptLevelO3.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 3, 0); OptLevelO3 = false; } const PassInfo *PassInf = PassList[i]; Pass *P = nullptr; if (PassInf->getTargetMachineCtor()) P = PassInf->getTargetMachineCtor()(TM.get()); else if (PassInf->getNormalCtor()) P = PassInf->getNormalCtor()(); else errs() << argv[0] << ": cannot create pass: "******"\n"; if (P) { PassKind Kind = P->getPassKind(); addPass(Passes, P); if (AnalyzeOnly) { switch (Kind) { case PT_BasicBlock: Passes.add(createBasicBlockPassPrinter(PassInf, Out->os(), Quiet)); break; case PT_Region: Passes.add(createRegionPassPrinter(PassInf, Out->os(), Quiet)); break; case PT_Loop: Passes.add(createLoopPassPrinter(PassInf, Out->os(), Quiet)); break; case PT_Function: Passes.add(createFunctionPassPrinter(PassInf, Out->os(), Quiet)); break; case PT_CallGraphSCC: Passes.add(createCallGraphPassPrinter(PassInf, Out->os(), Quiet)); break; default: Passes.add(createModulePassPrinter(PassInf, Out->os(), Quiet)); break; } } } if (PrintEachXForm) Passes.add( createPrintModulePass(errs(), "", PreserveAssemblyUseListOrder)); } if (StandardLinkOpts) { AddStandardLinkPasses(Passes); StandardLinkOpts = false; } if (OptLevelO1) AddOptimizationPasses(Passes, *FPasses, 1, 0); if (OptLevelO2) AddOptimizationPasses(Passes, *FPasses, 2, 0); if (OptLevelOs) AddOptimizationPasses(Passes, *FPasses, 2, 1); if (OptLevelOz) AddOptimizationPasses(Passes, *FPasses, 2, 2); if (OptLevelO3) AddOptimizationPasses(Passes, *FPasses, 3, 0); if (OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) { FPasses->doInitialization(); for (Function &F : *M) FPasses->run(F); FPasses->doFinalization(); } // Check that the module is well formed on completion of optimization if (!NoVerify && !VerifyEach) Passes.add(createVerifierPass()); // In run twice mode, we want to make sure the output is bit-by-bit // equivalent if we run the pass manager again, so setup two buffers and // a stream to write to them. Note that llc does something similar and it // may be worth to abstract this out in the future. SmallVector<char, 0> Buffer; SmallVector<char, 0> CompileTwiceBuffer; std::unique_ptr<raw_svector_ostream> BOS; raw_ostream *OS = nullptr; // Write bitcode or assembly to the output as the last step... if (!NoOutput && !AnalyzeOnly) { assert(Out); OS = &Out->os(); if (RunTwice) { BOS = make_unique<raw_svector_ostream>(Buffer); OS = BOS.get(); } if (OutputAssembly) { if (EmitSummaryIndex) report_fatal_error("Text output is incompatible with -module-summary"); if (EmitModuleHash) report_fatal_error("Text output is incompatible with -module-hash"); Passes.add(createPrintModulePass(*OS, "", PreserveAssemblyUseListOrder)); } else Passes.add(createBitcodeWriterPass(*OS, PreserveBitcodeUseListOrder, EmitSummaryIndex, EmitModuleHash)); } // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); // If requested, run all passes again with the same pass manager to catch // bugs caused by persistent state in the passes if (RunTwice) { std::unique_ptr<Module> M2(CloneModule(M.get())); Passes.run(*M2); CompileTwiceBuffer = Buffer; Buffer.clear(); } // Now that we have all of the passes ready, run them. Passes.run(*M); // Compare the two outputs and make sure they're the same if (RunTwice) { assert(Out); if (Buffer.size() != CompileTwiceBuffer.size() || (memcmp(Buffer.data(), CompileTwiceBuffer.data(), Buffer.size()) != 0)) { errs() << "Running the pass manager twice changed the output.\n" "Writing the result of the second run to the specified output.\n" "To generate the one-run comparison binary, just run without\n" "the compile-twice option\n"; Out->os() << BOS->str(); Out->keep(); return 1; } Out->os() << BOS->str(); } // Declare success. if (!NoOutput || PrintBreakpoints) Out->keep(); return 0; }
////////////////////////////////////////////////////////////////////////////////////////// // This function runs optimization passes based on command line arguments. // Returns true if any optimization passes were invoked. bool ldc_optimize_module(llvm::Module *M) { // Create a PassManager to hold and optimize the collection of // per-module passes we are about to build. #if LDC_LLVM_VER >= 307 legacy:: #endif PassManager mpm; #if LDC_LLVM_VER >= 307 // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfoImpl *tlii = new TargetLibraryInfoImpl(Triple(M->getTargetTriple())); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (disableSimplifyLibCalls) tlii->disableAllFunctions(); mpm.add(new TargetLibraryInfoWrapperPass(*tlii)); #else // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfo *tli = new TargetLibraryInfo(Triple(M->getTargetTriple())); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (disableSimplifyLibCalls) tli->disableAllFunctions(); mpm.add(tli); #endif // Add an appropriate DataLayout instance for this module. #if LDC_LLVM_VER >= 307 // The DataLayout is already set at the module (in module.cpp, // method Module::genLLVMModule()) // FIXME: Introduce new command line switch default-data-layout to // override the module data layout #elif LDC_LLVM_VER == 306 mpm.add(new DataLayoutPass()); #elif LDC_LLVM_VER == 305 const DataLayout *DL = M->getDataLayout(); assert(DL && "DataLayout not set at module"); mpm.add(new DataLayoutPass(*DL)); #elif LDC_LLVM_VER >= 302 mpm.add(new DataLayout(M)); #else mpm.add(new TargetData(M)); #endif #if LDC_LLVM_VER >= 307 // Add internal analysis passes from the target machine. mpm.add(createTargetTransformInfoWrapperPass(gTargetMachine->getTargetIRAnalysis())); #elif LDC_LLVM_VER >= 305 // Add internal analysis passes from the target machine. gTargetMachine->addAnalysisPasses(mpm); #endif // Also set up a manager for the per-function passes. #if LDC_LLVM_VER >= 307 legacy:: #endif FunctionPassManager fpm(M); #if LDC_LLVM_VER >= 307 // Add internal analysis passes from the target machine. fpm.add(createTargetTransformInfoWrapperPass(gTargetMachine->getTargetIRAnalysis())); #elif LDC_LLVM_VER >= 306 fpm.add(new DataLayoutPass()); gTargetMachine->addAnalysisPasses(fpm); #elif LDC_LLVM_VER == 305 fpm.add(new DataLayoutPass(M)); gTargetMachine->addAnalysisPasses(fpm); #elif LDC_LLVM_VER >= 302 fpm.add(new DataLayout(M)); #else fpm.add(new TargetData(M)); #endif // If the -strip-debug command line option was specified, add it before // anything else. if (stripDebug) mpm.add(createStripSymbolsPass(true)); bool defaultsAdded = false; // Create a new optimization pass for each one specified on the command line for (unsigned i = 0; i < passList.size(); ++i) { if (optimizeLevel && optimizeLevel.getPosition() < passList.getPosition(i)) { addOptimizationPasses(mpm, fpm, optLevel(), sizeLevel()); defaultsAdded = true; } const PassInfo *passInf = passList[i]; Pass *pass = 0; if (passInf->getNormalCtor()) pass = passInf->getNormalCtor()(); else { const char* arg = passInf->getPassArgument(); // may return null if (arg) error(Loc(), "Can't create pass '-%s' (%s)", arg, pass->getPassName()); else error(Loc(), "Can't create pass (%s)", pass->getPassName()); llvm_unreachable("pass creation failed"); } if (pass) { addPass(mpm, pass); } } // Add the default passes for the specified optimization level. if (!defaultsAdded) addOptimizationPasses(mpm, fpm, optLevel(), sizeLevel()); // Run per-function passes. fpm.doInitialization(); for (llvm::Module::iterator F = M->begin(), E = M->end(); F != E; ++F) fpm.run(*F); fpm.doFinalization(); // Run per-module passes. mpm.run(*M); // Verify the resulting module. verifyModule(M); // Report that we run some passes. return true; }
int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); LLVMContext &Context = getGlobalContext(); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm linker\n"); unsigned BaseArg = 0; std::string ErrorMessage; std::auto_ptr<Module> Composite(LoadFile(argv[0], InputFilenames[BaseArg], Context)); if (Composite.get() == 0) { errs() << argv[0] << ": error loading file '" << InputFilenames[BaseArg] << "'\n"; return 1; } for (unsigned i = BaseArg+1; i < InputFilenames.size(); ++i) { std::auto_ptr<Module> M(LoadFile(argv[0], InputFilenames[i], Context)); if (M.get() == 0) { errs() << argv[0] << ": error loading file '" <<InputFilenames[i]<< "'\n"; return 1; } if (Verbose) errs() << "Linking in '" << InputFilenames[i] << "'\n"; if (Linker::LinkModules(Composite.get(), M.get(), Linker::DestroySource, &ErrorMessage)) { errs() << argv[0] << ": link error in '" << InputFilenames[i] << "': " << ErrorMessage << "\n"; return 1; } } // TODO: Iterate over the -l list and link in any modules containing // global symbols that have not been resolved so far. if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite; std::string ErrorInfo; tool_output_file Out(OutputFilename.c_str(), ErrorInfo, raw_fd_ostream::F_Binary); if (!ErrorInfo.empty()) { errs() << ErrorInfo << '\n'; return 1; } if (verifyModule(*Composite)) { errs() << argv[0] << ": linked module is broken!\n"; return 1; } if (Verbose) errs() << "Writing bitcode...\n"; if (OutputAssembly) { Out.os() << *Composite; } else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true)) WriteBitcodeToFile(Composite.get(), Out.os()); // Declare success. Out.keep(); return 0; }
bool optimize() { return optimizeLevel || doInline() || !passList.empty(); }
//===----------------------------------------------------------------------===// // main for opt // int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); // Enable debug stream buffering. EnableDebugBuffering = true; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. LLVMContext &Context = getGlobalContext(); InitializeAllTargets(); InitializeAllTargetMCs(); // Initialize passes PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); initializeDebugIRPass(Registry); initializeScalarOpts(Registry); initializeObjCARCOpts(Registry); initializeVectorization(Registry); initializeIPO(Registry); initializeAnalysis(Registry); initializeIPA(Registry); initializeTransformUtils(Registry); initializeInstCombine(Registry); initializeInstrumentation(Registry); initializeTarget(Registry); cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .bc modular optimizer and analysis printer\n"); if (AnalyzeOnly && NoOutput) { errs() << argv[0] << ": analyze mode conflicts with no-output mode.\n"; return 1; } SMDiagnostic Err; // Load the input module... OwningPtr<Module> M; M.reset(ParseIRFile(InputFilename, Err, Context)); if (M.get() == 0) { Err.print(argv[0], errs()); return 1; } // If we are supposed to override the target triple, do so now. if (!TargetTriple.empty()) M->setTargetTriple(Triple::normalize(TargetTriple)); // Figure out what stream we are supposed to write to... OwningPtr<tool_output_file> Out; if (NoOutput) { if (!OutputFilename.empty()) errs() << "WARNING: The -o (output filename) option is ignored when\n" "the --disable-output option is used.\n"; } else { // Default to standard output. if (OutputFilename.empty()) OutputFilename = "-"; std::string ErrorInfo; Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo, sys::fs::F_Binary)); if (!ErrorInfo.empty()) { errs() << ErrorInfo << '\n'; return 1; } } // If the output is set to be emitted to standard out, and standard out is a // console, print out a warning message and refuse to do it. We don't // impress anyone by spewing tons of binary goo to a terminal. if (!Force && !NoOutput && !AnalyzeOnly && !OutputAssembly) if (CheckBitcodeOutputToConsole(Out->os(), !Quiet)) NoOutput = true; // Create a PassManager to hold and optimize the collection of passes we are // about to build. // PassManager Passes; // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfo *TLI = new TargetLibraryInfo(Triple(M->getTargetTriple())); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (DisableSimplifyLibCalls) TLI->disableAllFunctions(); Passes.add(TLI); // Add an appropriate DataLayout instance for this module. DataLayout *TD = 0; const std::string &ModuleDataLayout = M.get()->getDataLayout(); if (!ModuleDataLayout.empty()) TD = new DataLayout(ModuleDataLayout); else if (!DefaultDataLayout.empty()) TD = new DataLayout(DefaultDataLayout); if (TD) Passes.add(TD); Triple ModuleTriple(M->getTargetTriple()); TargetMachine *Machine = 0; if (ModuleTriple.getArch()) Machine = GetTargetMachine(Triple(ModuleTriple)); OwningPtr<TargetMachine> TM(Machine); // Add internal analysis passes from the target machine. if (TM.get()) TM->addAnalysisPasses(Passes); OwningPtr<FunctionPassManager> FPasses; if (OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) { FPasses.reset(new FunctionPassManager(M.get())); if (TD) FPasses->add(new DataLayout(*TD)); } if (PrintBreakpoints) { // Default to standard output. if (!Out) { if (OutputFilename.empty()) OutputFilename = "-"; std::string ErrorInfo; Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo, sys::fs::F_Binary)); if (!ErrorInfo.empty()) { errs() << ErrorInfo << '\n'; return 1; } } Passes.add(new BreakpointPrinter(Out->os())); NoOutput = true; } // If the -strip-debug command line option was specified, add it. If // -std-compile-opts was also specified, it will handle StripDebug. if (StripDebug && !StandardCompileOpts) addPass(Passes, createStripSymbolsPass(true)); // Create a new optimization pass for each one specified on the command line for (unsigned i = 0; i < PassList.size(); ++i) { // Check to see if -std-compile-opts was specified before this option. If // so, handle it. if (StandardCompileOpts && StandardCompileOpts.getPosition() < PassList.getPosition(i)) { AddStandardCompilePasses(Passes); StandardCompileOpts = false; } if (StandardLinkOpts && StandardLinkOpts.getPosition() < PassList.getPosition(i)) { AddStandardLinkPasses(Passes); StandardLinkOpts = false; } if (OptLevelO1 && OptLevelO1.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 1, 0); OptLevelO1 = false; } if (OptLevelO2 && OptLevelO2.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 2, 0); OptLevelO2 = false; } if (OptLevelOs && OptLevelOs.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 2, 1); OptLevelOs = false; } if (OptLevelOz && OptLevelOz.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 2, 2); OptLevelOz = false; } if (OptLevelO3 && OptLevelO3.getPosition() < PassList.getPosition(i)) { AddOptimizationPasses(Passes, *FPasses, 3, 0); OptLevelO3 = false; } const PassInfo *PassInf = PassList[i]; Pass *P = 0; if (PassInf->getNormalCtor()) P = PassInf->getNormalCtor()(); else errs() << argv[0] << ": cannot create pass: "******"\n"; if (P) { PassKind Kind = P->getPassKind(); addPass(Passes, P); if (AnalyzeOnly) { switch (Kind) { case PT_BasicBlock: Passes.add(new BasicBlockPassPrinter(PassInf, Out->os())); break; case PT_Region: Passes.add(new RegionPassPrinter(PassInf, Out->os())); break; case PT_Loop: Passes.add(new LoopPassPrinter(PassInf, Out->os())); break; case PT_Function: Passes.add(new FunctionPassPrinter(PassInf, Out->os())); break; case PT_CallGraphSCC: Passes.add(new CallGraphSCCPassPrinter(PassInf, Out->os())); break; default: Passes.add(new ModulePassPrinter(PassInf, Out->os())); break; } } } if (PrintEachXForm) Passes.add(createPrintModulePass(&errs())); } // If -std-compile-opts was specified at the end of the pass list, add them. if (StandardCompileOpts) { AddStandardCompilePasses(Passes); StandardCompileOpts = false; } if (StandardLinkOpts) { AddStandardLinkPasses(Passes); StandardLinkOpts = false; } if (OptLevelO1) AddOptimizationPasses(Passes, *FPasses, 1, 0); if (OptLevelO2) AddOptimizationPasses(Passes, *FPasses, 2, 0); if (OptLevelOs) AddOptimizationPasses(Passes, *FPasses, 2, 1); if (OptLevelOz) AddOptimizationPasses(Passes, *FPasses, 2, 2); if (OptLevelO3) AddOptimizationPasses(Passes, *FPasses, 3, 0); if (OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) { FPasses->doInitialization(); for (Module::iterator F = M->begin(), E = M->end(); F != E; ++F) FPasses->run(*F); FPasses->doFinalization(); } // Check that the module is well formed on completion of optimization if (!NoVerify && !VerifyEach) Passes.add(createVerifierPass()); // Write bitcode or assembly to the output as the last step... if (!NoOutput && !AnalyzeOnly) { if (OutputAssembly) Passes.add(createPrintModulePass(&Out->os())); else Passes.add(createBitcodeWriterPass(Out->os())); } // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); // Now that we have all of the passes ready, run them. Passes.run(*M.get()); // Declare success. if (!NoOutput || PrintBreakpoints) Out->keep(); return 0; }
// Unbundle the files. Return true if an error was found. static bool UnbundleFiles() { // Open Input file. ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr = MemoryBuffer::getFileOrSTDIN(InputFileNames.front()); if (std::error_code EC = CodeOrErr.getError()) { errs() << "error: Can't open file " << InputFileNames.front() << ": " << EC.message() << "\n"; return true; } MemoryBuffer &Input = *CodeOrErr.get(); // Select the right files handler. std::unique_ptr<FileHandler> FH; FH.reset(CreateFileHandler(Input)); // Quit if we don't have a handler. if (!FH.get()) return true; // Read the header of the bundled file. FH.get()->ReadHeader(Input); // Create a work list that consist of the map triple/output file. StringMap<StringRef> Worklist; auto Output = OutputFileNames.begin(); for (auto &Triple : TargetNames) { Worklist[Triple] = *Output; ++Output; } // Read all the bundles that are in the work list. If we find no bundles we // assume the file is meant for the host target. bool FoundHostBundle = false; while (!Worklist.empty()) { StringRef CurTriple = FH.get()->ReadBundleStart(Input); // We don't have more bundles. if (CurTriple.empty()) break; auto Output = Worklist.find(CurTriple); // The file may have more bundles for other targets, that we don't care // about. Therefore, move on to the next triple if (Output == Worklist.end()) { continue; } // Check if the output file can be opened and copy the bundle to it. std::error_code EC; raw_fd_ostream OutputFile(Output->second, EC, sys::fs::F_None); if (EC) { errs() << "error: Can't open file " << Output->second << ": " << EC.message() << "\n"; return true; } FH.get()->ReadBundle(OutputFile, Input); FH.get()->ReadBundleEnd(Input); Worklist.erase(Output); // Record if we found the host bundle. if (hasHostKind(CurTriple)) FoundHostBundle = true; } // If no bundles were found, assume the input file is the host bundle and // create empty files for the remaining targets. if (Worklist.size() == TargetNames.size()) { for (auto &E : Worklist) { std::error_code EC; raw_fd_ostream OutputFile(E.second, EC, sys::fs::F_None); if (EC) { errs() << "error: Can't open file " << E.second << ": " << EC.message() << "\n"; return true; } // If this entry has a host kind, copy the input file to the output file. if (hasHostKind(E.first())) OutputFile.write(Input.getBufferStart(), Input.getBufferSize()); } return false; } // If we found elements, we emit an error if none of those were for the host. if (!FoundHostBundle) { errs() << "error: Can't find bundle for the host target\n"; return true; } // If we still have any elements in the worklist, create empty files for them. for (auto &E : Worklist) { std::error_code EC; raw_fd_ostream OutputFile(E.second, EC, sys::fs::F_None); if (EC) { errs() << "error: Can't open file " << E.second << ": " << EC.message() << "\n"; return true; } } return false; }