Skip to content

[flang] Add -mlink-builtin-bitcode option to fc1 #94763

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 17, 2024
Merged
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
9 changes: 6 additions & 3 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -7028,6 +7028,12 @@ def as_secure_log_file : Separate<["-"], "as-secure-log-file">,

} // let Visibility = [CC1Option, CC1AsOption]

let Visibility = [CC1Option, FC1Option] in {
def mlink_builtin_bitcode : Separate<["-"], "mlink-builtin-bitcode">,
HelpText<"Link and internalize needed symbols from the given bitcode file "
"before performing optimizations.">;
} // let Visibility = [CC1Option, FC1Option]

let Visibility = [CC1Option] in {

def llvm_verify_each : Flag<["-"], "llvm-verify-each">,
Expand Down Expand Up @@ -7130,9 +7136,6 @@ defm constructor_aliases : BoolMOption<"constructor-aliases",
" emitting complete constructors and destructors as aliases when possible">>;
def mlink_bitcode_file : Separate<["-"], "mlink-bitcode-file">,
HelpText<"Link the given bitcode file before performing optimizations.">;
def mlink_builtin_bitcode : Separate<["-"], "mlink-builtin-bitcode">,
HelpText<"Link and internalize needed symbols from the given bitcode file "
"before performing optimizations.">;
defm link_builtin_bitcode_postopt: BoolMOption<"link-builtin-bitcode-postopt",
CodeGenOpts<"LinkBitcodePostopt">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption], "Link builtin bitcodes after the "
Expand Down
4 changes: 4 additions & 0 deletions flang/include/flang/Frontend/CodeGenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// are offloading binaries containing device images and metadata.
std::vector<std::string> OffloadObjects;

/// List of filenames passed in using the -mlink-builtin-bitcode. These
/// are bc libraries that should be linked in and internalized;
std::vector<std::string> BuiltinBCLibs;

/// The directory where temp files are stored if specified by -save-temps
std::optional<std::string> SaveTempsDir;

Expand Down
5 changes: 4 additions & 1 deletion flang/include/flang/Frontend/FrontendActions.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,12 @@ class CodeGenAction : public FrontendAction {
std::unique_ptr<llvm::LLVMContext> llvmCtx;
std::unique_ptr<llvm::Module> llvmModule;

/// Embeds offload objects given with specified with -fembed-offload-object
/// Embeds offload objects specified with -fembed-offload-object
void embedOffloadObjects();

/// Links in BC libraries spefified with -mlink-builtin-bitcode
void linkBuiltinBCLibs();

/// Runs pass pipeline to lower HLFIR into FIR
void lowerHLFIRToFIR();

Expand Down
5 changes: 5 additions & 0 deletions flang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,11 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
if (auto *a = args.getLastArg(clang::driver::options::OPT_save_temps_EQ))
opts.SaveTempsDir = a->getValue();

// -mlink-builtin-bitcode
for (auto *a :
args.filtered(clang::driver::options::OPT_mlink_builtin_bitcode))
opts.BuiltinBCLibs.push_back(a->getValue());

// -mrelocation-model option.
if (const llvm::opt::Arg *a =
args.getLastArg(clang::driver::options::OPT_mrelocation_model)) {
Expand Down
56 changes: 56 additions & 0 deletions flang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
#include "mlir/Target/LLVMIR/ModuleTranslation.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticFrontend.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
Expand All @@ -54,6 +56,7 @@
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Object/OffloadBinary.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"
Expand All @@ -68,6 +71,7 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/TargetParser/RISCVISAInfo.h"
#include "llvm/TargetParser/RISCVTargetParser.h"
#include "llvm/Transforms/IPO/Internalize.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include <memory>
#include <system_error>
Expand Down Expand Up @@ -1146,6 +1150,54 @@ void CodeGenAction::embedOffloadObjects() {
}
}

void CodeGenAction::linkBuiltinBCLibs() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a fairly large chunk of code - does it come from Clang in some way - if so, is it possible to have one common function shared, rather than two copies?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does come from clang but it is distributed across a few classes with a lot more options, so there was not simple way to simply re-use the code. I don't know if we want to bring in all that code since it would add a lot more complexity, and I don't know if we need this in the future or not.

auto options = clang::FileSystemOptions();
clang::FileManager fileManager(options);
CompilerInstance &ci = this->getInstance();
const auto &cgOpts = ci.getInvocation().getCodeGenOpts();

std::vector<std::unique_ptr<llvm::Module>> modules;

// Load LLVM modules
for (llvm::StringRef bcLib : cgOpts.BuiltinBCLibs) {
auto BCBuf = fileManager.getBufferForFile(bcLib);
if (!BCBuf) {
auto diagID = ci.getDiagnostics().getCustomDiagID(
clang::DiagnosticsEngine::Error, "could not open '%0' for linking");
ci.getDiagnostics().Report(diagID) << bcLib;
return;
}

llvm::Expected<std::unique_ptr<llvm::Module>> ModuleOrErr =
getOwningLazyBitcodeModule(std::move(*BCBuf), *llvmCtx);
if (!ModuleOrErr) {
auto diagID = ci.getDiagnostics().getCustomDiagID(
clang::DiagnosticsEngine::Error, "error loading '%0' for linking");
ci.getDiagnostics().Report(diagID) << bcLib;
return;
}
modules.push_back(std::move(ModuleOrErr.get()));
}

// Link modules and internalize functions
for (auto &module : modules) {
bool Err;
Err = llvm::Linker::linkModules(
*llvmModule, std::move(module), llvm::Linker::Flags::LinkOnlyNeeded,
[](llvm::Module &M, const llvm::StringSet<> &GVS) {
llvm::internalizeModule(M, [&GVS](const llvm::GlobalValue &GV) {
return !GV.hasName() || (GVS.count(GV.getName()) == 0);
});
});
if (Err) {
auto diagID = ci.getDiagnostics().getCustomDiagID(
clang::DiagnosticsEngine::Error, "link error when linking '%0'");
ci.getDiagnostics().Report(diagID) << module->getSourceFileName();
return;
}
}
}

static void reportOptRecordError(llvm::Error e, clang::DiagnosticsEngine &diags,
const CodeGenOptions &codeGenOpts) {
handleAllErrors(
Expand Down Expand Up @@ -1237,6 +1289,10 @@ void CodeGenAction::executeAction() {
llvmModule->setTargetTriple(theTriple);
llvmModule->setDataLayout(targetMachine.createDataLayout());

// Link in builtin bitcode libraries
if (!codeGenOpts.BuiltinBCLibs.empty())
linkBuiltinBCLibs();

// Embed offload objects specified with -fembed-offload-object
if (!codeGenOpts.OffloadObjects.empty())
embedOffloadObjects();
Expand Down
4 changes: 4 additions & 0 deletions flang/test/Driver/Inputs/libfun.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
subroutine libfun(x)
integer :: x
end subroutine

15 changes: 15 additions & 0 deletions flang/test/Driver/mlink-builtin-bc.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
! Test -mlink-builtin-bitcode flag
! RUN: %flang -emit-llvm -c -o %t.bc %S/Inputs/libfun.f90
! RUN: %flang_fc1 -emit-llvm -o - -mlink-builtin-bitcode %t.bc %s 2>&1 | FileCheck %s

! CHECK: define internal void @libfun_

! RUN: not %flang_fc1 -emit-llvm -o - -mlink-builtin-bitcode %no-%t.bc %s 2>&1 | FileCheck %s --check-prefix=ERROR

! ERROR: error: could not open {{.*}}.bc

external libfun
parameter(i=1)
integer :: j
call libfun(j)
end program
Loading