blob: 987e36f9728f1ffb83f312ce444c098942d96ab5 [file] [edit]
! Test lowering of structure constructors
! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s
module m_struct_ctor
implicit none
type t_simple
real :: x
end type
type t_char_scalar
real :: x
character(3) :: c
end type
type t_array
real :: x
integer :: i(5)
end type
type t_char_array
real :: x
character(3) :: c(5)
end type
type t_ptr
real :: x
integer, pointer :: p(:,:)
end type
type t_nested
real :: x
type(t_array) :: dt
end type
contains
! CHECK-LABEL: func @_QMm_struct_ctorPtest_simple(
! CHECK-SAME: %[[arg0:.*]]: !fir.ref<f32>{{.*}})
subroutine test_simple(x)
real :: x
! CHECK: %[[tmp:.*]] = fir.alloca !fir.type<_QMm_struct_ctorTt_simple{x:f32}>
! CHECK: %[[xdecl:.*]]:2 = hlfir.declare %[[arg0]]{{.*}}{uniq_name = "_QMm_struct_ctorFtest_simpleEx"}
! CHECK: %[[tmpdecl:.*]]:2 = hlfir.declare %[[tmp]] {uniq_name = "ctor.temp"}
! CHECK: fir.call @_FortranAInitialize(
! CHECK: %[[xcoor:.*]] = hlfir.designate %[[tmpdecl]]#0{"x"}
! CHECK: %[[val:.*]] = fir.load %[[xdecl]]#0 : !fir.ref<f32>
! CHECK: hlfir.assign %[[val]] to %[[xcoor]] temporary_lhs : f32, !fir.ref<f32>
call print_simple(t_simple(x=x))
end subroutine
! CHECK-LABEL: func @_QMm_struct_ctorPtest_char_scalar(
! CHECK-SAME: %[[arg0:.*]]: !fir.ref<f32>{{.*}})
subroutine test_char_scalar(x)
! CHECK: %[[tmp:.*]] = fir.alloca !fir.type<_QMm_struct_ctorTt_char_scalar{x:f32,c:!fir.char<1,3>}>
! CHECK: %[[xdecl:.*]]:2 = hlfir.declare %[[arg0]]{{.*}}{uniq_name = "_QMm_struct_ctorFtest_char_scalarEx"}
! CHECK: %[[tmpdecl:.*]]:2 = hlfir.declare %[[tmp]] {uniq_name = "ctor.temp"}
! CHECK: fir.call @_FortranAInitialize(
! CHECK: %[[xcoor:.*]] = hlfir.designate %[[tmpdecl]]#0{"x"}
! CHECK: %[[val:.*]] = fir.load %[[xdecl]]#0 : !fir.ref<f32>
! CHECK: hlfir.assign %[[val]] to %[[xcoor]] temporary_lhs : f32, !fir.ref<f32>
! CHECK: %[[ccoor:.*]] = hlfir.designate %[[tmpdecl]]#0{"c"}{{.*}} typeparams %{{.*}} : (!fir.ref<!fir.type<_QMm_struct_ctorTt_char_scalar{x:f32,c:!fir.char<1,3>}>>, index) -> !fir.ref<!fir.char<1,3>>
! CHECK: %[[cst:.*]] = fir.address_of(@_QQ{{.*}}) : !fir.ref<!fir.char<1,3>>
! CHECK: %[[cstdecl:.*]]:2 = hlfir.declare %[[cst]] typeparams %{{.*}} {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQ{{.*}}"} : (!fir.ref<!fir.char<1,3>>, index) -> (!fir.ref<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>>)
! CHECK: hlfir.assign %[[cstdecl]]#0 to %[[ccoor]] temporary_lhs : !fir.ref<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>>
real :: x
call print_char_scalar(t_char_scalar(x=x, c="abc"))
end subroutine
! CHECK-LABEL: func @_QMm_struct_ctorPtest_simple_array(
! CHECK-SAME: %[[arg0:.*]]: !fir.ref<f32>{{.*}}, %[[arg1:.*]]: !fir.ref<!fir.array<5xi32>>{{.*}})
subroutine test_simple_array(x, j)
real :: x
integer :: j(5)
call print_simple_array(t_array(x=x, i=2*j))
! CHECK: %[[tmp:.*]] = fir.alloca !fir.type<_QMm_struct_ctorTt_array{x:f32,i:!fir.array<5xi32>}>
! CHECK: %[[shape:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
! CHECK: %[[jdecl:.*]]:2 = hlfir.declare %[[arg1]](%[[shape]]){{.*}}{uniq_name = "_QMm_struct_ctorFtest_simple_arrayEj"}
! CHECK: %[[xdecl:.*]]:2 = hlfir.declare %[[arg0]]{{.*}}{uniq_name = "_QMm_struct_ctorFtest_simple_arrayEx"}
! CHECK: %[[tmpdecl:.*]]:2 = hlfir.declare %[[tmp]] {uniq_name = "ctor.temp"}
! CHECK: fir.call @_FortranAInitialize(
! CHECK: %[[xcoor:.*]] = hlfir.designate %[[tmpdecl]]#0{"x"}
! CHECK: %[[xval:.*]] = fir.load %[[xdecl]]#0 : !fir.ref<f32>
! CHECK: hlfir.assign %[[xval]] to %[[xcoor]] temporary_lhs : f32, !fir.ref<f32>
! CHECK: %[[icoor:.*]] = hlfir.designate %[[tmpdecl]]#0{"i"}
! CHECK: %[[c2:.*]] = arith.constant 2 : i32
! CHECK: %[[elem:.*]] = hlfir.elemental %[[shape]] unordered : (!fir.shape<1>) -> !hlfir.expr<5xi32> {
! CHECK: %[[idx:.*]] = hlfir.designate %[[jdecl]]#0 (%{{.*}}) : (!fir.ref<!fir.array<5xi32>>, index) -> !fir.ref<i32>
! CHECK: %[[jval:.*]] = fir.load %[[idx]] : !fir.ref<i32>
! CHECK: %[[mul:.*]] = arith.muli %[[c2]], %[[jval]] : i32
! CHECK: hlfir.yield_element %[[mul]] : i32
! CHECK: }
! CHECK: hlfir.assign %[[elem]] to %[[icoor]] temporary_lhs : !hlfir.expr<5xi32>, !fir.ref<!fir.array<5xi32>>
! CHECK: hlfir.destroy %[[elem]] : !hlfir.expr<5xi32>
end subroutine
! CHECK-LABEL: func @_QMm_struct_ctorPtest_char_array(
! CHECK-SAME: %[[arg0:.*]]: !fir.ref<f32>{{.*}}, %[[arg1:.*]]: !fir.boxchar<1>{{.*}}) {
subroutine test_char_array(x, c1)
! CHECK: %[[tmp:.*]] = fir.alloca !fir.type<_QMm_struct_ctorTt_char_array{x:f32,c:!fir.array<5x!fir.char<1,3>>}>
! CHECK: %[[unbox:.*]]:2 = fir.unboxchar %[[arg1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
! CHECK: %[[c1ref:.*]] = fir.convert %[[unbox]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<5x!fir.char<1,3>>>
! CHECK: %[[c1decl:.*]]:2 = hlfir.declare %[[c1ref]](%{{.*}}) typeparams %{{.*}}{{.*}}{uniq_name = "_QMm_struct_ctorFtest_char_arrayEc1"}
! CHECK: %[[xdecl:.*]]:2 = hlfir.declare %[[arg0]]{{.*}}{uniq_name = "_QMm_struct_ctorFtest_char_arrayEx"}
! CHECK: %[[tmpdecl:.*]]:2 = hlfir.declare %[[tmp]] {uniq_name = "ctor.temp"}
! CHECK: fir.call @_FortranAInitialize(
! CHECK: %[[xcoor:.*]] = hlfir.designate %[[tmpdecl]]#0{"x"}
! CHECK: hlfir.assign %{{.*}} to %[[xcoor]] temporary_lhs : f32, !fir.ref<f32>
! CHECK: %[[ccoor:.*]] = hlfir.designate %[[tmpdecl]]#0{"c"}
! CHECK: %[[elem:.*]] = hlfir.elemental %{{.*}} typeparams %{{.*}} unordered : (!fir.shape<1>, i64) -> !hlfir.expr<5x!fir.char<1,?>> {
! CHECK: %[[carg:.*]] = hlfir.designate %[[c1decl]]#0 (%{{.*}}) typeparams %{{.*}} : (!fir.ref<!fir.array<5x!fir.char<1,3>>>, index, index) -> !fir.ref<!fir.char<1,3>>
! CHECK: %[[setlen:.*]] = hlfir.set_length %[[carg]] len %{{.*}} : (!fir.ref<!fir.char<1,3>>, i64) -> !hlfir.expr<!fir.char<1,3>>
! CHECK: hlfir.yield_element %[[setlen]] : !hlfir.expr<!fir.char<1,3>>
! CHECK: }
! CHECK: hlfir.assign %[[elem]] to %[[ccoor]] temporary_lhs : !hlfir.expr<5x!fir.char<1,?>>, !fir.ref<!fir.array<5x!fir.char<1,3>>>
! CHECK: fir.call @_QMm_struct_ctorPprint_char_array(%[[tmpdecl]]#0)
real :: x
character(3) :: c1(5)
call print_char_array(t_char_array(x=x, c=c1))
! CHECK: return
! CHECK: }
end subroutine
! CHECK-LABEL: func @_QMm_struct_ctorPtest_ptr(
! CHECK-SAME: %[[arg0:.*]]: !fir.ref<f32>{{.*}}, %[[arg1:.*]]: !fir.box<!fir.array<?x?xi32>> {{{.*}}, fir.target}) {
! CHECK: %[[tmp:.*]] = fir.alloca !fir.type<_QMm_struct_ctorTt_ptr{x:f32,p:!fir.box<!fir.ptr<!fir.array<?x?xi32>>>}>
! CHECK: %[[adecl:.*]]:2 = hlfir.declare %[[arg1]]{{.*}}{fortran_attrs = #fir.var_attrs<target>, uniq_name = "_QMm_struct_ctorFtest_ptrEa"}
! CHECK: %[[xdecl:.*]]:2 = hlfir.declare %[[arg0]]{{.*}}{uniq_name = "_QMm_struct_ctorFtest_ptrEx"}
! CHECK: %[[tmpdecl:.*]]:2 = hlfir.declare %[[tmp]] {uniq_name = "ctor.temp"}
! CHECK: fir.call @_FortranAInitialize(
! CHECK: %[[xcoor:.*]] = hlfir.designate %[[tmpdecl]]#0{"x"}
! CHECK: hlfir.assign %{{.*}} to %[[xcoor]] temporary_lhs : f32, !fir.ref<f32>
! CHECK: %[[pcoor:.*]] = hlfir.designate %[[tmpdecl]]#0{"p"}{{.*}}{fortran_attrs = #fir.var_attrs<pointer>}
! CHECK: %[[slice:.*]] = hlfir.designate %[[adecl]]#0 (%{{.*}}:%{{.*}}:%{{.*}}, %{{.*}}:%{{.*}}:%{{.*}}) shape %{{.*}} : (!fir.box<!fir.array<?x?xi32>>, index, index, index, index, index, index, !fir.shape<2>) -> !fir.box<!fir.array<2x3xi32>>
! CHECK: %[[rebox:.*]] = fir.rebox %[[slice]] : (!fir.box<!fir.array<2x3xi32>>) -> !fir.box<!fir.ptr<!fir.array<?x?xi32>>>
! CHECK: fir.store %[[rebox]] to %[[pcoor]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xi32>>>>
! CHECK: fir.call @_QMm_struct_ctorPprint_ptr(%[[tmpdecl]]#0)
! CHECK: return
! CHECK: }
subroutine test_ptr(x, a)
real :: x
integer, target :: a(:, :)
call print_ptr(t_ptr(x=x, p=a(1:4:2, 1:3:1)))
end subroutine
! CHECK-LABEL: func @_QMm_struct_ctorPtest_nested(
! CHECK-SAME: %[[arg0:.*]]: !fir.ref<f32>{{.*}}, %[[arg1:.*]]: !fir.ref<!fir.type<_QMm_struct_ctorTt_array{x:f32,i:!fir.array<5xi32>}>>
subroutine test_nested(x, d)
real :: x
type(t_array) :: d
! CHECK: %[[tmp:.*]] = fir.alloca !fir.type<_QMm_struct_ctorTt_nested{x:f32,dt:!fir.type<_QMm_struct_ctorTt_array{x:f32,i:!fir.array<5xi32>}>}>
! CHECK: %[[ddecl:.*]]:2 = hlfir.declare %[[arg1]]{{.*}}{uniq_name = "_QMm_struct_ctorFtest_nestedEd"}
! CHECK: %[[xdecl:.*]]:2 = hlfir.declare %[[arg0]]{{.*}}{uniq_name = "_QMm_struct_ctorFtest_nestedEx"}
! CHECK: %[[tmpdecl:.*]]:2 = hlfir.declare %[[tmp]] {uniq_name = "ctor.temp"}
! CHECK: fir.call @_FortranAInitialize(
! CHECK: %[[xcoor:.*]] = hlfir.designate %[[tmpdecl]]#0{"x"}
! CHECK: %[[xval:.*]] = fir.load %[[xdecl]]#0 : !fir.ref<f32>
! CHECK: hlfir.assign %[[xval]] to %[[xcoor]] temporary_lhs : f32, !fir.ref<f32>
! CHECK: %[[dtcoor:.*]] = hlfir.designate %[[tmpdecl]]#0{"dt"}
! CHECK: hlfir.assign %[[ddecl]]#0 to %[[dtcoor]] temporary_lhs : !fir.ref<!fir.type<_QMm_struct_ctorTt_array{x:f32,i:!fir.array<5xi32>}>>, !fir.ref<!fir.type<_QMm_struct_ctorTt_array{x:f32,i:!fir.array<5xi32>}>>
call print_nested(t_nested(x=x, dt=d))
end subroutine
subroutine print_simple(t)
type(t_simple) :: t
print *, t%x
end subroutine
subroutine print_char_scalar(t)
type(t_char_scalar) :: t
print *, t%x, t%c
end subroutine
subroutine print_simple_array(t)
type(t_array) :: t
print *, t%x, t%i
end subroutine
subroutine print_char_array(t)
type(t_char_array) :: t
print *, t%x, t%c
end subroutine
subroutine print_ptr(t)
type(t_ptr) :: t
print *, t%x, t%p
end subroutine
subroutine print_nested(t)
type(t_nested) :: t
print *, t%x, t%dt%x, t%dt%i
end subroutine
end module
use m_struct_ctor
integer, target :: i(4,3) = reshape([1,2,3,4,5,6,7,8,9,10,11,12], [4,3])
call test_simple(42.)
call test_char_scalar(42.)
call test_simple_array(42., [1,2,3,4,5])
call test_char_array(42., ["abc", "def", "geh", "ijk", "lmn"])
call test_ptr(42., i)
call test_nested(42., t_array(x=43., i=[5,6,7,8,9]))
end
! CHECK-LABEL: func.func @_QPtest_parent_component1() {
! CHECK: %[[ro:.*]] = fir.address_of(@_QQro._QFtest_parent_component1Tmid.{{[0-9]+}}) : !fir.ref<!fir.type<_QFtest_parent_component1Tmid{base:!fir.type<_QFtest_parent_component1Tbase{x:i32,y:!fir.array<2xi32>}>,mask:!fir.logical<4>}>>
! CHECK: %[[rodecl:.*]]:2 = hlfir.declare %[[ro]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro._QFtest_parent_component1Tmid.{{[0-9]+}}"}
! CHECK: %[[expr:.*]] = hlfir.as_expr %[[rodecl]]#0 : (!fir.ref<!fir.type<_QFtest_parent_component1Tmid{base:!fir.type<_QFtest_parent_component1Tbase{x:i32,y:!fir.array<2xi32>}>,mask:!fir.logical<4>}>>) -> !hlfir.expr<!fir.type<_QFtest_parent_component1Tmid{base:!fir.type<_QFtest_parent_component1Tbase{x:i32,y:!fir.array<2xi32>}>,mask:!fir.logical<4>}>>
! CHECK: %[[assoc:.*]]:3 = hlfir.associate %[[expr]] {adapt.valuebyref}
! CHECK: fir.call @_QPprint_parent_component1(%[[assoc]]#0)
! CHECK: hlfir.end_associate %[[assoc]]#1, %[[assoc]]#2
! CHECK: return
! CHECK: }
subroutine test_parent_component1()
type base
integer :: x, y(2)
end type base
type, extends(base) :: mid
logical :: mask
end type mid
call print_parent_component1(mid(base = base(1, [2, 3]), mask = .true.))
end
! CHECK-LABEL: func.func @_QPtest_parent_component2() {
! CHECK: %[[tmp:.*]] = fir.alloca !fir.type<_QFtest_parent_component2Tmid{base:!fir.type<_QFtest_parent_component2Tbase{z:!fir.char<1,5>}>,mask:!fir.logical<4>}>
! CHECK: %[[pv:.*]] = fir.address_of(@_QFtest_parent_component2Epv) : !fir.ref<!fir.type<_QFtest_parent_component2Tbase{z:!fir.char<1,5>}>>
! CHECK: %[[pvdecl:.*]]:2 = hlfir.declare %[[pv]] {uniq_name = "_QFtest_parent_component2Epv"}
! CHECK: %[[tmpdecl:.*]]:2 = hlfir.declare %[[tmp]] {uniq_name = "ctor.temp"}
! CHECK: fir.call @_FortranAInitialize(
! CHECK: %[[basecoor:.*]] = hlfir.designate %[[tmpdecl]]#0{"base"}
! CHECK: hlfir.assign %[[pvdecl]]#0 to %[[basecoor]] temporary_lhs : !fir.ref<!fir.type<_QFtest_parent_component2Tbase{z:!fir.char<1,5>}>>, !fir.ref<!fir.type<_QFtest_parent_component2Tbase{z:!fir.char<1,5>}>>
! CHECK: %[[maskcoor:.*]] = hlfir.designate %[[tmpdecl]]#0{"mask"}
! CHECK: %[[t:.*]] = arith.constant true
! CHECK: %[[lt:.*]] = fir.convert %[[t]] : (i1) -> !fir.logical<4>
! CHECK: hlfir.assign %[[lt]] to %[[maskcoor]] temporary_lhs : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: fir.call @_QPprint_parent_component2(%[[tmpdecl]]#0)
! CHECK: return
! CHECK: }
subroutine test_parent_component2()
type base
character(5) :: z
end type base
type, extends(base) :: mid
logical :: mask
end type mid
type(base) :: pv = base("aaa")
call print_parent_component2(mid(base = pv, mask = .true.))
end
! CHECK-LABEL: func.func @_QPtest_parent_component3(
! CHECK-SAME: %[[arg0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.type<_QFtest_parent_component3Tbase{m:!fir.array<2x!fir.char<1,5>>}>>>> {fir.bindc_name = "pp"}) {
! CHECK: %[[tmp:.*]] = fir.alloca !fir.type<_QFtest_parent_component3Tmid{base:!fir.type<_QFtest_parent_component3Tbase{m:!fir.array<2x!fir.char<1,5>>}>,mask:!fir.logical<4>}>
! CHECK: %[[ppdecl:.*]]:2 = hlfir.declare %[[arg0]]{{.*}}{fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_parent_component3Epp"}
! CHECK: %[[tmpdecl:.*]]:2 = hlfir.declare %[[tmp]] {uniq_name = "ctor.temp"}
! CHECK: fir.call @_FortranAInitialize(
! CHECK: %[[basecoor:.*]] = hlfir.designate %[[tmpdecl]]#0{"base"}
! CHECK: %[[ppload:.*]] = fir.load %[[ppdecl]]#0 : !fir.ref<!fir.box<!fir.ptr<!fir.type<_QFtest_parent_component3Tbase{m:!fir.array<2x!fir.char<1,5>>}>>>>
! CHECK: %[[ppaddr:.*]] = fir.box_addr %[[ppload]] : (!fir.box<!fir.ptr<!fir.type<_QFtest_parent_component3Tbase{m:!fir.array<2x!fir.char<1,5>>}>>>) -> !fir.ptr<!fir.type<_QFtest_parent_component3Tbase{m:!fir.array<2x!fir.char<1,5>>}>>
! CHECK: hlfir.assign %[[ppaddr]] to %[[basecoor]] temporary_lhs : !fir.ptr<!fir.type<_QFtest_parent_component3Tbase{m:!fir.array<2x!fir.char<1,5>>}>>, !fir.ref<!fir.type<_QFtest_parent_component3Tbase{m:!fir.array<2x!fir.char<1,5>>}>>
! CHECK: %[[maskcoor:.*]] = hlfir.designate %[[tmpdecl]]#0{"mask"}
! CHECK: %[[t:.*]] = arith.constant true
! CHECK: %[[lt:.*]] = fir.convert %[[t]] : (i1) -> !fir.logical<4>
! CHECK: hlfir.assign %[[lt]] to %[[maskcoor]] temporary_lhs : !fir.logical<4>, !fir.ref<!fir.logical<4>>
! CHECK: fir.call @_QPprint_parent_component3(%[[tmpdecl]]#0)
! CHECK: return
! CHECK: }
subroutine test_parent_component3(pp)
type base
character(5) :: m(2)
end type base
type, extends(base) :: mid
logical :: mask
end type mid
type(base), pointer :: pp
call print_parent_component3(mid(base = pp, mask = .true.))
end