https://github.com/AdityaSinha149 updated 
https://github.com/llvm/llvm-project/pull/231783

>From 292317964da58d99a36c6dc4f8478e050d480d29 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         | 56 ++++++++++++-------
 .../Interpreter/HIP/hip-not-supported.hip     | 10 ++++
 clang/test/Interpreter/HIP/lit.local.cfg      | 12 ++++
 clang/tools/clang-repl/ClangRepl.cpp          | 48 +++++++++-------
 .../Interpreter/DeviceOffloadTest.cpp         | 29 +++++++---
 6 files changed, 119 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 64f02b797c204..64dee1cf80db8 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 9bd711c24be26..c910c0e4b1c8e 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"
@@ -76,6 +78,18 @@ GetCC1Arguments(DiagnosticsEngine *Diagnostics,
                                    "Driver initialization failed. "
                                    "Unable to create a driver job");
 
+  if (Compilation->getArgs().hasArg(options::OPT_offload_arch_EQ)) {
+    unsigned NumCompileJobs =
+        llvm::count_if(Jobs, [](const driver::Command &C) {
+          return llvm::StringRef(C.getCreator().getName()) == "clang";
+        });
+    if (NumCompileJobs > 1)
+      return llvm::createStringError(
+          llvm::errc::not_supported,
+          "Multiple device architectures are not supported. Pass a single "
+          "--offload-arch");
+  }
+
   // The one job we find should be to invoke clang again.
   const driver::Command *Cmd = &*Jobs.begin();
   if (llvm::StringRef(Cmd->getCreator().getName()) != "clang")
@@ -304,19 +318,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 +342,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 +355,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 +498,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 0000000000000..5e6f7d9035b34
--- /dev/null
+++ b/clang/test/Interpreter/HIP/hip-not-supported.hip
@@ -0,0 +1,10 @@
+// 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: not clang-repl -hip --offload-arch=gfx1100 "__attribute__((device)) 
void f() {}" 2>&1 | FileCheck %s --implicit-check-not=error:
+
+// CHECK: error: 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..ec9cf94c89ad8 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 039c919fe1e1e..f3b7ddf837cde 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
@@ -101,4 +101,17 @@ TEST_F(DeviceOffloadTest, EmptyDeviceModule) {
   EXPECT_TRUE((*Buf)->getBuffer().contains(".target"));
 }
 
+TEST(DeviceOffloadBuilderTest, MultipleOffloadArchsAreRejected) {
+  // The driver creates one compile job per architecture. Only one can be used,
+  // so this must be reported instead of silently using the first one.
+  IncrementalCompilerBuilder CB;
+  CB.SetCompilerArgs({"--offload-arch=gfx1100", "--offload-arch=gfx90a",
+                      "-nogpulib", "-nogpuinc"});
+  auto DeviceCI = CB.CreateDevice(OffloadType::HIP);
+  EXPECT_THAT_EXPECTED(
+      DeviceCI,
+      llvm::FailedWithMessage("Multiple device architectures are not "
+                              "supported. Pass a single --offload-arch"));
+}
+
 } // end anonymous namespace

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to