[flang-commits] [flang] 6c3c81b - [flang] Lower and code gen for allocate on polymorphic entities
Valentin Clement via flang-commits
flang-commits at lists.llvm.org
Fri Oct 21 05:34:09 PDT 2022
Author: Valentin Clement
Date: 2022-10-21T14:34:03+02:00
New Revision: 6c3c81b983edf8bf1299011b530edbc4d32285cf
URL: https://github.com/llvm/llvm-project/commit/6c3c81b983edf8bf1299011b530edbc4d32285cf
DIFF: https://github.com/llvm/llvm-project/commit/6c3c81b983edf8bf1299011b530edbc4d32285cf.diff
LOG: [flang] Lower and code gen for allocate on polymorphic entities
When allocating a polymorphic entity, its type descriptor can come
from the declared type or can be provided in the allocate statement.
This patch adds lowering for allocate on polymorphic by calling
the `AllocatableInitDerived` runtime function with the correct
type descriptor. Some adaptation are made in the code generation
to accept fir.class where it is appropriate.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D136426
Added:
flang/test/Lower/allocatable-polymorphic.f90
Modified:
flang/docs/PolymorphicEntities.md
flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
flang/lib/Lower/Allocatable.cpp
flang/lib/Optimizer/CodeGen/CodeGen.cpp
flang/lib/Optimizer/CodeGen/TypeConverter.h
Removed:
################################################################################
diff --git a/flang/docs/PolymorphicEntities.md b/flang/docs/PolymorphicEntities.md
index bd4ad7619cb4b..c7a14249f4ef4 100644
--- a/flang/docs/PolymorphicEntities.md
+++ b/flang/docs/PolymorphicEntities.md
@@ -683,14 +683,15 @@ allocate(rectangle::shapes(2)%item)
**FIR**
```c
-%0 = fir.alloca !fir.class<!fir.type<_QMgeometryTtriangle{color:i32,isFilled:!fir.logical<4>,base:f32,height:f32>>
-%1 = fir.alloca !fir.class<!fir.type<_QMgeometryTtriangle{color:i32,isFilled:!fir.logical<4>,base:f32,height:f32}>>
-%3 = fir.convert %0 : (!fir.ref<!fir.class<!fir.type<_QMgeometryTtriangle{color:i32,isFilled:!fir.logical<4>,base:f32,height:f32>>>) -> !fir.ref<!fir.box<none>>
-%4 = fir.gentypedesc !fir.type<_QMgeometryTtriangle{color:i32,isFilled:!fir.logical<4>,base:f32,height:f32}>>
-%5 = fir.call @_FortranAAllocatableInitDerived(%3, %4)
+%0 = fir.address_of(@_QMgeometryE.dt.triangle) : !fir.ref<!fir.type<_QM__fortran_type_infoTderivedtype>>
+%1 = fir.convert %item1 : (!fir.ref<!fir.class<!fir.type<_QMgeometryTtriangle{color:i32,isFilled:!fir.logical<4>,base:f32,height:f32>>>) -> !fir.ref<!fir.box<none>>
+%2 = fir.call @_FortranAAllocatableInitDerived(%1, %0)
+%3 = fir.call @_FortranAAllocatableAllocate(%1, ...)
-%6 = fir.convert %1 : (!fir.ref<!fir.class<_QMgeometryTtriangle{color:i32,isFilled:!fir.logical<4>,base:f32,height:f32}>>>) -> !fir.ref<!fir.box<none>>
-%7 = fir.gentypedesc !fir.type<_QMgeometryTtriangle{color:i32,isFilled:!fir.logical<4>,base:f32,height:f32}>> %8 = fir.call @_FortranAAllocatableInitDerived(%6, %7)
+%4 = fir.address_of(@_QMgeometryE.dt.rectangle) : !fir.ref<!fir.type<_QM__fortran_type_infoTderivedtype>>
+%5 = fir.convert %item2 : (!fir.ref<!fir.class<_QMgeometryTtriangle{color:i32,isFilled:!fir.logical<4>,base:f32,height:f32}>>>) -> !fir.ref<!fir.box<none>>
+%6 = fir.call @_FortranAAllocatableInitDerived(%5, %4)
+%7 = fir.call @_FortranAAllocatableAllocate(%5, ...)
```
For pointer allocation, the `PointerAllocate` function is used.
@@ -851,7 +852,6 @@ dynamic type of polymorphic entities.
Current list of TODOs in lowering:
- `flang/lib/Lower/Allocatable.cpp:465` not yet implemented: SOURCE allocation
- `flang/lib/Lower/Allocatable.cpp:468` not yet implemented: MOLD allocation
-- `flang/lib/Lower/Allocatable.cpp:471` not yet implemented: polymorphic entity allocation
- `flang/lib/Lower/Bridge.cpp:448` not yet implemented: create polymorphic host associated copy
- `flang/lib/Lower/Bridge.cpp:2185` not yet implemented: assignment to polymorphic allocatable
- `flang/lib/Lower/Bridge.cpp:2288` not yet implemented: pointer assignment involving polymorphic entity
diff --git a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
index b2e7abe893483..3a21479a1cfe2 100644
--- a/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/Runtime/RTBuilder.h
@@ -35,7 +35,10 @@ struct c_double_complex_t;
namespace Fortran::runtime {
class Descriptor;
+namespace typeInfo {
+class DerivedType;
}
+} // namespace Fortran::runtime
namespace fir::runtime {
@@ -280,6 +283,13 @@ constexpr TypeBuilderFunc getModel<Fortran::common::TypeCategory>() {
};
}
template <>
+constexpr TypeBuilderFunc
+getModel<const Fortran::runtime::typeInfo::DerivedType &>() {
+ return [](mlir::MLIRContext *context) -> mlir::Type {
+ return fir::ReferenceType::get(mlir::NoneType::get(context));
+ };
+}
+template <>
constexpr TypeBuilderFunc getModel<void>() {
return [](mlir::MLIRContext *context) -> mlir::Type {
return mlir::NoneType::get(context);
diff --git a/flang/lib/Lower/Allocatable.cpp b/flang/lib/Lower/Allocatable.cpp
index 5fda1f27475a1..af96be782abc0 100644
--- a/flang/lib/Lower/Allocatable.cpp
+++ b/flang/lib/Lower/Allocatable.cpp
@@ -14,6 +14,7 @@
#include "flang/Evaluate/tools.h"
#include "flang/Lower/AbstractConverter.h"
#include "flang/Lower/IterationSpace.h"
+#include "flang/Lower/Mangler.h"
#include "flang/Lower/PFTBuilder.h"
#include "flang/Lower/Runtime.h"
#include "flang/Lower/StatementContext.h"
@@ -23,6 +24,7 @@
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
#include "flang/Optimizer/Support/FatalError.h"
+#include "flang/Optimizer/Support/InternalNames.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Runtime/allocatable.h"
#include "flang/Runtime/pointer.h"
@@ -393,7 +395,7 @@ class AllocateStmtHelper {
if (alloc.hasCoarraySpec())
TODO(loc, "coarray allocation");
if (alloc.type.IsPolymorphic())
- genSetType(alloc, box);
+ genSetType(alloc, box, loc);
genSetDeferredLengthParameters(alloc, box);
// Set bounds for arrays
mlir::Type idxTy = builder.getIndexType();
@@ -467,8 +469,47 @@ class AllocateStmtHelper {
void genMoldAllocation(const Allocation &, const fir::MutableBoxValue &) {
TODO(loc, "MOLD allocation");
}
- void genSetType(const Allocation &, const fir::MutableBoxValue &) {
- TODO(loc, "polymorphic entity allocation");
+
+ /// Generate call to the AllocatableInitDerived to set up the type descriptor
+ /// and other part of the descriptor for derived type.
+ void genSetType(const Allocation &alloc, const fir::MutableBoxValue &box,
+ mlir::Location loc) {
+ const Fortran::semantics::DeclTypeSpec *typeSpec =
+ getIfAllocateStmtTypeSpec();
+
+ // No type spec provided in allocate statement so the declared type spec is
+ // used.
+ if (!typeSpec)
+ typeSpec = &alloc.type;
+
+ assert(typeSpec && "type spec missing for polymorphic allocation");
+ std::string typeName =
+ Fortran::lower::mangle::mangleName(typeSpec->derivedTypeSpec());
+ std::string typeDescName =
+ fir::NameUniquer::getTypeDescriptorName(typeName);
+
+ auto typeDescGlobal =
+ builder.getModule().lookupSymbol<fir::GlobalOp>(typeDescName);
+ if (!typeDescGlobal)
+ fir::emitFatalError(loc, "type descriptor not defined");
+ auto typeDescAddr = builder.create<fir::AddrOfOp>(
+ loc, fir::ReferenceType::get(typeDescGlobal.getType()),
+ typeDescGlobal.getSymbol());
+ mlir::func::FuncOp callee =
+ fir::runtime::getRuntimeFunc<mkRTKey(AllocatableInitDerived)>(loc,
+ builder);
+
+ llvm::ArrayRef<mlir::Type> inputTypes =
+ callee.getFunctionType().getInputs();
+ llvm::SmallVector<mlir::Value> args;
+ args.push_back(builder.createConvert(loc, inputTypes[0], box.getAddr()));
+ args.push_back(builder.createConvert(loc, inputTypes[1], typeDescAddr));
+ mlir::Value rank = builder.createIntegerConstant(loc, inputTypes[2],
+ alloc.getSymbol().Rank());
+ mlir::Value c0 = builder.createIntegerConstant(loc, inputTypes[3], 0);
+ args.push_back(rank);
+ args.push_back(c0);
+ builder.create<fir::CallOp>(loc, callee, args);
}
/// Returns a pointer to the DeclTypeSpec if a type-spec is provided in the
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index a49777fdd6b0f..9f4d1127d27fd 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -2753,7 +2753,7 @@ struct GlobalOpConversion : public FIROpConversion<fir::GlobalOp> {
matchAndRewrite(fir::GlobalOp global, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const override {
auto tyAttr = convertType(global.getType());
- if (global.getType().isa<fir::BoxType>())
+ if (global.getType().isa<fir::BaseBoxType>())
tyAttr = tyAttr.cast<mlir::LLVM::LLVMPointerType>().getElementType();
auto loc = global.getLoc();
mlir::Attribute initAttr = global.getInitVal().value_or(mlir::Attribute());
diff --git a/flang/lib/Optimizer/CodeGen/TypeConverter.h b/flang/lib/Optimizer/CodeGen/TypeConverter.h
index 13e7d7602093e..708b9ec9bf123 100644
--- a/flang/lib/Optimizer/CodeGen/TypeConverter.h
+++ b/flang/lib/Optimizer/CodeGen/TypeConverter.h
@@ -118,7 +118,7 @@ class LLVMTypeConverter : public mlir::LLVMTypeConverter {
for (auto mem : tuple.getTypes()) {
// Prevent fir.box from degenerating to a pointer to a descriptor in the
// context of a tuple type.
- if (auto box = mem.dyn_cast<fir::BoxType>())
+ if (auto box = mem.dyn_cast<fir::BaseBoxType>())
members.push_back(convertBoxTypeAsStruct(box));
else
members.push_back(convertType(mem).cast<mlir::Type>());
@@ -177,7 +177,7 @@ class LLVMTypeConverter : public mlir::LLVMTypeConverter {
for (auto mem : derived.getTypeList()) {
// Prevent fir.box from degenerating to a pointer to a descriptor in the
// context of a record type.
- if (auto box = mem.second.dyn_cast<fir::BoxType>())
+ if (auto box = mem.second.dyn_cast<fir::BaseBoxType>())
members.push_back(convertBoxTypeAsStruct(box));
else
members.push_back(convertType(mem.second).cast<mlir::Type>());
@@ -269,7 +269,7 @@ class LLVMTypeConverter : public mlir::LLVMTypeConverter {
/// Convert fir.box type to the corresponding llvm struct type instead of a
/// pointer to this struct type.
- mlir::Type convertBoxTypeAsStruct(BoxType box) {
+ mlir::Type convertBoxTypeAsStruct(BaseBoxType box) {
return convertBoxType(box)
.cast<mlir::LLVM::LLVMPointerType>()
.getElementType();
@@ -331,7 +331,7 @@ class LLVMTypeConverter : public mlir::LLVMTypeConverter {
// the same as a fir.box at the LLVM level.
// The distinction is kept in fir to denote when a descriptor is expected
// to be mutable (fir.ref<fir.box>) and when it is not (fir.box).
- if (eleTy.isa<fir::BoxType>())
+ if (eleTy.isa<fir::BaseBoxType>())
return convertType(eleTy);
return mlir::LLVM::LLVMPointerType::get(convertType(eleTy));
diff --git a/flang/test/Lower/allocatable-polymorphic.f90 b/flang/test/Lower/allocatable-polymorphic.f90
new file mode 100644
index 0000000000000..8f043486c36f8
--- /dev/null
+++ b/flang/test/Lower/allocatable-polymorphic.f90
@@ -0,0 +1,116 @@
+! RUN: bbc -polymorphic-type -emit-fir %s -o - | FileCheck %s
+! RUN: bbc -polymorphic-type -emit-fir %s -o - | tco | FileCheck %s --check-prefix=LLVM
+
+module poly
+ type p1
+ integer :: a
+ integer :: b
+ end type
+
+ type, extends(p1) :: p2
+ integer :: c
+ end type
+end module
+
+program test_allocatable
+ use poly
+
+ class(p1), allocatable :: p
+ class(p1), allocatable :: c1, c2
+ class(p1), allocatable, dimension(:) :: c3, c4
+
+ allocate(p) ! allocate as p1
+
+ allocate(p1::c1)
+ allocate(p2::c2)
+
+ allocate(p1::c3(10))
+ allocate(p2::c4(20))
+
+end
+
+! CHECK-LABEL: func.func @_QQmain()
+
+! CHECK-DAG: %[[C1:.*]] = fir.address_of(@_QFEc1) : !fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>
+! CHECK-DAG: %[[C2:.*]] = fir.address_of(@_QFEc2) : !fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>
+! CHECK-DAG: %[[C3:.*]] = fir.address_of(@_QFEc3) : !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>>
+! CHECK-DAG: %[[C4:.*]] = fir.address_of(@_QFEc4) : !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>>
+! CHECK-DAG: %[[P:.*]] = fir.address_of(@_QFEp) : !fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>
+
+! CHECK: %[[TYPE_DESC_P1:.*]] = fir.address_of(@_QMpolyE.dt.p1) : !fir.ref<!fir.type<_QM__fortran_type_infoTderivedtype
+! CHECK: %[[P_CAST:.*]] = fir.convert %[[P]] : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.ref<!fir.type<_QM__fortran_type_infoTderivedtype
+! CHECK: %[[RANK:.*]] = arith.constant 0 : i32
+! CHECK: %[[C0:.*]] = arith.constant 0 : i32
+! CHECK: fir.call @_FortranAAllocatableInitDerived(%[[P_CAST]], %[[TYPE_DESC_P1_CAST]], %[[RANK]], %[[C0]]) : (!fir.ref<!fir.box<none>>, !fir.ref<none>, i32, i32) -> none
+! CHECK: %[[P_CAST:.*]] = fir.convert %[[P]] : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %{{.*}} = fir.call @_FortranAAllocatableAllocate(%[[P_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
+
+! CHECK: %[[TYPE_DESC_P1:.*]] = fir.address_of(@_QMpolyE.dt.p1) : !fir.ref<!fir.type<_QM__fortran_type_infoTderivedtype
+! CHECK: %[[C1_CAST:.*]] = fir.convert %0 : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.ref<!fir.type<_QM__fortran_type_infoTderivedtype
+! CHECK: %[[RANK:.*]] = arith.constant 0 : i32
+! CHECK: %[[C0:.*]] = arith.constant 0 : i32
+! CHECK: fir.call @_FortranAAllocatableInitDerived(%[[C1_CAST]], %[[TYPE_DESC_P1_CAST]], %[[RANK]], %[[C0]]) : (!fir.ref<!fir.box<none>>, !fir.ref<none>, i32, i32) -> none
+! CHECK: %[[C1_CAST:.*]] = fir.convert %[[C1]] : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %{{.*}} = fir.call @_FortranAAllocatableAllocate(%[[C1_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
+
+! CHECK: %[[TYPE_DESC_P2:.*]] = fir.address_of(@_QMpolyE.dt.p2) : !fir.ref<!fir.type<
+! CHECK: %[[C2_CAST:.*]] = fir.convert %[[C2]] : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[TYPE_DESC_P2_CAST:.*]] = fir.convert %[[TYPE_DESC_P2]] : (!fir.ref<!fir.type<_QM__fortran_type_infoTderivedtype
+! CHECK: %[[RANK:.*]] = arith.constant 0 : i32
+! CHECK: %[[C0:.*]] = arith.constant 0 : i32
+! CHECK: fir.call @_FortranAAllocatableInitDerived(%[[C2_CAST]], %[[TYPE_DESC_P2_CAST]], %[[RANK]], %[[C0]]) : (!fir.ref<!fir.box<none>>, !fir.ref<none>, i32, i32) -> none
+! CHECK: %[[C2_CAST:.*]] = fir.convert %[[C2]] : (!fir.ref<!fir.class<!fir.heap<!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %{{.*}} = fir.call @_FortranAAllocatableAllocate(%[[C2_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
+
+! CHECK: %[[TYPE_DESC_P1:.*]] = fir.address_of(@_QMpolyE.dt.p1) : !fir.ref<!fir.type<_QM__fortran_type_infoTderivedtype
+! CHECK: %[[C3_CAST:.*]] = fir.convert %[[C3]] : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[TYPE_DESC_P1_CAST:.*]] = fir.convert %[[TYPE_DESC_P1]] : (!fir.ref<!fir.type<_QM__fortran_type_infoTderivedtype
+! CHECK: %[[RANK:.*]] = arith.constant 1 : i32
+! CHECK: %[[C0:.*]] = arith.constant 0 : i32
+! CHECK: fir.call @_FortranAAllocatableInitDerived(%[[C3_CAST]], %[[TYPE_DESC_P1_CAST]], %[[RANK]], %[[C0]]) : (!fir.ref<!fir.box<none>>, !fir.ref<none>, i32, i32) -> none
+! CHECK: %[[C1:.*]] = arith.constant 1 : index
+! CHECK: %[[C10:.*]] = arith.constant 10 : i32
+! CHECK: %[[C0:.*]] = arith.constant 0 : i32
+! CHECK: %[[C3_CAST:.*]] = fir.convert %[[C3]] : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[C1_I64:.*]] = fir.convert %c1 : (index) -> i64
+! CHECK: %[[C10_I64:.*]] = fir.convert %[[C10]] : (i32) -> i64
+! CHECK: %{{.*}} = fir.call @_FortranAAllocatableSetBounds(%[[C3_CAST]], %[[C0]], %[[C1_I64]], %[[C10_I64]]) : (!fir.ref<!fir.box<none>>, i32, i64, i64) -> none
+! CHECK: %[[C3_CAST:.*]] = fir.convert %[[C3]] : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %{{.*}} = fir.call @_FortranAAllocatableAllocate(%[[C3_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
+
+! CHECK: %[[TYPE_DESC_P2:.*]] = fir.address_of(@_QMpolyE.dt.p2) : !fir.ref<!fir.type<_QM__fortran_type_infoTderivedtype
+! CHECK: %[[C4_CAST:.*]] = fir.convert %[[C4]] : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[TYPE_DESC_P2_CAST:.*]] = fir.convert %[[TYPE_DESC_P2]] : (!fir.ref<!fir.type<_QM__fortran_type_infoTderivedtype
+! CHECK: %[[RANK:.*]] = arith.constant 1 : i32
+! CHECK: %[[C0:.*]] = arith.constant 0 : i32
+! CHECK: fir.call @_FortranAAllocatableInitDerived(%[[C4_CAST]], %[[TYPE_DESC_P2_CAST]], %[[RANK]], %[[C0]]) : (!fir.ref<!fir.box<none>>, !fir.ref<none>, i32, i32) -> none
+! CHECK: %[[C1:.*]] = arith.constant 1 : index
+! CHECK: %[[C20:.*]] = arith.constant 20 : i32
+! CHECK: %[[C0:.*]] = arith.constant 0 : i32
+! CHECK: %[[C4_CAST:.*]] = fir.convert %[[C4]] : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %[[C1_I64:.*]] = fir.convert %[[C1]] : (index) -> i64
+! CHECK: %[[C20_I64:.*]] = fir.convert %[[C20]] : (i32) -> i64
+! CHECK: %{{.*}} = fir.call @_FortranAAllocatableSetBounds(%[[C4_CAST]], %[[C0]], %[[C1_I64]], %[[C20_I64]]) : (!fir.ref<!fir.box<none>>, i32, i64, i64) -> none
+! CHECK: %[[C4_CAST:.*]] = fir.convert %[[C4]] : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMpolyTp1{a:i32,b:i32}>>>>>) -> !fir.ref<!fir.box<none>>
+! CHECK: %{{.*}} = fir.call @_FortranAAllocatableAllocate(%[[C4_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
+
+
+! Check code generation of allocate runtime calls for polymoprhic entities. This
+! is done from Fortran so we don't have a file full of auto-generated type info
+! in order to perform the checks.
+
+! LLVM-LABEL: define void @_QQmain()
+! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerived(ptr @_QFEp, ptr @_QMpolyE.dt.p1, i32 0, i32 0)
+! LLVM: %{{.*}} = call i32 @_FortranAAllocatableAllocate(ptr @_QFEp, i1 false, ptr null, ptr @_QQcl.{{.*}}, i32 {{.*}})
+! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerived(ptr @_QFEc1, ptr @_QMpolyE.dt.p1, i32 0, i32 0)
+! LLVM: %{{.*}} = call i32 @_FortranAAllocatableAllocate(ptr @_QFEc1, i1 false, ptr null, ptr @_QQcl.{{.*}}, i32 {{.*}})
+! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerived(ptr @_QFEc2, ptr @_QMpolyE.dt.p2, i32 0, i32 0)
+! LLVM: %{{.*}} = call i32 @_FortranAAllocatableAllocate(ptr @_QFEc2, i1 false, ptr null, ptr @_QQcl.{{.*}}, i32 {{.*}})
+! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerived(ptr @_QFEc3, ptr @_QMpolyE.dt.p1, i32 1, i32 0)
+! LLVM: %{{.*}} = call {} @_FortranAAllocatableSetBounds(ptr @_QFEc3, i32 0, i64 1, i64 10)
+! LLVM: %{{.*}} = call i32 @_FortranAAllocatableAllocate(ptr @_QFEc3, i1 false, ptr null, ptr @_QQcl.{{.*}}, i32 {{.*}})
+! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerived(ptr @_QFEc4, ptr @_QMpolyE.dt.p2, i32 1, i32 0)
+! LLVM: %{{.*}} = call {} @_FortranAAllocatableSetBounds(ptr @_QFEc4, i32 0, i64 1, i64 20)
+! LLVM: %{{.*}} = call i32 @_FortranAAllocatableAllocate(ptr @_QFEc4, i1 false, ptr null, ptr @_QQcl.{{.*}}, i32 {{.*}})
More information about the flang-commits
mailing list