Path: blob/main/contrib/llvm-project/llvm/tools/llc/llc.cpp
35231 views
//===-- llc.cpp - Implement the LLVM Native Code Generator ----------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This is the llc code generator driver. It provides a convenient9// command-line interface for generating an assembly file or a relocatable file,10// given LLVM bitcode.11//12//===----------------------------------------------------------------------===//1314#include "NewPMDriver.h"15#include "llvm/ADT/STLExtras.h"16#include "llvm/ADT/ScopeExit.h"17#include "llvm/Analysis/TargetLibraryInfo.h"18#include "llvm/CodeGen/CommandFlags.h"19#include "llvm/CodeGen/LinkAllAsmWriterComponents.h"20#include "llvm/CodeGen/LinkAllCodegenComponents.h"21#include "llvm/CodeGen/MIRParser/MIRParser.h"22#include "llvm/CodeGen/MachineFunctionPass.h"23#include "llvm/CodeGen/MachineModuleInfo.h"24#include "llvm/CodeGen/TargetPassConfig.h"25#include "llvm/CodeGen/TargetSubtargetInfo.h"26#include "llvm/IR/AutoUpgrade.h"27#include "llvm/IR/DataLayout.h"28#include "llvm/IR/DiagnosticInfo.h"29#include "llvm/IR/DiagnosticPrinter.h"30#include "llvm/IR/LLVMContext.h"31#include "llvm/IR/LLVMRemarkStreamer.h"32#include "llvm/IR/LegacyPassManager.h"33#include "llvm/IR/Module.h"34#include "llvm/IR/Verifier.h"35#include "llvm/IRReader/IRReader.h"36#include "llvm/InitializePasses.h"37#include "llvm/MC/MCTargetOptionsCommandFlags.h"38#include "llvm/MC/TargetRegistry.h"39#include "llvm/Pass.h"40#include "llvm/Remarks/HotnessThresholdParser.h"41#include "llvm/Support/CommandLine.h"42#include "llvm/Support/Debug.h"43#include "llvm/Support/FileSystem.h"44#include "llvm/Support/FormattedStream.h"45#include "llvm/Support/InitLLVM.h"46#include "llvm/Support/PluginLoader.h"47#include "llvm/Support/SourceMgr.h"48#include "llvm/Support/TargetSelect.h"49#include "llvm/Support/TimeProfiler.h"50#include "llvm/Support/ToolOutputFile.h"51#include "llvm/Support/WithColor.h"52#include "llvm/Target/TargetLoweringObjectFile.h"53#include "llvm/Target/TargetMachine.h"54#include "llvm/TargetParser/Host.h"55#include "llvm/TargetParser/SubtargetFeature.h"56#include "llvm/TargetParser/Triple.h"57#include "llvm/Transforms/Utils/Cloning.h"58#include <memory>59#include <optional>60using namespace llvm;6162static codegen::RegisterCodeGenFlags CGF;6364// General options for llc. Other pass-specific options are specified65// within the corresponding llc passes, and target-specific options66// and back-end code generation options are specified with the target machine.67//68static cl::opt<std::string>69InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));7071static cl::opt<std::string>72InputLanguage("x", cl::desc("Input language ('ir' or 'mir')"));7374static cl::opt<std::string>75OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"));7677static cl::opt<std::string>78SplitDwarfOutputFile("split-dwarf-output",79cl::desc(".dwo output filename"),80cl::value_desc("filename"));8182static cl::opt<unsigned>83TimeCompilations("time-compilations", cl::Hidden, cl::init(1u),84cl::value_desc("N"),85cl::desc("Repeat compilation N times for timing"));8687static cl::opt<bool> TimeTrace("time-trace", cl::desc("Record time trace"));8889static cl::opt<unsigned> TimeTraceGranularity(90"time-trace-granularity",91cl::desc(92"Minimum time granularity (in microseconds) traced by time profiler"),93cl::init(500), cl::Hidden);9495static cl::opt<std::string>96TimeTraceFile("time-trace-file",97cl::desc("Specify time trace file destination"),98cl::value_desc("filename"));99100static cl::opt<std::string>101BinutilsVersion("binutils-version", cl::Hidden,102cl::desc("Produced object files can use all ELF features "103"supported by this binutils version and newer."104"If -no-integrated-as is specified, the generated "105"assembly will consider GNU as support."106"'none' means that all ELF features can be used, "107"regardless of binutils support"));108109static cl::opt<bool>110PreserveComments("preserve-as-comments", cl::Hidden,111cl::desc("Preserve Comments in outputted assembly"),112cl::init(true));113114// Determine optimization level.115static cl::opt<char>116OptLevel("O",117cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "118"(default = '-O2')"),119cl::Prefix, cl::init('2'));120121static cl::opt<std::string>122TargetTriple("mtriple", cl::desc("Override target triple for module"));123124static cl::opt<std::string> SplitDwarfFile(125"split-dwarf-file",126cl::desc(127"Specify the name of the .dwo file to encode in the DWARF output"));128129static cl::opt<bool> NoVerify("disable-verify", cl::Hidden,130cl::desc("Do not verify input module"));131132static cl::opt<bool> DisableSimplifyLibCalls("disable-simplify-libcalls",133cl::desc("Disable simplify-libcalls"));134135static cl::opt<bool> ShowMCEncoding("show-mc-encoding", cl::Hidden,136cl::desc("Show encoding in .s output"));137138static cl::opt<bool>139DwarfDirectory("dwarf-directory", cl::Hidden,140cl::desc("Use .file directives with an explicit directory"),141cl::init(true));142143static cl::opt<bool> AsmVerbose("asm-verbose",144cl::desc("Add comments to directives."),145cl::init(true));146147static cl::opt<bool>148CompileTwice("compile-twice", cl::Hidden,149cl::desc("Run everything twice, re-using the same pass "150"manager and verify the result is the same."),151cl::init(false));152153static cl::opt<bool> DiscardValueNames(154"discard-value-names",155cl::desc("Discard names from Value (other than GlobalValue)."),156cl::init(false), cl::Hidden);157158static cl::list<std::string> IncludeDirs("I", cl::desc("include search path"));159160static cl::opt<bool> RemarksWithHotness(161"pass-remarks-with-hotness",162cl::desc("With PGO, include profile count in optimization remarks"),163cl::Hidden);164165static cl::opt<std::optional<uint64_t>, false, remarks::HotnessThresholdParser>166RemarksHotnessThreshold(167"pass-remarks-hotness-threshold",168cl::desc("Minimum profile count required for "169"an optimization remark to be output. "170"Use 'auto' to apply the threshold from profile summary."),171cl::value_desc("N or 'auto'"), cl::init(0), cl::Hidden);172173static cl::opt<std::string>174RemarksFilename("pass-remarks-output",175cl::desc("Output filename for pass remarks"),176cl::value_desc("filename"));177178static cl::opt<std::string>179RemarksPasses("pass-remarks-filter",180cl::desc("Only record optimization remarks from passes whose "181"names match the given regular expression"),182cl::value_desc("regex"));183184static cl::opt<std::string> RemarksFormat(185"pass-remarks-format",186cl::desc("The format used for serializing remarks (default: YAML)"),187cl::value_desc("format"), cl::init("yaml"));188189static cl::opt<bool> EnableNewPassManager(190"enable-new-pm", cl::desc("Enable the new pass manager"), cl::init(false));191192// This flag specifies a textual description of the optimization pass pipeline193// to run over the module. This flag switches opt to use the new pass manager194// infrastructure, completely disabling all of the flags specific to the old195// pass management.196static cl::opt<std::string> PassPipeline(197"passes",198cl::desc(199"A textual description of the pass pipeline. To have analysis passes "200"available before a certain pass, add 'require<foo-analysis>'."));201static cl::alias PassPipeline2("p", cl::aliasopt(PassPipeline),202cl::desc("Alias for -passes"));203204static cl::opt<bool> TryUseNewDbgInfoFormat(205"try-experimental-debuginfo-iterators",206cl::desc("Enable debuginfo iterator positions, if they're built in"),207cl::init(false), cl::Hidden);208209extern cl::opt<bool> UseNewDbgInfoFormat;210211namespace {212213std::vector<std::string> &getRunPassNames() {214static std::vector<std::string> RunPassNames;215return RunPassNames;216}217218struct RunPassOption {219void operator=(const std::string &Val) const {220if (Val.empty())221return;222SmallVector<StringRef, 8> PassNames;223StringRef(Val).split(PassNames, ',', -1, false);224for (auto PassName : PassNames)225getRunPassNames().push_back(std::string(PassName));226}227};228} // namespace229230static RunPassOption RunPassOpt;231232static cl::opt<RunPassOption, true, cl::parser<std::string>> RunPass(233"run-pass",234cl::desc("Run compiler only for specified passes (comma separated list)"),235cl::value_desc("pass-name"), cl::location(RunPassOpt));236237static int compileModule(char **, LLVMContext &);238239[[noreturn]] static void reportError(Twine Msg, StringRef Filename = "") {240SmallString<256> Prefix;241if (!Filename.empty()) {242if (Filename == "-")243Filename = "<stdin>";244("'" + Twine(Filename) + "': ").toStringRef(Prefix);245}246WithColor::error(errs(), "llc") << Prefix << Msg << "\n";247exit(1);248}249250[[noreturn]] static void reportError(Error Err, StringRef Filename) {251assert(Err);252handleAllErrors(createFileError(Filename, std::move(Err)),253[&](const ErrorInfoBase &EI) { reportError(EI.message()); });254llvm_unreachable("reportError() should not return");255}256257static std::unique_ptr<ToolOutputFile> GetOutputStream(const char *TargetName,258Triple::OSType OS,259const char *ProgName) {260// If we don't yet have an output filename, make one.261if (OutputFilename.empty()) {262if (InputFilename == "-")263OutputFilename = "-";264else {265// If InputFilename ends in .bc or .ll, remove it.266StringRef IFN = InputFilename;267if (IFN.ends_with(".bc") || IFN.ends_with(".ll"))268OutputFilename = std::string(IFN.drop_back(3));269else if (IFN.ends_with(".mir"))270OutputFilename = std::string(IFN.drop_back(4));271else272OutputFilename = std::string(IFN);273274switch (codegen::getFileType()) {275case CodeGenFileType::AssemblyFile:276OutputFilename += ".s";277break;278case CodeGenFileType::ObjectFile:279if (OS == Triple::Win32)280OutputFilename += ".obj";281else282OutputFilename += ".o";283break;284case CodeGenFileType::Null:285OutputFilename = "-";286break;287}288}289}290291// Decide if we need "binary" output.292bool Binary = false;293switch (codegen::getFileType()) {294case CodeGenFileType::AssemblyFile:295break;296case CodeGenFileType::ObjectFile:297case CodeGenFileType::Null:298Binary = true;299break;300}301302// Open the file.303std::error_code EC;304sys::fs::OpenFlags OpenFlags = sys::fs::OF_None;305if (!Binary)306OpenFlags |= sys::fs::OF_TextWithCRLF;307auto FDOut = std::make_unique<ToolOutputFile>(OutputFilename, EC, OpenFlags);308if (EC) {309reportError(EC.message());310return nullptr;311}312313return FDOut;314}315316// main - Entry point for the llc compiler.317//318int main(int argc, char **argv) {319InitLLVM X(argc, argv);320321// Enable debug stream buffering.322EnableDebugBuffering = true;323324// Initialize targets first, so that --version shows registered targets.325InitializeAllTargets();326InitializeAllTargetMCs();327InitializeAllAsmPrinters();328InitializeAllAsmParsers();329330// Initialize codegen and IR passes used by llc so that the -print-after,331// -print-before, and -stop-after options work.332PassRegistry *Registry = PassRegistry::getPassRegistry();333initializeCore(*Registry);334initializeCodeGen(*Registry);335initializeLoopStrengthReducePass(*Registry);336initializeLowerIntrinsicsPass(*Registry);337initializePostInlineEntryExitInstrumenterPass(*Registry);338initializeUnreachableBlockElimLegacyPassPass(*Registry);339initializeConstantHoistingLegacyPassPass(*Registry);340initializeScalarOpts(*Registry);341initializeVectorization(*Registry);342initializeScalarizeMaskedMemIntrinLegacyPassPass(*Registry);343initializeExpandReductionsPass(*Registry);344initializeExpandVectorPredicationPass(*Registry);345initializeHardwareLoopsLegacyPass(*Registry);346initializeTransformUtils(*Registry);347initializeReplaceWithVeclibLegacyPass(*Registry);348initializeTLSVariableHoistLegacyPassPass(*Registry);349350// Initialize debugging passes.351initializeScavengerTestPass(*Registry);352353// Register the Target and CPU printer for --version.354cl::AddExtraVersionPrinter(sys::printDefaultTargetAndDetectedCPU);355// Register the target printer for --version.356cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);357358cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n");359360if (!PassPipeline.empty() && !getRunPassNames().empty()) {361errs() << "The `llc -run-pass=...` syntax for the new pass manager is "362"not supported, please use `llc -passes=<pipeline>` (or the `-p` "363"alias for a more concise version).\n";364return 1;365}366367// RemoveDIs debug-info transition: tests may request that we /try/ to use the368// new debug-info format.369if (TryUseNewDbgInfoFormat) {370// Turn the new debug-info format on.371UseNewDbgInfoFormat = true;372}373374if (TimeTrace)375timeTraceProfilerInitialize(TimeTraceGranularity, argv[0]);376auto TimeTraceScopeExit = make_scope_exit([]() {377if (TimeTrace) {378if (auto E = timeTraceProfilerWrite(TimeTraceFile, OutputFilename)) {379handleAllErrors(std::move(E), [&](const StringError &SE) {380errs() << SE.getMessage() << "\n";381});382return;383}384timeTraceProfilerCleanup();385}386});387388LLVMContext Context;389Context.setDiscardValueNames(DiscardValueNames);390391// Set a diagnostic handler that doesn't exit on the first error392Context.setDiagnosticHandler(std::make_unique<LLCDiagnosticHandler>());393394Expected<std::unique_ptr<ToolOutputFile>> RemarksFileOrErr =395setupLLVMOptimizationRemarks(Context, RemarksFilename, RemarksPasses,396RemarksFormat, RemarksWithHotness,397RemarksHotnessThreshold);398if (Error E = RemarksFileOrErr.takeError())399reportError(std::move(E), RemarksFilename);400std::unique_ptr<ToolOutputFile> RemarksFile = std::move(*RemarksFileOrErr);401402if (InputLanguage != "" && InputLanguage != "ir" && InputLanguage != "mir")403reportError("input language must be '', 'IR' or 'MIR'");404405// Compile the module TimeCompilations times to give better compile time406// metrics.407for (unsigned I = TimeCompilations; I; --I)408if (int RetVal = compileModule(argv, Context))409return RetVal;410411if (RemarksFile)412RemarksFile->keep();413return 0;414}415416static bool addPass(PassManagerBase &PM, const char *argv0,417StringRef PassName, TargetPassConfig &TPC) {418if (PassName == "none")419return false;420421const PassRegistry *PR = PassRegistry::getPassRegistry();422const PassInfo *PI = PR->getPassInfo(PassName);423if (!PI) {424WithColor::error(errs(), argv0)425<< "run-pass " << PassName << " is not registered.\n";426return true;427}428429Pass *P;430if (PI->getNormalCtor())431P = PI->getNormalCtor()();432else {433WithColor::error(errs(), argv0)434<< "cannot create pass: " << PI->getPassName() << "\n";435return true;436}437std::string Banner = std::string("After ") + std::string(P->getPassName());438TPC.addMachinePrePasses();439PM.add(P);440TPC.addMachinePostPasses(Banner);441442return false;443}444445static int compileModule(char **argv, LLVMContext &Context) {446// Load the module to be compiled...447SMDiagnostic Err;448std::unique_ptr<Module> M;449std::unique_ptr<MIRParser> MIR;450Triple TheTriple;451std::string CPUStr = codegen::getCPUStr(),452FeaturesStr = codegen::getFeaturesStr();453454// Set attributes on functions as loaded from MIR from command line arguments.455auto setMIRFunctionAttributes = [&CPUStr, &FeaturesStr](Function &F) {456codegen::setFunctionAttributes(CPUStr, FeaturesStr, F);457};458459auto MAttrs = codegen::getMAttrs();460bool SkipModule =461CPUStr == "help" || (!MAttrs.empty() && MAttrs.front() == "help");462463CodeGenOptLevel OLvl;464if (auto Level = CodeGenOpt::parseLevel(OptLevel)) {465OLvl = *Level;466} else {467WithColor::error(errs(), argv[0]) << "invalid optimization level.\n";468return 1;469}470471// Parse 'none' or '$major.$minor'. Disallow -binutils-version=0 because we472// use that to indicate the MC default.473if (!BinutilsVersion.empty() && BinutilsVersion != "none") {474StringRef V = BinutilsVersion.getValue();475unsigned Num;476if (V.consumeInteger(10, Num) || Num == 0 ||477!(V.empty() ||478(V.consume_front(".") && !V.consumeInteger(10, Num) && V.empty()))) {479WithColor::error(errs(), argv[0])480<< "invalid -binutils-version, accepting 'none' or major.minor\n";481return 1;482}483}484TargetOptions Options;485auto InitializeOptions = [&](const Triple &TheTriple) {486Options = codegen::InitTargetOptionsFromCodeGenFlags(TheTriple);487488if (Options.XCOFFReadOnlyPointers) {489if (!TheTriple.isOSAIX())490reportError("-mxcoff-roptr option is only supported on AIX",491InputFilename);492493// Since the storage mapping class is specified per csect,494// without using data sections, it is less effective to use read-only495// pointers. Using read-only pointers may cause other RO variables in the496// same csect to become RW when the linker acts upon `-bforceimprw`;497// therefore, we require that separate data sections are used in the498// presence of ReadOnlyPointers. We respect the setting of data-sections499// since we have not found reasons to do otherwise that overcome the user500// surprise of not respecting the setting.501if (!Options.DataSections)502reportError("-mxcoff-roptr option must be used with -data-sections",503InputFilename);504}505506Options.BinutilsVersion =507TargetMachine::parseBinutilsVersion(BinutilsVersion);508Options.MCOptions.ShowMCEncoding = ShowMCEncoding;509Options.MCOptions.AsmVerbose = AsmVerbose;510Options.MCOptions.PreserveAsmComments = PreserveComments;511Options.MCOptions.IASSearchPaths = IncludeDirs;512Options.MCOptions.SplitDwarfFile = SplitDwarfFile;513if (DwarfDirectory.getPosition()) {514Options.MCOptions.MCUseDwarfDirectory =515DwarfDirectory ? MCTargetOptions::EnableDwarfDirectory516: MCTargetOptions::DisableDwarfDirectory;517} else {518// -dwarf-directory is not set explicitly. Some assemblers519// (e.g. GNU as or ptxas) do not support `.file directory'520// syntax prior to DWARFv5. Let the target decide the default521// value.522Options.MCOptions.MCUseDwarfDirectory =523MCTargetOptions::DefaultDwarfDirectory;524}525};526527std::optional<Reloc::Model> RM = codegen::getExplicitRelocModel();528std::optional<CodeModel::Model> CM = codegen::getExplicitCodeModel();529530const Target *TheTarget = nullptr;531std::unique_ptr<TargetMachine> Target;532533// If user just wants to list available options, skip module loading534if (!SkipModule) {535auto SetDataLayout = [&](StringRef DataLayoutTargetTriple,536StringRef OldDLStr) -> std::optional<std::string> {537// If we are supposed to override the target triple, do so now.538std::string IRTargetTriple = DataLayoutTargetTriple.str();539if (!TargetTriple.empty())540IRTargetTriple = Triple::normalize(TargetTriple);541TheTriple = Triple(IRTargetTriple);542if (TheTriple.getTriple().empty())543TheTriple.setTriple(sys::getDefaultTargetTriple());544545std::string Error;546TheTarget =547TargetRegistry::lookupTarget(codegen::getMArch(), TheTriple, Error);548if (!TheTarget) {549WithColor::error(errs(), argv[0]) << Error;550exit(1);551}552553InitializeOptions(TheTriple);554Target = std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(555TheTriple.getTriple(), CPUStr, FeaturesStr, Options, RM, CM, OLvl));556assert(Target && "Could not allocate target machine!");557558return Target->createDataLayout().getStringRepresentation();559};560if (InputLanguage == "mir" ||561(InputLanguage == "" && StringRef(InputFilename).ends_with(".mir"))) {562MIR = createMIRParserFromFile(InputFilename, Err, Context,563setMIRFunctionAttributes);564if (MIR)565M = MIR->parseIRModule(SetDataLayout);566} else {567M = parseIRFile(InputFilename, Err, Context,568ParserCallbacks(SetDataLayout));569}570if (!M) {571Err.print(argv[0], WithColor::error(errs(), argv[0]));572return 1;573}574if (!TargetTriple.empty())575M->setTargetTriple(Triple::normalize(TargetTriple));576577std::optional<CodeModel::Model> CM_IR = M->getCodeModel();578if (!CM && CM_IR)579Target->setCodeModel(*CM_IR);580if (std::optional<uint64_t> LDT = codegen::getExplicitLargeDataThreshold())581Target->setLargeDataThreshold(*LDT);582} else {583TheTriple = Triple(Triple::normalize(TargetTriple));584if (TheTriple.getTriple().empty())585TheTriple.setTriple(sys::getDefaultTargetTriple());586587// Get the target specific parser.588std::string Error;589TheTarget =590TargetRegistry::lookupTarget(codegen::getMArch(), TheTriple, Error);591if (!TheTarget) {592WithColor::error(errs(), argv[0]) << Error;593return 1;594}595596InitializeOptions(TheTriple);597Target = std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(598TheTriple.getTriple(), CPUStr, FeaturesStr, Options, RM, CM, OLvl));599assert(Target && "Could not allocate target machine!");600601// If we don't have a module then just exit now. We do this down602// here since the CPU/Feature help is underneath the target machine603// creation.604return 0;605}606607assert(M && "Should have exited if we didn't have a module!");608if (codegen::getFloatABIForCalls() != FloatABI::Default)609Target->Options.FloatABIType = codegen::getFloatABIForCalls();610611// Figure out where we are going to send the output.612std::unique_ptr<ToolOutputFile> Out =613GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0]);614if (!Out) return 1;615616// Ensure the filename is passed down to CodeViewDebug.617Target->Options.ObjectFilenameForDebug = Out->outputFilename();618619std::unique_ptr<ToolOutputFile> DwoOut;620if (!SplitDwarfOutputFile.empty()) {621std::error_code EC;622DwoOut = std::make_unique<ToolOutputFile>(SplitDwarfOutputFile, EC,623sys::fs::OF_None);624if (EC)625reportError(EC.message(), SplitDwarfOutputFile);626}627628// Add an appropriate TargetLibraryInfo pass for the module's triple.629TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple()));630631// The -disable-simplify-libcalls flag actually disables all builtin optzns.632if (DisableSimplifyLibCalls)633TLII.disableAllFunctions();634635// Verify module immediately to catch problems before doInitialization() is636// called on any passes.637if (!NoVerify && verifyModule(*M, &errs()))638reportError("input module cannot be verified", InputFilename);639640// Override function attributes based on CPUStr, FeaturesStr, and command line641// flags.642codegen::setFunctionAttributes(CPUStr, FeaturesStr, *M);643644if (mc::getExplicitRelaxAll() &&645codegen::getFileType() != CodeGenFileType::ObjectFile)646WithColor::warning(errs(), argv[0])647<< ": warning: ignoring -mc-relax-all because filetype != obj";648649if (EnableNewPassManager || !PassPipeline.empty()) {650return compileModuleWithNewPM(argv[0], std::move(M), std::move(MIR),651std::move(Target), std::move(Out),652std::move(DwoOut), Context, TLII, NoVerify,653PassPipeline, codegen::getFileType());654}655656// Build up all of the passes that we want to do to the module.657legacy::PassManager PM;658PM.add(new TargetLibraryInfoWrapperPass(TLII));659660{661raw_pwrite_stream *OS = &Out->os();662663// Manually do the buffering rather than using buffer_ostream,664// so we can memcmp the contents in CompileTwice mode665SmallVector<char, 0> Buffer;666std::unique_ptr<raw_svector_ostream> BOS;667if ((codegen::getFileType() != CodeGenFileType::AssemblyFile &&668!Out->os().supportsSeeking()) ||669CompileTwice) {670BOS = std::make_unique<raw_svector_ostream>(Buffer);671OS = BOS.get();672}673674const char *argv0 = argv[0];675LLVMTargetMachine &LLVMTM = static_cast<LLVMTargetMachine &>(*Target);676MachineModuleInfoWrapperPass *MMIWP =677new MachineModuleInfoWrapperPass(&LLVMTM);678679// Construct a custom pass pipeline that starts after instruction680// selection.681if (!getRunPassNames().empty()) {682if (!MIR) {683WithColor::warning(errs(), argv[0])684<< "run-pass is for .mir file only.\n";685delete MMIWP;686return 1;687}688TargetPassConfig *PTPC = LLVMTM.createPassConfig(PM);689TargetPassConfig &TPC = *PTPC;690if (TPC.hasLimitedCodeGenPipeline()) {691WithColor::warning(errs(), argv[0])692<< "run-pass cannot be used with "693<< TPC.getLimitedCodeGenPipelineReason() << ".\n";694delete PTPC;695delete MMIWP;696return 1;697}698699TPC.setDisableVerify(NoVerify);700PM.add(&TPC);701PM.add(MMIWP);702TPC.printAndVerify("");703for (const std::string &RunPassName : getRunPassNames()) {704if (addPass(PM, argv0, RunPassName, TPC))705return 1;706}707TPC.setInitialized();708PM.add(createPrintMIRPass(*OS));709PM.add(createFreeMachineFunctionPass());710} else if (Target->addPassesToEmitFile(711PM, *OS, DwoOut ? &DwoOut->os() : nullptr,712codegen::getFileType(), NoVerify, MMIWP)) {713reportError("target does not support generation of this file type");714}715716const_cast<TargetLoweringObjectFile *>(LLVMTM.getObjFileLowering())717->Initialize(MMIWP->getMMI().getContext(), *Target);718if (MIR) {719assert(MMIWP && "Forgot to create MMIWP?");720if (MIR->parseMachineFunctions(*M, MMIWP->getMMI()))721return 1;722}723724// Before executing passes, print the final values of the LLVM options.725cl::PrintOptionValues();726727// If requested, run the pass manager over the same module again,728// to catch any bugs due to persistent state in the passes. Note that729// opt has the same functionality, so it may be worth abstracting this out730// in the future.731SmallVector<char, 0> CompileTwiceBuffer;732if (CompileTwice) {733std::unique_ptr<Module> M2(llvm::CloneModule(*M));734PM.run(*M2);735CompileTwiceBuffer = Buffer;736Buffer.clear();737}738739PM.run(*M);740741if (Context.getDiagHandlerPtr()->HasErrors)742return 1;743744// Compare the two outputs and make sure they're the same745if (CompileTwice) {746if (Buffer.size() != CompileTwiceBuffer.size() ||747(memcmp(Buffer.data(), CompileTwiceBuffer.data(), Buffer.size()) !=7480)) {749errs()750<< "Running the pass manager twice changed the output.\n"751"Writing the result of the second run to the specified output\n"752"To generate the one-run comparison binary, just run without\n"753"the compile-twice option\n";754Out->os() << Buffer;755Out->keep();756return 1;757}758}759760if (BOS) {761Out->os() << Buffer;762}763}764765// Declare success.766Out->keep();767if (DwoOut)768DwoOut->keep();769770return 0;771}772773774