Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -1224,7 +1224,7 @@ NegFlag>; def fembed_offload_object_EQ : Joined<["-"], "fembed-offload-object=">, - Group, Flags<[NoXarchOption, CC1Option]>, + Group, Flags<[NoXarchOption, CC1Option, FC1Option]>, HelpText<"Embed Offloading device-side binary into host object file as a section.">, MarshallingInfoStringVector>; def fembed_bitcode_EQ : Joined<["-"], "fembed-bitcode=">, Index: flang/include/flang/Frontend/CodeGenOptions.h =================================================================== --- flang/include/flang/Frontend/CodeGenOptions.h +++ flang/include/flang/Frontend/CodeGenOptions.h @@ -49,6 +49,10 @@ /// The paths to the pass plugins that were registered using -fpass-plugin. std::vector LLVMPassPlugins; + /// List of filenames passed in using the -fembed-offload-object option. These + /// are offloading binaries containing device images and metadata. + std::vector OffloadObjects; + // Define accessors/mutators for code generation options of enumeration type. #define CODEGENOPT(Name, Bits, Default) #define ENUM_CODEGENOPT(Name, Type, Bits, Default) \ Index: flang/include/flang/Frontend/FrontendActions.h =================================================================== --- flang/include/flang/Frontend/FrontendActions.h +++ flang/include/flang/Frontend/FrontendActions.h @@ -221,6 +221,9 @@ std::unique_ptr llvmCtx; std::unique_ptr llvmModule; + /// Embeds offload objects given with specified with -fembed-offload-object + void embedOffloadObjects(); + /// Generates an LLVM IR module from CodeGenAction::mlirModule and saves it /// in CodeGenAction::llvmModule. void generateLLVMIR(); Index: flang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- flang/lib/Frontend/CompilerInvocation.cpp +++ flang/lib/Frontend/CompilerInvocation.cpp @@ -129,6 +129,11 @@ for (auto *a : args.filtered(clang::driver::options::OPT_fpass_plugin_EQ)) opts.LLVMPassPlugins.push_back(a->getValue()); + // -fembed-offload-object option + for (auto *a : + args.filtered(clang::driver::options::OPT_fembed_offload_object_EQ)) + opts.OffloadObjects.push_back(a->getValue()); + // -mrelocation-model option. if (const llvm::opt::Arg *A = args.getLastArg(clang::driver::options::OPT_mrelocation_model)) { Index: flang/lib/Frontend/FrontendActions.cpp =================================================================== --- flang/lib/Frontend/FrontendActions.cpp +++ flang/lib/Frontend/FrontendActions.cpp @@ -47,12 +47,14 @@ #include "llvm/IR/Verifier.h" #include "llvm/IRReader/IRReader.h" #include "llvm/MC/TargetRegistry.h" +#include "llvm/Object/OffloadBinary.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/Passes/PassPlugin.h" #include "llvm/Passes/StandardInstrumentations.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" #include using namespace Fortran::frontend; @@ -738,6 +740,25 @@ mpm.run(*llvmModule, mam); } +void CodeGenAction::embedOffloadObjects() { + CompilerInstance &ci = this->getInstance(); + const auto &CGOpts = ci.getInvocation().getCodeGenOpts(); + + for (llvm::StringRef OffloadObject : CGOpts.OffloadObjects) { + llvm::ErrorOr> ObjectOrErr = + llvm::MemoryBuffer::getFileOrSTDIN(OffloadObject); + if (std::error_code EC = ObjectOrErr.getError()) { + auto DiagID = ci.getDiagnostics().getCustomDiagID( + clang::DiagnosticsEngine::Error, "could not open '%0' for embedding"); + ci.getDiagnostics().Report(DiagID) << OffloadObject; + return; + } + llvm::embedBufferInModule( + *llvmModule, **ObjectOrErr, ".llvm.offloading", + llvm::Align(llvm::object::OffloadBinary::getAlignment())); + } +} + void CodeGenAction::executeAction() { CompilerInstance &ci = this->getInstance(); @@ -785,12 +806,17 @@ ci.getDiagnostics().Report(clang::diag::warn_fe_override_module) << theTriple; } + // Always set the triple and data layout, to make sure they match and are set. // Note that this overwrites any datalayout stored in the LLVM-IR. This avoids // an assert for incompatible data layout when the code-generation happens. llvmModule->setTargetTriple(theTriple); llvmModule->setDataLayout(tm->createDataLayout()); + // Embed offload objects specified with -fembed-offload-object + if (!ci.getInvocation().getCodeGenOpts().OffloadObjects.empty()) + embedOffloadObjects(); + // Run LLVM's middle-end (i.e. the optimizer). runOptimizationPipeline(*os); Index: flang/test/Driver/driver-help.f90 =================================================================== --- flang/test/Driver/driver-help.f90 +++ flang/test/Driver/driver-help.f90 @@ -109,6 +109,8 @@ ! HELP-FC1-NEXT: -fdefault-double-8 Set the default double precision kind to an 8 byte wide type ! HELP-FC1-NEXT: -fdefault-integer-8 Set the default integer kind to an 8 byte wide type ! HELP-FC1-NEXT: -fdefault-real-8 Set the default real kind to an 8 byte wide type +! HELP-FC1-NEXT: -fembed-offload-object= +! HELP-FC1-NEXT: Embed Offloading device-side binary into host object file as a section. ! HELP-FC1-NEXT: -ffast-math Allow aggressive, lossy floating-point optimizations ! HELP-FC1-NEXT: -ffixed-form Process source files in fixed form ! HELP-FC1-NEXT: -ffixed-line-length= Index: flang/test/Driver/embed-error.f90 =================================================================== --- /dev/null +++ flang/test/Driver/embed-error.f90 @@ -0,0 +1,12 @@ + +!---------- +! RUN lines +!---------- +! Embed something that can be easily checked +! RUN: not %flang_fc1 -emit-llvm -o - -fembed-offload-object=%S/Inputs/missing.f90 %s 2>&1 | FileCheck %s --check-prefix=ERROR + +! ERROR: error: could not open + +parameter(i=1) +integer :: j +end program Index: flang/test/Driver/embed.f90 =================================================================== --- /dev/null +++ flang/test/Driver/embed.f90 @@ -0,0 +1,13 @@ + +!---------- +! RUN lines +!---------- +! Embed something that can be easily checked +! RUN: %flang_fc1 -emit-llvm -o - -fembed-offload-object=%S/Inputs/hello.f90 %s 2>&1 | FileCheck %s + +! CHECK: llvm.embedded.object +! CHECK: Hello world! + +parameter(i=1) +integer :: j +end program