[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