[flang-commits] [flang] [mlir] [flang][FIR] Represent fir.global linkage with a typed enum attribute (PR #220243)
Scott Manley via flang-commits
flang-commits at lists.llvm.org
Tue Sep 1 06:14:06 PDT 2026
https://github.com/rscottmanley created https://github.com/llvm/llvm-project/pull/220243
Replace the string linkName on fir.global with fir::LinkageAttr / LinkageEnum so only the supported linkages can be used, and CodeGen can map them without string compares.
>From 2d7e9244b5591e5595524ab54ebc91211e83c334 Mon Sep 17 00:00:00 2001
From: Scott Manley <scmanley at nvidia.com>
Date: Tue, 1 Sep 2026 05:57:39 -0700
Subject: [PATCH] [flang][FIR] Represent fir.global linkage with a typed enum
attribute
Replace the string linkName on fir.global with fir::LinkageAttr /
LinkageEnum so only the supported linkages can be used, and CodeGen
can map them without string compares.
---
flang/include/flang/Lower/ConvertConstant.h | 2 +-
flang/include/flang/Lower/ConvertVariable.h | 2 +-
.../flang/Optimizer/Builder/FIRBuilder.h | 34 +++++++++-----
.../flang/Optimizer/Dialect/FIRAttr.td | 47 +++++++++++++++++++
.../include/flang/Optimizer/Dialect/FIROps.td | 10 ++--
flang/lib/Lower/ConvertConstant.cpp | 8 ++--
flang/lib/Lower/ConvertVariable.cpp | 24 +++++-----
flang/lib/Lower/IO.cpp | 4 +-
flang/lib/Lower/OpenMP/OpenMP.cpp | 2 +-
flang/lib/Optimizer/Builder/FIRBuilder.cpp | 4 +-
.../Builder/Runtime/EnvironmentDefaults.cpp | 2 +-
flang/lib/Optimizer/CodeGen/CodeGen.cpp | 22 +++++----
flang/lib/Optimizer/Dialect/FIROps.cpp | 33 +++++++------
.../Transforms/CUDA/CUFAddConstructor.cpp | 2 +-
.../CUFComputeSharedMemoryOffsetsAndSize.cpp | 2 +-
.../Transforms/CUDA/CUFDeviceGlobal.cpp | 8 ++--
.../Optimizer/Builder/FIRBuilderTest.cpp | 13 ++---
.../ACCDeclareGPUModuleInsertion.cpp | 2 +-
18 files changed, 137 insertions(+), 84 deletions(-)
diff --git a/flang/include/flang/Lower/ConvertConstant.h b/flang/include/flang/Lower/ConvertConstant.h
index dd19507d4c005..df903783471eb 100644
--- a/flang/include/flang/Lower/ConvertConstant.h
+++ b/flang/include/flang/Lower/ConvertConstant.h
@@ -63,7 +63,7 @@ fir::ExtendedValue convertConstant(Fortran::lower::AbstractConverter &converter,
fir::GlobalOp tryCreatingDenseGlobal(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Type symTy,
llvm::StringRef globalName,
- mlir::StringAttr linkage, bool isConst,
+ fir::LinkageAttr linkage, bool isConst,
const Fortran::lower::SomeExpr &initExpr,
cuf::DataAttributeAttr dataAttr = {},
bool setDefaultAlignment = true);
diff --git a/flang/include/flang/Lower/ConvertVariable.h b/flang/include/flang/Lower/ConvertVariable.h
index a4ad984579410..c8f117e63040f 100644
--- a/flang/include/flang/Lower/ConvertVariable.h
+++ b/flang/include/flang/Lower/ConvertVariable.h
@@ -136,7 +136,7 @@ mlir::Value genInitialDataTarget(Fortran::lower::AbstractConverter &,
/// Create the global op and its init if it has one
fir::GlobalOp defineGlobal(Fortran::lower::AbstractConverter &converter,
const Fortran::lower::pft::Variable &var,
- llvm::StringRef globalName, mlir::StringAttr linkage,
+ llvm::StringRef globalName, fir::LinkageAttr linkage,
cuf::DataAttributeAttr dataAttr = {});
/// Generate address \p addr inside an initializer.
diff --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h
index 22d0a6f7febbc..a29e3bf7063a5 100644
--- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h
@@ -340,7 +340,7 @@ class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener {
/// Create a global value.
fir::GlobalOp createGlobal(mlir::Location loc, mlir::Type type,
llvm::StringRef name,
- mlir::StringAttr linkage = {},
+ fir::LinkageAttr linkage = {},
mlir::Attribute value = {}, bool isConst = false,
bool isTarget = false,
cuf::DataAttributeAttr dataAttr = {},
@@ -349,14 +349,14 @@ class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener {
fir::GlobalOp createGlobal(mlir::Location loc, mlir::Type type,
llvm::StringRef name, bool isConst, bool isTarget,
std::function<void(FirOpBuilder &)> bodyBuilder,
- mlir::StringAttr linkage = {},
+ fir::LinkageAttr linkage = {},
cuf::DataAttributeAttr dataAttr = {},
bool setDefaultAlignment = true);
/// Create a global constant (read-only) value.
fir::GlobalOp createGlobalConstant(mlir::Location loc, mlir::Type type,
llvm::StringRef name,
- mlir::StringAttr linkage = {},
+ fir::LinkageAttr linkage = {},
mlir::Attribute value = {}) {
return createGlobal(loc, type, name, linkage, value, /*isConst=*/true,
/*isTarget=*/false);
@@ -366,7 +366,7 @@ class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener {
createGlobalConstant(mlir::Location loc, mlir::Type type,
llvm::StringRef name,
std::function<void(FirOpBuilder &)> bodyBuilder,
- mlir::StringAttr linkage = {}) {
+ fir::LinkageAttr linkage = {}) {
return createGlobal(loc, type, name, /*isConst=*/true, /*isTarget=*/false,
bodyBuilder, linkage);
}
@@ -383,24 +383,32 @@ class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener {
// Linkage helpers (inline). The default linkage is external.
//===--------------------------------------------------------------------===//
- static mlir::StringAttr createCommonLinkage(mlir::MLIRContext *context) {
- return mlir::StringAttr::get(context, "common");
+ static fir::LinkageAttr createCommonLinkage(mlir::MLIRContext *context) {
+ return fir::LinkageAttr::get(context, fir::LinkageEnum::Common);
}
- mlir::StringAttr createCommonLinkage() {
+ fir::LinkageAttr createCommonLinkage() {
return createCommonLinkage(getContext());
}
- mlir::StringAttr createExternalLinkage() { return getStringAttr("external"); }
+ fir::LinkageAttr createExternalLinkage() {
+ return fir::LinkageAttr::get(getContext(), fir::LinkageEnum::External);
+ }
- mlir::StringAttr createInternalLinkage() { return getStringAttr("internal"); }
+ fir::LinkageAttr createInternalLinkage() {
+ return fir::LinkageAttr::get(getContext(), fir::LinkageEnum::Internal);
+ }
- mlir::StringAttr createLinkOnceLinkage() { return getStringAttr("linkonce"); }
+ fir::LinkageAttr createLinkOnceLinkage() {
+ return fir::LinkageAttr::get(getContext(), fir::LinkageEnum::Linkonce);
+ }
- mlir::StringAttr createLinkOnceODRLinkage() {
- return getStringAttr("linkonce_odr");
+ fir::LinkageAttr createLinkOnceODRLinkage() {
+ return fir::LinkageAttr::get(getContext(), fir::LinkageEnum::LinkonceODR);
}
- mlir::StringAttr createWeakLinkage() { return getStringAttr("weak"); }
+ fir::LinkageAttr createWeakLinkage() {
+ return fir::LinkageAttr::get(getContext(), fir::LinkageEnum::Weak);
+ }
/// Get a function by name. If the function exists in the current module, it
/// is returned. Otherwise, a null FuncOp is returned.
diff --git a/flang/include/flang/Optimizer/Dialect/FIRAttr.td b/flang/include/flang/Optimizer/Dialect/FIRAttr.td
index c53a2b869e968..cfe8e96e8e4a5 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRAttr.td
+++ b/flang/include/flang/Optimizer/Dialect/FIRAttr.td
@@ -15,10 +15,57 @@
include "flang/Optimizer/Dialect/FIRDialect.td"
include "mlir/Dialect/OpenACC/OpenACCAttributes.td"
+include "mlir/IR/CommonAttrConstraints.td"
include "mlir/IR/EnumAttr.td"
class fir_Attr<string name> : AttrDef<FIROpsDialect, name>;
+//===----------------------------------------------------------------------===//
+// Linkage
+//===----------------------------------------------------------------------===//
+
+// Linkage attribute used on fir.global. This is a subset of LLVM linkage
+// types currently supported by FIR. The names match the keywords in the
+// custom assembly form of fir.global. External is the default when omitted.
+def FIR_LinkageExternal
+ : I64EnumAttrCase<"External", 0, "external">;
+def FIR_LinkageInternal
+ : I64EnumAttrCase<"Internal", 1, "internal">;
+def FIR_LinkageLinkonce
+ : I64EnumAttrCase<"Linkonce", 2, "linkonce">;
+def FIR_LinkageLinkonceODR
+ : I64EnumAttrCase<"LinkonceODR", 3, "linkonce_odr">;
+def FIR_LinkageWeak
+ : I64EnumAttrCase<"Weak", 4, "weak">;
+def FIR_LinkageCommon
+ : I64EnumAttrCase<"Common", 5, "common">;
+
+def fir_LinkageEnum : I64EnumAttr<
+ "LinkageEnum",
+ "FIR linkage types",
+ [FIR_LinkageExternal, FIR_LinkageInternal, FIR_LinkageLinkonce,
+ FIR_LinkageLinkonceODR, FIR_LinkageWeak, FIR_LinkageCommon]> {
+ let cppNamespace = "::fir";
+ let genSpecializedAttr = 0;
+}
+
+def fir_LinkageAttr : fir_Attr<"Linkage"> {
+ let mnemonic = "linkage";
+ let parameters = (ins "LinkageEnum":$linkage);
+ let assemblyFormat = "`<` $linkage `>`";
+}
+
+def fir_Linkage : DialectAttr<
+ FIROpsDialect,
+ CPred<"::llvm::isa<::fir::LinkageAttr>($_self)">,
+ "FIR linkage specification"> {
+ let storageType = "::fir::LinkageAttr";
+ let returnType = "::fir::LinkageEnum";
+ let convertFromStorage = "$_self.getLinkage()";
+ let constBuilderCall =
+ "::fir::LinkageAttr::get($_builder.getContext(), $0)";
+}
+
def FIRnoAttributes : I32BitEnumAttrCaseNone<"None">;
def FIRallocatable : I32BitEnumAttrCaseBit<"allocatable", 0>;
def FIRasynchronous : I32BitEnumAttrCaseBit<"asynchronous", 1>;
diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td
index fd0b5b16c87ad..1a5c29a6e991e 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.td
@@ -2920,7 +2920,7 @@ def fir_GlobalOp : fir_Op<"global", [IsolatedFromAbove, SymbolName,
OptionalAttr<AnyAttr>:$initVal,
OptionalAttr<UnitAttr>:$constant,
OptionalAttr<UnitAttr>:$target,
- OptionalAttr<StrAttr>:$linkName,
+ OptionalAttr<fir_Linkage>:$linkage,
OptionalAttr<cuf_DataAttributeAttr>:$data_attr,
OptionalAttr<I64Attr>:$alignment,
OptionalAttr<StrAttr>:$sym_visibility
@@ -2938,18 +2938,18 @@ def fir_GlobalOp : fir_Op<"global", [IsolatedFromAbove, SymbolName,
"bool":$isTarget, "mlir::Type":$type,
CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attrs)>,
OpBuilder<(ins "llvm::StringRef":$name, "mlir::Type":$type,
- CArg<"mlir::StringAttr", "{}">:$linkage,
+ CArg<"fir::LinkageAttr", "{}">:$linkage,
CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attrs)>,
OpBuilder<(ins "llvm::StringRef":$name, "bool":$isConstant,
"bool":$isTarget,
- "mlir::Type":$type, CArg<"mlir::StringAttr", "{}">:$linkage,
+ "mlir::Type":$type, CArg<"fir::LinkageAttr", "{}">:$linkage,
CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attrs)>,
OpBuilder<(ins "llvm::StringRef":$name, "mlir::Type":$type,
- "mlir::Attribute":$initVal, CArg<"mlir::StringAttr", "{}">:$linkage,
+ "mlir::Attribute":$initVal, CArg<"fir::LinkageAttr", "{}">:$linkage,
CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attrs)>,
OpBuilder<(ins "llvm::StringRef":$name, "bool":$isConstant,
"bool":$isTarget, "mlir::Type":$type, "mlir::Attribute":$initVal,
- CArg<"mlir::StringAttr", "{}">:$linkage,
+ CArg<"fir::LinkageAttr", "{}">:$linkage,
CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attrs)>,
];
diff --git a/flang/lib/Lower/ConvertConstant.cpp b/flang/lib/Lower/ConvertConstant.cpp
index 6525ce50f9fdc..f48dc9931e627 100644
--- a/flang/lib/Lower/ConvertConstant.cpp
+++ b/flang/lib/Lower/ConvertConstant.cpp
@@ -104,7 +104,7 @@ class DenseGlobalBuilder {
public:
static fir::GlobalOp
tryCreating(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type symTy,
- llvm::StringRef globalName, mlir::StringAttr linkage,
+ llvm::StringRef globalName, fir::LinkageAttr linkage,
bool isConst, const Fortran::lower::SomeExpr &initExpr,
cuf::DataAttributeAttr dataAttr, bool setDefaultAlignment) {
DenseGlobalBuilder globalBuilder;
@@ -130,7 +130,7 @@ class DenseGlobalBuilder {
template <Fortran::common::TypeCategory TC, int KIND>
static fir::GlobalOp tryCreating(
fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type symTy,
- llvm::StringRef globalName, mlir::StringAttr linkage, bool isConst,
+ llvm::StringRef globalName, fir::LinkageAttr linkage, bool isConst,
const Fortran::evaluate::Constant<Fortran::evaluate::Type<TC, KIND>>
&constant,
cuf::DataAttributeAttr dataAttr, bool setDefaultAlignment = true) {
@@ -202,7 +202,7 @@ class DenseGlobalBuilder {
fir::GlobalOp tryCreatingGlobal(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Type symTy,
llvm::StringRef globalName,
- mlir::StringAttr linkage, bool isConst,
+ fir::LinkageAttr linkage, bool isConst,
cuf::DataAttributeAttr dataAttr,
bool setDefaultAlignment) const {
// Not a "trivial" intrinsic constant array, or empty array.
@@ -228,7 +228,7 @@ class DenseGlobalBuilder {
fir::GlobalOp Fortran::lower::tryCreatingDenseGlobal(
fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type symTy,
- llvm::StringRef globalName, mlir::StringAttr linkage, bool isConst,
+ llvm::StringRef globalName, fir::LinkageAttr linkage, bool isConst,
const Fortran::lower::SomeExpr &initExpr, cuf::DataAttributeAttr dataAttr,
bool setDefaultAlignment) {
return DenseGlobalBuilder::tryCreating(builder, loc, symTy, globalName,
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index a808905850922..8438b39c990a9 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -198,7 +198,7 @@ static void attachAccDeclareAttribute(fir::FirOpBuilder &builder,
static fir::GlobalOp declareGlobal(Fortran::lower::AbstractConverter &converter,
const Fortran::lower::pft::Variable &var,
llvm::StringRef globalName,
- mlir::StringAttr linkage) {
+ fir::LinkageAttr linkage) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
if (fir::GlobalOp global = builder.getNamedGlobal(globalName))
return global;
@@ -497,7 +497,7 @@ createGlobalInitialization(fir::FirOpBuilder &builder, fir::GlobalOp global,
fir::GlobalOp Fortran::lower::defineGlobal(
Fortran::lower::AbstractConverter &converter,
const Fortran::lower::pft::Variable &var, llvm::StringRef globalName,
- mlir::StringAttr linkage, cuf::DataAttributeAttr dataAttr) {
+ fir::LinkageAttr linkage, cuf::DataAttributeAttr dataAttr) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
const Fortran::semantics::Symbol &sym = var.getSymbol();
mlir::Location loc = genLocation(converter, sym);
@@ -628,7 +628,7 @@ fir::GlobalOp Fortran::lower::defineGlobal(
// with no other definitions, and to never link the resulting module
// object file.
if (sym.attrs().test(Fortran::semantics::Attr::BIND_C))
- global.setLinkName(builder.createCommonLinkage());
+ global.setLinkageAttr(builder.createCommonLinkage());
createGlobalInitialization(
builder, global, [&](fir::FirOpBuilder &builder) {
mlir::Value initValue;
@@ -647,7 +647,7 @@ fir::GlobalOp Fortran::lower::defineGlobal(
}
/// Return linkage attribute for \p var.
-static mlir::StringAttr
+static fir::LinkageAttr
getLinkageAttribute(Fortran::lower::AbstractConverter &converter,
const Fortran::lower::pft::Variable &var) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
@@ -680,7 +680,7 @@ static void instantiateGlobal(Fortran::lower::AbstractConverter &converter,
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
std::string globalName = converter.mangleName(sym);
mlir::Location loc = genLocation(converter, sym);
- mlir::StringAttr linkage = getLinkageAttribute(converter, var);
+ fir::LinkageAttr linkage = getLinkageAttribute(converter, var);
fir::GlobalOp global;
if (Fortran::evaluate::IsCoarray(sym)) {
@@ -905,7 +905,7 @@ genInlinedInitWithMemcpy(Fortran::lower::AbstractConverter &converter,
(converter.mangleName(*declTy->AsDerived()) + fir::kNameSeparator +
fir::kDerivedTypeInitSuffix)
.str());
- mlir::StringAttr linkage = builder.createInternalLinkage();
+ fir::LinkageAttr linkage = builder.createInternalLinkage();
fir::GlobalOp global = builder.getNamedGlobal(globalName);
if (!global && details->init()) {
global = builder.createGlobal(symLoc, symTy, globalName, linkage,
@@ -1398,7 +1398,7 @@ getAggregateType(Fortran::lower::AbstractConverter &converter,
static fir::GlobalOp defineGlobalAggregateStore(
Fortran::lower::AbstractConverter &converter,
const Fortran::lower::pft::Variable::AggregateStore &aggregate,
- llvm::StringRef aggName, mlir::StringAttr linkage) {
+ llvm::StringRef aggName, fir::LinkageAttr linkage) {
assert(aggregate.isGlobal() && "not a global interval");
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
fir::GlobalOp global = builder.getNamedGlobal(aggName);
@@ -1443,7 +1443,7 @@ static fir::GlobalOp defineGlobalAggregateStore(
static fir::GlobalOp declareGlobalAggregateStore(
Fortran::lower::AbstractConverter &converter, mlir::Location loc,
const Fortran::lower::pft::Variable::AggregateStore &aggregate,
- llvm::StringRef aggName, mlir::StringAttr linkage) {
+ llvm::StringRef aggName, fir::LinkageAttr linkage) {
assert(aggregate.isGlobal() && "not a global interval");
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
if (fir::GlobalOp global = builder.getNamedGlobal(aggName))
@@ -1467,7 +1467,7 @@ instantiateAggregateStore(Fortran::lower::AbstractConverter &converter,
if (var.isGlobal()) {
fir::GlobalOp global;
auto &aggregate = var.getAggregateStore();
- mlir::StringAttr linkage = getLinkageAttribute(converter, var);
+ fir::LinkageAttr linkage = getLinkageAttribute(converter, var);
if (var.isModuleOrSubmoduleVariable()) {
// A module global was or will be defined when lowering the module. Emit
// only a declaration if the global does not exist at that point.
@@ -1668,7 +1668,7 @@ declareCommonBlock(Fortran::lower::AbstractConverter &converter,
Fortran::semantics::MutableSymbolVector cmnBlkMems =
getCommonMembersWithInitAliases(common);
mlir::Location loc = converter.genLocation(common.name());
- mlir::StringAttr linkage = builder.createCommonLinkage();
+ fir::LinkageAttr linkage = builder.createCommonLinkage();
const auto *details =
common.detailsIf<Fortran::semantics::CommonBlockDetails>();
assert(details && "Expect CommonBlockDetails on the common symbol");
@@ -2708,7 +2708,7 @@ void Fortran::lower::defineModuleVariable(
AbstractConverter &converter, const Fortran::lower::pft::Variable &var) {
// Use empty linkage for module variables, which makes them available
// for use in another unit.
- mlir::StringAttr linkage = getLinkageAttribute(converter, var);
+ fir::LinkageAttr linkage = getLinkageAttribute(converter, var);
if (!var.isGlobal())
fir::emitFatalError(converter.getCurrentLocation(),
"attempting to lower module variable as local");
@@ -2845,7 +2845,7 @@ void Fortran::lower::createRuntimeTypeInfoGlobal(
const Fortran::semantics::Symbol &typeInfoSym) {
std::string globalName = converter.mangleName(typeInfoSym);
auto var = Fortran::lower::pft::Variable(typeInfoSym, /*global=*/true);
- mlir::StringAttr linkage = getLinkageAttribute(converter, var);
+ fir::LinkageAttr linkage = getLinkageAttribute(converter, var);
defineGlobal(converter, var, globalName, linkage);
}
diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp
index 490db8cc1d1ba..611b6918fc46c 100644
--- a/flang/lib/Lower/IO.cpp
+++ b/flang/lib/Lower/IO.cpp
@@ -262,7 +262,7 @@ getNonTbpDefinedIoTableAddr(Fortran::lower::AbstractConverter &converter,
table.resultType(),
table.getSymbol()));
- mlir::StringAttr linkOnce = builder.createLinkOnceLinkage();
+ fir::LinkageAttr linkOnce = builder.createLinkOnceLinkage();
mlir::Type idxTy = builder.getIndexType();
mlir::Type sizeTy =
fir::runtime::getModel<std::size_t>()(builder.getContext());
@@ -426,7 +426,7 @@ getNamelistGroup(Fortran::lower::AbstractConverter &converter,
const auto &details =
symbol.GetUltimate().get<Fortran::semantics::NamelistDetails>();
mlir::MLIRContext *context = builder.getContext();
- mlir::StringAttr linkOnce = builder.createLinkOnceLinkage();
+ fir::LinkageAttr linkOnce = builder.createLinkOnceLinkage();
mlir::Type idxTy = builder.getIndexType();
mlir::Type sizeTy =
fir::runtime::getModel<std::size_t>()(builder.getContext());
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 4563d997b33ae..f2ca5c172d11a 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -1220,7 +1220,7 @@ static fir::GlobalOp globalInitialization(lower::AbstractConverter &converter,
const lower::pft::Variable &var,
mlir::Location currentLocation) {
std::string globalName = converter.mangleName(sym);
- mlir::StringAttr linkage = firOpBuilder.createInternalLinkage();
+ fir::LinkageAttr linkage = firOpBuilder.createInternalLinkage();
return Fortran::lower::defineGlobal(converter, var, globalName, linkage);
}
diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
index a84d4fd978e05..ee33c172494e9 100644
--- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp
+++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
@@ -457,7 +457,7 @@ void fir::FirOpBuilder::genStackRestore(mlir::Location loc,
/// must have a unique name to identify and reference it.
fir::GlobalOp fir::FirOpBuilder::createGlobal(
mlir::Location loc, mlir::Type type, llvm::StringRef name,
- mlir::StringAttr linkage, mlir::Attribute value, bool isConst,
+ fir::LinkageAttr linkage, mlir::Attribute value, bool isConst,
bool isTarget, cuf::DataAttributeAttr dataAttr, bool setDefaultAlignment) {
if (auto global = getNamedGlobal(name))
return global;
@@ -485,7 +485,7 @@ fir::GlobalOp fir::FirOpBuilder::createGlobal(
fir::GlobalOp fir::FirOpBuilder::createGlobal(
mlir::Location loc, mlir::Type type, llvm::StringRef name, bool isConst,
bool isTarget, std::function<void(FirOpBuilder &)> bodyBuilder,
- mlir::StringAttr linkage, cuf::DataAttributeAttr dataAttr,
+ fir::LinkageAttr linkage, cuf::DataAttributeAttr dataAttr,
bool setDefaultAlignment) {
if (auto global = getNamedGlobal(name))
return global;
diff --git a/flang/lib/Optimizer/Builder/Runtime/EnvironmentDefaults.cpp b/flang/lib/Optimizer/Builder/Runtime/EnvironmentDefaults.cpp
index fa3d00e8b844f..1c98f5066260e 100755
--- a/flang/lib/Optimizer/Builder/Runtime/EnvironmentDefaults.cpp
+++ b/flang/lib/Optimizer/Builder/Runtime/EnvironmentDefaults.cpp
@@ -20,7 +20,7 @@ mlir::Value fir::runtime::genEnvironmentDefaults(
fir::NameUniquer::doGenerated("EnvironmentDefaults");
mlir::MLIRContext *context = builder.getContext();
- mlir::StringAttr linkOnce = builder.createLinkOnceLinkage();
+ fir::LinkageAttr linkOnce = builder.createLinkOnceLinkage();
mlir::IntegerType intTy = builder.getIntegerType(8 * sizeof(int));
fir::ReferenceType charRefTy =
fir::ReferenceType::get(builder.getIntegerType(8));
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index fb98ca5fb5dcd..10ec85340fde6 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -3739,7 +3739,7 @@ struct GlobalOpConversion : public fir::FIROpConversion<fir::GlobalOp> {
auto loc = global.getLoc();
mlir::Attribute initAttr = global.getInitVal().value_or(mlir::Attribute());
assert(attributeTypeIsCompatible(global.getContext(), initAttr, tyAttr));
- auto linkage = convertLinkage(global.getLinkName());
+ auto linkage = convertLinkage(global.getLinkage());
auto isConst = global.getConstant().has_value();
mlir::SymbolRefAttr comdat;
llvm::ArrayRef<mlir::NamedAttribute> attrs;
@@ -3856,22 +3856,24 @@ struct GlobalOpConversion : public fir::FIROpConversion<fir::GlobalOp> {
return mlir::success();
}
- // TODO: String comparisons should be avoided. Replace linkName with an
- // enumeration.
mlir::LLVM::Linkage
- convertLinkage(std::optional<llvm::StringRef> optLinkage) const {
+ convertLinkage(std::optional<fir::LinkageEnum> optLinkage) const {
if (optLinkage) {
- auto name = *optLinkage;
- if (name == "internal")
+ switch (*optLinkage) {
+ case fir::LinkageEnum::Internal:
return mlir::LLVM::Linkage::Internal;
- if (name == "linkonce")
+ case fir::LinkageEnum::Linkonce:
return mlir::LLVM::Linkage::Linkonce;
- if (name == "linkonce_odr")
+ case fir::LinkageEnum::LinkonceODR:
return mlir::LLVM::Linkage::LinkonceODR;
- if (name == "common")
+ case fir::LinkageEnum::Common:
return mlir::LLVM::Linkage::Common;
- if (name == "weak")
+ case fir::LinkageEnum::Weak:
return mlir::LLVM::Linkage::Weak;
+ case fir::LinkageEnum::External:
+ return mlir::LLVM::Linkage::External;
+ }
+ return mlir::LLVM::Linkage::External;
}
return mlir::LLVM::Linkage::External;
}
diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index 108f7fc793c61..0aa5fd60e2b52 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -2810,10 +2810,11 @@ mlir::ParseResult fir::GlobalOp::parse(mlir::OpAsmParser &parser,
auto &builder = parser.getBuilder();
if (mlir::succeeded(parser.parseOptionalKeyword(&linkage))) {
if (fir::GlobalOp::verifyValidLinkage(linkage))
- return mlir::failure();
- mlir::StringAttr linkAttr = builder.getStringAttr(linkage);
- result.addAttribute(fir::GlobalOp::getLinkNameAttrName(result.name),
- linkAttr);
+ return parser.emitError(parser.getCurrentLocation())
+ << "invalid linkage '" << linkage << "'";
+ auto linkEnum = fir::symbolizeLinkageEnum(linkage);
+ result.addAttribute(fir::GlobalOp::getLinkageAttrName(result.name),
+ fir::LinkageAttr::get(builder.getContext(), *linkEnum));
}
// Parse the name as a symbol reference attribute.
@@ -2870,8 +2871,8 @@ mlir::ParseResult fir::GlobalOp::parse(mlir::OpAsmParser &parser,
void fir::GlobalOp::print(mlir::OpAsmPrinter &p) {
if (mlir::StringAttr visibility = getSymVisibilityAttr())
p << ' ' << visibility.getValue();
- if (getLinkName())
- p << ' ' << *getLinkName();
+ if (std::optional<fir::LinkageEnum> link = getLinkage())
+ p << ' ' << fir::stringifyLinkageEnum(*link);
p << ' ';
p.printAttributeWithoutType(getSymrefAttr());
if (auto val = getValueOrNull())
@@ -2880,7 +2881,7 @@ void fir::GlobalOp::print(mlir::OpAsmPrinter &p) {
p.printOptionalAttrDict(
(*this)->getAttrs(), /*elideAttrs=*/{
getSymNameAttrName(), getSymrefAttrName(), getTypeAttrName(),
- getConstantAttrName(), getTargetAttrName(), getLinkNameAttrName(),
+ getConstantAttrName(), getTargetAttrName(), getLinkageAttrName(),
getInitValAttrName(), getSymVisibilityAttrName()});
if (getOperation()->getAttr(getConstantAttrName()))
p << " " << getConstantAttrName().strref();
@@ -2903,7 +2904,7 @@ void fir::GlobalOp::appendInitialValue(mlir::Operation *op) {
void fir::GlobalOp::build(mlir::OpBuilder &builder,
mlir::OperationState &result, llvm::StringRef name,
bool isConstant, bool isTarget, mlir::Type type,
- mlir::Attribute initialVal, mlir::StringAttr linkage,
+ mlir::Attribute initialVal, fir::LinkageAttr linkage,
llvm::ArrayRef<mlir::NamedAttribute> attrs) {
result.addRegion();
result.addAttribute(getTypeAttrName(result.name), mlir::TypeAttr::get(type));
@@ -2919,14 +2920,14 @@ void fir::GlobalOp::build(mlir::OpBuilder &builder,
if (initialVal)
result.addAttribute(getInitValAttrName(result.name), initialVal);
if (linkage)
- result.addAttribute(getLinkNameAttrName(result.name), linkage);
+ result.addAttribute(getLinkageAttrName(result.name), linkage);
result.attributes.append(attrs.begin(), attrs.end());
}
void fir::GlobalOp::build(mlir::OpBuilder &builder,
mlir::OperationState &result, llvm::StringRef name,
mlir::Type type, mlir::Attribute initialVal,
- mlir::StringAttr linkage,
+ fir::LinkageAttr linkage,
llvm::ArrayRef<mlir::NamedAttribute> attrs) {
build(builder, result, name, /*isConstant=*/false, /*isTarget=*/false, type,
{}, linkage, attrs);
@@ -2935,14 +2936,14 @@ void fir::GlobalOp::build(mlir::OpBuilder &builder,
void fir::GlobalOp::build(mlir::OpBuilder &builder,
mlir::OperationState &result, llvm::StringRef name,
bool isConstant, bool isTarget, mlir::Type type,
- mlir::StringAttr linkage,
+ fir::LinkageAttr linkage,
llvm::ArrayRef<mlir::NamedAttribute> attrs) {
build(builder, result, name, isConstant, isTarget, type, {}, linkage, attrs);
}
void fir::GlobalOp::build(mlir::OpBuilder &builder,
mlir::OperationState &result, llvm::StringRef name,
- mlir::Type type, mlir::StringAttr linkage,
+ mlir::Type type, fir::LinkageAttr linkage,
llvm::ArrayRef<mlir::NamedAttribute> attrs) {
build(builder, result, name, /*isConstant=*/false, /*isTarget=*/false, type,
{}, linkage, attrs);
@@ -2952,7 +2953,7 @@ void fir::GlobalOp::build(mlir::OpBuilder &builder,
mlir::OperationState &result, llvm::StringRef name,
bool isConstant, bool isTarget, mlir::Type type,
llvm::ArrayRef<mlir::NamedAttribute> attrs) {
- build(builder, result, name, isConstant, isTarget, type, mlir::StringAttr{},
+ build(builder, result, name, isConstant, isTarget, type, fir::LinkageAttr{},
attrs);
}
@@ -2965,10 +2966,8 @@ void fir::GlobalOp::build(mlir::OpBuilder &builder,
}
mlir::ParseResult fir::GlobalOp::verifyValidLinkage(llvm::StringRef linkage) {
- // Supporting only a subset of the LLVM linkage types for now
- static const char *validNames[] = {"common", "internal", "linkonce",
- "linkonce_odr", "weak"};
- return mlir::success(llvm::is_contained(validNames, linkage));
+ // Supporting only a subset of the LLVM linkage types for now.
+ return mlir::success(fir::symbolizeLinkageEnum(linkage).has_value());
}
//===----------------------------------------------------------------------===//
diff --git a/flang/lib/Optimizer/Transforms/CUDA/CUFAddConstructor.cpp b/flang/lib/Optimizer/Transforms/CUDA/CUFAddConstructor.cpp
index 5c70342d1e0fa..aa393f2d2d9a8 100644
--- a/flang/lib/Optimizer/Transforms/CUDA/CUFAddConstructor.cpp
+++ b/flang/lib/Optimizer/Transforms/CUDA/CUFAddConstructor.cpp
@@ -63,7 +63,7 @@ static fir::GlobalOp createManagedPointerGlobal(fir::FirOpBuilder &builder,
auto ptrGlobal = fir::GlobalOp::create(
builder, globalOp.getLoc(), ptrGlobalName, /*isConstant=*/false,
/*isTarget=*/false, ptrTy, initAttr,
- /*linkName=*/builder.createInternalLinkage(), attrs);
+ /*linkage=*/builder.createInternalLinkage(), attrs);
mlir::Region ®ion = ptrGlobal.getRegion();
mlir::Block *block = builder.createBlock(®ion);
diff --git a/flang/lib/Optimizer/Transforms/CUDA/CUFComputeSharedMemoryOffsetsAndSize.cpp b/flang/lib/Optimizer/Transforms/CUDA/CUFComputeSharedMemoryOffsetsAndSize.cpp
index bc6df0c9d60b7..dae873fbc0195 100644
--- a/flang/lib/Optimizer/Transforms/CUDA/CUFComputeSharedMemoryOffsetsAndSize.cpp
+++ b/flang/lib/Optimizer/Transforms/CUDA/CUFComputeSharedMemoryOffsetsAndSize.cpp
@@ -54,7 +54,7 @@ static void createSharedMemoryGlobal(fir::FirOpBuilder &builder,
mlir::OpBuilder::InsertionGuard guard(builder);
builder.setInsertionPointToEnd(gpuMod.getBody());
- mlir::StringAttr linkage = isDynamic ? builder.createExternalLinkage()
+ fir::LinkageAttr linkage = isDynamic ? builder.createExternalLinkage()
: builder.createInternalLinkage();
llvm::SmallVector<mlir::NamedAttribute> attrs;
auto globalOpName = mlir::OperationName(fir::GlobalOp::getOperationName(),
diff --git a/flang/lib/Optimizer/Transforms/CUDA/CUFDeviceGlobal.cpp b/flang/lib/Optimizer/Transforms/CUDA/CUFDeviceGlobal.cpp
index 5e24366c87ba4..a505126c56a93 100644
--- a/flang/lib/Optimizer/Transforms/CUDA/CUFDeviceGlobal.cpp
+++ b/flang/lib/Optimizer/Transforms/CUDA/CUFDeviceGlobal.cpp
@@ -252,7 +252,7 @@ class CUFDeviceGlobal : public fir::impl::CUFDeviceGlobalBase<CUFDeviceGlobal> {
// Under -gpu=mem:unified, plain host module-scope variables (no
// explicit CUF data attribute, not a constant) get a no-body
// declaration in the GPU module: clear the body, init value, and
- // linkName. With no linkName, the LLVM lowering uses the default
+ // linkage. With no linkage, the LLVM lowering uses the default
// External linkage (see convertLinkage in CodeGen.cpp), so an
// initializer-less global emits as `.extern .global ...` in PTX.
// The host-side definition stays. CUFAddConstructor will emit
@@ -263,15 +263,15 @@ class CUFDeviceGlobal : public fir::impl::CUFDeviceGlobalBase<CUFDeviceGlobal> {
!globalOp.getDataAttrAttr()) {
clonedGlobal.getRegion().getBlocks().clear();
clonedGlobal.removeInitValAttr();
- clonedGlobal.removeLinkNameAttr();
+ clonedGlobal.removeLinkageAttr();
}
// Registered CUDA globals with internal linkage must have a visible
// device symbol so runtime lookups (cudaGetSymbolAddress) can resolve
// them. Drop internal linkage from the GPU clone so it uses default
// external linkage.
if (cuf::isRegisteredDeviceGlobal(globalOp) &&
- globalOp.getLinkName() == "internal")
- clonedGlobal.removeLinkNameAttr();
+ globalOp.getLinkage() == fir::LinkageEnum::Internal)
+ clonedGlobal.removeLinkageAttr();
gpuSymTable.insert(cloned);
}
// Type-info globals for mutually recursive derived types form initializer
diff --git a/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp b/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
index 10a7ddf339133..776ef4b043ef1 100644
--- a/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
+++ b/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
@@ -191,9 +191,8 @@ TEST_F(FIRBuilderTest, createGlobal1) {
EXPECT_EQ("global1", global.getSymName());
EXPECT_TRUE(global.getConstant().has_value());
EXPECT_EQ(i64Type, global.getType());
- EXPECT_TRUE(global.getLinkName().has_value());
- EXPECT_EQ(
- builder.createInternalLinkage().getValue(), global.getLinkName().value());
+ EXPECT_TRUE(global.getLinkage().has_value());
+ EXPECT_EQ(fir::LinkageEnum::Internal, global.getLinkage().value());
EXPECT_FALSE(global.getInitVal().has_value());
auto g1 = builder.getNamedGlobal("global1");
@@ -219,9 +218,8 @@ TEST_F(FIRBuilderTest, createGlobal2) {
EXPECT_TRUE(mlir::isa<mlir::IntegerAttr>(global.getInitVal().value()));
EXPECT_EQ(16,
mlir::cast<mlir::IntegerAttr>(global.getInitVal().value()).getValue());
- EXPECT_TRUE(global.getLinkName().has_value());
- EXPECT_EQ(
- builder.createLinkOnceLinkage().getValue(), global.getLinkName().value());
+ EXPECT_TRUE(global.getLinkage().has_value());
+ EXPECT_EQ(fir::LinkageEnum::Linkonce, global.getLinkage().value());
}
TEST_F(FIRBuilderTest, uniqueCFIdent) {
@@ -310,8 +308,7 @@ TEST_F(FIRBuilderTest, createStringLiteral) {
auto addrOp = dyn_cast<fir::AddrOfOp>(addr.getDefiningOp());
auto symbol = addrOp.getSymbol().getRootReference().getValue();
auto global = builder.getNamedGlobal(symbol);
- EXPECT_EQ(
- builder.createLinkOnceLinkage().getValue(), global.getLinkName().value());
+ EXPECT_EQ(fir::LinkageEnum::Linkonce, global.getLinkage().value());
EXPECT_EQ(fir::CharacterType::get(builder.getContext(), 1, strValue.size()),
global.getType());
diff --git a/mlir/lib/Dialect/OpenACC/Transforms/ACCDeclareGPUModuleInsertion.cpp b/mlir/lib/Dialect/OpenACC/Transforms/ACCDeclareGPUModuleInsertion.cpp
index f8efb98fb6771..e5b93e053c87d 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/ACCDeclareGPUModuleInsertion.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/ACCDeclareGPUModuleInsertion.cpp
@@ -80,7 +80,7 @@ static bool hasAccDeclareGlobals(ModuleOp mod) {
static void makeDeviceGlobalDeclaration(Operation &globalOp) {
globalOp.setInherentAttr(StringAttr::get(globalOp.getContext(), "initVal"),
{});
- globalOp.setInherentAttr(StringAttr::get(globalOp.getContext(), "linkName"),
+ globalOp.setInherentAttr(StringAttr::get(globalOp.getContext(), "linkage"),
{});
for (Region ®ion : globalOp.getRegions()) {
region.dropAllReferences();
More information about the flang-commits
mailing list