[flang-commits] [flang] e657acd - [flang] Handle NULL(mold) used in initializer region

Valentin Clement via flang-commits flang-commits at lists.llvm.org
Sat Sep 24 06:23:20 PDT 2022


Author: Valentin Clement
Date: 2022-09-24T15:23:08+02:00
New Revision: e657acd449a8b765db8bb333e3e969c9f787b640

URL: https://github.com/llvm/llvm-project/commit/e657acd449a8b765db8bb333e3e969c9f787b640
DIFF: https://github.com/llvm/llvm-project/commit/e657acd449a8b765db8bb333e3e969c9f787b640.diff

LOG: [flang] Handle NULL(mold) used in initializer region

NULL intrinsic with a MOLD argument can be used in a type constructor.
This patch handles this use case with a specific lowering that create
an unallocated box with the MOLD type.

Reviewed By: PeteSteinfeld

Differential Revision: https://reviews.llvm.org/D134554

Added: 
    

Modified: 
    flang/include/flang/Evaluate/tools.h
    flang/lib/Evaluate/tools.cpp
    flang/lib/Lower/ConvertVariable.cpp
    flang/test/Lower/default-initialization-globals.f90

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h
index dc0c02669cbe6..85de4805958b8 100644
--- a/flang/include/flang/Evaluate/tools.h
+++ b/flang/include/flang/Evaluate/tools.h
@@ -946,6 +946,8 @@ bool IsNullProcedurePointer(const Expr<SomeType> &);
 bool IsNullPointer(const Expr<SomeType> &);
 bool IsObjectPointer(const Expr<SomeType> &, FoldingContext &);
 
+const ProcedureRef *GetProcedureRef(const Expr<SomeType> &);
+
 // Can Expr be passed as absent to an optional dummy argument.
 // See 15.5.2.12 point 1 for more details.
 bool MayBePassedAsAbsentOptional(const Expr<SomeType> &, FoldingContext &);

diff  --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index 5836e47c21971..51b09f3b7af4e 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -784,6 +784,10 @@ bool IsObjectPointer(const Expr<SomeType> &expr, FoldingContext &context) {
   }
 }
 
+const ProcedureRef *GetProcedureRef(const Expr<SomeType> &expr) {
+  return UnwrapProcedureRef(expr);
+}
+
 // IsNullPointer() & variations
 
 template <bool IS_PROC_PTR> struct IsNullPointerHelper {

diff  --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 97c8d6866355a..3de87ca9f4bc3 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -189,17 +189,41 @@ mlir::Value Fortran::lower::genInitialDataTarget(
     return fir::factory::createUnallocatedBox(builder, loc, boxType,
                                               /*nonDeferredParams=*/llvm::None);
   // Pointer initial data target, and NULL(mold).
-  if (const Fortran::semantics::Symbol *sym =
-          Fortran::evaluate::GetFirstSymbol(initialTarget)) {
+  for (const auto &sym : Fortran::evaluate::CollectSymbols(initialTarget)) {
     // Length parameters processing will need care in global initializer
     // context.
-    if (hasDerivedTypeWithLengthParameters(*sym))
+    if (hasDerivedTypeWithLengthParameters(sym))
       TODO(loc, "initial-data-target with derived type length parameters");
 
-    auto var = Fortran::lower::pft::Variable(*sym, /*global=*/true);
+    auto var = Fortran::lower::pft::Variable(sym, /*global=*/true);
     Fortran::lower::instantiateVariable(converter, var, globalOpSymMap,
                                         storeMap);
   }
+
+  // Handle NULL(mold) as a special case. Return an unallocated box of MOLD
+  // type. The return box is correctly created as a fir.box<fir.ptr<T>> where
+  // T is extracted from the MOLD argument.
+  if (const Fortran::evaluate::ProcedureRef *procRef =
+          Fortran::evaluate::GetProcedureRef(initialTarget)) {
+    const Fortran::evaluate::SpecificIntrinsic *intrinsic =
+        procRef->proc().GetSpecificIntrinsic();
+    if (intrinsic && intrinsic->name == "null") {
+      assert(procRef->arguments().size() == 1 &&
+             "Expecting mold argument for NULL intrinsic");
+      const auto *argExpr = procRef->arguments()[0].value().UnwrapExpr();
+      assert(argExpr);
+      const Fortran::semantics::Symbol *sym =
+          Fortran::evaluate::GetFirstSymbol(*argExpr);
+      fir::ExtendedValue exv =
+          globalOpSymMap.lookupSymbol(sym).toExtendedValue();
+      const auto *mold = exv.getBoxOf<fir::MutableBoxValue>();
+      fir::BoxType boxType = mold->getBoxTy();
+      mlir::Value box =
+          fir::factory::createUnallocatedBox(builder, loc, boxType, {});
+      return box;
+    }
+  }
+
   mlir::Value box;
   if (initialTarget.Rank() > 0) {
     box = fir::getBase(Fortran::lower::createSomeArrayBox(

diff  --git a/flang/test/Lower/default-initialization-globals.f90 b/flang/test/Lower/default-initialization-globals.f90
index bde2636537569..3f7a6cd7ada56 100644
--- a/flang/test/Lower/default-initialization-globals.f90
+++ b/flang/test/Lower/default-initialization-globals.f90
@@ -55,6 +55,12 @@ module tinit
     integer :: j = 3
   end type
 
+  type tv
+    real, pointer :: v(:)
+  end type
+
+  real, pointer :: mv(:)
+
   ! Test scalar with default init
   type(t0) :: at0
 ! CHECK-LABEL: fir.global @_QMtinitEat0 : !fir.type<_QMtinitTt0{k:i32}> {
@@ -125,6 +131,17 @@ module tinit
   ! CHECK: %[[VAL_45:.*]] = fir.undefined i32
   ! CHECK: %[[VAL_46:.*]] = fir.insert_value %[[VAL_44]], %[[VAL_45]], ["l", !fir.type<_QMtinitTtextendst0{k:i32,l:i32}>] : (!fir.type<_QMtinitTtextendst0{k:i32,l:i32}>, i32) -> !fir.type<_QMtinitTtextendst0{k:i32,l:i32}>
   ! CHECK: fir.has_value %[[VAL_46]] : !fir.type<_QMtinitTtextendst0{k:i32,l:i32}>
+
+  type(tv) :: withmold = tv(null(mv))
+  ! CHECK-LABEL: fir.global @_QMtinitEwithmold
+  ! CHECK: %[[C0:.*]] = arith.constant 0 : index
+  ! CHECK: %[[UNDEF:.*]] = fir.undefined !fir.type<_QMtinitTtv{v:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>
+  ! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.ptr<!fir.array<?xf32>>
+  ! CHECK: %[[SHAPE:.*]] = fir.shape %[[C0]] : (index) -> !fir.shape<1>
+  ! CHECK: %[[ZEROBOX:.*]] = fir.embox %[[ZERO]](%[[SHAPE]]) : (!fir.ptr<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.box<!fir.ptr<!fir.array<?xf32>>>
+  ! CHECK: %[[RET:.*]] = fir.insert_value %[[UNDEF]], %[[ZEROBOX]], ["v", !fir.type<_QMtinitTtv{v:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>] : (!fir.type<_QMtinitTtv{v:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>, !fir.box<!fir.ptr<!fir.array<?xf32>>>) -> !fir.type<_QMtinitTtv{v:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>
+  ! CHECK: fir.has_value %[[RET]] : !fir.type<_QMtinitTtv{v:!fir.box<!fir.ptr<!fir.array<?xf32>>>}>
+
 end module
 
 


        


More information about the flang-commits mailing list