Skip to content

Commit

Permalink
[flang] Lower BIND(C) module variables
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jeanPerier committed Jan 16, 2024
1 parent 510626f commit 6cafba5
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 7 deletions.
17 changes: 10 additions & 7 deletions flang/lib/Lower/ConvertVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -595,14 +595,17 @@ static fir::GlobalOp defineGlobal(Fortran::lower::AbstractConverter &converter,
// Creates zero initializer for globals without initializers, this is a common
// and expected behavior (although not required by the standard)
if (!globalIsInitialized(global)) {
// TODO: For BIND(C) variables, an initial value may be given in another
// compilation unit (on the C side), and setting an zero init here creates
// linkage conflicts. See if there is a way to get it zero initialized if
// not initialized elsewhere. MLIR also used to drop globals without
// initializers that are not used in the file, but this may not be true
// anymore.
// 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))
TODO(loc, "BIND(C) module variable linkage");
global.setLinkName(builder.createCommonLinkage());
Fortran::lower::createGlobalInitialization(
builder, global, [&](fir::FirOpBuilder &builder) {
mlir::Value initValue = builder.create<fir::ZeroOp>(loc, symTy);
Expand Down
29 changes: 29 additions & 0 deletions flang/test/Lower/HLFIR/bindc-module-var.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
! Test BIND(C) module variable lowering
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s

module some_c_module
integer, bind(c, name="i_var") :: i = 1
integer, bind(c, name="i_var_no_init") :: i_no_init
integer, bind(c) :: j_var = 2
integer, bind(c) :: j_var_no_init
end module

! CHECK-LABEL: fir.global @i_var : i32 {
! CHECK: %[[VAL_0:.*]] = arith.constant 1 : i32
! CHECK: fir.has_value %[[VAL_0]] : i32
! CHECK: }

! CHECK-LABEL: fir.global common @i_var_no_init : i32 {
! CHECK: %[[VAL_0:.*]] = fir.zero_bits i32
! CHECK: fir.has_value %[[VAL_0]] : i32
! CHECK: }

! CHECK-LABEL: fir.global @j_var : i32 {
! CHECK: %[[VAL_0:.*]] = arith.constant 2 : i32
! CHECK: fir.has_value %[[VAL_0]] : i32
! CHECK: }

! CHECK-LABEL: fir.global common @j_var_no_init : i32 {
! CHECK: %[[VAL_0:.*]] = fir.zero_bits i32
! CHECK: fir.has_value %[[VAL_0]] : i32
! CHECK: }

0 comments on commit 6cafba5

Please sign in to comment.