diff options
author | Michael Toguchi <michael.d.toguchi@intel.com> | 2025-01-06 08:52:46 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-06 11:52:46 -0500 |
commit | d00f65c6acd9f0e1ddae83391f55eb9d232d2f9e (patch) | |
tree | 6e00ecc91872af7e36d3ed3f2a480375ad812982 /clang/lib | |
parent | 98b3191a340b03051281e1dc3655a7ffa9ab2311 (diff) | |
download | llvm-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.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Driver/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/Driver/Compilation.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Driver/Driver.cpp | 90 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChain.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Clang.cpp | 58 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Darwin.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Darwin.h | 4 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Gnu.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Gnu.h | 5 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Linux.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Linux.h | 2 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/MSVC.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/MSVC.h | 5 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/SYCL.cpp | 153 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/SYCL.h | 80 |
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 |