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 <mhaf...@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 <mhaf...@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 <mhaf...@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 <xla...@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 <mhaf...@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 <mhaf...@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 <m...@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 <xla...@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. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits