diff --git a/flang/include/flang/Optimizer/Builder/BoxValue.h b/flang/include/flang/Optimizer/Builder/BoxValue.h --- a/flang/include/flang/Optimizer/Builder/BoxValue.h +++ b/flang/include/flang/Optimizer/Builder/BoxValue.h @@ -149,11 +149,12 @@ /// Expressions with rank > 0 have extents. They may also have lbounds that are /// not 1. -class ArrayBoxValue : public AbstractBox, public AbstractArrayBox { +class ArrayBoxValue : public PolymorphicValue, public AbstractArrayBox { public: ArrayBoxValue(mlir::Value addr, llvm::ArrayRef extents, - llvm::ArrayRef lbounds = {}) - : AbstractBox{addr}, AbstractArrayBox{extents, lbounds} {} + llvm::ArrayRef lbounds = {}, + mlir::Value tdesc = {}) + : PolymorphicValue{addr, tdesc}, AbstractArrayBox{extents, lbounds} {} ArrayBoxValue clone(mlir::Value newBase) const { return {newBase, extents, lbounds}; diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp --- a/flang/lib/Lower/ConvertExpr.cpp +++ b/flang/lib/Lower/ConvertExpr.cpp @@ -396,6 +396,12 @@ const fir::ExtendedValue &addr) { return addr.match( [](const fir::CharBoxValue &box) -> fir::ExtendedValue { return box; }, + [&](const fir::PolymorphicValue &p) -> fir::ExtendedValue { + if (fir::unwrapRefType(fir::getBase(p).getType()) + .isa()) + return p; + return builder.create(loc, fir::getBase(p)); + }, [&](const fir::UnboxedValue &v) -> fir::ExtendedValue { if (fir::unwrapRefType(fir::getBase(v).getType()) .isa()) @@ -1999,7 +2005,6 @@ mlir::Value lb = getLBound(array, subsc.index(), ty); args.push_back(builder.create(loc, ty, val, lb)); } - mlir::Value base = fir::getBase(array); mlir::Type eleTy = fir::dyn_cast_ptrOrBoxEleTy(base.getType()); if (auto classTy = eleTy.dyn_cast()) diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -484,26 +484,15 @@ } mlir::Type boxTy = fir::BoxType::get(elementType); mlir::Value tdesc; - if (isPolymorphic) { + if (isPolymorphic) boxTy = fir::ClassType::get(elementType); - - // Look for the original tdesc for the new box. - if (auto *op = itemAddr.getDefiningOp()) { - if (auto coordOp = mlir::dyn_cast(op)) { - if (fir::isPolymorphicType(coordOp.getBaseType())) { - mlir::Type resultType = coordOp.getResult().getType(); - mlir::Type tdescType = - fir::TypeDescType::get(fir::unwrapRefType(resultType)); - tdesc = create(loc, tdescType, coordOp.getRef()); - } - } - } - } - return exv.match( [&](const fir::ArrayBoxValue &box) -> mlir::Value { + mlir::Value empty; + mlir::ValueRange emptyRange; mlir::Value s = createShape(loc, exv); - return create(loc, boxTy, itemAddr, s); + return create(loc, boxTy, itemAddr, s, /*slice=*/empty, + /*typeparams=*/emptyRange, box.getTdesc()); }, [&](const fir::CharArrayBoxValue &box) -> mlir::Value { mlir::Value s = createShape(loc, exv); @@ -997,6 +986,18 @@ } if (box.isDerivedWithLenParameters()) TODO(loc, "get length parameters from derived type BoxValue"); + if (box.isPolymorphic()) { + mlir::Type tdescType = + fir::TypeDescType::get(mlir::NoneType::get(builder.getContext())); + mlir::Value tdesc = builder.create( + loc, tdescType, fir::getBase(box)); + return fir::PolymorphicValue(element, tdesc); + } + return element; + }, + [&](const fir::ArrayBoxValue &box) -> fir::ExtendedValue { + if (box.getTdesc()) + return fir::PolymorphicValue(element, box.getTdesc()); return element; }, [&](const auto &) -> fir::ExtendedValue { return element; }); diff --git a/flang/lib/Optimizer/Builder/MutableBox.cpp b/flang/lib/Optimizer/Builder/MutableBox.cpp --- a/flang/lib/Optimizer/Builder/MutableBox.cpp +++ b/flang/lib/Optimizer/Builder/MutableBox.cpp @@ -417,15 +417,17 @@ return fir::CharArrayBoxValue{addr, len, extents, lbounds}; return fir::CharBoxValue{addr, len}; } - if (rank) - return fir::ArrayBoxValue{addr, extents, lbounds}; + mlir::Value tdesc; if (box.isPolymorphic()) { auto loadedBox = builder.create(loc, box.getAddr()); mlir::Type tdescType = fir::TypeDescType::get(mlir::NoneType::get(builder.getContext())); - auto tdesc = builder.create(loc, tdescType, loadedBox); - return fir::PolymorphicValue(addr, tdesc); + tdesc = builder.create(loc, tdescType, loadedBox); } + if (rank) + return fir::ArrayBoxValue{addr, extents, lbounds, tdesc}; + if (box.isPolymorphic()) + return fir::PolymorphicValue(addr, tdesc); return addr; } diff --git a/flang/test/Lower/allocatable-polymorphic.f90 b/flang/test/Lower/allocatable-polymorphic.f90 --- a/flang/test/Lower/allocatable-polymorphic.f90 +++ b/flang/test/Lower/allocatable-polymorphic.f90 @@ -36,13 +36,20 @@ print*, 'call proc2_p2' end subroutine + +! ------------------------------------------------------------------------------ +! Test lowering of ALLOCATE statement for polymoprhic pointer +! ------------------------------------------------------------------------------ + subroutine test_pointer() class(p1), pointer :: p class(p1), pointer :: c1, c2 class(p1), pointer, dimension(:) :: c3, c4 integer :: i + print*, '---------------------------------------' print*, 'test allocation of polymorphic pointers' + print*, '---------------------------------------' allocate(p) call p%proc1() @@ -162,59 +169,65 @@ ! CHECK-LABEL: fir.do_loop ! CHECK: %[[C3_LOAD:.*]] = fir.load %[[C3_DESC]] : !fir.ref>>>> ! CHECK: %[[C3_COORD:.*]] = fir.coordinate_of %[[C3_LOAD]], %{{.*}} : (!fir.class>>>, i64) -> !fir.ref> -! CHECK: %[[C3_TDESC:.*]] = fir.box_tdesc %[[C3_LOAD]] : (!fir.class>>>) -> !fir.tdesc> -! CHECK: %[[C3_BOXED:.*]] = fir.embox %[[C3_COORD]] tdesc %[[C3_TDESC]] : (!fir.ref>, !fir.tdesc>) -> !fir.class> +! CHECK: %[[C3_TDESC:.*]] = fir.box_tdesc %[[C3_LOAD]] : (!fir.class>>>) -> !fir.tdesc +! CHECK: %[[C3_BOXED:.*]] = fir.embox %[[C3_COORD]] tdesc %[[C3_TDESC]] : (!fir.ref>, !fir.tdesc) -> !fir.class> ! CHECK: fir.dispatch "proc2"(%[[C3_BOXED]] : !fir.class>) (%[[C3_BOXED]] : !fir.class>) {pass_arg_pos = 0 : i32} ! CHECK-LABEL: fir.do_loop ! CHECK: %[[C4_LOAD:.*]] = fir.load %[[C4_DESC]] : !fir.ref>>>> ! CHECK: %[[C4_COORD:.*]] = fir.coordinate_of %[[C4_LOAD]], %{{.*}} : (!fir.class>>>, i64) -> !fir.ref> -! CHECK: %[[C4_TDESC:.*]] = fir.box_tdesc %[[C4_LOAD]] : (!fir.class>>>) -> !fir.tdesc> -! CHECK: %[[C4_BOXED:.*]] = fir.embox %[[C4_COORD]] tdesc %[[C4_TDESC]] : (!fir.ref>, !fir.tdesc>) -> !fir.class> +! CHECK: %[[C4_TDESC:.*]] = fir.box_tdesc %[[C4_LOAD]] : (!fir.class>>>) -> !fir.tdesc +! CHECK: %[[C4_BOXED:.*]] = fir.embox %[[C4_COORD]] tdesc %[[C4_TDESC]] : (!fir.ref>, !fir.tdesc) -> !fir.class> ! CHECK: fir.dispatch "proc2"(%[[C4_BOXED]] : !fir.class>) (%[[C4_BOXED]] : !fir.class>) {pass_arg_pos = 0 : i32} -end module - -program test_allocatable - use poly +! ------------------------------------------------------------------------------ +! Test lowering of ALLOCATE statement for polymoprhic allocatable +! ------------------------------------------------------------------------------ - class(p1), allocatable :: p - class(p1), allocatable :: c1, c2 - class(p1), allocatable, dimension(:) :: c3, c4 - integer :: i + subroutine test_allocatable() + class(p1), allocatable :: p + class(p1), allocatable :: c1, c2 + class(p1), allocatable, dimension(:) :: c3, c4 + integer :: i - allocate(p) ! allocate as p1 + print*, '------------------------------------------' + print*, 'test allocation of polymorphic allocatable' + print*, '------------------------------------------' - allocate(p1::c1) - allocate(p2::c2) + allocate(p) ! allocate as p1 - allocate(p1::c3(10)) - allocate(p2::c4(20)) + allocate(p1::c1) + allocate(p2::c2) - call c1%proc1() - call c2%proc1() + allocate(p1::c3(10)) + allocate(p2::c4(20)) - call c1%proc2() - call c2%proc2() + call c1%proc1() + call c2%proc1() - do i = 1, 10 - call c3(i)%proc2() - end do + call c1%proc2() + call c2%proc2() - do i = 1, 20 - call c4(i)%proc2() - end do + do i = 1, 10 + call c3(i)%proc2() + end do - call test_pointer() -end + do i = 1, 20 + call c4(i)%proc2() + end do + end subroutine -! CHECK-LABEL: func.func @_QQmain() +! CHECK-LABEL: func.func @_QMpolyPtest_allocatable() -! CHECK-DAG: %[[C1:.*]] = fir.address_of(@_QFEc1) : !fir.ref>>> -! CHECK-DAG: %[[C2:.*]] = fir.address_of(@_QFEc2) : !fir.ref>>> -! CHECK-DAG: %[[C3:.*]] = fir.address_of(@_QFEc3) : !fir.ref>>>> -! CHECK-DAG: %[[C4:.*]] = fir.address_of(@_QFEc4) : !fir.ref>>>> -! CHECK-DAG: %[[P:.*]] = fir.address_of(@_QFEp) : !fir.ref>>> +! CHECK-DAG: %[[C1:.*]] = fir.alloca !fir.class>> {bindc_name = "c1", uniq_name = "_QMpolyFtest_allocatableEc1"} +! CHECK-DAG: %[[C1_ADDR:.*]] = fir.alloca !fir.heap> {uniq_name = "_QMpolyFtest_allocatableEc1.addr"} +! CHECK-DAG: %[[C2:.*]] = fir.alloca !fir.class>> {bindc_name = "c2", uniq_name = "_QMpolyFtest_allocatableEc2"} +! CHECK-DAG: %[[C2_ADDR:.*]] = fir.alloca !fir.heap> {uniq_name = "_QMpolyFtest_allocatableEc2.addr"} +! CHECK-DAG: %[[C3:.*]] = fir.alloca !fir.class>>> {bindc_name = "c3", uniq_name = "_QMpolyFtest_allocatableEc3"} +! CHECK-DAG: %[[C3_ADDR:.*]] = fir.alloca !fir.heap>> {uniq_name = "_QMpolyFtest_allocatableEc3.addr"} +! CHECK-DAG: %[[C4:.*]] = fir.alloca !fir.class>>> {bindc_name = "c4", uniq_name = "_QMpolyFtest_allocatableEc4"} +! CHECK-DAG: %[[C4_ADDR:.*]] = fir.alloca !fir.heap>> {uniq_name = "_QMpolyFtest_allocatableEc4.addr"} +! CHECK-DAG: %[[P:.*]] = fir.alloca !fir.class>> {bindc_name = "p", uniq_name = "_QMpolyFtest_allocatableEp"} ! CHECK: %[[TYPE_DESC_P1:.*]] = fir.address_of(@_QMpolyE.dt.p1) : !fir.ref>>>) -> !fir.ref> @@ -274,34 +287,48 @@ ! CHECK: %[[C4_CAST:.*]] = fir.convert %[[C4]] : (!fir.ref>>>>) -> !fir.ref> ! CHECK: %{{.*}} = fir.call @_FortranAAllocatableAllocate(%[[C4_CAST]], %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.ref>, i1, !fir.box, !fir.ref, i32) -> i32 -! Check fir.rebox for fir.class +! CHECK: %[[C1_ADDR_LOAD:.*]] = fir.load %[[C1_ADDR]] : !fir.ref>> ! CHECK: %[[C1_LOAD:.*]] = fir.load %[[C1]] : !fir.ref>>> -! CHECK: %[[C1_REBOX:.*]] = fir.rebox %[[C1_LOAD]] : (!fir.class>>) -> !fir.class> -! CHECK: fir.dispatch "proc2"(%[[C1_REBOX]] : !fir.class>) (%[[C1_REBOX]] : !fir.class>) {pass_arg_pos = 0 : i32} +! CHECK: %[[C1_TDESC:.*]] = fir.box_tdesc %[[C1_LOAD]] : (!fir.class>>) -> !fir.tdesc +! CHECK: %[[C1_EMBOX:.*]] = fir.embox %[[C1_ADDR_LOAD]] tdesc %[[C1_TDESC]] : (!fir.heap>, !fir.tdesc) -> !fir.class> +! CHECK: fir.dispatch "proc2"(%[[C1_EMBOX]] : !fir.class>) (%[[C1_EMBOX]] : !fir.class>) {pass_arg_pos = 0 : i32} +! CHECK: %[[C2_ADDR_LOAD:.*]] = fir.load %[[C2_ADDR]] : !fir.ref>> ! CHECK: %[[C2_LOAD:.*]] = fir.load %[[C2]] : !fir.ref>>> -! CHECK: %[[C2_REBOX:.*]] = fir.rebox %[[C2_LOAD]] : (!fir.class>>) -> !fir.class> -! CHECK: fir.dispatch "proc2"(%[[C2_REBOX]] : !fir.class>) (%[[C2_REBOX]] : !fir.class>) {pass_arg_pos = 0 : i32} +! CHECK: %[[C2_TDESC:.*]] = fir.box_tdesc %[[C2_LOAD]] : (!fir.class>>) -> !fir.tdesc +! CHECK: %[[C2_EMBOX:.*]] = fir.embox %[[C2_ADDR_LOAD]] tdesc %[[C2_TDESC]] : (!fir.heap>, !fir.tdesc) -> !fir.class> +! CHECK: fir.dispatch "proc2"(%[[C2_EMBOX]] : !fir.class>) (%[[C2_EMBOX]] : !fir.class>) {pass_arg_pos = 0 : i32} ! CHECK-LABEL: %{{.*}} = fir.do_loop +! CHECK: %[[C3_ADDR_LOAD:.*]] = fir.load %[[C3_ADDR]] : !fir.ref>>> ! CHECK: %[[C3_LOAD:.*]] = fir.load %[[C3]] : !fir.ref>>>> -! CHECK: %[[C3_COORD:.*]] = fir.coordinate_of %[[C3_LOAD]], %{{.*}} : (!fir.class>>>, i64) -> !fir.ref> -! CHECK: %[[C3_TDESC:.*]] = fir.box_tdesc %[[C3_LOAD]] : (!fir.class>>>) -> !fir.tdesc> -! CHECK: %[[C3_EMBOX:.*]] = fir.embox %[[C3_COORD]] tdesc %[[C3_TDESC]] : (!fir.ref>, !fir.tdesc>) -> !fir.class> +! CHECK: %[[C3_TDESC:.*]] = fir.box_tdesc %[[C3_LOAD]] : (!fir.class>>>) -> !fir.tdesc +! CHECK: %[[C3_COORD:.*]] = fir.coordinate_of %[[C3_ADDR_LOAD]], %{{.*}} : (!fir.heap>>, i64) -> !fir.ref> +! CHECK: %[[C3_EMBOX:.*]] = fir.embox %[[C3_COORD]] tdesc %[[C3_TDESC]] : (!fir.ref>, !fir.tdesc) -> !fir.class> ! CHECK: fir.dispatch "proc2"(%[[C3_EMBOX]] : !fir.class>) (%[[C3_EMBOX]] : !fir.class>) {pass_arg_pos = 0 : i32} ! CHECK-LABEL: %{{.*}} = fir.do_loop +! CHECK: %[[C4_ADDR_LOAD:.*]] = fir.load %[[C4_ADDR]] : !fir.ref>>> ! CHECK: %[[C4_LOAD:.*]] = fir.load %[[C4]] : !fir.ref>>>> -! CHECK: %[[C4_COORD:.*]] = fir.coordinate_of %[[C4_LOAD]], %{{.*}} : (!fir.class>>>, i64) -> !fir.ref> -! CHECK: %[[C4_TDESC:.*]] = fir.box_tdesc %[[C4_LOAD]] : (!fir.class>>>) -> !fir.tdesc> -! CHECK: %[[C4_EMBOX:.*]] = fir.embox %[[C4_COORD]] tdesc %[[C4_TDESC]] : (!fir.ref>, !fir.tdesc>) -> !fir.class> +! CHECK: %[[C4_TDESC:.*]] = fir.box_tdesc %[[C4_LOAD]] : (!fir.class>>>) -> !fir.tdesc +! CHECK: %[[C4_COORD:.*]] = fir.coordinate_of %[[C4_ADDR_LOAD]], %{{.*}} : (!fir.heap>>, i64) -> !fir.ref> +! CHECK: %[[C4_EMBOX:.*]] = fir.embox %[[C4_COORD]] tdesc %[[C4_TDESC]] : (!fir.ref>, !fir.tdesc) -> !fir.class> ! CHECK: fir.dispatch "proc2"(%[[C4_EMBOX]] : !fir.class>) (%[[C4_EMBOX]] : !fir.class>) {pass_arg_pos = 0 : i32} +end module + +program test_alloc + use poly + + call test_allocatable() + call test_pointer() +end + ! 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-LABEL: define void @_QMpolyPtest_allocatable() ! LLVM: %[[TMP1:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } ! LLVM: %[[TMP2:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] } ! LLVM: %[[TMP3:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } @@ -311,48 +338,52 @@ ! LLVM: %[[TMP7:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } ! LLVM: %[[TMP8:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } -! 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 {{.*}}) +! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerived(ptr %{{.*}}, ptr @_QMpolyE.dt.p1, i32 0, i32 0) +! LLVM: %{{.*}} = call i32 @_FortranAAllocatableAllocate(ptr %{{.*}}, i1 false, ptr null, ptr @_QQcl.{{.*}}, i32 {{.*}}) +! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerived(ptr %{{.*}}, ptr @_QMpolyE.dt.p1, i32 0, i32 0) +! LLVM: %{{.*}} = call i32 @_FortranAAllocatableAllocate(ptr %{{.*}}, i1 false, ptr null, ptr @_QQcl.{{.*}}, i32 {{.*}}) +! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerived(ptr %{{.*}}, ptr @_QMpolyE.dt.p2, i32 0, i32 0) +! LLVM: %{{.*}} = call i32 @_FortranAAllocatableAllocate(ptr %{{.*}}, i1 false, ptr null, ptr @_QQcl.{{.*}}, i32 {{.*}}) +! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerived(ptr %{{.*}}, ptr @_QMpolyE.dt.p1, i32 1, i32 0) +! LLVM: %{{.*}} = call {} @_FortranAAllocatableSetBounds(ptr %{{.*}}, i32 0, i64 1, i64 10) +! LLVM: %{{.*}} = call i32 @_FortranAAllocatableAllocate(ptr %{{.*}}, i1 false, ptr null, ptr @_QQcl.{{.*}}, i32 {{.*}}) +! LLVM: %{{.*}} = call {} @_FortranAAllocatableInitDerived(ptr %{{.*}}, ptr @_QMpolyE.dt.p2, i32 1, i32 0) +! LLVM: %{{.*}} = call {} @_FortranAAllocatableSetBounds(ptr %{{.*}}, i32 0, i64 1, i64 20) +! LLVM: %{{.*}} = call i32 @_FortranAAllocatableAllocate(ptr %{{.*}}, i1 false, ptr null, ptr @_QQcl.{{.*}}, i32 {{.*}}) ! LLVM-COUNT-2: call void %{{.*}}() -! LLVM: %[[C1_LOAD:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr @_QFEc1 +! LLVM: %[[C1_LOAD:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %{{.*}} ! LLVM: store { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[C1_LOAD]], ptr %[[TMP8]] ! LLVM: %[[GEP_TDESC_C1:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[TMP8]], i32 0, i32 7 ! LLVM: %[[TDESC_C1:.*]] = load ptr, ptr %[[GEP_TDESC_C1]] ! LLVM: %[[BOX0:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } { ptr undef, i64 ptrtoint (ptr getelementptr (%_QMpolyTp1, ptr null, i32 1) to i64), i32 20180515, i8 0, i8 42, i8 0, i8 1, ptr undef, [1 x i64] undef }, ptr %[[TDESC_C1]], 7 ! LLVM: %[[BOX1:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[BOX0]], ptr %{{.*}}, 0 ! LLVM: store { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[BOX1]], ptr %[[TMP7]] +! LLVM: call void %{{.*}}(ptr %[[TMP7]]) -! LLVM: %[[LOAD_C2:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr @_QFEc2 +! LLVM: %[[LOAD_C2:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %{{.*}} ! LLVM: store { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[LOAD_C2]], ptr %[[TMP6]] ! LLVM: %[[GEP_TDESC_C2:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, ptr %[[TMP6]], i32 0, i32 7 ! LLVM: %[[TDESC_C2:.*]] = load ptr, ptr %[[GEP_TDESC_C2]] ! LLVM: %[[BOX0:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } { ptr undef, i64 ptrtoint (ptr getelementptr (%_QMpolyTp1, ptr null, i32 1) to i64), i32 20180515, i8 0, i8 42, i8 0, i8 1, ptr undef, [1 x i64] undef }, ptr %[[TDESC_C2]], 7 ! LLVM: %[[BOX1:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[BOX0]], ptr %{{.*}}, 0 ! LLVM: store { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[BOX1]], ptr %[[TMP5]] +! LLVM: call void %{{.*}}(ptr %[[TMP5]]) -! LLVM: %[[C3_LOAD:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr @_QFEc3 +! LLVM: %[[C3_LOAD:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %{{.*}} ! LLVM: store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] } %[[C3_LOAD]], ptr %[[TMP2]] ! LLVM: %[[GEP_TDESC_C3:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[TMP2]], i32 0, i32 8 ! LLVM: %[[TDESC_C3:.*]] = load ptr, ptr %[[GEP_TDESC_C3]] ! LLVM: %[[BOX0:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } { ptr undef, i64 ptrtoint (ptr getelementptr (%_QMpolyTp1, ptr null, i32 1) to i64), i32 20180515, i8 0, i8 42, i8 0, i8 1, ptr undef, [1 x i64] undef }, ptr %[[TDESC_C3]], 7 ! LLVM: %[[BOX1:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[BOX0]], ptr %{{.*}}, 0 ! LLVM: store { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[BOX1]], ptr %[[TMP1]] +! LLVM: call void %{{.*}}(ptr %[[TMP1]]) -! LLVM: %[[C4_LOAD:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr @_QFEc4 +! LLVM: %[[C4_LOAD:.*]] = load { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %{{.*}} ! LLVM: store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] } %[[C4_LOAD]], ptr %[[TMP4]] ! LLVM: %[[GEP_TDESC_C4:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, ptr %[[TMP4]], i32 0, i32 8 ! LLVM: %[[TDESC_C4:.*]] = load ptr, ptr %[[GEP_TDESC_C4]] ! LLVM: %[[BOX0:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } { ptr undef, i64 ptrtoint (ptr getelementptr (%_QMpolyTp1, ptr null, i32 1) to i64), i32 20180515, i8 0, i8 42, i8 0, i8 1, ptr undef, [1 x i64] undef }, ptr %[[TDESC_C4]], 7 ! LLVM: %[[BOX1:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[BOX0]], ptr %{{.*}}, 0 ! LLVM: store { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] } %[[BOX1]], ptr %[[TMP3]] +! LLVM: call void %{{.*}}(ptr %[[TMP3]]) diff --git a/flang/test/Lower/dispatch.f90 b/flang/test/Lower/dispatch.f90 --- a/flang/test/Lower/dispatch.f90 +++ b/flang/test/Lower/dispatch.f90 @@ -203,8 +203,8 @@ ! CHECK-SAME: %[[ARG1:.*]]: !fir.ref>> {fir.bindc_name = "t"}) { ! CHECK: fir.do_loop {{.*}} { ! CHECK: %[[COORD:.*]] = fir.coordinate_of %[[ARG0]], %{{.*}} : (!fir.class>>, i64) -> !fir.ref> -! CHECK: %[[TDESC:.*]] = fir.box_tdesc %[[ARG0]] : (!fir.class>>) -> !fir.tdesc> -! CHECK: %[[CLASS_BOX:.*]] = fir.embox %[[COORD]] tdesc %[[TDESC]] : (!fir.ref>, !fir.tdesc>) -> !fir.class> +! CHECK: %[[TDESC:.*]] = fir.box_tdesc %[[ARG0]] : (!fir.class>>) -> !fir.tdesc +! CHECK: %[[CLASS_BOX:.*]] = fir.embox %[[COORD]] tdesc %[[TDESC]] : (!fir.ref>, !fir.tdesc) -> !fir.class> ! CHECK: fir.dispatch "tbp_pass"(%[[CLASS_BOX]] : !fir.class>) (%[[CLASS_BOX]] : !fir.class>) {pass_arg_pos = 0 : i32} ! CHECK: fir.do_loop {{.*}} { @@ -230,8 +230,8 @@ ! CHECK-SAME: %[[ARG1:.*]]: !fir.box>> {fir.bindc_name = "t"}) { ! CHECK: %{{.*}} = fir.do_loop {{.*}} { ! CHECK: %[[COORD:.*]] = fir.coordinate_of %[[ARG0]], %{{.*}} : (!fir.class>>, i64) -> !fir.ref> -! CHECK: %[[TDESC:.*]] = fir.box_tdesc %[[ARG0]] : (!fir.class>>) -> !fir.tdesc> -! CHECK: %[[CLASS_BOX:.*]] = fir.embox %[[COORD]] tdesc %[[TDESC]] : (!fir.ref>, !fir.tdesc>) -> !fir.class> +! CHECK: %[[TDESC:.*]] = fir.box_tdesc %[[ARG0]] : (!fir.class>>) -> !fir.tdesc +! CHECK: %[[CLASS_BOX:.*]] = fir.embox %[[COORD]] tdesc %[[TDESC]] : (!fir.ref>, !fir.tdesc) -> !fir.class> ! CHECK: fir.dispatch "tbp_pass"(%[[CLASS_BOX]] : !fir.class>) (%[[CLASS_BOX]] : !fir.class>) {pass_arg_pos = 0 : i32} ! CHECK: %{{.*}} = fir.do_loop {{.*}} { @@ -261,8 +261,8 @@ ! CHECK: %[[C0:.*]] = arith.constant 0 : index ! CHECK: %[[BOX_DIMS_ARG0:.*]]:3 = fir.box_dims %[[LOAD_ARG0]], %[[C0]] : (!fir.class>>>, index) -> (index, index, index) ! CHECK: %[[COORD:.*]] = fir.coordinate_of %[[LOAD_ARG0]], %{{.*}} : (!fir.class>>>, i64) -> !fir.ref> -! CHECK: %[[TDESC_ARG0:.*]] = fir.box_tdesc %[[LOAD_ARG0]] : (!fir.class>>>) -> !fir.tdesc> -! CHECK: %[[CLASS_BOX:.*]] = fir.embox %[[COORD]] tdesc %[[TDESC_ARG0]] : (!fir.ref>, !fir.tdesc>) -> !fir.class> +! CHECK: %[[TDESC_ARG0:.*]] = fir.box_tdesc %[[LOAD_ARG0]] : (!fir.class>>>) -> !fir.tdesc +! CHECK: %[[CLASS_BOX:.*]] = fir.embox %[[COORD]] tdesc %[[TDESC_ARG0]] : (!fir.ref>, !fir.tdesc) -> !fir.class> ! CHECK: fir.dispatch "tbp_pass"(%[[CLASS_BOX]] : !fir.class>) (%[[CLASS_BOX]] : !fir.class>) {pass_arg_pos = 0 : i32} ! CHECK: %{{.*}} = fir.do_loop {{.*}} { @@ -295,8 +295,8 @@ ! CHECK: %[[C0:.*]] = arith.constant 0 : index ! CHECK: %[[BOX_DIMS_ARG0]]:3 = fir.box_dims %[[LOAD_ARG0]], %[[C0]] : (!fir.class>>>, index) -> (index, index, index) ! CHECK: %[[COORD:.*]] = fir.coordinate_of %[[LOAD_ARG0]], %{{.*}} : (!fir.class>>>, i64) -> !fir.ref> -! CHECK: %[[TDESC_ARG0:.*]] = fir.box_tdesc %[[LOAD_ARG0]] : (!fir.class>>>) -> !fir.tdesc> -! CHECK: %[[CLASS_BOX]] = fir.embox %[[COORD]] tdesc %[[TDESC_ARG0]] : (!fir.ref>, !fir.tdesc>) -> !fir.class> +! CHECK: %[[TDESC_ARG0:.*]] = fir.box_tdesc %[[LOAD_ARG0]] : (!fir.class>>>) -> !fir.tdesc +! CHECK: %[[CLASS_BOX]] = fir.embox %[[COORD]] tdesc %[[TDESC_ARG0]] : (!fir.ref>, !fir.tdesc) -> !fir.class> ! CHECK: fir.dispatch "tbp_pass"(%[[CLASS_BOX]] : !fir.class>) (%[[CLASS_BOX]] : !fir.class>) {pass_arg_pos = 0 : i32} ! CHECK: %{{.*}} = fir.do_loop {{.*}} { @@ -322,11 +322,11 @@ ! CHECK-SAME: %[[ARG1:.*]]: !fir.class>> {fir.bindc_name = "o"}) { ! CHECK: %{{.*}} = fir.do_loop {{.*}} { ! CHECK: %[[COORD1:.*]] = fir.coordinate_of %[[ARG0]], %{{.*}} : (!fir.class>>, i64) -> !fir.ref> -! CHECK: %[[TDESC1:.*]] = fir.box_tdesc %[[ARG0]] : (!fir.class>>) -> !fir.tdesc> -! CHECK: %[[CLASS1:.*]] = fir.embox %[[COORD1]] tdesc %[[TDESC1]] : (!fir.ref>, !fir.tdesc>) -> !fir.class> +! CHECK: %[[TDESC1:.*]] = fir.box_tdesc %[[ARG0]] : (!fir.class>>) -> !fir.tdesc +! CHECK: %[[CLASS1:.*]] = fir.embox %[[COORD1]] tdesc %[[TDESC1]] : (!fir.ref>, !fir.tdesc) -> !fir.class> ! CHECK: %[[COORD2:.*]] = fir.coordinate_of %[[ARG1]], %{{.*}} : (!fir.class>>, i64) -> !fir.ref> -! CHECK: %[[TDESC2:.*]] = fir.box_tdesc %[[ARG1]] : (!fir.class>>) -> !fir.tdesc> -! CHECK: %[[CLASS2:.*]] = fir.embox %[[COORD2]] tdesc %[[TDESC2]] : (!fir.ref>, !fir.tdesc>) -> !fir.class> +! CHECK: %[[TDESC2:.*]] = fir.box_tdesc %[[ARG1]] : (!fir.class>>) -> !fir.tdesc +! CHECK: %[[CLASS2:.*]] = fir.embox %[[COORD2]] tdesc %[[TDESC2]] : (!fir.ref>, !fir.tdesc) -> !fir.class> ! CHECK: fir.dispatch "pass_with_class_arg"(%[[CLASS1]] : !fir.class>) (%[[CLASS1]], %[[CLASS2]] : !fir.class>, !fir.class>) {pass_arg_pos = 0 : i32} ! ------------------------------------------------------------------------------