Skip to content

Commit 4bb1751

Browse files
committed
[flang] Lowering and implementation for same_type_as
The test performed by same_type_as does not consider kind type parameters. If an exact match is not found, the name of the derived type is compared. The name in the runtime info does not include the kind type parameters as it does in the mangled name. Reviewed By: jeanPerier, PeteSteinfeld Differential Revision: https://reviews.llvm.org/D141364
1 parent b71bbbb commit 4bb1751

File tree

6 files changed

+120
-0
lines changed

6 files changed

+120
-0
lines changed

flang/include/flang/Optimizer/Builder/Runtime/Derived.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,8 @@ void genNullifyDerivedType(fir::FirOpBuilder &builder, mlir::Location loc,
3737
mlir::Value box, fir::RecordType derivedType,
3838
unsigned rank = 0);
3939

40+
mlir::Value genSameTypeAs(fir::FirOpBuilder &builder, mlir::Location loc,
41+
mlir::Value a, mlir::Value b);
42+
4043
} // namespace fir::runtime
4144
#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_DERIVED_H

flang/include/flang/Runtime/derived-api.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ void RTNAME(Assign)(const Descriptor &, const Descriptor &,
4646
// construct.
4747
bool RTNAME(ClassIs)(const Descriptor &, const typeInfo::DerivedType &);
4848

49+
// Perform the test of the SAME_TYPE_AS intrinsic.
50+
bool RTNAME(SameTypeAs)(const Descriptor &, const Descriptor &);
51+
4952
} // extern "C"
5053
} // namespace Fortran::runtime
5154
#endif // FORTRAN_RUNTIME_DERIVED_API_H_

flang/lib/Lower/IntrinsicCall.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "flang/Optimizer/Builder/MutableBox.h"
2626
#include "flang/Optimizer/Builder/Runtime/Character.h"
2727
#include "flang/Optimizer/Builder/Runtime/Command.h"
28+
#include "flang/Optimizer/Builder/Runtime/Derived.h"
2829
#include "flang/Optimizer/Builder/Runtime/Inquiry.h"
2930
#include "flang/Optimizer/Builder/Runtime/Numeric.h"
3031
#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
@@ -564,6 +565,8 @@ struct IntrinsicLibrary {
564565
fir::ExtendedValue genReshape(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
565566
mlir::Value genRRSpacing(mlir::Type resultType,
566567
llvm::ArrayRef<mlir::Value> args);
568+
fir::ExtendedValue genSameTypeAs(mlir::Type,
569+
llvm::ArrayRef<fir::ExtendedValue>);
567570
mlir::Value genScale(mlir::Type, llvm::ArrayRef<mlir::Value>);
568571
fir::ExtendedValue genScan(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
569572
mlir::Value genSelectedIntKind(mlir::Type, llvm::ArrayRef<mlir::Value>);
@@ -1013,6 +1016,10 @@ static constexpr IntrinsicHandler handlers[]{
10131016
{"order", asBox, handleDynamicOptional}}},
10141017
/*isElemental=*/false},
10151018
{"rrspacing", &I::genRRSpacing},
1019+
{"same_type_as",
1020+
&I::genSameTypeAs,
1021+
{{{"a", asBox}, {"b", asBox}}},
1022+
/*isElemental=*/false},
10161023
{"scale",
10171024
&I::genScale,
10181025
{{{"x", asValue}, {"i", asValue}}},
@@ -4491,6 +4498,18 @@ mlir::Value IntrinsicLibrary::genRRSpacing(mlir::Type resultType,
44914498
fir::runtime::genRRSpacing(builder, loc, fir::getBase(args[0])));
44924499
}
44934500

4501+
// SAME_TYPE_AS
4502+
fir::ExtendedValue
4503+
IntrinsicLibrary::genSameTypeAs(mlir::Type resultType,
4504+
llvm::ArrayRef<fir::ExtendedValue> args) {
4505+
assert(args.size() == 2);
4506+
4507+
return builder.createConvert(
4508+
loc, resultType,
4509+
fir::runtime::genSameTypeAs(builder, loc, fir::getBase(args[0]),
4510+
fir::getBase(args[1])));
4511+
}
4512+
44944513
// SCALE
44954514
mlir::Value IntrinsicLibrary::genScale(mlir::Type resultType,
44964515
llvm::ArrayRef<mlir::Value> args) {

flang/lib/Optimizer/Builder/Runtime/Derived.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,13 @@ void fir::runtime::genNullifyDerivedType(fir::FirOpBuilder &builder,
6262
args.push_back(c0);
6363
builder.create<fir::CallOp>(loc, callee, args);
6464
}
65+
66+
mlir::Value fir::runtime::genSameTypeAs(fir::FirOpBuilder &builder,
67+
mlir::Location loc, mlir::Value a,
68+
mlir::Value b) {
69+
mlir::func::FuncOp sameTypeAsFunc =
70+
fir::runtime::getRuntimeFunc<mkRTKey(SameTypeAs)>(loc, builder);
71+
auto fTy = sameTypeAsFunc.getFunctionType();
72+
auto args = fir::runtime::createArguments(builder, loc, fTy, a, b);
73+
return builder.create<fir::CallOp>(loc, sameTypeAsFunc, args).getResult(0);
74+
}

flang/runtime/derived-api.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,44 @@ bool RTNAME(ClassIs)(
5858
return false;
5959
}
6060

61+
static bool CompareDerivedTypeNames(const Descriptor &a, const Descriptor &b) {
62+
if (a.raw().version == CFI_VERSION &&
63+
a.type() == TypeCode{TypeCategory::Character, 1} &&
64+
a.ElementBytes() > 0 && a.rank() == 0 && a.OffsetElement() != nullptr &&
65+
a.raw().version == CFI_VERSION &&
66+
b.type() == TypeCode{TypeCategory::Character, 1} &&
67+
b.ElementBytes() > 0 && b.rank() == 0 && b.OffsetElement() != nullptr &&
68+
a.ElementBytes() == b.ElementBytes() &&
69+
memcmp(a.OffsetElement(), b.OffsetElement(), a.ElementBytes()) == 0) {
70+
return true;
71+
}
72+
return false;
73+
}
74+
75+
static const typeInfo::DerivedType *GetDerivedType(const Descriptor &desc) {
76+
if (const DescriptorAddendum * addendum{desc.Addendum()}) {
77+
if (const auto *derived{addendum->derivedType()}) {
78+
return derived;
79+
}
80+
}
81+
return nullptr;
82+
}
83+
84+
bool RTNAME(SameTypeAs)(const Descriptor &a, const Descriptor &b) {
85+
const typeInfo::DerivedType *derivedTypeA{GetDerivedType(a)};
86+
const typeInfo::DerivedType *derivedTypeB{GetDerivedType(b)};
87+
if (derivedTypeA == nullptr || derivedTypeB == nullptr) {
88+
return false;
89+
}
90+
// Exact match of derived type.
91+
if (derivedTypeA == derivedTypeB) {
92+
return true;
93+
}
94+
// Otherwise compare with the name. Note 16.29 kind type parameters are not
95+
// considered in the test.
96+
return CompareDerivedTypeNames(derivedTypeA->name(), derivedTypeB->name());
97+
}
98+
6199
// TODO: Assign()
62100

63101
} // extern "C"
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
! RUN: bbc -emit-fir -polymorphic-type %s -o - | FileCheck %s
2+
3+
module same_type_as_mod
4+
5+
type p1
6+
integer :: a
7+
end type
8+
9+
type, extends(p1) :: p2
10+
integer :: b
11+
end type
12+
13+
type k1(a)
14+
integer, kind :: a
15+
end type
16+
17+
contains
18+
subroutine is_same_type(a, b)
19+
class(*) :: a
20+
class(*) :: b
21+
22+
if (same_type_as(a, b)) then
23+
print*, 'same_type_as ok'
24+
else
25+
print*, 'same_type_as failed'
26+
end if
27+
end subroutine
28+
29+
! CHECK-LABEL: func.func @_QMsame_type_as_modPis_same_type(
30+
! CHECK-SAME: %[[ARG0:.*]]: !fir.class<none> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.class<none> {fir.bindc_name = "b"}) {
31+
! CHECK: %[[BOX0:.*]] = fir.convert %[[ARG0]] : (!fir.class<none>) -> !fir.box<none>
32+
! CHECK: %[[BOX1:.*]] = fir.convert %[[ARG1]] : (!fir.class<none>) -> !fir.box<none>
33+
! CHECK: %{{.*}} = fir.call @_FortranASameTypeAs(%[[BOX0]], %[[BOX1]]) {{.*}} : (!fir.box<none>, !fir.box<none>) -> i1
34+
35+
end module
36+
37+
program test
38+
use same_type_as_mod
39+
type(p1) :: p, r
40+
type(p2) :: q
41+
type(k1(10)) :: k10
42+
type(k1(20)) :: k20
43+
44+
call is_same_type(p, q)
45+
call is_same_type(p, r)
46+
call is_same_type(k10, k20)
47+
end

0 commit comments

Comments
 (0)