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