[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