[clang] [clang-repl] Added -hip option (PR #231783)
Aditya Sinha via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 14 03:03:14 PDT 2026
https://github.com/AdityaSinha149 updated https://github.com/llvm/llvm-project/pull/231783
>From 94d9cdfce372ed8817590578fdb8d70cddebf369 Mon Sep 17 00:00:00 2001
From: AdityaSinha149 <adsinha at amd.com>
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 | 29 +++++++++++++++++++
clang/lib/Interpreter/DeviceOffload.h | 16 +++++++++-
clang/lib/Interpreter/Interpreter.cpp | 24 +++++++++++++--
4 files changed, 73 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..31fa20fff450d 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 {
@@ -36,6 +37,34 @@ 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;
+ 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;
+ }
+}
+
+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 46ee52425e9bb297916367f0914e8f3078570101 Mon Sep 17 00:00:00 2001
From: AdityaSinha149 <adsinha at amd.com>
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/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 +++++++++++--------
5 files changed, 105 insertions(+), 38 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/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 =
More information about the cfe-commits
mailing list