Skip to content
← Back

src/ir/context.ghul

1
namespace IR is
2
use System.NotImplementedException
3
use IO.File
4
5
use Values.Call
6
7
class CONTEXT is
8
_logger: Logging.Logger
9
10
entry_point_name: string public
11
12
// Whether `--entry` named it. A build that asks for an entry point
13
// by name does not want a file's top-level statements instead, so
14
// the synthesised entry stops being a candidate when this is set.
15
entry_point_name_is_explicit: bool public
16
seen_entrypoint: bool public
17
18
// Binary emission state, carried here so that a value's `gen`
19
// can reach the method body it is being emitted into without
20
// every caller threading it through.
21
//
22
// The assembly emitter is installed by the driver before any
23
// pass that emits runs, and every emitting pass requires one, so
24
// it reads as non-optional: a build that reaches emission
25
// without one is a wiring error rather than a state to branch
26
// on, and fails here rather than silently emitting nothing.
27
//
28
// The body emitter is genuinely optional - it tracks the method
29
// the IL visitor currently has open, and is null outside one.
30
_srm_assembly_emitter: Emitter.SRM_ASSEMBLY_EMITTER?
31
32
// What the emitter was installed as, so a rebuild can make
33
// another one like it. Analysis compiles the project again on
34
// every edit and query miss, and an emitter accumulates a
35
// reference and specification cache per compile: kept across
36
// rebuilds it grows for as long as the editor session lasts.
37
_srm_module_name: string?
38
_srm_module_version: string?
39
_srm_want_library: bool
40
41
srm_assembly_emitter: Emitter.SRM_ASSEMBLY_EMITTER =>
42
_srm_assembly_emitter!
43
44
install_srm_assembly_emitter(
45
module_name: string,
46
module_version: string,
47
want_library: bool
48
) is
49
_srm_module_name = module_name
50
_srm_module_version = module_version
51
_srm_want_library = want_library
52
53
reset_srm_assembly_emitter()
54
si
55
56
// Called wherever the symbol table is abandoned: the handles the
57
// old emitter holds name symbols that no longer exist.
58
reset_srm_assembly_emitter() is
59
if let module_name = _srm_module_name then
60
_srm_assembly_emitter =
61
Emitter.SRM_ASSEMBLY_EMITTER(
62
"{module_name}.{if _srm_want_library then "dll" else "exe" fi}",
63
module_name,
64
_srm_module_version!,
65
_srm_want_library)
66
fi
67
si
68
69
current_srm_body_emitter: Emitter.SRM_METHOD_BODY_EMITTER? public
70
71
// Reads `--debug` off the shared build-flags singleton so
72
// non-debug builds pay nothing for the `mark_location` check.
73
want_debug_info: bool =>
74
IoC.CONTAINER.instance.build_flags.want_debug
75
76
// One step of an interactive session, where a later step is
77
// another assembly and may add an alternative to a hierarchy an
78
// earlier step compiled against. An ordinary build knows every
79
// alternative and pays for none of the guards that costs.
80
is_submission: bool =>
81
IoC.CONTAINER.instance.build_flags.submission_name?
82
83
// Compilation-global counter assigning each `@IL.output` region a
84
// sequence number, so the runner can rebuild source order across
85
// methods. Bumped once per region, at its start.
86
_il_output_sequence: int
87
88
init(
89
logger: Logging.Logger,
90
entry_point_name: string
91
) is
92
_logger = logger
93
self.entry_point_name = entry_point_name
94
si
95
96
// Note a source-language position at the current emission
97
// point. A position is recorded against the instruction offset
98
// the body has reached, so this is only meaningful while one is
99
// open; `mark_sequence_point` itself dedupes a repeated position
100
// at the same offset. Internal / sentinel locations are ignored.
101
mark_location(location: Source.LOCATION?) is
102
if !want_debug_info \/ !location? \/ location.is_internal \/ !current_srm_body_emitter? then
103
return
104
fi
105
106
current_srm_body_emitter.mark_sequence_point(location)
107
si
108
109
// Marks an emission path that isn't implemented yet, so a build
110
// can continue past a gap in the binary back end rather than
111
// crashing. Traced to stderr; nothing reads what a gap produces.
112
fixme(value: object) is
113
Logging.debug_always("FIXME: {value}")
114
si
115
116
next_il_output_sequence() -> int is
117
_il_output_sequence = _il_output_sequence + 1
118
119
return _il_output_sequence
120
si
121
122
// Resolves a call target to a member reference. Handles the two
123
// owner shapes a call can have: a ghūl global function, hosted on
124
// its namespace's $globals carrier, and a static method, hosted
125
// directly on its declaring type.
126
//
127
// Only void-returning signatures taking zero or one string
128
// argument are encoded; anything else needs the signature blob
129
// built from the function's actual argument and return types.
130
// The CLR parameter index of a named argument.
131
//
132
// Arguments are addressed by name up to here, and metadata has
133
// only positions. An instance method's slot 0 is the receiver,
134
// so a declared argument sits one further along.
135
resolve_argument_index(symbol: Semantic.Symbols.Symbol) -> int is
136
let function = cast Semantic.Symbols.Function?(symbol.owner)
137
138
assert function? else
139
"argument '{symbol.name}' is not owned by a function"
140
141
let names = function.argument_names
142
143
for i in 0..names.count do
144
if names[i] =~ symbol.name then
145
return if function.is_emitted_with_receiver then i + 1 else i fi
146
fi
147
od
148
149
assert false else
150
"argument '{symbol.name}' is not declared by {function.name}"
151
152
return 0
153
si
154
155
// The metadata token naming a type, for instructions that take
156
// one directly (box, castclass, isinst). A constructed generic
157
// needs a TypeSpec rather than a bare reference, which is not
158
// built yet, so those report rather than emitting a token that
159
// names the open definition.
160
// A unit variant is constructed by loading the one interned
161
// instance the back end synthesises for it, rather than by
162
// calling its constructor.
163
resolve_unit_variant_instance(
164
variant: Semantic.Scope
165
) -> System.Reflection.Metadata.EntityHandle is
166
let emitter = srm_assembly_emitter
167
168
// A specialization holds the open definition rather than
169
// being one, and only the definition has a row.
170
let classy =
171
if let generic: Semantic.Symbols.GENERIC = variant then
172
cast Semantic.Symbols.Classy?(generic.symbol)
173
else
174
cast Semantic.Symbols.Classy?(variant)
175
fi
176
177
assert classy? else "unit variant '{variant.name}' is not a type"
178
179
// A generic variant's instance field belongs to the
180
// instantiation, so it is reached through a reference whose
181
// parent is that instantiation's specification. The field's
182
// own type is written open — the variant applied to its own
183
// parameters — because the reference names the field on the
184
// open definition and the instantiation lives in the parent.
185
if classy.is_generic then
186
if let constructed: Semantic.Symbols.GENERIC = variant then
187
return cast System.Reflection.Metadata.EntityHandle(
188
emitter.add_named_member_reference(
189
resolve_type_token(constructed.type),
190
"_instance",
191
"_instance {constructed.type}",
192
Emitter.SRM_SIGNATURE_ENCODER(emitter)
193
.field_signature(classy.own_instantiation)))
194
fi
195
196
// Reached from inside the variant's own static
197
// initializer, where there is no instantiation to hand:
198
// the parent is the variant applied to its own
199
// parameters, which is what the field's row names too.
200
return cast System.Reflection.Metadata.EntityHandle(
201
emitter.add_named_member_reference(
202
resolve_type_token(classy.own_instantiation),
203
"_instance",
204
"_instance {classy.own_instantiation}",
205
Emitter.SRM_SIGNATURE_ENCODER(emitter)
206
.field_signature(classy.own_instantiation)))
207
fi
208
209
let instance = emitter.handles.unit_variant_instance(classy)
210
211
if instance? then
212
return cast System.Reflection.Metadata.EntityHandle(instance)
213
fi
214
215
// A variant of a union another assembly declares. Its
216
// interned instance is a field over there, so it is reached
217
// by reference rather than by the row this assembly would
218
// have written for one of its own.
219
assert classy.is_reflected else
220
"unit variant '{variant.name}' has no interned instance"
221
222
return cast System.Reflection.Metadata.EntityHandle(
223
emitter.add_named_member_reference(
224
resolve_type_token(classy.type!),
225
"_instance",
226
"_instance {classy.type}",
227
Emitter.SRM_SIGNATURE_ENCODER(emitter).field_signature(classy.type!)))
228
si
229
230
// A token for a type named rather than resolved: the compiler
231
// synthesises code around a few framework types it knows by
232
// name and has no symbol for, the way the assert helper names
233
// its own exception.
234
resolve_type_token_by_name(
235
assembly_name: string,
236
namespace_name: string,
237
name: string
238
) -> System.Reflection.Metadata.EntityHandle =>
239
cast System.Reflection.Metadata.EntityHandle(
240
srm_assembly_emitter.add_type_reference_by_name(
241
assembly_name, namespace_name, name))
242
243
resolve_type_token(type: Semantic.Types.Type) -> System.Reflection.Metadata.EntityHandle is
244
let emitter = srm_assembly_emitter
245
246
// A constructed generic has no row of its own, and neither
247
// does a type parameter or a primitive: all three are
248
// structural types, named by a specification carrying their
249
// encoded shape. A primitive especially cannot be named by
250
// reference — its il_name_override is the assembler keyword
251
// (`int8`, `int32`), which is not what the type is called.
252
if type.arguments.count > 0 \/
253
isa Semantic.Symbols.GenericArgument(type.symbol) \/
254
type.symbol.il_is_primitive_type
255
then
256
return cast System.Reflection.Metadata.EntityHandle(
257
emitter.add_type_specification(type))
258
fi
259
260
// Same unwrapping as the signature encoder: a constructed
261
// generic's symbol holds the open definition rather than
262
// being one, and only the definition has a row.
263
let symbol =
264
if let generic: Semantic.Symbols.GENERIC = type.symbol then
265
generic.symbol
266
else
267
cast Semantic.Symbols.Classy?(type.symbol)
268
fi
269
270
assert symbol? else "cannot name the type '{type}' in an instruction"
271
272
if let definition = emitter.handles.type_definition(symbol) then
273
return cast System.Reflection.Metadata.EntityHandle(definition)
274
fi
275
276
return cast System.Reflection.Metadata.EntityHandle(
277
Emitter.SRM_SIGNATURE_ENCODER(emitter).type_reference_for(symbol))
278
si
279
280
// Invoking a function value calls Invoke on the delegate type.
281
resolve_delegate_invoke(
282
func_type: Semantic.Types.Type,
283
argument_count: int,
284
is_action: bool
285
) -> System.Reflection.Metadata.EntityHandle is
286
let emitter = srm_assembly_emitter
287
288
return cast System.Reflection.Metadata.EntityHandle(
289
emitter.add_named_member_reference(
290
resolve_type_token(func_type),
291
"Invoke",
292
"Invoke {func_type}",
293
Emitter.SRM_SIGNATURE_ENCODER(emitter)
294
.delegate_invoke_signature(argument_count, is_action)))
295
si
296
297
// An inference sentinel inside a type reaching code
298
// generation means an inference gap upstream was never
299
// reported as a diagnostic — the signature encoder refuses
300
// sentinels, so without this check the gap surfaces as an
301
// internal error deep in emission instead.
302
contains_sentinel(type: Semantic.Types.Type?) -> bool static is
303
if !type? then
304
return false
305
fi
306
307
if type.is_sentinel then
308
return true
309
fi
310
311
// Every composite that carries child types — arrays,
312
// tuples, functions, refs, pointers, maybes — is a
313
// GENERIC over them, so recursing over the arguments
314
// visits the whole tree.
315
if let generic: Semantic.Types.GENERIC = type then
316
for argument in generic.arguments do
317
if contains_sentinel(argument) then
318
return true
319
fi
320
od
321
fi
322
323
return false
324
si
325
326
report_unresolved_type(location: Source.LOCATION, type: Semantic.Types.Type) is
327
_logger.error(
328
location,
329
"cannot call a function value whose type was not fully inferred: '{type}'")
330
si
331
332
// A tuple and a wrapped optional are both a constructed generic
333
// built from one value per type parameter, so both reach their
334
// constructor the same way: through the owning TypeSpec, with
335
// the parameters written as indexes.
336
resolve_generic_constructor(
337
type: Semantic.Types.Type,
338
argument_count: int
339
) -> System.Reflection.Metadata.EntityHandle is
340
let emitter = srm_assembly_emitter
341
342
return cast System.Reflection.Metadata.EntityHandle(
343
emitter.add_named_member_reference(
344
resolve_type_token(type),
345
".ctor",
346
".ctor {type}/{argument_count}",
347
Emitter.SRM_SIGNATURE_ENCODER(emitter)
348
.generic_constructor_signature(argument_count)))
349
si
350
351
// `assert` joins its location to its message and wraps the
352
// result in an exception. Both members belong to types no symbol
353
// in this compilation names, so both are built from their known
354
// shapes rather than read off a declaration.
355
resolve_string_concat() -> System.Reflection.Metadata.EntityHandle is
356
let emitter = srm_assembly_emitter
357
let lookup = IoC.CONTAINER.instance.innate_symbol_lookup
358
359
let arguments = Collections.LIST[Semantic.Types.Type]()
360
361
arguments.add(lookup.get_object_type())
362
arguments.add(lookup.get_object_type())
363
364
return cast System.Reflection.Metadata.EntityHandle(
365
emitter.add_named_member_reference(
366
cast System.Reflection.Metadata.EntityHandle(
367
emitter.add_type_reference_by_name("System.Runtime", "System", "String")),
368
"Concat",
369
"String::Concat(object,object)",
370
Emitter.SRM_SIGNATURE_ENCODER(emitter)
371
.static_signature(lookup.get_string_type(), arguments)))
372
si
373
374
// `=~` on two strings lowers to the framework's own equality
375
// operator rather than to an instruction, so it needs a member
376
// reference like any other imported static.
377
resolve_string_equality() -> System.Reflection.Metadata.EntityHandle is
378
let emitter = srm_assembly_emitter
379
let lookup = IoC.CONTAINER.instance.innate_symbol_lookup
380
381
let arguments = Collections.LIST[Semantic.Types.Type]()
382
383
arguments.add(lookup.get_string_type())
384
arguments.add(lookup.get_string_type())
385
386
return cast System.Reflection.Metadata.EntityHandle(
387
emitter.add_named_member_reference(
388
cast System.Reflection.Metadata.EntityHandle(
389
emitter.add_type_reference_by_name("System.Runtime", "System", "String")),
390
"op_Equality",
391
"String::op_Equality(string,string)",
392
Emitter.SRM_SIGNATURE_ENCODER(emitter)
393
.static_signature(lookup.get_bool_type(), arguments)))
394
si
395
396
// The two members of `EqualityComparer[T]` a value-equality test
397
// over a bare type parameter goes through. Neither is declared by
398
// any symbol in the compilation, so each is built from its known
399
// shape.
400
//
401
// The reference hangs off the caller's instantiation while the
402
// signature is written in the comparer's own terms — `!0` is the
403
// comparer's type parameter, not the caller's — the same open-form
404
// rule every other methodref on a constructed generic follows.
405
resolve_equality_comparer_default(
406
comparer_type: Semantic.Types.Type
407
) -> System.Reflection.Metadata.EntityHandle is
408
let emitter = srm_assembly_emitter
409
410
let classy = _comparer_classy(comparer_type)
411
412
return cast System.Reflection.Metadata.EntityHandle(
413
emitter.add_named_member_reference(
414
resolve_type_token(comparer_type),
415
"get_Default",
416
"EqualityComparer::get_Default()",
417
Emitter.SRM_SIGNATURE_ENCODER(emitter)
418
.static_signature(classy.own_instantiation, Collections.LIST[Semantic.Types.Type]())))
419
si
420
421
resolve_equality_comparer_equals(
422
comparer_type: Semantic.Types.Type
423
) -> System.Reflection.Metadata.EntityHandle is
424
let emitter = srm_assembly_emitter
425
let lookup = IoC.CONTAINER.instance.innate_symbol_lookup
426
427
let parameter = _comparer_classy(comparer_type).type_parameter_at(0)
428
let arguments = Collections.LIST[Semantic.Types.Type]()
429
430
arguments.add(parameter!.type!)
431
arguments.add(parameter.type!)
432
433
return cast System.Reflection.Metadata.EntityHandle(
434
emitter.add_named_member_reference(
435
resolve_type_token(comparer_type),
436
"Equals",
437
"EqualityComparer::Equals(!0,!0)",
438
Emitter.SRM_SIGNATURE_ENCODER(emitter)
439
.call_signature(lookup.get_bool_type(), arguments, true)))
440
si
441
442
// A constructed generic's symbol is a `Symbols.GENERIC` holding
443
// the open definition rather than being one.
444
_comparer_classy(comparer_type: Semantic.Types.Type) -> Semantic.Symbols.Classy is
445
if let generic: Semantic.Symbols.GENERIC = comparer_type.symbol then
446
return cast Semantic.Symbols.Classy(generic.symbol)
447
fi
448
449
return cast Semantic.Symbols.Classy?(comparer_type.symbol)!
450
si
451
452
// The constructor of the exception a body-less class method
453
// throws when it is called: it overrides an implemented member,
454
// so it has a slot to fill and nothing to fill it with.
455
resolve_not_implemented_constructor() -> System.Reflection.Metadata.EntityHandle is
456
let emitter = srm_assembly_emitter
457
let lookup = IoC.CONTAINER.instance.innate_symbol_lookup
458
459
let arguments = Collections.LIST[Semantic.Types.Type]()
460
461
arguments.add(lookup.get_string_type())
462
463
return cast System.Reflection.Metadata.EntityHandle(
464
emitter.add_constructor_reference(
465
cast System.Reflection.Metadata.EntityHandle(
466
emitter.add_type_reference_by_name(
467
"System.Runtime", "System", "NotImplementedException")),
468
"NotImplementedException::.ctor(string)",
469
arguments))
470
si
471
472
resolve_not_supported_constructor() -> System.Reflection.Metadata.EntityHandle is
473
let emitter = srm_assembly_emitter
474
475
return cast System.Reflection.Metadata.EntityHandle(
476
emitter.add_constructor_reference(
477
cast System.Reflection.Metadata.EntityHandle(
478
emitter.add_type_reference_by_name(
479
"System.Runtime", "System", "NotSupportedException")),
480
"NotSupportedException::.ctor()",
481
Collections.LIST[Semantic.Types.Type]()))
482
si
483
484
resolve_assert_failed_constructor() -> System.Reflection.Metadata.EntityHandle is
485
let emitter = srm_assembly_emitter
486
let lookup = IoC.CONTAINER.instance.innate_symbol_lookup
487
488
let arguments = Collections.LIST[Semantic.Types.Type]()
489
490
arguments.add(lookup.get_string_type())
491
492
return cast System.Reflection.Metadata.EntityHandle(
493
emitter.add_constructor_reference(
494
cast System.Reflection.Metadata.EntityHandle(
495
emitter.add_type_reference_by_name(
496
"ghul-runtime", "Ghul", "AssertFailedException")),
497
"AssertFailedException::.ctor(string)",
498
arguments))
499
si
500
501
// The free function a state-machine frame's ToString calls to
502
// render itself the way the runtime's own pipes do:
503
// `Ghul.Pipes.render_elements(source)`, or `Ghul.Pipes.join(source)`
504
// from a runtime too old to have it. The `Pipe[T]` trait's own
505
// to_string is a default interface method and so does not
506
// override Object.ToString, and a frame that called the trait
507
// member would reach its own override and recurse.
508
resolve_pipe_join(
509
element_type: Semantic.Types.Type
510
) -> System.Reflection.Metadata.EntityHandle is
511
let lookup = IoC.CONTAINER.instance.innate_symbol_lookup
512
513
let functions = lookup.get_render_elements_functions() ?? lookup.get_join_functions()
514
515
assert functions? else "Ghul.Pipes.join is not available"
516
517
let single_argument: Semantic.Symbols.Function? mut = null
518
519
for f in functions.functions do
520
if f.arguments.count == 1 then
521
single_argument = f
522
fi
523
od
524
525
assert single_argument? else
526
"Ghul.Pipes.join has no single-argument overload"
527
528
let specialized =
529
cast Semantic.Symbols.Function?(
530
single_argument.specialize(
531
Collections.LIST[Semantic.Types.Type]([element_type])))
532
533
assert specialized? else
534
"Ghul.Pipes.join could not be specialized over {element_type}"
535
536
return resolve_call_target(specialized)
537
si
538
539
// The builder members an async lowering reaches, located by their
540
// ghul names on the builder type - the same lookup for a reflected
541
// builder, whose members import under these names, and for one
542
// declared in ghul source. Resolution goes through the ordinary
543
// call-target machinery, so a same-assembly builder is called
544
// through its own definition row and a reflected one through a
545
// member reference, each with a signature read off the member
546
// rather than written out here.
547
resolve_builder_member(
548
builder_type: Semantic.Types.Type,
549
name: string,
550
argument_count: int
551
) -> System.Reflection.Metadata.EntityHandle is
552
let member = Semantic.TASK_LIKE.member_of_arity(builder_type, name, argument_count)
553
554
assert member? else "no {name}/{argument_count} member on builder {builder_type}"
555
556
return resolve_call_target(member)
557
si
558
559
resolve_builder_property(
560
builder_type: Semantic.Types.Type,
561
name: string
562
) -> System.Reflection.Metadata.EntityHandle is
563
let property = cast Semantic.Symbols.Property?(builder_type.find_member(name))
564
565
assert property? /\ property.read_function? else
566
"no readable {name} property on builder {builder_type}"
567
568
return resolve_call_target(property.read_function)
569
si
570
571
// Whether the builder's await-on-completed member takes the state
572
// machine by reference (the shape the BCL builders use) or by
573
// value as the interface (which lets a builder register a
574
// method value as the continuation, with no closure).
575
builder_awaits_sm_by_reference(
576
builder_type: Semantic.Types.Type,
577
is_critical: bool
578
) -> bool is
579
let name =
580
if is_critical then
581
"await_unsafe_on_completed"
582
else
583
"await_on_completed"
584
fi
585
586
let member = Semantic.TASK_LIKE.member_of_arity(builder_type, name, 2)
587
588
if !member? then
589
return true
590
fi
591
592
return isa Semantic.Types.REFERENCE(member.arguments[1])
593
si
594
595
// A generic builder member - `start[A](a: A ref)` or
596
// `await_on_completed[A, S](a: A ref, s: S ref)`. The reference
597
// names the open method and a specification supplies the
598
// construction types, which no member specialization carries.
599
resolve_builder_generic_member(
600
builder_type: Semantic.Types.Type,
601
name: string,
602
argument_count: int,
603
type_arguments: Collections.List[Semantic.Types.Type]
604
) -> System.Reflection.Metadata.EntityHandle is
605
let emitter = srm_assembly_emitter
606
607
let member = Semantic.TASK_LIKE.member_of_arity(builder_type, name, argument_count)
608
609
assert member? else "no {name}/{argument_count} member on builder {builder_type}"
610
611
let root = cast Semantic.Symbols.Function?(member.root_specialized_from) ?? member
612
613
let reference =
614
emitter.add_named_member_reference(
615
_member_owner_handle(member),
616
Emitter.SRM_FLAGS.method_name(root),
617
"method {member.owner}::{root.description}",
618
Emitter.SRM_SIGNATURE_ENCODER(emitter).method_signature(root))
619
620
return cast System.Reflection.Metadata.EntityHandle(
621
emitter.add_method_specification(
622
cast System.Reflection.Metadata.EntityHandle(reference),
623
"{member}",
624
type_arguments))
625
si
626
627
628
// `start[A](state_machine: A ref)` is generic in the state machine
629
// it drives, so the reference names the open method and a
630
// specification supplies the frame type.
631
resolve_async_builder_start(
632
builder_type: Semantic.Types.Type,
633
state_machine_type: Semantic.Types.Type
634
) -> System.Reflection.Metadata.EntityHandle is
635
let arguments = Collections.LIST[Semantic.Types.Type]()
636
637
arguments.add(state_machine_type)
638
639
return resolve_builder_generic_member(builder_type, "start", 1, arguments)
640
si
641
642
// The builder method that registers an await's continuation:
643
// `await_unsafe_on_completed` for an awaiter implementing
644
// `ICriticalNotifyCompletion`, `await_on_completed` otherwise.
645
// Both are generic in the awaiter and the state machine.
646
resolve_await_on_completed(
647
builder_type: Semantic.Types.Type,
648
awaiter_type: Semantic.Types.Type,
649
state_machine_type: Semantic.Types.Type,
650
is_critical: bool
651
) -> System.Reflection.Metadata.EntityHandle is
652
let name =
653
if is_critical then
654
"await_unsafe_on_completed"
655
else
656
"await_on_completed"
657
fi
658
659
let arguments = Collections.LIST[Semantic.Types.Type]()
660
661
arguments.add(awaiter_type)
662
663
// The specification names one type argument per method type
664
// parameter: a member typing the state machine as the
665
// interface has only the awaiter's.
666
let member = Semantic.TASK_LIKE.member_of_arity(builder_type, name, 2)
667
668
if !member? \/ member.generic_arguments.count > 1 then
669
arguments.add(state_machine_type)
670
fi
671
672
return resolve_builder_generic_member(builder_type, name, 2, arguments)
673
si
674
675
// `System.Type.GetTypeFromHandle`, which turns the handle
676
// `ldtoken` pushes into the `System.Type` a `typeof` yields.
677
// Neither the method nor either of the types it mentions is
678
// declared by any symbol in the compilation.
679
resolve_get_type_from_handle() -> System.Reflection.Metadata.EntityHandle is
680
let emitter = srm_assembly_emitter
681
682
let system_type =
683
emitter.add_type_reference_by_name("System.Runtime", "System", "Type")
684
685
let handle_type =
686
emitter.add_type_reference_by_name(
687
"System.Runtime", "System", "RuntimeTypeHandle")
688
689
let builder = System.Reflection.Metadata.BlobBuilder(16)
690
691
let return_type: System.Reflection.Metadata.Ecma335.ReturnTypeEncoder mut
692
let parameters: System.Reflection.Metadata.Ecma335.ParametersEncoder mut
693
694
System.Reflection.Metadata.Ecma335.BlobEncoder(builder)
695
.method_signature(
696
System.Reflection.Metadata.SignatureCallingConvention.DEFAULT, 0, false)
697
.parameters(1, return_type ref, parameters ref)
698
699
return_type.`type(false).`type(
700
cast System.Reflection.Metadata.EntityHandle(system_type), false)
701
702
parameters.add_parameter().`type(false).`type(
703
cast System.Reflection.Metadata.EntityHandle(handle_type), true)
704
705
return cast System.Reflection.Metadata.EntityHandle(
706
emitter.add_named_member_reference(
707
cast System.Reflection.Metadata.EntityHandle(system_type),
708
"GetTypeFromHandle",
709
"System.Type::GetTypeFromHandle(RuntimeTypeHandle)",
710
builder.to_array()))
711
si
712
713
// MoveNext.s trailer completes the task through `set_result`. A
714
// builder can declare both the parameterless and the one-argument
715
// overload; the one reached is chosen by whether there is a
716
// result to deliver.
717
resolve_async_builder_set_result(
718
builder_type: Semantic.Types.Type,
719
has_result: bool
720
) -> System.Reflection.Metadata.EntityHandle is
721
return resolve_builder_member(
722
builder_type, "set_result", if has_result then 1 else 0 fi)
723
si
724
725
resolve_async_builder_set_exception(
726
builder_type: Semantic.Types.Type
727
) -> System.Reflection.Metadata.EntityHandle =>
728
resolve_builder_member(builder_type, "set_exception", 1)
729
730
// `System.Object`'s constructor, which every constructor that
731
// does not chain to a declared superclass calls first. Named
732
// here because no symbol in the compilation declares it.
733
resolve_object_constructor() -> System.Reflection.Metadata.EntityHandle is
734
let emitter = srm_assembly_emitter
735
736
return cast System.Reflection.Metadata.EntityHandle(
737
emitter.add_constructor_reference(
738
cast System.Reflection.Metadata.EntityHandle(
739
emitter.add_type_reference_by_name("System.Runtime", "System", "Object")),
740
"Object::.ctor()",
741
Collections.LIST[Semantic.Types.Type]()))
742
si
743
744
// `System.Object.GetType()`. `!` on a plain reference-typed
745
// `T?` calls it through a dup-and-discard so the runtime's own
746
// null check does the throwing; named here for the same reason
747
// as `Object`'s constructor: no symbol in the compilation
748
// declares it.
749
resolve_object_get_type() -> System.Reflection.Metadata.EntityHandle is
750
let emitter = srm_assembly_emitter
751
752
let object_type =
753
emitter.add_type_reference_by_name("System.Runtime", "System", "Object")
754
755
let type_type =
756
emitter.add_type_reference_by_name("System.Runtime", "System", "Type")
757
758
return cast System.Reflection.Metadata.EntityHandle(
759
emitter.add_named_member_reference(
760
cast System.Reflection.Metadata.EntityHandle(object_type),
761
"GetType",
762
"Object::GetType()",
763
Emitter.SRM_SIGNATURE_ENCODER(emitter)
764
.nullary_instance_signature(cast System.Reflection.Metadata.EntityHandle(type_type))))
765
si
766
767
// `System.Decimal`'s full-resolution constructor, which a
768
// decimal literal is built through. Named here for the same
769
// reason as `Object`'s: no symbol in the compilation declares
770
// it.
771
resolve_decimal_constructor() -> System.Reflection.Metadata.EntityHandle is
772
let emitter = srm_assembly_emitter
773
let lookup = IoC.CONTAINER.instance.innate_symbol_lookup
774
775
let arguments = Collections.LIST[Semantic.Types.Type]()
776
777
arguments.add(lookup.get_int_type())
778
arguments.add(lookup.get_int_type())
779
arguments.add(lookup.get_int_type())
780
arguments.add(lookup.get_bool_type())
781
arguments.add(lookup.get_ubyte_type())
782
783
return cast System.Reflection.Metadata.EntityHandle(
784
emitter.add_constructor_reference(
785
resolve_type_token_by_name("System.Runtime", "System", "Decimal"),
786
"Decimal::.ctor(int32, int32, int32, bool, unsigned int8)",
787
arguments))
788
si
789
790
// `System.Numerics.BigInteger`'s single-`long` constructor and
791
// its `Parse`, which a `bigint` literal is built through. Named
792
// here for the same reason as `Decimal`'s constructor: no symbol
793
// in the compilation declares either.
794
resolve_bigint_constructor(bigint_type: Semantic.Types.Type) -> System.Reflection.Metadata.EntityHandle is
795
let emitter = srm_assembly_emitter
796
let lookup = IoC.CONTAINER.instance.innate_symbol_lookup
797
798
let arguments = Collections.LIST[Semantic.Types.Type]()
799
800
arguments.add(lookup.get_long_type())
801
802
return cast System.Reflection.Metadata.EntityHandle(
803
emitter.add_constructor_reference(
804
resolve_type_token(bigint_type),
805
"BigInteger::.ctor(int64)",
806
arguments))
807
si
808
809
resolve_bigint_parse(bigint_type: Semantic.Types.Type) -> System.Reflection.Metadata.EntityHandle is
810
let emitter = srm_assembly_emitter
811
let lookup = IoC.CONTAINER.instance.innate_symbol_lookup
812
813
let arguments = Collections.LIST[Semantic.Types.Type]()
814
815
arguments.add(lookup.get_string_type())
816
817
return cast System.Reflection.Metadata.EntityHandle(
818
emitter.add_named_member_reference(
819
resolve_type_token(bigint_type),
820
"Parse",
821
"BigInteger::Parse(string)",
822
Emitter.SRM_SIGNATURE_ENCODER(emitter)
823
.static_signature(bigint_type, arguments)))
824
si
825
826
// A static method on `System.Decimal`. Decimal has no IL
827
// opcodes of its own, so both its arithmetic and its
828
// conversions to and from other scalars are calls to one of
829
// these.
830
resolve_decimal_method(
831
method_name: string,
832
parameter_types: Collections.List[Semantic.Types.Type],
833
return_type: Semantic.Types.Type
834
) -> System.Reflection.Metadata.EntityHandle is
835
let emitter = srm_assembly_emitter
836
837
return cast System.Reflection.Metadata.EntityHandle(
838
emitter.add_named_member_reference(
839
resolve_type_token_by_name("System.Runtime", "System", "Decimal"),
840
method_name,
841
"Decimal::{method_name}/{parameter_types.count} -> {return_type}",
842
Emitter.SRM_SIGNATURE_ENCODER(emitter)
843
.static_signature(return_type, parameter_types)))
844
si
845
846
// A range struct is constructed from its two integer bounds.
847
resolve_range_constructor(
848
range_type: Semantic.Types.Type
849
) -> System.Reflection.Metadata.EntityHandle is
850
let emitter = srm_assembly_emitter
851
let lookup = IoC.CONTAINER.instance.innate_symbol_lookup
852
853
let arguments = Collections.LIST[Semantic.Types.Type]()
854
855
arguments.add(lookup.get_int_type())
856
arguments.add(lookup.get_int_type())
857
858
return cast System.Reflection.Metadata.EntityHandle(
859
emitter.add_constructor_reference(
860
resolve_type_token(range_type),
861
"range .ctor {range_type}",
862
arguments))
863
si
864
865
// A delegate is constructed from a receiver and a function
866
// pointer, so its constructor always takes (object, native int).
867
// The delegate type is normally a constructed generic, which
868
// has no reference row of its own: its TypeSpec is the owner.
869
resolve_delegate_constructor(
870
delegate_type: Semantic.Types.Type
871
) -> System.Reflection.Metadata.EntityHandle is
872
let emitter = srm_assembly_emitter
873
let lookup = IoC.CONTAINER.instance.innate_symbol_lookup
874
875
let arguments = Collections.LIST[Semantic.Types.Type]()
876
877
arguments.add(lookup.get_object_type())
878
arguments.add(lookup.get_word_type())
879
880
return cast System.Reflection.Metadata.EntityHandle(
881
emitter.add_constructor_reference(
882
resolve_type_token(delegate_type),
883
"delegate .ctor {delegate_type}",
884
arguments))
885
si
886
887
// The metadata token naming a field, for a load or store.
888
// Same rule as resolve_call_target: a field this assembly
889
// defines is named by its own FieldDef row, whose number the
890
// numbering pass has already fixed.
891
resolve_field_target(`field: Semantic.Symbols.Field) -> System.Reflection.Metadata.EntityHandle is
892
let emitter = srm_assembly_emitter
893
894
if let definition = emitter.handles.field_definition(`field) then
895
if !_owner_is_generic(`field) then
896
return cast System.Reflection.Metadata.EntityHandle(definition)
897
fi
898
fi
899
900
let root = cast Semantic.Symbols.Field?(`field.root_specialized_from) ?? `field
901
902
// The parent names the constructed owner while the name and
903
// signature come from the open definition: a reference to a
904
// field of `Pair[int]` hangs off a specification for that
905
// instantiation, and says its type is `!0`. Taking both from
906
// the unspecialized field points the reference at the open
907
// type, which is not a type any instantiation has.
908
//
909
// The name is the CLR one. A reflected member can be
910
// renamed on the way in — a tuple's `Item1` is `0` in ghūl —
911
// and it is the original the metadata has to carry.
912
return cast System.Reflection.Metadata.EntityHandle(
913
emitter.add_named_member_reference(
914
_member_owner_handle(`field),
915
root.il_name,
916
"field {root.owner}::{root.il_name}",
917
Emitter.SRM_SIGNATURE_ENCODER(emitter).field_signature(root)))
918
si
919
920
// Whether a member is declared by a generic type.
921
//
922
// A member of one cannot be named by its own definition row even
923
// when this assembly declares it: within the type's own methods
924
// the receiver is the type applied to its own parameters, and a
925
// definition row names the open type, which no instantiation is.
926
_owner_is_generic(member: Semantic.Symbols.Symbol) -> bool is
927
let owner = _owning_scope(member)
928
929
if isa Semantic.Symbols.GENERIC(owner) then
930
return true
931
fi
932
933
if let classy: Semantic.Symbols.Classy = owner then
934
return classy.is_generic
935
fi
936
937
return false
938
si
939
940
// An `impl` or `partial` block owns its members through the
941
// block's own scope, but they are members of the type the block
942
// injects into, and it is that type they hang off.
943
_owning_scope(member: Semantic.Symbols.Symbol) -> Semantic.Scope? =>
944
if let injection: Semantic.INJECTION_SCOPE = member.owner then
945
injection.target
946
else
947
member.owner
948
fi
949
950
// The reference row for the type an imported member hangs off.
951
// A global function or variable hangs off its namespace's
952
// globals carrier, which is a naming convention rather than a
953
// declared type; everything else hangs off its owning type.
954
_member_owner_handle(
955
member: Semantic.Symbols.Symbol
956
) -> System.Reflection.Metadata.EntityHandle is
957
let emitter = srm_assembly_emitter
958
959
let owner = _owning_scope(member)
960
961
// A member of a constructed generic hangs off the
962
// instantiation, which is named by a specification. The
963
// open type's own reference names a type of no arguments
964
// by that name, which does not exist, so a reference
965
// through it fails to load.
966
if let constructed: Semantic.Symbols.GENERIC = owner then
967
return resolve_type_token(constructed.type)
968
fi
969
970
// A member reached from inside its own generic type: the
971
// receiver is that type applied to its own parameters, so
972
// the reference hangs off a specification for exactly that,
973
// rendered `Type<!0, !1, ...>`.
974
//
975
// `Classy.type` is the *open* type (`Types.NAMED(self)`), so
976
// the instantiation has to be built here from the type
977
// parameters the class declared into its own scope.
978
if let classy: Semantic.Symbols.Classy = owner then
979
if classy.is_generic then
980
return cast System.Reflection.Metadata.EntityHandle(
981
emitter.add_type_specification(classy.own_instantiation))
982
fi
983
fi
984
985
// An imported global hangs off the carrier that holds it. A
986
// namespace can have several - one per assembly contributing
987
// globals to it, and a staging namespace re-homed onto it - so
988
// the carrier comes from the member rather than from the
989
// namespace it was re-homed onto.
990
let carrier =
991
if let global_function: Semantic.Symbols.GLOBAL_FUNCTION = member then
992
global_function.il_carrier
993
elif let global_variable: Semantic.Symbols.GLOBAL_VARIABLE = member then
994
global_variable.il_carrier
995
else
996
null
997
fi
998
999
if carrier? then
1000
return cast System.Reflection.Metadata.EntityHandle(
1001
Emitter.SRM_SIGNATURE_ENCODER(emitter).type_reference_for(carrier))
1002
fi
1003
1004
let owner_namespace =
1005
if let declared: Semantic.Symbols.NAMESPACE = owner then
1006
declared
1007
elif let scope: Semantic.NAMESPACE_SCOPE = owner then
1008
scope.containing_namespace
1009
else
1010
null
1011
fi
1012
1013
assert !owner_namespace? else
1014
"'{member.qualified_name}' is a global of a referenced assembly with no carrier recorded"
1015
1016
let owner_classy = cast Semantic.Symbols.Classy?(owner)
1017
1018
assert owner_classy? else "cannot reference a member owned by {owner}"
1019
1020
// A type this assembly defines is named by its own
1021
// definition row rather than by a reference into another
1022
// assembly. The row does not exist yet — the numbering pass
1023
// fixed which row it will be, and the token resolves once
1024
// the structure walk writes it.
1025
//
1026
// This comes after the generic branches above: a definition
1027
// row names the open type, so an instantiation still needs
1028
// a specification even when this assembly declares it.
1029
if let definition = emitter.handles.type_definition(owner_classy) then
1030
return cast System.Reflection.Metadata.EntityHandle(definition)
1031
fi
1032
1033
// il_name_override on an imported type is the CLR-side
1034
// dotted full name, unlike qualified_name which is the
1035
// ghūl-mapped spelling (e.g. "IO.Std" for System.Console).
1036
let il_name =
1037
owner_classy.il_name_override ?? owner_classy.qualified_name
1038
1039
let clr_type_name =
1040
Emitter.SRM_SIGNATURE_ENCODER.clr_name_for_primitive(il_name) ?? il_name
1041
1042
return cast System.Reflection.Metadata.EntityHandle(
1043
Emitter.SRM_SIGNATURE_ENCODER(emitter).reference_for_clr_name(
1044
owner_classy,
1045
_referenced_assembly(owner_classy.il_assembly_name ?? "", owner_classy),
1046
clr_type_name))
1047
si
1048
1049
// A type reference names the assembly it points into, which has
1050
// to have a row of its own before anything can name it.
1051
//
1052
// An empty name is not a usable reference: it produces a row the
1053
// runtime resolves to the assembly being built, so every type
1054
// named through it appears to be one this assembly defines and
1055
// fails to load. Refuse it rather than emit that.
1056
_referenced_assembly(assembly_name: string, owner: Semantic.Symbols.Symbol) -> string is
1057
assert assembly_name.length > 0 else
1058
"'{owner.qualified_name}' names no assembly to reference it through"
1059
1060
srm_assembly_emitter.add_assembly_reference(assembly_name)
1061
1062
return assembly_name
1063
si
1064
1065
resolve_call_target(function: Semantic.Symbols.Function) -> System.Reflection.Metadata.EntityHandle is
1066
let emitter = srm_assembly_emitter
1067
1068
// A target this assembly defines is called through its own
1069
// MethodDef row. The row does not exist yet — the numbering
1070
// pass fixed which row it will be, and the token embedded
1071
// here resolves once the structure walk writes it.
1072
//
1073
// Two cases cannot use it. A member of a generic type needs
1074
// a reference through the instantiation, because a
1075
// definition row names the open type. A generic method
1076
// called at an instantiation needs a MethodSpec over its
1077
// open definition, because a definition row names the
1078
// uninstantiated method and the runtime refuses to call one.
1079
if let definition = emitter.handles.method_definition(function) then
1080
if !_owner_is_generic(function) /\ function.generic_arguments.count == 0 then
1081
return cast System.Reflection.Metadata.EntityHandle(definition)
1082
fi
1083
fi
1084
1085
// An instantiation of a generic method is named by a
1086
// MethodSpec over the open method, not by a reference of its
1087
// own: the reference carries the method's own type
1088
// parameters as indexes, and the arguments live in the spec.
1089
let root = cast Semantic.Symbols.Function?(function.root_specialized_from) ?? function
1090
1091
// The open method this assembly defines is already a row of
1092
// its own, and a MethodSpec can name it directly. Building a
1093
// reference to it instead would name the same method twice,
1094
// once as a definition and once as a reference into this
1095
// assembly, which is not a shape the format has.
1096
//
1097
// Only when the owner is non-generic. A generic method on a
1098
// generic type needs both instantiations — the owner's, in a
1099
// reference through its TypeSpec, and the method's own — and
1100
// a definition row carries neither.
1101
if !_owner_is_generic(function) /\ function.generic_arguments.count > 0 then
1102
if let open_row = emitter.handles.method_definition(root) then
1103
return cast System.Reflection.Metadata.EntityHandle(
1104
emitter.add_method_specification(
1105
cast System.Reflection.Metadata.EntityHandle(open_row),
1106
"{function}",
1107
function.generic_arguments))
1108
fi
1109
fi
1110
1111
let owner_ref = _member_owner_handle(function)
1112
1113
let signature = Emitter.SRM_SIGNATURE_ENCODER(emitter).method_signature(root)
1114
1115
let reference =
1116
emitter.add_named_member_reference(
1117
owner_ref,
1118
Emitter.SRM_FLAGS.method_name(root),
1119
"method {function.owner}::{root.description}",
1120
signature)
1121
1122
if function.generic_arguments.count == 0 then
1123
return cast System.Reflection.Metadata.EntityHandle(reference)
1124
fi
1125
1126
return cast System.Reflection.Metadata.EntityHandle(
1127
emitter.add_method_specification(
1128
cast System.Reflection.Metadata.EntityHandle(reference),
1129
"{function}",
1130
function.generic_arguments))
1131
si
1132
si
1133
si