[flang-commits] [flang] bc991d9 - [flang][hlfir] Array constructor lowering [part 4/4]

Jean Perier via flang-commits flang-commits at lists.llvm.org
Fri Feb 24 00:18:57 PST 2023


Author: Jean Perier
Date: 2023-02-24T09:18:27+01:00
New Revision: bc991d940f9a80735fabaf64473d67a3dc69285a

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

LOG: [flang][hlfir] Array constructor lowering [part 4/4]

Enable character and derived type array constructor lowering.
Nothing special needs to be done other than lowering the types
before the array constructor lowering.
Derived type are forced to use the runtime for now to avoid
undesired usage of user defined assignment that hlfir.assign
may trigger when using the runtime.

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

Added: 
    flang/test/Lower/HLFIR/array-ctor-character.f90
    flang/test/Lower/HLFIR/array-ctor-derived.f90

Modified: 
    flang/lib/Lower/ConvertArrayConstructor.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/ConvertArrayConstructor.cpp b/flang/lib/Lower/ConvertArrayConstructor.cpp
index e9afec8b4c8b2..d5df432c4f257 100644
--- a/flang/lib/Lower/ConvertArrayConstructor.cpp
+++ b/flang/lib/Lower/ConvertArrayConstructor.cpp
@@ -477,6 +477,20 @@ class ArrayCtorLoweringStrategy {
 //   and chooses the lowering strategy.
 //===----------------------------------------------------------------------===//
 
+/// Helper to lower a scalar extent expression (like implied-do bounds).
+static mlir::Value lowerExtentExpr(mlir::Location loc,
+                                   Fortran::lower::AbstractConverter &converter,
+                                   Fortran::lower::SymMap &symMap,
+                                   Fortran::lower::StatementContext &stmtCtx,
+                                   const Fortran::evaluate::ExtentExpr &expr) {
+  fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+  mlir::IndexType idxTy = builder.getIndexType();
+  hlfir::Entity value = Fortran::lower::convertExprToHLFIR(
+      loc, converter, toEvExpr(expr), symMap, stmtCtx);
+  value = hlfir::loadTrivialScalar(loc, builder, value);
+  return builder.createConvert(loc, idxTy, value);
+}
+
 namespace {
 /// Helper class to lower the array constructor type and its length parameters.
 /// The length parameters, if any, are only lowered if this does not require
@@ -503,7 +517,10 @@ struct LengthAndTypeCollector<Fortran::evaluate::SomeDerived> {
           &arrayCtorExpr,
       Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
       mlir::SmallVectorImpl<mlir::Value> &lengths) {
-    TODO(loc, "collect derived type and length");
+    // Array constructors cannot be unlimited polymorphic (C7113), so there must
+    // be a derived type spec available.
+    return Fortran::lower::translateDerivedTypeToFIRType(
+        converter, arrayCtorExpr.result().derivedTypeSpec());
   }
 };
 
@@ -517,7 +534,17 @@ struct LengthAndTypeCollector<Character<Kind>> {
       const Fortran::evaluate::ArrayConstructor<Character<Kind>> &arrayCtorExpr,
       Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
       mlir::SmallVectorImpl<mlir::Value> &lengths) {
-    TODO(loc, "collect character type and length");
+    llvm::SmallVector<Fortran::lower::LenParameterTy> typeLengths;
+    if (const Fortran::evaluate::ExtentExpr *lenExpr = arrayCtorExpr.LEN()) {
+      lengths.push_back(
+          lowerExtentExpr(loc, converter, symMap, stmtCtx, *lenExpr));
+      if (std::optional<std::int64_t> cstLen =
+              Fortran::evaluate::ToInt64(*lenExpr))
+        typeLengths.push_back(*cstLen);
+    }
+    return Fortran::lower::getFIRType(&converter.getMLIRContext(),
+                                      Fortran::common::TypeCategory::Character,
+                                      Kind, typeLengths);
   }
 };
 } // namespace
@@ -611,20 +638,6 @@ ArrayCtorAnalysis::ArrayCtorAnalysis(
   }
 }
 
-/// Helper to lower a scalar extent expression (like implied-do bounds).
-static mlir::Value lowerExtentExpr(mlir::Location loc,
-                                   Fortran::lower::AbstractConverter &converter,
-                                   Fortran::lower::SymMap &symMap,
-                                   Fortran::lower::StatementContext &stmtCtx,
-                                   const Fortran::evaluate::ExtentExpr &expr) {
-  fir::FirOpBuilder &builder = converter.getFirOpBuilder();
-  mlir::IndexType idxTy = builder.getIndexType();
-  hlfir::Entity value = Fortran::lower::convertExprToHLFIR(
-      loc, converter, toEvExpr(expr), symMap, stmtCtx);
-  value = hlfir::loadTrivialScalar(loc, builder, value);
-  return builder.createConvert(loc, idxTy, value);
-}
-
 /// Does \p expr contain no calls to user function?
 static bool isCallFreeExpr(const Fortran::evaluate::ExtentExpr &expr) {
   for (const Fortran::semantics::Symbol &symbol :
@@ -679,7 +692,7 @@ static ArrayCtorLoweringStrategy selectArrayCtorLoweringStrategy(
   // Based on what was gathered and the result of the analysis, select and
   // instantiate the right lowering strategy for the array constructor.
   if (!extent || needToEvaluateOneExprToGetLengthParameters ||
-      analysis.anyArrayExpr)
+      analysis.anyArrayExpr || declaredType.getEleTy().isa<fir::RecordType>())
     return RuntimeTempStrategy(
         loc, builder, declaredType,
         extent ? std::optional<mlir::Value>(extent) : std::nullopt, lengths,

diff  --git a/flang/test/Lower/HLFIR/array-ctor-character.f90 b/flang/test/Lower/HLFIR/array-ctor-character.f90
new file mode 100644
index 0000000000000..d4c38bda3ecc0
--- /dev/null
+++ b/flang/test/Lower/HLFIR/array-ctor-character.f90
@@ -0,0 +1,87 @@
+! Test lowering of character array constructors to HLFIR.
+! RUN: bbc -emit-fir -hlfir -o - %s | FileCheck %s
+
+module chararrayctor
+  character(3), target :: ctarg1 = "abc"
+  character(3), target :: ctarg2 = "def"
+contains
+
+  subroutine test_pre_computed_length(c1, c2)
+    character(*) :: c1, c2
+    call takes_char([character(3):: c1, c2])
+  end subroutine
+! CHECK-LABEL: func.func @_QMchararrayctorPtest_pre_computed_length(
+! CHECK:  %[[VAL_9:.*]]:2 = hlfir.declare %{{.*}}Ec1"
+! CHECK:  %[[VAL_11:.*]]:2 = hlfir.declare %{{.*}}Ec2"
+! CHECK:  %[[VAL_12:.*]] = arith.constant 2 : index
+! CHECK:  %[[VAL_13:.*]] = arith.constant 3 : i64
+! CHECK:  %[[VAL_14:.*]] = fir.convert %[[VAL_13]] : (i64) -> index
+! CHECK:  %[[VAL_15:.*]] = arith.constant 1 : index
+! CHECK:  %[[VAL_16:.*]] = fir.allocmem !fir.array<2x!fir.char<1,3>> {bindc_name = ".tmp.arrayctor", uniq_name = ""}
+! CHECK:  %[[VAL_17:.*]] = fir.shape %[[VAL_12]] : (index) -> !fir.shape<1>
+! CHECK:  %[[VAL_18:.*]]:2 = hlfir.declare %[[VAL_16]](%[[VAL_17]]) typeparams %[[VAL_14]] {uniq_name = ".tmp.arrayctor"} : (!fir.heap<!fir.array<2x!fir.char<1,3>>>, !fir.shape<1>, index) -> (!fir.heap<!fir.array<2x!fir.char<1,3>>>, !fir.heap<!fir.array<2x!fir.char<1,3>>>)
+! CHECK:  %[[VAL_19:.*]] = arith.constant 3 : i64
+! CHECK:  %[[VAL_20:.*]] = hlfir.set_length %[[VAL_9]]#0 len %[[VAL_19]] : (!fir.boxchar<1>, i64) -> !hlfir.expr<!fir.char<1,3>>
+! CHECK:  %[[VAL_21:.*]] = arith.addi %[[VAL_15]], %[[VAL_15]] : index
+! CHECK:  %[[VAL_22:.*]] = hlfir.designate %[[VAL_18]]#0 (%[[VAL_15]])  typeparams %[[VAL_14]] : (!fir.heap<!fir.array<2x!fir.char<1,3>>>, index, index) -> !fir.ref<!fir.char<1,3>>
+! CHECK:  hlfir.assign %[[VAL_20]] to %[[VAL_22]] : !hlfir.expr<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>>
+! CHECK:  %[[VAL_23:.*]] = arith.constant 3 : i64
+! CHECK:  %[[VAL_24:.*]] = hlfir.set_length %[[VAL_11]]#0 len %[[VAL_23]] : (!fir.boxchar<1>, i64) -> !hlfir.expr<!fir.char<1,3>>
+! CHECK:  %[[VAL_25:.*]] = hlfir.designate %[[VAL_18]]#0 (%[[VAL_21]])  typeparams %[[VAL_14]] : (!fir.heap<!fir.array<2x!fir.char<1,3>>>, index, index) -> !fir.ref<!fir.char<1,3>>
+! CHECK:  hlfir.assign %[[VAL_24]] to %[[VAL_25]] : !hlfir.expr<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>>
+! CHECK:  %[[VAL_26:.*]] = arith.constant true
+! CHECK:  %[[VAL_27:.*]] = hlfir.as_expr %[[VAL_18]]#0 move %[[VAL_26]] : (!fir.heap<!fir.array<2x!fir.char<1,3>>>, i1) -> !hlfir.expr<2x!fir.char<1,3>>
+! CHECK:  fir.call @_QMchararrayctorPtakes_char
+! CHECK:  hlfir.destroy %[[VAL_27]] : !hlfir.expr<2x!fir.char<1,3>>
+
+  subroutine test_dynamic_length()
+    call takes_char([char_pointer(1), char_pointer(2)])
+  end subroutine
+! CHECK-LABEL: func.func @_QMchararrayctorPtest_dynamic_length() {
+! CHECK:  %[[VAL_0:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.char<1,?>>> {bindc_name = ".result"}
+! CHECK:  %[[VAL_1:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.char<1,?>>> {bindc_name = ".result"}
+! CHECK:  %[[VAL_2:.*]] = fir.alloca !fir.array<10xi64> {bindc_name = ".rt.arrayctor.vector"}
+! CHECK:  %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<2x!fir.char<1,?>>>> {bindc_name = ".tmp.arrayctor"}
+! CHECK:  %[[VAL_10:.*]] = arith.constant 2 : index
+! CHECK:  %[[VAL_11:.*]] = arith.constant 0 : index
+! CHECK:  %[[VAL_12:.*]] = fir.zero_bits !fir.heap<!fir.array<2x!fir.char<1,?>>>
+! CHECK:  %[[VAL_13:.*]] = fir.shape %[[VAL_10]] : (index) -> !fir.shape<1>
+! CHECK:  %[[VAL_14:.*]] = fir.embox %[[VAL_12]](%[[VAL_13]]) typeparams %[[VAL_11]] : (!fir.heap<!fir.array<2x!fir.char<1,?>>>, !fir.shape<1>, index) -> !fir.box<!fir.heap<!fir.array<2x!fir.char<1,?>>>>
+! CHECK:  fir.store %[[VAL_14]] to %[[VAL_3]] : !fir.ref<!fir.box<!fir.heap<!fir.array<2x!fir.char<1,?>>>>>
+! CHECK:  %[[VAL_15:.*]] = arith.constant true
+! CHECK:  %[[VAL_16:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.array<10xi64>>) -> !fir.llvm_ptr<i8>
+! CHECK:  %[[VAL_20:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<2x!fir.char<1,?>>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK:  %[[VAL_22:.*]] = fir.call @_FortranAInitArrayConstructorVector(%[[VAL_16]], %[[VAL_20]], %[[VAL_15]], %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.llvm_ptr<i8>, !fir.ref<!fir.box<none>>, i1, i32, !fir.ref<i8>, i32) -> none
+! CHECK:  fir.call @_QMchararrayctorPchar_pointer(
+! CHECK:  fir.call @_FortranAPushArrayConstructorValue(%[[VAL_16]], %{{.*}}) {{.*}}: (!fir.llvm_ptr<i8>, !fir.box<none>) -> none
+! CHECK:  fir.call @_QMchararrayctorPchar_pointer(
+! CHECK:  fir.call @_FortranAPushArrayConstructorValue(%[[VAL_16]], %{{.*}}) {{.*}}: (!fir.llvm_ptr<i8>, !fir.box<none>) -> none
+! CHECK:  %[[VAL_45:.*]] = arith.constant true
+! CHECK:  %[[VAL_46:.*]] = fir.load %[[VAL_3]] : !fir.ref<!fir.box<!fir.heap<!fir.array<2x!fir.char<1,?>>>>>
+! CHECK:  %[[VAL_47:.*]] = hlfir.as_expr %[[VAL_46]] move %[[VAL_45]] : (!fir.box<!fir.heap<!fir.array<2x!fir.char<1,?>>>>, i1) -> !hlfir.expr<2x!fir.char<1,?>>
+! CHECK:  fir.call @_QMchararrayctorPtakes_char(
+! CHECK:  hlfir.destroy %[[VAL_47]] : !hlfir.expr<2x!fir.char<1,?>>
+
+
+! Code below is only relevant for end-to-end test validation purpose.
+  function char_pointer(i)
+    integer :: i
+    character(:), pointer :: char_pointer
+    if (i.eq.1) then
+      char_pointer => ctarg1
+    else
+      char_pointer => ctarg2
+    end if
+  end function
+  subroutine takes_char(c)
+    character(*) :: c(:)
+    print *, "got   : ", c
+  end subroutine
+end module
+
+  use chararrayctor
+  print *, "expect: ab cde"
+  call test_pre_computed_length("ab", "cdefg")
+  print *, "expect: abcdef"
+  call test_dynamic_length()
+end

diff  --git a/flang/test/Lower/HLFIR/array-ctor-derived.f90 b/flang/test/Lower/HLFIR/array-ctor-derived.f90
new file mode 100644
index 0000000000000..d814083b59e4d
--- /dev/null
+++ b/flang/test/Lower/HLFIR/array-ctor-derived.f90
@@ -0,0 +1,88 @@
+! Test lowering of derived type array constructors to HLFIR.
+! RUN: bbc -emit-fir -hlfir --polymorphic-type -o - %s | FileCheck %s
+
+module types
+  type simple
+    integer :: i
+    integer :: j
+  end type
+end module
+module derivedarrayctor
+  use types
+contains
+  subroutine test_simple(s1, s2)
+    type(simple) :: s1, s2
+    call takes_simple([s1, s2])
+  end subroutine
+! CHECK-LABEL: func.func @_QMderivedarrayctorPtest_simple(
+! CHECK:  %[[VAL_2:.*]] = fir.alloca !fir.array<10xi64> {bindc_name = ".rt.arrayctor.vector"}
+! CHECK:  %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>> {bindc_name = ".tmp.arrayctor"}
+! CHECK:  %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}Es1"
+! CHECK:  %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}Es2"
+! CHECK:  %[[VAL_6:.*]] = arith.constant 2 : index
+! CHECK:  %[[VAL_7:.*]] = fir.allocmem !fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>> {bindc_name = ".tmp.arrayctor", uniq_name = ""}
+! CHECK:  %[[VAL_8:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1>
+! CHECK:  %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_7]](%[[VAL_8]]) {uniq_name = ".tmp.arrayctor"} : (!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>, !fir.shape<1>) -> (!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>, !fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>)
+! CHECK:  %[[VAL_10:.*]] = fir.embox %[[VAL_9]]#1(%[[VAL_8]]) : (!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>>
+! CHECK:  fir.store %[[VAL_10]] to %[[VAL_3]] : !fir.ref<!fir.box<!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>>>
+! CHECK:  %[[VAL_11:.*]] = arith.constant false
+! CHECK:  %[[VAL_12:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.array<10xi64>>) -> !fir.llvm_ptr<i8>
+! CHECK:  %[[VAL_16:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK:  %[[VAL_18:.*]] = fir.call @_FortranAInitArrayConstructorVector(%[[VAL_12]], %[[VAL_16]], %[[VAL_11]], %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.llvm_ptr<i8>, !fir.ref<!fir.box<none>>, i1, i32, !fir.ref<i8>, i32) -> none
+! CHECK:  %[[VAL_19:.*]] = fir.convert %[[VAL_4]]#1 : (!fir.ref<!fir.type<_QMtypesTsimple{i:i32,j:i32}>>) -> !fir.llvm_ptr<i8>
+! CHECK:  %[[VAL_20:.*]] = fir.call @_FortranAPushArrayConstructorSimpleScalar(%[[VAL_12]], %[[VAL_19]]) {{.*}}: (!fir.llvm_ptr<i8>, !fir.llvm_ptr<i8>) -> none
+! CHECK:  %[[VAL_21:.*]] = fir.convert %[[VAL_5]]#1 : (!fir.ref<!fir.type<_QMtypesTsimple{i:i32,j:i32}>>) -> !fir.llvm_ptr<i8>
+! CHECK:  %[[VAL_22:.*]] = fir.call @_FortranAPushArrayConstructorSimpleScalar(%[[VAL_12]], %[[VAL_21]]) {{.*}}: (!fir.llvm_ptr<i8>, !fir.llvm_ptr<i8>) -> none
+! CHECK:  %[[VAL_23:.*]] = arith.constant true
+! CHECK:  %[[VAL_24:.*]] = hlfir.as_expr %[[VAL_9]]#0 move %[[VAL_23]] : (!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>, i1) -> !hlfir.expr<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>
+! CHECK:  fir.call @_QMderivedarrayctorPtakes_simple
+! CHECK:  hlfir.destroy %[[VAL_24]] : !hlfir.expr<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>
+
+  subroutine test_with_polymorphic(s1, s2)
+    class(simple) :: s1, s2
+    call takes_simple([s1, s2])
+  end subroutine
+! CHECK-LABEL: func.func @_QMderivedarrayctorPtest_with_polymorphic(
+! CHECK:  %[[VAL_2:.*]] = fir.alloca !fir.array<10xi64> {bindc_name = ".rt.arrayctor.vector"}
+! CHECK:  %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>> {bindc_name = ".tmp.arrayctor"}
+! CHECK:  %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}Es1"
+! CHECK:  %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}Es2"
+! CHECK:  %[[VAL_6:.*]] = arith.constant 2 : index
+! CHECK:  %[[VAL_7:.*]] = fir.allocmem !fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>> {bindc_name = ".tmp.arrayctor", uniq_name = ""}
+! CHECK:  %[[VAL_8:.*]] = fir.shape %[[VAL_6]] : (index) -> !fir.shape<1>
+! CHECK:  %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_7]](%[[VAL_8]]) {uniq_name = ".tmp.arrayctor"} : (!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>, !fir.shape<1>) -> (!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>, !fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>)
+! CHECK:  %[[VAL_10:.*]] = fir.embox %[[VAL_9]]#1(%[[VAL_8]]) : (!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>>
+! CHECK:  fir.store %[[VAL_10]] to %[[VAL_3]] : !fir.ref<!fir.box<!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>>>
+! CHECK:  %[[VAL_11:.*]] = arith.constant false
+! CHECK:  %[[VAL_12:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.array<10xi64>>) -> !fir.llvm_ptr<i8>
+! CHECK:  %[[VAL_16:.*]] = fir.convert %[[VAL_3]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK:  %[[VAL_18:.*]] = fir.call @_FortranAInitArrayConstructorVector(%[[VAL_12]], %[[VAL_16]], %[[VAL_11]], %{{.*}}, %{{.*}}, %{{.*}}) {{.*}}: (!fir.llvm_ptr<i8>, !fir.ref<!fir.box<none>>, i1, i32, !fir.ref<i8>, i32) -> none
+! CHECK:  %[[VAL_19A:.*]] = fir.box_addr %[[VAL_4]]#1 : (!fir.class<!fir.type<_QMtypesTsimple{i:i32,j:i32}>>) -> !fir.ref<!fir.type<_QMtypesTsimple{i:i32,j:i32}>>
+! CHECK:  %[[VAL_19:.*]] = fir.convert %[[VAL_19A]] : (!fir.ref<!fir.type<_QMtypesTsimple{i:i32,j:i32}>>) -> !fir.llvm_ptr<i8>
+! CHECK:  %[[VAL_20:.*]] = fir.call @_FortranAPushArrayConstructorSimpleScalar(%[[VAL_12]], %[[VAL_19]]) {{.*}}: (!fir.llvm_ptr<i8>, !fir.llvm_ptr<i8>) -> none
+! CHECK:  %[[VAL_21A:.*]] = fir.box_addr %[[VAL_5]]#1 : (!fir.class<!fir.type<_QMtypesTsimple{i:i32,j:i32}>>) -> !fir.ref<!fir.type<_QMtypesTsimple{i:i32,j:i32}>>
+! CHECK:  %[[VAL_21:.*]] = fir.convert %[[VAL_21A]] : (!fir.ref<!fir.type<_QMtypesTsimple{i:i32,j:i32}>>) -> !fir.llvm_ptr<i8>
+! CHECK:  %[[VAL_22:.*]] = fir.call @_FortranAPushArrayConstructorSimpleScalar(%[[VAL_12]], %[[VAL_21]]) {{.*}}: (!fir.llvm_ptr<i8>, !fir.llvm_ptr<i8>) -> none
+! CHECK:  %[[VAL_23:.*]] = arith.constant true
+! CHECK:  %[[VAL_24:.*]] = hlfir.as_expr %[[VAL_9]]#0 move %[[VAL_23]] : (!fir.heap<!fir.array<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>>, i1) -> !hlfir.expr<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>
+! CHECK:  fir.call @_QMderivedarrayctorPtakes_simple
+! CHECK:  hlfir.destroy %[[VAL_24]] : !hlfir.expr<2x!fir.type<_QMtypesTsimple{i:i32,j:i32}>>
+
+  subroutine takes_simple(s)
+    type(simple) :: s(:)
+    print *, "got   :", s
+  end subroutine
+end module
+
+  use derivedarrayctor
+  type(simple) :: s1, s2
+  s1%i = 1
+  s1%j = 2
+  s2%i = 3
+  s2%j = 4
+
+  print *, "expect: 1 2 3 4"
+  call test_simple(s1, s2)
+  print *, "expect: 1 2 3 4"
+  call test_with_polymorphic(s1, s2)
+end


        


More information about the flang-commits mailing list