23#include "llvm/Config/config.h" 
   58#include <system_error> 
   62  return PACKAGE_NAME 
" version " PACKAGE_VERSION;
 
 
   67    "lto-discard-value-names",
 
   68    cl::desc(
"Strip names from Value during LTO (other than GlobalValue)."),
 
   77    "lto-pass-remarks-with-hotness",
 
   78    cl::desc(
"With PGO, include profile count in optimization remarks"),
 
   83        "lto-pass-remarks-hotness-threshold",
 
   84        cl::desc(
"Minimum profile count required for an " 
   85                 "optimization remark to be output." 
   86                 " Use 'auto' to apply the threshold from profile summary."),
 
   91                    cl::desc(
"Output filename for pass remarks"),
 
   96                  cl::desc(
"Only record optimization remarks from passes whose " 
   97                           "names match the given regular expression"),
 
  101    "lto-pass-remarks-format",
 
  102    cl::desc(
"The format used for serializing remarks (default: YAML)"),
 
  110    "lto-aix-system-assembler",
 
  111    cl::desc(
"Path to a system assembler, picked up on AIX only"),
 
  116                    cl::desc(
"Perform context sensitive PGO instrumentation"));
 
  120                   cl::desc(
"Context sensitive profile file path"));
 
  124    : Context(Context), MergedModule(new 
Module(
"ld-temp.o", Context)),
 
  125      TheLinker(new 
Linker(*MergedModule)) {
 
  127  Context.enableDebugTypeODRUniquing();
 
  129  Config.CodeModel = std::nullopt;
 
 
  138  AsmUndefinedRefs.insert_range(
Mod->getAsmUndefinedRefs());
 
 
  142  assert(&
Mod->getModule().getContext() == &Context &&
 
  143         "Expected module in same context");
 
  145  bool ret = TheLinker->linkInModule(
Mod->takeModule());
 
  149  HasVerifiedInput = 
false;
 
 
  155  assert(&
Mod->getModule().getContext() == &Context &&
 
  156         "Expected module in same context");
 
  158  AsmUndefinedRefs.clear();
 
  160  MergedModule = 
Mod->takeModule();
 
  161  TheLinker = std::make_unique<Linker>(*MergedModule);
 
  165  HasVerifiedInput = 
false;
 
 
  175    EmitDwarfDebugInfo = 
false;
 
  179    EmitDwarfDebugInfo = 
true;
 
 
  186  Config.OptLevel = Level;
 
  187  Config.PTO.LoopVectorization = Config.OptLevel > 1;
 
  188  Config.PTO.SLPVectorization = Config.OptLevel > 1;
 
  189  std::optional<CodeGenOptLevel> CGOptLevelOrNone =
 
  191  assert(CGOptLevelOrNone && 
"Unknown optimization level!");
 
  192  Config.CGOptLevel = *CGOptLevelOrNone;
 
 
  196  if (!determineTarget())
 
  200  verifyMergedModuleOnce();
 
  203  applyScopeRestrictions();
 
  209    std::string ErrMsg = 
"could not open bitcode file for writing: ";
 
  210    ErrMsg += Path.str() + 
": " + EC.message();
 
  220    std::string ErrMsg = 
"could not write bitcode file: ";
 
  221    ErrMsg += Path.str() + 
": " + Out.
os().
error().message();
 
 
  231bool LTOCodeGenerator::useAIXSystemAssembler() {
 
  232  const auto &
Triple = TargetMach->getTargetTriple();
 
  237  assert(useAIXSystemAssembler() &&
 
  238         "Runing AIX system assembler when integrated assembler is available!");
 
  246          "Cannot find the assembler specified by lto-aix-system-assembler");
 
  252  std::string LDR_CNTRL_var = 
"LDR_CNTRL=MAXDATA32=0xA0000000@DSA";
 
  254    LDR_CNTRL_var += (
"@" + *
V);
 
  257  const auto &Triple = TargetMach->getTargetTriple();
 
  258  const char *Arch = Triple.isArch64Bit() ? 
"-a64" : 
"-a32";
 
  260  ObjectFileName[ObjectFileName.size() - 1] = 
'o';
 
  262      "/bin/env",     LDR_CNTRL_var,
 
  272    emitError(
"LTO assembler exited abnormally");
 
  276    emitError(
"Unable to invoke LTO assembler");
 
  280    emitError(
"LTO assembler invocation returned non-zero");
 
  293bool LTOCodeGenerator::compileOptimizedToFile(
const char **Name) {
 
  294  if (useAIXSystemAssembler())
 
  302          const Twine &ModuleName) -> std::unique_ptr<CachedFileStream> {
 
  310      emitError(
EC.message());
 
  312    return std::make_unique<CachedFileStream>(
 
  313        std::make_unique<llvm::raw_fd_ostream>(FD, 
true));
 
  330  if (useAIXSystemAssembler())
 
  331    if (!runAIXSystemAssembler(Filename))
 
  334  NativeObjectPath = 
Filename.c_str();
 
  335  *
Name = NativeObjectPath.c_str();
 
  339std::unique_ptr<MemoryBuffer>
 
  342  if (!compileOptimizedToFile(&
name))
 
  348  if (std::error_code EC = BufferOrErr.
getError()) {
 
  349    emitError(EC.message());
 
  357  return std::move(*BufferOrErr);
 
 
  364  return compileOptimizedToFile(Name);
 
 
  374bool LTOCodeGenerator::determineTarget() {
 
  378  if (MergedModule->getTargetTriple().empty())
 
  392  Features.getDefaultSubtargetFeatures(MergedModule->getTargetTriple());
 
  393  FeatureStr = Features.getString();
 
  394  if (Config.
CPU.empty())
 
  403  assert(TargetMach && 
"Unable to create target machine");
 
  408std::unique_ptr<TargetMachine> LTOCodeGenerator::createTargetMachine() {
 
  409  assert(MArch && 
"MArch is not set!");
 
  410  return std::unique_ptr<TargetMachine>(MArch->createTargetMachine(
 
  411      MergedModule->getTargetTriple(), Config.CPU, FeatureStr, Config.Options,
 
  412      Config.RelocModel, std::nullopt, Config.CGOptLevel));
 
  418void LTOCodeGenerator::preserveDiscardableGVs(
 
  421  std::vector<GlobalValue *> 
Used;
 
  422  auto mayPreserveGlobal = [&](GlobalValue &GV) {
 
  423    if (!GV.isDiscardableIfUnused() || GV.isDeclaration() ||
 
  426    if (GV.hasAvailableExternallyLinkage())
 
  428          (Twine(
"Linker asked to preserve available_externally global: '") +
 
  429           GV.getName() + 
"'").str());
 
  430    if (GV.hasInternalLinkage())
 
  431      return emitWarning((Twine(
"Linker asked to preserve internal global: '") +
 
  432                   GV.getName() + 
"'").str());
 
  435  for (
auto &GV : TheModule)
 
  436    mayPreserveGlobal(GV);
 
  437  for (
auto &GV : TheModule.globals())
 
  438    mayPreserveGlobal(GV);
 
  439  for (
auto &GV : TheModule.aliases())
 
  440    mayPreserveGlobal(GV);
 
  448void LTOCodeGenerator::applyScopeRestrictions() {
 
  449  if (ScopeRestrictionsDone)
 
  455  SmallString<64> MangledName;
 
  465    MangledName.
reserve(GV.getName().size() + 1);
 
  467    return MustPreserveSymbols.count(MangledName);
 
  473  if (!ShouldInternalize)
 
  476  if (ShouldRestoreGlobalsLinkage) {
 
  481      if (!GV.hasAvailableExternallyLinkage() && !GV.hasLocalLinkage() &&
 
  483        ExternalSymbols.insert(std::make_pair(GV.getName(), GV.getLinkage()));
 
  485    for (
auto &GV : *MergedModule)
 
  487    for (
auto &GV : MergedModule->globals())
 
  489    for (
auto &GV : MergedModule->aliases())
 
  499  ScopeRestrictionsDone = 
true;
 
  503void LTOCodeGenerator::restoreLinkageForExternals() {
 
  504  if (!ShouldInternalize || !ShouldRestoreGlobalsLinkage)
 
  507  assert(ScopeRestrictionsDone &&
 
  508         "Cannot externalize without internalization!");
 
  510  if (ExternalSymbols.empty())
 
  514    if (!GV.hasLocalLinkage() || !GV.hasName())
 
  517    auto I = ExternalSymbols.find(GV.getName());
 
  518    if (
I == ExternalSymbols.end())
 
  521    GV.setLinkage(
I->second);
 
  529void LTOCodeGenerator::verifyMergedModuleOnce() {
 
  531  if (HasVerifiedInput)
 
  533  HasVerifiedInput = 
true;
 
  535  bool BrokenDebugInfo = 
false;
 
  538  if (BrokenDebugInfo) {
 
  539    emitWarning(
"Invalid debug info found, debug info will be stripped");
 
  544void LTOCodeGenerator::finishOptimizationRemarks() {
 
  545  if (DiagnosticOutputFile) {
 
  546    DiagnosticOutputFile->keep();
 
  548    DiagnosticOutputFile.finalize();
 
  549    DiagnosticOutputFile->os().flush();
 
  555  if (!this->determineTarget())
 
  564  if (!DiagFileOrErr) {
 
  565    errs() << 
"Error: " << 
toString(DiagFileOrErr.takeError()) << 
"\n";
 
  568  DiagnosticOutputFile = std::move(*DiagFileOrErr);
 
  572  if (!StatsFileOrErr) {
 
  573    errs() << 
"Error: " << 
toString(StatsFileOrErr.takeError()) << 
"\n";
 
  576  StatsFile = std::move(StatsFileOrErr.get());
 
  595  verifyMergedModuleOnce();
 
  598  this->applyScopeRestrictions();
 
  601  MergedModule->setDataLayout(TargetMach->createDataLayout());
 
  603  if (!SaveIRBeforeOptPath.empty()) {
 
  608                         " to save optimized bitcode\n");
 
  614  TargetMach = createTargetMachine();
 
  615  if (!
opt(Config, TargetMach.get(), 0, *MergedModule, 
false,
 
  616           &CombinedIndex, 
nullptr,
 
  617            std::vector<uint8_t>())) {
 
  618    emitError(
"LTO middle-end optimizations failed");
 
 
  626                                        unsigned ParallelismLevel) {
 
  627  if (!this->determineTarget())
 
  632  verifyMergedModuleOnce();
 
  636  restoreLinkageForExternals();
 
  640  Config.CodeGenOnly = 
true;
 
  641  Error Err = backend(Config, AddStream, ParallelismLevel, *MergedModule,
 
  643  assert(!Err && 
"unexpected code-generation failure");
 
  655  finishOptimizationRemarks();
 
 
  662    CodegenOptions.push_back(Option.str());
 
 
  666  if (!CodegenOptions.empty())
 
 
  673    std::vector<const char *> CodegenArgv(1, 
"libLLVMLTO");
 
  674    for (std::string &Arg : 
Options)
 
  675      CodegenArgv.push_back(Arg.c_str());
 
 
  698  std::string MsgStorage;
 
  706  assert(DiagHandler && 
"Invalid diagnostic handler");
 
  707  (*DiagHandler)(Severity, MsgStorage.c_str(), DiagContext);
 
 
  714      : CodeGenerator(CodeGenPtr) {}
 
  725  this->DiagHandler = DiagHandler;
 
  726  this->DiagContext = Ctxt;
 
  728    return Context.setDiagnosticHandler(
nullptr);
 
  731  Context.setDiagnosticHandler(std::make_unique<LTODiagnosticHandler>(
this),
 
 
  746void LTOCodeGenerator::emitError(
const std::string &ErrMsg) {
 
  748    (*DiagHandler)(
LTO_DS_ERROR, ErrMsg.c_str(), DiagContext);
 
  750    Context.diagnose(LTODiagnosticInfo(ErrMsg));
 
  753void LTOCodeGenerator::emitWarning(
const std::string &ErrMsg) {
 
  757    Context.diagnose(LTODiagnosticInfo(ErrMsg, 
DS_Warning));
 
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool mustPreserveGV(const GlobalValue &GV)
Predicate for Internalize pass.
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
#define LLVM_LIFETIME_BOUND
static ManagedStatic< cl::opt< bool, true >, CreateDebug > Debug
This file implements a simple parser to decode commandline option for remarks hotness threshold that ...
Module.h This file contains the declarations for the Module class.
static std::unique_ptr< TargetMachine > createTargetMachine(Function *F, CodeGenOptLevel OptLevel)
Create the TargetMachine object to query the backend for optimization preferences.
This header defines classes/functions to handle pass execution timing information with interfaces for...
Provides a library for accessing information about this process and other processes on the operating ...
static void externalize(GlobalValue *GV)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
This is the base abstract class for diagnostic reporting in the backend.
DiagnosticSeverity getSeverity() const
virtual void print(DiagnosticPrinter &DP) const =0
Print using the given DP a user-friendly message.
Basic diagnostic printer that uses an underlying raw_ostream.
Interface for custom diagnostic printing.
Represents either an error or a value T.
std::error_code getError() const
Lightweight error class with error context and mandatory checking.
This is an important class for using LLVM in a threaded context.
This class provides the core functionality of linking in LLVM.
LLVM_ABI void getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV, bool CannotUsePrivateLabel) const
Print the appropriate prefix and the specified global variable's name.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
Class to hold module path string table and global value map, and encapsulate methods for operating on...
A Module instance is used to store all the information related to an LLVM module.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void reserve(size_type N)
StringRef - Represent a constant reference to a string, i.e.
Manages the enabling and disabling of subtarget specific features.
unsigned DataSections
Emit data into separate sections.
unsigned DisableIntegratedAS
Disable the integrated assembler.
Triple - Helper class for working with autoconf configuration names.
bool isOSAIX() const
Tests whether the OS is AIX.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
An efficient, type-erasing, non-owning reference to a callable.
A raw_ostream that writes to a file descriptor.
bool has_error() const
Return the value of the flag in this raw_fd_ostream indicating whether an output error has been encou...
std::error_code error() const
void close()
Manually flush the stream and close the file.
void clear_error()
Set the flag read by has_error() to false.
A raw_ostream that writes to an std::string.
static LLVM_ABI std::optional< std::string > GetEnv(StringRef name)
lto_codegen_diagnostic_severity_t
Diagnostic severity.
void(* lto_diagnostic_handler_t)(lto_codegen_diagnostic_severity_t severity, const char *diag, void *ctxt)
Diagnostic handler type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
std::optional< CodeGenOptLevel > getLevel(int OL)
Get the Level identified by the integer OL.
initializer< Ty > init(const Ty &Val)
LLVM_ABI bool ParseCommandLineOptions(int argc, const char *const *argv, StringRef Overview="", raw_ostream *Errs=nullptr, vfs::FileSystem *VFS=nullptr, const char *EnvVar=nullptr, bool LongOptionsUseDoubleDash=false)
LLVM_ABI std::optional< bool > getExplicitDataSections()
LLVM_ABI StringLiteral getThinLTODefaultCPU(const Triple &TheTriple)
LLVM_ABI Expected< std::unique_ptr< ToolOutputFile > > setupStatsFile(StringRef StatsFilename)
Setups the output file for saving statistics.
LLVM_ABI Expected< LLVMRemarkFileHandle > setupLLVMOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, StringRef RemarksFormat, bool RemarksWithHotness, std::optional< uint64_t > RemarksHotnessThreshold=0, int Count=-1)
Setup optimization remarks.
LLVM_ABI std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
LLVM_ABI std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)
Collapse all .
LLVM_ABI std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, SmallVectorImpl< char > &ResultPath, OpenFlags Flags=OF_None)
Create a file in the system temporary directory.
LLVM_ABI std::string getDefaultTargetTriple()
getDefaultTargetTriple() - Return the default target triple the compiler has been configured to produ...
LLVM_ABI int ExecuteAndWait(StringRef Program, ArrayRef< StringRef > Args, std::optional< ArrayRef< StringRef > > Env=std::nullopt, ArrayRef< std::optional< StringRef > > Redirects={}, unsigned SecondsToWait=0, unsigned MemoryLimit=0, std::string *ErrMsg=nullptr, bool *ExecutionFailed=nullptr, std::optional< ProcessStatistics > *ProcStat=nullptr, BitVector *AffinityMask=nullptr)
This function executes the program using the arguments provided.
This is an optimization pass for GlobalISel generic memory operations.
cl::opt< std::string > RemarksFormat("lto-pass-remarks-format", cl::desc("The format used for serializing remarks (default: YAML)"), cl::value_desc("format"), cl::init("yaml"))
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
cl::opt< bool > LTODiscardValueNames("lto-discard-value-names", cl::desc("Strip names from Value during LTO (other than GlobalValue)."), cl::init(false), cl::Hidden)
LLVM_ABI void WriteBitcodeToFile(const Module &M, raw_ostream &Out, bool ShouldPreserveUseListOrder=false, const ModuleSummaryIndex *Index=nullptr, bool GenerateHash=false, ModuleHash *ModHash=nullptr)
Write the specified module to the specified raw output stream.
bool internalizeModule(Module &TheModule, std::function< bool(const GlobalValue &)> MustPreserveGV)
Helper function to internalize functions and variables in a Module.
static cl::opt< std::string > LTOCSIRProfile("cs-profile-path", cl::desc("Context sensitive profile file path"))
cl::opt< std::string > RemarksPasses("lto-pass-remarks-filter", cl::desc("Only record optimization remarks from passes whose " "names match the given regular expression"), cl::value_desc("regex"))
void updateCompilerUsed(Module &TheModule, const TargetMachine &TM, const StringSet<> &AsmUndefinedRefs)
Find all globals in TheModule that are referenced in AsmUndefinedRefs, as well as the user-supplied f...
LLVM_ABI void reportAndResetTimings(raw_ostream *OutStream=nullptr)
If -time-passes has been specified, report the timings immediately and then reset the timers to zero.
static cl::opt< std::string > AIXSystemAssemblerPath("lto-aix-system-assembler", cl::desc("Path to a system assembler, picked up on AIX only"), cl::value_desc("path"))
LLVM_ABI void updatePublicTypeTestCalls(Module &M, bool WholeProgramVisibilityEnabledInLTO)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI bool AreStatisticsEnabled()
Check if statistics are enabled.
cl::opt< bool > RemarksWithHotness("lto-pass-remarks-with-hotness", cl::desc("With PGO, include profile count in optimization remarks"), cl::Hidden)
cl::opt< std::string > RemarksFilename("lto-pass-remarks-output", cl::desc("Output filename for pass remarks"), cl::value_desc("filename"))
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI void parseCommandLineOptions(std::vector< std::string > &Options)
A convenience function that calls cl::ParseCommandLineOptions on the given set of options.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI bool StripDebugInfo(Module &M)
Strip debug info in the module if it exists.
@ Mod
The access may modify the value stored in memory.
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
LLVM_ABI void PrintStatistics()
Print statistics to the file returned by CreateInfoOutputFile().
LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
DiagnosticSeverity
Defines the different supported severity of a diagnostic.
cl::opt< std::optional< uint64_t >, false, remarks::HotnessThresholdParser > RemarksHotnessThreshold("lto-pass-remarks-hotness-threshold", cl::desc("Minimum profile count required for an " "optimization remark to be output." " Use 'auto' to apply the threshold from profile summary."), cl::value_desc("uint or 'auto'"), cl::init(0), cl::Hidden)
static cl::opt< std::string > LTOStatsFile("lto-stats-file", cl::desc("Save statistics to the specified file"), cl::Hidden)
std::function< Expected< std::unique_ptr< CachedFileStream > >( unsigned Task, const Twine &ModuleName)> AddStreamFn
This type defines the callback to add a file that is generated on the fly.
LLVM_ABI void PrintStatisticsJSON(raw_ostream &OS)
Print statistics in JSON format.
static cl::opt< bool > LTORunCSIRInstr("cs-profile-generate", cl::desc("Perform context sensitive PGO instrumentation"))
LLVM_ABI void updateVCallVisibilityInModule(Module &M, bool WholeProgramVisibilityEnabledInLTO, const DenseSet< GlobalValue::GUID > &DynamicExportSymbols, bool ValidateAllVtablesHaveTypeInfos, function_ref< bool(StringRef)> IsVisibleToRegularObj)
If whole program visibility asserted, then upgrade all public vcall visibility metadata on vtable def...
LLVM_ABI bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
This is the base class for diagnostic handling in LLVM.
C++ class which implements the opaque lto_code_gen_t type.
LLVM_ABI bool optimize()
Optimizes the merged module.
LLVM_ABI std::unique_ptr< MemoryBuffer > compile()
As with compile_to_file(), this function compiles the merged module into single output file.
LLVM_ABI void setModule(std::unique_ptr< LTOModule > M)
Set the destination module.
LLVM_ABI bool compile_to_file(const char **Name)
Compile the merged module into a single output file; the path to output file is returned to the calle...
LLVM_ABI void parseCodeGenDebugOptions()
Parse the options set in setCodeGenDebugOptions.
LLVM_ABI void setOptLevel(unsigned OptLevel)
LLVM_ABI void setAsmUndefinedRefs(struct LTOModule *)
LLVM_ABI void setDiagnosticHandler(lto_diagnostic_handler_t, void *)
void setFileType(CodeGenFileType FT)
Set the file type to be emitted (assembly or object code).
LLVM_ABI void setTargetOptions(const TargetOptions &Options)
LLVM_ABI void setCodeGenDebugOptions(ArrayRef< StringRef > Opts)
Pass options to the driver and optimization passes.
LLVM_ABI LTOCodeGenerator(LLVMContext &Context)
LLVM_ABI std::unique_ptr< MemoryBuffer > compileOptimized()
Compiles the merged optimized module into a single output file.
LLVM_ABI bool addModule(struct LTOModule *)
Merge given module.
LLVM_ABI void setDebugInfo(lto_debug_model)
LLVM_ABI ~LTOCodeGenerator()
LLVM_ABI bool writeMergedModules(StringRef Path)
Write the merged module to the file specified by the given path.
LLVM_ABI void DiagnosticHandler(const DiagnosticInfo &DI)
static LLVM_ABI const char * getVersionString()
C++ class which implements the opaque lto_module_t type.
static const Target * lookupTarget(StringRef TripleStr, std::string &Error)
lookupTarget - Lookup a target based on a target triple.
std::vector< std::string > MAttrs