Skip to content

Commit 832a342

Browse files
[flang] CDEFINED globals should have external linkage (#160167)
In Fortran::lower::defineGlobal() don't change the linkage and don't generate initializer for CDEFINED globals.
1 parent 2657c79 commit 832a342

File tree

2 files changed

+44
-33
lines changed

2 files changed

+44
-33
lines changed

flang/lib/Lower/ConvertVariable.cpp

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,9 @@ fir::GlobalOp Fortran::lower::defineGlobal(
511511
Fortran::semantics::IsProcedurePointer(sym))
512512
TODO(loc, "procedure pointer globals");
513513

514+
const auto *oeDetails =
515+
sym.detailsIf<Fortran::semantics::ObjectEntityDetails>();
516+
514517
// If this is an array, check to see if we can use a dense attribute
515518
// with a tensor mlir type. This optimization currently only supports
516519
// Fortran arrays of integer, real, complex, or logical. The tensor
@@ -520,12 +523,10 @@ fir::GlobalOp Fortran::lower::defineGlobal(
520523
mlir::Type eleTy = mlir::cast<fir::SequenceType>(symTy).getElementType();
521524
if (mlir::isa<mlir::IntegerType, mlir::FloatType, mlir::ComplexType,
522525
fir::LogicalType>(eleTy)) {
523-
const auto *details =
524-
sym.detailsIf<Fortran::semantics::ObjectEntityDetails>();
525-
if (details->init()) {
526+
if (oeDetails && oeDetails->init()) {
526527
global = Fortran::lower::tryCreatingDenseGlobal(
527528
builder, loc, symTy, globalName, linkage, isConst,
528-
details->init().value(), dataAttr);
529+
oeDetails->init().value(), dataAttr);
529530
if (global) {
530531
global.setVisibility(mlir::SymbolTable::Visibility::Public);
531532
return global;
@@ -539,10 +540,8 @@ fir::GlobalOp Fortran::lower::defineGlobal(
539540
isConst, var.isTarget(), dataAttr);
540541
if (Fortran::semantics::IsAllocatableOrPointer(sym) &&
541542
!Fortran::semantics::IsProcedure(sym)) {
542-
const auto *details =
543-
sym.detailsIf<Fortran::semantics::ObjectEntityDetails>();
544-
if (details && details->init()) {
545-
auto expr = *details->init();
543+
if (oeDetails && oeDetails->init()) {
544+
auto expr = *oeDetails->init();
546545
createGlobalInitialization(builder, global, [&](fir::FirOpBuilder &b) {
547546
mlir::Value box =
548547
Fortran::lower::genInitialDataTarget(converter, loc, symTy, expr);
@@ -558,15 +557,14 @@ fir::GlobalOp Fortran::lower::defineGlobal(
558557
fir::HasValueOp::create(b, loc, box);
559558
});
560559
}
561-
} else if (const auto *details =
562-
sym.detailsIf<Fortran::semantics::ObjectEntityDetails>()) {
563-
if (details->init()) {
560+
} else if (oeDetails) {
561+
if (oeDetails->init()) {
564562
createGlobalInitialization(
565563
builder, global, [&](fir::FirOpBuilder &builder) {
566564
Fortran::lower::StatementContext stmtCtx(
567565
/*cleanupProhibited=*/true);
568566
fir::ExtendedValue initVal = genInitializerExprValue(
569-
converter, loc, details->init().value(), stmtCtx);
567+
converter, loc, oeDetails->init().value(), stmtCtx);
570568
mlir::Value castTo =
571569
builder.createConvert(loc, symTy, fir::getBase(initVal));
572570
fir::HasValueOp::create(builder, loc, castTo);
@@ -615,28 +613,32 @@ fir::GlobalOp Fortran::lower::defineGlobal(
615613
TODO(loc, "global"); // Something else
616614
}
617615
// Creates zero initializer for globals without initializers, this is a common
618-
// and expected behavior (although not required by the standard)
616+
// and expected behavior (although not required by the standard).
617+
// Exception: CDEFINED globals are treated as "extern" in C and don't need
618+
// initializer.
619619
if (!globalIsInitialized(global)) {
620-
// Fortran does not provide means to specify that a BIND(C) module
621-
// uninitialized variables will be defined in C.
622-
// Add the common linkage to those to allow some level of support
623-
// for this use case. Note that this use case will not work if the Fortran
624-
// module code is placed in a shared library since, at least for the ELF
625-
// format, common symbols are assigned a section in shared libraries.
626-
// The best is still to declare C defined variables in a Fortran module file
627-
// with no other definitions, and to never link the resulting module object
628-
// file.
629-
if (sym.attrs().test(Fortran::semantics::Attr::BIND_C))
630-
global.setLinkName(builder.createCommonLinkage());
631-
createGlobalInitialization(
632-
builder, global, [&](fir::FirOpBuilder &builder) {
633-
mlir::Value initValue;
634-
if (converter.getLoweringOptions().getInitGlobalZero())
635-
initValue = fir::ZeroOp::create(builder, loc, symTy);
636-
else
637-
initValue = fir::UndefOp::create(builder, loc, symTy);
638-
fir::HasValueOp::create(builder, loc, initValue);
639-
});
620+
if (!oeDetails || !oeDetails->isCDefined()) {
621+
// Fortran does not provide means to specify that a BIND(C) module
622+
// uninitialized variables will be defined in C.
623+
// Add the common linkage to those to allow some level of support
624+
// for this use case. Note that this use case will not work if the Fortran
625+
// module code is placed in a shared library since, at least for the ELF
626+
// format, common symbols are assigned a section in shared libraries. The
627+
// best is still to declare C defined variables in a Fortran module file
628+
// with no other definitions, and to never link the resulting module
629+
// object file.
630+
if (sym.attrs().test(Fortran::semantics::Attr::BIND_C))
631+
global.setLinkName(builder.createCommonLinkage());
632+
createGlobalInitialization(
633+
builder, global, [&](fir::FirOpBuilder &builder) {
634+
mlir::Value initValue;
635+
if (converter.getLoweringOptions().getInitGlobalZero())
636+
initValue = fir::ZeroOp::create(builder, loc, symTy);
637+
else
638+
initValue = fir::UndefOp::create(builder, loc, symTy);
639+
fir::HasValueOp::create(builder, loc, initValue);
640+
});
641+
}
640642
}
641643
// Set public visibility to prevent global definition to be optimized out
642644
// even if they have no initializer and are unused in this compilation unit.

flang/test/Lower/cdefined.f90

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s
2+
! Ensure that CDEFINED variable has external (default) linkage and that
3+
! it doesn't have an initializer
4+
module m
5+
use iso_c_binding
6+
integer(c_int), bind(C, name='c_global', CDEFINED) :: c = 42
7+
! CHECK: fir.global @c_global : i32
8+
! CHECK-NOT: fir.zero_bits
9+
end

0 commit comments

Comments
 (0)