tools.cc
type.cc
variable.cc
- rte.cc
+ intrinsics-library.cc
)
target_link_libraries(FortranEvaluate
#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"
#include "../common/restorer.h"
#include "../parser/char-block.h"
#include "../parser/message.h"
-#include "rte-interface.h"
#include <cinttypes>
#include <map>
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<std::int64_t> GetImpliedDo(parser::CharBlock) const;
bool bigEndian_{false};
const semantics::DerivedTypeSpec *pdtInstance_{nullptr};
std::map<parser::CharBlock, std::int64_t> impliedDos_;
- rte::HostRte hostRte_;
+ HostIntrinsicProceduresLibrary hostIntrinsicsLibrary_;
};
void RealFlagWarnings(FoldingContext &, const RealFlags &, const char *op);
#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"
const std::string name{intrinsic->name};
if (name == "acos" || name == "acosh" ||
(name == "atan" && funcRef.arguments().size() == 1)) {
- if (auto callable{
- context.hostRte().GetHostProcedureWrapper<Scalar, T, T>(name)}) {
+ if (auto callable{context.hostIntrinsicsLibrary()
+ .GetHostProcedureWrapper<Scalar, T, T>(name)}) {
return FoldElementalIntrinsic<T, T>(
context, std::move(funcRef), *callable);
} else {
}
}
if (name == "atan") {
- if (auto callable{
- context.hostRte().GetHostProcedureWrapper<Scalar, T, T, T>(
- name)}) {
+ if (auto callable{context.hostIntrinsicsLibrary()
+ .GetHostProcedureWrapper<Scalar, T, T, T>(name)}) {
return FoldElementalIntrinsic<T, T, T>(
context, std::move(funcRef), *callable);
} else {
Fold(context, ConvertToType<Int8>(std::move(*n)));
}
if (auto callable{
- context.hostRte().GetHostProcedureWrapper<Scalar, T, Int8, T>(
- name)}) {
+ context.hostIntrinsicsLibrary()
+ .GetHostProcedureWrapper<Scalar, T, Int8, T>(name)}) {
return FoldElementalIntrinsic<T, Int8, T>(
context, std::move(funcRef), *callable);
} else {
const std::string name{intrinsic->name};
if (name == "acos" || name == "acosh" || name == "asin" || name == "atan" ||
name == "atanh") {
- if (auto callable{
- context.hostRte().GetHostProcedureWrapper<Scalar, T, T>(name)}) {
+ if (auto callable{context.hostIntrinsicsLibrary()
+ .GetHostProcedureWrapper<Scalar, T, T>(name)}) {
return FoldElementalIntrinsic<T, T>(
context, std::move(funcRef), *callable);
} else {
// 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"
#include <tuple>
#include <type_traits>
-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<typename T, typename... TT> struct IndexInTupleHelper {};
template<typename T, typename... TT>
};
static_assert(
- std::tuple_size_v<RteTypes> < std::numeric_limits<TypeCode>::max(),
+ std::tuple_size_v<RuntimeTypes> < std::numeric_limits<TypeCode>::max(),
"TypeCode is too small");
template<typename T>
-inline constexpr TypeCode typeCodeOf{IndexInTupleHelper<T, RteTypes>::value};
+inline constexpr TypeCode typeCodeOf{
+ IndexInTupleHelper<T, RuntimeTypes>::value};
-template<TypeCode n> using TypeOf = typename std::tuple_element_t<n, RteTypes>;
+template<TypeCode n>
+using RuntimeTypeOf = typename std::tuple_element_t<n, RuntimeTypes>;
template<typename TA, PassBy Pass>
using HostArgType = std::conditional_t<Pass == PassBy::Ref,
hostFPE.CheckAndRestoreFloatingPointEnvironment(context);
return host::CastHostToFortran<TR>(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<TR>{}; // unreachable
}
};
template<typename TR, typename... ArgInfo>
-RteProcedureSymbol::RteProcedureSymbol(
+IntrinsicProcedureRuntimeDescription::IntrinsicProcedureRuntimeDescription(
const Signature<TR, ArgInfo...> &signature, bool isElemental)
: name{signature.name}, returnType{typeCodeOf<TR>},
argumentsType{typeCodeOf<typename ArgInfo::Type>...},
Signature<host::FortranType<HostTR>, ArgInfoFromHostType<HostTA>...>;
template<typename HostTR, typename... HostTA>
-HostRteProcedureSymbol::HostRteProcedureSymbol(const std::string &name,
- FuncPointer<HostTR, HostTA...> func, bool isElemental)
- : RteProcedureSymbol(
+HostRuntimeIntrinsicProcedure::HostRuntimeIntrinsicProcedure(
+ const std::string &name, FuncPointer<HostTR, HostTA...> func,
+ bool isElemental)
+ : IntrinsicProcedureRuntimeDescription(
SignatureFromHostFuncPointer<HostTR, HostTA...>{name}, isElemental),
handle{reinterpret_cast<FuncPointer<void *>>(func)} {}
template<template<typename> typename ConstantContainer, typename TR,
typename... TA>
std::optional<HostProcedureWrapper<ConstantContainer, TR, TA...>>
-HostRte::GetHostProcedureWrapper(const std::string &name) {
+HostIntrinsicProceduresLibrary::GetHostProcedureWrapper(
+ const std::string &name) {
if constexpr (host::HostTypeExists<TR, TA...>()) {
auto rteProcRange{procedures.equal_range(name)};
const TypeCode resTypeCode{typeCodeOf<TR>};
}
template<typename TR, typename... ArgInfo>
-TargetRteProcedureSymbol::TargetRteProcedureSymbol(
+TargetRuntimeIntrinsicProcedure::TargetRuntimeIntrinsicProcedure(
const Signature<TR, ArgInfo...> &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_
// 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 <cmath> and <complex> functions
-// that are guaranteed to exist from the C++ standard.
+// The default HostIntrinsicProceduresLibrary is built with <cmath> and
+// <complex> functions that are guaranteed to exist from the C++ standard.
-#include "rte.h"
+#include "intrinsics-library-templates.h"
#include "../common/idioms.h"
#include <cerrno>
#include <cfenv>
#include <dlfcn.h>
#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) {
return false;
}
-void HostRte::LoadTargetRteLibrary(const TargetRteLibrary &lib) {
+void HostIntrinsicProceduresLibrary::LoadTargetIntrinsicProceduresLibrary(
+ const TargetIntrinsicProceduresLibrary &lib) {
if (dynamicallyLoadedLibraries.find(lib.name) !=
dynamicallyLoadedLibraries.end()) {
return; // already loaded
// 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<FuncPointer<void *>>(func)});
}
}
#endif
}
-HostRte::~HostRte() {
+HostIntrinsicProceduresLibrary::~HostIntrinsicProceduresLibrary() {
for (auto iter{dynamicallyLoadedLibraries.begin()};
iter != dynamicallyLoadedLibraries.end(); ++iter) {
#ifdef IS_POSIX_COMPLIANT
return std::cyl_neumann(static_cast<HostT>(n), x);
}
-template<typename HostT> void AddLibmRealHostProcedure(HostRte &hostRte) {
+template<typename HostT>
+void AddLibmRealHostProcedure(
+ HostIntrinsicProceduresLibrary &hostIntrinsicLibrary) {
using F = FuncPointer<HostT, HostT>;
using F2 = FuncPointer<HostT, HostT, HostT>;
- 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},
{"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<typename HostT> void AddLibmComplexHostProcedure(HostRte &hostRte) {
+template<typename HostT>
+void AddLibmComplexHostProcedure(
+ HostIntrinsicProceduresLibrary &hostIntrinsicLibrary) {
using F = FuncPointer<std::complex<HostT>, const std::complex<HostT> &>;
- 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},
{"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<typename T>
-static void AddLibpgmathTargetSymbols(TargetRteLibrary &lib, MathOption opt) {
+static void AddLibpgmathTargetSymbols(
+ TargetIntrinsicProceduresLibrary &lib, MathOption opt) {
using F = Signature<T, ArgumentInfo<T, PassBy::Val>>;
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<T>(name, opt), true});
}
if constexpr (T::category == TypeCategory::Real) {
using F2 = Signature<T, ArgumentInfo<T, PassBy::Val>,
ArgumentInfo<T, PassBy::Val>>;
- lib.AddProcedure(TargetRteProcedureSymbol{
+ lib.AddProcedure(TargetRuntimeIntrinsicProcedure{
F2{"atan2"}, MakeLibpgmathName<T>("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<T>(name, opt), true});
}
}
}
-TargetRteLibrary BuildLibpgmTargetRteLibrary(MathOption opt) {
- TargetRteLibrary lib{"libpgmath"};
+TargetIntrinsicProceduresLibrary BuildLibpgmTargetIntrinsicProceduresLibrary(
+ MathOption opt) {
+ TargetIntrinsicProceduresLibrary lib{"libpgmath"};
AddLibpgmathTargetSymbols<Type<TypeCategory::Real, 4>>(lib, opt);
AddLibpgmathTargetSymbols<Type<TypeCategory::Real, 8>>(lib, opt);
AddLibpgmathTargetSymbols<Type<TypeCategory::Complex, 4>>(lib, 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<float>(*this);
AddLibmRealHostProcedure<double>(*this);
--- /dev/null
+// 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 <functional>
+#include <map>
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace Fortran::evaluate {
+class FoldingContext;
+
+using TypeCode = unsigned char;
+
+template<typename TR, typename... TA> using FuncPointer = TR (*)(TA...);
+
+enum class PassBy { Ref, Val };
+template<typename TA, PassBy Pass = PassBy::Ref> struct ArgumentInfo {
+ using Type = TA;
+ static constexpr PassBy pass{Pass};
+};
+
+template<typename TR, typename... ArgInfo> struct Signature {
+ // Note valid template argument are of form
+ //<TR, ArgumentInfo<TA, PassBy>...> 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<TypeCode> argumentsType;
+ const std::vector<PassBy> argumentsPassedBy;
+ const bool isElemental;
+ const FuncPointer<void *> 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<typename TR, typename... ArgInfo>
+ IntrinsicProcedureRuntimeDescription(
+ const Signature<TR, ArgInfo...> &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<typename TR, typename... ArgInfo>
+ TargetRuntimeIntrinsicProcedure(const Signature<TR, ArgInfo...> &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<std::string, const TargetRuntimeIntrinsicProcedure> 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<typename HostTR, typename... HostTA>
+ HostRuntimeIntrinsicProcedure(const std::string &name,
+ FuncPointer<HostTR, HostTA...> func, bool isElemental = false);
+ HostRuntimeIntrinsicProcedure(
+ const IntrinsicProcedureRuntimeDescription &rteProc,
+ FuncPointer<void *> handle)
+ : IntrinsicProcedureRuntimeDescription{rteProc}, handle{handle} {}
+ const FuncPointer<void *> handle;
+};
+
+// Defines a wrapper type that indirects calls to host runtime functions.
+// Valid ConstantContainer are Scalar (only for elementals) and Constant.
+template<template<typename> typename ConstantContainer, typename TR,
+ typename... TA>
+using HostProcedureWrapper = std::function<ConstantContainer<TR>(
+ FoldingContext &, ConstantContainer<TA>...)>;
+
+// 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 <cmath> and <complex>
+ void LoadTargetIntrinsicProceduresLibrary(
+ const TargetIntrinsicProceduresLibrary &lib);
+ template<template<typename> typename ConstantContainer, typename TR,
+ typename... TA>
+ std::optional<HostProcedureWrapper<ConstantContainer, TR, TA...>>
+ GetHostProcedureWrapper(const std::string &name);
+ std::multimap<std::string, const HostRuntimeIntrinsicProcedure> procedures;
+ std::map<std::string, void *>
+ dynamicallyLoadedLibraries; // keep the handles for dlclose
+};
+
+}
+#endif // FORTRAN_EVALUATE_INTRINSICS_LIBRARY_H_
+++ /dev/null
-// 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 <functional>
-#include <map>
-#include <optional>
-#include <string>
-#include <vector>
-
-namespace Fortran::evaluate {
-class FoldingContext;
-namespace rte {
-
-using TypeCode = unsigned char;
-
-template<typename TR, typename... TA> using FuncPointer = TR (*)(TA...);
-
-enum class PassBy { Ref, Val };
-template<typename TA, PassBy Pass = PassBy::Ref> struct ArgumentInfo {
- using Type = TA;
- static constexpr PassBy pass{Pass};
-};
-
-template<typename TR, typename... ArgInfo> struct Signature {
- // Note valid template argument are of form
- //<TR, ArgumentInfo<TA, PassBy>...> 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<TypeCode> argumentsType;
- const std::vector<PassBy> argumentsPassedBy;
- const bool isElemental;
- const FuncPointer<void *> 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<typename TR, typename... ArgInfo>
- RteProcedureSymbol(
- const Signature<TR, ArgInfo...> &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<typename TR, typename... ArgInfo>
- TargetRteProcedureSymbol(const Signature<TR, ArgInfo...> &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<std::string, const TargetRteProcedureSymbol> procedures;
-};
-
-// To use host runtime for folding
-struct HostRteProcedureSymbol : RteProcedureSymbol {
- // Construct from runtime pointer with host types (float, double....)
- template<typename HostTR, typename... HostTA>
- HostRteProcedureSymbol(const std::string &name,
- FuncPointer<HostTR, HostTA...> func, bool isElemental = false);
- HostRteProcedureSymbol(
- const RteProcedureSymbol &rteProc, FuncPointer<void *> handle)
- : RteProcedureSymbol{rteProc}, handle{handle} {}
- const FuncPointer<void *> handle;
-};
-
-// valid ConstantContainer are Scalar (only for elementals) and Constant
-template<template<typename> typename ConstantContainer, typename TR,
- typename... TA>
-using HostProcedureWrapper = std::function<ConstantContainer<TR>(
- FoldingContext &, ConstantContainer<TA>...)>;
-
-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 <cmath> and <complex>
- void LoadTargetRteLibrary(const TargetRteLibrary &lib); // TODO
- template<template<typename> typename ConstantContainer, typename TR,
- typename... TA>
- std::optional<HostProcedureWrapper<ConstantContainer, TR, TA...>>
- GetHostProcedureWrapper(const std::string &name);
- // some data structure of HostRteProcedureSymbol
- std::multimap<std::string, const HostRteProcedureSymbol> procedures;
- std::map<std::string, void *>
- dynamicallyLoadedLibraries; // keep the handles for dlclose
-};
-
-}
-}
-#endif // FORTRAN_EVALUATE_RTE_INTERFACE_H_