Skip to content
← Back

src/ir/values/async_method_launch.ghul

1
namespace IR.Values is
2
use TypeTyped = Semantic.Types.Typed
3
use Semantic.Types.Type
4
5
// Outer-method body of an async function. Newobjs the state
6
// machine with the user's args (instance methods prefix
7
// `ldarg.0` for $outer_self), creates+stashes the builder,
8
// calls `builder.Start(ref this)`, and leaves the Task on the
9
// stack. Caller emits `ret`.
10
//
11
// Stack effect: 0 → 1.
12
class ASYNC_METHOD_LAUNCH: Value, TypeTyped is
13
type: Type
14
15
state_machine_type: Type
16
constructor: Semantic.Symbols.Function
17
ctor_arg_loads: Value
18
state_field: Semantic.Symbols.Field
19
builder_field: Semantic.Symbols.Field
20
21
sm_local_name: string
22
23
init(
24
type: Type,
25
state_machine_type: Type,
26
constructor: Semantic.Symbols.Function,
27
ctor_arg_loads: Value,
28
state_field: Semantic.Symbols.Field,
29
builder_field: Semantic.Symbols.Field,
30
sm_local_name: string
31
) is
32
super.init()
33
34
self.type = type
35
self.state_machine_type = state_machine_type
36
self.constructor = constructor
37
self.ctor_arg_loads = ctor_arg_loads
38
self.state_field = state_field
39
self.builder_field = builder_field
40
self.sm_local_name = sm_local_name
41
si
42
43
gen(context: IR.CONTEXT) is
44
let body = context.current_srm_body_emitter!
45
_gen_srm(context, body)
46
si
47
48
_gen_srm(context: IR.CONTEXT, body: IR.Emitter.SRM_METHOD_BODY_EMITTER) is
49
let builder_type = builder_field.type!
50
51
body.declare_local(sm_local_name, state_machine_type)
52
53
gen(ctor_arg_loads, context)
54
body.new_object(context.resolve_call_target(constructor))
55
body.stloc(sm_local_name)
56
57
body.ldloc(sm_local_name)
58
body.ldc_i4(-1)
59
body.stfld(context.resolve_field_target(state_field))
60
61
body.ldloc(sm_local_name)
62
body.call(
63
context.resolve_builder_member(builder_type, "create", 0))
64
body.stfld(context.resolve_field_target(builder_field))
65
66
body.ldloc(sm_local_name)
67
_load_builder(context, body, builder_type)
68
body.ldloca(sm_local_name)
69
body.call(context.resolve_async_builder_start(builder_type, state_machine_type))
70
71
body.ldloc(sm_local_name)
72
_load_builder(context, body, builder_type)
73
body.call(
74
context.resolve_builder_property(builder_type, "task"))
75
si
76
77
// A struct builder is reached through its address - `this` for a
78
// byref receiver and the `ref` the builder methods take - while a
79
// class builder is reached through the object the field holds.
80
// Shared with the MoveNext trailer, which reaches the builder
81
// the same way.
82
load_builder(
83
body: IR.Emitter.SRM_METHOD_BODY_EMITTER,
84
builder_type: Type,
85
builder_reference: System.Reflection.Metadata.EntityHandle
86
) static is
87
if builder_type.is_value_type then
88
body.ldflda(builder_reference)
89
else
90
body.ldfld(builder_reference)
91
fi
92
si
93
94
_load_builder(
95
context: IR.CONTEXT,
96
body: IR.Emitter.SRM_METHOD_BODY_EMITTER,
97
builder_type: Type
98
) is
99
load_builder(
100
body, builder_type, context.resolve_field_target(builder_field))
101
si
102
103
to_string() -> string =>
104
"async-method-launch:[{type}]({state_machine_type})"
105
si
106
si