Appearance
| 1 | namespace IR.Emitter is | |
| 2 | use System.Reflection.Metadata.TypeDefinitionHandle | |
| 3 | use System.Reflection.Metadata.MethodDefinitionHandle | |
| 4 | use System.Reflection.Metadata.FieldDefinitionHandle | |
| 5 | ||
| 6 | use Semantic.Symbols.Symbol | |
| 7 | use Semantic.Symbols.Classy | |
| 8 | use Semantic.Symbols.Function | |
| 9 | use Semantic.Symbols.Field | |
| 10 | ||
| 11 | // The members a state-machine frame carries that no symbol declares. | |
| 12 | // The lowering synthesises each one, so they are named by which | |
| 13 | // member they are rather than by a declaration. | |
| 14 | // | |
| 15 | // The frame's constructor is not here: it is declared into the | |
| 16 | // frame's own scope and has a symbol like any other method. | |
| 17 | enum FrameMember is | |
| 18 | MOVE_NEXT, | |
| 19 | GET_CURRENT, | |
| 20 | GET_ENUMERATOR, | |
| 21 | DISPOSE, | |
| 22 | RESET, | |
| 23 | TO_STRING, | |
| 24 | SET_STATE_MACHINE, | |
| 25 | si | |
| 26 | ||
| 27 | // The non-generic framework members an iterable or iterator type | |
| 28 | // has to answer for, which its generic ones derive from. Neither | |
| 29 | // is a declaration the symbol table holds, so like `FrameMember` | |
| 30 | // each is named by which member it is. | |
| 31 | enum BoilerplateMember is | |
| 32 | ENUMERABLE_GET_ENUMERATOR, | |
| 33 | ENUMERATOR_GET_CURRENT, | |
| 34 | si | |
| 35 | ||
| 36 | // Every metadata identity the emitter has assigned to a symbol, one | |
| 37 | // map per table. | |
| 38 | // | |
| 39 | // These are deliberately not fields on the symbols themselves. | |
| 40 | // `specialize` clones symbols, so a row number stored on a symbol | |
| 41 | // would be copied onto every specialization and silently name the | |
| 42 | // wrong row; a map forces each table to state which identity it | |
| 43 | // keys on. Definitions key on the symbol, because a definition is | |
| 44 | // never specialized in the assembly that emits it. References key | |
| 45 | // on `root_specialized_from`, because the format expects one | |
| 46 | // TypeRef / MemberRef per open definition, with instantiations | |
| 47 | // expressed as TypeSpec / MethodSpec built on top of it. | |
| 48 | class SRM_HANDLES is | |
| 49 | _type_defs: Collections.MAP[Classy, TypeDefinitionHandle] | |
| 50 | _method_defs: Collections.MAP[Function, MethodDefinitionHandle] | |
| 51 | _field_defs: Collections.MAP[Field, FieldDefinitionHandle] | |
| 52 | ||
| 53 | // Offsets into the method body stream, deposited by the tree | |
| 54 | // walk as each body is encoded and read back when the owning | |
| 55 | // MethodDef row is written. A function with no entry has no | |
| 56 | // body, which is what an abstract or bodyless member is. | |
| 57 | _bodies: Collections.MAP[Function, int] | |
| 58 | ||
| 59 | // `@IL.output` ranges per method, set as each body is emitted and | |
| 60 | // read when the method's attribute is written. | |
| 61 | _il_outputs: Collections.MAP[Function, Collections.List[SRM_IL_OUTPUT_RANGE]] | |
| 62 | ||
| 63 | // A unit variant carries one interned instance in a static | |
| 64 | // field, initialized by a static constructor. Neither is | |
| 65 | // declared: the back end synthesises both, so they are keyed on | |
| 66 | // the variant they belong to rather than on a symbol of their | |
| 67 | // own. | |
| 68 | _unit_variant_instances: Collections.MAP[Classy, FieldDefinitionHandle] | |
| 69 | _unit_variant_initializers: Collections.MAP[Classy, MethodDefinitionHandle] | |
| 70 | _unit_variant_initializer_bodies: Collections.MAP[Classy, int] | |
| 71 | ||
| 72 | // A state-machine frame's own members, which the lowering | |
| 73 | // synthesises rather than declares. Keyed on the frame and which | |
| 74 | // member it is, for the same reason the unit variant's are: the | |
| 75 | // member has no symbol of its own to key on. | |
| 76 | _frame_members: Collections.MAP[(frame: Classy, member: FrameMember), MethodDefinitionHandle] | |
| 77 | _frame_member_bodies: Collections.MAP[(frame: Classy, member: FrameMember), int] | |
| 78 | ||
| 79 | // The sequence the rows above were assigned in, so the pass | |
| 80 | // that writes them replays the pass that numbered them. | |
| 81 | emission_plan: SRM_EMISSION_PLAN | |
| 82 | ||
| 83 | init() is | |
| 84 | emission_plan = SRM_EMISSION_PLAN() | |
| 85 | ||
| 86 | _type_defs = Collections.MAP[Classy, TypeDefinitionHandle]() | |
| 87 | _method_defs = Collections.MAP[Function, MethodDefinitionHandle]() | |
| 88 | _field_defs = Collections.MAP[Field, FieldDefinitionHandle]() | |
| 89 | _bodies = Collections.MAP[Function, int]() | |
| 90 | _il_outputs = | |
| 91 | Collections.MAP[Function, Collections.List[SRM_IL_OUTPUT_RANGE]]() | |
| 92 | _unit_variant_instances = Collections.MAP[Classy, FieldDefinitionHandle]() | |
| 93 | _unit_variant_initializers = Collections.MAP[Classy, MethodDefinitionHandle]() | |
| 94 | _unit_variant_initializer_bodies = Collections.MAP[Classy, int]() | |
| 95 | _frame_members = Collections.MAP[(frame: Classy, member: FrameMember), MethodDefinitionHandle]() | |
| 96 | _frame_member_bodies = Collections.MAP[(frame: Classy, member: FrameMember), int]() | |
| 97 | si | |
| 98 | ||
| 99 | set_frame_member(frame: Classy, member: FrameMember, handle: MethodDefinitionHandle) is | |
| 100 | _frame_members[(frame = frame, member = member)] = handle | |
| 101 | si | |
| 102 | ||
| 103 | frame_member(frame: Classy, member: FrameMember) -> MethodDefinitionHandle? => | |
| 104 | if _frame_members.contains_key((frame = frame, member = member)) then | |
| 105 | _frame_members[(frame = frame, member = member)] | |
| 106 | else | |
| 107 | null | |
| 108 | fi | |
| 109 | ||
| 110 | set_frame_member_body(frame: Classy, member: FrameMember, offset: int) is | |
| 111 | _frame_member_bodies[(frame = frame, member = member)] = offset | |
| 112 | si | |
| 113 | ||
| 114 | frame_member_body(frame: Classy, member: FrameMember) -> int? => | |
| 115 | if _frame_member_bodies.contains_key((frame = frame, member = member)) then | |
| 116 | _frame_member_bodies[(frame = frame, member = member)] | |
| 117 | else | |
| 118 | null | |
| 119 | fi | |
| 120 | ||
| 121 | set_type_definition(symbol: Classy, handle: TypeDefinitionHandle) is | |
| 122 | _type_defs[symbol] = handle | |
| 123 | si | |
| 124 | ||
| 125 | set_method_definition(symbol: Function, handle: MethodDefinitionHandle) is | |
| 126 | _method_defs[symbol] = handle | |
| 127 | si | |
| 128 | ||
| 129 | set_field_definition(symbol: Field, handle: FieldDefinitionHandle) is | |
| 130 | _field_defs[symbol] = handle | |
| 131 | si | |
| 132 | ||
| 133 | // Type and method lookups take the root symbol, so a call | |
| 134 | // through a specialization still finds the definition it was | |
| 135 | // specialized from. | |
| 136 | type_definition(symbol: Classy) -> TypeDefinitionHandle? is | |
| 137 | let root = cast Classy?(symbol.root_specialized_from) | |
| 138 | ||
| 139 | if root? /\ _type_defs.contains_key(root) then | |
| 140 | return _type_defs[root] | |
| 141 | fi | |
| 142 | ||
| 143 | return null | |
| 144 | si | |
| 145 | ||
| 146 | method_definition(symbol: Function) -> MethodDefinitionHandle? is | |
| 147 | let root = cast Function?(symbol.root_specialized_from) | |
| 148 | ||
| 149 | if root? /\ _method_defs.contains_key(root) then | |
| 150 | return _method_defs[root] | |
| 151 | fi | |
| 152 | ||
| 153 | return null | |
| 154 | si | |
| 155 | ||
| 156 | field_definition(symbol: Field) -> FieldDefinitionHandle? is | |
| 157 | let root = cast Field?(symbol.root_specialized_from) | |
| 158 | ||
| 159 | if root? /\ _field_defs.contains_key(root) then | |
| 160 | return _field_defs[root] | |
| 161 | fi | |
| 162 | ||
| 163 | return null | |
| 164 | si | |
| 165 | ||
| 166 | set_unit_variant_instance(variant: Classy, handle: FieldDefinitionHandle) is | |
| 167 | _unit_variant_instances[variant] = handle | |
| 168 | si | |
| 169 | ||
| 170 | set_unit_variant_initializer(variant: Classy, handle: MethodDefinitionHandle) is | |
| 171 | _unit_variant_initializers[variant] = handle | |
| 172 | si | |
| 173 | ||
| 174 | set_unit_variant_initializer_body(variant: Classy, offset: int) is | |
| 175 | _unit_variant_initializer_bodies[variant] = offset | |
| 176 | si | |
| 177 | ||
| 178 | unit_variant_instance(variant: Classy) -> FieldDefinitionHandle? is | |
| 179 | let root = cast Classy?(variant.root_specialized_from) | |
| 180 | ||
| 181 | if root? /\ _unit_variant_instances.contains_key(root) then | |
| 182 | return _unit_variant_instances[root] | |
| 183 | fi | |
| 184 | ||
| 185 | return null | |
| 186 | si | |
| 187 | ||
| 188 | unit_variant_initializer_body(variant: Classy) -> int? => | |
| 189 | if _unit_variant_initializer_bodies.contains_key(variant) then | |
| 190 | _unit_variant_initializer_bodies[variant] | |
| 191 | else | |
| 192 | null | |
| 193 | fi | |
| 194 | ||
| 195 | set_body_offset(symbol: Function, offset: int) is | |
| 196 | _bodies[symbol] = offset | |
| 197 | si | |
| 198 | ||
| 199 | body_offset(symbol: Function) -> int? => | |
| 200 | if _bodies.contains_key(symbol) then _bodies[symbol] else null fi | |
| 201 | ||
| 202 | // `@IL.output` ranges captured while the method's body was emitted, | |
| 203 | // carried to the phase-3 structure walk that writes the method's | |
| 204 | // attribute. Null/empty is stored as absent so the attribute is | |
| 205 | // written only for methods that actually mark something. | |
| 206 | set_il_outputs( | |
| 207 | symbol: Function, | |
| 208 | outputs: Collections.List[SRM_IL_OUTPUT_RANGE]? | |
| 209 | ) is | |
| 210 | if outputs? /\ outputs.count > 0 then | |
| 211 | _il_outputs[symbol] = outputs | |
| 212 | fi | |
| 213 | si | |
| 214 | ||
| 215 | il_outputs(symbol: Function) -> Collections.List[SRM_IL_OUTPUT_RANGE]? => | |
| 216 | if _il_outputs.contains_key(symbol) then _il_outputs[symbol] else null fi | |
| 217 | si | |
| 218 | si |