Repository: llvm/llvm-project
Pull request #136404: [clang-repl] : Fix clang-repl crash with --cuda flag
Author: login: anutosh491
Labels: name: clang
description: Clang issues not falling into any other category
name: clang:frontend
description: Language frontend issues, e.g. anything involving "Sema"
Created: 2025-04-19T04:33:49Z | Merged: 2025-04-26T06:46:27Z



`clang-repl --cuda` was previously crashing with a segmentation fault, instead of reporting a clean error
```
(base) anutosh491@Anutoshs-MacBook-Air bin % ./clang-repl --cuda
#0 0x0000000111da4fbc llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/local/libexec/llvm-20/lib/libLLVM.dylib+0x150fbc)
#1 0x0000000111da31dc llvm::sys::RunSignalHandlers() (/opt/local/libexec/llvm-20/lib/libLLVM.dylib+0x14f1dc)
#2 0x0000000111da5628 SignalHandler(int) (/opt/local/libexec/llvm-20/lib/libLLVM.dylib+0x151628)
#3 0x000000019b242de4 (/usr/lib/system/libsystem_platform.dylib+0x180482de4)
#4 0x0000000107f638d0 clang::IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(std::__1::unique_ptr<clang::CompilerInstance, std::__1::default_delete<clang::CompilerInstance>>, clang::CompilerInstance&, llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>, llvm::Error&, std::__1::list<clang::PartialTranslationUnit, std::__1::allocator<clang::PartialTranslationUnit>> const&) (/opt/local/libexec/llvm-20/lib/libclang-cpp.dylib+0x216b8d0)
#5 0x0000000107f638d0 clang::IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(std::__1::unique_ptr<clang::CompilerInstance, std::__1::default_delete<clang::CompilerInstance>>, clang::CompilerInstance&, llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>, llvm::Error&, std::__1::list<clang::PartialTranslationUnit, std::__1::allocator<clang::PartialTranslationUnit>> const&) (/opt/local/libexec/llvm-20/lib/libclang-cpp.dylib+0x216b8d0)
#6 0x0000000107f6bac8 clang::Interpreter::createWithCUDA(std::__1::unique_ptr<clang::CompilerInstance, std::__1::default_delete<clang::CompilerInstance>>, std::__1::unique_ptr<clang::CompilerInstance, std::__1::default_delete<clang::CompilerInstance>>) (/opt/local/libexec/llvm-20/lib/libclang-cpp.dylib+0x2173ac8)
#7 0x000000010206f8a8 main (/opt/local/libexec/llvm-20/bin/clang-repl+0x1000038a8)
#8 0x000000019ae8c274 
Segmentation fault: 11
```


The underlying issue was that the `DeviceCompilerInstance` (used for device-side CUDA compilation) was never initialized with a `Sema`, which is required before constructing the `IncrementalCUDADeviceParser`. 

https://github.com/llvm/llvm-project/blob/89687e6f383b742a3c6542dc673a84d9f82d02de/clang/lib/Interpreter/DeviceOffload.cpp#L32

https://github.com/llvm/llvm-project/blob/89687e6f383b742a3c6542dc673a84d9f82d02de/clang/lib/Interpreter/IncrementalParser.cpp#L31

Unlike the host-side `CompilerInstance` which runs `ExecuteAction` inside the Interpreter constructor (thereby setting up Sema), the device-side CI was passed into the parser uninitialized, leading to an assertion or crash when accessing its internals.

To fix this, I refactored the `Interpreter::create` method to include an optional `DeviceCI` parameter. If provided, we know we need to take care of this instance too. Only then do we construct the `IncrementalCUDADeviceParser`.




Diff:
diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index b1b63aedf86ab..56213f88b9e30 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -41,6 +41,7 @@ class CXXRecordDecl;
 class Decl;
 class IncrementalExecutor;
 class IncrementalParser;
+class IncrementalCUDADeviceParser;
 
 /// Create a pre-configured \c CompilerInstance for incremental processing.
 class IncrementalCompilerBuilder {
@@ -93,7 +94,10 @@ class Interpreter {
   std::unique_ptr<IncrementalExecutor> IncrExecutor;
 
   // An optional parser for CUDA offloading
-  std::unique_ptr<IncrementalParser> DeviceParser;
+  std::unique_ptr<IncrementalCUDADeviceParser> DeviceParser;
+
+  // An optional action for CUDA offloading
+  std::unique_ptr<IncrementalAction> DeviceAct;
 
   /// List containing information about each incrementally parsed piece of code.
   std::list<PartialTranslationUnit> PTUs;
@@ -175,10 +179,11 @@ class Interpreter {
   llvm::Expected<Expr *> ExtractValueFromExpr(Expr *E);
   llvm::Expected<llvm::orc::ExecutorAddr> CompileDtorCall(CXXRecordDecl *CXXRD);
 
-  CodeGenerator *getCodeGen() const;
-  std::unique_ptr<llvm::Module> GenModule();
+  CodeGenerator *getCodeGen(IncrementalAction *Action = nullptr) const;
+  std::unique_ptr<llvm::Module> GenModule(IncrementalAction *Action = nullptr);
   PartialTranslationUnit &RegisterPTU(TranslationUnitDecl *TU,
-                                      std::unique_ptr<llvm::Module> M = {});
+                                      std::unique_ptr<llvm::Module> M = {},
+                                      IncrementalAction *Action = nullptr);
 
   // A cache for the compiled destructors used to for de-allocation of managed
   // clang::Values.
diff --git a/clang/lib/Interpreter/DeviceOffload.cpp b/clang/lib/Interpreter/DeviceOffload.cpp
index 1999d63d1aa04..7d0125403ea52 100644
--- a/clang/lib/Interpreter/DeviceOffload.cpp
+++ b/clang/lib/Interpreter/DeviceOffload.cpp
@@ -31,10 +31,9 @@ IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(
     llvm::Error &Err, const std::list<PartialTranslationUnit> &PTUs)
     : IncrementalParser(*DeviceInstance, Err), PTUs(PTUs), VFS(FS),
       CodeGenOpts(HostInstance.getCodeGenOpts()),
-      TargetOpts(HostInstance.getTargetOpts()) {
+      TargetOpts(DeviceInstance->getTargetOpts()) {
   if (Err)
     return;
-  DeviceCI = std::move(DeviceInstance);
   StringRef Arch = TargetOpts.CPU;
   if (!Arch.starts_with("sm_") || Arch.substr(3).getAsInteger(10, SMVersion)) {
     Err = llvm::joinErrors(std::move(Err), llvm::make_error<llvm::StringError>(
@@ -42,34 +41,7 @@ IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(
                                                llvm::inconvertibleErrorCode()));
     return;
   }
-}
-
-llvm::Expected<TranslationUnitDecl *>
-IncrementalCUDADeviceParser::Parse(llvm::StringRef Input) {
-  auto PTU = IncrementalParser::Parse(Input);
-  if (!PTU)
-    return PTU.takeError();
-
-  auto PTX = GeneratePTX();
-  if (!PTX)
-    return PTX.takeError();
-
-  auto Err = GenerateFatbinary();
-  if (Err)
-    return std::move(Err);
-
-  std::string FatbinFileName =
-      "/incr_module_" + std::to_string(PTUs.size()) + ".fatbin";
-  VFS->addFile(FatbinFileName, 0,
-               llvm::MemoryBuffer::getMemBuffer(
-                   llvm::StringRef(FatbinContent.data(), FatbinContent.size()),
-                   "", false));
-
-  CodeGenOpts.CudaGpuBinaryFileName = FatbinFileName;
-
-  FatbinContent.clear();
-
-  return PTU;
+  DeviceCI = std::move(DeviceInstance);
 }
 
 llvm::Expected<llvm::StringRef> IncrementalCUDADeviceParser::GeneratePTX() {
@@ -172,6 +144,19 @@ llvm::Error IncrementalCUDADeviceParser::GenerateFatbinary() {
 
   FatbinContent.append(PTXCode.begin(), PTXCode.end());
 
+  const PartialTranslationUnit &PTU = PTUs.back();
+
+  std::string FatbinFileName = "/" + PTU.TheModule->getName().str() + ".fatbin";
+
+  VFS->addFile(FatbinFileName, 0,
+               llvm::MemoryBuffer::getMemBuffer(
+                   llvm::StringRef(FatbinContent.data(), FatbinContent.size()),
+                   "", false));
+
+  CodeGenOpts.CudaGpuBinaryFileName = FatbinFileName;
+
+  FatbinContent.clear();
+
   return llvm::Error::success();
 }
 
diff --git a/clang/lib/Interpreter/DeviceOffload.h b/clang/lib/Interpreter/DeviceOffload.h
index b9a1acab004c3..43645033c4840 100644
--- a/clang/lib/Interpreter/DeviceOffload.h
+++ b/clang/lib/Interpreter/DeviceOffload.h
@@ -33,8 +33,6 @@ class IncrementalCUDADeviceParser : public IncrementalParser {
       llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS,
       llvm::Error &Err, const std::list<PartialTranslationUnit> &PTUs);
 
-  llvm::Expected<TranslationUnitDecl *> Parse(llvm::StringRef Input) override;
-
   // Generate PTX for the last PTU.
   llvm::Expected<llvm::StringRef> GeneratePTX();
 
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index f8c8d0a425659..f91563dd0378c 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -481,20 +481,34 @@ Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI,
   OverlayVFS->pushOverlay(IMVFS);
   CI->createFileManager(OverlayVFS);
 
-  auto Interp = Interpreter::create(std::move(CI));
-  if (auto E = Interp.takeError())
-    return std::move(E);
+  llvm::Expected<std::unique_ptr<Interpreter>> InterpOrErr =
+      Interpreter::create(std::move(CI));
+  if (!InterpOrErr)
+    return InterpOrErr;
+
+  std::unique_ptr<Interpreter> Interp = std::move(*InterpOrErr);
 
   llvm::Error Err = llvm::Error::success();
-  auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>(
-      std::move(DCI), *(*Interp)->getCompilerInstance(), IMVFS, Err,
-      (*Interp)->PTUs);
+  llvm::LLVMContext &LLVMCtx = *Interp->TSCtx->getContext();
+
+  auto DeviceAct =
+      std::make_unique<IncrementalAction>(*DCI, LLVMCtx, Err, *Interp);
+
   if (Err)
     return std::move(Err);
 
-  (*Interp)->DeviceParser = std::move(DeviceParser);
+  Interp->DeviceAct = std::move(DeviceAct);
+
+  DCI->ExecuteAction(*Interp->DeviceAct);
+
+  auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>(
+      std::move(DCI), *Interp->getCompilerInstance(), IMVFS, Err, Interp->PTUs);
+
+  if (Err)
+    return std::move(Err);
 
-  return Interp;
+  Interp->DeviceParser = std::move(DeviceParser);
+  return std::move(Interp);
 }
 
 const CompilerInstance *Interpreter::getCompilerInstance() const {
@@ -532,15 +546,17 @@ size_t Interpreter::getEffectivePTUSize() const {
 
 PartialTranslationUnit &
 Interpreter::RegisterPTU(TranslationUnitDecl *TU,
-                         std::unique_ptr<llvm::Module> M /*={}*/) {
+                         std::unique_ptr<llvm::Module> M /*={}*/,
+                         IncrementalAction *Action) {
   PTUs.emplace_back(PartialTranslationUnit());
   PartialTranslationUnit &LastPTU = PTUs.back();
   LastPTU.TUPart = TU;
 
   if (!M)
-    M = GenModule();
+    M = GenModule(Action);
 
-  assert((!getCodeGen() || M) && "Must have a llvm::Module at this point");
+  assert((!getCodeGen(Action) || M) &&
+         "Must have a llvm::Module at this point");
 
   LastPTU.TheModule = std::move(M);
   LLVM_DEBUG(llvm::dbgs() << "compile-ptu " << PTUs.size() - 1
@@ -560,6 +576,16 @@ Interpreter::Parse(llvm::StringRef Code) {
     llvm::Expected<TranslationUnitDecl *> DeviceTU = DeviceParser->Parse(Code);
     if (auto E = DeviceTU.takeError())
       return std::move(E);
+
+    RegisterPTU(*DeviceTU, nullptr, DeviceAct.get());
+
+    llvm::Expected<llvm::StringRef> PTX = DeviceParser->GeneratePTX();
+    if (!PTX)
+      return PTX.takeError();
+
+    llvm::Error Err = DeviceParser->GenerateFatbinary();
+    if (Err)
+      return std::move(Err);
   }
 
   // Tell the interpreter sliently ignore unused expressions since value
@@ -736,9 +762,10 @@ llvm::Error Interpreter::LoadDynamicLibrary(const char *name) {
   return llvm::Error::success();
 }
 
-std::unique_ptr<llvm::Module> Interpreter::GenModule() {
+std::unique_ptr<llvm::Module>
+Interpreter::GenModule(IncrementalAction *Action) {
   static unsigned ID = 0;
-  if (CodeGenerator *CG = getCodeGen()) {
+  if (CodeGenerator *CG = getCodeGen(Action)) {
     // Clang's CodeGen is designed to work with a single llvm::Module. In many
     // cases for convenience various CodeGen parts have a reference to the
     // llvm::Module (TheModule or Module) which does not change when a new
@@ -760,8 +787,10 @@ std::unique_ptr<llvm::Module> Interpreter::GenModule() {
   return nullptr;
 }
 
-CodeGenerator *Interpreter::getCodeGen() const {
-  FrontendAction *WrappedAct = Act->getWrapped();
+CodeGenerator *Interpreter::getCodeGen(IncrementalAction *Action) const {
+  if (!Action)
+    Action = Act.get();
+  FrontendAction *WrappedAct = Action->getWrapped();
   if (!WrappedAct->hasIRSupport())
     return nullptr;
   return static_cast<CodeGenAction *>(WrappedAct)->getCodeGenerator();


Reviews:
user: login: anutosh491
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-19T04:47:11Z
user: login: vgvassilev
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-19T06:42:51Z
user: login: anutosh491
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-19T06:44:08Z
user: login: vgvassilev
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-19T06:45:29Z
user: login: anutosh491
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-19T06:51:07Z
user: login: anutosh491
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-19T06:55:49Z
user: login: vgvassilev
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-19T07:00:48Z
user: login: anutosh491
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-19T08:42:47Z
user: login: vgvassilev
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-19T17:55:43Z
user: login: vgvassilev
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-19T17:57:38Z
user: login: anutosh491
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-19T19:05:59Z
user: login: anutosh491
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T13:08:28Z
user: login: anutosh491
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T13:15:19Z
user: login: anutosh491
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T13:23:42Z
user: login: vgvassilev
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T13:50:39Z
user: login: anutosh491
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T13:56:33Z
user: login: anutosh491
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T14:01:43Z
user: login: vgvassilev
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T14:48:42Z
user: login: vgvassilev
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T14:53:22Z
user: login: anutosh491
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T15:15:59Z
user: login: anutosh491
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T15:26:52Z
user: login: vgvassilev
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T20:06:29Z
user: login: anutosh491
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-25T09:46:45Z
user: login: anutosh491
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-25T10:07:48Z
user: login: vgvassilev
body: LGTM!
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T19:40:04Z

Review comments:
diff_hunk: @@ -451,13 +451,44 @@ const char *const Runtimes = R"(
 )";
 
 llvm::Expected<std::unique_ptr<Interpreter>>
-Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
+Interpreter::create(std::unique_ptr<CompilerInstance> CI,
+                    std::unique_ptr<CompilerInstance> DeviceCI) {
   llvm::Error Err = llvm::Error::success();
   auto Interp =
       std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
   if (Err)
     return std::move(Err);
 
+  if (DeviceCI) {
+    // auto DeviceLLVMCtx = std::make_unique<llvm::LLVMContext>();
+    // auto DeviceTSCtx =
+    //     std::make_unique<llvm::orc::ThreadSafeContext>(std::move(DeviceLLVMCtx));
+
+    // llvm::Error DeviceErr = llvm::Error::success();
+    // llvm::ErrorAsOutParameter EAO(&DeviceErr);
+
+    // auto DeviceAct = std::make_unique<IncrementalAction>(
+    //     *DeviceCI, *DeviceTSCtx->getContext(), DeviceErr, *Interp);
+
+    // if (DeviceErr)
+    //   return std::move(DeviceErr);
+
+    // DeviceCI->ExecuteAction(*DeviceAct);
+    DeviceCI->ExecuteAction(*Interp->Act);
path: clang/lib/Interpreter/Interpreter.cpp
user: login: anutosh491
body: Here,
I am not 100% sure how tightly coupled is an `Action` with a `CompilerInstance`. So I thought maybe we would need a new "DeviceAct" here rather than using the Host CI's Action.

So I wrote that and commented it out !

If that's not required, I'll get rid of whatever we don't want.
created_at: 2025-04-19T04:47:11Z
author_association: MEMBER
diff_hunk: @@ -451,13 +451,44 @@ const char *const Runtimes = R"(
 )";
 
 llvm::Expected<std::unique_ptr<Interpreter>>
-Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
+Interpreter::create(std::unique_ptr<CompilerInstance> CI,
+                    std::unique_ptr<CompilerInstance> DeviceCI) {
   llvm::Error Err = llvm::Error::success();
   auto Interp =
       std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
   if (Err)
     return std::move(Err);
 
+  if (DeviceCI) {
+    // auto DeviceLLVMCtx = std::make_unique<llvm::LLVMContext>();
+    // auto DeviceTSCtx =
+    //     std::make_unique<llvm::orc::ThreadSafeContext>(std::move(DeviceLLVMCtx));
+
+    // llvm::Error DeviceErr = llvm::Error::success();
+    // llvm::ErrorAsOutParameter EAO(&DeviceErr);
+
+    // auto DeviceAct = std::make_unique<IncrementalAction>(
+    //     *DeviceCI, *DeviceTSCtx->getContext(), DeviceErr, *Interp);
+
+    // if (DeviceErr)
+    //   return std::move(DeviceErr);
+
+    // DeviceCI->ExecuteAction(*DeviceAct);
+    DeviceCI->ExecuteAction(*Interp->Act);
path: clang/lib/Interpreter/Interpreter.cpp
user: login: vgvassilev
body: I think we can convert that into a fixme. If it works without a specific device action we should probably leave it as it is.
created_at: 2025-04-19T06:42:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -451,13 +451,44 @@ const char *const Runtimes = R"(
 )";
 
 llvm::Expected<std::unique_ptr<Interpreter>>
-Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
+Interpreter::create(std::unique_ptr<CompilerInstance> CI,
+                    std::unique_ptr<CompilerInstance> DeviceCI) {
   llvm::Error Err = llvm::Error::success();
   auto Interp =
       std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
   if (Err)
     return std::move(Err);
 
+  if (DeviceCI) {
+    // auto DeviceLLVMCtx = std::make_unique<llvm::LLVMContext>();
+    // auto DeviceTSCtx =
+    //     std::make_unique<llvm::orc::ThreadSafeContext>(std::move(DeviceLLVMCtx));
+
+    // llvm::Error DeviceErr = llvm::Error::success();
+    // llvm::ErrorAsOutParameter EAO(&DeviceErr);
+
+    // auto DeviceAct = std::make_unique<IncrementalAction>(
+    //     *DeviceCI, *DeviceTSCtx->getContext(), DeviceErr, *Interp);
+
+    // if (DeviceErr)
+    //   return std::move(DeviceErr);
+
+    // DeviceCI->ExecuteAction(*DeviceAct);
+    DeviceCI->ExecuteAction(*Interp->Act);
path: clang/lib/Interpreter/Interpreter.cpp
user: login: anutosh491
body: Yes, what we have currently should do the job !

Thanks for the reply.
created_at: 2025-04-19T06:44:08Z
author_association: MEMBER
diff_hunk: @@ -451,13 +451,44 @@ const char *const Runtimes = R"(
 )";
 
 llvm::Expected<std::unique_ptr<Interpreter>>
-Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
+Interpreter::create(std::unique_ptr<CompilerInstance> CI,
+                    std::unique_ptr<CompilerInstance> DeviceCI) {
   llvm::Error Err = llvm::Error::success();
   auto Interp =
       std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
   if (Err)
     return std::move(Err);
 
+  if (DeviceCI) {
+    // auto DeviceLLVMCtx = std::make_unique<llvm::LLVMContext>();
+    // auto DeviceTSCtx =
+    //     std::make_unique<llvm::orc::ThreadSafeContext>(std::move(DeviceLLVMCtx));
+
+    // llvm::Error DeviceErr = llvm::Error::success();
+    // llvm::ErrorAsOutParameter EAO(&DeviceErr);
+
+    // auto DeviceAct = std::make_unique<IncrementalAction>(
+    //     *DeviceCI, *DeviceTSCtx->getContext(), DeviceErr, *Interp);
+
+    // if (DeviceErr)
+    //   return std::move(DeviceErr);
+
+    // DeviceCI->ExecuteAction(*DeviceAct);
+    DeviceCI->ExecuteAction(*Interp->Act);
path: clang/lib/Interpreter/Interpreter.cpp
user: login: vgvassilev
body: Do you have a platform where you can test this?
created_at: 2025-04-19T06:45:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -451,13 +451,44 @@ const char *const Runtimes = R"(
 )";
 
 llvm::Expected<std::unique_ptr<Interpreter>>
-Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
+Interpreter::create(std::unique_ptr<CompilerInstance> CI,
+                    std::unique_ptr<CompilerInstance> DeviceCI) {
   llvm::Error Err = llvm::Error::success();
   auto Interp =
       std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
   if (Err)
     return std::move(Err);
 
+  if (DeviceCI) {
+    // auto DeviceLLVMCtx = std::make_unique<llvm::LLVMContext>();
+    // auto DeviceTSCtx =
+    //     std::make_unique<llvm::orc::ThreadSafeContext>(std::move(DeviceLLVMCtx));
+
+    // llvm::Error DeviceErr = llvm::Error::success();
+    // llvm::ErrorAsOutParameter EAO(&DeviceErr);
+
+    // auto DeviceAct = std::make_unique<IncrementalAction>(
+    //     *DeviceCI, *DeviceTSCtx->getContext(), DeviceErr, *Interp);
+
+    // if (DeviceErr)
+    //   return std::move(DeviceErr);
+
+    // DeviceCI->ExecuteAction(*DeviceAct);
+    DeviceCI->ExecuteAction(*Interp->Act);
path: clang/lib/Interpreter/Interpreter.cpp
user: login: anutosh491
body: Well sadly I can't test the whole thing end to end being on macos, but at least this block should end up being platform independent is what I think (Using DeviceACT or ACT should work similarly)
created_at: 2025-04-19T06:51:07Z
author_association: MEMBER
diff_hunk: @@ -451,13 +451,44 @@ const char *const Runtimes = R"(
 )";
 
 llvm::Expected<std::unique_ptr<Interpreter>>
-Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
+Interpreter::create(std::unique_ptr<CompilerInstance> CI,
+                    std::unique_ptr<CompilerInstance> DeviceCI) {
   llvm::Error Err = llvm::Error::success();
   auto Interp =
       std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
   if (Err)
     return std::move(Err);
 
+  if (DeviceCI) {
+    // auto DeviceLLVMCtx = std::make_unique<llvm::LLVMContext>();
+    // auto DeviceTSCtx =
+    //     std::make_unique<llvm::orc::ThreadSafeContext>(std::move(DeviceLLVMCtx));
+
+    // llvm::Error DeviceErr = llvm::Error::success();
+    // llvm::ErrorAsOutParameter EAO(&DeviceErr);
+
+    // auto DeviceAct = std::make_unique<IncrementalAction>(
+    //     *DeviceCI, *DeviceTSCtx->getContext(), DeviceErr, *Interp);
+
+    // if (DeviceErr)
+    //   return std::move(DeviceErr);
+
+    // DeviceCI->ExecuteAction(*DeviceAct);
+    DeviceCI->ExecuteAction(*Interp->Act);
path: clang/lib/Interpreter/Interpreter.cpp
user: login: anutosh491
body: Afk right now, shall address the above fixme soon !
created_at: 2025-04-19T06:55:49Z
author_association: MEMBER
diff_hunk: @@ -451,13 +451,44 @@ const char *const Runtimes = R"(
 )";
 
 llvm::Expected<std::unique_ptr<Interpreter>>
-Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
+Interpreter::create(std::unique_ptr<CompilerInstance> CI,
+                    std::unique_ptr<CompilerInstance> DeviceCI) {
   llvm::Error Err = llvm::Error::success();
   auto Interp =
       std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
   if (Err)
     return std::move(Err);
 
+  if (DeviceCI) {
+    // auto DeviceLLVMCtx = std::make_unique<llvm::LLVMContext>();
+    // auto DeviceTSCtx =
+    //     std::make_unique<llvm::orc::ThreadSafeContext>(std::move(DeviceLLVMCtx));
+
+    // llvm::Error DeviceErr = llvm::Error::success();
+    // llvm::ErrorAsOutParameter EAO(&DeviceErr);
+
+    // auto DeviceAct = std::make_unique<IncrementalAction>(
+    //     *DeviceCI, *DeviceTSCtx->getContext(), DeviceErr, *Interp);
+
+    // if (DeviceErr)
+    //   return std::move(DeviceErr);
+
+    // DeviceCI->ExecuteAction(*DeviceAct);
+    DeviceCI->ExecuteAction(*Interp->Act);
path: clang/lib/Interpreter/Interpreter.cpp
user: login: vgvassilev
body: > Well sadly I can't test the whole thing end to end being on macos, but at least this block should end up being platform independent is what I think (Using DeviceACT or ACT should work similarly)

Once this is ready I can test it.
created_at: 2025-04-19T07:00:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -451,13 +451,44 @@ const char *const Runtimes = R"(
 )";
 
 llvm::Expected<std::unique_ptr<Interpreter>>
-Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
+Interpreter::create(std::unique_ptr<CompilerInstance> CI,
+                    std::unique_ptr<CompilerInstance> DeviceCI) {
   llvm::Error Err = llvm::Error::success();
   auto Interp =
       std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
   if (Err)
     return std::move(Err);
 
+  if (DeviceCI) {
+    // auto DeviceLLVMCtx = std::make_unique<llvm::LLVMContext>();
+    // auto DeviceTSCtx =
+    //     std::make_unique<llvm::orc::ThreadSafeContext>(std::move(DeviceLLVMCtx));
+
+    // llvm::Error DeviceErr = llvm::Error::success();
+    // llvm::ErrorAsOutParameter EAO(&DeviceErr);
+
+    // auto DeviceAct = std::make_unique<IncrementalAction>(
+    //     *DeviceCI, *DeviceTSCtx->getContext(), DeviceErr, *Interp);
+
+    // if (DeviceErr)
+    //   return std::move(DeviceErr);
+
+    // DeviceCI->ExecuteAction(*DeviceAct);
+    DeviceCI->ExecuteAction(*Interp->Act);
path: clang/lib/Interpreter/Interpreter.cpp
user: login: anutosh491
body: > Once this is ready I can test it.

Thank you !
created_at: 2025-04-19T08:42:47Z
author_association: MEMBER
diff_hunk: @@ -451,13 +451,44 @@ const char *const Runtimes = R"(
 )";
 
 llvm::Expected<std::unique_ptr<Interpreter>>
-Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
+Interpreter::create(std::unique_ptr<CompilerInstance> CI,
+                    std::unique_ptr<CompilerInstance> DeviceCI) {
   llvm::Error Err = llvm::Error::success();
   auto Interp =
       std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
   if (Err)
     return std::move(Err);
 
+  if (DeviceCI) {
+    // auto DeviceLLVMCtx = std::make_unique<llvm::LLVMContext>();
+    // auto DeviceTSCtx =
+    //     std::make_unique<llvm::orc::ThreadSafeContext>(std::move(DeviceLLVMCtx));
+
+    // llvm::Error DeviceErr = llvm::Error::success();
+    // llvm::ErrorAsOutParameter EAO(&DeviceErr);
+
+    // auto DeviceAct = std::make_unique<IncrementalAction>(
+    //     *DeviceCI, *DeviceTSCtx->getContext(), DeviceErr, *Interp);
+
+    // if (DeviceErr)
+    //   return std::move(DeviceErr);
+
+    // DeviceCI->ExecuteAction(*DeviceAct);
+    DeviceCI->ExecuteAction(*Interp->Act);
path: clang/lib/Interpreter/Interpreter.cpp
user: login: vgvassilev
body: With this patch I get:
```
llvm-build $ ./bin/clang-repl --cuda
clang-repl: /home/vvassilev/workspace/sources/llvm-project/clang/lib/Frontend/FrontendAction.cpp:743: bool clang::FrontendAction::BeginSourceFile(clang::CompilerInstance&, const clang::FrontendInputFile&): Assertion `!Instance && "Already processing a source file!"' failed.
 #0 0x00007ffff46daba8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/vvassilev/workspace/sources/llvm-project/llvm/lib/Support/Unix/Signals.inc:804:22
 #1 0x00007ffff46dafc9 PrintStackTraceSignalHandler(void*) /home/vvassilev/workspace/sources/llvm-project/llvm/lib/Support/Unix/Signals.inc:880:1
 #2 0x00007ffff46d83f7 llvm::sys::RunSignalHandlers() /home/vvassilev/workspace/sources/llvm-project/llvm/lib/Support/Signals.cpp:105:20
 #3 0x00007ffff46da417 SignalHandler(int, siginfo_t*, void*) /home/vvassilev/workspace/sources/llvm-project/llvm/lib/Support/Unix/Signals.inc:418:13
 #4 0x00007ffff3f73520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #5 0x00007ffff3fc79fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #6 0x00007ffff3fc79fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #7 0x00007ffff3fc79fc pthread_kill ./nptl/pthread_kill.c:89:10
 #8 0x00007ffff3f73476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
 #9 0x00007ffff3f597f3 abort ./stdlib/abort.c:81:7
#10 0x00007ffff3f5971b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#11 0x00007ffff3f6ae96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#12 0x00007ffff65f58c3 clang::FrontendAction::BeginSourceFile(clang::CompilerInstance&, clang::FrontendInputFile const&) /home/vvassilev/workspace/sources/llvm-project/clang/lib/Frontend/FrontendAction.cpp:744:3
#13 0x00007ffff64e15c2 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) /home/vvassilev/workspace/sources/llvm-project/clang/lib/Frontend/CompilerInstance.cpp:1055:5
#14 0x00007ffff7b50a59 clang::Interpreter::create(std::unique_ptr<clang::CompilerInstance, std::default_delete<clang::CompilerInstance>>, std::unique_ptr<clang::CompilerInstance, std::default_delete<clang::CompilerInstance>>) /home/vvassilev/workspace/sources/llvm-project/clang/lib/Interpreter/Interpreter.cpp:466:56
#15 0x00007ffff7b50e40 clang::Interpreter::createWithCUDA(std::unique_ptr<clang::CompilerInstance, std::default_delete<clang::CompilerInstance>>, std::unique_ptr<clang::CompilerInstance, std::default_delete<clang::CompilerInstance>>) /home/vvassilev/workspace/sources/llvm-project/clang/lib/Interpreter/Interpreter.cpp:501:59
#16 0x000055555555a8e0 main /home/vvassilev/workspace/sources/llvm-project/clang/tools/clang-repl/ClangRepl.cpp:208:23
#17 0x00007ffff3f5ad90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#18 0x00007ffff3f5ae40 call_init ./csu/../csu/libc-start.c:128:20
#19 0x00007ffff3f5ae40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#20 0x0000555555559925 _start (./bin/clang-repl+0x5925)
Aborted (core dumped)
```
created_at: 2025-04-19T17:55:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -451,13 +451,44 @@ const char *const Runtimes = R"(
 )";
 
 llvm::Expected<std::unique_ptr<Interpreter>>
-Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
+Interpreter::create(std::unique_ptr<CompilerInstance> CI,
+                    std::unique_ptr<CompilerInstance> DeviceCI) {
   llvm::Error Err = llvm::Error::success();
   auto Interp =
       std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
   if (Err)
     return std::move(Err);
 
+  if (DeviceCI) {
+    // auto DeviceLLVMCtx = std::make_unique<llvm::LLVMContext>();
+    // auto DeviceTSCtx =
+    //     std::make_unique<llvm::orc::ThreadSafeContext>(std::move(DeviceLLVMCtx));
+
+    // llvm::Error DeviceErr = llvm::Error::success();
+    // llvm::ErrorAsOutParameter EAO(&DeviceErr);
+
+    // auto DeviceAct = std::make_unique<IncrementalAction>(
+    //     *DeviceCI, *DeviceTSCtx->getContext(), DeviceErr, *Interp);
+
+    // if (DeviceErr)
+    //   return std::move(DeviceErr);
+
+    // DeviceCI->ExecuteAction(*DeviceAct);
+    DeviceCI->ExecuteAction(*Interp->Act);
path: clang/lib/Interpreter/Interpreter.cpp
user: login: vgvassilev
body: While doing testing I came across on a patch of mine which does not crash:
```patch
commit bcc670b90af2cefedbb654d3057cda4f891fa4b7
Author: Vassil Vassilev <v.g.vassilev@gmail.com>
Date:   Sat Apr 19 15:39:41 2025 +0000

    fix cuda

diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index b1b63aedf86a..ba61c063d96a 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -94,6 +94,8 @@ class Interpreter {
 
   // An optional parser for CUDA offloading
   std::unique_ptr<IncrementalParser> DeviceParser;
+  // An optional action for CUDA offloading
+  std::unique_ptr<IncrementalAction> DeviceAct;
 
   /// List containing information about each incrementally parsed piece of code.
   std::list<PartialTranslationUnit> PTUs;
@@ -129,7 +131,8 @@ protected:
 public:
   virtual ~Interpreter();
   static llvm::Expected<std::unique_ptr<Interpreter>>
-  create(std::unique_ptr<CompilerInstance> CI);
+  create(std::unique_ptr<CompilerInstance> CI,
+         std::unique_ptr<CompilerInstance> DeviceCI = nullptr);
   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 1999d63d1aa0..3db96a6fd517 100644
--- a/clang/lib/Interpreter/DeviceOffload.cpp
+++ b/clang/lib/Interpreter/DeviceOffload.cpp
@@ -27,18 +27,27 @@ namespace clang {
 IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(
     std::unique_ptr<CompilerInstance> DeviceInstance,
     CompilerInstance &HostInstance,
-    llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS,
     llvm::Error &Err, const std::list<PartialTranslationUnit> &PTUs)
-    : IncrementalParser(*DeviceInstance, Err), PTUs(PTUs), VFS(FS),
-      CodeGenOpts(HostInstance.getCodeGenOpts()),
-      TargetOpts(HostInstance.getTargetOpts()) {
+  : IncrementalParser([this](CompilerInstance *DCI) -> CompilerInstance& {
+    // Avoid writing fat binary to disk using an in-memory virtual file system.
+    VFS = new llvm::vfs::InMemoryFileSystem();
+    llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayVFS =
+      std::make_unique<llvm::vfs::OverlayFileSystem>(
+          llvm::vfs::getRealFileSystem());
+    OverlayVFS->pushOverlay(VFS);
+    DCI->createFileManager(OverlayVFS);
+    return *DCI;
+  }(DeviceInstance.get()), Err), PTUs(PTUs),
+      HostCodeGenOpts(HostInstance.getCodeGenOpts()),
+      HostTargetOpts(HostInstance.getTargetOpts()) {
   if (Err)
     return;
   DeviceCI = std::move(DeviceInstance);
-  StringRef Arch = TargetOpts.CPU;
+  StringRef Arch = HostTargetOpts.CPU;
   if (!Arch.starts_with("sm_") || Arch.substr(3).getAsInteger(10, SMVersion)) {
     Err = llvm::joinErrors(std::move(Err), llvm::make_error<llvm::StringError>(
-                                               "Invalid CUDA architecture",
+                                               "Invalid CUDA architecture '" +
+                                               Arch + "'",
                                                llvm::inconvertibleErrorCode()));
     return;
   }
@@ -65,7 +74,7 @@ IncrementalCUDADeviceParser::Parse(llvm::StringRef Input) {
                    llvm::StringRef(FatbinContent.data(), FatbinContent.size()),
                    "", false));
 
-  CodeGenOpts.CudaGpuBinaryFileName = FatbinFileName;
+  HostCodeGenOpts.CudaGpuBinaryFileName = FatbinFileName;
 
   FatbinContent.clear();
 
@@ -83,7 +92,7 @@ llvm::Expected<llvm::StringRef> IncrementalCUDADeviceParser::GeneratePTX() {
                                                std::error_code());
   llvm::TargetOptions TO = llvm::TargetOptions();
   llvm::TargetMachine *TargetMachine = Target->createTargetMachine(
-      PTU.TheModule->getTargetTriple(), TargetOpts.CPU, "", TO,
+      PTU.TheModule->getTargetTriple(), HostTargetOpts.CPU, "", TO,
       llvm::Reloc::Model::PIC_);
   PTU.TheModule->setDataLayout(TargetMachine->createDataLayout());
 
diff --git a/clang/lib/Interpreter/DeviceOffload.h b/clang/lib/Interpreter/DeviceOffload.h
index b9a1acab004c..07994ccb40eb 100644
--- a/clang/lib/Interpreter/DeviceOffload.h
+++ b/clang/lib/Interpreter/DeviceOffload.h
@@ -30,7 +30,6 @@ public:
   IncrementalCUDADeviceParser(
       std::unique_ptr<CompilerInstance> DeviceInstance,
       CompilerInstance &HostInstance,
-      llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS,
       llvm::Error &Err, const std::list<PartialTranslationUnit> &PTUs);
 
   llvm::Expected<TranslationUnitDecl *> Parse(llvm::StringRef Input) override;
@@ -49,8 +48,8 @@ protected:
   llvm::SmallString<1024> PTXCode;
   llvm::SmallVector<char, 1024> FatbinContent;
   llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS;
-  CodeGenOptions &CodeGenOpts; // Intentionally a reference.
-  const TargetOptions &TargetOpts;
+  CodeGenOptions &HostCodeGenOpts; // Intentionally a reference.
+  const TargetOptions &HostTargetOpts;
 };
 
 } // namespace clang
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 1859c6802c6f..3ca2e21d6f8a 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -450,13 +450,33 @@ const char *const Runtimes = R"(
 )";
 
 llvm::Expected<std::unique_ptr<Interpreter>>
-Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
+Interpreter::create(std::unique_ptr<CompilerInstance> CI,
+                    std::unique_ptr<CompilerInstance> DeviceCI/*=nullptr*/) {
   llvm::Error Err = llvm::Error::success();
+
   auto Interp =
       std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
+  CompilerInstance &HostCI = *(Interp->getCompilerInstance());
   if (Err)
     return std::move(Err);
 
+  if (DeviceCI) {
+    Interp->DeviceAct = std::make_unique<IncrementalAction>(*DeviceCI, *Interp->TSCtx->getContext(), Err,
+                                                            *Interp);
+
+    if (Err)
+      return std::move(Err);
+
+    DeviceCI->ExecuteAction(*Interp->DeviceAct);
+
+    auto DeviceParser = new IncrementalCUDADeviceParser(std::move(DeviceCI),
+                                                        HostCI, Err, Interp->PTUs);
+    if (Err)
+      return std::move(Err);
+
+    Interp->DeviceParser.reset(DeviceParser);
+  }
+
   // Add runtime code and set a marker to hide it from user code. Undo will not
   // go through that.
   auto PTU = Interp->Parse(Runtimes);
@@ -471,29 +491,7 @@ Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
 llvm::Expected<std::unique_ptr<Interpreter>>
 Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI,
                             std::unique_ptr<CompilerInstance> DCI) {
-  // 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>();
-  llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayVFS =
-      std::make_unique<llvm::vfs::OverlayFileSystem>(
-          llvm::vfs::getRealFileSystem());
-  OverlayVFS->pushOverlay(IMVFS);
-  CI->createFileManager(OverlayVFS);
-
-  auto Interp = Interpreter::create(std::move(CI));
-  if (auto E = Interp.takeError())
-    return std::move(E);
-
-  llvm::Error Err = llvm::Error::success();
-  auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>(
-      std::move(DCI), *(*Interp)->getCompilerInstance(), IMVFS, Err,
-      (*Interp)->PTUs);
-  if (Err)
-    return std::move(Err);
-
-  (*Interp)->DeviceParser = std::move(DeviceParser);
-
-  return Interp;
+  return Interpreter::create(std::move(CI), std::move(DCI));
 }
 
 const CompilerInstance *Interpreter::getCompilerInstance() const {
 ```
 
 but shows:
 
 ```
 ./bin/clang-repl  --cuda
module flag identifiers must be unique (or of 'require' type)
!"wchar_size"
module flag identifiers must be unique (or of 'require' type)
!"nvvm-reflect-ftz"
module flag identifiers must be unique (or of 'require' type)
!"frame-pointer"
fatal error: error in backend: Broken module found, compilation aborted!
```
created_at: 2025-04-19T17:57:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -451,13 +451,44 @@ const char *const Runtimes = R"(
 )";
 
 llvm::Expected<std::unique_ptr<Interpreter>>
-Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
+Interpreter::create(std::unique_ptr<CompilerInstance> CI,
+                    std::unique_ptr<CompilerInstance> DeviceCI) {
   llvm::Error Err = llvm::Error::success();
   auto Interp =
       std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
   if (Err)
     return std::move(Err);
 
+  if (DeviceCI) {
+    // auto DeviceLLVMCtx = std::make_unique<llvm::LLVMContext>();
+    // auto DeviceTSCtx =
+    //     std::make_unique<llvm::orc::ThreadSafeContext>(std::move(DeviceLLVMCtx));
+
+    // llvm::Error DeviceErr = llvm::Error::success();
+    // llvm::ErrorAsOutParameter EAO(&DeviceErr);
+
+    // auto DeviceAct = std::make_unique<IncrementalAction>(
+    //     *DeviceCI, *DeviceTSCtx->getContext(), DeviceErr, *Interp);
+
+    // if (DeviceErr)
+    //   return std::move(DeviceErr);
+
+    // DeviceCI->ExecuteAction(*DeviceAct);
+    DeviceCI->ExecuteAction(*Interp->Act);
path: clang/lib/Interpreter/Interpreter.cpp
user: login: anutosh491
body: Thanks a lot for the help Vassil.

I'll look into all of this soon !
created_at: 2025-04-19T19:05:59Z
author_association: MEMBER
diff_hunk: @@ -28,20 +28,21 @@ IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(
     std::unique_ptr<CompilerInstance> DeviceInstance,
     CompilerInstance &HostInstance,
     llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS,
-    llvm::Error &Err, const std::list<PartialTranslationUnit> &PTUs)
+    llvm::Error &Err, std::list<PartialTranslationUnit> &PTUs)
     : IncrementalParser(*DeviceInstance, Err), PTUs(PTUs), VFS(FS),
       CodeGenOpts(HostInstance.getCodeGenOpts()),
-      TargetOpts(HostInstance.getTargetOpts()) {
+      TargetOpts(DeviceInstance->getTargetOpts()) {
path: clang/lib/Interpreter/DeviceOffload.cpp
user: login: anutosh491
body: `TargetOpts` should be fetched from `DeviceInstance` rather than `HostInstance`

This can be seen even through the cc1 command generated through createCI (skipping some flags)

```
// FOR THE DEVICE (Skipping lot of flags just keeping the main ones)

 "/Users/anutosh491/work/llvm-project/build2/bin/clang-repl" -cc1 -triple nvptx64-nvidia-cuda -aux-triple arm64-apple-darwin24.3.0 ....... -aux-target-cpu apple-m1 ........ -target-cpu sm_35 -target-feature ...... --offload-new-driver -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -fcolor-diagnostics -fincremental-extensions -cuid=6c8ca225f780e660 -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o "/var/folders/m1/cdn74f917994jd99d_2cpf440000gn/T/<<< inputs >>>-sm_35-14d471.s" -x cuda "<<< inputs >>>"
 "ptxas" -m64 -O0 -v --gpu-name sm_35 --output-file "<<< inputs >>>-cuda-nvptx64-nvidia-cuda-sm_35.o" "/var/folders/m1/cdn74f917994jd99d_2cpf440000gn/T/<<< inputs >>>-sm_35-14d471.s"
 ```

As seen `-target-cpu sm_35` so the check below with regards to the `Arch` doesn't even make sense if we use it from the host side.

`if (!Arch.starts_with("sm_") || Arch.substr(3).getAsInteger(10, SMVersion)) {`
 
 
created_at: 2025-04-24T13:08:27Z
author_association: MEMBER
diff_hunk: @@ -560,6 +576,16 @@ Interpreter::Parse(llvm::StringRef Code) {
     llvm::Expected<TranslationUnitDecl *> DeviceTU = DeviceParser->Parse(Code);
     if (auto E = DeviceTU.takeError())
       return std::move(E);
+
+    RegisterPTU(*DeviceTU, nullptr, DeviceAct.get());
+
+    llvm::Expected<llvm::StringRef> PTX = DeviceParser->GeneratePTX();
+    if (!PTX)
+      return PTX.takeError();
+
+    llvm::Error Err = DeviceParser->GenerateFatbinary();
+    if (Err)
+      return std::move(Err);
   }
path: clang/lib/Interpreter/Interpreter.cpp
user: login: anutosh491
body: Changes with respect to parsing if `DeviceParser` is non nullptr

If we currently look at how generatePTX is framed (check [lines](https://github.com/llvm/llvm-project/pull/136404/files#diff-facf198ec2120aeb2be299cac501daf8e32793547be89a06139bcb988ad532c7R58-R59)) 

We operate on PTUs from the list of PTUS.

But currently we add no "devicePTUs" (produced by the deviceparser) as such in our list of PTUs.

So `auto &PTU = PTUs.back();`  would
i) either return a nullptr
ii) or point to a host PTU 

Both of which are wrong. The generatePTX function is meant to work on "devicePTUs" (produced by the deviceparser) as such who's modules have the target triple `nvptx64-nvidia-cuda` rather than that provided by the host (possibly `x86_64-unknown-linux-gnu`)

So first we 
i) Parse the code
ii) Register the PTU just like we do for the host case
iii) Then we operate on it (using `GeneratePTX` and `GenerateFatbinary`)
 




created_at: 2025-04-24T13:15:19Z
author_association: MEMBER
diff_hunk: @@ -760,8 +787,10 @@ std::unique_ptr<llvm::Module> Interpreter::GenModule() {
   return nullptr;
 }
 
-CodeGenerator *Interpreter::getCodeGen() const {
-  FrontendAction *WrappedAct = Act->getWrapped();
+CodeGenerator *Interpreter::getCodeGen(IncrementalAction *Action) const {
+  if (!Action)
+    Action = Act.get();
+  FrontendAction *WrappedAct = Action->getWrapped();
path: clang/lib/Interpreter/Interpreter.cpp
user: login: anutosh491
body: Talking about changes with respect to codegen.

So errors like these 
```
./bin/clang-repl  --cuda
module flag identifiers must be unique (or of 'require' type)
!"wchar_size"
module flag identifiers must be unique (or of 'require' type)
!"nvvm-reflect-ftz"
module flag identifiers must be unique (or of 'require' type)
!"frame-pointer"
fatal error: error in backend: Broken module found, compilation aborted!
```
or even something like this 
```
error: Added modules have incompatible data layouts: e-p6:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64 (module) vs e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128 (jit)
```

Occur because we use the `Act` (the host IncrementalAction) to come up with the Module every time as of now.

But think about it when we are registering a PTU through registerPTU .... we have this block

```
  if (!M)
    M = GenModule();
```
 Here shouldn't be generating the same Module for both the hostPTU (parsed through the incremental parser) and the devicePTU (parsed through the incrementalCudaParser) .

For the first case the Module should revolve around the triple `x86_64-unknown-linux-gnu` and for the device case the module should be framed around the target triple `nvptx64-nvidia-cuda`.

This is taken care of based on which `IncrementalAction` we use. We should use Act for hostPTU and DeviceACT for PTU. 

Hence the changes here (as one trickles into the other)
```
  CodeGenerator *getCodeGen(IncrementalAction *Action = nullptr) const;
  std::unique_ptr<llvm::Module> GenModule(IncrementalAction *Action = nullptr);
  PartialTranslationUnit &RegisterPTU(TranslationUnitDecl *TU,
                                      std::unique_ptr<llvm::Module> M = {},
                                      IncrementalAction *Action = nullptr);                                
```
So by **default we use Act**, but we can take care of it when required.

1) So while regiserting a devicePTU we use this https://github.com/llvm/llvm-project/pull/136404/files#diff-b8484f1fc5b057f146ed5d9b6e2cd47c3f6f5ae879c7a0eee44f0a272581a88cR580
2) While registering a hostptu we use this https://github.com/llvm/llvm-project/pull/136404/files#diff-b8484f1fc5b057f146ed5d9b6e2cd47c3f6f5ae879c7a0eee44f0a272581a88cR600




created_at: 2025-04-24T13:23:42Z
author_association: MEMBER
diff_hunk: @@ -28,20 +28,21 @@ IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(
     std::unique_ptr<CompilerInstance> DeviceInstance,
     CompilerInstance &HostInstance,
     llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS,
-    llvm::Error &Err, const std::list<PartialTranslationUnit> &PTUs)
+    llvm::Error &Err, std::list<PartialTranslationUnit> &PTUs)
     : IncrementalParser(*DeviceInstance, Err), PTUs(PTUs), VFS(FS),
       CodeGenOpts(HostInstance.getCodeGenOpts()),
-      TargetOpts(HostInstance.getTargetOpts()) {
+      TargetOpts(DeviceInstance->getTargetOpts()) {
   if (Err)
     return;
-  DeviceCI = std::move(DeviceInstance);
   StringRef Arch = TargetOpts.CPU;
   if (!Arch.starts_with("sm_") || Arch.substr(3).getAsInteger(10, SMVersion)) {
+    DeviceInstance.release();
path: clang/lib/Interpreter/DeviceOffload.cpp
user: login: vgvassilev
body: We don't need that release here I think.
created_at: 2025-04-24T13:49:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -28,20 +28,21 @@ IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(
     std::unique_ptr<CompilerInstance> DeviceInstance,
     CompilerInstance &HostInstance,
     llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS,
-    llvm::Error &Err, const std::list<PartialTranslationUnit> &PTUs)
path: clang/lib/Interpreter/DeviceOffload.cpp
user: login: vgvassilev
body: Why removing the const?
created_at: 2025-04-24T13:49:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -172,6 +154,19 @@ llvm::Error IncrementalCUDADeviceParser::GenerateFatbinary() {
 
   FatbinContent.append(PTXCode.begin(), PTXCode.end());
 
+  auto &PTU = PTUs.back();
path: clang/lib/Interpreter/DeviceOffload.cpp
user: login: vgvassilev
body: ```suggestion
  const PartialTranslationUnit &PTU = PTUs.back();
```
created_at: 2025-04-24T13:50:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -28,20 +28,21 @@ IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(
     std::unique_ptr<CompilerInstance> DeviceInstance,
     CompilerInstance &HostInstance,
     llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS,
-    llvm::Error &Err, const std::list<PartialTranslationUnit> &PTUs)
path: clang/lib/Interpreter/DeviceOffload.cpp
user: login: anutosh491
body: Thanks for pointing this out. I was probably testing something when i took it out !
created_at: 2025-04-24T13:56:32Z
author_association: MEMBER
diff_hunk: @@ -28,20 +28,21 @@ IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(
     std::unique_ptr<CompilerInstance> DeviceInstance,
     CompilerInstance &HostInstance,
     llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS,
-    llvm::Error &Err, const std::list<PartialTranslationUnit> &PTUs)
+    llvm::Error &Err, std::list<PartialTranslationUnit> &PTUs)
     : IncrementalParser(*DeviceInstance, Err), PTUs(PTUs), VFS(FS),
       CodeGenOpts(HostInstance.getCodeGenOpts()),
-      TargetOpts(HostInstance.getTargetOpts()) {
+      TargetOpts(DeviceInstance->getTargetOpts()) {
   if (Err)
     return;
-  DeviceCI = std::move(DeviceInstance);
   StringRef Arch = TargetOpts.CPU;
   if (!Arch.starts_with("sm_") || Arch.substr(3).getAsInteger(10, SMVersion)) {
+    DeviceInstance.release();
path: clang/lib/Interpreter/DeviceOffload.cpp
user: login: anutosh491
body: Yupp. Got rid of it !
created_at: 2025-04-24T14:01:43Z
author_association: MEMBER
diff_hunk: @@ -50,25 +50,6 @@ IncrementalCUDADeviceParser::Parse(llvm::StringRef Input) {
   if (!PTU)
     return PTU.takeError();
 
-  auto PTX = GeneratePTX();
path: clang/lib/Interpreter/DeviceOffload.cpp
user: login: vgvassilev
body: If this code moved, can't we rely on the base class implementation of `Parse` here?
created_at: 2025-04-24T14:48:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -760,8 +787,10 @@ std::unique_ptr<llvm::Module> Interpreter::GenModule() {
   return nullptr;
 }
 
-CodeGenerator *Interpreter::getCodeGen() const {
-  FrontendAction *WrappedAct = Act->getWrapped();
+CodeGenerator *Interpreter::getCodeGen(IncrementalAction *Action) const {
+  if (!Action)
+    Action = Act.get();
+  FrontendAction *WrappedAct = Action->getWrapped();
path: clang/lib/Interpreter/Interpreter.cpp
user: login: vgvassilev
body: I do not understand this change. Is it because we call `getCodeGen` from both Device and Host compiler instance but we only return the codegen for the Host?
created_at: 2025-04-24T14:53:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -760,8 +787,10 @@ std::unique_ptr<llvm::Module> Interpreter::GenModule() {
   return nullptr;
 }
 
-CodeGenerator *Interpreter::getCodeGen() const {
-  FrontendAction *WrappedAct = Act->getWrapped();
+CodeGenerator *Interpreter::getCodeGen(IncrementalAction *Action) const {
+  if (!Action)
+    Action = Act.get();
+  FrontendAction *WrappedAct = Action->getWrapped();
path: clang/lib/Interpreter/Interpreter.cpp
user: login: anutosh491
body: Yupp. Basically this comment https://github.com/llvm/llvm-project/pull/136404#discussion_r2058443908

In short putting DeviceAct and Act to use for their respective use cases.
created_at: 2025-04-24T15:15:59Z
author_association: MEMBER
diff_hunk: @@ -50,25 +50,6 @@ IncrementalCUDADeviceParser::Parse(llvm::StringRef Input) {
   if (!PTU)
     return PTU.takeError();
 
-  auto PTX = GeneratePTX();
path: clang/lib/Interpreter/DeviceOffload.cpp
user: login: anutosh491
body: Yes absolutely !

Sorry for overlooking this. Made the change.
created_at: 2025-04-24T15:26:52Z
author_association: MEMBER
diff_hunk: @@ -760,8 +787,10 @@ std::unique_ptr<llvm::Module> Interpreter::GenModule() {
   return nullptr;
 }
 
-CodeGenerator *Interpreter::getCodeGen() const {
-  FrontendAction *WrappedAct = Act->getWrapped();
+CodeGenerator *Interpreter::getCodeGen(IncrementalAction *Action) const {
+  if (!Action)
+    Action = Act.get();
+  FrontendAction *WrappedAct = Action->getWrapped();
path: clang/lib/Interpreter/Interpreter.cpp
user: login: vgvassilev
body: Shouldn't we delegate somehow to the IncrementalParser/IncrementalCUDAParser instead?
created_at: 2025-04-24T20:06:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -760,8 +787,10 @@ std::unique_ptr<llvm::Module> Interpreter::GenModule() {
   return nullptr;
 }
 
-CodeGenerator *Interpreter::getCodeGen() const {
-  FrontendAction *WrappedAct = Act->getWrapped();
+CodeGenerator *Interpreter::getCodeGen(IncrementalAction *Action) const {
+  if (!Action)
+    Action = Act.get();
+  FrontendAction *WrappedAct = Action->getWrapped();
path: clang/lib/Interpreter/Interpreter.cpp
user: login: anutosh491
body: Hey @vgvassilev ,

Yes I think this makes lot of sense.

1) Reading through the docstring for IncrementalAction I see this 
`
IncrementalAction ensures it keeps its underlying action's objects alive as long as the IncrementalParser needs them.`

I think this implies that It’s designed for use with IncrementalParser, and the parser is meant to reuse its state. 

2) The parser should not only be responsible for parsing but also for managing its respective PTUs. So stuff like registering the PTU, generating module for the PTUs should totally be taken care of by IncrementalParser/IncrementalCudaDeviceParser.

So the latest comment couples the respective Action to its respective Parser (Act to incrparser and DeviceAct to DeviceParser as per point 1.
it also moves the code related to module generation in incrementalParser.
created_at: 2025-04-25T09:46:45Z
author_association: MEMBER
diff_hunk: @@ -760,8 +787,10 @@ std::unique_ptr<llvm::Module> Interpreter::GenModule() {
   return nullptr;
 }
 
-CodeGenerator *Interpreter::getCodeGen() const {
-  FrontendAction *WrappedAct = Act->getWrapped();
+CodeGenerator *Interpreter::getCodeGen(IncrementalAction *Action) const {
+  if (!Action)
+    Action = Act.get();
+  FrontendAction *WrappedAct = Action->getWrapped();
path: clang/lib/Interpreter/Interpreter.cpp
user: login: anutosh491
body: Squashed the commits into 2 meaningful ones. So for the above changes (or what I mean by the latest commit) ... I am pointing to this one https://github.com/llvm/llvm-project/pull/136404/commits/bbf41f4a4f6b3eccadd29e6c4dfdf65ba4ae0776
created_at: 2025-04-25T10:07:48Z
author_association: MEMBER

PR comments:
user: login: llvmbot
created_at: 2025-04-19T04:34:23Z
body: 
<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Anutosh Bhat (anutosh491)

<details>
<summary>Changes</summary>



`clang-repl --cuda` was previously crashing with a segmentation fault, instead of reporting a clean error
```
(base) anutosh491@<!-- -->Anutoshs-MacBook-Air bin % ./clang-repl --cuda
#<!-- -->0 0x0000000111da4fbc llvm::sys::PrintStackTrace(llvm::raw_ostream&amp;, int) (/opt/local/libexec/llvm-20/lib/libLLVM.dylib+0x150fbc)
#<!-- -->1 0x0000000111da31dc llvm::sys::RunSignalHandlers() (/opt/local/libexec/llvm-20/lib/libLLVM.dylib+0x14f1dc)
#<!-- -->2 0x0000000111da5628 SignalHandler(int) (/opt/local/libexec/llvm-20/lib/libLLVM.dylib+0x151628)
#<!-- -->3 0x000000019b242de4 (/usr/lib/system/libsystem_platform.dylib+0x180482de4)
#<!-- -->4 0x0000000107f638d0 clang::IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(std::__1::unique_ptr&lt;clang::CompilerInstance, std::__1::default_delete&lt;clang::CompilerInstance&gt;&gt;, clang::CompilerInstance&amp;, llvm::IntrusiveRefCntPtr&lt;llvm::vfs::InMemoryFileSystem&gt;, llvm::Error&amp;, std::__1::list&lt;clang::PartialTranslationUnit, std::__1::allocator&lt;clang::PartialTranslationUnit&gt;&gt; const&amp;) (/opt/local/libexec/llvm-20/lib/libclang-cpp.dylib+0x216b8d0)
#<!-- -->5 0x0000000107f638d0 clang::IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(std::__1::unique_ptr&lt;clang::CompilerInstance, std::__1::default_delete&lt;clang::CompilerInstance&gt;&gt;, clang::CompilerInstance&amp;, llvm::IntrusiveRefCntPtr&lt;llvm::vfs::InMemoryFileSystem&gt;, llvm::Error&amp;, std::__1::list&lt;clang::PartialTranslationUnit, std::__1::allocator&lt;clang::PartialTranslationUnit&gt;&gt; const&amp;) (/opt/local/libexec/llvm-20/lib/libclang-cpp.dylib+0x216b8d0)
#<!-- -->6 0x0000000107f6bac8 clang::Interpreter::createWithCUDA(std::__1::unique_ptr&lt;clang::CompilerInstance, std::__1::default_delete&lt;clang::CompilerInstance&gt;&gt;, std::__1::unique_ptr&lt;clang::CompilerInstance, std::__1::default_delete&lt;clang::CompilerInstance&gt;&gt;) (/opt/local/libexec/llvm-20/lib/libclang-cpp.dylib+0x2173ac8)
#<!-- -->7 0x000000010206f8a8 main (/opt/local/libexec/llvm-20/bin/clang-repl+0x1000038a8)
#<!-- -->8 0x000000019ae8c274 
Segmentation fault: 11
```


The underlying issue was that the `DeviceCompilerInstance` (used for device-side CUDA compilation) was never initialized with a `Sema`, which is required before constructing the `IncrementalCUDADeviceParser`. 

https://github.com/llvm/llvm-project/blob/89687e6f383b742a3c6542dc673a84d9f82d02de/clang/lib/Interpreter/DeviceOffload.cpp#L32

https://github.com/llvm/llvm-project/blob/89687e6f383b742a3c6542dc673a84d9f82d02de/clang/lib/Interpreter/IncrementalParser.cpp#L31

Unlike the host-side `CompilerInstance` which runs `ExecuteAction` inside the Interpreter constructor (thereby setting up Sema), the device-side CI was passed into the parser uninitialized, leading to an assertion or crash when accessing its internals.

To fix this, I refactored the `Interpreter::create` method to include an optional `DeviceCI` parameter. If provided, we know we need to take care of this instance too. Only then do we construct the `IncrementalCUDADeviceParser`.



---
Full diff: https://github.com/llvm/llvm-project/pull/136404.diff


3 Files Affected:

- (modified) clang/include/clang/Interpreter/Interpreter.h (+2-1) 
- (modified) clang/lib/Interpreter/DeviceOffload.cpp (+2-1) 
- (modified) clang/lib/Interpreter/Interpreter.cpp (+33-15) 


``````````diff
diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index b1b63aedf86ab..20d22c4437a97 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -129,7 +129,8 @@ class Interpreter {
 public:
   virtual ~Interpreter();
   static llvm::Expected<std::unique_ptr<Interpreter>>
-  create(std::unique_ptr<CompilerInstance> CI);
+  create(std::unique_ptr<CompilerInstance> CI,
+    std::unique_ptr<CompilerInstance> DeviceCI = nullptr);
   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 1999d63d1aa04..9a7be006250a0 100644
--- a/clang/lib/Interpreter/DeviceOffload.cpp
+++ b/clang/lib/Interpreter/DeviceOffload.cpp
@@ -34,14 +34,15 @@ IncrementalCUDADeviceParser::IncrementalCUDADeviceParser(
       TargetOpts(HostInstance.getTargetOpts()) {
   if (Err)
     return;
-  DeviceCI = std::move(DeviceInstance);
   StringRef Arch = TargetOpts.CPU;
   if (!Arch.starts_with("sm_") || Arch.substr(3).getAsInteger(10, SMVersion)) {
+    DeviceInstance.release();
     Err = llvm::joinErrors(std::move(Err), llvm::make_error<llvm::StringError>(
                                                "Invalid CUDA architecture",
                                                llvm::inconvertibleErrorCode()));
     return;
   }
+  DeviceCI = std::move(DeviceInstance);
 }
 
 llvm::Expected<TranslationUnitDecl *>
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index f8c8d0a425659..1af3f24774028 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -451,13 +451,44 @@ const char *const Runtimes = R"(
 )";
 
 llvm::Expected<std::unique_ptr<Interpreter>>
-Interpreter::create(std::unique_ptr<CompilerInstance> CI) {
+Interpreter::create(std::unique_ptr<CompilerInstance> CI,
+                    std::unique_ptr<CompilerInstance> DeviceCI) {
   llvm::Error Err = llvm::Error::success();
   auto Interp =
       std::unique_ptr<Interpreter>(new Interpreter(std::move(CI), Err));
   if (Err)
     return std::move(Err);
 
+  if (DeviceCI) {
+    // auto DeviceLLVMCtx = std::make_unique<llvm::LLVMContext>();
+    // auto DeviceTSCtx =
+    //     std::make_unique<llvm::orc::ThreadSafeContext>(std::move(DeviceLLVMCtx));
+
+    // llvm::Error DeviceErr = llvm::Error::success();
+    // llvm::ErrorAsOutParameter EAO(&DeviceErr);
+
+    // auto DeviceAct = std::make_unique<IncrementalAction>(
+    //     *DeviceCI, *DeviceTSCtx->getContext(), DeviceErr, *Interp);
+
+    // if (DeviceErr)
+    //   return std::move(DeviceErr);
+
+    //DeviceCI->ExecuteAction(*DeviceAct);
+    DeviceCI->ExecuteAction(*Interp->Act);
+
+    llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> IMVFS =
+        std::make_unique<llvm::vfs::InMemoryFileSystem>();
+
+    auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>(
+        std::move(DeviceCI), *Interp->getCompilerInstance(), IMVFS, Err,
+        Interp->PTUs);
+
+    if (Err)
+      return std::move(Err);
+
+    Interp->DeviceParser = std::move(DeviceParser);
+  }
+
   // Add runtime code and set a marker to hide it from user code. Undo will not
   // go through that.
   auto PTU = Interp->Parse(Runtimes);
@@ -481,20 +512,7 @@ Interpreter::createWithCUDA(std::unique_ptr<CompilerInstance> CI,
   OverlayVFS->pushOverlay(IMVFS);
   CI->createFileManager(OverlayVFS);
 
-  auto Interp = Interpreter::create(std::move(CI));
-  if (auto E = Interp.takeError())
-    return std::move(E);
-
-  llvm::Error Err = llvm::Error::success();
-  auto DeviceParser = std::make_unique<IncrementalCUDADeviceParser>(
-      std::move(DCI), *(*Interp)->getCompilerInstance(), IMVFS, Err,
-      (*Interp)->PTUs);
-  if (Err)
-    return std::move(Err);
-
-  (*Interp)->DeviceParser = std::move(DeviceParser);
-
-  return Interp;
+  return Interpreter::create(std::move(CI), std::move(DCI));
 }
 
 const CompilerInstance *Interpreter::getCompilerInstance() const {

``````````

</details>

author_association: MEMBER
user: login: github-actions[bot]
created_at: 2025-04-19T04:36:08Z
body: <!--LLVM CODE FORMAT COMMENT: {clang-format}-->

:white_check_mark: With the latest revision this PR passed the C/C++ code formatter.
author_association: NONE
user: login: anutosh491
created_at: 2025-04-19T04:42:13Z
body: cc @AaronBallman @vgvassilev 

This fixes this discussion y'all had https://github.com/llvm/llvm-project/pull/107737#discussion_r1806913203

Unfortunately I am on an Apple m1 so I can just justify seeing this on my side 
```
(base) anutosh491@Anutoshs-MacBook-Air bin % ./clang-repl --cuda
clang-repl: Invalid CUDA architecture
```

But actually this error is more justified that what we are seeing with clang-repl-19
```
(base) anutosh491@Anutoshs-MacBook-Air bin % ./clang-repl-19 --cuda
clang-repl: dlopen(libcudart.so, 0x0009): tried: 'libcudart.so' (no such file), '/System/Volumes/Preboot/Cryptexes/OSlibcudart.so' (no such file), '/opt/local/libexec/llvm-19/lib/../lib/libcudart.so' (no such file), '/opt/local/libexec/llvm-19/bin/../lib/libcudart.so' (no such file), '/usr/lib/libcudart.so' (no such file, not in dyld cache), 'libcudart.so' (no such file)
```

So everything spawns from here 

https://github.com/llvm/llvm-project/blob/3bcb724903d82414a0952fe0349d5181ff2f0f26/clang/tools/clang-repl/ClangRepl.cpp#L207-L212

But for 
i) clang-repl-20: The call to createwithcuda would error out from here

The first one comes from here 
https://github.com/llvm/llvm-project/blob/3bcb724903d82414a0952fe0349d5181ff2f0f26/clang/lib/Interpreter/DeviceOffload.cpp#L38-L43

ii) clang-repl-19: Passes that, successfully creates the interpreter and ends up failing at the Loading step (**although we should expect it to fail on the top itself isn't it ?**)


author_association: MEMBER
user: login: anutosh491
created_at: 2025-04-24T07:33:24Z
body: Hey @vgvassilev @argentite 

With these changes, I am positive we atleast have the design in place to run any of these Cuda tests (https://github.com/llvm/llvm-project/tree/main/clang/test/Interpreter/CUDA)

For example running the sanity.cu file 
```
anutosh491@vv-nuc:/build/anutosh491/llvm-project/build/bin$ ./clang-repl --cuda
clang-repl> extern "C" int printf(const char*, ...);
clang-repl> __global__ void test_func() {}
clang-repl> test_func<<<1,1>>>();
clang-repl> printf("CUDA Error: %d", cudaGetLastError());
CUDA Error: 0
clang-repl> 
```

The only thing which I am kinda struggling to figure out is how to put the virtual filesystem to use. So to get the above tests working, I had to just comment out what we do through VFS and use the real filesystem 

```
  // VFS->addFile(FatbinFileName, 0,
  //              llvm::MemoryBuffer::getMemBuffer(
  //                  llvm::StringRef(FatbinContent.data(), FatbinContent.size()),
  //                  "", false));
  // Write directly to disk
  std::error_code EC;
  llvm::raw_fd_ostream OS(FatbinFileName, EC);
  if (EC) {
    return llvm::make_error<llvm::StringError>(
        "Failed to write fatbin: " + EC.message(), llvm::inconvertibleErrorCode());
  }
  OS.write(FatbinContent.data(), FatbinContent.size());
  OS.close();
  ```
  
  So hopefully the VFS used here
  https://github.com/llvm/llvm-project/blob/bea110db3ed1fa1215bb8e22d2057019fcbd2d16/clang/lib/Interpreter/DeviceOffload.cpp#L63
  
  and here 
  
  https://github.com/llvm/llvm-project/blob/bea110db3ed1fa1215bb8e22d2057019fcbd2d16/clang/lib/CodeGen/CGCUDANV.cpp#L791-L792
  
  Should be the same, but my logs tell me otherwise. I added some simple logs to verify the same and I see this 
```
[DeviceOffload] Current working directory: /
[DeviceOffload] Fatbin file successfully found in VFS: /incr_module_3.fatbin
[CGCUDANV] CudaGpuBinaryFileName: /incr_module_3.fatbin
[CGCUDANV] VFS CWD: /build/anutosh491/llvm-project/build/bin
[CGCUDANV] status() failed: No such file or directory
```

So if you see both VFS point to different locations.
I tried some workarounds but haven't been able to figure this out and possibly might need some help.

So the current changes would just fail with 
```
anutosh491@vv-nuc:/build/anutosh491/llvm-project/build/bin$ ./clang-repl --cuda
clang-repl> extern "C" int printf(const char*, ...);
clang-repl> __global__ void test_func() {}
fatal error: cannot open file '/incr_module_3.fatbin': No such file or directory
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0  clang-repl 0x0000555557fde34f llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 63
1  clang-repl 0x0000555557fdc264 llvm::sys::RunSignalHandlers() + 52
2  clang-repl 0x0000555557fdc5b9
3  libc.so.6  0x00007ffff795c520
4  clang-repl 0x00005555581608e7 clang::Interpreter::GenModule(clang::IncrementalAction*) + 519
5  clang-repl 0x0000555558160dee clang::Interpreter::RegisterPTU(clang::TranslationUnitDecl*, std::unique_ptr<llvm::Module, std::default_delete<llvm::Module>>, clang::IncrementalAction*) + 206
6  clang-repl 0x0000555558161027 clang::Interpreter::Parse(llvm::StringRef) + 471
7  clang-repl 0x0000555558162360 clang::Interpreter::ParseAndExecute(llvm::StringRef, clang::Value*) + 48
8  clang-repl 0x0000555556263075 main + 4085
9  libc.so.6  0x00007ffff7943d90
10 libc.so.6  0x00007ffff7943e40 __libc_start_main + 128
11 clang-repl 0x00005555563da585 _start + 37
Segmentation fault (core dumped)
```

Once we start fetching these files from the correct location, this should be ready !
  
  


author_association: MEMBER
user: login: anutosh491
created_at: 2025-04-24T09:54:12Z
body: Was able to address the issue here. 

Making a commit soon !
author_association: MEMBER
user: login: anutosh491
created_at: 2025-04-24T13:04:31Z
body: Making a note of the major changes below !
author_association: MEMBER
user: login: llvm-ci
created_at: 2025-04-26T07:07:20Z
body: LLVM Buildbot has detected a new failure on builder `lldb-arm-ubuntu` running on `linaro-lldb-arm-ubuntu` while building `clang` at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/18/builds/15088

<details>
<summary>Here is the relevant piece of the build log for the reference</summary>

```
Step 6 (test) failure: build (failure)
...
PASS: lldb-api :: symbol_ondemand/shared_library/TestSharedLibOnDemand.py (1146 of 3001)
PASS: lldb-api :: terminal/TestSTTYBeforeAndAfter.py (1147 of 3001)
PASS: lldb-api :: test_utils/TestDecorators.py (1148 of 3001)
PASS: lldb-api :: test_utils/TestInlineTest.py (1149 of 3001)
PASS: lldb-api :: test_utils/TestPExpectTest.py (1150 of 3001)
PASS: lldb-api :: test_utils/base/TestBaseTest.py (1151 of 3001)
PASS: lldb-api :: python_api/watchpoint/watchlocation/TestTargetWatchAddress.py (1152 of 3001)
PASS: lldb-api :: tools/lldb-dap/attach/TestDAP_attachByPortNum.py (1153 of 3001)
UNSUPPORTED: lldb-api :: tools/lldb-dap/breakpoint-events/TestDAP_breakpointEvents.py (1154 of 3001)
PASS: lldb-api :: terminal/TestEditline.py (1155 of 3001)
FAIL: lldb-api :: tools/lldb-dap/attach/TestDAP_attach.py (1156 of 3001)
******************** TEST 'lldb-api :: tools/lldb-dap/attach/TestDAP_attach.py' FAILED ********************
Script:
--
/usr/bin/python3.10 /home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./lib --env LLVM_INCLUDE_DIR=/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/include --env LLVM_TOOLS_DIR=/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin --arch armv8l --build-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/lldb-test-build.noindex --lldb-module-cache-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin/lldb --compiler /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin/clang --dsymutil /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin --lldb-obj-root /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/tools/lldb --lldb-libs-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./lib /home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/test/API/tools/lldb-dap/attach -p TestDAP_attach.py
--
Exit Code: 1

Command Output (stdout):
--
lldb version 21.0.0git (https://github.com/llvm/llvm-project.git revision 21fb19f3b5d572f608e959af895d781b9b24fbbd)
  clang revision 21fb19f3b5d572f608e959af895d781b9b24fbbd
  llvm revision 21fb19f3b5d572f608e959af895d781b9b24fbbd
Skipping the following test categories: ['libc++', 'dsym', 'gmodules', 'debugserver', 'objc']

--
Command Output (stderr):
--
========= DEBUG ADAPTER PROTOCOL LOGS =========
1745651006.068298101 --> (stdin/stdout) {"command":"initialize","type":"request","arguments":{"adapterID":"lldb-native","clientID":"vscode","columnsStartAt1":true,"linesStartAt1":true,"locale":"en-us","pathFormat":"path","supportsRunInTerminalRequest":true,"supportsVariablePaging":true,"supportsVariableType":true,"supportsStartDebuggingRequest":true,"supportsProgressReporting":true,"$__lldb_sourceInitFile":false},"seq":1}
1745651006.072639704 <-- (stdin/stdout) {"body":{"$__lldb_version":"lldb version 21.0.0git (https://github.com/llvm/llvm-project.git revision 21fb19f3b5d572f608e959af895d781b9b24fbbd)\n  clang revision 21fb19f3b5d572f608e959af895d781b9b24fbbd\n  llvm revision 21fb19f3b5d572f608e959af895d781b9b24fbbd","completionTriggerCharacters":["."," ","\t"],"exceptionBreakpointFilters":[{"default":false,"filter":"cpp_catch","label":"C++ Catch"},{"default":false,"filter":"cpp_throw","label":"C++ Throw"},{"default":false,"filter":"objc_catch","label":"Objective-C Catch"},{"default":false,"filter":"objc_throw","label":"Objective-C Throw"}],"supportTerminateDebuggee":true,"supportsBreakpointLocationsRequest":true,"supportsCancelRequest":true,"supportsCompletionsRequest":true,"supportsConditionalBreakpoints":true,"supportsConfigurationDoneRequest":true,"supportsDataBreakpoints":true,"supportsDelayedStackTraceLoading":true,"supportsDisassembleRequest":true,"supportsEvaluateForHovers":true,"supportsExceptionInfoRequest":true,"supportsExceptionOptions":true,"supportsFunctionBreakpoints":true,"supportsHitConditionalBreakpoints":true,"supportsInstructionBreakpoints":true,"supportsLogPoints":true,"supportsModulesRequest":true,"supportsReadMemoryRequest":true,"supportsRestartRequest":true,"supportsSetVariable":true,"supportsStepInTargetsRequest":true,"supportsSteppingGranularity":true,"supportsValueFormattingOptions":true},"command":"initialize","request_seq":1,"seq":0,"success":true,"type":"response"}
1745651006.073540688 --> (stdin/stdout) {"command":"attach","type":"request","arguments":{"program":"/tmp/lit-tmp-lz9mwtzv/tmpv73_0lcd","initCommands":["settings clear -all","settings set symbols.enable-external-lookup false","settings set target.inherit-tcc true","settings set target.disable-aslr false","settings set target.detach-on-error false","settings set target.auto-apply-fixits false","settings set plugin.process.gdb-remote.packet-timeout 60","settings set symbols.clang-modules-cache-path \"/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api\"","settings set use-color false","settings set show-statusline false"]},"seq":2}
1745651006.074194908 <-- (stdin/stdout) {"body":{"category":"console","output":"Running initCommands:\n"},"event":"output","seq":0,"type":"event"}
1745651006.074261189 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings clear -all\n"},"event":"output","seq":0,"type":"event"}
1745651006.074277401 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings set symbols.enable-external-lookup false\n"},"event":"output","seq":0,"type":"event"}
1745651006.074291468 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings set target.inherit-tcc true\n"},"event":"output","seq":0,"type":"event"}
1745651006.074304342 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings set target.disable-aslr false\n"},"event":"output","seq":0,"type":"event"}
1745651006.074316502 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings set target.detach-on-error false\n"},"event":"output","seq":0,"type":"event"}
1745651006.074328423 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings set target.auto-apply-fixits false\n"},"event":"output","seq":0,"type":"event"}
1745651006.074341059 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings set plugin.process.gdb-remote.packet-timeout 60\n"},"event":"output","seq":0,"type":"event"}
1745651006.074354887 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings set symbols.clang-modules-cache-path \"/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api\"\n"},"event":"output","seq":0,"type":"event"}
1745651006.074389696 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings set use-color false\n"},"event":"output","seq":0,"type":"event"}
1745651006.074403286 <-- (stdin/stdout) {"body":{"category":"console","output":"(lldb) settings set show-statusline false\n"},"event":"output","seq":0,"type":"event"}
1745651006.251921415 <-- (stdin/stdout) {"command":"attach","request_seq":2,"seq":0,"success":true,"type":"response"}
1745651006.252081156 <-- (stdin/stdout) {"body":{"isLocalProcess":true,"name":"/tmp/lit-tmp-lz9mwtzv/tmpv73_0lcd","startMethod":"attach","systemProcessId":2701527},"event":"process","seq":0,"type":"event"}
1745651006.252115726 <-- (stdin/stdout) {"event":"initialized","seq":0,"type":"event"}
1745651006.253348351 --> (stdin/stdout) {"command":"setBreakpoints","type":"request","arguments":{"source":{"name":"main.c","path":"main.c"},"sourceModified":false,"lines":[28],"breakpoints":[{"line":28}]},"seq":3}
1745651006.265577793 <-- (stdin/stdout) {"body":{"breakpoints":[{"column":3,"id":1,"instructionReference":"0x4607D8","line":28,"source":{"name":"main.c","path":"main.c"},"verified":true}]},"command":"setBreakpoints","request_seq":3,"seq":0,"success":true,"type":"response"}
1745651006.266095400 <-- (stdin/stdout) {"body":{"breakpoint":{"column":3,"id":1,"instructionReference":"0x4607D8","line":28,"verified":true},"reason":"changed"},"event":"breakpoint","seq":0,"type":"event"}

```

</details>
author_association: NONE
user: login: anutosh491
created_at: 2025-04-28T10:38:43Z
body: /cherry-pick [21fb19f](https://github.com/llvm/llvm-project/commit/21fb19f3b5d572f608e959af895d781b9b24fbbd)
author_association: MEMBER
user: login: llvmbot
created_at: 2025-04-28T10:44:32Z
body: <!--IGNORE-->
Failed to cherry-pick: [21fb19f](https://github.com/llvm/llvm-project/commit/21fb19f3b5d572f608e959af895d781b9b24fbbd)

https://github.com/llvm/llvm-project/actions/runs/14705725537

Please manually backport the fix and push it to your github fork.  Once this is done, please create a [pull request](https://github.com/llvm/llvm-project/compare)
author_association: MEMBER
user: login: anutosh491
created_at: 2025-04-28T10:52:55Z
body: /cherry-pick https://github.com/llvm/llvm-project/commit/21fb19f3b5d572f608e959af895d781b9b24fbbd
author_association: MEMBER
user: login: llvmbot
created_at: 2025-04-28T10:58:59Z
body: /pull-request llvm/llvm-project#137615
author_association: MEMBER