aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
authorMichael Toguchi <michael.d.toguchi@intel.com>2025-01-06 08:52:46 -0800
committerGitHub <noreply@github.com>2025-01-06 11:52:46 -0500
commitd00f65c6acd9f0e1ddae83391f55eb9d232d2f9e (patch)
tree6e00ecc91872af7e36d3ed3f2a480375ad812982 /clang/lib
parent98b3191a340b03051281e1dc3655a7ffa9ab2311 (diff)
downloadllvm-d00f65c6acd9f0e1ddae83391f55eb9d232d2f9e.zip
llvm-d00f65c6acd9f0e1ddae83391f55eb9d232d2f9e.tar.gz
llvm-d00f65c6acd9f0e1ddae83391f55eb9d232d2f9e.tar.bz2
[Driver][SYCL] Add initial SYCL offload compilation support (#117268)
Introduces the SYCL based toolchain and initial toolchain construction when using the '-fsycl' option. This option will enable SYCL based offloading, creating a SPIR-V based IR file packaged into the compiled host object. This includes early support for creating the host/device object using the new offloading model. The device object is created using the spir64-unknown-unknown target triple. New/Updated Options: -fsycl Enables SYCL offloading for host and device -fsycl-device-only Enables device only compilation for SYCL -fsycl-host-only Enables host only compilation for SYCL RFC Reference: https://discourse.llvm.org/t/rfc-sycl-driver-enhancements/74092 This is a reland of: https://github.com/llvm/llvm-project/pull/107493
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Driver/Action.cpp8
-rw-r--r--clang/lib/Driver/CMakeLists.txt1
-rw-r--r--clang/lib/Driver/Compilation.cpp9
-rw-r--r--clang/lib/Driver/Driver.cpp90
-rw-r--r--clang/lib/Driver/ToolChain.cpp3
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp58
-rw-r--r--clang/lib/Driver/ToolChains/Darwin.cpp8
-rw-r--r--clang/lib/Driver/ToolChains/Darwin.h4
-rw-r--r--clang/lib/Driver/ToolChains/Gnu.cpp8
-rw-r--r--clang/lib/Driver/ToolChains/Gnu.h5
-rw-r--r--clang/lib/Driver/ToolChains/Linux.cpp5
-rw-r--r--clang/lib/Driver/ToolChains/Linux.h2
-rw-r--r--clang/lib/Driver/ToolChains/MSVC.cpp7
-rw-r--r--clang/lib/Driver/ToolChains/MSVC.h5
-rw-r--r--clang/lib/Driver/ToolChains/SYCL.cpp153
-rw-r--r--clang/lib/Driver/ToolChains/SYCL.h80
16 files changed, 424 insertions, 22 deletions
diff --git a/clang/lib/Driver/Action.cpp b/clang/lib/Driver/Action.cpp
index 849bf60..23dbceb 100644
--- a/clang/lib/Driver/Action.cpp
+++ b/clang/lib/Driver/Action.cpp
@@ -111,6 +111,8 @@ std::string Action::getOffloadingKindPrefix() const {
return "device-openmp";
case OFK_HIP:
return "device-hip";
+ case OFK_SYCL:
+ return "device-sycl";
// TODO: Add other programming models here.
}
@@ -128,6 +130,8 @@ std::string Action::getOffloadingKindPrefix() const {
Res += "-hip";
if (ActiveOffloadKindMask & OFK_OpenMP)
Res += "-openmp";
+ if (ActiveOffloadKindMask & OFK_SYCL)
+ Res += "-sycl";
// TODO: Add other programming models here.
@@ -164,6 +168,8 @@ StringRef Action::GetOffloadKindName(OffloadKind Kind) {
return "openmp";
case OFK_HIP:
return "hip";
+ case OFK_SYCL:
+ return "sycl";
// TODO: Add other programming models here.
}
@@ -320,7 +326,7 @@ void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,
DeviceBoundArchs.push_back(BoundArch);
// Add each active offloading kind from a mask.
- for (OffloadKind OKind : {OFK_OpenMP, OFK_Cuda, OFK_HIP})
+ for (OffloadKind OKind : {OFK_OpenMP, OFK_Cuda, OFK_HIP, OFK_SYCL})
if (OKind & OffloadKindMask)
DeviceOffloadKinds.push_back(OKind);
}
diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt
index 57d04c3..5bdb661 100644
--- a/clang/lib/Driver/CMakeLists.txt
+++ b/clang/lib/Driver/CMakeLists.txt
@@ -78,6 +78,7 @@ add_clang_library(clangDriver
ToolChains/Solaris.cpp
ToolChains/SPIRV.cpp
ToolChains/SPIRVOpenMP.cpp
+ ToolChains/SYCL.cpp
ToolChains/TCE.cpp
ToolChains/UEFI.cpp
ToolChains/VEToolchain.cpp
diff --git a/clang/lib/Driver/Compilation.cpp b/clang/lib/Driver/Compilation.cpp
index 4d40805..a39952e 100644
--- a/clang/lib/Driver/Compilation.cpp
+++ b/clang/lib/Driver/Compilation.cpp
@@ -214,10 +214,11 @@ static bool ActionFailed(const Action *A,
if (FailingCommands.empty())
return false;
- // CUDA/HIP can have the same input source code compiled multiple times so do
- // not compiled again if there are already failures. It is OK to abort the
- // CUDA pipeline on errors.
- if (A->isOffloading(Action::OFK_Cuda) || A->isOffloading(Action::OFK_HIP))
+ // CUDA/HIP/SYCL can have the same input source code compiled multiple times
+ // so do not compile again if there are already failures. It is OK to abort
+ // the CUDA/HIP/SYCL pipeline on errors.
+ if (A->isOffloading(Action::OFK_Cuda) || A->isOffloading(Action::OFK_HIP) ||
+ A->isOffloading(Action::OFK_SYCL))
return true;
for (const auto &CI : FailingCommands)
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index bc5ce9f..36d6c93 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -44,6 +44,7 @@
#include "ToolChains/RISCVToolchain.h"
#include "ToolChains/SPIRV.h"
#include "ToolChains/SPIRVOpenMP.h"
+#include "ToolChains/SYCL.h"
#include "ToolChains/Solaris.h"
#include "ToolChains/TCE.h"
#include "ToolChains/UEFI.h"
@@ -781,6 +782,35 @@ Driver::OpenMPRuntimeKind Driver::getOpenMPRuntime(const ArgList &Args) const {
return RT;
}
+static llvm::Triple getSYCLDeviceTriple(StringRef TargetArch) {
+ SmallVector<StringRef, 5> SYCLAlias = {"spir", "spir64", "spirv", "spirv32",
+ "spirv64"};
+ if (llvm::is_contained(SYCLAlias, TargetArch)) {
+ llvm::Triple TargetTriple;
+ TargetTriple.setArchName(TargetArch);
+ TargetTriple.setVendor(llvm::Triple::UnknownVendor);
+ TargetTriple.setOS(llvm::Triple::UnknownOS);
+ return TargetTriple;
+ }
+ return llvm::Triple(TargetArch);
+}
+
+static bool addSYCLDefaultTriple(Compilation &C,
+ SmallVectorImpl<llvm::Triple> &SYCLTriples) {
+ // Check current set of triples to see if the default has already been set.
+ for (const auto &SYCLTriple : SYCLTriples) {
+ if (SYCLTriple.getSubArch() == llvm::Triple::NoSubArch &&
+ SYCLTriple.isSPIROrSPIRV())
+ return false;
+ }
+ // Add the default triple as it was not found.
+ llvm::Triple DefaultTriple = getSYCLDeviceTriple(
+ C.getDefaultToolChain().getTriple().isArch32Bit() ? "spirv32"
+ : "spirv64");
+ SYCLTriples.insert(SYCLTriples.begin(), DefaultTriple);
+ return true;
+}
+
void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
InputList &Inputs) {
@@ -842,7 +872,6 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
return;
auto *HIPTC = &getOffloadingDeviceToolChain(C.getInputArgs(), *HIPTriple,
*HostTC, OFK);
- assert(HIPTC && "Could not create offloading device tool chain.");
C.addOffloadDeviceToolChain(HIPTC, OFK);
}
@@ -997,6 +1026,38 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
return;
}
+ // We need to generate a SYCL toolchain if the user specified -fsycl.
+ bool IsSYCL = C.getInputArgs().hasFlag(options::OPT_fsycl,
+ options::OPT_fno_sycl, false);
+
+ auto argSYCLIncompatible = [&](OptSpecifier OptId) {
+ if (!IsSYCL)
+ return;
+ if (Arg *IncompatArg = C.getInputArgs().getLastArg(OptId))
+ Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << IncompatArg->getSpelling() << "-fsycl";
+ };
+ // -static-libstdc++ is not compatible with -fsycl.
+ argSYCLIncompatible(options::OPT_static_libstdcxx);
+ // -ffreestanding cannot be used with -fsycl
+ argSYCLIncompatible(options::OPT_ffreestanding);
+
+ llvm::SmallVector<llvm::Triple, 4> UniqueSYCLTriplesVec;
+
+ if (IsSYCL) {
+ addSYCLDefaultTriple(C, UniqueSYCLTriplesVec);
+
+ // We'll need to use the SYCL and host triples as the key into
+ // getOffloadingDeviceToolChain, because the device toolchains we're
+ // going to create will depend on both.
+ const ToolChain *HostTC = C.getSingleOffloadToolChain<Action::OFK_Host>();
+ for (const auto &TargetTriple : UniqueSYCLTriplesVec) {
+ auto SYCLTC = &getOffloadingDeviceToolChain(
+ C.getInputArgs(), TargetTriple, *HostTC, Action::OFK_SYCL);
+ C.addOffloadDeviceToolChain(SYCLTC, Action::OFK_SYCL);
+ }
+ }
+
//
// TODO: Add support for other offloading programming models here.
//
@@ -4234,6 +4295,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
bool UseNewOffloadingDriver =
C.isOffloadingHostKind(Action::OFK_OpenMP) ||
+ C.isOffloadingHostKind(Action::OFK_SYCL) ||
Args.hasFlag(options::OPT_foffload_via_llvm,
options::OPT_fno_offload_via_llvm, false) ||
Args.hasFlag(options::OPT_offload_new_driver,
@@ -4651,6 +4713,8 @@ Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
Archs.insert(OffloadArchToString(OffloadArch::HIPDefault));
else if (Kind == Action::OFK_OpenMP)
Archs.insert(StringRef());
+ else if (Kind == Action::OFK_SYCL)
+ Archs.insert(StringRef());
} else {
Args.ClaimAllArgs(options::OPT_offload_arch_EQ);
Args.ClaimAllArgs(options::OPT_no_offload_arch_EQ);
@@ -4675,7 +4739,7 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
OffloadAction::DeviceDependences DDeps;
const Action::OffloadKind OffloadKinds[] = {
- Action::OFK_OpenMP, Action::OFK_Cuda, Action::OFK_HIP};
+ Action::OFK_OpenMP, Action::OFK_Cuda, Action::OFK_HIP, Action::OFK_SYCL};
for (Action::OffloadKind Kind : OffloadKinds) {
SmallVector<const ToolChain *, 2> ToolChains;
@@ -4712,6 +4776,15 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
if (DeviceActions.empty())
return HostAction;
+ // FIXME: Do not collapse the host side for Darwin targets with SYCL offload
+ // compilations. The toolchain is not properly initialized for the target.
+ if (isa<CompileJobAction>(HostAction) && Kind == Action::OFK_SYCL &&
+ HostAction->getType() != types::TY_Nothing &&
+ C.getSingleOffloadToolChain<Action::OFK_Host>()
+ ->getTriple()
+ .isOSDarwin())
+ HostAction->setCannotBeCollapsedWithNextDependentAction();
+
auto PL = types::getCompilationPhases(*this, Args, InputType);
for (phases::ID Phase : PL) {
@@ -4720,6 +4793,11 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
break;
}
+ // Assemble actions are not used for the SYCL device side. Both compile
+ // and backend actions are used to generate IR and textual IR if needed.
+ if (Kind == Action::OFK_SYCL && Phase == phases::Assemble)
+ continue;
+
auto TCAndArch = TCAndArchs.begin();
for (Action *&A : DeviceActions) {
if (A->getType() == types::TY_Nothing)
@@ -4958,6 +5036,7 @@ Action *Driver::ConstructPhaseAction(
return C.MakeAction<BackendJobAction>(Input, Output);
}
if (Args.hasArg(options::OPT_emit_llvm) ||
+ TargetDeviceOffloadKind == Action::OFK_SYCL ||
(((Input->getOffloadingToolChain() &&
Input->getOffloadingToolChain()->getTriple().isAMDGPU()) ||
TargetDeviceOffloadKind == Action::OFK_HIP) &&
@@ -6644,11 +6723,16 @@ const ToolChain &Driver::getOffloadingDeviceToolChain(
HostTC, Args);
break;
}
+ case Action::OFK_SYCL:
+ if (Target.isSPIROrSPIRV())
+ TC = std::make_unique<toolchains::SYCLToolChain>(*this, Target, HostTC,
+ Args);
+ break;
default:
break;
}
}
-
+ assert(TC && "Could not create offloading device tool chain.");
return *TC;
}
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 9f174fb..2b4df64 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -1485,6 +1485,9 @@ void ToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
void ToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {}
+void ToolChain::addSYCLIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {}
+
llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
ToolChain::getDeviceLibs(const ArgList &DriverArgs) const {
return {};
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index daf863c..a000237 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -24,6 +24,7 @@
#include "Hexagon.h"
#include "MSP430.h"
#include "PS4CPU.h"
+#include "SYCL.h"
#include "clang/Basic/CLWarnings.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/CodeGenOptions.h"
@@ -122,6 +123,13 @@ forAllAssociatedToolChains(Compilation &C, const JobAction &JA,
} else if (JA.isDeviceOffloading(Action::OFK_OpenMP))
Work(*C.getSingleOffloadToolChain<Action::OFK_Host>());
+ if (JA.isHostOffloading(Action::OFK_SYCL)) {
+ auto TCs = C.getOffloadToolChains<Action::OFK_SYCL>();
+ for (auto II = TCs.first, IE = TCs.second; II != IE; ++II)
+ Work(*II->second);
+ } else if (JA.isDeviceOffloading(Action::OFK_SYCL))
+ Work(*C.getSingleOffloadToolChain<Action::OFK_Host>());
+
//
// TODO: Add support for other offloading programming models here.
//
@@ -1070,14 +1078,16 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_MP);
Args.AddLastArg(CmdArgs, options::OPT_MV);
- // Add offload include arguments specific for CUDA/HIP. This must happen
+ // Add offload include arguments specific for CUDA/HIP/SYCL. This must happen
// before we -I or -include anything else, because we must pick up the
- // CUDA/HIP headers from the particular CUDA/ROCm installation, rather than
- // from e.g. /usr/local/include.
+ // CUDA/HIP/SYCL headers from the particular CUDA/ROCm/SYCL installation,
+ // rather than from e.g. /usr/local/include.
if (JA.isOffloading(Action::OFK_Cuda))
getToolChain().AddCudaIncludeArgs(Args, CmdArgs);
if (JA.isOffloading(Action::OFK_HIP))
getToolChain().AddHIPIncludeArgs(Args, CmdArgs);
+ if (JA.isOffloading(Action::OFK_SYCL))
+ getToolChain().addSYCLIncludeArgs(Args, CmdArgs);
// If we are offloading to a target via OpenMP we need to include the
// openmp_wrappers folder which contains alternative system headers.
@@ -5037,17 +5047,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// second input. Module precompilation accepts a list of header files to
// include as part of the module. API extraction accepts a list of header
// files whose API information is emitted in the output. All other jobs are
- // expected to have exactly one input.
+ // expected to have exactly one input. SYCL compilation only expects a
+ // single input.
bool IsCuda = JA.isOffloading(Action::OFK_Cuda);
bool IsCudaDevice = JA.isDeviceOffloading(Action::OFK_Cuda);
bool IsHIP = JA.isOffloading(Action::OFK_HIP);
bool IsHIPDevice = JA.isDeviceOffloading(Action::OFK_HIP);
+ bool IsSYCL = JA.isOffloading(Action::OFK_SYCL);
+ bool IsSYCLDevice = JA.isDeviceOffloading(Action::OFK_SYCL);
bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
bool IsExtractAPI = isa<ExtractAPIJobAction>(JA);
bool IsDeviceOffloadAction = !(JA.isDeviceOffloading(Action::OFK_None) ||
JA.isDeviceOffloading(Action::OFK_Host));
bool IsHostOffloadingAction =
JA.isHostOffloading(Action::OFK_OpenMP) ||
+ JA.isHostOffloading(Action::OFK_SYCL) ||
(JA.isHostOffloading(C.getActiveOffloadKinds()) &&
Args.hasFlag(options::OPT_offload_new_driver,
options::OPT_no_offload_new_driver, false));
@@ -5097,10 +5111,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
bool IsWindowsMSVC = RawTriple.isWindowsMSVCEnvironment();
bool IsIAMCU = RawTriple.isOSIAMCU();
- // Adjust IsWindowsXYZ for CUDA/HIP compilations. Even when compiling in
+ // Adjust IsWindowsXYZ for CUDA/HIP/SYCL compilations. Even when compiling in
// device mode (i.e., getToolchain().getTriple() is NVPTX/AMDGCN, not
// Windows), we need to pass Windows-specific flags to cc1.
- if (IsCuda || IsHIP)
+ if (IsCuda || IsHIP || IsSYCL)
IsWindowsMSVC |= AuxTriple && AuxTriple->isWindowsMSVCEnvironment();
// C++ is not supported for IAMCU.
@@ -5184,11 +5198,33 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (const Arg *PF = Args.getLastArg(options::OPT_mprintf_kind_EQ))
PF->claim();
- if (Args.hasFlag(options::OPT_fsycl, options::OPT_fno_sycl, false)) {
- CmdArgs.push_back("-fsycl-is-device");
+ if (IsSYCL) {
+ if (IsSYCLDevice) {
+ // Host triple is needed when doing SYCL device compilations.
+ llvm::Triple AuxT = C.getDefaultToolChain().getTriple();
+ std::string NormalizedTriple = AuxT.normalize();
+ CmdArgs.push_back("-aux-triple");
+ CmdArgs.push_back(Args.MakeArgString(NormalizedTriple));
- if (Arg *A = Args.getLastArg(options::OPT_sycl_std_EQ)) {
- A->render(Args, CmdArgs);
+ // We want to compile sycl kernels.
+ CmdArgs.push_back("-fsycl-is-device");
+
+ // Set O2 optimization level by default
+ if (!Args.getLastArg(options::OPT_O_Group))
+ CmdArgs.push_back("-O2");
+ } else {
+ // Add any options that are needed specific to SYCL offload while
+ // performing the host side compilation.
+
+ // Let the front-end host compilation flow know about SYCL offload
+ // compilation.
+ CmdArgs.push_back("-fsycl-is-host");
+ }
+
+ // Set options for both host and device.
+ Arg *SYCLStdArg = Args.getLastArg(options::OPT_sycl_std_EQ);
+ if (SYCLStdArg) {
+ SYCLStdArg->render(Args, CmdArgs);
} else {
// Ensure the default version in SYCL mode is 2020.
CmdArgs.push_back("-sycl-std=2020");
@@ -6135,7 +6171,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Prepare `-aux-target-cpu` and `-aux-target-feature` unless
// `--gpu-use-aux-triple-only` is specified.
if (!Args.getLastArg(options::OPT_gpu_use_aux_triple_only) &&
- (IsCudaDevice || IsHIPDevice)) {
+ (IsCudaDevice || IsHIPDevice || IsSYCLDevice)) {
const ArgList &HostArgs =
C.getArgsForToolChain(nullptr, StringRef(), Action::OFK_None);
std::string HostCPU =
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 4105d38..56b6dd7 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -969,7 +969,8 @@ MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
/// Darwin - Darwin tool chain for i386 and x86_64.
Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: MachO(D, Triple, Args), TargetInitialized(false),
- CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {}
+ CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args),
+ SYCLInstallation(D, Triple, Args) {}
types::ID MachO::LookupTypeForExtension(StringRef Ext) const {
types::ID Ty = ToolChain::LookupTypeForExtension(Ext);
@@ -1028,6 +1029,11 @@ void Darwin::AddHIPIncludeArgs(const ArgList &DriverArgs,
RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args);
}
+void Darwin::addSYCLIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ SYCLInstallation->addSYCLIncludeArgs(DriverArgs, CC1Args);
+}
+
// This is just a MachO name translation routine and there's no
// way to join this into ARMTargetParser without breaking all
// other assumptions. Maybe MachO should consider standardising
diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h
index 2e55b496..5bc1858 100644
--- a/clang/lib/Driver/ToolChains/Darwin.h
+++ b/clang/lib/Driver/ToolChains/Darwin.h
@@ -12,6 +12,7 @@
#include "Cuda.h"
#include "LazyDetector.h"
#include "ROCm.h"
+#include "SYCL.h"
#include "clang/Basic/DarwinSDKInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Driver/Tool.h"
@@ -331,6 +332,7 @@ public:
LazyDetector<CudaInstallationDetector> CudaInstallation;
LazyDetector<RocmInstallationDetector> RocmInstallation;
+ LazyDetector<SYCLInstallationDetector> SYCLInstallation;
private:
void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const;
@@ -563,6 +565,8 @@ public:
llvm::opt::ArgStringList &CC1Args) const override;
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ void addSYCLIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
bool UseObjCMixedDispatch() const override {
// This is only used with the non-fragile ABI and non-legacy dispatch.
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index 8397f11..e5db1b2 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -3058,7 +3058,8 @@ bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args), GCCInstallation(D),
- CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {
+ CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args),
+ SYCLInstallation(D, Triple, Args) {
getProgramPaths().push_back(getDriver().Dir);
}
@@ -3274,6 +3275,11 @@ void Generic_GCC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
}
}
+void Generic_GCC::addSYCLIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ SYCLInstallation->addSYCLIncludeArgs(DriverArgs, CC1Args);
+}
+
void
Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
diff --git a/clang/lib/Driver/ToolChains/Gnu.h b/clang/lib/Driver/ToolChains/Gnu.h
index 0b664a1..3b8df71 100644
--- a/clang/lib/Driver/ToolChains/Gnu.h
+++ b/clang/lib/Driver/ToolChains/Gnu.h
@@ -12,6 +12,7 @@
#include "Cuda.h"
#include "LazyDetector.h"
#include "ROCm.h"
+#include "SYCL.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
#include <set>
@@ -288,6 +289,7 @@ protected:
GCCInstallationDetector GCCInstallation;
LazyDetector<CudaInstallationDetector> CudaInstallation;
LazyDetector<RocmInstallationDetector> RocmInstallation;
+ LazyDetector<SYCLInstallationDetector> SYCLInstallation;
public:
Generic_GCC(const Driver &D, const llvm::Triple &Triple,
@@ -336,6 +338,9 @@ protected:
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ void addSYCLIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
virtual void
addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index c91b55b..1c56355 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -777,6 +777,11 @@ void Linux::AddIAMCUIncludeArgs(const ArgList &DriverArgs,
}
}
+void Linux::addSYCLIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ SYCLInstallation->addSYCLIncludeArgs(DriverArgs, CC1Args);
+}
+
bool Linux::isPIEDefault(const llvm::opt::ArgList &Args) const {
return CLANG_DEFAULT_PIE_ON_LINUX || getTriple().isAndroid() ||
getTriple().isMusl() || getSanitizerArgs(Args).requiresPIE();
diff --git a/clang/lib/Driver/ToolChains/Linux.h b/clang/lib/Driver/ToolChains/Linux.h
index 2d9e674..2eb2d05 100644
--- a/clang/lib/Driver/ToolChains/Linux.h
+++ b/clang/lib/Driver/ToolChains/Linux.h
@@ -41,6 +41,8 @@ public:
llvm::opt::ArgStringList &CmdArgs) const override;
void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
+ void addSYCLIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
RuntimeLibType GetDefaultRuntimeLibType() const override;
unsigned GetDefaultDwarfVersion() const override;
CXXStdlibType GetDefaultCXXStdlibType() const override;
diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp
index 752c2e2..bae41fc 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -430,7 +430,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
- RocmInstallation(D, Triple, Args) {
+ RocmInstallation(D, Triple, Args), SYCLInstallation(D, Triple, Args) {
getProgramPaths().push_back(getDriver().Dir);
std::optional<llvm::StringRef> VCToolsDir, VCToolsVersion;
@@ -509,6 +509,11 @@ void MSVCToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
RocmInstallation->AddHIPIncludeArgs(DriverArgs, CC1Args);
}
+void MSVCToolChain::addSYCLIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ SYCLInstallation->addSYCLIncludeArgs(DriverArgs, CC1Args);
+}
+
void MSVCToolChain::AddHIPRuntimeLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CmdArgs.append({Args.MakeArgString(StringRef("-libpath:") +
diff --git a/clang/lib/Driver/ToolChains/MSVC.h b/clang/lib/Driver/ToolChains/MSVC.h
index 3950a8e..b35390c 100644
--- a/clang/lib/Driver/ToolChains/MSVC.h
+++ b/clang/lib/Driver/ToolChains/MSVC.h
@@ -12,6 +12,7 @@
#include "AMDGPU.h"
#include "Cuda.h"
#include "LazyDetector.h"
+#include "SYCL.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
@@ -100,6 +101,9 @@ public:
void AddHIPRuntimeLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
+ void addSYCLIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
bool getWindowsSDKLibraryPath(
const llvm::opt::ArgList &Args, std::string &path) const;
bool getUniversalCRTLibraryPath(const llvm::opt::ArgList &Args,
@@ -138,6 +142,7 @@ private:
llvm::ToolsetLayout VSLayout = llvm::ToolsetLayout::OlderVS;
LazyDetector<CudaInstallationDetector> CudaInstallation;
LazyDetector<RocmInstallationDetector> RocmInstallation;
+ LazyDetector<SYCLInstallationDetector> SYCLInstallation;
};
} // end namespace toolchains
diff --git a/clang/lib/Driver/ToolChains/SYCL.cpp b/clang/lib/Driver/ToolChains/SYCL.cpp
new file mode 100644
index 0000000..e42b65c
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/SYCL.cpp
@@ -0,0 +1,153 @@
+//===--- SYCL.cpp - SYCL Tool and ToolChain Implementations -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "SYCL.h"
+#include "CommonArgs.h"
+#include "llvm/Support/Path.h"
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+SYCLInstallationDetector::SYCLInstallationDetector(
+ const Driver &D, const llvm::Triple &HostTriple,
+ const llvm::opt::ArgList &Args)
+ : D(D) {}
+
+void SYCLInstallationDetector::addSYCLIncludeArgs(
+ const ArgList &DriverArgs, ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(clang::driver::options::OPT_nobuiltininc))
+ return;
+
+ // Add the SYCL header search locations in the specified order.
+ // FIXME: Add the header file locations once the SYCL library and headers
+ // are properly established within the build.
+}
+
+// Unsupported options for SYCL device compilation.
+static ArrayRef<OptSpecifier> getUnsupportedOpts() {
+ return {
+ options::OPT_fsanitize_EQ, // -fsanitize
+ options::OPT_fcf_protection_EQ, // -fcf-protection
+ options::OPT_fprofile_generate,
+ options::OPT_fprofile_generate_EQ,
+ options::OPT_fno_profile_generate, // -f[no-]profile-generate
+ options::OPT_ftest_coverage,
+ options::OPT_fno_test_coverage, // -f[no-]test-coverage
+ options::OPT_fcoverage_mapping,
+ options::OPT_fno_coverage_mapping, // -f[no-]coverage-mapping
+ options::OPT_coverage, // --coverage
+ options::OPT_fprofile_instr_generate,
+ options::OPT_fprofile_instr_generate_EQ,
+ options::OPT_fno_profile_instr_generate, // -f[no-]profile-instr-generate
+ options::OPT_fprofile_arcs,
+ options::OPT_fno_profile_arcs, // -f[no-]profile-arcs
+ options::OPT_fcreate_profile, // -fcreate-profile
+ options::OPT_fprofile_instr_use,
+ options::OPT_fprofile_instr_use_EQ, // -fprofile-instr-use
+ options::OPT_forder_file_instrumentation, // -forder-file-instrumentation
+ options::OPT_fcs_profile_generate, // -fcs-profile-generate
+ options::OPT_fcs_profile_generate_EQ};
+}
+
+SYCLToolChain::SYCLToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ToolChain &HostTC, const ArgList &Args)
+ : ToolChain(D, Triple, Args), HostTC(HostTC),
+ SYCLInstallation(D, Triple, Args) {
+ // Lookup binaries into the driver directory, this is used to discover any
+ // dependent SYCL offload compilation tools.
+ getProgramPaths().push_back(getDriver().Dir);
+
+ // Diagnose unsupported options only once.
+ for (OptSpecifier Opt : getUnsupportedOpts()) {
+ if (const Arg *A = Args.getLastArg(Opt)) {
+ D.Diag(clang::diag::warn_drv_unsupported_option_for_target)
+ << A->getAsString(Args) << getTriple().str();
+ }
+ }
+}
+
+void SYCLToolChain::addClangTargetOptions(
+ const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadingKind) const {
+ HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind);
+}
+
+llvm::opt::DerivedArgList *
+SYCLToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
+ StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const {
+ DerivedArgList *DAL =
+ HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind);
+
+ bool IsNewDAL = false;
+ if (!DAL) {
+ DAL = new DerivedArgList(Args.getBaseArgs());
+ IsNewDAL = true;
+ }
+
+ for (Arg *A : Args) {
+ // Filter out any options we do not want to pass along to the device
+ // compilation.
+ auto Opt(A->getOption());
+ bool Unsupported = false;
+ for (OptSpecifier UnsupportedOpt : getUnsupportedOpts()) {
+ if (Opt.matches(UnsupportedOpt)) {
+ if (Opt.getID() == options::OPT_fsanitize_EQ &&
+ A->getValues().size() == 1) {
+ std::string SanitizeVal = A->getValue();
+ if (SanitizeVal == "address") {
+ if (IsNewDAL)
+ DAL->append(A);
+ continue;
+ }
+ }
+ if (!IsNewDAL)
+ DAL->eraseArg(Opt.getID());
+ Unsupported = true;
+ }
+ }
+ if (Unsupported)
+ continue;
+ if (IsNewDAL)
+ DAL->append(A);
+ }
+
+ const OptTable &Opts = getDriver().getOpts();
+ if (!BoundArch.empty()) {
+ DAL->eraseArg(options::OPT_march_EQ);
+ DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ),
+ BoundArch);
+ }
+ return DAL;
+}
+
+void SYCLToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {
+ HostTC.addClangWarningOptions(CC1Args);
+}
+
+ToolChain::CXXStdlibType
+SYCLToolChain::GetCXXStdlibType(const ArgList &Args) const {
+ return HostTC.GetCXXStdlibType(Args);
+}
+
+void SYCLToolChain::addSYCLIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ SYCLInstallation.addSYCLIncludeArgs(DriverArgs, CC1Args);
+}
+
+void SYCLToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args);
+}
+
+void SYCLToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args,
+ ArgStringList &CC1Args) const {
+ HostTC.AddClangCXXStdlibIncludeArgs(Args, CC1Args);
+}
diff --git a/clang/lib/Driver/ToolChains/SYCL.h b/clang/lib/Driver/ToolChains/SYCL.h
new file mode 100644
index 0000000..9af2fd0
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/SYCL.h
@@ -0,0 +1,80 @@
+//===--- SYCL.h - SYCL ToolChain Implementations ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_SYCL_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_SYCL_H
+
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+
+class SYCLInstallationDetector {
+public:
+ SYCLInstallationDetector(const Driver &D, const llvm::Triple &HostTriple,
+ const llvm::opt::ArgList &Args);
+
+ void addSYCLIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const;
+
+private:
+ const Driver &D;
+};
+
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY SYCLToolChain : public ToolChain {
+public:
+ SYCLToolChain(const Driver &D, const llvm::Triple &Triple,
+ const ToolChain &HostTC, const llvm::opt::ArgList &Args);
+
+ const llvm::Triple *getAuxTriple() const override {
+ return &HostTC.getTriple();
+ }
+
+ llvm::opt::DerivedArgList *
+ TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
+ Action::OffloadKind DeviceOffloadKind) const override;
+ void
+ addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
+
+ bool useIntegratedAs() const override { return true; }
+ bool isPICDefault() const override { return false; }
+ llvm::codegenoptions::DebugInfoFormat getDefaultDebugFormat() const override {
+ return this->HostTC.getDefaultDebugFormat();
+ }
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
+ return false;
+ }
+ bool isPICDefaultForced() const override { return false; }
+
+ void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
+ CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+ void addSYCLIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void AddClangCXXStdlibIncludeArgs(
+ const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CC1Args) const override;
+
+private:
+ const ToolChain &HostTC;
+ SYCLInstallationDetector SYCLInstallation;
+};
+
+} // end namespace toolchains
+
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_SYCL_H