Skip to content
← Back

src/ir/values/memoized_delegate.ghul

1
namespace IR.Values is
2
use TypeTyped = Semantic.Types.Typed
3
use Semantic.Types.Type
4
5
// Wraps the creation of a stateless delegate (a zero-capture,
6
// ground function literal) so it is built at most once and reused.
7
// The first evaluation allocates the delegate and stores it into a
8
// static cache field; every later evaluation loads the cached one.
9
// Behaviour matches `inner` exactly because the wrapped literal
10
// captures nothing and carries no type arguments, so a single
11
// instance is interchangeable everywhere it is used.
12
//
13
// ldsfld <cache>
14
// dup
15
// brtrue Lpresent
16
// pop
17
// <inner delegate-creation IL>
18
// dup
19
// stsfld <cache>
20
// Lpresent:
21
class MEMOIZED_DELEGATE: Value, TypeTyped is
22
_inner: Value
23
_cache_field: Semantic.Symbols.Field
24
_type: Type
25
26
type: Type => _type
27
28
inner: Value => _inner
29
30
init(
31
inner: Value,
32
cache_field: Semantic.Symbols.Field,
33
type: Type
34
) is
35
super.init()
36
37
_inner = inner
38
_cache_field = cache_field
39
_type = type
40
si
41
42
referenced_function: Semantic.Symbols.Function? => _inner.referenced_function
43
44
// Stay live rather than freezing to a pre-rendered RAW: gen()
45
// mints a fresh cache-hoist label per emit site, so a delegate
46
// emitted from more than one place gets distinct labels instead
47
// of one baked into a RAW and duplicated.
48
freeze() -> Value => self
49
50
gen(context: IR.CONTEXT) is
51
let present = IR.LABEL()
52
53
let body = context.current_srm_body_emitter!
54
let cache = context.resolve_field_target(_cache_field)
55
56
body.ldsfld(cache)
57
body.op(System.Reflection.Metadata.ILOpCode.DUP)
58
body.branch(System.Reflection.Metadata.ILOpCode.BRTRUE, present)
59
body.op(System.Reflection.Metadata.ILOpCode.POP)
60
gen(_inner, context)
61
body.op(System.Reflection.Metadata.ILOpCode.DUP)
62
body.stsfld(cache)
63
body.mark_label(present)
64
si
65
66
to_string() -> string =>
67
"memoized-delegate:[{_type}]({_inner})"
68
si
69
si