Path: blob/main/contrib/llvm-project/clang/lib/CodeGen/BackendUtil.cpp
35232 views
//===--- BackendUtil.cpp - LLVM Backend Utilities -------------------------===//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//===----------------------------------------------------------------------===//78#include "clang/CodeGen/BackendUtil.h"9#include "BackendConsumer.h"10#include "LinkInModulesPass.h"11#include "clang/Basic/CodeGenOptions.h"12#include "clang/Basic/Diagnostic.h"13#include "clang/Basic/LangOptions.h"14#include "clang/Basic/TargetOptions.h"15#include "clang/Frontend/FrontendDiagnostic.h"16#include "clang/Frontend/Utils.h"17#include "clang/Lex/HeaderSearchOptions.h"18#include "llvm/ADT/SmallSet.h"19#include "llvm/ADT/StringExtras.h"20#include "llvm/ADT/StringSwitch.h"21#include "llvm/Analysis/AliasAnalysis.h"22#include "llvm/Analysis/GlobalsModRef.h"23#include "llvm/Analysis/TargetLibraryInfo.h"24#include "llvm/Analysis/TargetTransformInfo.h"25#include "llvm/Bitcode/BitcodeReader.h"26#include "llvm/Bitcode/BitcodeWriter.h"27#include "llvm/Bitcode/BitcodeWriterPass.h"28#include "llvm/CodeGen/RegAllocRegistry.h"29#include "llvm/CodeGen/SchedulerRegistry.h"30#include "llvm/CodeGen/TargetSubtargetInfo.h"31#include "llvm/Frontend/Driver/CodeGenOptions.h"32#include "llvm/IR/DataLayout.h"33#include "llvm/IR/DebugInfo.h"34#include "llvm/IR/LegacyPassManager.h"35#include "llvm/IR/Module.h"36#include "llvm/IR/ModuleSummaryIndex.h"37#include "llvm/IR/PassManager.h"38#include "llvm/IR/Verifier.h"39#include "llvm/IRPrinter/IRPrintingPasses.h"40#include "llvm/LTO/LTOBackend.h"41#include "llvm/MC/MCAsmInfo.h"42#include "llvm/MC/TargetRegistry.h"43#include "llvm/Object/OffloadBinary.h"44#include "llvm/Passes/PassBuilder.h"45#include "llvm/Passes/PassPlugin.h"46#include "llvm/Passes/StandardInstrumentations.h"47#include "llvm/ProfileData/InstrProfCorrelator.h"48#include "llvm/Support/BuryPointer.h"49#include "llvm/Support/CommandLine.h"50#include "llvm/Support/MemoryBuffer.h"51#include "llvm/Support/PrettyStackTrace.h"52#include "llvm/Support/TimeProfiler.h"53#include "llvm/Support/Timer.h"54#include "llvm/Support/ToolOutputFile.h"55#include "llvm/Support/VirtualFileSystem.h"56#include "llvm/Support/raw_ostream.h"57#include "llvm/Target/TargetMachine.h"58#include "llvm/Target/TargetOptions.h"59#include "llvm/TargetParser/SubtargetFeature.h"60#include "llvm/TargetParser/Triple.h"61#include "llvm/Transforms/HipStdPar/HipStdPar.h"62#include "llvm/Transforms/IPO/EmbedBitcodePass.h"63#include "llvm/Transforms/IPO/LowerTypeTests.h"64#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"65#include "llvm/Transforms/InstCombine/InstCombine.h"66#include "llvm/Transforms/Instrumentation.h"67#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"68#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"69#include "llvm/Transforms/Instrumentation/BoundsChecking.h"70#include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"71#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"72#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"73#include "llvm/Transforms/Instrumentation/InstrProfiling.h"74#include "llvm/Transforms/Instrumentation/KCFI.h"75#include "llvm/Transforms/Instrumentation/LowerAllowCheckPass.h"76#include "llvm/Transforms/Instrumentation/MemProfiler.h"77#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"78#include "llvm/Transforms/Instrumentation/NumericalStabilitySanitizer.h"79#include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"80#include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"81#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"82#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"83#include "llvm/Transforms/ObjCARC.h"84#include "llvm/Transforms/Scalar/EarlyCSE.h"85#include "llvm/Transforms/Scalar/GVN.h"86#include "llvm/Transforms/Scalar/JumpThreading.h"87#include "llvm/Transforms/Utils/Debugify.h"88#include "llvm/Transforms/Utils/ModuleUtils.h"89#include <memory>90#include <optional>91using namespace clang;92using namespace llvm;9394#define HANDLE_EXTENSION(Ext) \95llvm::PassPluginLibraryInfo get##Ext##PluginInfo();96#include "llvm/Support/Extension.def"9798namespace llvm {99extern cl::opt<bool> PrintPipelinePasses;100101// Experiment to move sanitizers earlier.102static cl::opt<bool> ClSanitizeOnOptimizerEarlyEP(103"sanitizer-early-opt-ep", cl::Optional,104cl::desc("Insert sanitizers on OptimizerEarlyEP."));105106// Experiment to mark cold functions as optsize/minsize/optnone.107// TODO: remove once this is exposed as a proper driver flag.108static cl::opt<PGOOptions::ColdFuncOpt> ClPGOColdFuncAttr(109"pgo-cold-func-opt", cl::init(PGOOptions::ColdFuncOpt::Default), cl::Hidden,110cl::desc(111"Function attribute to apply to cold functions as determined by PGO"),112cl::values(clEnumValN(PGOOptions::ColdFuncOpt::Default, "default",113"Default (no attribute)"),114clEnumValN(PGOOptions::ColdFuncOpt::OptSize, "optsize",115"Mark cold functions with optsize."),116clEnumValN(PGOOptions::ColdFuncOpt::MinSize, "minsize",117"Mark cold functions with minsize."),118clEnumValN(PGOOptions::ColdFuncOpt::OptNone, "optnone",119"Mark cold functions with optnone.")));120121extern cl::opt<InstrProfCorrelator::ProfCorrelatorKind> ProfileCorrelate;122} // namespace llvm123124namespace {125126// Default filename used for profile generation.127std::string getDefaultProfileGenName() {128return DebugInfoCorrelate || ProfileCorrelate != InstrProfCorrelator::NONE129? "default_%m.proflite"130: "default_%m.profraw";131}132133class EmitAssemblyHelper {134DiagnosticsEngine &Diags;135const HeaderSearchOptions &HSOpts;136const CodeGenOptions &CodeGenOpts;137const clang::TargetOptions &TargetOpts;138const LangOptions &LangOpts;139llvm::Module *TheModule;140IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS;141142Timer CodeGenerationTime;143144std::unique_ptr<raw_pwrite_stream> OS;145146Triple TargetTriple;147148TargetIRAnalysis getTargetIRAnalysis() const {149if (TM)150return TM->getTargetIRAnalysis();151152return TargetIRAnalysis();153}154155/// Generates the TargetMachine.156/// Leaves TM unchanged if it is unable to create the target machine.157/// Some of our clang tests specify triples which are not built158/// into clang. This is okay because these tests check the generated159/// IR, and they require DataLayout which depends on the triple.160/// In this case, we allow this method to fail and not report an error.161/// When MustCreateTM is used, we print an error if we are unable to load162/// the requested target.163void CreateTargetMachine(bool MustCreateTM);164165/// Add passes necessary to emit assembly or LLVM IR.166///167/// \return True on success.168bool AddEmitPasses(legacy::PassManager &CodeGenPasses, BackendAction Action,169raw_pwrite_stream &OS, raw_pwrite_stream *DwoOS);170171std::unique_ptr<llvm::ToolOutputFile> openOutputFile(StringRef Path) {172std::error_code EC;173auto F = std::make_unique<llvm::ToolOutputFile>(Path, EC,174llvm::sys::fs::OF_None);175if (EC) {176Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message();177F.reset();178}179return F;180}181182void RunOptimizationPipeline(183BackendAction Action, std::unique_ptr<raw_pwrite_stream> &OS,184std::unique_ptr<llvm::ToolOutputFile> &ThinLinkOS, BackendConsumer *BC);185void RunCodegenPipeline(BackendAction Action,186std::unique_ptr<raw_pwrite_stream> &OS,187std::unique_ptr<llvm::ToolOutputFile> &DwoOS);188189/// Check whether we should emit a module summary for regular LTO.190/// The module summary should be emitted by default for regular LTO191/// except for ld64 targets.192///193/// \return True if the module summary should be emitted.194bool shouldEmitRegularLTOSummary() const {195return CodeGenOpts.PrepareForLTO && !CodeGenOpts.DisableLLVMPasses &&196TargetTriple.getVendor() != llvm::Triple::Apple;197}198199/// Check whether we should emit a flag for UnifiedLTO.200/// The UnifiedLTO module flag should be set when UnifiedLTO is enabled for201/// ThinLTO or Full LTO with module summaries.202bool shouldEmitUnifiedLTOModueFlag() const {203return CodeGenOpts.UnifiedLTO &&204(CodeGenOpts.PrepareForThinLTO || shouldEmitRegularLTOSummary());205}206207public:208EmitAssemblyHelper(DiagnosticsEngine &_Diags,209const HeaderSearchOptions &HeaderSearchOpts,210const CodeGenOptions &CGOpts,211const clang::TargetOptions &TOpts,212const LangOptions &LOpts, llvm::Module *M,213IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)214: Diags(_Diags), HSOpts(HeaderSearchOpts), CodeGenOpts(CGOpts),215TargetOpts(TOpts), LangOpts(LOpts), TheModule(M), VFS(std::move(VFS)),216CodeGenerationTime("codegen", "Code Generation Time"),217TargetTriple(TheModule->getTargetTriple()) {}218219~EmitAssemblyHelper() {220if (CodeGenOpts.DisableFree)221BuryPointer(std::move(TM));222}223224std::unique_ptr<TargetMachine> TM;225226// Emit output using the new pass manager for the optimization pipeline.227void EmitAssembly(BackendAction Action, std::unique_ptr<raw_pwrite_stream> OS,228BackendConsumer *BC);229};230} // namespace231232static SanitizerCoverageOptions233getSancovOptsFromCGOpts(const CodeGenOptions &CGOpts) {234SanitizerCoverageOptions Opts;235Opts.CoverageType =236static_cast<SanitizerCoverageOptions::Type>(CGOpts.SanitizeCoverageType);237Opts.IndirectCalls = CGOpts.SanitizeCoverageIndirectCalls;238Opts.TraceBB = CGOpts.SanitizeCoverageTraceBB;239Opts.TraceCmp = CGOpts.SanitizeCoverageTraceCmp;240Opts.TraceDiv = CGOpts.SanitizeCoverageTraceDiv;241Opts.TraceGep = CGOpts.SanitizeCoverageTraceGep;242Opts.Use8bitCounters = CGOpts.SanitizeCoverage8bitCounters;243Opts.TracePC = CGOpts.SanitizeCoverageTracePC;244Opts.TracePCGuard = CGOpts.SanitizeCoverageTracePCGuard;245Opts.NoPrune = CGOpts.SanitizeCoverageNoPrune;246Opts.Inline8bitCounters = CGOpts.SanitizeCoverageInline8bitCounters;247Opts.InlineBoolFlag = CGOpts.SanitizeCoverageInlineBoolFlag;248Opts.PCTable = CGOpts.SanitizeCoveragePCTable;249Opts.StackDepth = CGOpts.SanitizeCoverageStackDepth;250Opts.TraceLoads = CGOpts.SanitizeCoverageTraceLoads;251Opts.TraceStores = CGOpts.SanitizeCoverageTraceStores;252Opts.CollectControlFlow = CGOpts.SanitizeCoverageControlFlow;253return Opts;254}255256static SanitizerBinaryMetadataOptions257getSanitizerBinaryMetadataOptions(const CodeGenOptions &CGOpts) {258SanitizerBinaryMetadataOptions Opts;259Opts.Covered = CGOpts.SanitizeBinaryMetadataCovered;260Opts.Atomics = CGOpts.SanitizeBinaryMetadataAtomics;261Opts.UAR = CGOpts.SanitizeBinaryMetadataUAR;262return Opts;263}264265// Check if ASan should use GC-friendly instrumentation for globals.266// First of all, there is no point if -fdata-sections is off (expect for MachO,267// where this is not a factor). Also, on ELF this feature requires an assembler268// extension that only works with -integrated-as at the moment.269static bool asanUseGlobalsGC(const Triple &T, const CodeGenOptions &CGOpts) {270if (!CGOpts.SanitizeAddressGlobalsDeadStripping)271return false;272switch (T.getObjectFormat()) {273case Triple::MachO:274case Triple::COFF:275return true;276case Triple::ELF:277return !CGOpts.DisableIntegratedAS;278case Triple::GOFF:279llvm::report_fatal_error("ASan not implemented for GOFF");280case Triple::XCOFF:281llvm::report_fatal_error("ASan not implemented for XCOFF.");282case Triple::Wasm:283case Triple::DXContainer:284case Triple::SPIRV:285case Triple::UnknownObjectFormat:286break;287}288return false;289}290291static std::optional<llvm::CodeModel::Model>292getCodeModel(const CodeGenOptions &CodeGenOpts) {293unsigned CodeModel = llvm::StringSwitch<unsigned>(CodeGenOpts.CodeModel)294.Case("tiny", llvm::CodeModel::Tiny)295.Case("small", llvm::CodeModel::Small)296.Case("kernel", llvm::CodeModel::Kernel)297.Case("medium", llvm::CodeModel::Medium)298.Case("large", llvm::CodeModel::Large)299.Case("default", ~1u)300.Default(~0u);301assert(CodeModel != ~0u && "invalid code model!");302if (CodeModel == ~1u)303return std::nullopt;304return static_cast<llvm::CodeModel::Model>(CodeModel);305}306307static CodeGenFileType getCodeGenFileType(BackendAction Action) {308if (Action == Backend_EmitObj)309return CodeGenFileType::ObjectFile;310else if (Action == Backend_EmitMCNull)311return CodeGenFileType::Null;312else {313assert(Action == Backend_EmitAssembly && "Invalid action!");314return CodeGenFileType::AssemblyFile;315}316}317318static bool actionRequiresCodeGen(BackendAction Action) {319return Action != Backend_EmitNothing && Action != Backend_EmitBC &&320Action != Backend_EmitLL;321}322323static bool initTargetOptions(DiagnosticsEngine &Diags,324llvm::TargetOptions &Options,325const CodeGenOptions &CodeGenOpts,326const clang::TargetOptions &TargetOpts,327const LangOptions &LangOpts,328const HeaderSearchOptions &HSOpts) {329switch (LangOpts.getThreadModel()) {330case LangOptions::ThreadModelKind::POSIX:331Options.ThreadModel = llvm::ThreadModel::POSIX;332break;333case LangOptions::ThreadModelKind::Single:334Options.ThreadModel = llvm::ThreadModel::Single;335break;336}337338// Set float ABI type.339assert((CodeGenOpts.FloatABI == "soft" || CodeGenOpts.FloatABI == "softfp" ||340CodeGenOpts.FloatABI == "hard" || CodeGenOpts.FloatABI.empty()) &&341"Invalid Floating Point ABI!");342Options.FloatABIType =343llvm::StringSwitch<llvm::FloatABI::ABIType>(CodeGenOpts.FloatABI)344.Case("soft", llvm::FloatABI::Soft)345.Case("softfp", llvm::FloatABI::Soft)346.Case("hard", llvm::FloatABI::Hard)347.Default(llvm::FloatABI::Default);348349// Set FP fusion mode.350switch (LangOpts.getDefaultFPContractMode()) {351case LangOptions::FPM_Off:352// Preserve any contraction performed by the front-end. (Strict performs353// splitting of the muladd intrinsic in the backend.)354Options.AllowFPOpFusion = llvm::FPOpFusion::Standard;355break;356case LangOptions::FPM_On:357case LangOptions::FPM_FastHonorPragmas:358Options.AllowFPOpFusion = llvm::FPOpFusion::Standard;359break;360case LangOptions::FPM_Fast:361Options.AllowFPOpFusion = llvm::FPOpFusion::Fast;362break;363}364365Options.BinutilsVersion =366llvm::TargetMachine::parseBinutilsVersion(CodeGenOpts.BinutilsVersion);367Options.UseInitArray = CodeGenOpts.UseInitArray;368Options.DisableIntegratedAS = CodeGenOpts.DisableIntegratedAS;369370// Set EABI version.371Options.EABIVersion = TargetOpts.EABIVersion;372373if (LangOpts.hasSjLjExceptions())374Options.ExceptionModel = llvm::ExceptionHandling::SjLj;375if (LangOpts.hasSEHExceptions())376Options.ExceptionModel = llvm::ExceptionHandling::WinEH;377if (LangOpts.hasDWARFExceptions())378Options.ExceptionModel = llvm::ExceptionHandling::DwarfCFI;379if (LangOpts.hasWasmExceptions())380Options.ExceptionModel = llvm::ExceptionHandling::Wasm;381382Options.NoInfsFPMath = LangOpts.NoHonorInfs;383Options.NoNaNsFPMath = LangOpts.NoHonorNaNs;384Options.NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS;385Options.UnsafeFPMath = LangOpts.AllowFPReassoc && LangOpts.AllowRecip &&386LangOpts.NoSignedZero && LangOpts.ApproxFunc &&387(LangOpts.getDefaultFPContractMode() ==388LangOptions::FPModeKind::FPM_Fast ||389LangOpts.getDefaultFPContractMode() ==390LangOptions::FPModeKind::FPM_FastHonorPragmas);391Options.ApproxFuncFPMath = LangOpts.ApproxFunc;392393Options.BBAddrMap = CodeGenOpts.BBAddrMap;394Options.BBSections =395llvm::StringSwitch<llvm::BasicBlockSection>(CodeGenOpts.BBSections)396.Case("all", llvm::BasicBlockSection::All)397.Case("labels", llvm::BasicBlockSection::Labels)398.StartsWith("list=", llvm::BasicBlockSection::List)399.Case("none", llvm::BasicBlockSection::None)400.Default(llvm::BasicBlockSection::None);401402if (Options.BBSections == llvm::BasicBlockSection::List) {403ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =404MemoryBuffer::getFile(CodeGenOpts.BBSections.substr(5));405if (!MBOrErr) {406Diags.Report(diag::err_fe_unable_to_load_basic_block_sections_file)407<< MBOrErr.getError().message();408return false;409}410Options.BBSectionsFuncListBuf = std::move(*MBOrErr);411}412413Options.EnableMachineFunctionSplitter = CodeGenOpts.SplitMachineFunctions;414Options.FunctionSections = CodeGenOpts.FunctionSections;415Options.DataSections = CodeGenOpts.DataSections;416Options.IgnoreXCOFFVisibility = LangOpts.IgnoreXCOFFVisibility;417Options.UniqueSectionNames = CodeGenOpts.UniqueSectionNames;418Options.UniqueBasicBlockSectionNames =419CodeGenOpts.UniqueBasicBlockSectionNames;420Options.SeparateNamedSections = CodeGenOpts.SeparateNamedSections;421Options.TLSSize = CodeGenOpts.TLSSize;422Options.EnableTLSDESC = CodeGenOpts.EnableTLSDESC;423Options.EmulatedTLS = CodeGenOpts.EmulatedTLS;424Options.DebuggerTuning = CodeGenOpts.getDebuggerTuning();425Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection;426Options.StackUsageOutput = CodeGenOpts.StackUsageOutput;427Options.EmitAddrsig = CodeGenOpts.Addrsig;428Options.ForceDwarfFrameSection = CodeGenOpts.ForceDwarfFrameSection;429Options.EmitCallSiteInfo = CodeGenOpts.EmitCallSiteInfo;430Options.EnableAIXExtendedAltivecABI = LangOpts.EnableAIXExtendedAltivecABI;431Options.XRayFunctionIndex = CodeGenOpts.XRayFunctionIndex;432Options.LoopAlignment = CodeGenOpts.LoopAlignment;433Options.DebugStrictDwarf = CodeGenOpts.DebugStrictDwarf;434Options.ObjectFilenameForDebug = CodeGenOpts.ObjectFilenameForDebug;435Options.Hotpatch = CodeGenOpts.HotPatch;436Options.JMCInstrument = CodeGenOpts.JMCInstrument;437Options.XCOFFReadOnlyPointers = CodeGenOpts.XCOFFReadOnlyPointers;438439switch (CodeGenOpts.getSwiftAsyncFramePointer()) {440case CodeGenOptions::SwiftAsyncFramePointerKind::Auto:441Options.SwiftAsyncFramePointer =442SwiftAsyncFramePointerMode::DeploymentBased;443break;444445case CodeGenOptions::SwiftAsyncFramePointerKind::Always:446Options.SwiftAsyncFramePointer = SwiftAsyncFramePointerMode::Always;447break;448449case CodeGenOptions::SwiftAsyncFramePointerKind::Never:450Options.SwiftAsyncFramePointer = SwiftAsyncFramePointerMode::Never;451break;452}453454Options.MCOptions.SplitDwarfFile = CodeGenOpts.SplitDwarfFile;455Options.MCOptions.EmitDwarfUnwind = CodeGenOpts.getEmitDwarfUnwind();456Options.MCOptions.EmitCompactUnwindNonCanonical =457CodeGenOpts.EmitCompactUnwindNonCanonical;458Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll;459Options.MCOptions.MCSaveTempLabels = CodeGenOpts.SaveTempLabels;460Options.MCOptions.MCUseDwarfDirectory =461CodeGenOpts.NoDwarfDirectoryAsm462? llvm::MCTargetOptions::DisableDwarfDirectory463: llvm::MCTargetOptions::EnableDwarfDirectory;464Options.MCOptions.MCNoExecStack = CodeGenOpts.NoExecStack;465Options.MCOptions.MCIncrementalLinkerCompatible =466CodeGenOpts.IncrementalLinkerCompatible;467Options.MCOptions.MCFatalWarnings = CodeGenOpts.FatalWarnings;468Options.MCOptions.MCNoWarn = CodeGenOpts.NoWarn;469Options.MCOptions.AsmVerbose = CodeGenOpts.AsmVerbose;470Options.MCOptions.Dwarf64 = CodeGenOpts.Dwarf64;471Options.MCOptions.PreserveAsmComments = CodeGenOpts.PreserveAsmComments;472Options.MCOptions.Crel = CodeGenOpts.Crel;473Options.MCOptions.X86RelaxRelocations = CodeGenOpts.RelaxELFRelocations;474Options.MCOptions.CompressDebugSections =475CodeGenOpts.getCompressDebugSections();476Options.MCOptions.ABIName = TargetOpts.ABI;477for (const auto &Entry : HSOpts.UserEntries)478if (!Entry.IsFramework &&479(Entry.Group == frontend::IncludeDirGroup::Quoted ||480Entry.Group == frontend::IncludeDirGroup::Angled ||481Entry.Group == frontend::IncludeDirGroup::System))482Options.MCOptions.IASSearchPaths.push_back(483Entry.IgnoreSysRoot ? Entry.Path : HSOpts.Sysroot + Entry.Path);484Options.MCOptions.Argv0 = CodeGenOpts.Argv0;485Options.MCOptions.CommandLineArgs = CodeGenOpts.CommandLineArgs;486Options.MCOptions.AsSecureLogFile = CodeGenOpts.AsSecureLogFile;487Options.MCOptions.PPCUseFullRegisterNames =488CodeGenOpts.PPCUseFullRegisterNames;489Options.MisExpect = CodeGenOpts.MisExpect;490491return true;492}493494static std::optional<GCOVOptions>495getGCOVOptions(const CodeGenOptions &CodeGenOpts, const LangOptions &LangOpts) {496if (CodeGenOpts.CoverageNotesFile.empty() &&497CodeGenOpts.CoverageDataFile.empty())498return std::nullopt;499// Not using 'GCOVOptions::getDefault' allows us to avoid exiting if500// LLVM's -default-gcov-version flag is set to something invalid.501GCOVOptions Options;502Options.EmitNotes = !CodeGenOpts.CoverageNotesFile.empty();503Options.EmitData = !CodeGenOpts.CoverageDataFile.empty();504llvm::copy(CodeGenOpts.CoverageVersion, std::begin(Options.Version));505Options.NoRedZone = CodeGenOpts.DisableRedZone;506Options.Filter = CodeGenOpts.ProfileFilterFiles;507Options.Exclude = CodeGenOpts.ProfileExcludeFiles;508Options.Atomic = CodeGenOpts.AtomicProfileUpdate;509return Options;510}511512static std::optional<InstrProfOptions>513getInstrProfOptions(const CodeGenOptions &CodeGenOpts,514const LangOptions &LangOpts) {515if (!CodeGenOpts.hasProfileClangInstr())516return std::nullopt;517InstrProfOptions Options;518Options.NoRedZone = CodeGenOpts.DisableRedZone;519Options.InstrProfileOutput = CodeGenOpts.InstrProfileOutput;520Options.Atomic = CodeGenOpts.AtomicProfileUpdate;521return Options;522}523524static void setCommandLineOpts(const CodeGenOptions &CodeGenOpts) {525SmallVector<const char *, 16> BackendArgs;526BackendArgs.push_back("clang"); // Fake program name.527if (!CodeGenOpts.DebugPass.empty()) {528BackendArgs.push_back("-debug-pass");529BackendArgs.push_back(CodeGenOpts.DebugPass.c_str());530}531if (!CodeGenOpts.LimitFloatPrecision.empty()) {532BackendArgs.push_back("-limit-float-precision");533BackendArgs.push_back(CodeGenOpts.LimitFloatPrecision.c_str());534}535// Check for the default "clang" invocation that won't set any cl::opt values.536// Skip trying to parse the command line invocation to avoid the issues537// described below.538if (BackendArgs.size() == 1)539return;540BackendArgs.push_back(nullptr);541// FIXME: The command line parser below is not thread-safe and shares a global542// state, so this call might crash or overwrite the options of another Clang543// instance in the same process.544llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1,545BackendArgs.data());546}547548void EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {549// Create the TargetMachine for generating code.550std::string Error;551std::string Triple = TheModule->getTargetTriple();552const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);553if (!TheTarget) {554if (MustCreateTM)555Diags.Report(diag::err_fe_unable_to_create_target) << Error;556return;557}558559std::optional<llvm::CodeModel::Model> CM = getCodeModel(CodeGenOpts);560std::string FeaturesStr =561llvm::join(TargetOpts.Features.begin(), TargetOpts.Features.end(), ",");562llvm::Reloc::Model RM = CodeGenOpts.RelocationModel;563std::optional<CodeGenOptLevel> OptLevelOrNone =564CodeGenOpt::getLevel(CodeGenOpts.OptimizationLevel);565assert(OptLevelOrNone && "Invalid optimization level!");566CodeGenOptLevel OptLevel = *OptLevelOrNone;567568llvm::TargetOptions Options;569if (!initTargetOptions(Diags, Options, CodeGenOpts, TargetOpts, LangOpts,570HSOpts))571return;572TM.reset(TheTarget->createTargetMachine(Triple, TargetOpts.CPU, FeaturesStr,573Options, RM, CM, OptLevel));574TM->setLargeDataThreshold(CodeGenOpts.LargeDataThreshold);575}576577bool EmitAssemblyHelper::AddEmitPasses(legacy::PassManager &CodeGenPasses,578BackendAction Action,579raw_pwrite_stream &OS,580raw_pwrite_stream *DwoOS) {581// Add LibraryInfo.582std::unique_ptr<TargetLibraryInfoImpl> TLII(583llvm::driver::createTLII(TargetTriple, CodeGenOpts.getVecLib()));584CodeGenPasses.add(new TargetLibraryInfoWrapperPass(*TLII));585586// Normal mode, emit a .s or .o file by running the code generator. Note,587// this also adds codegenerator level optimization passes.588CodeGenFileType CGFT = getCodeGenFileType(Action);589590// Add ObjC ARC final-cleanup optimizations. This is done as part of the591// "codegen" passes so that it isn't run multiple times when there is592// inlining happening.593if (CodeGenOpts.OptimizationLevel > 0)594CodeGenPasses.add(createObjCARCContractPass());595596if (TM->addPassesToEmitFile(CodeGenPasses, OS, DwoOS, CGFT,597/*DisableVerify=*/!CodeGenOpts.VerifyModule)) {598Diags.Report(diag::err_fe_unable_to_interface_with_target);599return false;600}601602return true;603}604605static OptimizationLevel mapToLevel(const CodeGenOptions &Opts) {606switch (Opts.OptimizationLevel) {607default:608llvm_unreachable("Invalid optimization level!");609610case 0:611return OptimizationLevel::O0;612613case 1:614return OptimizationLevel::O1;615616case 2:617switch (Opts.OptimizeSize) {618default:619llvm_unreachable("Invalid optimization level for size!");620621case 0:622return OptimizationLevel::O2;623624case 1:625return OptimizationLevel::Os;626627case 2:628return OptimizationLevel::Oz;629}630631case 3:632return OptimizationLevel::O3;633}634}635636static void addKCFIPass(const Triple &TargetTriple, const LangOptions &LangOpts,637PassBuilder &PB) {638// If the back-end supports KCFI operand bundle lowering, skip KCFIPass.639if (TargetTriple.getArch() == llvm::Triple::x86_64 ||640TargetTriple.isAArch64(64) || TargetTriple.isRISCV())641return;642643// Ensure we lower KCFI operand bundles with -O0.644PB.registerOptimizerLastEPCallback(645[&](ModulePassManager &MPM, OptimizationLevel Level) {646if (Level == OptimizationLevel::O0 &&647LangOpts.Sanitize.has(SanitizerKind::KCFI))648MPM.addPass(createModuleToFunctionPassAdaptor(KCFIPass()));649});650651// When optimizations are requested, run KCIFPass after InstCombine to652// avoid unnecessary checks.653PB.registerPeepholeEPCallback(654[&](FunctionPassManager &FPM, OptimizationLevel Level) {655if (Level != OptimizationLevel::O0 &&656LangOpts.Sanitize.has(SanitizerKind::KCFI))657FPM.addPass(KCFIPass());658});659}660661static void addSanitizers(const Triple &TargetTriple,662const CodeGenOptions &CodeGenOpts,663const LangOptions &LangOpts, PassBuilder &PB) {664auto SanitizersCallback = [&](ModulePassManager &MPM,665OptimizationLevel Level) {666if (CodeGenOpts.hasSanitizeCoverage()) {667auto SancovOpts = getSancovOptsFromCGOpts(CodeGenOpts);668MPM.addPass(SanitizerCoveragePass(669SancovOpts, CodeGenOpts.SanitizeCoverageAllowlistFiles,670CodeGenOpts.SanitizeCoverageIgnorelistFiles));671}672673if (CodeGenOpts.hasSanitizeBinaryMetadata()) {674MPM.addPass(SanitizerBinaryMetadataPass(675getSanitizerBinaryMetadataOptions(CodeGenOpts),676CodeGenOpts.SanitizeMetadataIgnorelistFiles));677}678679auto MSanPass = [&](SanitizerMask Mask, bool CompileKernel) {680if (LangOpts.Sanitize.has(Mask)) {681int TrackOrigins = CodeGenOpts.SanitizeMemoryTrackOrigins;682bool Recover = CodeGenOpts.SanitizeRecover.has(Mask);683684MemorySanitizerOptions options(TrackOrigins, Recover, CompileKernel,685CodeGenOpts.SanitizeMemoryParamRetval);686MPM.addPass(MemorySanitizerPass(options));687if (Level != OptimizationLevel::O0) {688// MemorySanitizer inserts complex instrumentation that mostly follows689// the logic of the original code, but operates on "shadow" values. It690// can benefit from re-running some general purpose optimization691// passes.692MPM.addPass(RequireAnalysisPass<GlobalsAA, llvm::Module>());693FunctionPassManager FPM;694FPM.addPass(EarlyCSEPass(true /* Enable mem-ssa. */));695FPM.addPass(InstCombinePass());696FPM.addPass(JumpThreadingPass());697FPM.addPass(GVNPass());698FPM.addPass(InstCombinePass());699MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));700}701}702};703MSanPass(SanitizerKind::Memory, false);704MSanPass(SanitizerKind::KernelMemory, true);705706if (LangOpts.Sanitize.has(SanitizerKind::Thread)) {707MPM.addPass(ModuleThreadSanitizerPass());708MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));709}710711if (LangOpts.Sanitize.has(SanitizerKind::NumericalStability))712MPM.addPass(NumericalStabilitySanitizerPass());713714auto ASanPass = [&](SanitizerMask Mask, bool CompileKernel) {715if (LangOpts.Sanitize.has(Mask)) {716bool UseGlobalGC = asanUseGlobalsGC(TargetTriple, CodeGenOpts);717bool UseOdrIndicator = CodeGenOpts.SanitizeAddressUseOdrIndicator;718llvm::AsanDtorKind DestructorKind =719CodeGenOpts.getSanitizeAddressDtor();720AddressSanitizerOptions Opts;721Opts.CompileKernel = CompileKernel;722Opts.Recover = CodeGenOpts.SanitizeRecover.has(Mask);723Opts.UseAfterScope = CodeGenOpts.SanitizeAddressUseAfterScope;724Opts.UseAfterReturn = CodeGenOpts.getSanitizeAddressUseAfterReturn();725MPM.addPass(AddressSanitizerPass(Opts, UseGlobalGC, UseOdrIndicator,726DestructorKind));727}728};729ASanPass(SanitizerKind::Address, false);730ASanPass(SanitizerKind::KernelAddress, true);731732auto HWASanPass = [&](SanitizerMask Mask, bool CompileKernel) {733if (LangOpts.Sanitize.has(Mask)) {734bool Recover = CodeGenOpts.SanitizeRecover.has(Mask);735MPM.addPass(HWAddressSanitizerPass(736{CompileKernel, Recover,737/*DisableOptimization=*/CodeGenOpts.OptimizationLevel == 0}));738}739};740HWASanPass(SanitizerKind::HWAddress, false);741HWASanPass(SanitizerKind::KernelHWAddress, true);742743if (LangOpts.Sanitize.has(SanitizerKind::DataFlow)) {744MPM.addPass(DataFlowSanitizerPass(LangOpts.NoSanitizeFiles));745}746};747if (ClSanitizeOnOptimizerEarlyEP) {748PB.registerOptimizerEarlyEPCallback(749[SanitizersCallback](ModulePassManager &MPM, OptimizationLevel Level) {750ModulePassManager NewMPM;751SanitizersCallback(NewMPM, Level);752if (!NewMPM.isEmpty()) {753// Sanitizers can abandon<GlobalsAA>.754NewMPM.addPass(RequireAnalysisPass<GlobalsAA, llvm::Module>());755MPM.addPass(std::move(NewMPM));756}757});758} else {759// LastEP does not need GlobalsAA.760PB.registerOptimizerLastEPCallback(SanitizersCallback);761}762763if (LowerAllowCheckPass::IsRequested()) {764// We can optimize after inliner, and PGO profile matching. The hook below765// is called at the end `buildFunctionSimplificationPipeline`, which called766// from `buildInlinerPipeline`, which called after profile matching.767PB.registerScalarOptimizerLateEPCallback(768[](FunctionPassManager &FPM, OptimizationLevel Level) {769FPM.addPass(LowerAllowCheckPass());770});771}772}773774void EmitAssemblyHelper::RunOptimizationPipeline(775BackendAction Action, std::unique_ptr<raw_pwrite_stream> &OS,776std::unique_ptr<llvm::ToolOutputFile> &ThinLinkOS, BackendConsumer *BC) {777std::optional<PGOOptions> PGOOpt;778779if (CodeGenOpts.hasProfileIRInstr())780// -fprofile-generate.781PGOOpt = PGOOptions(782CodeGenOpts.InstrProfileOutput.empty() ? getDefaultProfileGenName()783: CodeGenOpts.InstrProfileOutput,784"", "", CodeGenOpts.MemoryProfileUsePath, nullptr, PGOOptions::IRInstr,785PGOOptions::NoCSAction, ClPGOColdFuncAttr,786CodeGenOpts.DebugInfoForProfiling,787/*PseudoProbeForProfiling=*/false, CodeGenOpts.AtomicProfileUpdate);788else if (CodeGenOpts.hasProfileIRUse()) {789// -fprofile-use.790auto CSAction = CodeGenOpts.hasProfileCSIRUse() ? PGOOptions::CSIRUse791: PGOOptions::NoCSAction;792PGOOpt = PGOOptions(CodeGenOpts.ProfileInstrumentUsePath, "",793CodeGenOpts.ProfileRemappingFile,794CodeGenOpts.MemoryProfileUsePath, VFS,795PGOOptions::IRUse, CSAction, ClPGOColdFuncAttr,796CodeGenOpts.DebugInfoForProfiling);797} else if (!CodeGenOpts.SampleProfileFile.empty())798// -fprofile-sample-use799PGOOpt = PGOOptions(800CodeGenOpts.SampleProfileFile, "", CodeGenOpts.ProfileRemappingFile,801CodeGenOpts.MemoryProfileUsePath, VFS, PGOOptions::SampleUse,802PGOOptions::NoCSAction, ClPGOColdFuncAttr,803CodeGenOpts.DebugInfoForProfiling, CodeGenOpts.PseudoProbeForProfiling);804else if (!CodeGenOpts.MemoryProfileUsePath.empty())805// -fmemory-profile-use (without any of the above options)806PGOOpt = PGOOptions("", "", "", CodeGenOpts.MemoryProfileUsePath, VFS,807PGOOptions::NoAction, PGOOptions::NoCSAction,808ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling);809else if (CodeGenOpts.PseudoProbeForProfiling)810// -fpseudo-probe-for-profiling811PGOOpt =812PGOOptions("", "", "", /*MemoryProfile=*/"", nullptr,813PGOOptions::NoAction, PGOOptions::NoCSAction,814ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling, true);815else if (CodeGenOpts.DebugInfoForProfiling)816// -fdebug-info-for-profiling817PGOOpt = PGOOptions("", "", "", /*MemoryProfile=*/"", nullptr,818PGOOptions::NoAction, PGOOptions::NoCSAction,819ClPGOColdFuncAttr, true);820821// Check to see if we want to generate a CS profile.822if (CodeGenOpts.hasProfileCSIRInstr()) {823assert(!CodeGenOpts.hasProfileCSIRUse() &&824"Cannot have both CSProfileUse pass and CSProfileGen pass at "825"the same time");826if (PGOOpt) {827assert(PGOOpt->Action != PGOOptions::IRInstr &&828PGOOpt->Action != PGOOptions::SampleUse &&829"Cannot run CSProfileGen pass with ProfileGen or SampleUse "830" pass");831PGOOpt->CSProfileGenFile = CodeGenOpts.InstrProfileOutput.empty()832? getDefaultProfileGenName()833: CodeGenOpts.InstrProfileOutput;834PGOOpt->CSAction = PGOOptions::CSIRInstr;835} else836PGOOpt = PGOOptions("",837CodeGenOpts.InstrProfileOutput.empty()838? getDefaultProfileGenName()839: CodeGenOpts.InstrProfileOutput,840"", /*MemoryProfile=*/"", nullptr,841PGOOptions::NoAction, PGOOptions::CSIRInstr,842ClPGOColdFuncAttr, CodeGenOpts.DebugInfoForProfiling);843}844if (TM)845TM->setPGOOption(PGOOpt);846847PipelineTuningOptions PTO;848PTO.LoopUnrolling = CodeGenOpts.UnrollLoops;849// For historical reasons, loop interleaving is set to mirror setting for loop850// unrolling.851PTO.LoopInterleaving = CodeGenOpts.UnrollLoops;852PTO.LoopVectorization = CodeGenOpts.VectorizeLoop;853PTO.SLPVectorization = CodeGenOpts.VectorizeSLP;854PTO.MergeFunctions = CodeGenOpts.MergeFunctions;855// Only enable CGProfilePass when using integrated assembler, since856// non-integrated assemblers don't recognize .cgprofile section.857PTO.CallGraphProfile = !CodeGenOpts.DisableIntegratedAS;858PTO.UnifiedLTO = CodeGenOpts.UnifiedLTO;859860LoopAnalysisManager LAM;861FunctionAnalysisManager FAM;862CGSCCAnalysisManager CGAM;863ModuleAnalysisManager MAM;864865bool DebugPassStructure = CodeGenOpts.DebugPass == "Structure";866PassInstrumentationCallbacks PIC;867PrintPassOptions PrintPassOpts;868PrintPassOpts.Indent = DebugPassStructure;869PrintPassOpts.SkipAnalyses = DebugPassStructure;870StandardInstrumentations SI(871TheModule->getContext(),872(CodeGenOpts.DebugPassManager || DebugPassStructure),873CodeGenOpts.VerifyEach, PrintPassOpts);874SI.registerCallbacks(PIC, &MAM);875PassBuilder PB(TM.get(), PTO, PGOOpt, &PIC);876877// Handle the assignment tracking feature options.878switch (CodeGenOpts.getAssignmentTrackingMode()) {879case CodeGenOptions::AssignmentTrackingOpts::Forced:880PB.registerPipelineStartEPCallback(881[&](ModulePassManager &MPM, OptimizationLevel Level) {882MPM.addPass(AssignmentTrackingPass());883});884break;885case CodeGenOptions::AssignmentTrackingOpts::Enabled:886// Disable assignment tracking in LTO builds for now as the performance887// cost is too high. Disable for LLDB tuning due to llvm.org/PR43126.888if (!CodeGenOpts.PrepareForThinLTO && !CodeGenOpts.PrepareForLTO &&889CodeGenOpts.getDebuggerTuning() != llvm::DebuggerKind::LLDB) {890PB.registerPipelineStartEPCallback(891[&](ModulePassManager &MPM, OptimizationLevel Level) {892// Only use assignment tracking if optimisations are enabled.893if (Level != OptimizationLevel::O0)894MPM.addPass(AssignmentTrackingPass());895});896}897break;898case CodeGenOptions::AssignmentTrackingOpts::Disabled:899break;900}901902// Enable verify-debuginfo-preserve-each for new PM.903DebugifyEachInstrumentation Debugify;904DebugInfoPerPass DebugInfoBeforePass;905if (CodeGenOpts.EnableDIPreservationVerify) {906Debugify.setDebugifyMode(DebugifyMode::OriginalDebugInfo);907Debugify.setDebugInfoBeforePass(DebugInfoBeforePass);908909if (!CodeGenOpts.DIBugsReportFilePath.empty())910Debugify.setOrigDIVerifyBugsReportFilePath(911CodeGenOpts.DIBugsReportFilePath);912Debugify.registerCallbacks(PIC, MAM);913}914// Attempt to load pass plugins and register their callbacks with PB.915for (auto &PluginFN : CodeGenOpts.PassPlugins) {916auto PassPlugin = PassPlugin::Load(PluginFN);917if (PassPlugin) {918PassPlugin->registerPassBuilderCallbacks(PB);919} else {920Diags.Report(diag::err_fe_unable_to_load_plugin)921<< PluginFN << toString(PassPlugin.takeError());922}923}924for (const auto &PassCallback : CodeGenOpts.PassBuilderCallbacks)925PassCallback(PB);926#define HANDLE_EXTENSION(Ext) \927get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);928#include "llvm/Support/Extension.def"929930// Register the target library analysis directly and give it a customized931// preset TLI.932std::unique_ptr<TargetLibraryInfoImpl> TLII(933llvm::driver::createTLII(TargetTriple, CodeGenOpts.getVecLib()));934FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });935936// Register all the basic analyses with the managers.937PB.registerModuleAnalyses(MAM);938PB.registerCGSCCAnalyses(CGAM);939PB.registerFunctionAnalyses(FAM);940PB.registerLoopAnalyses(LAM);941PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);942943ModulePassManager MPM;944// Add a verifier pass, before any other passes, to catch CodeGen issues.945if (CodeGenOpts.VerifyModule)946MPM.addPass(VerifierPass());947948if (!CodeGenOpts.DisableLLVMPasses) {949// Map our optimization levels into one of the distinct levels used to950// configure the pipeline.951OptimizationLevel Level = mapToLevel(CodeGenOpts);952953const bool PrepareForThinLTO = CodeGenOpts.PrepareForThinLTO;954const bool PrepareForLTO = CodeGenOpts.PrepareForLTO;955956if (LangOpts.ObjCAutoRefCount) {957PB.registerPipelineStartEPCallback(958[](ModulePassManager &MPM, OptimizationLevel Level) {959if (Level != OptimizationLevel::O0)960MPM.addPass(961createModuleToFunctionPassAdaptor(ObjCARCExpandPass()));962});963PB.registerPipelineEarlySimplificationEPCallback(964[](ModulePassManager &MPM, OptimizationLevel Level) {965if (Level != OptimizationLevel::O0)966MPM.addPass(ObjCARCAPElimPass());967});968PB.registerScalarOptimizerLateEPCallback(969[](FunctionPassManager &FPM, OptimizationLevel Level) {970if (Level != OptimizationLevel::O0)971FPM.addPass(ObjCARCOptPass());972});973}974975// If we reached here with a non-empty index file name, then the index976// file was empty and we are not performing ThinLTO backend compilation977// (used in testing in a distributed build environment).978bool IsThinLTOPostLink = !CodeGenOpts.ThinLTOIndexFile.empty();979// If so drop any the type test assume sequences inserted for whole program980// vtables so that codegen doesn't complain.981if (IsThinLTOPostLink)982PB.registerPipelineStartEPCallback(983[](ModulePassManager &MPM, OptimizationLevel Level) {984MPM.addPass(LowerTypeTestsPass(/*ExportSummary=*/nullptr,985/*ImportSummary=*/nullptr,986/*DropTypeTests=*/true));987});988989// Register callbacks to schedule sanitizer passes at the appropriate part990// of the pipeline.991if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds))992PB.registerScalarOptimizerLateEPCallback(993[](FunctionPassManager &FPM, OptimizationLevel Level) {994FPM.addPass(BoundsCheckingPass());995});996997// Don't add sanitizers if we are here from ThinLTO PostLink. That already998// done on PreLink stage.999if (!IsThinLTOPostLink) {1000addSanitizers(TargetTriple, CodeGenOpts, LangOpts, PB);1001addKCFIPass(TargetTriple, LangOpts, PB);1002}10031004if (std::optional<GCOVOptions> Options =1005getGCOVOptions(CodeGenOpts, LangOpts))1006PB.registerPipelineStartEPCallback(1007[Options](ModulePassManager &MPM, OptimizationLevel Level) {1008MPM.addPass(GCOVProfilerPass(*Options));1009});1010if (std::optional<InstrProfOptions> Options =1011getInstrProfOptions(CodeGenOpts, LangOpts))1012PB.registerPipelineStartEPCallback(1013[Options](ModulePassManager &MPM, OptimizationLevel Level) {1014MPM.addPass(InstrProfilingLoweringPass(*Options, false));1015});10161017// TODO: Consider passing the MemoryProfileOutput to the pass builder via1018// the PGOOptions, and set this up there.1019if (!CodeGenOpts.MemoryProfileOutput.empty()) {1020PB.registerOptimizerLastEPCallback(1021[](ModulePassManager &MPM, OptimizationLevel Level) {1022MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass()));1023MPM.addPass(ModuleMemProfilerPass());1024});1025}10261027if (CodeGenOpts.FatLTO) {1028MPM.addPass(PB.buildFatLTODefaultPipeline(1029Level, PrepareForThinLTO,1030PrepareForThinLTO || shouldEmitRegularLTOSummary()));1031} else if (PrepareForThinLTO) {1032MPM.addPass(PB.buildThinLTOPreLinkDefaultPipeline(Level));1033} else if (PrepareForLTO) {1034MPM.addPass(PB.buildLTOPreLinkDefaultPipeline(Level));1035} else {1036MPM.addPass(PB.buildPerModuleDefaultPipeline(Level));1037}1038}10391040// Link against bitcodes supplied via the -mlink-builtin-bitcode option1041if (CodeGenOpts.LinkBitcodePostopt)1042MPM.addPass(LinkInModulesPass(BC));10431044// Add a verifier pass if requested. We don't have to do this if the action1045// requires code generation because there will already be a verifier pass in1046// the code-generation pipeline.1047// Since we already added a verifier pass above, this1048// might even not run the analysis, if previous passes caused no changes.1049if (!actionRequiresCodeGen(Action) && CodeGenOpts.VerifyModule)1050MPM.addPass(VerifierPass());10511052if (Action == Backend_EmitBC || Action == Backend_EmitLL ||1053CodeGenOpts.FatLTO) {1054if (CodeGenOpts.PrepareForThinLTO && !CodeGenOpts.DisableLLVMPasses) {1055if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))1056TheModule->addModuleFlag(llvm::Module::Error, "EnableSplitLTOUnit",1057CodeGenOpts.EnableSplitLTOUnit);1058if (Action == Backend_EmitBC) {1059if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) {1060ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile);1061if (!ThinLinkOS)1062return;1063}1064MPM.addPass(ThinLTOBitcodeWriterPass(1065*OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr));1066} else if (Action == Backend_EmitLL) {1067MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists,1068/*EmitLTOSummary=*/true));1069}1070} else {1071// Emit a module summary by default for Regular LTO except for ld641072// targets1073bool EmitLTOSummary = shouldEmitRegularLTOSummary();1074if (EmitLTOSummary) {1075if (!TheModule->getModuleFlag("ThinLTO") && !CodeGenOpts.UnifiedLTO)1076TheModule->addModuleFlag(llvm::Module::Error, "ThinLTO", uint32_t(0));1077if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))1078TheModule->addModuleFlag(llvm::Module::Error, "EnableSplitLTOUnit",1079uint32_t(1));1080}1081if (Action == Backend_EmitBC) {1082MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists,1083EmitLTOSummary));1084} else if (Action == Backend_EmitLL) {1085MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists,1086EmitLTOSummary));1087}1088}10891090if (shouldEmitUnifiedLTOModueFlag())1091TheModule->addModuleFlag(llvm::Module::Error, "UnifiedLTO", uint32_t(1));1092}10931094// Print a textual, '-passes=' compatible, representation of pipeline if1095// requested.1096if (PrintPipelinePasses) {1097MPM.printPipeline(outs(), [&PIC](StringRef ClassName) {1098auto PassName = PIC.getPassNameForClassName(ClassName);1099return PassName.empty() ? ClassName : PassName;1100});1101outs() << "\n";1102return;1103}11041105if (LangOpts.HIPStdPar && !LangOpts.CUDAIsDevice &&1106LangOpts.HIPStdParInterposeAlloc)1107MPM.addPass(HipStdParAllocationInterpositionPass());11081109// Now that we have all of the passes ready, run them.1110{1111PrettyStackTraceString CrashInfo("Optimizer");1112llvm::TimeTraceScope TimeScope("Optimizer");1113MPM.run(*TheModule, MAM);1114}1115}11161117void EmitAssemblyHelper::RunCodegenPipeline(1118BackendAction Action, std::unique_ptr<raw_pwrite_stream> &OS,1119std::unique_ptr<llvm::ToolOutputFile> &DwoOS) {1120// We still use the legacy PM to run the codegen pipeline since the new PM1121// does not work with the codegen pipeline.1122// FIXME: make the new PM work with the codegen pipeline.1123legacy::PassManager CodeGenPasses;11241125// Append any output we need to the pass manager.1126switch (Action) {1127case Backend_EmitAssembly:1128case Backend_EmitMCNull:1129case Backend_EmitObj:1130CodeGenPasses.add(1131createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));1132if (!CodeGenOpts.SplitDwarfOutput.empty()) {1133DwoOS = openOutputFile(CodeGenOpts.SplitDwarfOutput);1134if (!DwoOS)1135return;1136}1137if (!AddEmitPasses(CodeGenPasses, Action, *OS,1138DwoOS ? &DwoOS->os() : nullptr))1139// FIXME: Should we handle this error differently?1140return;1141break;1142default:1143return;1144}11451146// If -print-pipeline-passes is requested, don't run the legacy pass manager.1147// FIXME: when codegen is switched to use the new pass manager, it should also1148// emit pass names here.1149if (PrintPipelinePasses) {1150return;1151}11521153{1154PrettyStackTraceString CrashInfo("Code generation");1155llvm::TimeTraceScope TimeScope("CodeGenPasses");1156CodeGenPasses.run(*TheModule);1157}1158}11591160void EmitAssemblyHelper::EmitAssembly(BackendAction Action,1161std::unique_ptr<raw_pwrite_stream> OS,1162BackendConsumer *BC) {1163TimeRegion Region(CodeGenOpts.TimePasses ? &CodeGenerationTime : nullptr);1164setCommandLineOpts(CodeGenOpts);11651166bool RequiresCodeGen = actionRequiresCodeGen(Action);1167CreateTargetMachine(RequiresCodeGen);11681169if (RequiresCodeGen && !TM)1170return;1171if (TM)1172TheModule->setDataLayout(TM->createDataLayout());11731174// Before executing passes, print the final values of the LLVM options.1175cl::PrintOptionValues();11761177std::unique_ptr<llvm::ToolOutputFile> ThinLinkOS, DwoOS;1178RunOptimizationPipeline(Action, OS, ThinLinkOS, BC);1179RunCodegenPipeline(Action, OS, DwoOS);11801181if (ThinLinkOS)1182ThinLinkOS->keep();1183if (DwoOS)1184DwoOS->keep();1185}11861187static void runThinLTOBackend(1188DiagnosticsEngine &Diags, ModuleSummaryIndex *CombinedIndex,1189llvm::Module *M, const HeaderSearchOptions &HeaderOpts,1190const CodeGenOptions &CGOpts, const clang::TargetOptions &TOpts,1191const LangOptions &LOpts, std::unique_ptr<raw_pwrite_stream> OS,1192std::string SampleProfile, std::string ProfileRemapping,1193BackendAction Action) {1194DenseMap<StringRef, DenseMap<GlobalValue::GUID, GlobalValueSummary *>>1195ModuleToDefinedGVSummaries;1196CombinedIndex->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);11971198setCommandLineOpts(CGOpts);11991200// We can simply import the values mentioned in the combined index, since1201// we should only invoke this using the individual indexes written out1202// via a WriteIndexesThinBackend.1203FunctionImporter::ImportMapTy ImportList;1204if (!lto::initImportList(*M, *CombinedIndex, ImportList))1205return;12061207auto AddStream = [&](size_t Task, const Twine &ModuleName) {1208return std::make_unique<CachedFileStream>(std::move(OS),1209CGOpts.ObjectFilenameForDebug);1210};1211lto::Config Conf;1212if (CGOpts.SaveTempsFilePrefix != "") {1213if (Error E = Conf.addSaveTemps(CGOpts.SaveTempsFilePrefix + ".",1214/* UseInputModulePath */ false)) {1215handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {1216errs() << "Error setting up ThinLTO save-temps: " << EIB.message()1217<< '\n';1218});1219}1220}1221Conf.CPU = TOpts.CPU;1222Conf.CodeModel = getCodeModel(CGOpts);1223Conf.MAttrs = TOpts.Features;1224Conf.RelocModel = CGOpts.RelocationModel;1225std::optional<CodeGenOptLevel> OptLevelOrNone =1226CodeGenOpt::getLevel(CGOpts.OptimizationLevel);1227assert(OptLevelOrNone && "Invalid optimization level!");1228Conf.CGOptLevel = *OptLevelOrNone;1229Conf.OptLevel = CGOpts.OptimizationLevel;1230initTargetOptions(Diags, Conf.Options, CGOpts, TOpts, LOpts, HeaderOpts);1231Conf.SampleProfile = std::move(SampleProfile);1232Conf.PTO.LoopUnrolling = CGOpts.UnrollLoops;1233// For historical reasons, loop interleaving is set to mirror setting for loop1234// unrolling.1235Conf.PTO.LoopInterleaving = CGOpts.UnrollLoops;1236Conf.PTO.LoopVectorization = CGOpts.VectorizeLoop;1237Conf.PTO.SLPVectorization = CGOpts.VectorizeSLP;1238// Only enable CGProfilePass when using integrated assembler, since1239// non-integrated assemblers don't recognize .cgprofile section.1240Conf.PTO.CallGraphProfile = !CGOpts.DisableIntegratedAS;12411242// Context sensitive profile.1243if (CGOpts.hasProfileCSIRInstr()) {1244Conf.RunCSIRInstr = true;1245Conf.CSIRProfile = std::move(CGOpts.InstrProfileOutput);1246} else if (CGOpts.hasProfileCSIRUse()) {1247Conf.RunCSIRInstr = false;1248Conf.CSIRProfile = std::move(CGOpts.ProfileInstrumentUsePath);1249}12501251Conf.ProfileRemapping = std::move(ProfileRemapping);1252Conf.DebugPassManager = CGOpts.DebugPassManager;1253Conf.VerifyEach = CGOpts.VerifyEach;1254Conf.RemarksWithHotness = CGOpts.DiagnosticsWithHotness;1255Conf.RemarksFilename = CGOpts.OptRecordFile;1256Conf.RemarksPasses = CGOpts.OptRecordPasses;1257Conf.RemarksFormat = CGOpts.OptRecordFormat;1258Conf.SplitDwarfFile = CGOpts.SplitDwarfFile;1259Conf.SplitDwarfOutput = CGOpts.SplitDwarfOutput;1260switch (Action) {1261case Backend_EmitNothing:1262Conf.PreCodeGenModuleHook = [](size_t Task, const llvm::Module &Mod) {1263return false;1264};1265break;1266case Backend_EmitLL:1267Conf.PreCodeGenModuleHook = [&](size_t Task, const llvm::Module &Mod) {1268M->print(*OS, nullptr, CGOpts.EmitLLVMUseLists);1269return false;1270};1271break;1272case Backend_EmitBC:1273Conf.PreCodeGenModuleHook = [&](size_t Task, const llvm::Module &Mod) {1274WriteBitcodeToFile(*M, *OS, CGOpts.EmitLLVMUseLists);1275return false;1276};1277break;1278default:1279Conf.CGFileType = getCodeGenFileType(Action);1280break;1281}1282if (Error E =1283thinBackend(Conf, -1, AddStream, *M, *CombinedIndex, ImportList,1284ModuleToDefinedGVSummaries[M->getModuleIdentifier()],1285/* ModuleMap */ nullptr, CGOpts.CmdArgs)) {1286handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {1287errs() << "Error running ThinLTO backend: " << EIB.message() << '\n';1288});1289}1290}12911292void clang::EmitBackendOutput(1293DiagnosticsEngine &Diags, const HeaderSearchOptions &HeaderOpts,1294const CodeGenOptions &CGOpts, const clang::TargetOptions &TOpts,1295const LangOptions &LOpts, StringRef TDesc, llvm::Module *M,1296BackendAction Action, IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,1297std::unique_ptr<raw_pwrite_stream> OS, BackendConsumer *BC) {12981299llvm::TimeTraceScope TimeScope("Backend");13001301std::unique_ptr<llvm::Module> EmptyModule;1302if (!CGOpts.ThinLTOIndexFile.empty()) {1303// If we are performing a ThinLTO importing compile, load the function index1304// into memory and pass it into runThinLTOBackend, which will run the1305// function importer and invoke LTO passes.1306std::unique_ptr<ModuleSummaryIndex> CombinedIndex;1307if (Error E = llvm::getModuleSummaryIndexForFile(1308CGOpts.ThinLTOIndexFile,1309/*IgnoreEmptyThinLTOIndexFile*/ true)1310.moveInto(CombinedIndex)) {1311logAllUnhandledErrors(std::move(E), errs(),1312"Error loading index file '" +1313CGOpts.ThinLTOIndexFile + "': ");1314return;1315}13161317// A null CombinedIndex means we should skip ThinLTO compilation1318// (LLVM will optionally ignore empty index files, returning null instead1319// of an error).1320if (CombinedIndex) {1321if (!CombinedIndex->skipModuleByDistributedBackend()) {1322runThinLTOBackend(Diags, CombinedIndex.get(), M, HeaderOpts, CGOpts,1323TOpts, LOpts, std::move(OS), CGOpts.SampleProfileFile,1324CGOpts.ProfileRemappingFile, Action);1325return;1326}1327// Distributed indexing detected that nothing from the module is needed1328// for the final linking. So we can skip the compilation. We sill need to1329// output an empty object file to make sure that a linker does not fail1330// trying to read it. Also for some features, like CFI, we must skip1331// the compilation as CombinedIndex does not contain all required1332// information.1333EmptyModule = std::make_unique<llvm::Module>("empty", M->getContext());1334EmptyModule->setTargetTriple(M->getTargetTriple());1335M = EmptyModule.get();1336}1337}13381339EmitAssemblyHelper AsmHelper(Diags, HeaderOpts, CGOpts, TOpts, LOpts, M, VFS);1340AsmHelper.EmitAssembly(Action, std::move(OS), BC);13411342// Verify clang's TargetInfo DataLayout against the LLVM TargetMachine's1343// DataLayout.1344if (AsmHelper.TM) {1345std::string DLDesc = M->getDataLayout().getStringRepresentation();1346if (DLDesc != TDesc) {1347unsigned DiagID = Diags.getCustomDiagID(1348DiagnosticsEngine::Error, "backend data layout '%0' does not match "1349"expected target description '%1'");1350Diags.Report(DiagID) << DLDesc << TDesc;1351}1352}1353}13541355// With -fembed-bitcode, save a copy of the llvm IR as data in the1356// __LLVM,__bitcode section.1357void clang::EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts,1358llvm::MemoryBufferRef Buf) {1359if (CGOpts.getEmbedBitcode() == CodeGenOptions::Embed_Off)1360return;1361llvm::embedBitcodeInModule(1362*M, Buf, CGOpts.getEmbedBitcode() != CodeGenOptions::Embed_Marker,1363CGOpts.getEmbedBitcode() != CodeGenOptions::Embed_Bitcode,1364CGOpts.CmdArgs);1365}13661367void clang::EmbedObject(llvm::Module *M, const CodeGenOptions &CGOpts,1368DiagnosticsEngine &Diags) {1369if (CGOpts.OffloadObjects.empty())1370return;13711372for (StringRef OffloadObject : CGOpts.OffloadObjects) {1373llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ObjectOrErr =1374llvm::MemoryBuffer::getFileOrSTDIN(OffloadObject);1375if (ObjectOrErr.getError()) {1376auto DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,1377"could not open '%0' for embedding");1378Diags.Report(DiagID) << OffloadObject;1379return;1380}13811382llvm::embedBufferInModule(*M, **ObjectOrErr, ".llvm.offloading",1383Align(object::OffloadBinary::getAlignment()));1384}1385}138613871388