[clang] [CIR] Upstream global variable linkage types (PR #129072)
Morris Hafner via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 5 07:54:03 PST 2025
https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/129072
>From f19e6f6c5da44bd47c71a1b3d047aa1a0df96568 Mon Sep 17 00:00:00 2001
From: Morris Hafner <mhafner at nvidia.com>
Date: Wed, 5 Mar 2025 16:36:21 +0100
Subject: [PATCH 1/7] [CIR] Upstream global variable linkage types
This change implements variable linkage types in ClangIR except for common linkage which requires Comdat support.
---
.../include/clang/CIR/Dialect/IR/CIRDialect.h | 2 +
clang/include/clang/CIR/Dialect/IR/CIROps.td | 83 ++++++-
.../clang/CIR/Dialect/IR/CIROpsEnums.h | 119 +++++++++++
.../clang/CIR/Dialect/IR/CMakeLists.txt | 4 +-
.../clang/CIR/Interfaces/CIROpInterfaces.h | 29 +++
.../clang/CIR/Interfaces/CIROpInterfaces.td | 63 ++++++
.../clang/CIR/Interfaces/CMakeLists.txt | 9 +
clang/include/clang/CIR/MissingFeatures.h | 4 +
clang/lib/CIR/CodeGen/CIRGenModule.cpp | 202 +++++++++++++++++-
clang/lib/CIR/CodeGen/CIRGenModule.h | 12 ++
clang/lib/CIR/CodeGen/CMakeLists.txt | 1 +
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 8 +-
clang/lib/CIR/Dialect/IR/CMakeLists.txt | 3 +-
clang/lib/CIR/FrontendAction/CMakeLists.txt | 4 +
clang/lib/CIR/Interfaces/CIROpInterfaces.cpp | 22 ++
clang/lib/CIR/Interfaces/CMakeLists.txt | 4 +-
.../CIR/Lowering/DirectToLLVM/CMakeLists.txt | 5 +
clang/test/CIR/global-var-simple.cpp | 64 +++---
clang/test/CIR/global_var_linkage.cpp | 11 +
19 files changed, 608 insertions(+), 41 deletions(-)
create mode 100644 clang/include/clang/CIR/Dialect/IR/CIROpsEnums.h
create mode 100644 clang/include/clang/CIR/Interfaces/CIROpInterfaces.h
create mode 100644 clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
create mode 100644 clang/lib/CIR/Interfaces/CIROpInterfaces.cpp
create mode 100644 clang/test/CIR/global_var_linkage.cpp
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
index 683176b139ca4..0684cf5034f5d 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
@@ -28,6 +28,8 @@
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIROpsDialect.h.inc"
+#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
+#include "clang/CIR/Interfaces/CIROpInterfaces.h"
// TableGen'erated files for MLIR dialects require that a macro be defined when
// they are included. GET_OP_CLASSES tells the file to define the classes for
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 48178b0ff247d..2cef98099fdbb 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -18,6 +18,8 @@ include "clang/CIR/Dialect/IR/CIRDialect.td"
include "clang/CIR/Dialect/IR/CIRTypes.td"
include "clang/CIR/Dialect/IR/CIRAttrs.td"
+include "clang/CIR/Interfaces/CIROpInterfaces.td"
+
include "mlir/IR/BuiltinAttributeInterfaces.td"
include "mlir/IR/EnumAttr.td"
include "mlir/IR/SymbolInterfaces.td"
@@ -430,6 +432,59 @@ def ScopeOp : CIR_Op<"scope", [
// GlobalOp
//===----------------------------------------------------------------------===//
+// Linkage types. This is currently a replay of llvm/IR/GlobalValue.h, this is
+// currently handy as part of forwarding appropriate linkage types for LLVM
+// lowering, specially useful for C++ support.
+
+// Externally visible function
+def Global_ExternalLinkage :
+ I32EnumAttrCase<"ExternalLinkage", 0, "external">;
+// Available for inspection, not emission.
+def Global_AvailableExternallyLinkage :
+ I32EnumAttrCase<"AvailableExternallyLinkage", 1, "available_externally">;
+// Keep one copy of function when linking (inline)
+def Global_LinkOnceAnyLinkage :
+ I32EnumAttrCase<"LinkOnceAnyLinkage", 2, "linkonce">;
+// Same, but only replaced by something equivalent.
+def Global_LinkOnceODRLinkage :
+ I32EnumAttrCase<"LinkOnceODRLinkage", 3, "linkonce_odr">;
+// Keep one copy of named function when linking (weak)
+def Global_WeakAnyLinkage :
+ I32EnumAttrCase<"WeakAnyLinkage", 4, "weak">;
+// Same, but only replaced by something equivalent.
+def Global_WeakODRLinkage :
+ I32EnumAttrCase<"WeakODRLinkage", 5, "weak_odr">;
+// TODO: should we add something like appending linkage too?
+// Special purpose, only applies to global arrays
+// def Global_AppendingLinkage :
+// I32EnumAttrCase<"AppendingLinkage", 6, "appending">;
+// Rename collisions when linking (static functions).
+def Global_InternalLinkage :
+ I32EnumAttrCase<"InternalLinkage", 7, "internal">;
+// Like Internal, but omit from symbol table, prefix it with
+// "cir_" to prevent clash with MLIR's symbol "private".
+def Global_PrivateLinkage :
+ I32EnumAttrCase<"PrivateLinkage", 8, "cir_private">;
+// ExternalWeak linkage description.
+def Global_ExternalWeakLinkage :
+ I32EnumAttrCase<"ExternalWeakLinkage", 9, "extern_weak">;
+// Tentative definitions.
+def Global_CommonLinkage :
+ I32EnumAttrCase<"CommonLinkage", 10, "common">;
+
+/// An enumeration for the kinds of linkage for global values.
+def GlobalLinkageKind : I32EnumAttr<
+ "GlobalLinkageKind",
+ "Linkage type/kind",
+ [Global_ExternalLinkage, Global_AvailableExternallyLinkage,
+ Global_LinkOnceAnyLinkage, Global_LinkOnceODRLinkage,
+ Global_WeakAnyLinkage, Global_WeakODRLinkage,
+ Global_InternalLinkage, Global_PrivateLinkage,
+ Global_ExternalWeakLinkage, Global_CommonLinkage
+ ]> {
+ let cppNamespace = "::cir";
+}
+
// TODO(CIR): For starters, cir.global has only name and type. The other
// properties of a global variable will be added over time as more of ClangIR
// is upstreamed.
@@ -441,12 +496,19 @@ def GlobalOp : CIR_Op<"global"> {
The backing memory for the variable is allocated statically and is
described by the type of the variable.
+
+ The `linkage` tracks C/C++ linkage types, currently very similar to LLVM's.
}];
- let arguments = (ins SymbolNameAttr:$sym_name, TypeAttr:$sym_type,
- OptionalAttr<AnyAttr>:$initial_value);
+ let arguments = (ins SymbolNameAttr:$sym_name,
+ TypeAttr:$sym_type,
+ Arg<GlobalLinkageKind, "linkage type">:$linkage,
+ OptionalAttr<AnyAttr>:$initial_value,
+ UnitAttr:$dsolocal);
let assemblyFormat = [{
+ $linkage
+ (`dsolocal` $dsolocal^)?
$sym_name
custom<GlobalOpTypeAndInitialValue>($sym_type, $initial_value)
attr-dict
@@ -455,12 +517,25 @@ def GlobalOp : CIR_Op<"global"> {
let extraClassDeclaration = [{
bool isDeclaration() { return !getInitialValue(); }
bool hasInitializer() { return !isDeclaration(); }
+ bool hasAvailableExternallyLinkage() {
+ return cir::isAvailableExternallyLinkage(getLinkage());
+ }
+ bool hasInternalLinkage() {
+ return cir::isInternalLinkage(getLinkage());
+ }
+ /// Whether the definition of this global may be replaced at link time.
+ bool isWeakForLinker() { return cir::isWeakForLinker(getLinkage()); }
+ bool isDSOLocal() { return getDsolocal(); }
}];
let skipDefaultBuilders = 1;
- let builders = [OpBuilder<(ins "llvm::StringRef":$sym_name,
- "mlir::Type":$sym_type)>];
+ let builders = [OpBuilder<(ins
+ "llvm::StringRef":$sym_name,
+ "mlir::Type":$sym_type,
+ // CIR defaults to external linkage.
+ CArg<"cir::GlobalLinkageKind",
+ "cir::GlobalLinkageKind::ExternalLinkage">:$linkage)>];
let hasVerifier = 1;
}
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROpsEnums.h b/clang/include/clang/CIR/Dialect/IR/CIROpsEnums.h
new file mode 100644
index 0000000000000..a1e32209555f3
--- /dev/null
+++ b/clang/include/clang/CIR/Dialect/IR/CIROpsEnums.h
@@ -0,0 +1,119 @@
+//===- CIROpsEnumsDialect.h - MLIR Dialect for CIR ----------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the Target dialect for CIR in MLIR.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_CIR_CIROPSENUMS_H_
+#define MLIR_DIALECT_CIR_CIROPSENUMS_H_
+
+#include "mlir/IR/BuiltinAttributes.h"
+#include "clang/CIR/Dialect/IR/CIROpsEnums.h.inc"
+
+namespace cir {
+
+static bool isExternalLinkage(GlobalLinkageKind linkage) {
+ return linkage == GlobalLinkageKind::ExternalLinkage;
+}
+static bool isAvailableExternallyLinkage(GlobalLinkageKind linkage) {
+ return linkage == GlobalLinkageKind::AvailableExternallyLinkage;
+}
+static bool isLinkOnceAnyLinkage(GlobalLinkageKind linkage) {
+ return linkage == GlobalLinkageKind::LinkOnceAnyLinkage;
+}
+static bool isLinkOnceODRLinkage(GlobalLinkageKind linkage) {
+ return linkage == GlobalLinkageKind::LinkOnceODRLinkage;
+}
+static bool isLinkOnceLinkage(GlobalLinkageKind linkage) {
+ return isLinkOnceAnyLinkage(linkage) || isLinkOnceODRLinkage(linkage);
+}
+static bool isWeakAnyLinkage(GlobalLinkageKind linkage) {
+ return linkage == GlobalLinkageKind::WeakAnyLinkage;
+}
+static bool isWeakODRLinkage(GlobalLinkageKind linkage) {
+ return linkage == GlobalLinkageKind::WeakODRLinkage;
+}
+static bool isWeakLinkage(GlobalLinkageKind linkage) {
+ return isWeakAnyLinkage(linkage) || isWeakODRLinkage(linkage);
+}
+static bool isInternalLinkage(GlobalLinkageKind linkage) {
+ return linkage == GlobalLinkageKind::InternalLinkage;
+}
+static bool isPrivateLinkage(GlobalLinkageKind linkage) {
+ return linkage == GlobalLinkageKind::PrivateLinkage;
+}
+static bool isLocalLinkage(GlobalLinkageKind linkage) {
+ return isInternalLinkage(linkage) || isPrivateLinkage(linkage);
+}
+static bool isExternalWeakLinkage(GlobalLinkageKind linkage) {
+ return linkage == GlobalLinkageKind::ExternalWeakLinkage;
+}
+LLVM_ATTRIBUTE_UNUSED static bool isCommonLinkage(GlobalLinkageKind linkage) {
+ return linkage == GlobalLinkageKind::CommonLinkage;
+}
+LLVM_ATTRIBUTE_UNUSED static bool
+isValidDeclarationLinkage(GlobalLinkageKind linkage) {
+ return isExternalWeakLinkage(linkage) || isExternalLinkage(linkage);
+}
+
+/// Whether the definition of this global may be replaced by something
+/// non-equivalent at link time. For example, if a function has weak linkage
+/// then the code defining it may be replaced by different code.
+LLVM_ATTRIBUTE_UNUSED static bool
+isInterposableLinkage(GlobalLinkageKind linkage) {
+ switch (linkage) {
+ case GlobalLinkageKind::WeakAnyLinkage:
+ case GlobalLinkageKind::LinkOnceAnyLinkage:
+ case GlobalLinkageKind::CommonLinkage:
+ case GlobalLinkageKind::ExternalWeakLinkage:
+ return true;
+
+ case GlobalLinkageKind::AvailableExternallyLinkage:
+ case GlobalLinkageKind::LinkOnceODRLinkage:
+ case GlobalLinkageKind::WeakODRLinkage:
+ // The above three cannot be overridden but can be de-refined.
+
+ case GlobalLinkageKind::ExternalLinkage:
+ case GlobalLinkageKind::InternalLinkage:
+ case GlobalLinkageKind::PrivateLinkage:
+ return false;
+ }
+ llvm_unreachable("Fully covered switch above!");
+}
+
+/// Whether the definition of this global may be discarded if it is not used
+/// in its compilation unit.
+LLVM_ATTRIBUTE_UNUSED static bool
+isDiscardableIfUnused(GlobalLinkageKind linkage) {
+ return isLinkOnceLinkage(linkage) || isLocalLinkage(linkage) ||
+ isAvailableExternallyLinkage(linkage);
+}
+
+/// Whether the definition of this global may be replaced at link time. NB:
+/// Using this method outside of the code generators is almost always a
+/// mistake: when working at the IR level use isInterposable instead as it
+/// knows about ODR semantics.
+LLVM_ATTRIBUTE_UNUSED static bool isWeakForLinker(GlobalLinkageKind linkage) {
+ return linkage == GlobalLinkageKind::WeakAnyLinkage ||
+ linkage == GlobalLinkageKind::WeakODRLinkage ||
+ linkage == GlobalLinkageKind::LinkOnceAnyLinkage ||
+ linkage == GlobalLinkageKind::LinkOnceODRLinkage ||
+ linkage == GlobalLinkageKind::CommonLinkage ||
+ linkage == GlobalLinkageKind::ExternalWeakLinkage;
+}
+
+LLVM_ATTRIBUTE_UNUSED static bool isValidLinkage(GlobalLinkageKind gl) {
+ return isExternalLinkage(gl) || isLocalLinkage(gl) || isWeakLinkage(gl) ||
+ isLinkOnceLinkage(gl);
+}
+
+} // namespace cir
+
+#endif // MLIR_DIALECT_CIR_CIROPSENUMS_H_
diff --git a/clang/include/clang/CIR/Dialect/IR/CMakeLists.txt b/clang/include/clang/CIR/Dialect/IR/CMakeLists.txt
index 1fdbc24ba6b4a..39292fb541daa 100644
--- a/clang/include/clang/CIR/Dialect/IR/CMakeLists.txt
+++ b/clang/include/clang/CIR/Dialect/IR/CMakeLists.txt
@@ -16,4 +16,6 @@ add_dependencies(mlir-headers MLIRCIROpsIncGen)
mlir_tablegen(CIROpsAttributes.h.inc -gen-attrdef-decls)
mlir_tablegen(CIROpsAttributes.cpp.inc -gen-attrdef-defs)
-add_public_tablegen_target(MLIRCIRAttrsEnumsGen)
+mlir_tablegen(CIROpsEnums.h.inc -gen-enum-decls)
+mlir_tablegen(CIROpsEnums.cpp.inc -gen-enum-defs)
+add_public_tablegen_target(MLIRCIREnumsGen)
diff --git a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.h b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.h
new file mode 100644
index 0000000000000..86064619af7db
--- /dev/null
+++ b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.h
@@ -0,0 +1,29 @@
+//===- CIROpInterfaces.h - CIR Op Interfaces --------------------*- 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 MLIR_INTERFACES_CIR_OP_H_
+#define MLIR_INTERFACES_CIR_OP_H_
+
+#include "mlir/IR/Attributes.h"
+#include "mlir/IR/Operation.h"
+#include "mlir/IR/Value.h"
+#include "mlir/Interfaces/CallInterfaces.h"
+
+#include "clang/AST/Attr.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Mangle.h"
+#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
+
+namespace cir {} // namespace cir
+
+/// Include the generated interface declarations.
+#include "clang/CIR/Interfaces/CIROpInterfaces.h.inc"
+
+namespace cir {} // namespace cir
+
+#endif // MLIR_INTERFACES_CIR_OP_H_
diff --git a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
new file mode 100644
index 0000000000000..b765a3e65f70b
--- /dev/null
+++ b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
@@ -0,0 +1,63 @@
+//===- CIROpInterfaces.td - CIR Op Interface Definitions --------*- 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 MLIR_CIR_OP_INTERFACES
+#define MLIR_CIR_OP_INTERFACES
+
+include "mlir/IR/OpBase.td"
+
+let cppNamespace = "::cir" in {
+ def CIRGlobalValueInterface
+ : OpInterface<"CIRGlobalValueInterface"> {
+
+ let methods = [
+ InterfaceMethod<"",
+ "bool", "hasAvailableExternallyLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{ return false; }]
+ >,
+ InterfaceMethod<"",
+ "bool", "hasLocalLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
+ return cir::isLocalLinkage($_op.getLinkage());
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "hasExternalWeakLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
+ return cir::isExternalWeakLinkage($_op.getLinkage());
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "isExternalLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
+ return cir::isExternalLinkage($_op.getLinkage());
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "isDeclarationForLinker", (ins), [{}],
+ /*defaultImplementation=*/[{
+ if ($_op.hasAvailableExternallyLinkage())
+ return true;
+ return $_op.isDeclaration();
+ }]
+ >,
+ InterfaceMethod<"",
+ "void", "setDSOLocal", (ins "bool":$val), [{}],
+ /*defaultImplementation=*/[{
+ $_op.setDsolocal(val);
+ }]
+ >,
+ ];
+ let extraClassDeclaration = [{
+ bool canBenefitFromLocalAlias();
+ }];
+ }
+
+} // namespace cir
+
+#endif // MLIR_CIR_OP_INTERFACES
diff --git a/clang/include/clang/CIR/Interfaces/CMakeLists.txt b/clang/include/clang/CIR/Interfaces/CMakeLists.txt
index 1c90b6b5a23cb..e9929f6964605 100644
--- a/clang/include/clang/CIR/Interfaces/CMakeLists.txt
+++ b/clang/include/clang/CIR/Interfaces/CMakeLists.txt
@@ -3,6 +3,14 @@
# directory which is not the case for CIR (and also FIR, both have similar
# workarounds).
+function(add_clang_mlir_op_interface interface)
+ set(LLVM_TARGET_DEFINITIONS ${interface}.td)
+ mlir_tablegen(${interface}.h.inc -gen-op-interface-decls)
+ mlir_tablegen(${interface}.cpp.inc -gen-op-interface-defs)
+ add_public_tablegen_target(MLIR${interface}IncGen)
+ add_dependencies(mlir-generic-headers MLIR${interface}IncGen)
+endfunction()
+
function(add_clang_mlir_type_interface interface)
set(LLVM_TARGET_DEFINITIONS ${interface}.td)
mlir_tablegen(${interface}.h.inc -gen-type-interface-decls)
@@ -11,4 +19,5 @@ function(add_clang_mlir_type_interface interface)
add_dependencies(mlir-generic-headers MLIR${interface}IncGen)
endfunction()
+add_clang_mlir_op_interface(CIROpInterfaces)
add_clang_mlir_type_interface(CIRFPTypeInterface)
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 6fbaa27bc7073..83177a004e80b 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -37,6 +37,10 @@ struct MissingFeatures {
static bool opGlobalAlignment() { return false; }
static bool opGlobalLinkage() { return false; }
+ static bool supportIFuncAttr() { return false; }
+ static bool supportVisibility() { return false; }
+ static bool supportComdat() { return false; }
+
// Load/store attributes
static bool opLoadThreadLocal() { return false; }
static bool opLoadEmitScalarRangeCheck() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index d8acc99e550ad..8eb08228075ef 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/GlobalDecl.h"
#include "clang/Basic/SourceManager.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/MissingFeatures.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/Location.h"
@@ -31,7 +32,7 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
const clang::CodeGenOptions &cgo,
DiagnosticsEngine &diags)
: builder(mlirContext, *this), astContext(astContext),
- langOpts(astContext.getLangOpts()),
+ langOpts(astContext.getLangOpts()), codeGenOpts(cgo),
theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&mlirContext))},
diags(diags), target(astContext.getTargetInfo()), genTypes(*this) {
@@ -176,6 +177,18 @@ void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
}
varOp.setInitialValueAttr(initializer);
}
+
+ // Set CIR's linkage type as appropriate.
+ cir::GlobalLinkageKind linkage =
+ getCIRLinkageVarDefinition(vd, /*IsConstant=*/false);
+
+ // Set CIR linkage and DLL storage class.
+ varOp.setLinkage(linkage);
+
+ if (linkage == cir::GlobalLinkageKind::CommonLinkage) {
+ errorNYI(initExpr->getSourceRange(), "common linkage");
+ }
+
theModule.push_back(varOp);
} else {
errorNYI(vd->getSourceRange().getBegin(),
@@ -210,6 +223,193 @@ void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd,
llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition");
}
+static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d) {
+ assert(!cir::MissingFeatures::supportComdat());
+
+ if (d.hasAttr<SelectAnyAttr>())
+ return true;
+
+ GVALinkage linkage;
+ if (auto *vd = dyn_cast<VarDecl>(&d))
+ linkage = cgm.getASTContext().GetGVALinkageForVariable(vd);
+ else
+ linkage =
+ cgm.getASTContext().GetGVALinkageForFunction(cast<FunctionDecl>(&d));
+
+ switch (linkage) {
+ case clang::GVA_Internal:
+ case clang::GVA_AvailableExternally:
+ case clang::GVA_StrongExternal:
+ return false;
+ case clang::GVA_DiscardableODR:
+ case clang::GVA_StrongODR:
+ return true;
+ }
+ llvm_unreachable("No such linkage");
+}
+
+// TODO(CIR): this could be a common method between LLVM codegen.
+static bool isVarDeclStrongDefinition(const ASTContext &astContext,
+ CIRGenModule &cgm, const VarDecl *vd,
+ bool noCommon) {
+ // Don't give variables common linkage if -fno-common was specified unless it
+ // was overridden by a NoCommon attribute.
+ if ((noCommon || vd->hasAttr<NoCommonAttr>()) && !vd->hasAttr<CommonAttr>())
+ return true;
+
+ // C11 6.9.2/2:
+ // A declaration of an identifier for an object that has file scope without
+ // an initializer, and without a storage-class specifier or with the
+ // storage-class specifier static, constitutes a tentative definition.
+ if (vd->getInit() || vd->hasExternalStorage())
+ return true;
+
+ // A variable cannot be both common and exist in a section.
+ if (vd->hasAttr<SectionAttr>())
+ return true;
+
+ // A variable cannot be both common and exist in a section.
+ // We don't try to determine which is the right section in the front-end.
+ // If no specialized section name is applicable, it will resort to default.
+ if (vd->hasAttr<PragmaClangBSSSectionAttr>() ||
+ vd->hasAttr<PragmaClangDataSectionAttr>() ||
+ vd->hasAttr<PragmaClangRelroSectionAttr>() ||
+ vd->hasAttr<PragmaClangRodataSectionAttr>())
+ return true;
+
+ // Thread local vars aren't considered common linkage.
+ if (vd->getTLSKind())
+ return true;
+
+ // Tentative definitions marked with WeakImportAttr are true definitions.
+ if (vd->hasAttr<WeakImportAttr>())
+ return true;
+
+ // A variable cannot be both common and exist in a comdat.
+ if (shouldBeInCOMDAT(cgm, *vd))
+ return true;
+
+ // Declarations with a required alignment do not have common linkage in MSVC
+ // mode.
+ if (astContext.getTargetInfo().getCXXABI().isMicrosoft()) {
+ if (vd->hasAttr<AlignedAttr>())
+ return true;
+ QualType varType = vd->getType();
+ if (astContext.isAlignmentRequired(varType))
+ return true;
+
+ if (const auto *rt = varType->getAs<RecordType>()) {
+ const RecordDecl *rd = rt->getDecl();
+ for (const FieldDecl *fd : rd->fields()) {
+ if (fd->isBitField())
+ continue;
+ if (fd->hasAttr<AlignedAttr>())
+ return true;
+ if (astContext.isAlignmentRequired(fd->getType()))
+ return true;
+ }
+ }
+ }
+
+ // Microsoft's link.exe doesn't support alignments greater than 32 bytes for
+ // common symbols, so symbols with greater alignment requirements cannot be
+ // common.
+ // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two
+ // alignments for common symbols via the aligncomm directive, so this
+ // restriction only applies to MSVC environments.
+ if (astContext.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() &&
+ astContext.getTypeAlignIfKnown(vd->getType()) >
+ astContext.toBits(CharUnits::fromQuantity(32)))
+ return true;
+
+ return false;
+}
+
+cir::GlobalLinkageKind CIRGenModule::getCIRLinkageForDeclarator(
+ const DeclaratorDecl *dd, GVALinkage linkage, bool isConstantVariable) {
+ if (linkage == GVA_Internal)
+ return cir::GlobalLinkageKind::InternalLinkage;
+
+ if (dd->hasAttr<WeakAttr>()) {
+ if (isConstantVariable)
+ return cir::GlobalLinkageKind::WeakODRLinkage;
+ return cir::GlobalLinkageKind::WeakAnyLinkage;
+ }
+
+ if (const auto *fd = dd->getAsFunction())
+ if (fd->isMultiVersion() && linkage == GVA_AvailableExternally)
+ return cir::GlobalLinkageKind::LinkOnceAnyLinkage;
+
+ // We are guaranteed to have a strong definition somewhere else,
+ // so we can use available_externally linkage.
+ if (linkage == GVA_AvailableExternally)
+ return cir::GlobalLinkageKind::AvailableExternallyLinkage;
+
+ // Note that Apple's kernel linker doesn't support symbol
+ // coalescing, so we need to avoid linkonce and weak linkages there.
+ // Normally, this means we just map to internal, but for explicit
+ // instantiations we'll map to external.
+
+ // In C++, the compiler has to emit a definition in every translation unit
+ // that references the function. We should use linkonce_odr because
+ // a) if all references in this translation unit are optimized away, we
+ // don't need to codegen it. b) if the function persists, it needs to be
+ // merged with other definitions. c) C++ has the ODR, so we know the
+ // definition is dependable.
+ if (linkage == GVA_DiscardableODR)
+ return !astContext.getLangOpts().AppleKext
+ ? cir::GlobalLinkageKind::LinkOnceODRLinkage
+ : cir::GlobalLinkageKind::InternalLinkage;
+
+ // An explicit instantiation of a template has weak linkage, since
+ // explicit instantiations can occur in multiple translation units
+ // and must all be equivalent. However, we are not allowed to
+ // throw away these explicit instantiations.
+ //
+ // CUDA/HIP: For -fno-gpu-rdc case, device code is limited to one TU,
+ // so say that CUDA templates are either external (for kernels) or internal.
+ // This lets llvm perform aggressive inter-procedural optimizations. For
+ // -fgpu-rdc case, device function calls across multiple TU's are allowed,
+ // therefore we need to follow the normal linkage paradigm.
+ if (linkage == GVA_StrongODR) {
+ if (getLangOpts().AppleKext)
+ return cir::GlobalLinkageKind::ExternalLinkage;
+ if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice &&
+ !getLangOpts().GPURelocatableDeviceCode)
+ return dd->hasAttr<CUDAGlobalAttr>()
+ ? cir::GlobalLinkageKind::ExternalLinkage
+ : cir::GlobalLinkageKind::InternalLinkage;
+ return cir::GlobalLinkageKind::WeakODRLinkage;
+ }
+
+ // C++ doesn't have tentative definitions and thus cannot have common
+ // linkage.
+ if (!getLangOpts().CPlusPlus && isa<VarDecl>(dd) &&
+ !isVarDeclStrongDefinition(astContext, *this, cast<VarDecl>(dd),
+ getCodeGenOpts().NoCommon)) {
+ errorNYI(dd->getBeginLoc(), "common linkage", dd->getDeclKindName());
+ return cir::GlobalLinkageKind::CommonLinkage;
+ }
+
+ // selectany symbols are externally visible, so use weak instead of
+ // linkonce. MSVC optimizes away references to const selectany globals, so
+ // all definitions should be the same and ODR linkage should be used.
+ // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
+ if (dd->hasAttr<SelectAnyAttr>())
+ return cir::GlobalLinkageKind::WeakODRLinkage;
+
+ // Otherwise, we have strong external linkage.
+ assert(linkage == GVA_StrongExternal);
+ return cir::GlobalLinkageKind::ExternalLinkage;
+}
+
+cir::GlobalLinkageKind
+CIRGenModule::getCIRLinkageVarDefinition(const VarDecl *vd, bool isConstant) {
+ assert(!isConstant && "constant variables NYI");
+ GVALinkage linkage = astContext.GetGVALinkageForVariable(vd);
+ return getCIRLinkageForDeclarator(vd, linkage, isConstant);
+}
+
// Emit code for a single top level declaration.
void CIRGenModule::emitTopLevelDecl(Decl *decl) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
index 71a37b8c9a2ea..5fb5ef505a8c1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -23,8 +23,10 @@
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/MLIRContext.h"
+#include "clang/AST/Decl.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/TargetParser/Triple.h"
@@ -62,6 +64,8 @@ class CIRGenModule : public CIRGenTypeCache {
const clang::LangOptions &langOpts;
+ const clang::CodeGenOptions &codeGenOpts;
+
/// A "module" matches a c/cpp source file: containing a list of functions.
mlir::ModuleOp theModule;
@@ -75,6 +79,7 @@ class CIRGenModule : public CIRGenTypeCache {
mlir::ModuleOp getModule() const { return theModule; }
CIRGenBuilderTy &getBuilder() { return builder; }
clang::ASTContext &getASTContext() const { return astContext; }
+ const clang::CodeGenOptions &getCodeGenOpts() const { return codeGenOpts; }
CIRGenTypes &getTypes() { return genTypes; }
const clang::LangOptions &getLangOpts() const { return langOpts; }
mlir::MLIRContext &getMLIRContext() { return *builder.getContext(); }
@@ -123,6 +128,13 @@ class CIRGenModule : public CIRGenTypeCache {
const llvm::Triple &getTriple() const { return target.getTriple(); }
+ cir::GlobalLinkageKind getCIRLinkageForDeclarator(const DeclaratorDecl *dd,
+ GVALinkage linkage,
+ bool isConstantVariable);
+
+ cir::GlobalLinkageKind getCIRLinkageVarDefinition(const VarDecl *vd,
+ bool isConstant);
+
/// Helpers to emit "not yet implemented" error diagnostics
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef);
diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt b/clang/lib/CIR/CodeGen/CMakeLists.txt
index dbb6d9e7b3807..e6d3cbabd853b 100644
--- a/clang/lib/CIR/CodeGen/CMakeLists.txt
+++ b/clang/lib/CIR/CodeGen/CMakeLists.txt
@@ -18,6 +18,7 @@ add_clang_library(clangCIR
DEPENDS
MLIRCIR
+ MLIRCIROpInterfacesIncGen
${dialect_libs}
LINK_LIBS
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index aa21edcb5e99d..5ad369b40cda1 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -18,6 +18,7 @@
#include "mlir/Support/LogicalResult.h"
#include "clang/CIR/Dialect/IR/CIROpsDialect.cpp.inc"
+#include "clang/CIR/Dialect/IR/CIROpsEnums.cpp.inc"
using namespace mlir;
using namespace cir;
@@ -297,11 +298,16 @@ mlir::LogicalResult cir::GlobalOp::verify() {
}
void cir::GlobalOp::build(OpBuilder &odsBuilder, OperationState &odsState,
- llvm::StringRef sym_name, mlir::Type sym_type) {
+ llvm::StringRef sym_name, mlir::Type sym_type,
+ cir::GlobalLinkageKind linkage) {
odsState.addAttribute(getSymNameAttrName(odsState.name),
odsBuilder.getStringAttr(sym_name));
odsState.addAttribute(getSymTypeAttrName(odsState.name),
mlir::TypeAttr::get(sym_type));
+
+ cir::GlobalLinkageKindAttr linkageAttr =
+ cir::GlobalLinkageKindAttr::get(odsBuilder.getContext(), linkage);
+ odsState.addAttribute(getLinkageAttrName(odsState.name), linkageAttr);
}
static void printGlobalOpTypeAndInitialValue(OpAsmPrinter &p, cir::GlobalOp op,
diff --git a/clang/lib/CIR/Dialect/IR/CMakeLists.txt b/clang/lib/CIR/Dialect/IR/CMakeLists.txt
index 925af0d61c984..e3a6fc6e80ecc 100644
--- a/clang/lib/CIR/Dialect/IR/CMakeLists.txt
+++ b/clang/lib/CIR/Dialect/IR/CMakeLists.txt
@@ -6,7 +6,8 @@ add_clang_library(MLIRCIR
DEPENDS
MLIRCIROpsIncGen
- MLIRCIRAttrsEnumsGen
+ MLIRCIREnumsGen
+ MLIRCIROpInterfacesIncGen
LINK_LIBS PUBLIC
MLIRIR
diff --git a/clang/lib/CIR/FrontendAction/CMakeLists.txt b/clang/lib/CIR/FrontendAction/CMakeLists.txt
index ac2b857239d07..6d5a8758468f6 100644
--- a/clang/lib/CIR/FrontendAction/CMakeLists.txt
+++ b/clang/lib/CIR/FrontendAction/CMakeLists.txt
@@ -8,6 +8,10 @@ get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
add_clang_library(clangCIRFrontendAction
CIRGenAction.cpp
+ DEPENDS
+ MLIRCIROpsIncGen
+ MLIRCIROpInterfacesIncGen
+
LINK_LIBS
clangAST
clangFrontend
diff --git a/clang/lib/CIR/Interfaces/CIROpInterfaces.cpp b/clang/lib/CIR/Interfaces/CIROpInterfaces.cpp
new file mode 100644
index 0000000000000..dfbbdc2fd2382
--- /dev/null
+++ b/clang/lib/CIR/Interfaces/CIROpInterfaces.cpp
@@ -0,0 +1,22 @@
+//====- CIROpInterfaces.cpp - Interface to AST Attributes ---------------===//
+//
+// 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/CIR/Interfaces/CIROpInterfaces.h"
+
+using namespace cir;
+
+/// Include the generated type qualifiers interfaces.
+#include "clang/CIR/Interfaces/CIROpInterfaces.cpp.inc"
+
+#include "clang/CIR/MissingFeatures.h"
+
+bool CIRGlobalValueInterface::canBenefitFromLocalAlias() {
+ assert(!cir::MissingFeatures::supportIFuncAttr());
+ assert(!cir::MissingFeatures::supportVisibility());
+ assert(!cir::MissingFeatures::supportComdat());
+ return false;
+}
diff --git a/clang/lib/CIR/Interfaces/CMakeLists.txt b/clang/lib/CIR/Interfaces/CMakeLists.txt
index b826bf612cc35..2fe5714520b74 100644
--- a/clang/lib/CIR/Interfaces/CMakeLists.txt
+++ b/clang/lib/CIR/Interfaces/CMakeLists.txt
@@ -1,12 +1,14 @@
add_clang_library(MLIRCIRInterfaces
+ CIROpInterfaces.cpp
CIRFPTypeInterface.cpp
ADDITIONAL_HEADER_DIRS
${MLIR_MAIN_INCLUDE_DIR}/mlir/Interfaces
DEPENDS
- MLIRCIRAttrsEnumsGen
+ MLIRCIREnumsGen
MLIRCIRFPTypeInterfaceIncGen
+ MLIRCIROpInterfacesIncGen
LINK_LIBS
${dialect_libs}
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt b/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt
index 3f74c79249a27..c11ecb82183d0 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt
@@ -8,6 +8,11 @@ get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
add_clang_library(clangCIRLoweringDirectToLLVM
LowerToLLVM.cpp
+ DEPENDS
+ MLIRCIREnumsGen
+ MLIRCIROpsIncGen
+ MLIRCIROpInterfacesIncGen
+
LINK_LIBS
MLIRIR
${dialect_libs}
diff --git a/clang/test/CIR/global-var-simple.cpp b/clang/test/CIR/global-var-simple.cpp
index f8e233cd5fe33..585f1ed38390f 100644
--- a/clang/test/CIR/global-var-simple.cpp
+++ b/clang/test/CIR/global-var-simple.cpp
@@ -2,100 +2,100 @@
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s
char c;
-// CHECK: cir.global @c : !cir.int<s, 8>
+// CHECK: cir.global external @c : !cir.int<s, 8>
signed char sc;
-// CHECK: cir.global @sc : !cir.int<s, 8>
+// CHECK: cir.global external @sc : !cir.int<s, 8>
unsigned char uc;
-// CHECK: cir.global @uc : !cir.int<u, 8>
+// CHECK: cir.global external @uc : !cir.int<u, 8>
short ss;
-// CHECK: cir.global @ss : !cir.int<s, 16>
+// CHECK: cir.global external @ss : !cir.int<s, 16>
unsigned short us = 100;
-// CHECK: cir.global @us = #cir.int<100> : !cir.int<u, 16>
+// CHECK: cir.global external @us = #cir.int<100> : !cir.int<u, 16>
int si = 42;
-// CHECK: cir.global @si = #cir.int<42> : !cir.int<s, 32>
+// CHECK: cir.global external @si = #cir.int<42> : !cir.int<s, 32>
unsigned ui;
-// CHECK: cir.global @ui : !cir.int<u, 32>
+// CHECK: cir.global external @ui : !cir.int<u, 32>
long sl;
-// CHECK: cir.global @sl : !cir.int<s, 64>
+// CHECK: cir.global external @sl : !cir.int<s, 64>
unsigned long ul;
-// CHECK: cir.global @ul : !cir.int<u, 64>
+// CHECK: cir.global external @ul : !cir.int<u, 64>
long long sll;
-// CHECK: cir.global @sll : !cir.int<s, 64>
+// CHECK: cir.global external @sll : !cir.int<s, 64>
unsigned long long ull = 123456;
-// CHECK: cir.global @ull = #cir.int<123456> : !cir.int<u, 64>
+// CHECK: cir.global external @ull = #cir.int<123456> : !cir.int<u, 64>
__int128 s128;
-// CHECK: cir.global @s128 : !cir.int<s, 128>
+// CHECK: cir.global external @s128 : !cir.int<s, 128>
unsigned __int128 u128;
-// CHECK: cir.global @u128 : !cir.int<u, 128>
+// CHECK: cir.global external @u128 : !cir.int<u, 128>
wchar_t wc;
-// CHECK: cir.global @wc : !cir.int<s, 32>
+// CHECK: cir.global external @wc : !cir.int<s, 32>
char8_t c8;
-// CHECK: cir.global @c8 : !cir.int<u, 8>
+// CHECK: cir.global external @c8 : !cir.int<u, 8>
char16_t c16;
-// CHECK: cir.global @c16 : !cir.int<u, 16>
+// CHECK: cir.global external @c16 : !cir.int<u, 16>
char32_t c32;
-// CHECK: cir.global @c32 : !cir.int<u, 32>
+// CHECK: cir.global external @c32 : !cir.int<u, 32>
_BitInt(20) sb20;
-// CHECK: cir.global @sb20 : !cir.int<s, 20>
+// CHECK: cir.global external @sb20 : !cir.int<s, 20>
unsigned _BitInt(48) ub48;
-// CHECK: cir.global @ub48 : !cir.int<u, 48>
+// CHECK: cir.global external @ub48 : !cir.int<u, 48>
bool boolfalse = false;
// CHECK: cir.global @boolfalse = #false
_Float16 f16;
-// CHECK: cir.global @f16 : !cir.f16
+// CHECK: cir.global external @f16 : !cir.f16
__bf16 bf16;
-// CHECK: cir.global @bf16 : !cir.bf16
+// CHECK: cir.global external @bf16 : !cir.bf16
float f;
-// CHECK: cir.global @f : !cir.float
+// CHECK: cir.global external @f : !cir.float
double d = 1.25;
-// CHECK: cir.global @d = #cir.fp<1.250000e+00> : !cir.double
+// CHECK: cir.global external @d = #cir.fp<1.250000e+00> : !cir.double
long double ld;
-// CHECK: cir.global @ld : !cir.long_double<!cir.f80>
+// CHECK: cir.global external @ld : !cir.long_double<!cir.f80>
__float128 f128;
-// CHECK: cir.global @f128 : !cir.f128
+// CHECK: cir.global external @f128 : !cir.f128
void *vp;
-// CHECK: cir.global @vp : !cir.ptr<!cir.void>
+// CHECK: cir.global external @vp : !cir.ptr<!cir.void>
int *ip = 0;
-// CHECK: cir.global @ip = #cir.ptr<null> : !cir.ptr<!cir.int<s, 32>>
+// CHECK: cir.global external @ip = #cir.ptr<null> : !cir.ptr<!cir.int<s, 32>>
double *dp;
-// CHECK: cir.global @dp : !cir.ptr<!cir.double>
+// CHECK: cir.global external @dp : !cir.ptr<!cir.double>
char **cpp;
-// CHECK: cir.global @cpp : !cir.ptr<!cir.ptr<!cir.int<s, 8>>>
+// CHECK: cir.global external @cpp : !cir.ptr<!cir.ptr<!cir.int<s, 8>>>
void (*fp)();
-// CHECK: cir.global @fp : !cir.ptr<!cir.func<()>>
+// CHECK: cir.global external @fp : !cir.ptr<!cir.func<()>>
int (*fpii)(int) = 0;
-// CHECK: cir.global @fpii = #cir.ptr<null> : !cir.ptr<!cir.func<(!cir.int<s, 32>) -> !cir.int<s, 32>>>
+// CHECK: cir.global external @fpii = #cir.ptr<null> : !cir.ptr<!cir.func<(!cir.int<s, 32>) -> !cir.int<s, 32>>>
void (*fpvar)(int, ...);
-// CHECK: cir.global @fpvar : !cir.ptr<!cir.func<(!cir.int<s, 32>, ...)>>
+// CHECK: cir.global external @fpvar : !cir.ptr<!cir.func<(!cir.int<s, 32>, ...)>>
diff --git a/clang/test/CIR/global_var_linkage.cpp b/clang/test/CIR/global_var_linkage.cpp
new file mode 100644
index 0000000000000..18f17a3c2eb61
--- /dev/null
+++ b/clang/test/CIR/global_var_linkage.cpp
@@ -0,0 +1,11 @@
+// Linkage types of global variables
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - | FileCheck %s
+
+int aaaa;
+// CHECK: cir.global external @aaaa
+static int bbbb;
+// CHECK: cir.global internal @bbbb
+inline int cccc;
+// CHECK: cir.global linkonce_odr @cccc
+[[gnu::selectany]] int dddd;
+// CHECK: cir.global weak_odr @dddd
>From a7f29ff3fdd2b8cf244e76d78f76d21b97d281d0 Mon Sep 17 00:00:00 2001
From: Morris Hafner <mhafner at nvidia.com>
Date: Wed, 5 Mar 2025 16:38:24 +0100
Subject: [PATCH 2/7] Addressed some review feedback
- Various formatting changes
- Changed file header comments
- Changed include guards
- Added global linkage to LLVM lowering
---
.../clang/CIR/Dialect/IR/CIROpsEnums.h | 10 ++--
.../clang/CIR/Interfaces/CIROpInterfaces.h | 12 ++--
.../clang/CIR/Interfaces/CIROpInterfaces.td | 58 ++++++++-----------
clang/include/clang/CIR/MissingFeatures.h | 1 -
clang/lib/CIR/CodeGen/CIRGenModule.cpp | 3 +-
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 34 +++++++++--
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 3 +
...var_linkage.cpp => global-var-linkage.cpp} | 0
clang/test/CIR/global-var-simple.cpp | 2 +-
9 files changed, 67 insertions(+), 56 deletions(-)
rename clang/test/CIR/{global_var_linkage.cpp => global-var-linkage.cpp} (100%)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROpsEnums.h b/clang/include/clang/CIR/Dialect/IR/CIROpsEnums.h
index a1e32209555f3..2b7270c42d343 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROpsEnums.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIROpsEnums.h
@@ -1,4 +1,4 @@
-//===- CIROpsEnumsDialect.h - MLIR Dialect for CIR ----------------------*- C++
+//===----------------------------------------------------------------------===//
//-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -7,12 +7,12 @@
//
//===----------------------------------------------------------------------===//
//
-// This file declares the Target dialect for CIR in MLIR.
+// This file declares the CIR enumerations.
//
//===----------------------------------------------------------------------===//
-#ifndef MLIR_DIALECT_CIR_CIROPSENUMS_H_
-#define MLIR_DIALECT_CIR_CIROPSENUMS_H_
+#ifndef CLANG_CIR_DIALECT_IR_CIROPSENUMS_H
+#define CLANG_CIR_DIALECT_IR_CIROPSENUMS_H
#include "mlir/IR/BuiltinAttributes.h"
#include "clang/CIR/Dialect/IR/CIROpsEnums.h.inc"
@@ -116,4 +116,4 @@ LLVM_ATTRIBUTE_UNUSED static bool isValidLinkage(GlobalLinkageKind gl) {
} // namespace cir
-#endif // MLIR_DIALECT_CIR_CIROPSENUMS_H_
+#endif // CLANG_CIR_DIALECT_IR_CIROPSENUMS_H
diff --git a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.h b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.h
index 86064619af7db..4c171c309ae29 100644
--- a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.h
+++ b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.h
@@ -1,4 +1,4 @@
-//===- CIROpInterfaces.h - CIR Op Interfaces --------------------*- C++ -*-===//
+//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef MLIR_INTERFACES_CIR_OP_H_
-#define MLIR_INTERFACES_CIR_OP_H_
+#ifndef CLANG_CIR_INTERFACES_CIR_OP_H
+#define CLANG_CIR_INTERFACES_CIR_OP_H
#include "mlir/IR/Attributes.h"
#include "mlir/IR/Operation.h"
@@ -19,11 +19,7 @@
#include "clang/AST/Mangle.h"
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
-namespace cir {} // namespace cir
-
/// Include the generated interface declarations.
#include "clang/CIR/Interfaces/CIROpInterfaces.h.inc"
-namespace cir {} // namespace cir
-
-#endif // MLIR_INTERFACES_CIR_OP_H_
+#endif // CLANG_CIR_INTERFACES_CIR_OP_H
diff --git a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
index b765a3e65f70b..235b5a05c5ba8 100644
--- a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
+++ b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
@@ -6,52 +6,40 @@
//
//===----------------------------------------------------------------------===//
-#ifndef MLIR_CIR_OP_INTERFACES
-#define MLIR_CIR_OP_INTERFACES
+#ifndef CLANG_CIR_INTERFACES_CIROPINTERFACES_TD
+#define CLANG_CIR_INTERFACES_CIROPINTERFACES_TD
include "mlir/IR/OpBase.td"
let cppNamespace = "::cir" in {
- def CIRGlobalValueInterface
- : OpInterface<"CIRGlobalValueInterface"> {
+ def CIRGlobalValueInterface : OpInterface<"CIRGlobalValueInterface"> {
- let methods = [
- InterfaceMethod<"",
- "bool", "hasAvailableExternallyLinkage", (ins), [{}],
- /*defaultImplementation=*/[{ return false; }]
- >,
- InterfaceMethod<"",
- "bool", "hasLocalLinkage", (ins), [{}],
- /*defaultImplementation=*/[{
+ let methods =
+ [InterfaceMethod<"", "bool", "hasAvailableExternallyLinkage", (ins),
+ [{}],
+ /*defaultImplementation=*/[{ return false; }]>,
+ InterfaceMethod<"", "bool", "hasLocalLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
return cir::isLocalLinkage($_op.getLinkage());
- }]
- >,
- InterfaceMethod<"",
- "bool", "hasExternalWeakLinkage", (ins), [{}],
- /*defaultImplementation=*/[{
+ }]>,
+ InterfaceMethod<"", "bool", "hasExternalWeakLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
return cir::isExternalWeakLinkage($_op.getLinkage());
- }]
- >,
- InterfaceMethod<"",
- "bool", "isExternalLinkage", (ins), [{}],
- /*defaultImplementation=*/[{
+ }]>,
+ InterfaceMethod<"", "bool", "isExternalLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
return cir::isExternalLinkage($_op.getLinkage());
- }]
- >,
- InterfaceMethod<"",
- "bool", "isDeclarationForLinker", (ins), [{}],
- /*defaultImplementation=*/[{
+ }]>,
+ InterfaceMethod<"", "bool", "isDeclarationForLinker", (ins), [{}],
+ /*defaultImplementation=*/[{
if ($_op.hasAvailableExternallyLinkage())
return true;
return $_op.isDeclaration();
- }]
- >,
- InterfaceMethod<"",
- "void", "setDSOLocal", (ins "bool":$val), [{}],
- /*defaultImplementation=*/[{
+ }]>,
+ InterfaceMethod<"", "void", "setDSOLocal", (ins "bool":$val), [{}],
+ /*defaultImplementation=*/[{
$_op.setDsolocal(val);
- }]
- >,
+ }]>,
];
let extraClassDeclaration = [{
bool canBenefitFromLocalAlias();
@@ -60,4 +48,4 @@ let cppNamespace = "::cir" in {
} // namespace cir
-#endif // MLIR_CIR_OP_INTERFACES
+#endif // CLANG_CIR_INTERFACES_CIROPINTERFACES_TD
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 83177a004e80b..6f845b7689e51 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -35,7 +35,6 @@ struct MissingFeatures {
static bool opGlobalThreadLocal() { return false; }
static bool opGlobalConstant() { return false; }
static bool opGlobalAlignment() { return false; }
- static bool opGlobalLinkage() { return false; }
static bool supportIFuncAttr() { return false; }
static bool supportVisibility() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 8eb08228075ef..0e3e15ca2cadc 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -185,9 +185,8 @@ void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
// Set CIR linkage and DLL storage class.
varOp.setLinkage(linkage);
- if (linkage == cir::GlobalLinkageKind::CommonLinkage) {
+ if (linkage == cir::GlobalLinkageKind::CommonLinkage)
errorNYI(initExpr->getSourceRange(), "common linkage");
- }
theModule.push_back(varOp);
} else {
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index f614c5d1db0c0..3200527bd03af 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -109,6 +109,34 @@ static mlir::Value emitToMemory(mlir::ConversionPatternRewriter &rewriter,
return value;
}
+mlir::LLVM::Linkage convertLinkage(cir::GlobalLinkageKind linkage) {
+ using CIR = cir::GlobalLinkageKind;
+ using LLVM = mlir::LLVM::Linkage;
+
+ switch (linkage) {
+ case CIR::AvailableExternallyLinkage:
+ return LLVM::AvailableExternally;
+ case CIR::CommonLinkage:
+ return LLVM::Common;
+ case CIR::ExternalLinkage:
+ return LLVM::External;
+ case CIR::ExternalWeakLinkage:
+ return LLVM::ExternWeak;
+ case CIR::InternalLinkage:
+ return LLVM::Internal;
+ case CIR::LinkOnceAnyLinkage:
+ return LLVM::Linkonce;
+ case CIR::LinkOnceODRLinkage:
+ return LLVM::LinkonceODR;
+ case CIR::PrivateLinkage:
+ return LLVM::Private;
+ case CIR::WeakAnyLinkage:
+ return LLVM::Weak;
+ case CIR::WeakODRLinkage:
+ return LLVM::WeakODR;
+ };
+}
+
class CIRAttrToValue {
public:
CIRAttrToValue(mlir::Operation *parentOp,
@@ -442,8 +470,7 @@ void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
const bool isThreadLocal = false;
assert(!cir::MissingFeatures::opGlobalAlignment());
const uint64_t alignment = 0;
- assert(!cir::MissingFeatures::opGlobalLinkage());
- const mlir::LLVM::Linkage linkage = mlir::LLVM::Linkage::External;
+ const mlir::LLVM::Linkage linkage = convertLinkage(op.getLinkage());
const StringRef symbol = op.getSymName();
SmallVector<mlir::NamedAttribute> attributes;
@@ -498,8 +525,7 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
const bool isThreadLocal = false;
assert(!cir::MissingFeatures::opGlobalAlignment());
const uint64_t alignment = 0;
- assert(!cir::MissingFeatures::opGlobalLinkage());
- const mlir::LLVM::Linkage linkage = mlir::LLVM::Linkage::External;
+ const mlir::LLVM::Linkage linkage = convertLinkage(op.getLinkage());
const StringRef symbol = op.getSymName();
SmallVector<mlir::NamedAttribute> attributes;
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
index ccb4065c3019e..a694047e3616b 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -12,6 +12,7 @@
#ifndef CLANG_CIR_LOWERTOLLVM_H
#define CLANG_CIR_LOWERTOLLVM_H
+#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
#include "mlir/Transforms/DialectConversion.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
@@ -19,6 +20,8 @@ namespace cir {
namespace direct {
+mlir::LLVM::Linkage convertLinkage(cir::GlobalLinkageKind linkage);
+
class CIRToLLVMReturnOpLowering
: public mlir::OpConversionPattern<cir::ReturnOp> {
public:
diff --git a/clang/test/CIR/global_var_linkage.cpp b/clang/test/CIR/global-var-linkage.cpp
similarity index 100%
rename from clang/test/CIR/global_var_linkage.cpp
rename to clang/test/CIR/global-var-linkage.cpp
diff --git a/clang/test/CIR/global-var-simple.cpp b/clang/test/CIR/global-var-simple.cpp
index 585f1ed38390f..f18f00fd6bd13 100644
--- a/clang/test/CIR/global-var-simple.cpp
+++ b/clang/test/CIR/global-var-simple.cpp
@@ -59,7 +59,7 @@ unsigned _BitInt(48) ub48;
// CHECK: cir.global external @ub48 : !cir.int<u, 48>
bool boolfalse = false;
-// CHECK: cir.global @boolfalse = #false
+// CHECK: cir.global external @boolfalse = #false
_Float16 f16;
// CHECK: cir.global external @f16 : !cir.f16
>From c6bb2e4ad6e830df3454e49b21ca1a2196b1f50f Mon Sep 17 00:00:00 2001
From: Morris Hafner <mhafner at nvidia.com>
Date: Mon, 3 Mar 2025 18:39:52 +0100
Subject: [PATCH 3/7] Address more review comments
- Add header comments to CIROpInterfaces
- Fix test clang-cir-ir-global
---
.../clang/CIR/Interfaces/CIROpInterfaces.h | 4 +
.../clang/CIR/Interfaces/CIROpInterfaces.td | 4 +
clang/lib/CIR/Interfaces/CIROpInterfaces.cpp | 4 +
clang/test/CIR/IR/global.cir | 128 +++++++++---------
4 files changed, 76 insertions(+), 64 deletions(-)
diff --git a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.h b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.h
index 4c171c309ae29..cb7488d3aee36 100644
--- a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.h
+++ b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.h
@@ -5,6 +5,10 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+//
+// Defines the interface to CIR operations.
+//
+//===----------------------------------------------------------------------===//
#ifndef CLANG_CIR_INTERFACES_CIR_OP_H
#define CLANG_CIR_INTERFACES_CIR_OP_H
diff --git a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
index 235b5a05c5ba8..64a96bd55cf86 100644
--- a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
+++ b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
@@ -5,6 +5,10 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+//
+// Defines the interface to CIR operations.
+//
+//===----------------------------------------------------------------------===//
#ifndef CLANG_CIR_INTERFACES_CIROPINTERFACES_TD
#define CLANG_CIR_INTERFACES_CIROPINTERFACES_TD
diff --git a/clang/lib/CIR/Interfaces/CIROpInterfaces.cpp b/clang/lib/CIR/Interfaces/CIROpInterfaces.cpp
index dfbbdc2fd2382..3ae103c2e65b4 100644
--- a/clang/lib/CIR/Interfaces/CIROpInterfaces.cpp
+++ b/clang/lib/CIR/Interfaces/CIROpInterfaces.cpp
@@ -5,6 +5,10 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
+//
+// Defines the interface to CIR operations.
+//
+//===----------------------------------------------------------------------===//
#include "clang/CIR/Interfaces/CIROpInterfaces.h"
using namespace cir;
diff --git a/clang/test/CIR/IR/global.cir b/clang/test/CIR/IR/global.cir
index 9d187686d996c..12eda5a946af5 100644
--- a/clang/test/CIR/IR/global.cir
+++ b/clang/test/CIR/IR/global.cir
@@ -1,69 +1,69 @@
// RUN: cir-opt %s -o - | FileCheck %s
module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
- cir.global @c : !cir.int<s, 8>
- cir.global @sc : !cir.int<s, 8>
- cir.global @uc : !cir.int<u, 8>
- cir.global @ss : !cir.int<s, 16>
- cir.global @us = #cir.int<100> : !cir.int<u, 16>
- cir.global @si = #cir.int<42> : !cir.int<s, 32>
- cir.global @ui : !cir.int<u, 32>
- cir.global @sl : !cir.int<s, 64>
- cir.global @ul : !cir.int<u, 64>
- cir.global @sll : !cir.int<s, 64>
- cir.global @ull = #cir.int<123456> : !cir.int<u, 64>
- cir.global @s128 : !cir.int<s, 128>
- cir.global @u128 : !cir.int<u, 128>
- cir.global @wc : !cir.int<s, 32>
- cir.global @c8 : !cir.int<u, 8>
- cir.global @c16 : !cir.int<u, 16>
- cir.global @c32 : !cir.int<u, 32>
- cir.global @sb20 : !cir.int<s, 20>
- cir.global @ub48 : !cir.int<u, 48>
- cir.global @f16 : !cir.f16
- cir.global @bf16 : !cir.bf16
- cir.global @f : !cir.float
- cir.global @d = #cir.fp<1.250000e+00> : !cir.double
- cir.global @ld : !cir.long_double<!cir.f80>
- cir.global @f128 : !cir.f128
- cir.global @vp : !cir.ptr<!cir.void>
- cir.global @ip = #cir.ptr<null> : !cir.ptr<!cir.int<s, 32>>
- cir.global @dp : !cir.ptr<!cir.double>
- cir.global @cpp : !cir.ptr<!cir.ptr<!cir.int<s, 8>>>
- cir.global @fp : !cir.ptr<!cir.func<()>>
- cir.global @fpii = #cir.ptr<null> : !cir.ptr<!cir.func<(!cir.int<s, 32>) -> !cir.int<s, 32>>>
- cir.global @fpvar : !cir.ptr<!cir.func<(!cir.int<s, 32>, ...)>>
+ cir.global external @c : !cir.int<s, 8>
+ cir.global external @sc : !cir.int<s, 8>
+ cir.global external @uc : !cir.int<u, 8>
+ cir.global external @ss : !cir.int<s, 16>
+ cir.global external @us = #cir.int<100> : !cir.int<u, 16>
+ cir.global external @si = #cir.int<42> : !cir.int<s, 32>
+ cir.global external @ui : !cir.int<u, 32>
+ cir.global external @sl : !cir.int<s, 64>
+ cir.global external @ul : !cir.int<u, 64>
+ cir.global external @sll : !cir.int<s, 64>
+ cir.global external @ull = #cir.int<123456> : !cir.int<u, 64>
+ cir.global external @s128 : !cir.int<s, 128>
+ cir.global external @u128 : !cir.int<u, 128>
+ cir.global external @wc : !cir.int<s, 32>
+ cir.global external @c8 : !cir.int<u, 8>
+ cir.global external @c16 : !cir.int<u, 16>
+ cir.global external @c32 : !cir.int<u, 32>
+ cir.global external @sb20 : !cir.int<s, 20>
+ cir.global external @ub48 : !cir.int<u, 48>
+ cir.global external @f16 : !cir.f16
+ cir.global external @bf16 : !cir.bf16
+ cir.global external @f : !cir.float
+ cir.global external @d = #cir.fp<1.250000e+00> : !cir.double
+ cir.global external @ld : !cir.long_double<!cir.f80>
+ cir.global external @f128 : !cir.f128
+ cir.global external @vp : !cir.ptr<!cir.void>
+ cir.global external @ip = #cir.ptr<null> : !cir.ptr<!cir.int<s, 32>>
+ cir.global external @dp : !cir.ptr<!cir.double>
+ cir.global external @cpp : !cir.ptr<!cir.ptr<!cir.int<s, 8>>>
+ cir.global external @fp : !cir.ptr<!cir.func<()>>
+ cir.global external @fpii = #cir.ptr<null> : !cir.ptr<!cir.func<(!cir.int<s, 32>) -> !cir.int<s, 32>>>
+ cir.global external @fpvar : !cir.ptr<!cir.func<(!cir.int<s, 32>, ...)>>
}
-// CHECK: cir.global @c : !cir.int<s, 8>
-// CHECK: cir.global @sc : !cir.int<s, 8>
-// CHECK: cir.global @uc : !cir.int<u, 8>
-// CHECK: cir.global @ss : !cir.int<s, 16>
-// CHECK: cir.global @us = #cir.int<100>
-// CHECK: cir.global @si = #cir.int<42>
-// CHECK: cir.global @ui : !cir.int<u, 32>
-// CHECK: cir.global @sl : !cir.int<s, 64>
-// CHECK: cir.global @ul : !cir.int<u, 64>
-// CHECK: cir.global @sll : !cir.int<s, 64>
-// CHECK: cir.global @ull = #cir.int<123456> : !cir.int<u, 64>
-// CHECK: cir.global @s128 : !cir.int<s, 128>
-// CHECK: cir.global @u128 : !cir.int<u, 128>
-// CHECK: cir.global @wc : !cir.int<s, 32>
-// CHECK: cir.global @c8 : !cir.int<u, 8>
-// CHECK: cir.global @c16 : !cir.int<u, 16>
-// CHECK: cir.global @c32 : !cir.int<u, 32>
-// CHECK: cir.global @sb20 : !cir.int<s, 20>
-// CHECK: cir.global @ub48 : !cir.int<u, 48>
-// CHECK: cir.global @f16 : !cir.f16
-// CHECK: cir.global @bf16 : !cir.bf16
-// CHECK: cir.global @f : !cir.float
-// CHECK: cir.global @d = #cir.fp<1.250000e+00> : !cir.double
-// CHECK: cir.global @ld : !cir.long_double<!cir.f80>
-// CHECK: cir.global @f128 : !cir.f128
-// CHECK: cir.global @vp : !cir.ptr<!cir.void>
-// CHECK: cir.global @ip = #cir.ptr<null> : !cir.ptr<!cir.int<s, 32>>
-// CHECK: cir.global @dp : !cir.ptr<!cir.double>
-// CHECK: cir.global @cpp : !cir.ptr<!cir.ptr<!cir.int<s, 8>>>
-// CHECK: cir.global @fp : !cir.ptr<!cir.func<()>>
-// CHECK: cir.global @fpii = #cir.ptr<null> : !cir.ptr<!cir.func<(!cir.int<s, 32>) -> !cir.int<s, 32>>>
-// CHECK: cir.global @fpvar : !cir.ptr<!cir.func<(!cir.int<s, 32>, ...)>>
+// CHECK: cir.global external @c : !cir.int<s, 8>
+// CHECK: cir.global external @sc : !cir.int<s, 8>
+// CHECK: cir.global external @uc : !cir.int<u, 8>
+// CHECK: cir.global external @ss : !cir.int<s, 16>
+// CHECK: cir.global external @us = #cir.int<100>
+// CHECK: cir.global external @si = #cir.int<42>
+// CHECK: cir.global external @ui : !cir.int<u, 32>
+// CHECK: cir.global external @sl : !cir.int<s, 64>
+// CHECK: cir.global external @ul : !cir.int<u, 64>
+// CHECK: cir.global external @sll : !cir.int<s, 64>
+// CHECK: cir.global external @ull = #cir.int<123456> : !cir.int<u, 64>
+// CHECK: cir.global external @s128 : !cir.int<s, 128>
+// CHECK: cir.global external @u128 : !cir.int<u, 128>
+// CHECK: cir.global external @wc : !cir.int<s, 32>
+// CHECK: cir.global external @c8 : !cir.int<u, 8>
+// CHECK: cir.global external @c16 : !cir.int<u, 16>
+// CHECK: cir.global external @c32 : !cir.int<u, 32>
+// CHECK: cir.global external @sb20 : !cir.int<s, 20>
+// CHECK: cir.global external @ub48 : !cir.int<u, 48>
+// CHECK: cir.global external @f16 : !cir.f16
+// CHECK: cir.global external @bf16 : !cir.bf16
+// CHECK: cir.global external @f : !cir.float
+// CHECK: cir.global external @d = #cir.fp<1.250000e+00> : !cir.double
+// CHECK: cir.global external @ld : !cir.long_double<!cir.f80>
+// CHECK: cir.global external @f128 : !cir.f128
+// CHECK: cir.global external @vp : !cir.ptr<!cir.void>
+// CHECK: cir.global external @ip = #cir.ptr<null> : !cir.ptr<!cir.int<s, 32>>
+// CHECK: cir.global external @dp : !cir.ptr<!cir.double>
+// CHECK: cir.global external @cpp : !cir.ptr<!cir.ptr<!cir.int<s, 8>>>
+// CHECK: cir.global external @fp : !cir.ptr<!cir.func<()>>
+// CHECK: cir.global external @fpii = #cir.ptr<null> : !cir.ptr<!cir.func<(!cir.int<s, 32>) -> !cir.int<s, 32>>>
+// CHECK: cir.global external @fpvar : !cir.ptr<!cir.func<(!cir.int<s, 32>, ...)>>
>From 422aded79077ee6e69e05d85c64b73e5f3b25e5d Mon Sep 17 00:00:00 2001
From: Henrich Lauko <xlauko at mail.muni.cz>
Date: Sat, 1 Mar 2025 02:04:44 +0100
Subject: [PATCH 4/7] cherry-pick 0bedc28 Clean up and complete
CIRGlobalValueInterface methods
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 9 ---
.../clang/CIR/Interfaces/CIROpInterfaces.td | 64 ++++++++++++++++---
2 files changed, 56 insertions(+), 17 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 2cef98099fdbb..e2ab50c78ec2d 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -517,15 +517,6 @@ def GlobalOp : CIR_Op<"global"> {
let extraClassDeclaration = [{
bool isDeclaration() { return !getInitialValue(); }
bool hasInitializer() { return !isDeclaration(); }
- bool hasAvailableExternallyLinkage() {
- return cir::isAvailableExternallyLinkage(getLinkage());
- }
- bool hasInternalLinkage() {
- return cir::isInternalLinkage(getLinkage());
- }
- /// Whether the definition of this global may be replaced at link time.
- bool isWeakForLinker() { return cir::isWeakForLinker(getLinkage()); }
- bool isDSOLocal() { return getDsolocal(); }
}];
let skipDefaultBuilders = 1;
diff --git a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
index 64a96bd55cf86..bd78be41d0bca 100644
--- a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
+++ b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
@@ -14,14 +14,54 @@
#define CLANG_CIR_INTERFACES_CIROPINTERFACES_TD
include "mlir/IR/OpBase.td"
+include "mlir/IR/SymbolInterfaces.td"
let cppNamespace = "::cir" in {
- def CIRGlobalValueInterface : OpInterface<"CIRGlobalValueInterface"> {
+ def CIRGlobalValueInterface
+ : OpInterface<"CIRGlobalValueInterface", [Symbol]> {
let methods =
- [InterfaceMethod<"", "bool", "hasAvailableExternallyLinkage", (ins),
+ [InterfaceMethod<"", "bool", "hasExternalLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
+ return cir::isExternalLinkage($_op.getLinkage());
+ }]>,
+ InterfaceMethod<"", "bool", "hasAvailableExternallyLinkage", (ins),
[{}],
- /*defaultImplementation=*/[{ return false; }]>,
+ /*defaultImplementation=*/[{
+ return cir::isAvailableExternallyLinkage($_op.getLinkage());
+ }]>,
+ InterfaceMethod<"", "bool", "hasLinkOnceLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
+ return cir::isLinkOnceLinkage($_op.getLinkage());
+ }]>,
+ InterfaceMethod<"", "bool", "hasLinkOnceAnyLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
+ return cir::isLinkOnceAnyLinkage($_op.getLinkage());
+ }]>,
+ InterfaceMethod<"", "bool", "hasLinkOnceODRLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
+ return cir::isLinkOnceODRLinkage($_op.getLinkage());
+ }]>,
+ InterfaceMethod<"", "bool", "hasWeakLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
+ return cir::isWeakLinkage($_op.getLinkage());
+ }]>,
+ InterfaceMethod<"", "bool", "hasWeakAnyLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
+ return cir::isWeakAnyLinkage($_op.getLinkage());
+ }]>,
+ InterfaceMethod<"", "bool", "hasWeakODRLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
+ return cir::isWeakODRLinkage($_op.getLinkage());
+ }]>,
+ InterfaceMethod<"", "bool", "hasInternalLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
+ return cir::isInternalLinkage($_op.getLinkage());
+ }]>,
+ InterfaceMethod<"", "bool", "hasPrivateLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
+ return cir::isPrivateLinkage($_op.getLinkage());
+ }]>,
InterfaceMethod<"", "bool", "hasLocalLinkage", (ins), [{}],
/*defaultImplementation=*/[{
return cir::isLocalLinkage($_op.getLinkage());
@@ -30,9 +70,9 @@ let cppNamespace = "::cir" in {
/*defaultImplementation=*/[{
return cir::isExternalWeakLinkage($_op.getLinkage());
}]>,
- InterfaceMethod<"", "bool", "isExternalLinkage", (ins), [{}],
+ InterfaceMethod<"", "bool", "hasCommonLinkage", (ins), [{}],
/*defaultImplementation=*/[{
- return cir::isExternalLinkage($_op.getLinkage());
+ return cir::isCommonLinkage($_op.getLinkage());
}]>,
InterfaceMethod<"", "bool", "isDeclarationForLinker", (ins), [{}],
/*defaultImplementation=*/[{
@@ -44,10 +84,18 @@ let cppNamespace = "::cir" in {
/*defaultImplementation=*/[{
$_op.setDsolocal(val);
}]>,
- ];
+ InterfaceMethod<"", "bool", "isDSOLocal", (ins), [{}],
+ /*defaultImplementation=*/[{
+ return $_op.getDsolocal();
+ }]>,
+ InterfaceMethod<"", "bool", "isWeakForLinker", (ins), [{}],
+ /*defaultImplementation=*/[{
+ return cir::isWeakForLinker($_op.getLinkage());
+ }]>];
let extraClassDeclaration = [{
- bool canBenefitFromLocalAlias();
- }];
+ bool hasDefaultVisibility();
+ bool canBenefitFromLocalAlias();
+ }];
}
} // namespace cir
>From 403356204953b27528f6e27e63a4be5cde446f38 Mon Sep 17 00:00:00 2001
From: Morris Hafner <mhafner at nvidia.com>
Date: Tue, 4 Mar 2025 18:27:47 +0100
Subject: [PATCH 5/7] Add CIR -> CIR test for global variable linkage
---
clang/test/CIR/IR/global-var-linkage.cir | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
create mode 100644 clang/test/CIR/IR/global-var-linkage.cir
diff --git a/clang/test/CIR/IR/global-var-linkage.cir b/clang/test/CIR/IR/global-var-linkage.cir
new file mode 100644
index 0000000000000..055201b27000d
--- /dev/null
+++ b/clang/test/CIR/IR/global-var-linkage.cir
@@ -0,0 +1,18 @@
+// RUN: cir-opt %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+ cir.global external @aaaa : !cir.int<s, 32>
+ cir.global internal @bbbb : !cir.int<s, 32>
+ cir.global linkonce_odr @cccc : !cir.int<s, 32>
+ cir.global internal @ffff = #cir.int<0> : !cir.int<s, 32>
+ cir.global weak_odr @dddd : !cir.int<s, 32>
+}
+
+// CHECK: module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+// CHECK: cir.global external @aaaa : !cir.int<s, 32>
+// CHECK: cir.global internal @bbbb : !cir.int<s, 32>
+// CHECK: cir.global linkonce_odr @cccc : !cir.int<s, 32>
+// CHECK: cir.global internal @ffff = #cir.int<0> : !cir.int<s, 32>
+// CHECK: cir.global weak_odr @dddd : !cir.int<s, 32>
+// CHECK: }
>From 8639f6576c7ec814f1aaaea3f813d5d9e01e8001 Mon Sep 17 00:00:00 2001
From: Morris Hafner <mhafner at nvidia.com>
Date: Tue, 4 Mar 2025 19:50:56 +0100
Subject: [PATCH 6/7] Reformat CIROpInterfaces.td
---
.../clang/CIR/Interfaces/CIROpInterfaces.td | 146 +++++++++++-------
1 file changed, 93 insertions(+), 53 deletions(-)
diff --git a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
index bd78be41d0bca..39ef402c59e43 100644
--- a/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
+++ b/clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
@@ -20,78 +20,118 @@ let cppNamespace = "::cir" in {
def CIRGlobalValueInterface
: OpInterface<"CIRGlobalValueInterface", [Symbol]> {
- let methods =
- [InterfaceMethod<"", "bool", "hasExternalLinkage", (ins), [{}],
- /*defaultImplementation=*/[{
+ let methods = [
+ InterfaceMethod<"",
+ "bool", "hasExternalLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
return cir::isExternalLinkage($_op.getLinkage());
- }]>,
- InterfaceMethod<"", "bool", "hasAvailableExternallyLinkage", (ins),
- [{}],
- /*defaultImplementation=*/[{
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "hasAvailableExternallyLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
return cir::isAvailableExternallyLinkage($_op.getLinkage());
- }]>,
- InterfaceMethod<"", "bool", "hasLinkOnceLinkage", (ins), [{}],
- /*defaultImplementation=*/[{
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "hasLinkOnceLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
return cir::isLinkOnceLinkage($_op.getLinkage());
- }]>,
- InterfaceMethod<"", "bool", "hasLinkOnceAnyLinkage", (ins), [{}],
- /*defaultImplementation=*/[{
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "hasLinkOnceAnyLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
return cir::isLinkOnceAnyLinkage($_op.getLinkage());
- }]>,
- InterfaceMethod<"", "bool", "hasLinkOnceODRLinkage", (ins), [{}],
- /*defaultImplementation=*/[{
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "hasLinkOnceODRLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
return cir::isLinkOnceODRLinkage($_op.getLinkage());
- }]>,
- InterfaceMethod<"", "bool", "hasWeakLinkage", (ins), [{}],
- /*defaultImplementation=*/[{
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "hasWeakLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
return cir::isWeakLinkage($_op.getLinkage());
- }]>,
- InterfaceMethod<"", "bool", "hasWeakAnyLinkage", (ins), [{}],
- /*defaultImplementation=*/[{
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "hasWeakAnyLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
return cir::isWeakAnyLinkage($_op.getLinkage());
- }]>,
- InterfaceMethod<"", "bool", "hasWeakODRLinkage", (ins), [{}],
- /*defaultImplementation=*/[{
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "hasWeakODRLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
return cir::isWeakODRLinkage($_op.getLinkage());
- }]>,
- InterfaceMethod<"", "bool", "hasInternalLinkage", (ins), [{}],
- /*defaultImplementation=*/[{
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "hasInternalLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
return cir::isInternalLinkage($_op.getLinkage());
- }]>,
- InterfaceMethod<"", "bool", "hasPrivateLinkage", (ins), [{}],
- /*defaultImplementation=*/[{
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "hasPrivateLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
return cir::isPrivateLinkage($_op.getLinkage());
- }]>,
- InterfaceMethod<"", "bool", "hasLocalLinkage", (ins), [{}],
- /*defaultImplementation=*/[{
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "hasLocalLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
return cir::isLocalLinkage($_op.getLinkage());
- }]>,
- InterfaceMethod<"", "bool", "hasExternalWeakLinkage", (ins), [{}],
- /*defaultImplementation=*/[{
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "hasExternalWeakLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
return cir::isExternalWeakLinkage($_op.getLinkage());
- }]>,
- InterfaceMethod<"", "bool", "hasCommonLinkage", (ins), [{}],
- /*defaultImplementation=*/[{
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "hasCommonLinkage", (ins), [{}],
+ /*defaultImplementation=*/[{
return cir::isCommonLinkage($_op.getLinkage());
- }]>,
- InterfaceMethod<"", "bool", "isDeclarationForLinker", (ins), [{}],
- /*defaultImplementation=*/[{
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "isDeclarationForLinker", (ins), [{}],
+ /*defaultImplementation=*/[{
if ($_op.hasAvailableExternallyLinkage())
return true;
return $_op.isDeclaration();
- }]>,
- InterfaceMethod<"", "void", "setDSOLocal", (ins "bool":$val), [{}],
- /*defaultImplementation=*/[{
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "hasComdat", (ins), [{}],
+ /*defaultImplementation=*/[{
+ return $_op.getComdat();
+ }]
+ >,
+ InterfaceMethod<"",
+ "void", "setDSOLocal", (ins "bool":$val), [{}],
+ /*defaultImplementation=*/[{
$_op.setDsolocal(val);
- }]>,
- InterfaceMethod<"", "bool", "isDSOLocal", (ins), [{}],
- /*defaultImplementation=*/[{
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "isDSOLocal", (ins), [{}],
+ /*defaultImplementation=*/[{
return $_op.getDsolocal();
- }]>,
- InterfaceMethod<"", "bool", "isWeakForLinker", (ins), [{}],
- /*defaultImplementation=*/[{
+ }]
+ >,
+ InterfaceMethod<"",
+ "bool", "isWeakForLinker", (ins), [{}],
+ /*defaultImplementation=*/[{
return cir::isWeakForLinker($_op.getLinkage());
- }]>];
+ }]
+ >
+ ];
let extraClassDeclaration = [{
bool hasDefaultVisibility();
bool canBenefitFromLocalAlias();
>From 9f4fcdfb73c8bf1e6df01eb46ffd52d8a34ac0ab Mon Sep 17 00:00:00 2001
From: Morris Hafner <mmha at users.noreply.github.com>
Date: Wed, 5 Mar 2025 13:25:32 +0100
Subject: [PATCH 7/7] Update clang/include/clang/CIR/Dialect/IR/CIROpsEnums.h
Co-authored-by: Henrich Lauko <xlauko at mail.muni.cz>
---
clang/include/clang/CIR/Dialect/IR/CIROpsEnums.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROpsEnums.h b/clang/include/clang/CIR/Dialect/IR/CIROpsEnums.h
index 2b7270c42d343..fead5725d183d 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROpsEnums.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIROpsEnums.h
@@ -1,5 +1,4 @@
//===----------------------------------------------------------------------===//
-//-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
More information about the cfe-commits
mailing list