[clang] [CIR] Upstream global variable linkage types (PR #129072)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 27 07:57:22 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Morris Hafner (mmha)
<details>
<summary>Changes</summary>
This change implements variable linkage types in ClangIR except for common linkage which requires Comdat support.
---
Patch is 37.19 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/129072.diff
19 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/IR/CIRDialect.h (+2)
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+79-4)
- (added) clang/include/clang/CIR/Dialect/IR/CIROpsEnums.h (+119)
- (modified) clang/include/clang/CIR/Dialect/IR/CMakeLists.txt (+3-1)
- (added) clang/include/clang/CIR/Interfaces/CIROpInterfaces.h (+29)
- (added) clang/include/clang/CIR/Interfaces/CIROpInterfaces.td (+63)
- (modified) clang/include/clang/CIR/Interfaces/CMakeLists.txt (+9)
- (modified) clang/include/clang/CIR/MissingFeatures.h (+4)
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.cpp (+201-1)
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.h (+12)
- (modified) clang/lib/CIR/CodeGen/CMakeLists.txt (+1)
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+7-1)
- (modified) clang/lib/CIR/Dialect/IR/CMakeLists.txt (+2-1)
- (modified) clang/lib/CIR/FrontendAction/CMakeLists.txt (+4)
- (added) clang/lib/CIR/Interfaces/CIROpInterfaces.cpp (+22)
- (modified) clang/lib/CIR/Interfaces/CMakeLists.txt (+3-1)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt (+5)
- (modified) clang/test/CIR/global-var-simple.cpp (+32-32)
- (added) clang/test/CIR/global_var_linkage.cpp (+11)
``````````diff
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 f9ce38588e436..7c5d339130ec5 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"
@@ -278,6 +280,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.
@@ -289,12 +344,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
@@ -303,12 +365,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 d4fcd52e7e6e3..0d0083850eb70 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -36,6 +36,10 @@ struct MissingFeatures {
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; }
+ static bool supportComdat() { return false; }
};
} // namespace cir
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 (...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/129072
More information about the cfe-commits
mailing list