5
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
6
//
7
7
// ===----------------------------------------------------------------------===//
8
-
9
8
#include " clang/Driver/Driver.h"
10
9
#include " InputInfo.h"
11
10
#include " ToolChains/AIX.h"
@@ -2720,6 +2719,16 @@ static SmallVector<const char *, 16> getLinkerArgs(Compilation &C,
2720
2719
return LibArgs;
2721
2720
}
2722
2721
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
+
2723
2732
// Goes through all of the arguments, including inputs expected for the
2724
2733
// linker directly, to determine if we need to perform additional work for
2725
2734
// static offload libraries.
@@ -3798,7 +3807,13 @@ class OffloadingActionBuilder final {
3798
3807
if (IA->getType () == types::TY_Object) {
3799
3808
if (!isObjectFile (FileName))
3800
3809
return ABRT_Inactive;
3801
- 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 ()))
3802
3817
FPGAObjectInputs.push_back (IA);
3803
3818
}
3804
3819
// When creating FPGA device fat objects, all host objects are
@@ -3862,6 +3877,92 @@ class OffloadingActionBuilder final {
3862
3877
SYCLDeviceActions.clear ();
3863
3878
}
3864
3879
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
+
3865
3966
void appendLinkDependences (OffloadAction::DeviceDependences &DA) override {
3866
3967
assert (ToolChains.size () == DeviceLinkerInputs.size () &&
3867
3968
" Toolchains and linker inputs sizes do not match." );
@@ -3941,13 +4042,27 @@ class OffloadingActionBuilder final {
3941
4042
}
3942
4043
ActionList DeviceLibObjects;
3943
4044
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;
3944
4050
for (const auto &Input : LI) {
3945
4051
// FPGA aoco does not go through the link, everything else does.
3946
4052
if (Input->getType () == types::TY_FPGA_AOCO)
3947
4053
DeviceLibObjects.push_back (Input);
3948
4054
else
3949
4055
LinkObjects.push_back (Input);
3950
4056
}
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
+ }
3951
4066
// The linkage actions subgraph leading to the offload wrapper.
3952
4067
// [cond] Means incoming/outgoing dependence is created only when cond
3953
4068
// is true. A function of:
@@ -4002,7 +4117,6 @@ class OffloadingActionBuilder final {
4002
4117
Action *DeviceLinkAction =
4003
4118
C.MakeAction <LinkJobAction>(LinkObjects, types::TY_LLVM_BC);
4004
4119
// setup some flags upfront
4005
- auto isNVPTX = (*TC)->getTriple ().isNVPTX ();
4006
4120
4007
4121
if (isNVPTX && DeviceCodeSplit) {
4008
4122
// TODO Temporary limitation, need to support code splitting for PTX
@@ -4014,10 +4128,6 @@ class OffloadingActionBuilder final {
4014
4128
D.Diag (diag::err_drv_unsupported_opt_for_target)
4015
4129
<< OptName << (*TC)->getTriple ().str ();
4016
4130
}
4017
- auto TT = SYCLTripleList[I];
4018
- bool isSpirvAOT = TT.getSubArch () == llvm::Triple::SPIRSubArch_fpga ||
4019
- TT.getSubArch () == llvm::Triple::SPIRSubArch_gen ||
4020
- TT.getSubArch () == llvm::Triple::SPIRSubArch_x86_64;
4021
4131
// reflects whether current target is ahead-of-time and can't support
4022
4132
// runtime setting of specialization constants
4023
4133
bool isAOT = isNVPTX || isSpirvAOT;
0 commit comments