[flang] Make `TypeParamInquiry` monomorphic

Change the expression representation TypeParamInquiry from being
a class that's templatized on the integer KIND of its result into
a monomorphic representation that results in a SubscriptInteger
that can then be converted.

This is a minor simplification, but it's worth doing because
it is believed to also be a work-around for bugs in the MSVC
compiler with overload resolution that affect the expression
traversal framework.

Differential Revision: https://reviews.llvm.org/D86551
This commit is contained in:
peter klausler 2020-08-25 09:40:20 -07:00
parent b79e19e6d6
commit 4cbfd93a59
16 changed files with 49 additions and 95 deletions

View File

@ -516,15 +516,18 @@ private:
Power<Result>, Extremum<Result>>;
using Indices = std::conditional_t<KIND == ImpliedDoIndex::Result::kind,
std::tuple<ImpliedDoIndex>, std::tuple<>>;
using TypeParamInquiries =
std::conditional_t<KIND == TypeParamInquiry::Result::kind,
std::tuple<TypeParamInquiry>, std::tuple<>>;
using DescriptorInquiries =
std::conditional_t<KIND == DescriptorInquiry::Result::kind,
std::tuple<DescriptorInquiry>, std::tuple<>>;
using Others = std::tuple<Constant<Result>, ArrayConstructor<Result>,
TypeParamInquiry<KIND>, Designator<Result>, FunctionRef<Result>>;
Designator<Result>, FunctionRef<Result>>;
public:
common::TupleToVariant<common::CombineTuples<Operations, Conversions, Indices,
DescriptorInquiries, Others>>
TypeParamInquiries, DescriptorInquiries, Others>>
u;
};

View File

@ -93,9 +93,7 @@ public:
Result operator()(const ImpliedDoIndex &) const { return Scalar(); }
Result operator()(const DescriptorInquiry &) const { return Scalar(); }
template <int KIND> Result operator()(const TypeParamInquiry<KIND> &) const {
return Scalar();
}
Result operator()(const TypeParamInquiry &) const { return Scalar(); }
Result operator()(const BOZLiteralConstant &) const { return Scalar(); }
Result operator()(const StaticDataObject::Pointer &) const {
return Scalar();

View File

@ -120,7 +120,7 @@ public:
return visitor_(x.GetFirstSymbol());
}
}
template <int KIND> Result operator()(const TypeParamInquiry<KIND> &x) const {
Result operator()(const TypeParamInquiry &x) const {
return visitor_(x.base());
}
Result operator()(const Triplet &x) const {

View File

@ -128,9 +128,9 @@ private:
// KIND(x), which is then folded to a constant value.
// "Bare" type parameter references within a derived type definition do
// not have base objects.
template <int KIND> class TypeParamInquiry {
class TypeParamInquiry {
public:
using Result = Type<TypeCategory::Integer, KIND>;
using Result = SubscriptInteger;
CLASS_BOILERPLATE(TypeParamInquiry)
TypeParamInquiry(NamedEntity &&x, const Symbol &param)
: base_{std::move(x)}, parameter_{param} {}
@ -150,9 +150,6 @@ private:
SymbolRef parameter_;
};
EXPAND_FOR_EACH_INTEGER_KIND(
TEMPLATE_INSTANTIATION, extern template class TypeParamInquiry, )
// R921 subscript-triplet
class Triplet {
public:
@ -422,8 +419,6 @@ private:
};
#define INSTANTIATE_VARIABLE_TEMPLATES \
EXPAND_FOR_EACH_INTEGER_KIND( \
TEMPLATE_INSTANTIATION, template class TypeParamInquiry, ) \
FOR_EACH_SPECIFIC_TYPE(template class Designator, )
} // namespace Fortran::evaluate
#endif // FORTRAN_EVALUATE_VARIABLE_H_

View File

@ -29,7 +29,7 @@ public:
IsConstantExprHelper() : Base{*this} {}
using Base::operator();
template <int KIND> bool operator()(const TypeParamInquiry<KIND> &inq) const {
bool operator()(const TypeParamInquiry &inq) const {
return IsKindTypeParameter(inq.parameter());
}
bool operator()(const semantics::Symbol &symbol) const {
@ -155,9 +155,7 @@ public:
return true;
}
bool operator()(const StaticDataObject &) const { return false; }
template <int KIND> bool operator()(const TypeParamInquiry<KIND> &) const {
return false;
}
bool operator()(const TypeParamInquiry &) const { return false; }
bool operator()(const Triplet &x) const {
return IsConstantExpr(x.lower()) && IsConstantExpr(x.upper()) &&
IsConstantExpr(x.stride());
@ -310,8 +308,7 @@ public:
return std::nullopt;
}
template <int KIND>
Result operator()(const TypeParamInquiry<KIND> &inq) const {
Result operator()(const TypeParamInquiry &inq) const {
if (scope_.IsDerivedType() && !IsConstantExpr(inq) &&
inq.parameter().owner() != scope_) { // C750, C754
return "non-constant reference to a type parameter inquiry not "

View File

@ -115,9 +115,8 @@ Expr<T> FoldOperation(FoldingContext &context, Designator<T> &&designator) {
return Folder<T>{context}.Folding(std::move(designator));
}
template <int KIND>
Expr<Type<TypeCategory::Integer, KIND>> FoldOperation(
FoldingContext &, TypeParamInquiry<KIND> &&);
Expr<TypeParamInquiry::Result> FoldOperation(
FoldingContext &, TypeParamInquiry &&);
Expr<ImpliedDoIndex::Result> FoldOperation(
FoldingContext &context, ImpliedDoIndex &&);
template <typename T>

View File

@ -600,10 +600,8 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldIntrinsicFunction(
}
// Substitute a bare type parameter reference with its value if it has one now
template <int KIND>
Expr<Type<TypeCategory::Integer, KIND>> FoldOperation(
FoldingContext &context, TypeParamInquiry<KIND> &&inquiry) {
using IntKIND = Type<TypeCategory::Integer, KIND>;
Expr<TypeParamInquiry::Result> FoldOperation(
FoldingContext &context, TypeParamInquiry &&inquiry) {
if (!inquiry.base()) {
// A "bare" type parameter: replace with its value, if that's now known.
if (const auto *pdt{context.pdtInstance()}) {
@ -617,21 +615,20 @@ Expr<Type<TypeCategory::Integer, KIND>> FoldOperation(
IsConstantExpr(*details->init()))) {
Expr<SomeInteger> expr{*details->init()};
return Fold(context,
Expr<IntKIND>{
Convert<IntKIND, TypeCategory::Integer>(std::move(expr))});
ConvertToType<TypeParamInquiry::Result>(std::move(expr)));
}
}
}
if (const auto *value{pdt->FindParameter(inquiry.parameter().name())}) {
if (value->isExplicit()) {
return Fold(context,
Expr<IntKIND>{Convert<IntKIND, TypeCategory::Integer>(
Expr<SomeInteger>{value->GetExplicit().value()})});
AsExpr(ConvertToType<TypeParamInquiry::Result>(
Expr<SomeInteger>{value->GetExplicit().value()})));
}
}
}
}
return Expr<IntKIND>{std::move(inquiry)};
return AsExpr(std::move(inquiry));
}
std::optional<std::int64_t> ToInt64(const Expr<SomeInteger> &expr) {

View File

@ -606,9 +606,7 @@ llvm::raw_ostream &BaseObject::AsFortran(llvm::raw_ostream &o) const {
return EmitVar(o, u);
}
template <int KIND>
llvm::raw_ostream &TypeParamInquiry<KIND>::AsFortran(
llvm::raw_ostream &o) const {
llvm::raw_ostream &TypeParamInquiry::AsFortran(llvm::raw_ostream &o) const {
if (base_) {
return base_->AsFortran(o) << '%';
}

View File

@ -635,9 +635,7 @@ bool NamedEntity::operator==(const NamedEntity &that) const {
return !that.IsSymbol() && GetComponent() == that.GetComponent();
}
}
template <int KIND>
bool TypeParamInquiry<KIND>::operator==(
const TypeParamInquiry<KIND> &that) const {
bool TypeParamInquiry::operator==(const TypeParamInquiry &that) const {
return &*parameter_ == &*that.parameter_ && base_ == that.base_;
}
bool Triplet::operator==(const Triplet &that) const {

View File

@ -262,13 +262,13 @@ private:
//===--------------------------------------------------------------------===//
mlir::Type gen(const Fortran::evaluate::ImpliedDoIndex &) {
return genFIRType<Fortran::common::TypeCategory::Integer>(
context, defaultKind<Fortran::common::TypeCategory::Integer>());
return genFIRType<Fortran::evaluate::ImpliedDoIndex::Result::category>(
context, Fortran::evaluate::ImpliedDoIndex::Result::kind);
}
template <int KIND>
mlir::Type gen(const Fortran::evaluate::TypeParamInquiry<KIND> &) {
return genFIRType<Fortran::common::TypeCategory::Integer, KIND>(context);
mlir::Type gen(const Fortran::evaluate::TypeParamInquiry &) {
return genFIRType<Fortran::evaluate::TypeParamInquiry::Result::category>(
context, Fortran::evaluate::TypeParamInquiry::Result::kind);
}
template <typename A>

View File

@ -643,38 +643,6 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::BOZLiteralConstant &x) {
return AsGenericExpr(std::move(value.value));
}
// For use with SearchTypes to create a TypeParamInquiry with the
// right integer kind.
struct TypeParamInquiryVisitor {
using Result = std::optional<Expr<SomeInteger>>;
using Types = IntegerTypes;
TypeParamInquiryVisitor(int k, NamedEntity &&b, const Symbol &param)
: kind{k}, base{std::move(b)}, parameter{param} {}
TypeParamInquiryVisitor(int k, const Symbol &param)
: kind{k}, parameter{param} {}
template <typename T> Result Test() {
if (kind == T::kind) {
return Expr<SomeInteger>{
Expr<T>{TypeParamInquiry<T::kind>{std::move(base), parameter}}};
}
return std::nullopt;
}
int kind;
std::optional<NamedEntity> base;
const Symbol &parameter;
};
static std::optional<Expr<SomeInteger>> MakeBareTypeParamInquiry(
const Symbol *symbol) {
if (std::optional<DynamicType> dyType{DynamicType::From(symbol)}) {
if (dyType->category() == TypeCategory::Integer) {
return common::SearchTypes(
TypeParamInquiryVisitor{dyType->kind(), *symbol});
}
}
return std::nullopt;
}
// Names and named constants
MaybeExpr ExpressionAnalyzer::Analyze(const parser::Name &n) {
if (std::optional<int> kind{IsImpliedDo(n.source)}) {
@ -690,7 +658,8 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Name &n) {
if (ultimate.has<semantics::TypeParamDetails>()) {
// A bare reference to a derived type parameter (within a parameterized
// derived type definition)
return AsMaybeExpr(MakeBareTypeParamInquiry(&ultimate));
return Fold(ConvertToType(
ultimate, AsGenericExpr(TypeParamInquiry{std::nullopt, ultimate})));
} else {
if (n.symbol->attrs().test(semantics::Attr::VOLATILE)) {
if (const semantics::Scope *
@ -989,9 +958,9 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) {
if (auto *designator{UnwrapExpr<Designator<SomeDerived>>(*dtExpr)}) {
if (std::optional<DynamicType> dyType{DynamicType::From(*sym)}) {
if (dyType->category() == TypeCategory::Integer) {
return AsMaybeExpr(
common::SearchTypes(TypeParamInquiryVisitor{dyType->kind(),
IgnoreAnySubscripts(std::move(*designator)), *sym}));
return Fold(ConvertToType(*dyType,
AsGenericExpr(TypeParamInquiry{
IgnoreAnySubscripts(std::move(*designator)), *sym})));
}
}
Say(name, "Type parameter is not INTEGER"_err_en_US);

View File

@ -5,7 +5,7 @@
!REF: /MainProgram1/ipdt/k
integer, kind :: k
!REF: /MainProgram1/ipdt/k
!DEF: /MainProgram1/ipdt/x ObjectEntity INTEGER(int(k,kind=8))
!DEF: /MainProgram1/ipdt/x ObjectEntity INTEGER(int(int(k,kind=4),kind=8))
integer(kind=k) :: x
end type ipdt
!DEF: /MainProgram1/rpdt DerivedType
@ -14,7 +14,7 @@
!REF: /MainProgram1/rpdt/k
integer, kind :: k
!REF: /MainProgram1/rpdt/k
!DEF: /MainProgram1/rpdt/x ObjectEntity REAL(int(k,kind=8))
!DEF: /MainProgram1/rpdt/x ObjectEntity REAL(int(int(k,kind=4),kind=8))
real(kind=k) :: x
end type rpdt
!DEF: /MainProgram1/zpdt DerivedType
@ -23,7 +23,7 @@
!REF: /MainProgram1/zpdt/k
integer, kind :: k
!REF: /MainProgram1/zpdt/k
!DEF: /MainProgram1/zpdt/x ObjectEntity COMPLEX(int(k,kind=8))
!DEF: /MainProgram1/zpdt/x ObjectEntity COMPLEX(int(int(k,kind=4),kind=8))
complex(kind=k) :: x
end type zpdt
!DEF: /MainProgram1/lpdt DerivedType
@ -32,7 +32,7 @@
!REF: /MainProgram1/lpdt/k
integer, kind :: k
!REF: /MainProgram1/lpdt/k
!DEF: /MainProgram1/lpdt/x ObjectEntity LOGICAL(int(k,kind=8))
!DEF: /MainProgram1/lpdt/x ObjectEntity LOGICAL(int(int(k,kind=4),kind=8))
logical(kind=k) :: x
end type lpdt
!REF: /MainProgram1/ipdt

View File

@ -91,21 +91,21 @@ end module
!integer(2),kind::k2
!integer(4),kind::k4
!integer(8),kind::k8
!integer(int(k1,kind=8))::j1
!integer(int(k2,kind=8))::j2
!integer(int(k4,kind=8))::j4
!integer(int(int(k1,kind=1),kind=8))::j1
!integer(int(int(k2,kind=2),kind=8))::j2
!integer(int(int(k4,kind=4),kind=8))::j4
!integer(k8)::j8
!end type
!type::defaulted(n1,n2,n4,n8)
!integer(1),kind::n1=1_1
!integer(2),kind::n2=int(int(n1,kind=4)*2_4,kind=2)
!integer(4),kind::n4=2_4*int(n2,kind=4)
!integer(8),kind::n8=int(12_4-n4,kind=8)
!type(capture(k1=n1,k2=n2,k4=n4,k8=n8))::cap
!integer(2),kind::n2=int(int(int(n1,kind=1),kind=4)*2_4,kind=2)
!integer(4),kind::n4=2_4*int(int(n2,kind=2),kind=4)
!integer(8),kind::n8=int(12_4-int(n4,kind=4),kind=8)
!type(capture(k1=int(n1,kind=1),k2=int(n2,kind=2),k4=int(n4,kind=4),k8=n8))::cap
!end type
!type,extends(defaulted)::extension(k5)
!integer(4),kind::k5=4_4
!integer(int(k5,kind=8))::j5
!integer(int(int(k5,kind=4),kind=8))::j5
!end type
!type(capture(k1=1_1,k2=1_2,k4=1_4,k8=1_8))::x1111
!integer(1)::res01_1

View File

@ -15,8 +15,8 @@ end module m
!module m
!type::t(k)
!integer(4),kind::k=1_4
!character(1_4,int(k,kind=8))::a
!character(3_4,int(k,kind=8))::b
!character(1_4,int(int(k,kind=4),kind=8))::a
!character(3_4,int(int(k,kind=4),kind=8))::b
!end type
!type(t(k=1_4)),parameter::p=t(k=1_4)(a="x",b="xx ")
!character(2_4,1),parameter::c2(1_8:3_8)=[CHARACTER(KIND=1,LEN=2)::"x ","xx","xx"]

View File

@ -608,7 +608,7 @@ end
!module m7
! type :: t(k)
! integer(4), kind :: k
! real(int(k, kind=8)) :: a
! real(int(int(k,kind=4),kind=8))::a
! end type
! interface operator(+)
! procedure :: f1

View File

@ -80,7 +80,7 @@ type(fwdpdt(kind(0))) function f2(n)
!REF: /f2/fwdpdt/k
integer, kind :: k
!REF: /f2/fwdpdt/k
!DEF: /f2/fwdpdt/n ObjectEntity INTEGER(int(k,kind=8))
!DEF: /f2/fwdpdt/n ObjectEntity INTEGER(int(int(k,kind=4),kind=8))
integer(kind=k) :: n
end type
!DEF: /f2/f2 ObjectEntity TYPE(fwdpdt(k=4_4))
@ -100,7 +100,7 @@ subroutine s2 (q1)
!REF: /s2/fwdpdt/k
integer, kind :: k
!REF: /s2/fwdpdt/k
!DEF: /s2/fwdpdt/n ObjectEntity INTEGER(int(k,kind=8))
!DEF: /s2/fwdpdt/n ObjectEntity INTEGER(int(int(k,kind=4),kind=8))
integer(kind=k) :: n
end type
!REF: /s2/q1