Skip to content

Commit a96b467

Browse files
authored
[flang] Lower BIND(C) module variables (#78279)
Lower initialized BIND(C) module variable as regular module variable, except that the fir.global symbol name is the binding label. For uninitialized variables, add the common linkage so that C code may define the variables. The standard does not provide a way to indicate that a variable is defined in C, but there are use cases. Beware that if the module file compiled object is added to a shared library, the variable will become a regular global definition and may override the C variable depending on the linking order.
1 parent 90bdf76 commit a96b467

File tree

2 files changed

+39
-7
lines changed

2 files changed

+39
-7
lines changed

flang/lib/Lower/ConvertVariable.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -595,14 +595,17 @@ static fir::GlobalOp defineGlobal(Fortran::lower::AbstractConverter &converter,
595595
// Creates zero initializer for globals without initializers, this is a common
596596
// and expected behavior (although not required by the standard)
597597
if (!globalIsInitialized(global)) {
598-
// TODO: For BIND(C) variables, an initial value may be given in another
599-
// compilation unit (on the C side), and setting an zero init here creates
600-
// linkage conflicts. See if there is a way to get it zero initialized if
601-
// not initialized elsewhere. MLIR also used to drop globals without
602-
// initializers that are not used in the file, but this may not be true
603-
// anymore.
598+
// Fortran does not provide means to specify that a BIND(C) module
599+
// uninitialized variables will be defined in C.
600+
// Add the common linkage to those to allow some level of support
601+
// for this use case. Note that this use case will not work if the Fortran
602+
// module code is placed in a shared library since, at least for the ELF
603+
// format, common symbols are assigned a section in shared libraries.
604+
// The best is still to declare C defined variables in a Fortran module file
605+
// with no other definitions, and to never link the resulting module object
606+
// file.
604607
if (sym.attrs().test(Fortran::semantics::Attr::BIND_C))
605-
TODO(loc, "BIND(C) module variable linkage");
608+
global.setLinkName(builder.createCommonLinkage());
606609
Fortran::lower::createGlobalInitialization(
607610
builder, global, [&](fir::FirOpBuilder &builder) {
608611
mlir::Value initValue = builder.create<fir::ZeroOp>(loc, symTy);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
! Test BIND(C) module variable lowering
2+
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s
3+
4+
module some_c_module
5+
integer, bind(c, name="i_var") :: i = 1
6+
integer, bind(c, name="i_var_no_init") :: i_no_init
7+
integer, bind(c) :: j_var = 2
8+
integer, bind(c) :: j_var_no_init
9+
end module
10+
11+
! CHECK-LABEL: fir.global @i_var : i32 {
12+
! CHECK: %[[VAL_0:.*]] = arith.constant 1 : i32
13+
! CHECK: fir.has_value %[[VAL_0]] : i32
14+
! CHECK: }
15+
16+
! CHECK-LABEL: fir.global common @i_var_no_init : i32 {
17+
! CHECK: %[[VAL_0:.*]] = fir.zero_bits i32
18+
! CHECK: fir.has_value %[[VAL_0]] : i32
19+
! CHECK: }
20+
21+
! CHECK-LABEL: fir.global @j_var : i32 {
22+
! CHECK: %[[VAL_0:.*]] = arith.constant 2 : i32
23+
! CHECK: fir.has_value %[[VAL_0]] : i32
24+
! CHECK: }
25+
26+
! CHECK-LABEL: fir.global common @j_var_no_init : i32 {
27+
! CHECK: %[[VAL_0:.*]] = fir.zero_bits i32
28+
! CHECK: fir.has_value %[[VAL_0]] : i32
29+
! CHECK: }

0 commit comments

Comments
 (0)