auto stringLitOp = builder.createStringLitOp(loc, str);
builder.create<fir::HasValueOp>(loc, stringLitOp);
},
- builder.createInternalLinkage());
- // TODO: This can be changed to linkonce linkage once we have support for
- // generating comdat sections
+ builder.createLinkOnceLinkage());
auto addr = builder.create<fir::AddrOfOp>(loc, global.resultType(),
global.getSymbol());
auto len = builder.createIntegerConstant(
auto g = rewriter.create<mlir::LLVM::GlobalOp>(
loc, tyAttr, isConst, linkage, global.getSymName(), initAttr);
+ auto module = global->getParentOfType<mlir::ModuleOp>();
+ // Add comdat if necessary
+ if (fir::getTargetTriple(module).supportsCOMDAT() &&
+ (linkage == mlir::LLVM::Linkage::Linkonce ||
+ linkage == mlir::LLVM::Linkage::LinkonceODR)) {
+ addComdat(g, rewriter, module);
+ }
+
// Apply all non-Fir::GlobalOp attributes to the LLVM::GlobalOp, preserving
// them; whilst taking care not to apply attributes that are lowered in
// other ways.
}
return mlir::LLVM::Linkage::External;
}
+
+private:
+ static void addComdat(mlir::LLVM::GlobalOp &global,
+ mlir::ConversionPatternRewriter &rewriter,
+ mlir::ModuleOp &module) {
+ const char *comdatName = "__llvm_comdat";
+ mlir::LLVM::ComdatOp comdatOp =
+ module.lookupSymbol<mlir::LLVM::ComdatOp>(comdatName);
+ if (!comdatOp) {
+ comdatOp =
+ rewriter.create<mlir::LLVM::ComdatOp>(module.getLoc(), comdatName);
+ }
+ mlir::OpBuilder::InsertionGuard guard(rewriter);
+ rewriter.setInsertionPointToEnd(&comdatOp.getBody().back());
+ auto selectorOp = rewriter.create<mlir::LLVM::ComdatSelectorOp>(
+ comdatOp.getLoc(), global.getSymName(),
+ mlir::LLVM::comdat::Comdat::Any);
+ global.setComdatAttr(mlir::SymbolRefAttr::get(
+ rewriter.getContext(), comdatName,
+ mlir::FlatSymbolRefAttr::get(selectorOp.getSymNameAttr())));
+ }
};
/// `fir.load` --> `llvm.load`
-// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s | FileCheck %s
-// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=aarch64-unknown-linux-gnu" %s | FileCheck %s
-// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=i386-unknown-linux-gnu" %s | FileCheck %s
-// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=powerpc64le-unknown-linux-gn" %s | FileCheck %s
+// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT
+// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=aarch64-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT
+// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=i386-unknown-linux-gnu" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT
+// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=powerpc64le-unknown-linux-gn" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT
+// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=x86_64-pc-win32" %s | FileCheck %s --check-prefixes=CHECK,CHECK-COMDAT
+// RUN: fir-opt --split-input-file --fir-to-llvm-ir="target=aarch64-apple-darwin" %s | FileCheck %s --check-prefixes=CHECK,CHECK-NO-COMDAT
//=============================================================================
// SUMMARY: Tests for FIR --> LLVM MLIR conversion independent of the target
// -----
fir.global linkonce @w_i86 (86:i32) : i32
-// CHECK: llvm.mlir.global linkonce @w_i86(86 : i32) {addr_space = 0 : i32} : i32
+// CHECK-COMDAT: llvm.mlir.global linkonce @w_i86(86 : i32) comdat(@__llvm_comdat::@w_i86) {addr_space = 0 : i32} : i32
+// CHECK-NO-COMDAT: llvm.mlir.global linkonce @w_i86(86 : i32) {addr_space = 0 : i32} : i32
// -----
return
}
-// CHECK: llvm.mlir.global linkonce constant @_QMtest_dinitE.dt.tseq() {addr_space = 0 : i32} : i8
+// CHECK-COMDAT: llvm.mlir.global linkonce constant @_QMtest_dinitE.dt.tseq() comdat(@__llvm_comdat::@_QMtest_dinitE.dt.tseq) {addr_space = 0 : i32} : i8
+// CHECK-NO-COMDAT: llvm.mlir.global linkonce constant @_QMtest_dinitE.dt.tseq() {addr_space = 0 : i32} : i8
// CHECK-LABEL: llvm.func @embox1
// CHECK: %[[TYPE_CODE:.*]] = llvm.mlir.constant(42 : i32) : i32
// CHECK: %[[TYPE_CODE_I8:.*]] = llvm.trunc %[[TYPE_CODE]] : i32 to i8
// CHECK: llvm.func @_FortranAioOutputDescriptor(!llvm.ptr<i8>, !llvm.ptr<struct<(ptr<struct<()>>, i64, i32, i8, i8, i8, i8, ptr<i8>, array<1 x i64>)>>) -> i1 attributes {fir.io, fir.runtime, sym_visibility = "private"}
// CHECK: llvm.func @_FortranAioEndIoStatement(!llvm.ptr<i8>) -> i32 attributes {fir.io, fir.runtime, sym_visibility = "private"}
-// CHECK-LABEL: llvm.mlir.global linkonce constant @_QQcl.2E2F64756D6D792E66393000() {addr_space = 0 : i32} : !llvm.array<12 x i8> {
+// CHECK-LABEL: llvm.mlir.global linkonce constant @_QQcl.2E2F64756D6D792E66393000() comdat(@__llvm_comdat::@_QQcl.2E2F64756D6D792E66393000) {addr_space = 0 : i32} : !llvm.array<12 x i8> {
// CHECK: %[[VAL_0:.*]] = llvm.mlir.constant("./dummy.f90\00") : !llvm.array<12 x i8>
// CHECK: llvm.return %[[VAL_0]] : !llvm.array<12 x i8>
// CHECK: }
! CHECK: }
end subroutine
-! CHECK: fir.global internal @[[error_message]] constant : !fir.char<1,76> {
+! CHECK: fir.global linkonce @[[error_message]] constant : !fir.char<1,76> {
! CHECK: %[[msg:.*]] = fir.string_lit "array left hand side must be allocated when the right hand side is a scalar\00"(76) : !fir.char<1,76>
! CHECK: fir.has_value %[[msg:.*]] : !fir.char<1,76>
! CHECK: }
! CHECK: return
end subroutine
-! CHECK-LABEL: fir.global internal @_QQcl.48656C6C6F20576F726C64
+! CHECK-LABEL: fir.global linkonce @_QQcl.48656C6C6F20576F726C64
! CHECK: %[[lit:.*]] = fir.string_lit "Hello World"(11) : !fir.char<1,11>
! CHECK: fir.has_value %[[lit]] : !fir.char<1,11>
! CHECK: }
! ALL: %[[VAL_8:.*]] = fir.insert_value %[[VAL_4]], %[[VAL_7]], [0 : index, 1 : index] : (!fir.array<1xtuple<!fir.ref<i8>, !fir.ref<i8>>>, !fir.ref<i8>) -> !fir.array<1xtuple<!fir.ref<i8>, !fir.ref<i8>>>
! ALL: fir.has_value %[[VAL_8]] : !fir.array<1xtuple<!fir.ref<i8>, !fir.ref<i8>>>
-! ALL: fir.global internal @[[FC_STR]] constant : !fir.char<1,13> {
+! ALL: fir.global linkonce @[[FC_STR]] constant : !fir.char<1,13> {
! ALL: %[[VAL_0:.*]] = fir.string_lit "FORT_CONVERT\00"(13) : !fir.char<1,13>
! ALL: fir.has_value %[[VAL_0]] : !fir.char<1,13>
-! ALL: fir.global internal @[[OPT_STR]] constant : !fir.char<1,[[OPT_STR_LEN]]> {
+! ALL: fir.global linkonce @[[OPT_STR]] constant : !fir.char<1,[[OPT_STR_LEN]]> {
! UNKNOWN: %[[VAL_0:.*]] = fir.string_lit "UNKNOWN\00"([[OPT_STR_LEN]]) : !fir.char<1,[[OPT_STR_LEN]]>
! NATIVE: %[[VAL_0:.*]] = fir.string_lit "NATIVE\00"([[OPT_STR_LEN]]) : !fir.char<1,[[OPT_STR_LEN]]>
! LITTLE_ENDIAN: %[[VAL_0:.*]] = fir.string_lit "LITTLE_ENDIAN\00"([[OPT_STR_LEN]]) : !fir.char<1,[[OPT_STR_LEN]]>
! CHECK: fir.address_of(@{{.*}}) :
1008 format('ok')
end
-! CHECK-LABEL: fir.global internal @_QQcl.28276F6B2729 constant
+! CHECK-LABEL: fir.global linkonce @_QQcl.28276F6B2729 constant
! CHECK: %[[lit:.*]] = fir.string_lit "('ok')"(6) : !fir.char<1,6>
! CHECK: fir.has_value %[[lit]] : !fir.char<1,6>
! CHECK: }
close(unit)
end subroutine
-! CHECK: fir.global internal @[[be_str_name]] constant : !fir.char<1,10> {
+! CHECK: fir.global linkonce @[[be_str_name]] constant : !fir.char<1,10> {
! CHECK: %[[be_str_lit:.*]] = fir.string_lit "BIG_ENDIAN"(10) : !fir.char<1,10>
! CHECK: fir.has_value %[[be_str_lit]] : !fir.char<1,10>
write(10, nml=mygroup)
end
- ! CHECK-DAG: fir.global internal @_QQcl.6A6A6A00 constant : !fir.char<1,4>
- ! CHECK-DAG: fir.global internal @_QQcl.63636300 constant : !fir.char<1,4>
- ! CHECK-DAG: fir.global internal @_QQcl.6E6E6E00 constant : !fir.char<1,4>
+ ! CHECK-DAG: fir.global linkonce @_QQcl.6A6A6A00 constant : !fir.char<1,4>
+ ! CHECK-DAG: fir.global linkonce @_QQcl.63636300 constant : !fir.char<1,4>
+ ! CHECK-DAG: fir.global linkonce @_QQcl.6E6E6E00 constant : !fir.char<1,4>
write (buffer, 10) "compiler"
read (buffer, 10) greeting
end
-! CHECK-LABEL: fir.global internal @_QQcl.636F6D70696C6572
+! CHECK-LABEL: fir.global linkonce @_QQcl.636F6D70696C6572
! CHECK: %[[lit:.*]] = fir.string_lit "compiler"(8) : !fir.char<1,8>
! CHECK: fir.has_value %[[lit]] : !fir.char<1,8>
! CHECK: }
auto symbol = addrOp.getSymbol().getRootReference().getValue();
auto global = builder.getNamedGlobal(symbol);
EXPECT_EQ(
- builder.createInternalLinkage().getValue(), global.getLinkName().value());
+ builder.createLinkOnceLinkage().getValue(), global.getLinkName().value());
EXPECT_EQ(fir::CharacterType::get(builder.getContext(), 1, strValue.size()),
global.getType());