Files
clang-p2996/flang/test/HLFIR/parent_comp-codegen.fir
Jean Perier 131c9174d9 [flang][hlfir] Add hlfir.parent_comp for leaf parent component references
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
2023-02-28 14:08:16 +01:00

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}>>>