diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -44,6 +44,7 @@ #include "mlir/Target/LLVMIR/ModuleTranslation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/TypeSwitch.h" +#include #include namespace fir { @@ -2931,6 +2932,26 @@ auto isConst = global.getConstant().has_value(); auto g = rewriter.create( loc, tyAttr, isConst, linkage, global.getSymName(), initAttr); + // Apply all non-LLVM::GlobalOp attributes to the GlobalOp, preserving them; + // whilst taking care not to apply duplicates or attributes that are lowered + // in other ways. + auto isExcludedAttr = [](mlir::StringAttr attrName, fir::GlobalOp gOp) { + if (attrName == gOp.getTargetAttrName() || + attrName == gOp.getSymNameAttr() || + attrName == gOp.getSymrefAttrName() || + attrName == gOp.getConstantAttrName() || + attrName == gOp.getLinkNameAttrName() || + attrName == gOp.getTypeAttrName() || + attrName == gOp.getInitValAttrName()) + return true; + return false; + }; + + for (auto attr : global->getAttrs()) + if (!g->getAttrDictionary().contains(attr.getName()) && + !isExcludedAttr(attr.getName(), global)) + g->setAttr(attr.getName(), attr.getValue()); + auto &gr = g.getInitializerRegion(); rewriter.inlineRegionBefore(global.getRegion(), gr, gr.end()); if (!gr.empty()) { diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp --- a/flang/lib/Optimizer/Dialect/FIROps.cpp +++ b/flang/lib/Optimizer/Dialect/FIROps.cpp @@ -1308,6 +1308,9 @@ simpleInitializer = true; } + if (parser.parseOptionalAttrDict(result.attributes)) + return mlir::failure(); + if (succeeded(parser.parseOptionalKeyword("constant"))) { // if "constant" keyword then mark this as a constant, not a variable result.addAttribute("constant", builder.getUnitAttr()); @@ -1342,6 +1345,11 @@ p.printAttributeWithoutType(getSymrefAttr()); if (auto val = getValueOrNull()) p << '(' << val << ')'; + p.printOptionalAttrDict((*this)->getAttrs(), + {getTargetAttrName(), getSymbolAttrName(), + getConstantAttrName(), getSymrefAttrName(), + getLinkNameAttrName(), getTypeAttrName(), + getSymNameAttrName(), getInitValAttrName()}); if (getOperation()->getAttr(fir::GlobalOp::getConstantAttrNameStr())) p << " constant"; if (getOperation()->getAttr(getTargetAttrName())) diff --git a/flang/test/Fir/global-attributes.fir b/flang/test/Fir/global-attributes.fir new file mode 100644 --- /dev/null +++ b/flang/test/Fir/global-attributes.fir @@ -0,0 +1,17 @@ +// RUN: fir-opt --fir-to-llvm-ir %s | FileCheck %s +// RUN: tco --fir-to-llvm-ir %s | FileCheck %s +// RUN: fir-opt %s | FileCheck %s --check-prefix=READ-OUT +// RUN: tco --emit-fir %s | FileCheck %s --check-prefix=READ-OUT + +// CHECK: llvm.mlir.global external @_QMtest_0Edata_int() {{{.*}}test = "string_attribute_maintained"{{.*}}} : i32 { +// CHECK: [[CST0:%.*]] = llvm.mlir.constant(10 : i32) : i32 +// CHECK: llvm.return [[CST0]] : i32 +// CHECK: } +// READ-OUT: fir.global @_QMtest_0Edata_int {test = "string_attribute_maintained"} : i32 { +// READ-OUT: %c10_i32 = arith.constant 10 : i32 +// READ-OUT: fir.has_value %c10_i32 : i32 +// READ-OUT: } +fir.global @_QMtest_0Edata_int {test = "string_attribute_maintained"} : i32 { + %c10_i32 = arith.constant 10 : i32 + fir.has_value %c10_i32 : i32 +} \ No newline at end of file