Skip to content
← Back

src/ir/values/load/self.ghul

1
namespace IR.Values.Load is
2
use TypeTyped = Semantic.Types.Typed;
3
use Semantic.Types.Type;
4
use SymbolBase = Semantic.Symbols.Symbol;
5
6
class REFERENCE_SELF: Value, TypeTyped is
7
`self: SymbolBase;
8
type: Type;
9
10
is_self: bool => true;
11
has_address: bool => true;
12
is_lightweight_pure: bool => true;
13
14
init(`self: SymbolBase) is
15
init(`self, null);
16
si
17
18
init(`self: SymbolBase, type: Type?) is
19
super.init();
20
21
self.`self = `self;
22
23
if type? then
24
self.type = type;
25
elif isa TypeTyped(`self) then
26
self.type = cast TypeTyped(`self).type!;
27
fi
28
si
29
30
gen(context: IR.CONTEXT) is
31
context.write_line("ldarg.0");
32
si
33
34
gen_address(context: IR.CONTEXT) is
35
context.write_line("ldarg.0");
36
si
37
38
to_string() -> string =>
39
"self:[{type}]";
40
si
41
42
// Self-load inside a generator's MoveNext: ldarg.0 is the
43
// state-machine frame, not the user's instance, so the body's
44
// `self` accesses go through the synthesised _outer_self
45
// frame field. INSTANCE_GENERATOR_METHOD.load_self constructs
46
// this variant; ordinary instance methods keep the plain
47
// REFERENCE_SELF (ldarg.0).
48
class OUTER_SELF: Value, TypeTyped is
49
`self: SymbolBase;
50
outer_self_field: Semantic.Symbols.Field;
51
type: Type;
52
53
is_self: bool => true;
54
has_address: bool => true;
55
is_lightweight_pure: bool => true;
56
57
init(`self: SymbolBase, type: Type?, outer_self_field: Semantic.Symbols.Field) is
58
super.init();
59
60
self.`self = `self;
61
self.outer_self_field = outer_self_field;
62
63
if type? then
64
self.type = type;
65
elif isa TypeTyped(`self) then
66
self.type = cast TypeTyped(`self).type!;
67
fi
68
si
69
70
gen(context: IR.CONTEXT) is
71
context.write_line("ldarg.0");
72
context.write_line("ldfld {outer_self_field.get_il_reference()}");
73
si
74
75
gen_address(context: IR.CONTEXT) is
76
context.write_line("ldarg.0");
77
context.write_line("ldfld {outer_self_field.get_il_reference()}");
78
si
79
80
to_string() -> string =>
81
"outer_self:[{type}]";
82
si
83
84
// pretty much all the time we reference a struct's self
85
// we actually want the address, but for an explicit `self`
86
// we need the value:
87
class VALUE_SELF: Value, TypeTyped is
88
`self: SymbolBase;
89
type: Type;
90
91
is_self: bool => true;
92
has_address: bool => true;
93
is_lightweight_pure: bool => true;
94
95
init(`self: SymbolBase) is
96
init(`self, null);
97
si
98
99
init(`self: SymbolBase, type: Type?) is
100
super.init();
101
102
self.`self = `self;
103
104
if type? then
105
self.type = type;
106
elif isa TypeTyped(`self) then
107
self.type = cast TypeTyped(`self).type!;
108
fi
109
si
110
111
gen(context: IR.CONTEXT) is
112
context.write_line("ldarg.0");
113
context.write_line("ldobj {type.get_il_type()}");
114
si
115
116
// we do actually have an address, just default to the value
117
gen_address(context: IR.CONTEXT) is
118
context.write_line("ldarg.0");
119
si
120
121
to_string() -> string =>
122
"self:[{type}]";
123
si
124
125
si