In Fortran, it is possible to refer to the "parent part" of a derived type as if it were a component: ```Fortran type t1 integer :: i end type type t2 integer :: j end type type(t2) :: a print *, a%t1%i ! "inner" parent component reference print *, a%t1 ! "leaf" parent component reference end ``` Inner parent component references can be dropped on the floor in lowering: "a%t1%i" is equivalent to "a%i". Leaf parent component references, however, must be taken care of. For scalars, "a%t1" is a simple addressc ast to "t1", for arrays, however, this creates an array section that must be represented with a descriptor (fir.box). hlfir.designate could have been extended to deal with this, but I think it would make hlfir.designate too complex and hard to manipulate. This patch adds an hlfir.parent_comp op that represents and implements leaf parent component references. Differential Revision: https://reviews.llvm.org/D144946
45 lines
2.7 KiB
Plaintext
45 lines
2.7 KiB
Plaintext
// Test hlfir.parent_comp code generation to FIR
|
|
// RUN: fir-opt %s -convert-hlfir-to-fir | FileCheck %s
|
|
|
|
func.func @test_scalar(%arg0: !fir.ref<!fir.type<t2{i:i32,j:i32}>>) {
|
|
%1 = hlfir.parent_comp %arg0 : (!fir.ref<!fir.type<t2{i:i32,j:i32}>>) -> !fir.ref<!fir.type<t1{i:i32}>>
|
|
return
|
|
}
|
|
// CHECK-LABEL: func.func @test_scalar(
|
|
// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.type<t2{i:i32,j:i32}>>) {
|
|
// CHECK: fir.convert %[[VAL_0]] : (!fir.ref<!fir.type<t2{i:i32,j:i32}>>) -> !fir.ref<!fir.type<t1{i:i32}>>
|
|
|
|
func.func @test_scalar_polymorphic(%arg0: !fir.class<!fir.type<t2{i:i32,j:i32}>>) {
|
|
%1 = hlfir.parent_comp %arg0 : (!fir.class<!fir.type<t2{i:i32,j:i32}>>) -> !fir.ref<!fir.type<t1{i:i32}>>
|
|
return
|
|
}
|
|
// CHECK-LABEL: func.func @test_scalar_polymorphic(
|
|
// CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.type<t2{i:i32,j:i32}>>) {
|
|
// CHECK: %[[VAL_1:.*]] = fir.box_addr %[[VAL_0]] : (!fir.class<!fir.type<t2{i:i32,j:i32}>>) -> !fir.ref<!fir.type<t2{i:i32,j:i32}>>
|
|
// CHECK: fir.convert %[[VAL_1]] : (!fir.ref<!fir.type<t2{i:i32,j:i32}>>) -> !fir.ref<!fir.type<t1{i:i32}>>
|
|
|
|
func.func @test_array(%arg0: !fir.ref<!fir.array<10x!fir.type<t2{i:i32,j:i32}>>>) {
|
|
%c10 = arith.constant 10 : index
|
|
%1 = fir.shape %c10 : (index) -> !fir.shape<1>
|
|
%2 = hlfir.parent_comp %arg0 shape %1 : (!fir.ref<!fir.array<10x!fir.type<t2{i:i32,j:i32}>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.type<t1{i:i32}>>>
|
|
return
|
|
}
|
|
// CHECK-LABEL: func.func @test_array(
|
|
// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10x!fir.type<t2{i:i32,j:i32}>>>) {
|
|
// CHECK: %[[VAL_1:.*]] = arith.constant 10 : index
|
|
// CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1>
|
|
// CHECK: %[[VAL_3:.*]] = fir.embox %[[VAL_0]](%[[VAL_2]]) : (!fir.ref<!fir.array<10x!fir.type<t2{i:i32,j:i32}>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.type<t2{i:i32,j:i32}>>>
|
|
// CHECK: fir.rebox %[[VAL_3]] : (!fir.box<!fir.array<10x!fir.type<t2{i:i32,j:i32}>>>) -> !fir.box<!fir.array<10x!fir.type<t1{i:i32}>>>
|
|
|
|
func.func @test_array_polymorphic(%arg0: !fir.class<!fir.array<10x!fir.type<t2{i:i32,j:i32}>>>) {
|
|
%c10 = arith.constant 10 : index
|
|
%1 = fir.shape %c10 : (index) -> !fir.shape<1>
|
|
%2 = hlfir.parent_comp %arg0 shape %1 : (!fir.class<!fir.array<10x!fir.type<t2{i:i32,j:i32}>>>, !fir.shape<1>) -> !fir.box<!fir.array<10x!fir.type<t1{i:i32}>>>
|
|
return
|
|
}
|
|
// CHECK-LABEL: func.func @test_array_polymorphic(
|
|
// CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.array<10x!fir.type<t2{i:i32,j:i32}>>>) {
|
|
// CHECK: %[[VAL_1:.*]] = arith.constant 10 : index
|
|
// CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1>
|
|
// CHECK: fir.rebox %[[VAL_0]] : (!fir.class<!fir.array<10x!fir.type<t2{i:i32,j:i32}>>>) -> !fir.box<!fir.array<10x!fir.type<t1{i:i32}>>>
|