Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions include/eld/Config/GeneralOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,15 @@ class GeneralOptions {
return UnparsedLTOOptions;
}

const std::optional<std::string> &getLTOObjPath() const { return LTOObjPath; }
void setLTOObjPath(const std::string &V) { LTOObjPath = V; }

void setThinLTOJobs(llvm::StringRef V) { ThinLTOJobs = V; }
llvm::StringRef getThinLTOJobs() const { return ThinLTOJobs; }

void setLTOPartitions(unsigned V) { LTOPartitions = V; }
unsigned getLTOPartitions() const { return LTOPartitions; }

void getSymbolsFromFile(llvm::StringRef Filename, std::vector<std::string> &);

void setCopyFarCallsFromFile(std::string File) {
Expand Down Expand Up @@ -1214,9 +1223,12 @@ class GeneralOptions {
bool Savetemps = false; // -save-temps
std::optional<std::string> SaveTempsDir; // -save-temps=
bool Rosegment = false; // merge read only with readonly/execute segments.
std::optional<std::string> LTOObjPath; // --lto-obj-path=
std::vector<std::string>
UnparsedLTOOptions; // Unparsed -flto-options, to pass to plugin.
uint32_t LTOOptions = 0; // -flto-options
llvm::StringRef ThinLTOJobs; // --thinlto-jobs=
unsigned LTOPartitions = 1; // --lto-partitions=
bool Verify = true; // Linker verifies output file.
bool Colormap = false; // Map file with color.
bool EnableThreads = true; // threads enabled ?
Expand Down
6 changes: 6 additions & 0 deletions include/eld/Driver/GnuLdDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ class DLL_A_EXPORT GnuLdDriver {
getAllArgs(const std::vector<const char *> &allArgs,
const std::vector<llvm::StringRef> &ELDFlagsArgs) const;

bool isRunLTOOnly() const { return m_RunLTOOnly; }

protected:
int getInteger(llvm::opt::InputArgList &Args, unsigned Key,
int Default) const;
Expand Down Expand Up @@ -191,6 +193,10 @@ class DLL_A_EXPORT GnuLdDriver {
DriverFlavor m_DriverFlavor;
std::vector<std::string> m_SupportedTargets;
std::string LinkerProgramName;

// In LTO, only invoke compiler to generate the output file, but do not link
// it. This option is used by --lto-emit-llvm and --lto-emit-asm options.
bool m_RunLTOOnly = false;
};

#endif
49 changes: 49 additions & 0 deletions include/eld/Driver/GnuLinkerOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,9 @@ defm save_temps_EQ : smDashOnlyEq<"save-temps", "save_temps_EQ",
"Save the temporary files produced by LTO">,
MetaVarName<"<filename>">,
Group<grp_ltooptions>;
def : F<"plugin-opt=save-temps">,
Alias<save_temps>,
HelpText<"Alias for --save-temps">;
defm exclude_lto_filelist
: smDashWithOpt<"exclude-lto-filelist", "exclude_lto_filelist",
"Specify a list of files that are to be disregarded while "
Expand All @@ -1087,11 +1090,51 @@ defm include_lto_filelist
"be used for LTO. This has no effect if -flto switch is used">,
MetaVarName<"<list_of_files>">,
Group<grp_ltooptions>;

def lto_cs_profile_generate
: FF<"lto-cs-profile-generate">,
HelpText<"Perform context sensitive PGO instrumentation">;
def lto_cs_profile_file : JJ<"lto-cs-profile-file=">,
HelpText<"Context sensitive profile file path">;

def : F<"plugin-opt=cs-profile-generate">,
Alias<lto_cs_profile_generate>,
HelpText<"Alias for --lto-cs-profile-generate">;
def : J<"plugin-opt=cs-profile-path=">,
Alias<lto_cs_profile_file>,
HelpText<"Alias for --lto-cs-profile-file">;

def disable_verify : F<"disable-verify">;
def : F<"plugin-opt=disable-verify">,
Alias<disable_verify>,
HelpText<"Alias for --disable-verify">;

defm dwodir
: smDash<"dwodir", "dwodir",
"Directory to save .dwo files when split DWARF is used in LTO">,
Group<grp_ltooptions>;

def lto_obj_path_eq : JJ<"lto-obj-path=">;
def : J<"plugin-opt=obj-path=">,
Alias<lto_obj_path_eq>,
HelpText<"Alias for --lto-obj-path=">;

def lto_emit_asm : FF<"lto-emit-asm">, HelpText<"Emit assembly code">;
def plugin_opt_emit_asm : F<"plugin-opt=emit-asm">,
Alias<lto_emit_asm>,
HelpText<"Alias for --lto-emit-asm">;

def lto_emit_llvm : FF<"lto-emit-llvm">, HelpText<"Emit LLVM-IR bitcode">;
def plugin_opt_emit_llvm : F<"plugin-opt=emit-llvm">,
Alias<lto_emit_llvm>,
HelpText<"Alias for --lto-emit-llvm">;

def thinlto_jobs_eq : JJ<"thinlto-jobs=">,
HelpText<"Number of ThinLTO jobs. Default to --threads=">;
def : J<"plugin-opt=jobs=">,
Alias<thinlto_jobs_eq>,
HelpText<"Alias for --thinlto-jobs=">;

def lto_O : JJ<"lto-O">,
MetaVarName<"<opt-level>">,
HelpText<"Optimization level for LTO">;
Expand All @@ -1107,6 +1150,12 @@ defm plugin_opt_sample_profile
"Alias for -lto-sample-profile=">,
Group<grp_ltooptions>;

def lto_partitions : JJ<"lto-partitions=">,
HelpText<"Number of LTO codegen partitions">;
def : J<"plugin-opt=lto-partitions=">,
Alias<lto_partitions>,
HelpText<"Alias for --lto-partitions">;

def lto_debug_pass_manager : FF<"lto-debug-pass-manager">,
HelpText<"Debug new pass manager">,
Group<grp_ltooptions>;
Expand Down
11 changes: 7 additions & 4 deletions include/eld/Object/ObjectLinker.h
Original file line number Diff line number Diff line change
Expand Up @@ -365,13 +365,14 @@ class ObjectLinker {
}

private:
std::unique_ptr<llvm::lto::LTO> ltoInit(llvm::lto::Config Conf);
std::unique_ptr<llvm::lto::LTO> ltoInit(llvm::lto::Config Conf,
bool CompileToAssembly);

bool
finalizeLtoSymbolResolution(llvm::lto::LTO &LTO,
const std::vector<BitcodeFile *> &BitCodeFiles);

bool doLto(llvm::lto::LTO &LTO);
bool doLto(llvm::lto::LTO &LTO, bool CompileToAssembly);

/// writeRelocationResult - helper function of syncRelocationResult, write
/// relocation target data to output
Expand Down Expand Up @@ -415,8 +416,10 @@ class ObjectLinker {

std::string getLTOTempPrefix() const;

std::unique_ptr<llvm::raw_fd_ostream> createLTOOutputFile() const;

llvm::Expected<std::unique_ptr<llvm::raw_fd_ostream>>
createLTOTempFile(size_t Task, const std::string &Suffix,
createLTOTempFile(size_t Number, bool Asm,
llvm::SmallString<256> &FileName) const;

/// Adds input files to outputTar if --reproduce option is used
Expand Down Expand Up @@ -497,7 +500,7 @@ class ObjectLinker {

bool MTraceLTO = false;

std::string MLtoTempPrefix;
std::optional<std::string> MLtoTempPrefix;

// Paths of all generated LTO objects
std::vector<std::string> LtoObjects;
Expand Down
3 changes: 3 additions & 0 deletions lib/Core/Linker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,9 @@ bool Linker::normalize() {
if (!ObjLinker->createLTOObject())
return false;

if (Driver->isRunLTOOnly())
return true;

if (ThisModule->getPrinter()->isVerbose())
ThisConfig->raise(Diag::beginning_post_LTO_phase);
LinkerProgress->incrementAndDisplayProgress();
Expand Down
54 changes: 50 additions & 4 deletions lib/LinkerWrapper/GnuLdDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1555,15 +1555,59 @@ bool GnuLdDriver::processLTOOptions(llvm::lto::Config &Conf,
for (opt::Arg *Arg : Args.filtered(OptTable::plugin_opt_eq_minus))
LLVMOptions.push_back(std::string("-") + Arg->getValue());

if (const auto *Arg = Args.getLastArg(OptTable::lto_cs_profile_file))
Conf.CSIRProfile = Arg->getValue();

if (Args.hasArg(OptTable::lto_cs_profile_generate))
Conf.RunCSIRInstr = true;

if (const auto *Arg = Args.getLastArg(OptTable::dwodir))
Conf.DwoDir = Arg->getValue();

if (Args.hasArg(OptTable::lto_emit_llvm))
m_RunLTOOnly = true;

if (Args.hasArg(OptTable::lto_emit_asm)) {
Conf.CGFileType = CodeGenFileType::AssemblyFile;
Conf.Options.MCOptions.AsmVerbose = true;
m_RunLTOOnly = true;
}

if (const auto *Arg = Args.getLastArg(OptTable::thinlto_jobs_eq)) {
llvm::StringRef S = Arg->getValue();
if (!get_threadpool_strategy(S)) {
Config.raise(Diag::invalid_value_for_option)
<< Arg->getOption().getPrefixedName() << S;
return false;
}
Config.options().setThinLTOJobs(S);
}

if (const auto *Arg = Args.getLastArg(OptTable::lto_obj_path_eq)) {
Conf.AlwaysEmitRegularLTOObj = true;
Config.options().setLTOObjPath(Arg->getValue());
}

if (const auto *Arg = Args.getLastArg(OptTable::lto_partitions)) {
llvm::StringRef S = Arg->getValue();
unsigned Value;
if (S.getAsInteger(0, Value) || Value == 0) {
Config.raise(Diag::invalid_value_for_option)
<< Arg->getOption().getPrefixedName() << S;
return false;
}
Config.options().setLTOPartitions(Value);
}

if (const auto *Arg = Args.getLastArg(OptTable::lto_sample_profile))
Conf.SampleProfile = Arg->getValue();

if (Args.hasArg(OptTable::lto_debug_pass_manager))
Conf.DebugPassManager = true;

if (Args.hasArg(OptTable::disable_verify))
Conf.DisableVerify = true;

if (const auto *Arg = Args.getLastArg(OptTable::lto_O)) {
llvm::StringRef S = Arg->getValue();
uint64_t Value;
Expand Down Expand Up @@ -1733,12 +1777,14 @@ bool GnuLdDriver::doLink(llvm::opt::InputArgList &Args,
// llvm::errs() << "prepare: linkStatus: " << linkStatus << "\n";
if (!linkStatus || Config.options().getRecordInputFiles())
handleReproduce<T>(Args, actions, false);
if (linkStatus)
linkStatus = linker.link();
// llvm::errs() << "link: linkStatus: " << linkStatus << "\n";
if (!isRunLTOOnly()) {
if (linkStatus)
linkStatus = linker.link();
// llvm::errs() << "link: linkStatus: " << linkStatus << "\n";
linker.printLayout();
}
if (!linkStatus || Config.options().getRecordInputFiles())
handleReproduce<T>(Args, actions, true);
linker.printLayout();
linkStatus &= ThisModule->getPluginManager().callDestroyHook();
// llvm::errs() << "destroy hook: linkStatus: " << linkStatus << "\n";
linker.unloadPlugins();
Expand Down
Loading
Loading