xref: /aosp_15_r20/external/llvm/docs/FaultMaps.rst (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker==============================
2*9880d681SAndroid Build Coastguard WorkerFaultMaps and implicit checks
3*9880d681SAndroid Build Coastguard Worker==============================
4*9880d681SAndroid Build Coastguard Worker
5*9880d681SAndroid Build Coastguard Worker.. contents::
6*9880d681SAndroid Build Coastguard Worker   :local:
7*9880d681SAndroid Build Coastguard Worker   :depth: 2
8*9880d681SAndroid Build Coastguard Worker
9*9880d681SAndroid Build Coastguard WorkerMotivation
10*9880d681SAndroid Build Coastguard Worker==========
11*9880d681SAndroid Build Coastguard Worker
12*9880d681SAndroid Build Coastguard WorkerCode generated by managed language runtimes tend to have checks that
13*9880d681SAndroid Build Coastguard Workerare required for safety but never fail in practice.  In such cases, it
14*9880d681SAndroid Build Coastguard Workeris profitable to make the non-failing case cheaper even if it makes
15*9880d681SAndroid Build Coastguard Workerthe failing case significantly more expensive.  This asymmetry can be
16*9880d681SAndroid Build Coastguard Workerexploited by folding such safety checks into operations that can be
17*9880d681SAndroid Build Coastguard Workermade to fault reliably if the check would have failed, and recovering
18*9880d681SAndroid Build Coastguard Workerfrom such a fault by using a signal handler.
19*9880d681SAndroid Build Coastguard Worker
20*9880d681SAndroid Build Coastguard WorkerFor example, Java requires null checks on objects before they are read
21*9880d681SAndroid Build Coastguard Workerfrom or written to.  If the object is ``null`` then a
22*9880d681SAndroid Build Coastguard Worker``NullPointerException`` has to be thrown, interrupting normal
23*9880d681SAndroid Build Coastguard Workerexecution.  In practice, however, dereferencing a ``null`` pointer is
24*9880d681SAndroid Build Coastguard Workerextremely rare in well-behaved Java programs, and typically the null
25*9880d681SAndroid Build Coastguard Workercheck can be folded into a nearby memory operation that operates on
26*9880d681SAndroid Build Coastguard Workerthe same memory location.
27*9880d681SAndroid Build Coastguard Worker
28*9880d681SAndroid Build Coastguard WorkerThe Fault Map Section
29*9880d681SAndroid Build Coastguard Worker=====================
30*9880d681SAndroid Build Coastguard Worker
31*9880d681SAndroid Build Coastguard WorkerInformation about implicit checks generated by LLVM are put in a
32*9880d681SAndroid Build Coastguard Workerspecial "fault map" section.  On Darwin this section is named
33*9880d681SAndroid Build Coastguard Worker``__llvm_faultmaps``.
34*9880d681SAndroid Build Coastguard Worker
35*9880d681SAndroid Build Coastguard WorkerThe format of this section is
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Worker.. code-block:: none
38*9880d681SAndroid Build Coastguard Worker
39*9880d681SAndroid Build Coastguard Worker  Header {
40*9880d681SAndroid Build Coastguard Worker    uint8  : Fault Map Version (current version is 1)
41*9880d681SAndroid Build Coastguard Worker    uint8  : Reserved (expected to be 0)
42*9880d681SAndroid Build Coastguard Worker    uint16 : Reserved (expected to be 0)
43*9880d681SAndroid Build Coastguard Worker  }
44*9880d681SAndroid Build Coastguard Worker  uint32 : NumFunctions
45*9880d681SAndroid Build Coastguard Worker  FunctionInfo[NumFunctions] {
46*9880d681SAndroid Build Coastguard Worker    uint64 : FunctionAddress
47*9880d681SAndroid Build Coastguard Worker    uint32 : NumFaultingPCs
48*9880d681SAndroid Build Coastguard Worker    uint32 : Reserved (expected to be 0)
49*9880d681SAndroid Build Coastguard Worker    FunctionFaultInfo[NumFaultingPCs] {
50*9880d681SAndroid Build Coastguard Worker      uint32  : FaultKind = FaultMaps::FaultingLoad (only legal value currently)
51*9880d681SAndroid Build Coastguard Worker      uint32  : FaultingPCOffset
52*9880d681SAndroid Build Coastguard Worker      uint32  : HandlerPCOffset
53*9880d681SAndroid Build Coastguard Worker    }
54*9880d681SAndroid Build Coastguard Worker  }
55*9880d681SAndroid Build Coastguard Worker
56*9880d681SAndroid Build Coastguard Worker
57*9880d681SAndroid Build Coastguard WorkerThe ``ImplicitNullChecks`` pass
58*9880d681SAndroid Build Coastguard Worker===============================
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard WorkerThe ``ImplicitNullChecks`` pass transforms explicit control flow for
61*9880d681SAndroid Build Coastguard Workerchecking if a pointer is ``null``, like:
62*9880d681SAndroid Build Coastguard Worker
63*9880d681SAndroid Build Coastguard Worker.. code-block:: llvm
64*9880d681SAndroid Build Coastguard Worker
65*9880d681SAndroid Build Coastguard Worker    %ptr = call i32* @get_ptr()
66*9880d681SAndroid Build Coastguard Worker    %ptr_is_null = icmp i32* %ptr, null
67*9880d681SAndroid Build Coastguard Worker    br i1 %ptr_is_null, label %is_null, label %not_null, !make.implicit !0
68*9880d681SAndroid Build Coastguard Worker
69*9880d681SAndroid Build Coastguard Worker  not_null:
70*9880d681SAndroid Build Coastguard Worker    %t = load i32, i32* %ptr
71*9880d681SAndroid Build Coastguard Worker    br label %do_something_with_t
72*9880d681SAndroid Build Coastguard Worker
73*9880d681SAndroid Build Coastguard Worker  is_null:
74*9880d681SAndroid Build Coastguard Worker    call void @HFC()
75*9880d681SAndroid Build Coastguard Worker    unreachable
76*9880d681SAndroid Build Coastguard Worker
77*9880d681SAndroid Build Coastguard Worker  !0 = !{}
78*9880d681SAndroid Build Coastguard Worker
79*9880d681SAndroid Build Coastguard Workerto control flow implicit in the instruction loading or storing through
80*9880d681SAndroid Build Coastguard Workerthe pointer being null checked:
81*9880d681SAndroid Build Coastguard Worker
82*9880d681SAndroid Build Coastguard Worker.. code-block:: llvm
83*9880d681SAndroid Build Coastguard Worker
84*9880d681SAndroid Build Coastguard Worker    %ptr = call i32* @get_ptr()
85*9880d681SAndroid Build Coastguard Worker    %t = load i32, i32* %ptr  ;; handler-pc = label %is_null
86*9880d681SAndroid Build Coastguard Worker    br label %do_something_with_t
87*9880d681SAndroid Build Coastguard Worker
88*9880d681SAndroid Build Coastguard Worker  is_null:
89*9880d681SAndroid Build Coastguard Worker    call void @HFC()
90*9880d681SAndroid Build Coastguard Worker    unreachable
91*9880d681SAndroid Build Coastguard Worker
92*9880d681SAndroid Build Coastguard WorkerThis transform happens at the ``MachineInstr`` level, not the LLVM IR
93*9880d681SAndroid Build Coastguard Workerlevel (so the above example is only representative, not literal).  The
94*9880d681SAndroid Build Coastguard Worker``ImplicitNullChecks`` pass runs during codegen, if
95*9880d681SAndroid Build Coastguard Worker``-enable-implicit-null-checks`` is passed to ``llc``.
96*9880d681SAndroid Build Coastguard Worker
97*9880d681SAndroid Build Coastguard WorkerThe ``ImplicitNullChecks`` pass adds entries to the
98*9880d681SAndroid Build Coastguard Worker``__llvm_faultmaps`` section described above as needed.
99*9880d681SAndroid Build Coastguard Worker
100*9880d681SAndroid Build Coastguard Worker``make.implicit`` metadata
101*9880d681SAndroid Build Coastguard Worker--------------------------
102*9880d681SAndroid Build Coastguard Worker
103*9880d681SAndroid Build Coastguard WorkerMaking null checks implicit is an aggressive optimization, and it can
104*9880d681SAndroid Build Coastguard Workerbe a net performance pessimization if too many memory operations end
105*9880d681SAndroid Build Coastguard Workerup faulting because of it.  A language runtime typically needs to
106*9880d681SAndroid Build Coastguard Workerensure that only a negligible number of implicit null checks actually
107*9880d681SAndroid Build Coastguard Workerfault once the application has reached a steady state.  A standard way
108*9880d681SAndroid Build Coastguard Workerof doing this is by healing failed implicit null checks into explicit
109*9880d681SAndroid Build Coastguard Workernull checks via code patching or recompilation.  It follows that there
110*9880d681SAndroid Build Coastguard Workerare two requirements an explicit null check needs to satisfy for it to
111*9880d681SAndroid Build Coastguard Workerbe profitable to convert it to an implicit null check:
112*9880d681SAndroid Build Coastguard Worker
113*9880d681SAndroid Build Coastguard Worker  1. The case where the pointer is actually null (i.e. the "failing"
114*9880d681SAndroid Build Coastguard Worker     case) is extremely rare.
115*9880d681SAndroid Build Coastguard Worker
116*9880d681SAndroid Build Coastguard Worker  2. The failing path heals the implicit null check into an explicit
117*9880d681SAndroid Build Coastguard Worker     null check so that the application does not repeatedly page
118*9880d681SAndroid Build Coastguard Worker     fault.
119*9880d681SAndroid Build Coastguard Worker
120*9880d681SAndroid Build Coastguard WorkerThe frontend is expected to mark branches that satisfy (1) and (2)
121*9880d681SAndroid Build Coastguard Workerusing a ``!make.implicit`` metadata node (the actual content of the
122*9880d681SAndroid Build Coastguard Workermetadata node is ignored).  Only branches that are marked with
123*9880d681SAndroid Build Coastguard Worker``!make.implicit`` metadata are considered as candidates for
124*9880d681SAndroid Build Coastguard Workerconversion into implicit null checks.
125*9880d681SAndroid Build Coastguard Worker
126*9880d681SAndroid Build Coastguard Worker(Note that while we could deal with (1) using profiling data, dealing
127*9880d681SAndroid Build Coastguard Workerwith (2) requires some information not present in branch profiles.)
128