1 //===-- runtime/type-info.h -------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef FORTRAN_RUNTIME_TYPE_INFO_H_ 10 #define FORTRAN_RUNTIME_TYPE_INFO_H_ 11 12 // A C++ perspective of the derived type description schemata in 13 // flang/module/__fortran_type_info.f90. 14 15 #include "descriptor.h" 16 #include "flang/Common/Fortran.h" 17 #include <cinttypes> 18 #include <memory> 19 20 namespace Fortran::runtime::typeInfo { 21 22 class DerivedType { 23 public: 24 ~DerivedType(); 25 26 // This member comes first because it's used like a vtable by generated code. 27 // It includes all of the ancestor types' bindings, if any, first, 28 // with any overrides from descendants already applied to them. Local 29 // bindings then follow in alphabetic order of binding name. 30 StaticDescriptor<1> binding; // TYPE(BINDING), DIMENSION(:), POINTER 31 32 StaticDescriptor<0> name; // CHARACTER(:), POINTER 33 34 std::uint64_t sizeInBytes{0}; 35 StaticDescriptor<0> parent; // TYPE(DERIVEDTYPE), POINTER 36 37 // Instantiations of a parameterized derived type with KIND type 38 // parameters will point this data member to the description of 39 // the original uninstantiated type, which may be shared from a 40 // module via use association. The original uninstantiated derived 41 // type description will point to itself. Derived types that have 42 // no KIND type parameters will have a null pointer here. 43 StaticDescriptor<0> uninstantiated; // TYPE(DERIVEDTYPE), POINTER 44 45 // TODO: flags for SEQUENCE, BIND(C), any PRIVATE component(? see 7.5.2) 46 std::uint64_t typeHash{0}; 47 48 // These pointer targets include all of the items from the parent, if any. 49 StaticDescriptor<1> kindParameter; // pointer to rank-1 array of INTEGER(8) 50 StaticDescriptor<1> lenParameterKind; // pointer to rank-1 array of INTEGER(1) 51 52 // This array of local data components includes the parent component. 53 // Components are in alphabetic order. 54 // It does not include procedure pointer components. 55 StaticDescriptor<1, true> component; // TYPE(COMPONENT), POINTER, DIMENSION(:) 56 57 // Procedure pointer components 58 StaticDescriptor<1, true> procPtr; // TYPE(PROCPTR), POINTER, DIMENSION(:) 59 60 // Does not include special bindings from ancestral types. 61 StaticDescriptor<1, true> 62 special; // TYPE(SPECIALBINDING), POINTER, DIMENSION(:) 63 LenParameters()64 std::size_t LenParameters() const { 65 return lenParameterKind.descriptor().Elements(); 66 } 67 }; 68 69 using ProcedurePointer = void (*)(); // TYPE(C_FUNPTR) 70 71 struct Binding { 72 ProcedurePointer proc; 73 StaticDescriptor<0> name; // CHARACTER(:), POINTER 74 }; 75 76 struct Value { 77 enum class Genre : std::uint8_t { 78 Deferred = 1, 79 Explicit = 2, 80 LenParameter = 3 81 }; 82 Genre genre{Genre::Explicit}; 83 // The value encodes an index into the table of LEN type parameters in 84 // a descriptor's addendum for genre == Genre::LenParameter. 85 TypeParameterValue value{0}; 86 }; 87 88 struct Component { 89 enum class Genre : std::uint8_t { Data, Pointer, Allocatable, Automatic }; 90 StaticDescriptor<0> name; // CHARACTER(:), POINTER 91 Genre genre{Genre::Data}; 92 std::uint8_t category; // common::TypeCategory 93 std::uint8_t kind{0}; 94 std::uint8_t rank{0}; 95 std::uint64_t offset{0}; 96 Value characterLen; // for TypeCategory::Character 97 StaticDescriptor<0, true> derivedType; // TYPE(DERIVEDTYPE), POINTER 98 StaticDescriptor<1, true> lenValue; // TYPE(VALUE), POINTER, DIMENSION(:) 99 StaticDescriptor<2, true> bounds; // TYPE(VALUE), POINTER, DIMENSION(2,:) 100 char *initialization{nullptr}; // for Genre::Data and Pointer 101 // TODO: cobounds 102 // TODO: `PRIVATE` attribute 103 }; 104 105 struct ProcPtrComponent { 106 StaticDescriptor<0> name; // CHARACTER(:), POINTER 107 std::uint64_t offset{0}; 108 ProcedurePointer procInitialization; // for Genre::Procedure 109 }; 110 111 struct SpecialBinding { 112 enum class Which : std::uint8_t { 113 None = 0, 114 Assignment = 4, 115 ElementalAssignment = 5, 116 Final = 8, 117 ElementalFinal = 9, 118 AssumedRankFinal = 10, 119 ReadFormatted = 16, 120 ReadUnformatted = 17, 121 WriteFormatted = 18, 122 WriteUnformatted = 19 123 } which{Which::None}; 124 125 // Used for Which::Final only. Which::Assignment always has rank 0, as 126 // type-bound defined assignment for rank > 0 must be elemental 127 // due to the required passed object dummy argument, which are scalar. 128 // User defined derived type I/O is always scalar. 129 std::uint8_t rank{0}; 130 131 // The following little bit-set identifies which dummy arguments are 132 // passed via descriptors for their derived type arguments. 133 // Which::Assignment and Which::ElementalAssignment: 134 // Set to 1, 2, or (usually 3). 135 // The passed-object argument (usually the "to") is always passed via a 136 // a descriptor in the cases where the runtime will call a defined 137 // assignment because these calls are to type-bound generics, 138 // not generic interfaces, and type-bound generic defined assigment 139 // may appear only in an extensible type and requires a passed-object 140 // argument (see C774), and passed-object arguments to TBPs must be 141 // both polymorphic and scalar (C760). The non-passed-object argument 142 // (usually the "from") is usually, but not always, also a descriptor. 143 // Which::Final and Which::ElementalFinal: 144 // Set to 1 when dummy argument is assumed-shape; otherwise, the 145 // argument can be passed by address. (Fortran guarantees that 146 // any finalized object must be whole and contiguous by restricting 147 // the use of DEALLOCATE on pointers. The dummy argument of an 148 // elemental final subroutine must be scalar and monomorphic, but 149 // use a descriptors when the type has LEN parameters.) 150 // Which::AssumedRankFinal: flag must necessarily be set 151 // User derived type I/O: 152 // Set to 1 when "dtv" initial dummy argument is polymorphic, which is 153 // the case when and only when the derived type is extensible. 154 // When false, the user derived type I/O subroutine must have been 155 // called via a generic interface, not a generic TBP. 156 std::uint8_t isArgDescriptorSet{0}; 157 158 ProcedurePointer proc{nullptr}; 159 }; 160 } // namespace Fortran::runtime::typeInfo 161 #endif // FORTRAN_RUNTIME_TYPE_INFO_H_ 162