From: Jean Perier Date: Fri, 1 Mar 2019 17:20:12 +0000 (-0800) Subject: [flang] renaming to focus scope on intrinsic runtime X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8d032dc96b4f2eaf252a5b04178dc27e8e4bacab;p=platform%2Fupstream%2Fllvm.git [flang] renaming to focus scope on intrinsic runtime Original-commit: flang-compiler/f18@7cfd33b178d3ea3502ea87cb9416720f6cce4ba9 Tree-same-pre-rewrite: false --- diff --git a/flang/lib/evaluate/CMakeLists.txt b/flang/lib/evaluate/CMakeLists.txt index c173f3a..0bded45 100644 --- a/flang/lib/evaluate/CMakeLists.txt +++ b/flang/lib/evaluate/CMakeLists.txt @@ -29,7 +29,7 @@ add_library(FortranEvaluate tools.cc type.cc variable.cc - rte.cc + intrinsics-library.cc ) target_link_libraries(FortranEvaluate diff --git a/flang/lib/evaluate/common.h b/flang/lib/evaluate/common.h index 8dbf09d..d91da13 100644 --- a/flang/lib/evaluate/common.h +++ b/flang/lib/evaluate/common.h @@ -15,6 +15,7 @@ #ifndef FORTRAN_EVALUATE_COMMON_H_ #define FORTRAN_EVALUATE_COMMON_H_ +#include "intrinsics-library.h" #include "../common/Fortran.h" #include "../common/enum-set.h" #include "../common/idioms.h" @@ -22,7 +23,6 @@ #include "../common/restorer.h" #include "../parser/char-block.h" #include "../parser/message.h" -#include "rte-interface.h" #include #include @@ -219,7 +219,9 @@ public: bool flushSubnormalsToZero() const { return flushSubnormalsToZero_; } bool bigEndian() const { return bigEndian_; } const semantics::DerivedTypeSpec *pdtInstance() const { return pdtInstance_; } - rte::HostRte &hostRte() { return hostRte_; } + HostIntrinsicProceduresLibrary &hostIntrinsicsLibrary() { + return hostIntrinsicsLibrary_; + } std::int64_t &StartImpliedDo(parser::CharBlock, std::int64_t = 1); std::optional GetImpliedDo(parser::CharBlock) const; @@ -241,7 +243,7 @@ private: bool bigEndian_{false}; const semantics::DerivedTypeSpec *pdtInstance_{nullptr}; std::map impliedDos_; - rte::HostRte hostRte_; + HostIntrinsicProceduresLibrary hostIntrinsicsLibrary_; }; void RealFlagWarnings(FoldingContext &, const RealFlags &, const char *op); diff --git a/flang/lib/evaluate/fold.cc b/flang/lib/evaluate/fold.cc index 17ef66a..742740c 100644 --- a/flang/lib/evaluate/fold.cc +++ b/flang/lib/evaluate/fold.cc @@ -18,7 +18,7 @@ #include "expression.h" #include "host.h" #include "int-power.h" -#include "rte.h" +#include "intrinsics-library-templates.h" #include "tools.h" #include "traversal.h" #include "type.h" @@ -331,8 +331,8 @@ Expr> FoldOperation(FoldingContext &context, const std::string name{intrinsic->name}; if (name == "acos" || name == "acosh" || (name == "atan" && funcRef.arguments().size() == 1)) { - if (auto callable{ - context.hostRte().GetHostProcedureWrapper(name)}) { + if (auto callable{context.hostIntrinsicsLibrary() + .GetHostProcedureWrapper(name)}) { return FoldElementalIntrinsic( context, std::move(funcRef), *callable); } else { @@ -342,9 +342,8 @@ Expr> FoldOperation(FoldingContext &context, } } if (name == "atan") { - if (auto callable{ - context.hostRte().GetHostProcedureWrapper( - name)}) { + if (auto callable{context.hostIntrinsicsLibrary() + .GetHostProcedureWrapper(name)}) { return FoldElementalIntrinsic( context, std::move(funcRef), *callable); } else { @@ -361,8 +360,8 @@ Expr> FoldOperation(FoldingContext &context, Fold(context, ConvertToType(std::move(*n))); } if (auto callable{ - context.hostRte().GetHostProcedureWrapper( - name)}) { + context.hostIntrinsicsLibrary() + .GetHostProcedureWrapper(name)}) { return FoldElementalIntrinsic( context, std::move(funcRef), *callable); } else { @@ -423,8 +422,8 @@ Expr> FoldOperation(FoldingContext &context, const std::string name{intrinsic->name}; if (name == "acos" || name == "acosh" || name == "asin" || name == "atan" || name == "atanh") { - if (auto callable{ - context.hostRte().GetHostProcedureWrapper(name)}) { + if (auto callable{context.hostIntrinsicsLibrary() + .GetHostProcedureWrapper(name)}) { return FoldElementalIntrinsic( context, std::move(funcRef), *callable); } else { diff --git a/flang/lib/evaluate/rte.h b/flang/lib/evaluate/intrinsics-library-templates.h similarity index 81% rename from flang/lib/evaluate/rte.h rename to flang/lib/evaluate/intrinsics-library-templates.h index f50c76a..74d3a31 100644 --- a/flang/lib/evaluate/rte.h +++ b/flang/lib/evaluate/intrinsics-library-templates.h @@ -12,18 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef FORTRAN_EVALUATE_RTE_H_ -#define FORTRAN_EVALUATE_RTE_H_ +#ifndef FORTRAN_EVALUATE_INTRINSICS_LIBRARY_TEMPLATES_H_ +#define FORTRAN_EVALUATE_INTRINSICS_LIBRARY_TEMPLATES_H_ // This header defines the actual implementation of the templatized member -// function of the structures defined in rte-interface.h. It should only be -// included if these member functions are used, else rte-interface.h is +// function of the structures defined in intrinsics-library.h. It should only be +// included if these member functions are used, else intrinsics-library.h is // sufficient. This is to avoid circular dependencies. The below implementation // cannot be defined in .cc file because it would be too cumbersome to decide // which version should be instantiated in a generic way. #include "host.h" -#include "rte-interface.h" +#include "intrinsics-library.h" #include "type.h" #include "../common/template.h" @@ -31,11 +31,11 @@ #include #include -namespace Fortran::evaluate::rte { +namespace Fortran::evaluate { // Define meaningful types for the runtime // TODO: add the support for void and descriptor -using RteTypes = evaluate::AllIntrinsicTypes; +using RuntimeTypes = evaluate::AllIntrinsicTypes; template struct IndexInTupleHelper {}; template @@ -44,12 +44,14 @@ struct IndexInTupleHelper> { }; static_assert( - std::tuple_size_v < std::numeric_limits::max(), + std::tuple_size_v < std::numeric_limits::max(), "TypeCode is too small"); template -inline constexpr TypeCode typeCodeOf{IndexInTupleHelper::value}; +inline constexpr TypeCode typeCodeOf{ + IndexInTupleHelper::value}; -template using TypeOf = typename std::tuple_element_t; +template +using RuntimeTypeOf = typename std::tuple_element_t; template using HostArgType = std::conditional_t struct CallableHostWrapper { hostFPE.CheckAndRestoreFloatingPointEnvironment(context); return host::CastHostToFortran(res); } else { - common::die("Internal error: Host does not supports rte functions types. " + common::die("Internal error: Host does not supports this function types." "This should not have been called for folding"); return Scalar{}; // unreachable } @@ -93,7 +95,7 @@ template struct CallableHostWrapper { }; template -RteProcedureSymbol::RteProcedureSymbol( +IntrinsicProcedureRuntimeDescription::IntrinsicProcedureRuntimeDescription( const Signature &signature, bool isElemental) : name{signature.name}, returnType{typeCodeOf}, argumentsType{typeCodeOf...}, @@ -119,16 +121,18 @@ using SignatureFromHostFuncPointer = Signature, ArgInfoFromHostType...>; template -HostRteProcedureSymbol::HostRteProcedureSymbol(const std::string &name, - FuncPointer func, bool isElemental) - : RteProcedureSymbol( +HostRuntimeIntrinsicProcedure::HostRuntimeIntrinsicProcedure( + const std::string &name, FuncPointer func, + bool isElemental) + : IntrinsicProcedureRuntimeDescription( SignatureFromHostFuncPointer{name}, isElemental), handle{reinterpret_cast>(func)} {} template typename ConstantContainer, typename TR, typename... TA> std::optional> -HostRte::GetHostProcedureWrapper(const std::string &name) { +HostIntrinsicProceduresLibrary::GetHostProcedureWrapper( + const std::string &name) { if constexpr (host::HostTypeExists()) { auto rteProcRange{procedures.equal_range(name)}; const TypeCode resTypeCode{typeCodeOf}; @@ -165,10 +169,11 @@ HostRte::GetHostProcedureWrapper(const std::string &name) { } template -TargetRteProcedureSymbol::TargetRteProcedureSymbol( +TargetRuntimeIntrinsicProcedure::TargetRuntimeIntrinsicProcedure( const Signature &signature, const std::string &symbolName, bool isElemental) - : RteProcedureSymbol{signature, isElemental}, symbol{symbolName} {} + : IntrinsicProcedureRuntimeDescription{signature, isElemental}, + symbol{symbolName} {} } -#endif // FORTRAN_EVALUATE_RTE_H_ +#endif // FORTRAN_EVALUATE_INTRINSICS_LIBRARY_TEMPLATES_H_ diff --git a/flang/lib/evaluate/rte.cc b/flang/lib/evaluate/intrinsics-library.cc similarity index 84% rename from flang/lib/evaluate/rte.cc rename to flang/lib/evaluate/intrinsics-library.cc index fcf96af..261f1fa 100644 --- a/flang/lib/evaluate/rte.cc +++ b/flang/lib/evaluate/intrinsics-library.cc @@ -14,10 +14,10 @@ // This file defines the runtime libraries for the target as well as a default // set of host rte functions that can be used for folding. -// The default HostRte is built with and functions -// that are guaranteed to exist from the C++ standard. +// The default HostIntrinsicProceduresLibrary is built with and +// functions that are guaranteed to exist from the C++ standard. -#include "rte.h" +#include "intrinsics-library-templates.h" #include "../common/idioms.h" #include #include @@ -27,11 +27,12 @@ #include #endif -namespace Fortran::evaluate::rte { +namespace Fortran::evaluate { using namespace Fortran::parser::literals; // Note: argument passing is ignored in equivalence -bool HostRte::HasEquivalentProcedure(const RteProcedureSymbol &sym) const { +bool HostIntrinsicProceduresLibrary::HasEquivalentProcedure( + const IntrinsicProcedureRuntimeDescription &sym) const { const auto rteProcRange{procedures.equal_range(sym.name)}; const size_t nargs{sym.argumentsType.size()}; for (auto iter{rteProcRange.first}; iter != rteProcRange.second; ++iter) { @@ -54,7 +55,8 @@ bool HostRte::HasEquivalentProcedure(const RteProcedureSymbol &sym) const { return false; } -void HostRte::LoadTargetRteLibrary(const TargetRteLibrary &lib) { +void HostIntrinsicProceduresLibrary::LoadTargetIntrinsicProceduresLibrary( + const TargetIntrinsicProceduresLibrary &lib) { if (dynamicallyLoadedLibraries.find(lib.name) != dynamicallyLoadedLibraries.end()) { return; // already loaded @@ -75,7 +77,7 @@ void HostRte::LoadTargetRteLibrary(const TargetRteLibrary &lib) { // is implementation defined whether this is supported. POSIX mandates // that such cast from function pointers to void* are defined. Hence this // reinterpret_cast is and MUST REMAIN inside ifdef related to POSIX. - AddProcedure(HostRteProcedureSymbol{ + AddProcedure(HostRuntimeIntrinsicProcedure{ sym.second, reinterpret_cast>(func)}); } } @@ -84,7 +86,7 @@ void HostRte::LoadTargetRteLibrary(const TargetRteLibrary &lib) { #endif } -HostRte::~HostRte() { +HostIntrinsicProceduresLibrary::~HostIntrinsicProceduresLibrary() { for (auto iter{dynamicallyLoadedLibraries.begin()}; iter != dynamicallyLoadedLibraries.end(); ++iter) { #ifdef IS_POSIX_COMPLIANT @@ -105,10 +107,12 @@ template static HostT Bessel_yn(std::int64_t n, HostT x) { return std::cyl_neumann(static_cast(n), x); } -template void AddLibmRealHostProcedure(HostRte &hostRte) { +template +void AddLibmRealHostProcedure( + HostIntrinsicProceduresLibrary &hostIntrinsicLibrary) { using F = FuncPointer; using F2 = FuncPointer; - HostRteProcedureSymbol libmSymbols[]{{"acos", F{std::acos}, true}, + HostRuntimeIntrinsicProcedure libmSymbols[]{{"acos", F{std::acos}, true}, {"acosh", F{std::acosh}, true}, {"asin", F{std::asin}, true}, {"asinh", F{std::asinh}, true}, {"atan", F{std::atan}, true}, {"atan", F2{std::atan2}, true}, {"atanh", F{std::atanh}, true}, @@ -119,15 +123,17 @@ template void AddLibmRealHostProcedure(HostRte &hostRte) { {"tan", F{std::tan}, true}, {"tanh", F{std::tanh}, true}}; for (auto sym : libmSymbols) { - if (!hostRte.HasEquivalentProcedure(sym)) { - hostRte.AddProcedure(std::move(sym)); + if (!hostIntrinsicLibrary.HasEquivalentProcedure(sym)) { + hostIntrinsicLibrary.AddProcedure(std::move(sym)); } } } -template void AddLibmComplexHostProcedure(HostRte &hostRte) { +template +void AddLibmComplexHostProcedure( + HostIntrinsicProceduresLibrary &hostIntrinsicLibrary) { using F = FuncPointer, const std::complex &>; - HostRteProcedureSymbol libmSymbols[]{{"acos", F{std::acos}, true}, + HostRuntimeIntrinsicProcedure libmSymbols[]{{"acos", F{std::acos}, true}, {"acosh", F{std::acosh}, true}, {"asin", F{std::asin}, true}, {"asinh", F{std::asinh}, true}, {"atan", F{std::atan}, true}, {"atanh", F{std::atanh}, true}, {"cos", F{std::cos}, true}, @@ -136,8 +142,8 @@ template void AddLibmComplexHostProcedure(HostRte &hostRte) { {"tan", F{std::tan}, true}, {"tanh", F{std::tanh}, true}}; for (auto sym : libmSymbols) { - if (!hostRte.HasEquivalentProcedure(sym)) { - hostRte.AddProcedure(std::move(sym)); + if (!hostIntrinsicLibrary.HasEquivalentProcedure(sym)) { + hostIntrinsicLibrary.AddProcedure(std::move(sym)); } } } @@ -183,32 +189,34 @@ static std::string MakeLibpgmathName(const std::string &name, MathOption m) { } template -static void AddLibpgmathTargetSymbols(TargetRteLibrary &lib, MathOption opt) { +static void AddLibpgmathTargetSymbols( + TargetIntrinsicProceduresLibrary &lib, MathOption opt) { using F = Signature>; const std::string oneArgFuncs[]{"acos", "asin", "atan", "cos", "cosh", "exp", "log", "log10", "sin", "sinh", "tan", "tanh"}; for (const std::string &name : oneArgFuncs) { - lib.AddProcedure(TargetRteProcedureSymbol{ + lib.AddProcedure(TargetRuntimeIntrinsicProcedure{ F{name}, MakeLibpgmathName(name, opt), true}); } if constexpr (T::category == TypeCategory::Real) { using F2 = Signature, ArgumentInfo>; - lib.AddProcedure(TargetRteProcedureSymbol{ + lib.AddProcedure(TargetRuntimeIntrinsicProcedure{ F2{"atan2"}, MakeLibpgmathName("acos", opt), true}); } else { const std::string oneArgCmplxFuncs[]{ "div", "sqrt"}; // for scalar, only complex available for (const std::string &name : oneArgCmplxFuncs) { - lib.AddProcedure(TargetRteProcedureSymbol{ + lib.AddProcedure(TargetRuntimeIntrinsicProcedure{ F{name}, MakeLibpgmathName(name, opt), true}); } } } -TargetRteLibrary BuildLibpgmTargetRteLibrary(MathOption opt) { - TargetRteLibrary lib{"libpgmath"}; +TargetIntrinsicProceduresLibrary BuildLibpgmTargetIntrinsicProceduresLibrary( + MathOption opt) { + TargetIntrinsicProceduresLibrary lib{"libpgmath"}; AddLibpgmathTargetSymbols>(lib, opt); AddLibpgmathTargetSymbols>(lib, opt); AddLibpgmathTargetSymbols>(lib, opt); @@ -218,13 +226,14 @@ TargetRteLibrary BuildLibpgmTargetRteLibrary(MathOption opt) { // Defines which host runtime functions will be used for folding -void HostRte::DefaultInit() { +void HostIntrinsicProceduresLibrary::DefaultInit() { // TODO: when linkage information is available, this needs to be modified to // load runtime accordingly. For now, try loading libpgmath (libpgmath.so // needs to be in a directory from LD_LIBRARY_PATH) and then add libm symbols // when no equivalent symbols were already loaded - TargetRteLibrary libpgmath{BuildLibpgmTargetRteLibrary(MathOption::Precise)}; - LoadTargetRteLibrary(libpgmath); + TargetIntrinsicProceduresLibrary libpgmath{ + BuildLibpgmTargetIntrinsicProceduresLibrary(MathOption::Precise)}; + LoadTargetIntrinsicProceduresLibrary(libpgmath); AddLibmRealHostProcedure(*this); AddLibmRealHostProcedure(*this); diff --git a/flang/lib/evaluate/intrinsics-library.h b/flang/lib/evaluate/intrinsics-library.h new file mode 100644 index 0000000..36afb91c --- /dev/null +++ b/flang/lib/evaluate/intrinsics-library.h @@ -0,0 +1,148 @@ +// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef FORTRAN_EVALUATE_INTRINSICS_LIBRARY_H_ +#define FORTRAN_EVALUATE_INTRINSICS_LIBRARY_H_ + +// Defines structures to be used in F18 when dealing with the intrinsic +// procedures runtime. It abstracts both: +// - the target intrinsic procedure runtime to be used for code generation +// - the host intrinsic runtime to be used for constant folding purposes. +// To avoid unnecessary header circular dependencies, the actual implementation +// of the templatized member function are defined in +// intrinsics-library-templates.h The header at hand is meant to be included by +// files that need to define intrinsic runtime data structure but that do not +// use them directly. To actually use the runtime data structures, +// intrinsics-library-templates.h must be included Note that +// intrinsics-library-templates.h includes the header at hand. + +#include +#include +#include +#include +#include + +namespace Fortran::evaluate { +class FoldingContext; + +using TypeCode = unsigned char; + +template using FuncPointer = TR (*)(TA...); + +enum class PassBy { Ref, Val }; +template struct ArgumentInfo { + using Type = TA; + static constexpr PassBy pass{Pass}; +}; + +template struct Signature { + // Note valid template argument are of form + //...> where TA and TR belong to RuntimeTypes. + // RuntimeTypes is a type union defined in intrinsics-library-templates.h to + // avoid circular dependencies. Argument of type void cannot be passed by + // value. So far TR cannot be a pointer. + const std::string name; +}; + +struct IntrinsicProcedureRuntimeDescription { + const std::string name; + const TypeCode returnType; + const std::vector argumentsType; + const std::vector argumentsPassedBy; + const bool isElemental; + const FuncPointer callable; + // callable only usable by HostRuntimeIntrinsicProcedure but need to be + // created in case TargetRuntimeIntrinsicProcedure is dynamically loaded + // because creating it dynamically would be too complex + + // Construct from description using host independent types (RuntimeTypes) + template + IntrinsicProcedureRuntimeDescription( + const Signature &signature, bool isElemental = false); +}; + +// TargetRuntimeIntrinsicProcedure holds target runtime information +// for an intrinsics procedure. +struct TargetRuntimeIntrinsicProcedure : IntrinsicProcedureRuntimeDescription { + // Construct from description using host independent types (RuntimeTypes) + // Note: passing ref/val also needs to be passed by template to build + // the callable + template + TargetRuntimeIntrinsicProcedure(const Signature &signature, + const std::string &symbolName, bool isElemental = false); + const std::string symbol; +}; + +struct TargetIntrinsicProceduresLibrary { + TargetIntrinsicProceduresLibrary(const std::string &name) : name{name} {} + void AddProcedure(TargetRuntimeIntrinsicProcedure &&sym) { + const std::string name{sym.name}; + procedures.insert(std::make_pair(name, std::move(sym))); + } + const std::string name; + std::multimap procedures; +}; + +// HostRuntimeIntrinsicProcedure allows host runtime function to be called for +// constant folding. +struct HostRuntimeIntrinsicProcedure : IntrinsicProcedureRuntimeDescription { + // Construct from runtime pointer with host types (float, double....) + template + HostRuntimeIntrinsicProcedure(const std::string &name, + FuncPointer func, bool isElemental = false); + HostRuntimeIntrinsicProcedure( + const IntrinsicProcedureRuntimeDescription &rteProc, + FuncPointer handle) + : IntrinsicProcedureRuntimeDescription{rteProc}, handle{handle} {} + const FuncPointer handle; +}; + +// Defines a wrapper type that indirects calls to host runtime functions. +// Valid ConstantContainer are Scalar (only for elementals) and Constant. +template typename ConstantContainer, typename TR, + typename... TA> +using HostProcedureWrapper = std::function( + FoldingContext &, ConstantContainer...)>; + +// HostIntrinsicProceduresLibrary is a data structure that holds +// HostRuntimeIntrinsicProcedure elements. It is meant for constant folding. +// When queried for an intrinsic procedure, it can return a callable object that +// implements this intrinsic if a host runtime function pointer for this +// intrinsic was added to its data structure. It can also dynamically load +// function pointer from a TargetIntrinsicProceduresLibrary if the related +// library is available on the host. +struct HostIntrinsicProceduresLibrary { + void AddProcedure(HostRuntimeIntrinsicProcedure &&sym) { + const std::string name{sym.name}; + procedures.insert(std::make_pair(name, std::move(sym))); + } + bool HasEquivalentProcedure( + const IntrinsicProcedureRuntimeDescription &sym) const; + HostIntrinsicProceduresLibrary() { DefaultInit(); } + ~HostIntrinsicProceduresLibrary(); + void DefaultInit(); // Try loading libpgmath functions and then load + // functions from and + void LoadTargetIntrinsicProceduresLibrary( + const TargetIntrinsicProceduresLibrary &lib); + template typename ConstantContainer, typename TR, + typename... TA> + std::optional> + GetHostProcedureWrapper(const std::string &name); + std::multimap procedures; + std::map + dynamicallyLoadedLibraries; // keep the handles for dlclose +}; + +} +#endif // FORTRAN_EVALUATE_INTRINSICS_LIBRARY_H_ diff --git a/flang/lib/evaluate/rte-interface.h b/flang/lib/evaluate/rte-interface.h deleted file mode 100644 index bacaa2e..0000000 --- a/flang/lib/evaluate/rte-interface.h +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef FORTRAN_EVALUATE_RTE_INTERFACE_H_ -#define FORTRAN_EVALUATE_RTE_INTERFACE_H_ - -// Defines the structure that must be used in F18 when dealing with the -// runtime, either with the target runtime or with the host runtime for -// folding purposes -// To avoid unnecessary header circular dependencies, the actual implementation -// of the templatized member function are defined in rte.h -// The header at hand must be included in order to add the rte interface data -// structure as a member of some structure. -// To actually use the rte interface, rte.h must be included. Note that rte.h -// includes the header at hand. - -#include -#include -#include -#include -#include - -namespace Fortran::evaluate { -class FoldingContext; -namespace rte { - -using TypeCode = unsigned char; - -template using FuncPointer = TR (*)(TA...); - -enum class PassBy { Ref, Val }; -template struct ArgumentInfo { - using Type = TA; - static constexpr PassBy pass{Pass}; -}; - -template struct Signature { - // Note valid template argument are of form - //...> where TA and TR belong to RteTypes. - // RteTypes is a type union defined in rte.h to avoid circular dependencies. - // Argument of type void cannot be passed by value - // So far TR cannot be a pointer. - const std::string name; -}; - -struct RteProcedureSymbol { - const std::string name; - const TypeCode returnType; - const std::vector argumentsType; - const std::vector argumentsPassedBy; - const bool isElemental; - const FuncPointer callable; - // callable only usable by HostRteProcedureSymbol but need to be created in - // case TargetRteProcedureSymbol is dynamically loaded because creating it - // dynamically would be too complex - - // Construct from description using host independent types (RteTypes) - template - RteProcedureSymbol( - const Signature &signature, bool isElemental = false); -}; - -// For target rte library info -struct TargetRteProcedureSymbol : RteProcedureSymbol { - // Construct from description using host independent types (RteTypes) - // Note: passing ref/val also needs to be passed by template to build - // the callable - template - TargetRteProcedureSymbol(const Signature &signature, - const std::string &symbolName, bool isElemental = false); - const std::string symbol; -}; - -struct TargetRteLibrary { - TargetRteLibrary(const std::string &name) : name{name} {} - void AddProcedure(TargetRteProcedureSymbol &&sym) { - const std::string name{sym.name}; - procedures.insert(std::make_pair(name, std::move(sym))); - } - const std::string name; - std::multimap procedures; -}; - -// To use host runtime for folding -struct HostRteProcedureSymbol : RteProcedureSymbol { - // Construct from runtime pointer with host types (float, double....) - template - HostRteProcedureSymbol(const std::string &name, - FuncPointer func, bool isElemental = false); - HostRteProcedureSymbol( - const RteProcedureSymbol &rteProc, FuncPointer handle) - : RteProcedureSymbol{rteProc}, handle{handle} {} - const FuncPointer handle; -}; - -// valid ConstantContainer are Scalar (only for elementals) and Constant -template typename ConstantContainer, typename TR, - typename... TA> -using HostProcedureWrapper = std::function( - FoldingContext &, ConstantContainer...)>; - -struct HostRte { - void AddProcedure(HostRteProcedureSymbol &&sym) { - const std::string name{sym.name}; - procedures.insert(std::make_pair(name, std::move(sym))); - } - bool HasEquivalentProcedure(const RteProcedureSymbol &sym) const; - HostRte() { DefaultInit(); } - ~HostRte(); - void DefaultInit(); // load functions from and - void LoadTargetRteLibrary(const TargetRteLibrary &lib); // TODO - template typename ConstantContainer, typename TR, - typename... TA> - std::optional> - GetHostProcedureWrapper(const std::string &name); - // some data structure of HostRteProcedureSymbol - std::multimap procedures; - std::map - dynamicallyLoadedLibraries; // keep the handles for dlclose -}; - -} -} -#endif // FORTRAN_EVALUATE_RTE_INTERFACE_H_