forked from OSchip/llvm-project
162 lines
6.3 KiB
C++
162 lines
6.3 KiB
C++
//===-- runtime/type-info.h -------------------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef FORTRAN_RUNTIME_TYPE_INFO_H_
|
|
#define FORTRAN_RUNTIME_TYPE_INFO_H_
|
|
|
|
// A C++ perspective of the derived type description schemata in
|
|
// flang/module/__fortran_type_info.f90.
|
|
|
|
#include "descriptor.h"
|
|
#include "flang/Common/Fortran.h"
|
|
#include <cinttypes>
|
|
#include <memory>
|
|
|
|
namespace Fortran::runtime::typeInfo {
|
|
|
|
class DerivedType {
|
|
public:
|
|
~DerivedType();
|
|
|
|
// This member comes first because it's used like a vtable by generated code.
|
|
// It includes all of the ancestor types' bindings, if any, first,
|
|
// with any overrides from descendants already applied to them. Local
|
|
// bindings then follow in alphabetic order of binding name.
|
|
StaticDescriptor<1> binding; // TYPE(BINDING), DIMENSION(:), POINTER
|
|
|
|
StaticDescriptor<0> name; // CHARACTER(:), POINTER
|
|
|
|
std::uint64_t sizeInBytes{0};
|
|
StaticDescriptor<0> parent; // TYPE(DERIVEDTYPE), POINTER
|
|
|
|
// Instantiations of a parameterized derived type with KIND type
|
|
// parameters will point this data member to the description of
|
|
// the original uninstantiated type, which may be shared from a
|
|
// module via use association. The original uninstantiated derived
|
|
// type description will point to itself. Derived types that have
|
|
// no KIND type parameters will have a null pointer here.
|
|
StaticDescriptor<0> uninstantiated; // TYPE(DERIVEDTYPE), POINTER
|
|
|
|
// TODO: flags for SEQUENCE, BIND(C), any PRIVATE component(? see 7.5.2)
|
|
std::uint64_t typeHash{0};
|
|
|
|
// These pointer targets include all of the items from the parent, if any.
|
|
StaticDescriptor<1> kindParameter; // pointer to rank-1 array of INTEGER(8)
|
|
StaticDescriptor<1> lenParameterKind; // pointer to rank-1 array of INTEGER(1)
|
|
|
|
// This array of local data components includes the parent component.
|
|
// Components are in alphabetic order.
|
|
// It does not include procedure pointer components.
|
|
StaticDescriptor<1, true> component; // TYPE(COMPONENT), POINTER, DIMENSION(:)
|
|
|
|
// Procedure pointer components
|
|
StaticDescriptor<1, true> procPtr; // TYPE(PROCPTR), POINTER, DIMENSION(:)
|
|
|
|
// Does not include special bindings from ancestral types.
|
|
StaticDescriptor<1, true>
|
|
special; // TYPE(SPECIALBINDING), POINTER, DIMENSION(:)
|
|
|
|
std::size_t LenParameters() const {
|
|
return lenParameterKind.descriptor().Elements();
|
|
}
|
|
};
|
|
|
|
using ProcedurePointer = void (*)(); // TYPE(C_FUNPTR)
|
|
|
|
struct Binding {
|
|
ProcedurePointer proc;
|
|
StaticDescriptor<0> name; // CHARACTER(:), POINTER
|
|
};
|
|
|
|
struct Value {
|
|
enum class Genre : std::uint8_t {
|
|
Deferred = 1,
|
|
Explicit = 2,
|
|
LenParameter = 3
|
|
};
|
|
Genre genre{Genre::Explicit};
|
|
// The value encodes an index into the table of LEN type parameters in
|
|
// a descriptor's addendum for genre == Genre::LenParameter.
|
|
TypeParameterValue value{0};
|
|
};
|
|
|
|
struct Component {
|
|
enum class Genre : std::uint8_t { Data, Pointer, Allocatable, Automatic };
|
|
StaticDescriptor<0> name; // CHARACTER(:), POINTER
|
|
Genre genre{Genre::Data};
|
|
std::uint8_t category; // common::TypeCategory
|
|
std::uint8_t kind{0};
|
|
std::uint8_t rank{0};
|
|
std::uint64_t offset{0};
|
|
Value characterLen; // for TypeCategory::Character
|
|
StaticDescriptor<0, true> derivedType; // TYPE(DERIVEDTYPE), POINTER
|
|
StaticDescriptor<1, true> lenValue; // TYPE(VALUE), POINTER, DIMENSION(:)
|
|
StaticDescriptor<2, true> bounds; // TYPE(VALUE), POINTER, DIMENSION(2,:)
|
|
char *initialization{nullptr}; // for Genre::Data and Pointer
|
|
// TODO: cobounds
|
|
// TODO: `PRIVATE` attribute
|
|
};
|
|
|
|
struct ProcPtrComponent {
|
|
StaticDescriptor<0> name; // CHARACTER(:), POINTER
|
|
std::uint64_t offset{0};
|
|
ProcedurePointer procInitialization; // for Genre::Procedure
|
|
};
|
|
|
|
struct SpecialBinding {
|
|
enum class Which : std::uint8_t {
|
|
None = 0,
|
|
Assignment = 4,
|
|
ElementalAssignment = 5,
|
|
Final = 8,
|
|
ElementalFinal = 9,
|
|
AssumedRankFinal = 10,
|
|
ReadFormatted = 16,
|
|
ReadUnformatted = 17,
|
|
WriteFormatted = 18,
|
|
WriteUnformatted = 19
|
|
} which{Which::None};
|
|
|
|
// Used for Which::Final only. Which::Assignment always has rank 0, as
|
|
// type-bound defined assignment for rank > 0 must be elemental
|
|
// due to the required passed object dummy argument, which are scalar.
|
|
// User defined derived type I/O is always scalar.
|
|
std::uint8_t rank{0};
|
|
|
|
// The following little bit-set identifies which dummy arguments are
|
|
// passed via descriptors for their derived type arguments.
|
|
// Which::Assignment and Which::ElementalAssignment:
|
|
// Set to 1, 2, or (usually 3).
|
|
// The passed-object argument (usually the "to") is always passed via a
|
|
// a descriptor in the cases where the runtime will call a defined
|
|
// assignment because these calls are to type-bound generics,
|
|
// not generic interfaces, and type-bound generic defined assigment
|
|
// may appear only in an extensible type and requires a passed-object
|
|
// argument (see C774), and passed-object arguments to TBPs must be
|
|
// both polymorphic and scalar (C760). The non-passed-object argument
|
|
// (usually the "from") is usually, but not always, also a descriptor.
|
|
// Which::Final and Which::ElementalFinal:
|
|
// Set to 1 when dummy argument is assumed-shape; otherwise, the
|
|
// argument can be passed by address. (Fortran guarantees that
|
|
// any finalized object must be whole and contiguous by restricting
|
|
// the use of DEALLOCATE on pointers. The dummy argument of an
|
|
// elemental final subroutine must be scalar and monomorphic, but
|
|
// use a descriptors when the type has LEN parameters.)
|
|
// Which::AssumedRankFinal: flag must necessarily be set
|
|
// User derived type I/O:
|
|
// Set to 1 when "dtv" initial dummy argument is polymorphic, which is
|
|
// the case when and only when the derived type is extensible.
|
|
// When false, the user derived type I/O subroutine must have been
|
|
// called via a generic interface, not a generic TBP.
|
|
std::uint8_t isArgDescriptorSet{0};
|
|
|
|
ProcedurePointer proc{nullptr};
|
|
};
|
|
} // namespace Fortran::runtime::typeInfo
|
|
#endif // FORTRAN_RUNTIME_TYPE_INFO_H_
|