https://github.com/AdityaSinha149 updated https://github.com/llvm/llvm-project/pull/231783
>From e5f7ada2d3b034a9aedca62d762e1206da876ef9 Mon Sep 17 00:00:00 2001 From: AdityaSinha149 <[email protected]> Date: Wed, 14 Oct 2026 13:00:27 +0530 Subject: [PATCH] [clang-repl] Added -hip option --- clang/include/clang/Interpreter/Interpreter.h | 20 ++++---- clang/lib/Interpreter/Interpreter.cpp | 44 +++++++++-------- .../Interpreter/HIP/hip-not-supported.hip | 11 +++++ clang/test/Interpreter/HIP/lit.local.cfg | 12 +++++ clang/tools/clang-repl/ClangRepl.cpp | 48 +++++++++++-------- .../Interpreter/DeviceOffloadTest.cpp | 16 +++---- 6 files changed, 95 insertions(+), 56 deletions(-) create mode 100644 clang/test/Interpreter/HIP/hip-not-supported.hip create mode 100644 clang/test/Interpreter/HIP/lit.local.cfg diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index 64f02b797c204f..64dee1cf80db8d 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -69,28 +69,33 @@ class IncrementalCompilerBuilder { // Offload options void SetOffloadArch(llvm::StringRef Arch) { OffloadArch = Arch; }; - // CUDA specific - void SetCudaSDK(llvm::StringRef path) { CudaSDKPath = path; }; + // The SDK path (CUDA or ROCm) of the device language being offloaded to. + void SetDeviceSDK(llvm::StringRef Path) { DeviceSDKPath = Path; } // Hand over the compilation. void SetDriverCompilationCallback(std::function<DriverCompilationFn> C) { CompilationCB = C; } - llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCudaHost(); - llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCudaDevice(); + llvm::Expected<std::unique_ptr<CompilerInstance>> + CreateHost(OffloadType Type); + llvm::Expected<std::unique_ptr<CompilerInstance>> + CreateDevice(OffloadType Type); private: llvm::Expected<std::unique_ptr<CompilerInstance>> create(std::string TT, std::vector<const char *> &ClangArgv); - llvm::Expected<std::unique_ptr<CompilerInstance>> createCuda(bool device); + llvm::Expected<std::unique_ptr<CompilerInstance>> + createOffload(bool device, OffloadType Type = OffloadType::Detect); std::vector<const char *> UserArgs; std::optional<std::string> TargetTriple; llvm::StringRef OffloadArch; - llvm::StringRef CudaSDKPath; + llvm::StringRef DeviceSDKPath; + + std::string OffloadCUID; std::optional<std::function<DriverCompilationFn>> CompilationCB; }; @@ -154,9 +159,6 @@ class Interpreter { createWithDevice(std::unique_ptr<CompilerInstance> CI, std::unique_ptr<CompilerInstance> DCI, OffloadType Type = OffloadType::Detect); - static llvm::Expected<std::unique_ptr<Interpreter>> - createWithCUDA(std::unique_ptr<CompilerInstance> CI, - std::unique_ptr<CompilerInstance> DCI); const ASTContext &getASTContext() const; ASTContext &getASTContext(); diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 9bd711c24be26d..ae88c5e1a6346f 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -45,12 +45,14 @@ #include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ModuleCache.h" #include "clang/Serialization/ObjectFilePCHContainerReader.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" #include "llvm/IR/Module.h" #include "llvm/Support/Errc.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Process.h" #include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Host.h" @@ -304,19 +306,21 @@ IncrementalCompilerBuilder::CreateCpp() { } llvm::Expected<std::unique_ptr<CompilerInstance>> -IncrementalCompilerBuilder::createCuda(bool device) { +IncrementalCompilerBuilder::createOffload(bool device, OffloadType Type) { + if (Type == OffloadType::Detect) + return llvm::make_error<llvm::StringError>( + "Detecting the device vendor is not supported yet.", + llvm::inconvertibleErrorCode()); + + const bool HipEnabled = Type == OffloadType::HIP; std::vector<const char *> Argv; Argv.reserve(5 + 4 + UserArgs.size()); + Argv.push_back(HipEnabled ? "-xhip" : "-xcuda"); + Argv.push_back(device ? "--cuda-device-only" : "--cuda-host-only"); - Argv.push_back("-xcuda"); - if (device) - Argv.push_back("--cuda-device-only"); - else - Argv.push_back("--cuda-host-only"); - - std::string SDKPathArg = "--cuda-path="; - if (!CudaSDKPath.empty()) { - SDKPathArg += CudaSDKPath; + std::string SDKPathArg = HipEnabled ? "--rocm-path=" : "--cuda-path="; + if (!DeviceSDKPath.empty()) { + SDKPathArg += DeviceSDKPath; Argv.push_back(SDKPathArg.c_str()); } @@ -326,6 +330,12 @@ IncrementalCompilerBuilder::createCuda(bool device) { Argv.push_back(ArchArg.c_str()); } + if (OffloadCUID.empty()) + OffloadCUID = llvm::utohexstr(llvm::sys::Process::GetRandomNumber(), + /*LowerCase=*/true); + std::string CUIDArg = "-cuid=" + OffloadCUID; + Argv.push_back(CUIDArg.c_str()); + llvm::append_range(Argv, UserArgs); std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple(); @@ -333,13 +343,13 @@ IncrementalCompilerBuilder::createCuda(bool device) { } llvm::Expected<std::unique_ptr<CompilerInstance>> -IncrementalCompilerBuilder::CreateCudaDevice() { - return IncrementalCompilerBuilder::createCuda(true); +IncrementalCompilerBuilder::CreateDevice(OffloadType Type) { + return IncrementalCompilerBuilder::createOffload(/*device=*/true, Type); } llvm::Expected<std::unique_ptr<CompilerInstance>> -IncrementalCompilerBuilder::CreateCudaHost() { - return IncrementalCompilerBuilder::createCuda(false); +IncrementalCompilerBuilder::CreateHost(OffloadType Type) { + return IncrementalCompilerBuilder::createOffload(/*device=*/false, Type); } Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance, @@ -476,12 +486,6 @@ llvm::Expected<std::unique_ptr<Interpreter>> Interpreter::create( return std::move(Interp); } -llvm::Expected<std::unique_ptr<Interpreter>> -Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI, - std::unique_ptr<CompilerInstance> DCI) { - return createWithDevice(std::move(CI), std::move(DCI), OffloadType::CUDA); -} - llvm::Expected<std::unique_ptr<Interpreter>> Interpreter::createWithDevice(std::unique_ptr<CompilerInstance> CI, std::unique_ptr<CompilerInstance> DCI, diff --git a/clang/test/Interpreter/HIP/hip-not-supported.hip b/clang/test/Interpreter/HIP/hip-not-supported.hip new file mode 100644 index 00000000000000..add1769b837165 --- /dev/null +++ b/clang/test/Interpreter/HIP/hip-not-supported.hip @@ -0,0 +1,11 @@ +// Check that clang-repl sets up the HIP environment but reports that HIP +// offload binary generation is not supported yet. An explicit --offload-arch +// is passed so the test does not rely on GPU auto-detection. No device code +// is run, so the architecture is arbitrary. +// FIXME: Replace this with real HIP execution tests once the HIP device parser +// can generate offload binaries. + +// RUN: cat %s | clang-repl -hip --offload-arch=gfx1100 2>&1 | FileCheck %s + +__attribute__((device)) void f() {} +// CHECK: HIP offload binary generation is not supported yet. diff --git a/clang/test/Interpreter/HIP/lit.local.cfg b/clang/test/Interpreter/HIP/lit.local.cfg new file mode 100644 index 00000000000000..cc84168b237130 --- /dev/null +++ b/clang/test/Interpreter/HIP/lit.local.cfg @@ -0,0 +1,12 @@ +import ctypes + +if "host-supports-jit" not in config.available_features: + config.unsupported = True +elif "amdgpu-registered-target" not in config.available_features: + config.unsupported = True +else: + # clang-repl loads the HIP runtime on startup, so it must be available. + try: + ctypes.CDLL("libamdhip64.so") + except OSError: + config.unsupported = True diff --git a/clang/tools/clang-repl/ClangRepl.cpp b/clang/tools/clang-repl/ClangRepl.cpp index c9873540a5d66b..ec9cf94c89ad88 100644 --- a/clang/tools/clang-repl/ClangRepl.cpp +++ b/clang/tools/clang-repl/ClangRepl.cpp @@ -53,6 +53,8 @@ LLVM_ATTRIBUTE_USED int __lsan_is_turned_off() { return 1; } #define DEBUG_TYPE "clang-repl" static llvm::cl::opt<bool> CudaEnabled("cuda", llvm::cl::Hidden); +static llvm::cl::opt<bool> HipEnabled("hip", llvm::cl::Hidden); +static llvm::cl::opt<std::string> RocmPath("rocm-path", llvm::cl::Hidden); static llvm::cl::opt<std::string> CudaPath("cuda-path", llvm::cl::Hidden); static llvm::cl::opt<std::string> OffloadArch("offload-arch", llvm::cl::Hidden); static llvm::cl::OptionCategory OOPCategory("Out-of-process Execution Options"); @@ -310,24 +312,31 @@ int main(int argc, const char **argv) { IEB->SlabAllocateSize = *SizeOrErr; IEB->UseSharedMemory = UseSharedMemory; - std::unique_ptr<clang::CompilerInstance> DeviceCI; - if (CudaEnabled) { - if (!CudaPath.empty()) - CB.SetCudaSDK(CudaPath); + // If both -cuda and -hip are passed, the one that appears later wins. + bool UseHip = HipEnabled && (!CudaEnabled || HipEnabled.getPosition() > + CudaEnabled.getPosition()); + bool DeviceEnabled = HipEnabled || CudaEnabled; - if (OffloadArch.empty()) { - OffloadArch = "sm_35"; - } - CB.SetOffloadArch(OffloadArch); + clang::OffloadType OffloadKind = + UseHip ? clang::OffloadType::HIP : clang::OffloadType::CUDA; + std::string DevicePath = UseHip ? RocmPath : CudaPath; + llvm::StringRef DeviceOffloadArch = !OffloadArch.empty() + ? llvm::StringRef(OffloadArch) + : (UseHip ? "native" : "sm_35"); + + std::unique_ptr<clang::CompilerInstance> DeviceCI; - DeviceCI = ExitOnErr(CB.CreateCudaDevice()); + if (DeviceEnabled) { + CB.SetDeviceSDK(DevicePath); + CB.SetOffloadArch(DeviceOffloadArch); + DeviceCI = ExitOnErr(CB.CreateDevice(OffloadKind)); } // FIXME: Investigate if we could use runToolOnCodeWithArgs from tooling. It // can replace the boilerplate code for creation of the compiler instance. std::unique_ptr<clang::CompilerInstance> CI; - if (CudaEnabled) { - CI = ExitOnErr(CB.CreateCudaHost()); + if (DeviceEnabled) { + CI = ExitOnErr(CB.CreateHost(OffloadKind)); } else { CI = ExitOnErr(CB.CreateCpp()); } @@ -339,20 +348,21 @@ int main(int argc, const char **argv) { // Load any requested plugins. CI->LoadRequestedPlugins(); - if (CudaEnabled) + if (DeviceEnabled) DeviceCI->LoadRequestedPlugins(); std::unique_ptr<clang::Interpreter> Interp; - if (CudaEnabled) { - Interp = ExitOnErr( - clang::Interpreter::createWithCUDA(std::move(CI), std::move(DeviceCI))); + if (DeviceEnabled) { + Interp = ExitOnErr(clang::Interpreter::createWithDevice( + std::move(CI), std::move(DeviceCI), OffloadKind)); - if (CudaPath.empty()) { - ExitOnErr(Interp->LoadDynamicLibrary("libcudart.so")); + const char *RuntimeLib = UseHip ? "libamdhip64.so" : "libcudart.so"; + if (DevicePath.empty()) { + ExitOnErr(Interp->LoadDynamicLibrary(RuntimeLib)); } else { - auto CudaRuntimeLibPath = CudaPath + "/lib/libcudart.so"; - ExitOnErr(Interp->LoadDynamicLibrary(CudaRuntimeLibPath.c_str())); + std::string RuntimeLibPath = DevicePath + "/lib/" + RuntimeLib; + ExitOnErr(Interp->LoadDynamicLibrary(RuntimeLibPath.c_str())); } } else { Interp = diff --git a/clang/unittests/Interpreter/DeviceOffloadTest.cpp b/clang/unittests/Interpreter/DeviceOffloadTest.cpp index 039c919fe1e1e0..d3a84fd7bc54ee 100644 --- a/clang/unittests/Interpreter/DeviceOffloadTest.cpp +++ b/clang/unittests/Interpreter/DeviceOffloadTest.cpp @@ -62,10 +62,10 @@ TEST_F(DeviceOffloadTest, FirstDeviceModuleVerifies) { IncrementalCompilerBuilder CB; CB.SetCompilerArgs( {"-nocudainc", "-nocudalib", "-fverify-intermediate-code"}); - auto DeviceCI = llvm::cantFail(CB.CreateCudaDevice()); - auto HostCI = llvm::cantFail(CB.CreateCudaHost()); - auto Interp = llvm::cantFail(Interpreter::createWithCUDA( - std::move(HostCI), std::move(DeviceCI))); + auto DeviceCI = llvm::cantFail(CB.CreateDevice(OffloadType::CUDA)); + auto HostCI = llvm::cantFail(CB.CreateHost(OffloadType::CUDA)); + auto Interp = llvm::cantFail(Interpreter::createWithDevice( + std::move(HostCI), std::move(DeviceCI), OffloadType::CUDA)); llvm::cantFail(Interp->Parse("__attribute__((device)) void f() {}")); exit(0); }, @@ -79,12 +79,12 @@ TEST_F(DeviceOffloadTest, EmptyDeviceModule) { // Without the runtime headers and libdevice no CUDA toolkit is needed. IncrementalCompilerBuilder CB; CB.SetCompilerArgs({"-nocudainc", "-nocudalib"}); - auto DeviceCI = CB.CreateCudaDevice(); + auto DeviceCI = CB.CreateDevice(OffloadType::CUDA); ASSERT_THAT_EXPECTED(DeviceCI, llvm::Succeeded()); - auto HostCI = CB.CreateCudaHost(); + auto HostCI = CB.CreateHost(OffloadType::CUDA); ASSERT_THAT_EXPECTED(HostCI, llvm::Succeeded()); - auto Interp = - Interpreter::createWithCUDA(std::move(*HostCI), std::move(*DeviceCI)); + auto Interp = Interpreter::createWithDevice( + std::move(*HostCI), std::move(*DeviceCI), OffloadType::CUDA); ASSERT_THAT_EXPECTED(Interp, llvm::Succeeded()); // A host-only input leaves the device module without a function. Its PTX _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
