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 <[email protected]> Date: Thu, 7 May 2026 06:18:01 +0000 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<llvm::Module> Module; + bool PropagateAttrs; + bool Internalize; + unsigned LinkFlags; + }; + + SmallVector<LinkModule, 4> LinkModules; + public: CIRGenConsumer(CIRGenAction::OutputType Action, CompilerInstance &CI, CodeGenOptions &CGO, std::unique_ptr<raw_pwrite_stream> OS) @@ -160,10 +175,16 @@ class CIRGenConsumer : public clang::ASTConsumer { } llvm::LLVMContext LLVMCtx; + if (loadLinkModules(LLVMCtx)) + return; + std::unique_ptr<llvm::Module> 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<std::unique_ptr<llvm::Module>> 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 0000000000000..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-unknown-linux-gnu -fclangir -DBITCODE2 -emit-llvm-bc -o %t-2.bc %s +// RUN: %clang_cc1 -O1 -triple x86_64-unknown-linux-gnu -fclangir -mlink-bitcode-file %t.bc \ +// RUN: -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-BC %s +// RUN: %clang_cc1 -O1 -triple x86_64-unknown-linux-gnu -fclangir -mlink-builtin-bitcode %t.bc \ +// RUN: -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-BUILTIN-BC %s +// RUN: %clang_cc1 -O1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -o - \ +// RUN: -mlink-bitcode-file %t.bc -mlink-bitcode-file %t-2.bc %s \ +// RUN: | FileCheck -check-prefix=CHECK-BC -check-prefix=CHECK-BC2 %s +// RUN: not %clang_cc1 -O1 -triple x86_64-unknown-linux-gnu -fclangir \ +// RUN: -mlink-bitcode-file no-such-file.bc -emit-llvm -o - %s 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-NO-FILE %s + +int f(void); + +#ifdef BITCODE + +extern int f2(void); + +int f(void) { + f2(); + return 42; +} + +#elif defined(BITCODE2) + +int f2(void) { return 43; } + +#else + +// CHECK-BC-LABEL: define{{.*}} i32 @g +// CHECK-BC: ret i32 42 +// CHECK-BUILTIN-BC-LABEL: define{{.*}} i32 @g +// CHECK-BUILTIN-BC: ret i32 42 +int g(void) { + return f(); +} + +// CHECK-BC-LABEL: define{{.*}} i32 @f +// CHECK-BC2-LABEL: define{{.*}} i32 @f2 + +#endif + +// CHECK-NO-FILE: fatal error: cannot open file 'no-such-file.bc' _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
