Skip to content
← Back

src/ir/values/reference_null_check.ghul

1
namespace IR.Values is
2
use Semantic.Types.Type
3
4
// `!` on a plain reference-typed `T?`: at IL a reference optional is
5
// already just `T`, so there is nothing to unwrap — `!`'s only job
6
// is to make an absent value throw here, rather than silently
7
// passing null on to wherever the (now falsely non-optional) value
8
// is eventually read. `GetType()` is called and discarded purely to
9
// force the runtime's own null check; the JIT is free to see the
10
// loaded `Type` go unused and keep only the check.
11
//
12
// <inner IL> // [..., v]
13
// dup // [..., v, v]
14
// callvirt GetType() // [..., v, type] — throws NullReferenceException if v is null
15
// pop // [..., v]
16
class REFERENCE_NULL_CHECK: Value is
17
inner: Value
18
_type: Type
19
20
type: Type => _type
21
is_lightweight_pure: bool => false
22
23
init(inner: Value, result_type: Type) is
24
super.init()
25
26
self.inner = inner
27
self._type = result_type
28
si
29
30
gen(context: IR.CONTEXT) is
31
gen(inner, context)
32
33
let body = context.current_srm_body_emitter!
34
body.op(System.Reflection.Metadata.ILOpCode.DUP)
35
body.call_virtual(context.resolve_object_get_type())
36
body.op(System.Reflection.Metadata.ILOpCode.POP)
37
si
38
39
to_string() -> string =>
40
"reference-null-check:[{type}]({inner})"
41
si
42
si