[clang] [CIR] Add Support for linking modules on cc1 (PR #196245)

2026-05-06 Thread David Rivera via cfe-commits

https://github.com/RiverDave edited 
https://github.com/llvm/llvm-project/pull/196245
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Add Support for linking modules on cc1 (PR #196245)

2026-05-06 Thread David Rivera via cfe-commits

https://github.com/RiverDave created 
https://github.com/llvm/llvm-project/pull/196245

I found certain unresolved external symbols when compiling polybench (for CUDA) 
specifically for libdevice - Therefore, this patch upstreams 
https://github.com/llvm/clangir/pull/2010/changes.

>From e47a97d0cfdf88b925c7f012b063640a3ff135aa Mon Sep 17 00:00:00 2001
From: David Rivera 
Date: Thu, 7 May 2026 06:18:01 +
Subject: [PATCH] [CIR] Add Support for linking modules on cc1

---
 clang/lib/CIR/FrontendAction/CIRGenAction.cpp | 79 +++
 clang/test/CIR/CodeGen/link-bitcode-file.c| 44 +++
 2 files changed, 123 insertions(+)
 create mode 100644 clang/test/CIR/CodeGen/link-bitcode-file.c

diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp 
b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
index af38872c5ca98..424fbd4f1186a 100644
--- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
+++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
@@ -16,9 +16,15 @@
 #include "clang/CodeGen/BackendUtil.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Bitcode/BitcodeReader.h"
+#include "llvm/IR/GlobalValue.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Linker/Linker.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/IPO/Internalize.h"
 
 using namespace cir;
 using namespace clang;
@@ -70,6 +76,15 @@ class CIRGenConsumer : public clang::ASTConsumer {
   const FrontendOptions &FEOptions;
   CodeGenOptions &CGO;
 
+  struct LinkModule {
+std::unique_ptr Module;
+bool PropagateAttrs;
+bool Internalize;
+unsigned LinkFlags;
+  };
+
+  SmallVector LinkModules;
+
 public:
   CIRGenConsumer(CIRGenAction::OutputType Action, CompilerInstance &CI,
  CodeGenOptions &CGO, std::unique_ptr OS)
@@ -160,10 +175,16 @@ class CIRGenConsumer : public clang::ASTConsumer {
   }
 
   llvm::LLVMContext LLVMCtx;
+  if (loadLinkModules(LLVMCtx))
+return;
+
   std::unique_ptr LLVMModule =
   lowerFromCIRToLLVMIR(MlirModule, LLVMCtx, mlirSaveTempsOutFile,
&CI.getVirtualFileSystem());
 
+  if (linkInModules(*LLVMModule))
+return;
+
   BackendAction BEAction = getBackendActionFromOutputType(Action);
   emitBackendOutput(
   CI, CI.getCodeGenOpts(), C.getTargetInfo().getDataLayoutString(),
@@ -173,6 +194,64 @@ class CIRGenConsumer : public clang::ASTConsumer {
 }
   }
 
+  bool loadLinkModules(llvm::LLVMContext &LLVMCtx) {
+if (!LinkModules.empty())
+  return false;
+
+for (const CodeGenOptions::BitcodeFileToLink &F :
+ CI.getCodeGenOpts().LinkBitcodeFiles) {
+  auto BCBuf = CI.getFileManager().getBufferForFile(F.Filename);
+  if (!BCBuf) {
+CI.getDiagnostics().Report(diag::err_cannot_open_file)
+<< F.Filename << BCBuf.getError().message();
+LinkModules.clear();
+return true;
+  }
+
+  llvm::Expected> ModuleOrErr =
+  llvm::getOwningLazyBitcodeModule(std::move(*BCBuf), LLVMCtx);
+  if (!ModuleOrErr) {
+llvm::handleAllErrors(
+ModuleOrErr.takeError(), [&](llvm::ErrorInfoBase &EIB) {
+  CI.getDiagnostics().Report(diag::err_cannot_open_file)
+  << F.Filename << EIB.message();
+});
+LinkModules.clear();
+return true;
+  }
+
+  LinkModules.push_back({std::move(ModuleOrErr.get()), F.PropagateAttrs,
+ F.Internalize, F.LinkFlags});
+}
+
+return false;
+  }
+
+  bool linkInModules(llvm::Module &M) {
+for (auto &LM : LinkModules) {
+  assert(LM.Module && "LinkModule does not actually have a module");
+
+  bool Err;
+  if (LM.Internalize) {
+Err = llvm::Linker::linkModules(
+M, std::move(LM.Module), LM.LinkFlags,
+[](llvm::Module &M, const llvm::StringSet<> &GVS) {
+  llvm::internalizeModule(M, [&GVS](const llvm::GlobalValue &GV) {
+return !GV.hasName() || (GVS.count(GV.getName()) == 0);
+  });
+});
+  } else {
+Err = llvm::Linker::linkModules(M, std::move(LM.Module), LM.LinkFlags);
+  }
+
+  if (Err)
+return true;
+}
+
+LinkModules.clear();
+return false;
+  }
+
   void HandleTagDeclDefinition(TagDecl *D) override {
 PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
Context->getSourceManager(),
diff --git a/clang/test/CIR/CodeGen/link-bitcode-file.c 
b/clang/test/CIR/CodeGen/link-bitcode-file.c
new file mode 100644
index 0..ca6c070699f81
--- /dev/null
+++ b/clang/test/CIR/CodeGen/link-bitcode-file.c
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -O1 -triple x86_64-unknown-linux-gnu -fclangir -DBITCODE 
-emit-llvm-bc -o %t.bc %s
+// RUN: %clang_cc1 -O1 -triple x86_64-un