[clang] 170d37d - [CIR] Add Support for linking bitcode modules on cc1 (#196245)

via cfe-commits cfe-commits at lists.llvm.org
Fri May 22 10:54:43 PDT 2026


Author: David Rivera
Date: 2026-05-22T13:54:39-04:00
New Revision: 170d37d861b036c5d645472dcc53a5d48e39e848

URL: https://github.com/llvm/llvm-project/commit/170d37d861b036c5d645472dcc53a5d48e39e848
DIFF: https://github.com/llvm/llvm-project/commit/170d37d861b036c5d645472dcc53a5d48e39e848.diff

LOG: [CIR] Add Support for linking bitcode modules on cc1 (#196245)

Co-authored-by: <konstantinos.parasyris at intel.com>

Added: 
    clang/include/clang/CodeGen/ModuleLinker.h
    clang/lib/CodeGen/ModuleLinker.cpp
    clang/test/CIR/CodeGen/link-bitcode-file.c

Modified: 
    clang/include/clang/CIR/FrontendAction/CIRGenAction.h
    clang/include/clang/CodeGen/CodeGenAction.h
    clang/lib/CIR/FrontendAction/CIRGenAction.cpp
    clang/lib/CIR/FrontendAction/CMakeLists.txt
    clang/lib/CodeGen/BackendConsumer.h
    clang/lib/CodeGen/CGCall.h
    clang/lib/CodeGen/CMakeLists.txt
    clang/lib/CodeGen/CodeGenAction.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/CIR/FrontendAction/CIRGenAction.h b/clang/include/clang/CIR/FrontendAction/CIRGenAction.h
index 99495f4718c5f..e803d18ec0ab6 100644
--- a/clang/include/clang/CIR/FrontendAction/CIRGenAction.h
+++ b/clang/include/clang/CIR/FrontendAction/CIRGenAction.h
@@ -9,11 +9,17 @@
 #ifndef LLVM_CLANG_CIR_CIRGENACTION_H
 #define LLVM_CLANG_CIR_CIRGENACTION_H
 
+#include "clang/CodeGen/ModuleLinker.h"
 #include "clang/Frontend/FrontendAction.h"
+#include "llvm/ADT/SmallVector.h"
 
 #include "mlir/IR/BuiltinOps.h"
 #include "mlir/IR/OwningOpRef.h"
 
+namespace llvm {
+class LLVMContext;
+} // namespace llvm
+
 namespace mlir {
 class MLIRContext;
 class ModuleOp;
@@ -39,9 +45,14 @@ class CIRGenAction : public clang::ASTFrontendAction {
 
   mlir::MLIRContext *MLIRCtx;
 
+  std::unique_ptr<llvm::LLVMContext> Ctx;
+  llvm::SmallVector<clang::LinkModule> LinkModules;
+
 protected:
   CIRGenAction(OutputType Action, mlir::MLIRContext *MLIRCtx = nullptr);
 
+  bool BeginSourceFileAction(clang::CompilerInstance &CI) override;
+
   std::unique_ptr<clang::ASTConsumer>
   CreateASTConsumer(clang::CompilerInstance &CI,
                     llvm::StringRef InFile) override;

diff  --git a/clang/include/clang/CodeGen/CodeGenAction.h b/clang/include/clang/CodeGen/CodeGenAction.h
index 186dbb43f01ef..84fa4549d5033 100644
--- a/clang/include/clang/CodeGen/CodeGenAction.h
+++ b/clang/include/clang/CodeGen/CodeGenAction.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_CLANG_CODEGEN_CODEGENACTION_H
 #define LLVM_CLANG_CODEGEN_CODEGENACTION_H
 
+#include "clang/CodeGen/ModuleLinker.h"
 #include "clang/Frontend/FrontendAction.h"
 #include <memory>
 
@@ -23,26 +24,6 @@ class CodeGenerator;
 
 class CodeGenAction : public ASTFrontendAction {
 private:
-  // Let BackendConsumer access LinkModule.
-  friend class BackendConsumer;
-
-  /// Info about module to link into a module we're generating.
-  struct LinkModule {
-    /// The module to link in.
-    std::unique_ptr<llvm::Module> Module;
-
-    /// If true, we set attributes on Module's functions according to our
-    /// CodeGenOptions and LangOptions, as though we were generating the
-    /// function ourselves.
-    bool PropagateAttrs;
-
-    /// If true, we use LLVM module internalizer.
-    bool Internalize;
-
-    /// Bitwise combination of llvm::LinkerFlags used when we link the module.
-    unsigned LinkFlags;
-  };
-
   unsigned Act;
   std::unique_ptr<llvm::Module> TheModule;
 
@@ -53,9 +34,6 @@ class CodeGenAction : public ASTFrontendAction {
 
   std::unique_ptr<llvm::Module> loadModule(llvm::MemoryBufferRef MBRef);
 
-  /// Load bitcode modules to link into our module from the options.
-  bool loadLinkModules(CompilerInstance &CI);
-
 protected:
   bool BeginSourceFileAction(CompilerInstance &CI) override;
 

diff  --git a/clang/include/clang/CodeGen/ModuleLinker.h b/clang/include/clang/CodeGen/ModuleLinker.h
new file mode 100644
index 0000000000000..4f94e6057f1e8
--- /dev/null
+++ b/clang/include/clang/CodeGen/ModuleLinker.h
@@ -0,0 +1,69 @@
+//===--- ModuleLinker.h - Shared bitcode link helpers ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGEN_MODULELINKER_H
+#define LLVM_CLANG_CODEGEN_MODULELINKER_H
+
+#include "llvm/ADT/SmallVector.h"
+#include <memory>
+
+namespace llvm {
+class Function;
+class LLVMContext;
+class Module;
+} // namespace llvm
+
+namespace clang {
+class CodeGenOptions;
+class CompilerInstance;
+class LangOptions;
+class TargetOptions;
+
+/// Info about a module to link into the module currently being generated.
+/// Shared between the classic clang CodeGen path and the ClangIR path.
+struct LinkModule {
+  std::unique_ptr<llvm::Module> Module;
+  bool PropagateAttrs;
+  bool Internalize;
+  unsigned LinkFlags;
+};
+
+/// Load every bitcode file listed in CodeGenOpts.LinkBitcodeFiles into
+/// \p LinkModules. Returns true on error (diagnostic already reported).
+/// Appends to \p LinkModules; does not clear it.
+bool loadLinkModules(CompilerInstance &CI, llvm::LLVMContext &Ctx,
+                     llvm::SmallVectorImpl<LinkModule> &LinkModules);
+
+namespace CodeGen {
+/// Adds attributes to \p F according to our \p CodeGenOpts and \p LangOpts, as
+/// though we had emitted it ourselves. We remove any attributes on F that
+/// conflict with the attributes we add here.
+///
+/// This is useful for adding attrs to bitcode modules that you want to link
+/// with but don't control, such as CUDA's libdevice.  When linking with such
+/// a bitcode library, you might want to set e.g. its functions'
+/// denormal_fp_math attribute to match the attr of the functions you're
+/// codegen'ing.  Otherwise, LLVM will interpret the bitcode module's lack of
+/// denormal-fp-math attrs as tantamount to denormal-fp-math=ieee, and then LLVM
+/// will propagate denormal-fp-math=ieee up to every transitive caller of a
+/// function in the bitcode library!
+///
+/// With the exception of fast-math attrs, this will only make the attributes
+/// on the function more conservative.  But it's unsafe to call this on a
+/// function which relies on particular fast-math attributes for correctness.
+/// It's up to you to ensure that this is safe.
+void mergeDefaultFunctionDefinitionAttributes(llvm::Function &F,
+                                              const CodeGenOptions &CodeGenOpts,
+                                              const LangOptions &LangOpts,
+                                              const TargetOptions &TargetOpts,
+                                              bool WillInternalize);
+} // namespace CodeGen
+
+} // namespace clang
+
+#endif

diff  --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
index af38872c5ca98..fccd270a95ccd 100644
--- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
+++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
@@ -14,11 +14,20 @@
 #include "clang/CIR/CIRToCIRPasses.h"
 #include "clang/CIR/LowerToLLVM.h"
 #include "clang/CodeGen/BackendUtil.h"
+#include "clang/CodeGen/ModuleLinker.h"
 #include "clang/Frontend/CompilerInstance.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/IR/DiagnosticHandler.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Linker/Linker.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,14 +79,20 @@ class CIRGenConsumer : public clang::ASTConsumer {
   const FrontendOptions &FEOptions;
   CodeGenOptions &CGO;
 
+  llvm::LLVMContext &LLVMCtx;
+  SmallVectorImpl<::clang::LinkModule> &LinkModules;
+
 public:
   CIRGenConsumer(CIRGenAction::OutputType Action, CompilerInstance &CI,
-                 CodeGenOptions &CGO, std::unique_ptr<raw_pwrite_stream> OS)
+                 CodeGenOptions &CGO, std::unique_ptr<raw_pwrite_stream> OS,
+                 llvm::LLVMContext &LLVMCtx,
+                 SmallVectorImpl<::clang::LinkModule> &LinkModules)
       : Action(Action), CI(CI), OutputStream(std::move(OS)),
         FS(&CI.getVirtualFileSystem()),
         Gen(std::make_unique<CIRGenerator>(CI.getDiagnostics(), std::move(FS),
                                            CI.getCodeGenOpts())),
-        FEOptions(CI.getFrontendOpts()), CGO(CGO) {}
+        FEOptions(CI.getFrontendOpts()), CGO(CGO), LLVMCtx(LLVMCtx),
+        LinkModules(LinkModules) {}
 
   void Initialize(ASTContext &Ctx) override {
     assert(!Context && "initialized multiple times");
@@ -159,11 +174,13 @@ class CIRGenConsumer : public clang::ASTConsumer {
           MlirModule->print(out);
       }
 
-      llvm::LLVMContext LLVMCtx;
       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 +190,41 @@ class CIRGenConsumer : public clang::ASTConsumer {
     }
   }
 
+  // TODO: share with BackendConsumer::LinkInModules once OG's CurLinkModule
+  // diagnostic-handler indirection is abstracted behind a callback for CIR.
+  bool linkInModules(llvm::Module &M) {
+    for (auto &LM : LinkModules) {
+      assert(LM.Module && "LinkModule does not actually have a module");
+
+      if (LM.PropagateAttrs)
+        for (llvm::Function &F : *LM.Module) {
+          if (F.isIntrinsic())
+            continue;
+          clang::CodeGen::mergeDefaultFunctionDefinitionAttributes(
+              F, CGO, CI.getLangOpts(), CI.getTargetOpts(), LM.Internalize);
+        }
+
+      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(),
@@ -195,10 +247,17 @@ class CIRGenConsumer : public clang::ASTConsumer {
 void CIRGenConsumer::anchor() {}
 
 CIRGenAction::CIRGenAction(OutputType Act, mlir::MLIRContext *MLIRCtx)
-    : MLIRCtx(MLIRCtx ? MLIRCtx : new mlir::MLIRContext), Action(Act) {}
+    : MLIRCtx(MLIRCtx ? MLIRCtx : new mlir::MLIRContext),
+      Ctx(std::make_unique<llvm::LLVMContext>()), Action(Act) {}
 
 CIRGenAction::~CIRGenAction() { MLIRMod.release(); }
 
+bool CIRGenAction::BeginSourceFileAction(CompilerInstance &CI) {
+  if (clang::loadLinkModules(CI, *Ctx, LinkModules))
+    return false;
+  return ASTFrontendAction::BeginSourceFileAction(CI);
+}
+
 static std::unique_ptr<raw_pwrite_stream>
 getOutputStream(CompilerInstance &CI, StringRef InFile,
                 CIRGenAction::OutputType Action) {
@@ -225,7 +284,7 @@ CIRGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
     Out = getOutputStream(CI, InFile, Action);
 
   auto Result = std::make_unique<cir::CIRGenConsumer>(
-      Action, CI, CI.getCodeGenOpts(), std::move(Out));
+      Action, CI, CI.getCodeGenOpts(), std::move(Out), *Ctx, LinkModules);
 
   return Result;
 }

diff  --git a/clang/lib/CIR/FrontendAction/CMakeLists.txt b/clang/lib/CIR/FrontendAction/CMakeLists.txt
index 50d6ea7108ce1..b2d2fc1621693 100644
--- a/clang/lib/CIR/FrontendAction/CMakeLists.txt
+++ b/clang/lib/CIR/FrontendAction/CMakeLists.txt
@@ -1,5 +1,7 @@
 set(LLVM_LINK_COMPONENTS
   Core
+  ipo
+  Linker
   Support
   )
 

diff  --git a/clang/lib/CodeGen/BackendConsumer.h b/clang/lib/CodeGen/BackendConsumer.h
index b7bbb81074836..eeac13bd42379 100644
--- a/clang/lib/CodeGen/BackendConsumer.h
+++ b/clang/lib/CodeGen/BackendConsumer.h
@@ -11,6 +11,7 @@
 
 #include "clang/CodeGen/BackendUtil.h"
 #include "clang/CodeGen/CodeGenAction.h"
+#include "clang/CodeGen/ModuleLinker.h"
 
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/Support/Timer.h"
@@ -25,8 +26,6 @@ class CodeGenAction;
 class CoverageSourceInfo;
 
 class BackendConsumer : public ASTConsumer {
-  using LinkModule = CodeGenAction::LinkModule;
-
   virtual void anchor();
   CompilerInstance &CI;
   DiagnosticsEngine &Diags;

diff  --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h
index fdf17fb530788..675c448ab0b00 100644
--- a/clang/lib/CodeGen/CGCall.h
+++ b/clang/lib/CodeGen/CGCall.h
@@ -21,6 +21,7 @@
 #include "clang/AST/CanonicalType.h"
 #include "clang/AST/GlobalDecl.h"
 #include "clang/AST/Type.h"
+#include "clang/CodeGen/ModuleLinker.h"
 #include "llvm/ADT/STLForwardCompat.h"
 #include "llvm/IR/Value.h"
 
@@ -405,29 +406,6 @@ class ReturnValueSlot {
   Address getAddress() const { return Addr; }
 };
 
-/// Adds attributes to \p F according to our \p CodeGenOpts and \p LangOpts, as
-/// though we had emitted it ourselves. We remove any attributes on F that
-/// conflict with the attributes we add here.
-///
-/// This is useful for adding attrs to bitcode modules that you want to link
-/// with but don't control, such as CUDA's libdevice.  When linking with such
-/// a bitcode library, you might want to set e.g. its functions'
-/// denormal_fp_math attribute to match the attr of the functions you're
-/// codegen'ing.  Otherwise, LLVM will interpret the bitcode module's lack of
-/// denormal-fp-math attrs as tantamount to denormal-fp-math=ieee, and then LLVM
-/// will propagate denormal-fp-math=ieee up to every transitive caller of a
-/// function in the bitcode library!
-///
-/// With the exception of fast-math attrs, this will only make the attributes
-/// on the function more conservative.  But it's unsafe to call this on a
-/// function which relies on particular fast-math attributes for correctness.
-/// It's up to you to ensure that this is safe.
-void mergeDefaultFunctionDefinitionAttributes(llvm::Function &F,
-                                              const CodeGenOptions &CodeGenOpts,
-                                              const LangOptions &LangOpts,
-                                              const TargetOptions &TargetOpts,
-                                              bool WillInternalize);
-
 enum class FnInfoOpts {
   None = 0,
   IsInstanceMethod = 1 << 0,

diff  --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt
index 117438c616ab5..75b2f5826f863 100644
--- a/clang/lib/CodeGen/CMakeLists.txt
+++ b/clang/lib/CodeGen/CMakeLists.txt
@@ -115,6 +115,7 @@ add_clang_library(clangCodeGen
   MacroPPCallbacks.cpp
   MicrosoftCXXABI.cpp
   ModuleBuilder.cpp
+  ModuleLinker.cpp
   ObjectFilePCHContainerWriter.cpp
   PatternInit.cpp
   QualTypeMapper.cpp

diff  --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp
index 73bf49b1a8046..fb1a410ce1761 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -911,36 +911,6 @@ CodeGenAction::~CodeGenAction() {
     delete VMContext;
 }
 
-bool CodeGenAction::loadLinkModules(CompilerInstance &CI) {
-  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;
-    }
-
-    Expected<std::unique_ptr<llvm::Module>> ModuleOrErr =
-        getOwningLazyBitcodeModule(std::move(*BCBuf), *VMContext);
-    if (!ModuleOrErr) {
-      handleAllErrors(ModuleOrErr.takeError(), [&](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 CodeGenAction::hasIRSupport() const { return true; }
 
 void CodeGenAction::EndSourceFileAction() {
@@ -1004,7 +974,7 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
     return nullptr;
 
   // Load bitcode modules to link with, if we need to.
-  if (loadLinkModules(CI))
+  if (clang::loadLinkModules(CI, *VMContext, LinkModules))
     return nullptr;
 
   CoverageSourceInfo *CoverageInfo = nullptr;
@@ -1082,7 +1052,7 @@ CodeGenAction::loadModule(MemoryBufferRef MBRef) {
   }
 
   // Load bitcode modules to link with, if we need to.
-  if (loadLinkModules(CI))
+  if (clang::loadLinkModules(CI, *VMContext, LinkModules))
     return nullptr;
 
   // Handle textual IR and bitcode file with one single module.

diff  --git a/clang/lib/CodeGen/ModuleLinker.cpp b/clang/lib/CodeGen/ModuleLinker.cpp
new file mode 100644
index 0000000000000..6c876276e344b
--- /dev/null
+++ b/clang/lib/CodeGen/ModuleLinker.cpp
@@ -0,0 +1,49 @@
+//===--- ModuleLinker.cpp - Shared bitcode link helpers -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CodeGen/ModuleLinker.h"
+
+#include "clang/Basic/CodeGenOptions.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "llvm/Bitcode/BitcodeReader.h"
+#include "llvm/IR/Module.h"
+
+using namespace clang;
+
+bool clang::loadLinkModules(CompilerInstance &CI, llvm::LLVMContext &Ctx,
+                            llvm::SmallVectorImpl<LinkModule> &LinkModules) {
+  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), Ctx);
+    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;
+}

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..d8b372499061f
--- /dev/null
+++ b/clang/test/CIR/CodeGen/link-bitcode-file.c
@@ -0,0 +1,70 @@
+// 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
+//
+// -mlink-builtin-bitcode propagates the host TU's default function-definition
+// attributes onto linked-in functions. Linking at -O0 keeps f from being
+// inlined into g so the propagated attribute group is observable.
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -target-cpu skylake -fclangir \
+// RUN:     -mlink-builtin-bitcode %t.bc -emit-llvm -o - %s \
+// RUN:     | FileCheck -check-prefix=CHECK-PROPAGATE %s
+//
+// -mlink-bitcode-file does NOT propagate (PropagateAttrs=false).
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -target-cpu skylake -fclangir \
+// RUN:     -mlink-bitcode-file %t.bc -emit-llvm -o - %s \
+// RUN:     | FileCheck -check-prefix=CHECK-NO-PROPAGATE %s
+
+int f(void);
+
+#ifdef BITCODE
+
+extern int f2(void);
+
+volatile int gvar = 7;
+
+int f(void) {
+  f2();
+  return 42;
+}
+
+#elif defined(BITCODE2)
+int f2(void) { return 43; }
+#else
+
+extern volatile int gvar;
+
+// -mlink-bitcode-file leaves linked symbols with external linkage.
+// CHECK-BC: @gvar = global i32 7
+// -mlink-builtin-bitcode internalizes linked symbols not referenced as roots.
+// CHECK-BUILTIN-BC: @gvar = internal global i32 7
+
+// 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) {
+  gvar = 1;
+  return f();
+}
+
+// CHECK-BC-LABEL: define{{.*}} i32 @f
+// CHECK-BC2-LABEL: define{{.*}} i32 @f2
+
+// CHECK-PROPAGATE: define internal{{.*}} i32 @f(){{[^#]*}}#[[F_ATTRS:[0-9]+]]
+// CHECK-PROPAGATE: attributes #[[F_ATTRS]] = {{.*}}"target-cpu"="skylake"
+
+// CHECK-NO-PROPAGATE: define{{.*}} i32 @f(){{[^#]*}}#[[F_ATTRS:[0-9]+]]
+// CHECK-NO-PROPAGATE-NOT: attributes #[[F_ATTRS]] = {{.*}}"target-cpu"="skylake"
+
+#endif
+
+// CHECK-NO-FILE: fatal error: cannot open file 'no-such-file.bc'


        


More information about the cfe-commits mailing list