forked from OSchip/llvm-project
[flang] renaming to focus scope on intrinsic runtime
Original-commit: flang-compiler/f18@7cfd33b178 Tree-same-pre-rewrite: false
This commit is contained in:
parent
fa3a179fec
commit
8d032dc96b
|
@ -29,7 +29,7 @@ add_library(FortranEvaluate
|
|||
tools.cc
|
||||
type.cc
|
||||
variable.cc
|
||||
rte.cc
|
||||
intrinsics-library.cc
|
||||
)
|
||||
|
||||
target_link_libraries(FortranEvaluate
|
||||
|
|
|
@ -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 <cinttypes>
|
||||
#include <map>
|
||||
|
||||
|
@ -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<std::int64_t> GetImpliedDo(parser::CharBlock) const;
|
||||
|
@ -241,7 +243,7 @@ private:
|
|||
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);
|
||||
|
|
|
@ -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<Type<TypeCategory::Real, KIND>> 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<Scalar, T, T>(name)}) {
|
||||
if (auto callable{context.hostIntrinsicsLibrary()
|
||||
.GetHostProcedureWrapper<Scalar, T, T>(name)}) {
|
||||
return FoldElementalIntrinsic<T, T>(
|
||||
context, std::move(funcRef), *callable);
|
||||
} else {
|
||||
|
@ -342,9 +342,8 @@ Expr<Type<TypeCategory::Real, KIND>> FoldOperation(FoldingContext &context,
|
|||
}
|
||||
}
|
||||
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 {
|
||||
|
@ -361,8 +360,8 @@ Expr<Type<TypeCategory::Real, KIND>> FoldOperation(FoldingContext &context,
|
|||
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 {
|
||||
|
@ -423,8 +422,8 @@ Expr<Type<TypeCategory::Complex, KIND>> 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<Scalar, T, T>(name)}) {
|
||||
if (auto callable{context.hostIntrinsicsLibrary()
|
||||
.GetHostProcedureWrapper<Scalar, T, T>(name)}) {
|
||||
return FoldElementalIntrinsic<T, T>(
|
||||
context, std::move(funcRef), *callable);
|
||||
} else {
|
||||
|
|
|
@ -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 <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>
|
||||
|
@ -44,12 +44,14 @@ struct IndexInTupleHelper<T, std::tuple<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,
|
||||
|
@ -84,7 +86,7 @@ template<typename TR, typename... ArgInfo> struct CallableHostWrapper {
|
|||
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
|
||||
}
|
||||
|
@ -93,7 +95,7 @@ template<typename TR, typename... ArgInfo> struct CallableHostWrapper {
|
|||
};
|
||||
|
||||
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>...},
|
||||
|
@ -119,16 +121,18 @@ using SignatureFromHostFuncPointer =
|
|||
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>};
|
||||
|
@ -165,10 +169,11 @@ HostRte::GetHostProcedureWrapper(const std::string &name) {
|
|||
}
|
||||
|
||||
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_
|
|
@ -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 <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>
|
||||
|
@ -27,11 +27,12 @@
|
|||
#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) {
|
||||
|
@ -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<FuncPointer<void *>>(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<typename HostT> static HostT Bessel_yn(std::int64_t n, HostT x) {
|
|||
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},
|
||||
|
@ -119,15 +123,17 @@ template<typename HostT> 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<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},
|
||||
|
@ -136,8 +142,8 @@ template<typename HostT> 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<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);
|
||||
|
@ -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<float>(*this);
|
||||
AddLibmRealHostProcedure<double>(*this);
|
|
@ -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 <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_
|
|
@ -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 <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_
|
Loading…
Reference in New Issue