@@ -1681,11 +1681,12 @@ that use a SIL value are required to be able to be semantically partitioned in
1681
1681
between "non-lifetime ending uses" that just require the value to be live and
1682
1682
"lifetime ending uses" that end the lifetime of the value and after which the
1683
1683
value can no longer be used. Since by definition operands that are lifetime
1684
- ending uses end their associated value's lifetime, we must have that the
1685
- lifetime ending use points jointly post-dominate all non-lifetime ending use
1686
- points and that a value must have exactly one lifetime ending use along all
1687
- reachable program paths, preventing leaks and use-after-frees. As an example,
1688
- consider the following SIL example with partitioned defs/uses annotated inline::
1684
+ ending uses end their associated value's lifetime, we must have that, ignoring
1685
+ program ending `Dead End Blocks `_, the lifetime ending use points jointly
1686
+ post-dominate all non-lifetime ending use points and that a value must have
1687
+ exactly one lifetime ending use along all reachable program paths, preventing
1688
+ leaks and use-after-frees. As an example, consider the following SIL example
1689
+ with partitioned defs/uses annotated inline::
1689
1690
1690
1691
sil @stash_and_cast : $@convention(thin) (@owned Klass) -> @owned SuperKlass {
1691
1692
bb0(%kls1 : @owned $Klass): // Definition of %kls1
@@ -2316,6 +2317,81 @@ The current list of interior pointer SIL instructions are:
2316
2317
(*) We still need to finish adding support for project_box, but all other
2317
2318
interior pointers are guarded already.
2318
2319
2320
+ Dead End Blocks
2321
+ ~~~~~~~~~~~~~~~
2322
+
2323
+ In SIL, one can express that a program is semantically expected to exit at the
2324
+ end of a block by terminating the block with an `unreachable `_. Such a block is
2325
+ called a *program terminating block * and all blocks that are post-dominated by
2326
+ blocks of the aforementioned kind are called *dead end blocks *. Intuitively, any
2327
+ path through a dead end block is known to result in program termination, so
2328
+ resources that normally would need to be released back to the system will
2329
+ instead be returned to the system by process tear down.
2330
+
2331
+ Since we rely on the system at these points to perform resource cleanup, we are
2332
+ able to loosen our lifetime requirements by allowing for values to not have
2333
+ their lifetimes ended along paths that end in program terminating
2334
+ blocks. Operationally, this implies that:
2335
+
2336
+ * All SIL values must have exactly one lifetime ending use on all paths that
2337
+ terminate in a `return `_ or `throw `_. In contrast, a SIL value does not need to
2338
+ have a lifetime ending use along paths that end in an `unreachable `_.
2339
+
2340
+ * `end_borrow `_ and `destroy_value `_ are redundent, albeit legal, in blocks
2341
+ where all paths through the block end in an `unreachable `_.
2342
+
2343
+ Consider the following legal SIL where we leak ``%0 `` in blocks prefixed with
2344
+ ``bbDeadEndBlock `` and consume it in ``bb2 ``::
2345
+
2346
+ sil @user : $@convention(thin) (@owned Klass) -> @owned Klass {
2347
+ bb0(%0 : @owned $Klass):
2348
+ cond_br ..., bb1, bb2
2349
+
2350
+ bb1:
2351
+ // This is a dead end block since it is post-dominated by two dead end
2352
+ // blocks. It is not a program terminating block though since the program
2353
+ // does not end in this block.
2354
+ cond_br ..., bbDeadEndBlock1, bbDeadEndBlock2
2355
+
2356
+ bbDeadEndBlock1:
2357
+ // This is a dead end block and a program terminating block.
2358
+ //
2359
+ // We are exiting the program here causing the operating system to clean up
2360
+ // all resources associated with our process, so there is no need for a
2361
+ // destroy_value. That memory will be cleaned up anyways.
2362
+ unreachable
2363
+
2364
+ bbDeadEndBlock2:
2365
+ // This is a dead end block and a program terminating block.
2366
+ //
2367
+ // Even though we do not need to insert destroy_value along these paths, we
2368
+ // can if we want to. It is just necessary and the optimizer can eliminate
2369
+ // such a destroy_value if it wishes.
2370
+ //
2371
+ // NOTE: The author arbitrarily chose just to destroy %0: we could legally
2372
+ // destroy either value (or both!).
2373
+ destroy_value %0 : $Klass
2374
+ unreachable
2375
+
2376
+ bb2:
2377
+ cond_br ..., bb3, bb4
2378
+
2379
+ bb3:
2380
+ // This block is live, so we need to ensure that %0 is consumed within the
2381
+ // block. In this case, %0 is consumed by returning %0 to our caller.
2382
+ return %0 : $Klass
2383
+
2384
+ bb4:
2385
+ // This block is also live, but since we do not return %0, we must insert a
2386
+ // destroy_value to cleanup %0.
2387
+ //
2388
+ // NOTE: The copy_value/destroy_value here is redundent and can be removed by
2389
+ // the optimizer. The author left it in for illustrative purposes.
2390
+ %1 = copy_value %0 : $Klass
2391
+ destroy_value %0 : $Klass
2392
+ return %1 : $Klass
2393
+ }
2394
+
2319
2395
Runtime Failure
2320
2396
---------------
2321
2397
0 commit comments