File 0159-compiler-Document-exception-handling-at-the-BEAM-SSA.patch of Package erlang

From 476baa9b2ce73dbb7e56036b56935b0e17c9d346 Mon Sep 17 00:00:00 2001
From: Frej Drejhammar <frej.drejhammar@gmail.com>
Date: Fri, 28 May 2021 10:43:53 +0200
Subject: [PATCH] compiler: Document exception handling at the BEAM SSA level
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Document how exception handlers are structured at the the BEAM SSA
level. The material in this patch is based on an email conversation
between the author and Björn Gustavsson <bjorn@erlang.org>.
---
 lib/compiler/internal_doc/beam_ssa.md | 107 ++++++++++++++++++++++++++
 1 file changed, 107 insertions(+)

diff --git a/lib/compiler/internal_doc/beam_ssa.md b/lib/compiler/internal_doc/beam_ssa.md
index 29ad019194..d32431ecff 100644
--- a/lib/compiler/internal_doc/beam_ssa.md
+++ b/lib/compiler/internal_doc/beam_ssa.md
@@ -1,6 +1,113 @@
 Invariants on the Structure and Format of BEAM SSA
 ==================================================
 
+Exception Handling
+------------------
+
+The translation of a `try`-`catch` expression into BEAM SSA has the
+following structure:
+
+    @tag = new_try_tag `try`
+	br @tag, ^protected_block0, ^landing_pad_block
+
+	protected_block0:
+	  @success0 = ... % Something that could raise an exception
+	  br @success0, ^protected_block1, ^landing_pad_block
+
+	...
+
+	protected_blockN:
+	  % The end of the protected code
+	  @ignored0 = kill_try_tag @tag
+      br ^after_try_catch
+
+	landing_pad_block:
+	  @aggregate = landingpad try, @tag
+	  @class  = extract @aggregate, `0` % The error class
+	  @reason = extract @aggregate, `1` % The reason
+	  @stk    = extract @aggregate, `2` % The stack trace
+	  @ignored1 = kill_try_tag @tag
+	  %% Pattern matching on @class, @reason, and @stk is done here
+	  %% to send control to the appropriate catch clause
+      br ^after_try_catch
+
+    after_try_catch:
+      % Normal execution continues
+
+The following invariants must hold for the SSA:
+
+ * All code that can cause an exception in one of the protected blocks
+   must have explicit control flow edges to the landing pad block. If
+   there are no edges to the landing pad block except from the block
+   containing the `new_try_tag`, the compiler will remove the
+   redundant exception handler.
+ * The extraction of the class, reason and stack trace from the result
+   of the `landingpad` instruction must be done in that
+   order. Omitting the extraction of elements which are unused is
+   allowed.
+ * Both the landing pad block and the final protected block must end
+   with a `kill_try_tag` instruction. Trying to share the
+   `kill_try_tag` epilogue between the last protected block and the
+   landing pad is unlikely to work.
+
+The translation of an old-style `catch` expression into BEAM SSA has
+the following structure:
+
+    @tag = new_try_tag `try`
+	br @tag, ^protected_block0, ^landing_pad_block
+
+	protected_block0:
+	  @success0 = ... % Something that could raise an exception
+	  br @success0, ^protected_block1, ^landing_pad_block
+
+	...
+
+	protected_blockN:
+	  % The end of the protected code
+	  @successful_result = .... % The result of a successful computation
+	  br ^common_end_of_catch
+
+	landing_pad_block:
+	   @aggregate = landingpad catch, @tag
+	   @catched_val = extract @ssa_agg, `0`
+	   br ^common_end_of_catch
+
+	common_end_of_catch:
+	  @tmp = phi { @catched_val, ^landing_pad_block },
+	             { @successful_result, ^protected_blockN }
+	  @result_of_catch_expr = catch_end @tag, @tmp
+
+Just as for a `try`-`catch` expression all code that can cause an
+exception in one of the protected blocks must have explicit control
+flow edges to the landing pad block.
+
+Exception Re-issuing
+--------------------
+
+A typical user-written `try`-`catch` expression will catch a subset of
+all possible exception classes and reasons and leave unhandled
+exceptions to a handler further up the call stack. Re-issuing an
+exception is done with the `resume` instruction. The `resume` must
+come after the `kill_try_tag` instruction in the program flow. For
+example, if the [example in the Exception Handling Section](#exception-handling)
+was to only handle user `throws`, the relevant blocks would look like this:
+
+	landing_pad_block:
+	  @aggregate = landingpad `try`, @tag
+	  @class  = extract @aggregate, `0` % The error class
+	  @reason = extract @aggregate, `1` % The reason
+	  @stk    = extract @aggregate, `2` % The stack trace
+	  @ignored1 = kill_try_tag @tag
+	  @is_throw = bif:'=:=' @class, `throw`
+      br @is_throw ^first_block_of_throw_handler, ^reissue
+
+	first_block_of_throw_handler:
+	  %% Handle the user-defined throw
+
+	reissue:
+	  @tmp = resume @stk, @reason
+	  ret @tmp
+
 Function Calls
 --------------
 
-- 
2.26.2

openSUSE Build Service is sponsored by