[flang-commits] [flang] 832a342 - [flang] CDEFINED globals should have external linkage (#160167)
via flang-commits
flang-commits at lists.llvm.org
Thu Sep 25 07:26:50 PDT 2025
Author: Eugene Epshteyn
Date: 2025-09-25T10:26:45-04:00
New Revision: 832a342328cfb62f434d3d506a7bf30df5e2589d
URL: https://github.com/llvm/llvm-project/commit/832a342328cfb62f434d3d506a7bf30df5e2589d
DIFF: https://github.com/llvm/llvm-project/commit/832a342328cfb62f434d3d506a7bf30df5e2589d.diff
LOG: [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.
Added:
flang/test/Lower/cdefined.f90
Modified:
flang/lib/Lower/ConvertVariable.cpp
Removed:
################################################################################
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index da964c956dbd0..00ec1b51e5400 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -511,6 +511,9 @@ fir::GlobalOp Fortran::lower::defineGlobal(
Fortran::semantics::IsProcedurePointer(sym))
TODO(loc, "procedure pointer globals");
+ const auto *oeDetails =
+ sym.detailsIf<Fortran::semantics::ObjectEntityDetails>();
+
// If this is an array, check to see if we can use a dense attribute
// with a tensor mlir type. This optimization currently only supports
// Fortran arrays of integer, real, complex, or logical. The tensor
@@ -520,12 +523,10 @@ fir::GlobalOp Fortran::lower::defineGlobal(
mlir::Type eleTy = mlir::cast<fir::SequenceType>(symTy).getElementType();
if (mlir::isa<mlir::IntegerType, mlir::FloatType, mlir::ComplexType,
fir::LogicalType>(eleTy)) {
- const auto *details =
- sym.detailsIf<Fortran::semantics::ObjectEntityDetails>();
- if (details->init()) {
+ if (oeDetails && oeDetails->init()) {
global = Fortran::lower::tryCreatingDenseGlobal(
builder, loc, symTy, globalName, linkage, isConst,
- details->init().value(), dataAttr);
+ oeDetails->init().value(), dataAttr);
if (global) {
global.setVisibility(mlir::SymbolTable::Visibility::Public);
return global;
@@ -539,10 +540,8 @@ fir::GlobalOp Fortran::lower::defineGlobal(
isConst, var.isTarget(), dataAttr);
if (Fortran::semantics::IsAllocatableOrPointer(sym) &&
!Fortran::semantics::IsProcedure(sym)) {
- const auto *details =
- sym.detailsIf<Fortran::semantics::ObjectEntityDetails>();
- if (details && details->init()) {
- auto expr = *details->init();
+ if (oeDetails && oeDetails->init()) {
+ auto expr = *oeDetails->init();
createGlobalInitialization(builder, global, [&](fir::FirOpBuilder &b) {
mlir::Value box =
Fortran::lower::genInitialDataTarget(converter, loc, symTy, expr);
@@ -558,15 +557,14 @@ fir::GlobalOp Fortran::lower::defineGlobal(
fir::HasValueOp::create(b, loc, box);
});
}
- } else if (const auto *details =
- sym.detailsIf<Fortran::semantics::ObjectEntityDetails>()) {
- if (details->init()) {
+ } else if (oeDetails) {
+ if (oeDetails->init()) {
createGlobalInitialization(
builder, global, [&](fir::FirOpBuilder &builder) {
Fortran::lower::StatementContext stmtCtx(
/*cleanupProhibited=*/true);
fir::ExtendedValue initVal = genInitializerExprValue(
- converter, loc, details->init().value(), stmtCtx);
+ converter, loc, oeDetails->init().value(), stmtCtx);
mlir::Value castTo =
builder.createConvert(loc, symTy, fir::getBase(initVal));
fir::HasValueOp::create(builder, loc, castTo);
@@ -615,28 +613,32 @@ fir::GlobalOp Fortran::lower::defineGlobal(
TODO(loc, "global"); // Something else
}
// Creates zero initializer for globals without initializers, this is a common
- // and expected behavior (although not required by the standard)
+ // and expected behavior (although not required by the standard).
+ // Exception: CDEFINED globals are treated as "extern" in C and don't need
+ // initializer.
if (!globalIsInitialized(global)) {
- // Fortran does not provide means to specify that a BIND(C) module
- // uninitialized variables will be defined in C.
- // Add the common linkage to those to allow some level of support
- // for this use case. Note that this use case will not work if the Fortran
- // module code is placed in a shared library since, at least for the ELF
- // format, common symbols are assigned a section in shared libraries.
- // The best is still to declare C defined variables in a Fortran module file
- // 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());
- createGlobalInitialization(
- builder, global, [&](fir::FirOpBuilder &builder) {
- mlir::Value initValue;
- if (converter.getLoweringOptions().getInitGlobalZero())
- initValue = fir::ZeroOp::create(builder, loc, symTy);
- else
- initValue = fir::UndefOp::create(builder, loc, symTy);
- fir::HasValueOp::create(builder, loc, initValue);
- });
+ if (!oeDetails || !oeDetails->isCDefined()) {
+ // Fortran does not provide means to specify that a BIND(C) module
+ // uninitialized variables will be defined in C.
+ // Add the common linkage to those to allow some level of support
+ // for this use case. Note that this use case will not work if the Fortran
+ // module code is placed in a shared library since, at least for the ELF
+ // format, common symbols are assigned a section in shared libraries. The
+ // best is still to declare C defined variables in a Fortran module file
+ // 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());
+ createGlobalInitialization(
+ builder, global, [&](fir::FirOpBuilder &builder) {
+ mlir::Value initValue;
+ if (converter.getLoweringOptions().getInitGlobalZero())
+ initValue = fir::ZeroOp::create(builder, loc, symTy);
+ else
+ initValue = fir::UndefOp::create(builder, loc, symTy);
+ fir::HasValueOp::create(builder, loc, initValue);
+ });
+ }
}
// Set public visibility to prevent global definition to be optimized out
// even if they have no initializer and are unused in this compilation unit.
diff --git a/flang/test/Lower/cdefined.f90 b/flang/test/Lower/cdefined.f90
new file mode 100644
index 0000000000000..89599442589eb
--- /dev/null
+++ b/flang/test/Lower/cdefined.f90
@@ -0,0 +1,9 @@
+! RUN: bbc -emit-hlfir -o - %s | FileCheck %s
+! Ensure that CDEFINED variable has external (default) linkage and that
+! it doesn't have an initializer
+module m
+ use iso_c_binding
+ integer(c_int), bind(C, name='c_global', CDEFINED) :: c = 42
+ ! CHECK: fir.global @c_global : i32
+ ! CHECK-NOT: fir.zero_bits
+end
More information about the flang-commits
mailing list