Sunday, 30 May 2010

[Book] Chapter 2.5 Custom IR1 Translators [part 2]

The special operator tagbody is handled by this translator:




The translator uses a supplementary function to analyze the body, sb-c::parse-tagbody (from the same source file). For the IR1 conversion, it performs the next steps:

- allocates a dummy control transfer, a new entry and a new cleanup node;
- collects a tag and its control transfer for all tags in the body;
- converts all segments using sb-c::ir1-convert-progn-body, and links 'result' lvar with the last segment's return value. Notice the tricky starts/ctrans collection: 'starts' has the dummy control transfer as the first list element, and 'ctrans' has 'next' control transfer as the last list element. This allows to have the elegant solution with mapc later, when control flow goes through all tags and reaches 'next' ctran eventually.

The conversion result is shown on this figure:




The translator uses the value of the last segment as a result, so we show it separately with 'last-tag' control transfer.

Another IR1 translator which is tightly coupled with the above is the one for go special operator. Its code is here:




As one can see, it is pretty simple. The translator searches for the tag to go in the current lexical environment, where the tag has been stored by tagbody converter. Then the code flow will be start → exit → tag-ctran. Notice that 'result' lvar is not touched at all. We do not give the explanatory figure here, due to the trivial nature of the conversion.

Let and let* converters delegate most of their work to other functions. They both use sb-c::extract-let-vars to extract the essential information about the declared variables. After that, the familiar to us functions parse-body, processing-decls, ir1-convert-lambda-body, ir1-convert-aux-bindings and some others do the rest of the conversion. The main idea of both these conversions is that they are performed in the modified 'post-binding-lexenv' lexical environment.

Catch, throw and unwind-protect share some similar principles of the conversion. They are implemented as wrappers over their body code, and use internal forms %within-cleanup, %catch, %throw and %unwind-protect to express the conversion in more low-level terms.

Let us look at %within-cleanup IR1 converter closer. Here is its code:




The things which happen during the conversion are illustrated on this figure:




Some manipulations with lexical environments and cleanups are not shown here, you can read about them in the source code comments.

2 comments:

  1. Thanks a bunch for writing this! Ive always wanted to understand sbcl internals and now with your articles Ive been able to get a window into the sbcl architecture.

    ReplyDelete
  2. I am glad that you like it :)

    The main goal of this book is to grow the SBCL developers community, and I encourage my readers to select easy bugs in Launchpad and try to fix them.

    ReplyDelete