diff --git a/flang/include/flang/Lower/ConvertType.h b/flang/include/flang/Lower/ConvertType.h --- a/flang/include/flang/Lower/ConvertType.h +++ b/flang/include/flang/Lower/ConvertType.h @@ -22,6 +22,7 @@ #define FORTRAN_LOWER_CONVERT_TYPE_H #include "flang/Common/Fortran.h" +#include "flang/Evaluate/type.h" #include "mlir/IR/BuiltinTypes.h" namespace mlir { @@ -39,6 +40,8 @@ namespace evaluate { template class Expr; +template +class FunctionRef; struct SomeType; } // namespace evaluate @@ -83,6 +86,15 @@ /// Translate a REAL of KIND to the mlir::Type. mlir::Type convertReal(mlir::MLIRContext *ctxt, int KIND); +template +class TypeBuilder { +public: + static mlir::Type genType(Fortran::lower::AbstractConverter &, + const Fortran::evaluate::FunctionRef &); +}; +using namespace evaluate; +FOR_EACH_SPECIFIC_TYPE(extern template class TypeBuilder, ) + } // namespace lower } // namespace Fortran diff --git a/flang/lib/Lower/ConvertType.cpp b/flang/lib/Lower/ConvertType.cpp --- a/flang/lib/Lower/ConvertType.cpp +++ b/flang/lib/Lower/ConvertType.cpp @@ -122,7 +122,7 @@ // Symbol and expression type translation //===--------------------------------------------------------------------===// -/// TypeBuilder translates expression and symbol type taking into account +/// TypeBuilderImpl translates expression and symbol type taking into account /// their shape and length parameters. For symbols, attributes such as /// ALLOCATABLE or POINTER are reflected in the fir type. /// It uses evaluate::DynamicType and evaluate::Shape when possible to @@ -130,12 +130,13 @@ /// Do not use the FirOpBuilder from the AbstractConverter to get fir/mlir types /// since it is not guaranteed to exist yet when we lower types. namespace { -struct TypeBuilder { +struct TypeBuilderImpl { - TypeBuilder(Fortran::lower::AbstractConverter &converter) + TypeBuilderImpl(Fortran::lower::AbstractConverter &converter) : converter{converter}, context{&converter.getMLIRContext()} {} - mlir::Type genExprType(const Fortran::lower::SomeExpr &expr) { + template + mlir::Type genExprType(const A &expr) { std::optional dynamicType = expr.GetType(); if (!dynamicType) return genTypelessExprType(expr); @@ -188,6 +189,11 @@ converter.getFoldingContext(), std::move(expr))); } + template + mlir::Type genTypelessExprType(const A &expr) { + fir::emitFatalError(converter.getCurrentLocation(), "not a typeless expr"); + } + mlir::Type genTypelessExprType(const Fortran::lower::SomeExpr &expr) { return std::visit( Fortran::common::visitors{ @@ -397,6 +403,11 @@ } llvm_unreachable("unknown character kind"); } + + template + Fortran::lower::LenParameterTy getCharacterLength(const A &expr) { + return fir::SequenceType::getUnknownExtent(); + } Fortran::lower::LenParameterTy getCharacterLength(const Fortran::lower::SomeExpr &expr) { // Do not use dynamic type length here. We would miss constant @@ -450,25 +461,36 @@ mlir::Type Fortran::lower::translateDerivedTypeToFIRType( Fortran::lower::AbstractConverter &converter, const Fortran::semantics::DerivedTypeSpec &tySpec) { - return TypeBuilder{converter}.genDerivedType(tySpec); + return TypeBuilderImpl{converter}.genDerivedType(tySpec); } mlir::Type Fortran::lower::translateSomeExprToFIRType( Fortran::lower::AbstractConverter &converter, const SomeExpr &expr) { - return TypeBuilder{converter}.genExprType(expr); + return TypeBuilderImpl{converter}.genExprType(expr); } mlir::Type Fortran::lower::translateSymbolToFIRType( Fortran::lower::AbstractConverter &converter, const SymbolRef symbol) { - return TypeBuilder{converter}.genSymbolType(symbol); + return TypeBuilderImpl{converter}.genSymbolType(symbol); } mlir::Type Fortran::lower::translateVariableToFIRType( Fortran::lower::AbstractConverter &converter, const Fortran::lower::pft::Variable &var) { - return TypeBuilder{converter}.genVariableType(var); + return TypeBuilderImpl{converter}.genVariableType(var); } mlir::Type Fortran::lower::convertReal(mlir::MLIRContext *context, int kind) { return genRealType(context, kind); } + +template +mlir::Type Fortran::lower::TypeBuilder::genType( + Fortran::lower::AbstractConverter &converter, + const Fortran::evaluate::FunctionRef &funcRef) { + return TypeBuilderImpl{converter}.genExprType(funcRef); +} + +using namespace Fortran::evaluate; +using namespace Fortran::common; +FOR_EACH_SPECIFIC_TYPE(template class Fortran::lower::TypeBuilder, )