Skip to content
← Back

src/ir/values/null_coalesce.ghul

1
namespace IR.Values is
2
use Semantic.Types.Type
3
4
// The result of `a ?? b` for a reference-typed `a: T?`. `T?` is a
5
// reference that may be null at IL, so a single dup-and-branch is
6
// enough — `b` is evaluated only when `a` is null.
7
//
8
// <left IL> // [..., a]
9
// dup // [..., a, a]
10
// brtrue.s <end> // pops the top a; non-null leaves the
11
// // other a on the stack at end
12
// pop // [...]
13
// <right IL> // [..., b]
14
// <end>:
15
//
16
// Built by COMPILE_OPERATORS.visit_binary when the operator is `??`.
17
// The two operands are evaluated by their own Values; this Value
18
// composes the surrounding short-circuit shell.
19
class NULL_COALESCE: Value is
20
left: Value
21
right: Value
22
_result_type: Type
23
24
type: Type => _result_type
25
is_lightweight_pure: bool => false
26
27
init(left: Value, right: Value, result_type: Type) is
28
super.init()
29
30
self.left = left
31
self.right = right
32
self._result_type = result_type
33
si
34
35
gen(context: IR.CONTEXT) is
36
let end_label = IR.LABEL()
37
38
gen(left, context)
39
40
let body = context.current_srm_body_emitter!
41
body.op(System.Reflection.Metadata.ILOpCode.DUP)
42
body.branch(System.Reflection.Metadata.ILOpCode.BRTRUE, end_label)
43
body.op(System.Reflection.Metadata.ILOpCode.POP)
44
gen(right, context)
45
body.mark_label(end_label)
46
si
47
48
to_string() -> string =>
49
"null-coalesce:[{type}]({left},{right})"
50
si
51
si