This is an archive of the discontinued LLVM Phabricator instance.

[flang] Support lowering of intrinsic module procedure C_F_POINTER
ClosedPublic

Authored by peixin on Aug 20 2022, 8:56 AM.

Details

Summary

As Fortran 2018 18.2.3.3, the intrinsic module procedure
C_F_POINTER(CPTR, FPTR [, SHAPE]) associates a data pointer with the
target of a C pointer and specify its shape. CPTR shall be a scalar of
type C_PTR, and its value is the C address or the result of a reference
to C_LOC. FPTR is one pointer, either scalar or array. SHAPE is a
rank-one integer array, and it shall be present if and only if FPTR is
an array.

C_PTR is the derived type with only one component of integer 64, and the
integer 64 component value is the address. Build the right "source"
fir::ExtendedValue based on the address and shape, and use
associateMutableBox to associate the pointer with the target of the C
pointer.

Refactor the getting the address of C_PTR to reuse the code.

Diff Detail

Event Timeline

peixin created this revision.Aug 20 2022, 8:56 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 20 2022, 8:56 AM
peixin requested review of this revision.Aug 20 2022, 8:56 AM

Evaluated the end-to-end execution result using the following example.

$ cat main.f90 
program main
  use iso_c_binding
  real, pointer :: cptr, cptr2(:,:)
  real, pointer :: fptr, fptr2(:,:)
  integer :: x = 3, y = 4
  type(c_ptr) :: foo

  allocate(cptr)
  allocate(cptr2(x, y))

  cptr = 1
  cptr2 = 2

  call c_f_pointer(c_loc(cptr), fptr)
  call c_f_pointer(c_loc(cptr2), fptr2, [x, y])

  print *, "loc(FPTR) = ", c_loc(fptr)
  print *, "loc(CPTR) = ", c_loc(cptr)
  print *, "FPTR = ", fptr
  print *, "shape(FPTR2) = ", shape(fptr2)
  print *, "loc(FPTR2) = ", c_loc(fptr2)
  print *, "loc(CPTR2) = ", c_loc(cptr2)
  print *, "FPTR2 = ", fptr2
end
$ flang-new -flang-experimental-exec main.f90 && ./a.out
 loc(FPTR) =  25268896
 loc(CPTR) =  25268896
 FPTR =  1.
 shape(FPTR2) =  3 4
 loc(FPTR2) =  25268928
 loc(CPTR2) =  25268928
 FPTR2 =  2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2. 2.
jeanPerier requested changes to this revision.Aug 31 2022, 5:22 AM

The way you deal with the CPTR arguments looks good to me, but I think the manual pointer association does not handle all the cases properly and you should favor using fir::factory::associateMutableBox.

flang/lib/Lower/IntrinsicCall.cpp
733

asInquired would be a better choice, you would get a fir::MutableBox that represent all the Pointer cases correctly.

2502

It should not be assumed that Fortran pointers are fir.ref<fir.ptr>, it is wrong if they are not local variables. All the pointer manipulations should go through the fir::MutableBoxValue abstraction.

I think all the code below should be using associateMutableBox defined here: https://github.com/llvm/llvm-project/blob/73026a4fbf7095613df4f8c205912cfc1485ed7d/flang/include/flang/Optimizer/Builder/MutableBox.h#L56.

All the work here should be to build the right "source" fir::ExtendedValue based on cPtrAddrVal and shape.
You will also to handle the character case (and add a TODO for derived type with length parameters). The standard tells the length parameters of FPTR cannot be deferred, so you will have to get the length to build the fir::CharBoxValue/fir::CharArrayBoxValue from there.

flang/test/Lower/Intrinsics/c_f_pointer.f90
24

The lowering code will most likely not work with:

subroutine test_scalar(cptr, fptr)
  use iso_c_binding
  real, pointer :: fptr
  type(c_ptr) :: cptr

  call c_f_pointer(cptr, fptr)
end
55

With everything dealing with pointer association it is worth adding tests with characters. Both with:

subroutine test_array_character(fptr, ...)
  character(10), pointer :: fptr(:,:)
...
end subroutine

and

subroutine test_array_character(fptr, n, ...)
  character(n), pointer :: fptr(:,:)
...
end subroutine
This revision now requires changes to proceed.Aug 31 2022, 5:22 AM
peixin updated this revision to Diff 457545.Sep 2 2022, 3:02 AM
peixin edited the summary of this revision. (Show Details)

Reimplement this according to @jeanPerier 's suggestions.

Refactor the getting the address of C_PTR to reuse the code of several previous patches.

jeanPerier accepted this revision.Sep 5 2022, 2:34 AM

Thanks a lot @peixin, I only added a small nit to move genCPtrOrCFunptrAddr into an another header/implementation file. Otherwise looks great !

flang/include/flang/Lower/ConvertExpr.h
239 ↗(On Diff #457545)

Can you move this helper into the Optimizer/Builder/FIRBuilder.h header into the factory namespace ? That is where all helpers generating code from MLIR data structures live. ConvertExpr.h is mainly intended to define utilities that takes an evaluate::XXX data structure and generate FIR for it.

This revision is now accepted and ready to land.Sep 5 2022, 2:34 AM
peixin updated this revision to Diff 457988.Sep 5 2022, 7:16 AM

Thanks @jeanPerier for the info. Move it into the Optimizer/Builder/FIRBuilder as suggested.