https://github.com/AdityaSinha149 updated https://github.com/llvm/llvm-project/pull/231783
>From ebec042c12844bb47fd08531b341c2aac3401ecb Mon Sep 17 00:00:00 2001 From: AdityaSinha149 <[email protected]> Date: Tue, 13 Oct 2026 11:57:25 +0530 Subject: [PATCH 1/2] [clang-repl] Add OffloadType enum and HIP device parser skeleton --- clang/include/clang/Interpreter/Interpreter.h | 8 ++++++ clang/lib/Interpreter/DeviceOffload.cpp | 27 +++++++++++++++++++ clang/lib/Interpreter/DeviceOffload.h | 16 ++++++++++- clang/lib/Interpreter/Interpreter.cpp | 24 ++++++++++++++--- 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index a598574b417c0..64f02b797c204 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -46,6 +46,10 @@ class Decl; class IncrementalParser; class IncrementalDeviceParser; +/// The device language to offload to. \c Detect selects the vendor of the +/// device available on the machine. +enum class OffloadType { Detect, CUDA, HIP }; + /// Create a pre-configured \c CompilerInstance for incremental processing. class IncrementalCompilerBuilder { using DriverCompilationFn = llvm::Error(const driver::Compilation &); @@ -147,6 +151,10 @@ class Interpreter { create(std::unique_ptr<CompilerInstance> CI, std::unique_ptr<IncrementalExecutorBuilder> IEB = nullptr); static llvm::Expected<std::unique_ptr<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); diff --git a/clang/lib/Interpreter/DeviceOffload.cpp b/clang/lib/Interpreter/DeviceOffload.cpp index e5887bc9c8841..3f416a1918e24 100644 --- a/clang/lib/Interpreter/DeviceOffload.cpp +++ b/clang/lib/Interpreter/DeviceOffload.cpp @@ -36,6 +36,33 @@ IncrementalDeviceParser::IncrementalDeviceParser( IncrementalDeviceParser::~IncrementalDeviceParser() {} +IncrementalHIPDeviceParser::IncrementalHIPDeviceParser( + CompilerInstance &DeviceInstance, CompilerInstance &HostInstance, + IncrementalAction *DeviceAct, + llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS, + llvm::Error &Err, std::list<PartialTranslationUnit> &PTUs) + : IncrementalDeviceParser(DeviceInstance, HostInstance, DeviceAct, FS, Err, + PTUs) { + if (Err) + return; + StringRef Arch = TargetOpts.CPU; + if (!Arch.starts_with("gfx")) { + Err = llvm::joinErrors(std::move(Err), llvm::make_error<llvm::StringError>( + "Invalid HIP architecture", + llvm::inconvertibleErrorCode())); + return; + } +} + +llvm::Error IncrementalHIPDeviceParser::GenerateOffloadBinary() { + // FIXME: Generate the HSACO and bundle it for the host compilation. + return llvm::make_error<llvm::StringError>( + "HIP offload binary generation is not supported yet.", + llvm::inconvertibleErrorCode()); +} + +IncrementalHIPDeviceParser::~IncrementalHIPDeviceParser() {} + IncrementalCUDADeviceParser::IncrementalCUDADeviceParser( CompilerInstance &DeviceInstance, CompilerInstance &HostInstance, IncrementalAction *DeviceAct, diff --git a/clang/lib/Interpreter/DeviceOffload.h b/clang/lib/Interpreter/DeviceOffload.h index fc780ef64add8..0275c0e10cda8 100644 --- a/clang/lib/Interpreter/DeviceOffload.h +++ b/clang/lib/Interpreter/DeviceOffload.h @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines a base class required for offloading to devices. +// This file defines the classes required for offloading to devices. // //===----------------------------------------------------------------------===// @@ -44,6 +44,20 @@ class IncrementalDeviceParser : public IncrementalParser { const TargetOptions &TargetOpts; }; +class IncrementalHIPDeviceParser : public IncrementalDeviceParser { + +public: + IncrementalHIPDeviceParser( + CompilerInstance &DeviceInstance, CompilerInstance &HostInstance, + IncrementalAction *DeviceAct, + llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS, + llvm::Error &Err, std::list<PartialTranslationUnit> &PTUs); + + llvm::Error GenerateOffloadBinary() override; + + ~IncrementalHIPDeviceParser() override; +}; + class IncrementalCUDADeviceParser : public IncrementalDeviceParser { public: diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index a8e54d62864b5..9bd711c24be26 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -479,6 +479,18 @@ llvm::Expected<std::unique_ptr<Interpreter>> Interpreter::create( 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, + OffloadType Type) { + if (Type == OffloadType::Detect) + return llvm::make_error<llvm::StringError>( + "Detecting the device vendor is not supported yet.", + llvm::inconvertibleErrorCode()); + // avoid writing fat binary to disk using an in-memory virtual file system llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> IMVFS = std::make_unique<llvm::vfs::InMemoryFileSystem>(); @@ -515,9 +527,15 @@ Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI, Interp->DeviceCI = std::move(DCI); - auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>( - *Interp->DeviceCI, *Interp->getCompilerInstance(), - Interp->DeviceAct.get(), IMVFS, Err, Interp->PTUs); + std::unique_ptr<IncrementalDeviceParser> DeviceParser; + if (Type == OffloadType::HIP) + DeviceParser = std::make_unique<IncrementalHIPDeviceParser>( + *Interp->DeviceCI, *Interp->getCompilerInstance(), + Interp->DeviceAct.get(), IMVFS, Err, Interp->PTUs); + else + DeviceParser = std::make_unique<IncrementalCUDADeviceParser>( + *Interp->DeviceCI, *Interp->getCompilerInstance(), + Interp->DeviceAct.get(), IMVFS, Err, Interp->PTUs); if (Err) return std::move(Err); >From 98b3ca7292e242d99cf3f8b57cd22a1fa984ab67 Mon Sep 17 00:00:00 2001 From: AdityaSinha149 <[email protected]> Date: Wed, 14 Oct 2026 13:00:27 +0530 Subject: [PATCH 2/2] [clang-repl] Added -hip option --- clang/include/clang/Interpreter/Interpreter.h | 33 +++++++++++-- clang/lib/Interpreter/DeviceOffload.cpp | 14 ++++-- clang/lib/Interpreter/Interpreter.cpp | 39 +++++++++------ .../Interpreter/HIP/hip-not-supported.hip | 11 +++++ clang/test/Interpreter/HIP/lit.local.cfg | 12 +++++ clang/tools/clang-repl/ClangRepl.cpp | 48 +++++++++++-------- 6 files changed, 114 insertions(+), 43 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 64f02b797c204..abd8868ba9d6d 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -69,29 +69,52 @@ class IncrementalCompilerBuilder { // Offload options void SetOffloadArch(llvm::StringRef Arch) { OffloadArch = Arch; }; - // CUDA specific - void SetCudaSDK(llvm::StringRef path) { CudaSDKPath = path; }; + void SetDeviceSDK(OffloadType Type, llvm::StringRef Path) { + if (Type == OffloadType::HIP) + RocmSDKPath = Path; + else if (Type == OffloadType::CUDA) + CudaSDKPath = Path; + } + + // Retained for compatibility with existing CUDA callers. + void SetCudaSDK(llvm::StringRef Path) { + SetDeviceSDK(OffloadType::CUDA, 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); + + // Retained for compatibility with existing CUDA callers. + llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCudaHost() { + return CreateHost(OffloadType::CUDA); + } + llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCudaDevice() { + return CreateDevice(OffloadType::CUDA); + } 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 RocmSDKPath; llvm::StringRef CudaSDKPath; + std::string OffloadCUID; + std::optional<std::function<DriverCompilationFn>> CompilationCB; }; diff --git a/clang/lib/Interpreter/DeviceOffload.cpp b/clang/lib/Interpreter/DeviceOffload.cpp index 3f416a1918e24..dcbcc6c06906f 100644 --- a/clang/lib/Interpreter/DeviceOffload.cpp +++ b/clang/lib/Interpreter/DeviceOffload.cpp @@ -22,6 +22,7 @@ #include "llvm/IR/Module.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/TargetParser/Triple.h" namespace clang { @@ -45,11 +46,14 @@ IncrementalHIPDeviceParser::IncrementalHIPDeviceParser( PTUs) { if (Err) return; - StringRef Arch = TargetOpts.CPU; - if (!Arch.starts_with("gfx")) { - Err = llvm::joinErrors(std::move(Err), llvm::make_error<llvm::StringError>( - "Invalid HIP architecture", - llvm::inconvertibleErrorCode())); + // The GPU architecture is encoded in the triple (e.g. amdgpu11.00-amd-amdhsa + // for gfx1100) and not in the target CPU. + if (!llvm::Triple(TargetOpts.Triple).isAMDGCN()) { + Err = llvm::joinErrors( + std::move(Err), + llvm::make_error<llvm::StringError>( + "Invalid HIP architecture for target '" + TargetOpts.Triple + "'", + llvm::inconvertibleErrorCode())); return; } } diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index 9bd711c24be26..d6662c0217aff 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,22 @@ 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; + llvm::StringRef SDKPath = HipEnabled ? RocmSDKPath : CudaSDKPath; + std::string SDKPathArg = HipEnabled ? "--rocm-path=" : "--cuda-path="; + if (!SDKPath.empty()) { + SDKPathArg += SDKPath; Argv.push_back(SDKPathArg.c_str()); } @@ -326,6 +331,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 +344,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, 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 0000000000000..add1769b83716 --- /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 0000000000000..cc84168b23713 --- /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 c9873540a5d66..3782c0b7f1f75 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(OffloadKind, 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 = _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
