55// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66//
77// ===----------------------------------------------------------------------===//
8-
98#include " clang/Driver/Driver.h"
109#include " InputInfo.h"
1110#include " ToolChains/AIX.h"
@@ -1788,20 +1787,21 @@ llvm::Triple Driver::MakeSYCLDeviceTriple(StringRef TargetArch) const {
17881787// Print the help from any of the given tools which are used for AOT
17891788// compilation for SYCL
17901789void Driver::PrintSYCLToolHelp (const Compilation &C) const {
1791- SmallVector<std::tuple<llvm::Triple, StringRef, StringRef>, 4 > HelpArgs;
1790+ SmallVector<std::tuple<llvm::Triple, StringRef, StringRef, StringRef>, 4 >
1791+ HelpArgs;
17921792 // Populate the vector with the tools and help options
17931793 if (Arg *A = C.getArgs ().getLastArg (options::OPT_fsycl_help_EQ)) {
17941794 StringRef AV (A->getValue ());
17951795 llvm::Triple T;
17961796 if (AV == " gen" || AV == " all" )
17971797 HelpArgs.push_back (std::make_tuple (MakeSYCLDeviceTriple (" spir64_gen" ),
1798- " ocloc" , " --help" ));
1798+ " ocloc" , " --help" , " " ));
17991799 if (AV == " fpga" || AV == " all" )
1800- HelpArgs.push_back (
1801- std::make_tuple ( MakeSYCLDeviceTriple ( " spir64_fpga " ) , " aoc " , " -help " ));
1800+ HelpArgs.push_back (std::make_tuple ( MakeSYCLDeviceTriple ( " spir64_fpga " ),
1801+ " aoc " , " -help " , " -sycl " ));
18021802 if (AV == " x86_64" || AV == " all" )
18031803 HelpArgs.push_back (std::make_tuple (MakeSYCLDeviceTriple (" spir64_x86_64" ),
1804- " opencl-aot" , " --help" ));
1804+ " opencl-aot" , " --help" , " " ));
18051805 if (HelpArgs.empty ()) {
18061806 C.getDriver ().Diag (diag::err_drv_unsupported_option_argument)
18071807 << A->getOption ().getName () << AV;
@@ -1814,7 +1814,8 @@ void Driver::PrintSYCLToolHelp(const Compilation &C) const {
18141814 llvm::outs () << " Emitting help information for " << std::get<1 >(HA) << ' \n '
18151815 << " Use triple of '" << std::get<0 >(HA).normalize () <<
18161816 " ' to enable ahead of time compilation\n " ;
1817- std::vector<StringRef> ToolArgs = { std::get<1 >(HA), std::get<2 >(HA) };
1817+ std::vector<StringRef> ToolArgs = {std::get<1 >(HA), std::get<2 >(HA),
1818+ std::get<3 >(HA)};
18181819 SmallString<128 > ExecPath (
18191820 C.getDefaultToolChain ().GetProgramPath (std::get<1 >(HA).data ()));
18201821 auto ToolBinary = llvm::sys::findProgramByName (ExecPath);
@@ -1824,7 +1825,10 @@ void Driver::PrintSYCLToolHelp(const Compilation &C) const {
18241825 }
18251826 // do not run the tools with -###.
18261827 if (C.getArgs ().hasArg (options::OPT__HASH_HASH_HASH)) {
1827- llvm::errs () << " \" " << ExecPath << " \" \" " << ToolArgs[1 ] << " \"\n " ;
1828+ llvm::errs () << " \" " << ExecPath << " \" \" " << ToolArgs[1 ] << " \" " ;
1829+ if (!ToolArgs[2 ].empty ())
1830+ llvm::errs () << " \" " << ToolArgs[2 ] << " \" " ;
1831+ llvm::errs () << " \n " ;
18281832 continue ;
18291833 }
18301834 // Run the Tool.
@@ -2715,6 +2719,16 @@ static SmallVector<const char *, 16> getLinkerArgs(Compilation &C,
27152719 return LibArgs;
27162720}
27172721
2722+ static bool IsSYCLDeviceLibObj (std::string ObjFilePath, bool isMSVCEnv) {
2723+ StringRef ObjFileName = llvm::sys::path::filename (ObjFilePath);
2724+ StringRef ObjSuffix = isMSVCEnv ? " .obj" : " .o" ;
2725+ bool Ret =
2726+ (ObjFileName.startswith (" libsycl-" ) && ObjFileName.endswith (ObjSuffix))
2727+ ? true
2728+ : false ;
2729+ return Ret;
2730+ }
2731+
27182732// Goes through all of the arguments, including inputs expected for the
27192733// linker directly, to determine if we need to perform additional work for
27202734// static offload libraries.
@@ -3793,7 +3807,13 @@ class OffloadingActionBuilder final {
37933807 if (IA->getType () == types::TY_Object) {
37943808 if (!isObjectFile (FileName))
37953809 return ABRT_Inactive;
3796- if (Args.hasArg (options::OPT_fintelfpga))
3810+ // For SYCL device libraries, don't need to add them to
3811+ // FPGAObjectInputs as there is no FPGA dep files inside.
3812+
3813+ if (Args.hasArg (options::OPT_fintelfpga) &&
3814+ !IsSYCLDeviceLibObj (FileName, C.getDefaultToolChain ()
3815+ .getTriple ()
3816+ .isWindowsMSVCEnvironment ()))
37973817 FPGAObjectInputs.push_back (IA);
37983818 }
37993819 // When creating FPGA device fat objects, all host objects are
@@ -3857,6 +3877,92 @@ class OffloadingActionBuilder final {
38573877 SYCLDeviceActions.clear ();
38583878 }
38593879
3880+ void addSYCLDeviceLibs (const ToolChain *TC, ActionList &DeviceLinkObjects,
3881+ bool isSpirvAOT, bool isMSVCEnv) {
3882+ enum SYCLDeviceLibType {
3883+ sycl_devicelib_wrapper,
3884+ sycl_devicelib_fallback
3885+ };
3886+ struct DeviceLibOptInfo {
3887+ StringRef devicelib_name;
3888+ StringRef devicelib_option;
3889+ };
3890+
3891+ bool NoDeviceLibs = false ;
3892+ // Currently, libc, libm-fp32 will be linked in by default. In order
3893+ // to use libm-fp64, -fsycl-device-lib=libm-fp64/all should be used.
3894+ llvm::StringMap<bool > devicelib_link_info = {
3895+ {" libc" , true }, {" libm-fp32" , true }, {" libm-fp64" , false }};
3896+ if (Arg *A = Args.getLastArg (options::OPT_fsycl_device_lib_EQ,
3897+ options::OPT_fno_sycl_device_lib_EQ)) {
3898+ if (A->getValues ().size () == 0 )
3899+ C.getDriver ().Diag (diag::warn_drv_empty_joined_argument)
3900+ << A->getAsString (Args);
3901+ else {
3902+ if (A->getOption ().matches (options::OPT_fno_sycl_device_lib_EQ))
3903+ NoDeviceLibs = true ;
3904+
3905+ for (StringRef Val : A->getValues ()) {
3906+ if (Val == " all" ) {
3907+ for (auto &K : devicelib_link_info.keys ())
3908+ devicelib_link_info[K] = true && !NoDeviceLibs;
3909+ break ;
3910+ }
3911+ auto LinkInfoIter = devicelib_link_info.find (Val);
3912+ if (LinkInfoIter == devicelib_link_info.end ()) {
3913+ C.getDriver ().Diag (diag::err_drv_unsupported_option_argument)
3914+ << A->getOption ().getName () << Val;
3915+ }
3916+ devicelib_link_info[Val] = true && !NoDeviceLibs;
3917+ }
3918+ }
3919+ }
3920+
3921+ SmallString<128 > LibLoc (TC->getDriver ().Dir );
3922+ llvm::sys::path::append (LibLoc, " /../lib" );
3923+ StringRef LibSuffix = isMSVCEnv ? " .obj" : " .o" ;
3924+ SmallVector<DeviceLibOptInfo, 5 > sycl_device_wrapper_libs = {
3925+ {" libsycl-crt" , " libc" },
3926+ {" libsycl-complex" , " libm-fp32" },
3927+ {" libsycl-complex-fp64" , " libm-fp64" },
3928+ {" libsycl-cmath" , " libm-fp32" },
3929+ {" libsycl-cmath-fp64" , " libm-fp64" }};
3930+ // For AOT compilation, we need to link sycl_device_fallback_libs as
3931+ // default too.
3932+ SmallVector<DeviceLibOptInfo, 5 > sycl_device_fallback_libs = {
3933+ {" libsycl-fallback-cassert" , " libc" },
3934+ {" libsycl-fallback-complex" , " libm-fp32" },
3935+ {" libsycl-fallback-complex-fp64" , " libm-fp64" },
3936+ {" libsycl-fallback-cmath" , " libm-fp32" },
3937+ {" libsycl-fallback-cmath-fp64" , " libm-fp64" }};
3938+ auto addInputs = [&](SYCLDeviceLibType t) {
3939+ auto sycl_libs = (t == sycl_devicelib_wrapper)
3940+ ? sycl_device_wrapper_libs
3941+ : sycl_device_fallback_libs;
3942+ for (const DeviceLibOptInfo &Lib : sycl_libs) {
3943+ if (!devicelib_link_info[Lib.devicelib_option ])
3944+ continue ;
3945+ SmallString<128 > LibName (LibLoc);
3946+ llvm::sys::path::append (LibName, Lib.devicelib_name );
3947+ llvm::sys::path::replace_extension (LibName, LibSuffix);
3948+ if (llvm::sys::fs::exists (LibName)) {
3949+ Arg *InputArg = MakeInputArg (Args, C.getDriver ().getOpts (),
3950+ Args.MakeArgString (LibName));
3951+ auto *SYCLDeviceLibsInputAction =
3952+ C.MakeAction <InputAction>(*InputArg, types::TY_Object);
3953+ auto *SYCLDeviceLibsUnbundleAction =
3954+ C.MakeAction <OffloadUnbundlingJobAction>(
3955+ SYCLDeviceLibsInputAction);
3956+ addDeviceDepences (SYCLDeviceLibsUnbundleAction);
3957+ DeviceLinkObjects.push_back (SYCLDeviceLibsUnbundleAction);
3958+ }
3959+ }
3960+ };
3961+ addInputs (sycl_devicelib_wrapper);
3962+ if (isSpirvAOT)
3963+ addInputs (sycl_devicelib_fallback);
3964+ }
3965+
38603966 void appendLinkDependences (OffloadAction::DeviceDependences &DA) override {
38613967 assert (ToolChains.size () == DeviceLinkerInputs.size () &&
38623968 " Toolchains and linker inputs sizes do not match." );
@@ -3936,13 +4042,27 @@ class OffloadingActionBuilder final {
39364042 }
39374043 ActionList DeviceLibObjects;
39384044 ActionList LinkObjects;
4045+ auto TT = SYCLTripleList[I];
4046+ auto isNVPTX = (*TC)->getTriple ().isNVPTX ();
4047+ bool isSpirvAOT = TT.getSubArch () == llvm::Triple::SPIRSubArch_fpga ||
4048+ TT.getSubArch () == llvm::Triple::SPIRSubArch_gen ||
4049+ TT.getSubArch () == llvm::Triple::SPIRSubArch_x86_64;
39394050 for (const auto &Input : LI) {
39404051 // FPGA aoco does not go through the link, everything else does.
39414052 if (Input->getType () == types::TY_FPGA_AOCO)
39424053 DeviceLibObjects.push_back (Input);
39434054 else
39444055 LinkObjects.push_back (Input);
39454056 }
4057+ // FIXME: Link all wrapper and fallback device libraries as default,
4058+ // When spv online link is supported by all backends, the fallback
4059+ // device libraries are only needed when current toolchain is using
4060+ // AOT compilation.
4061+ if (!isNVPTX) {
4062+ addSYCLDeviceLibs (
4063+ *TC, LinkObjects, true ,
4064+ C.getDefaultToolChain ().getTriple ().isWindowsMSVCEnvironment ());
4065+ }
39464066 // The linkage actions subgraph leading to the offload wrapper.
39474067 // [cond] Means incoming/outgoing dependence is created only when cond
39484068 // is true. A function of:
@@ -3997,7 +4117,6 @@ class OffloadingActionBuilder final {
39974117 Action *DeviceLinkAction =
39984118 C.MakeAction <LinkJobAction>(LinkObjects, types::TY_LLVM_BC);
39994119 // setup some flags upfront
4000- auto isNVPTX = (*TC)->getTriple ().isNVPTX ();
40014120
40024121 if (isNVPTX && DeviceCodeSplit) {
40034122 // TODO Temporary limitation, need to support code splitting for PTX
@@ -4009,10 +4128,6 @@ class OffloadingActionBuilder final {
40094128 D.Diag (diag::err_drv_unsupported_opt_for_target)
40104129 << OptName << (*TC)->getTriple ().str ();
40114130 }
4012- auto TT = SYCLTripleList[I];
4013- bool isSpirvAOT = TT.getSubArch () == llvm::Triple::SPIRSubArch_fpga ||
4014- TT.getSubArch () == llvm::Triple::SPIRSubArch_gen ||
4015- TT.getSubArch () == llvm::Triple::SPIRSubArch_x86_64;
40164131 // reflects whether current target is ahead-of-time and can't support
40174132 // runtime setting of specialization constants
40184133 bool isAOT = isNVPTX || isSpirvAOT;
0 commit comments