1#lang scribble/doc
2@(require scribble/manual
3          "common.rkt"
4          (for-label racket/base
5                     racket/contract
6                     compiler/zo-parse
7                     compiler/decompile
8                     compiler/faslable-correlated
9                     racket/set))
10
11@(define-syntax-rule (defstruct+ id fields . rest)
12   (defstruct id fields #:prefab . rest))
13
14@title{API for Parsing Bytecode}
15
16@defmodule[compiler/zo-parse]
17
18The @racketmodname[compiler/zo-parse] module re-exports
19@racketmodname[compiler/zo-structs] in addition to
20@racket[zo-parse].
21
22@defproc[(zo-parse [in input-port? (current-input-port)]) (or/c linkl-directory? linkl-bundle?)]{
23  Parses a port (typically the result of opening a @filepath{.zo} file)
24  containing bytecode.  Beware that the structure types used to
25  represent the bytecode are subject to frequent changes across Racket
26  versions.
27
28  The parsed bytecode is returned in a @racket[linkl-directory] or
29  @racket[linkl-bundle] structure---the latter only for the compilation
30  of a module that contains no submodules.
31
32  Beyond the linklet bundle or directory structure, the result of
33  @racket[zo-parse] contains linklets that depend on the machine for
34  which the bytecode is compiled:
35
36  @itemlist[
37
38    @item{For a machine-independent bytecode file, a linklet is
39          represented as a @racket[faslable-correlated-linklet].}
40
41    @item{For a Racket @CS bytecode file, a linklet is opaque, because
42          it is primarily machine code, but @racket[decompile] can
43          extract some information and potentially disassemble the
44          machine code.}
45
46    @item{For Racket @BC bytecode, the bytecode can be parsed into
47          structures as described below.}
48
49   ]
50
51  The rest of this section is specific to @BC bytecode.
52
53  Within a linklet, the bytecode representation of an expression is closer to an
54  S-expression than a traditional, flat control string.  For example, an
55  @racket[if] form is represented by a @racket[branch] structure that
56  has three fields: a test expression, a ``then'' expression, and an
57  ``else'' expression.  Similarly, a function call is represented by an
58  @racket[application] structure that has a list of argument
59  expressions.
60
61  Storage for local variables or intermediate values (such as the
62  arguments for a function call) is explicitly specified in terms of a
63  stack.  For example, execution of an @racket[application] structure
64  reserves space on the stack for each argument result.  Similarly, when
65  a @racket[let-one] structure (for a simple @racket[let]) is executed,
66  the value obtained by evaluating the right-hand side expression is
67  pushed onto the stack, and then the body is evaluated.  Local
68  variables are always accessed as offsets from the current stack
69  position.  When a function is called, its arguments are passed on the
70  stack.  A closure is created by transferring values from the stack to
71  a flat closure record, and when a closure is applied, the saved values
72  are restored on the stack (though possibly in a different order and
73  likely in a more compact layout than when they were captured).
74
75  When a sub-expression produces a value, then the stack pointer is
76  restored to its location from before evaluating the sub-expression.
77  For example, evaluating the right-hand size for a @racket[let-one]
78  structure may temporarily push values onto the stack, but the stack is
79  restored to its pre-@racket[let-one] position before pushing the
80  resulting value and continuing with the body.  In addition, a tail
81  call resets the stack pointer to the position that follows the
82  enclosing function's arguments, and then the tail call continues by
83  pushing onto the stack the arguments for the tail-called function.
84
85  Values for global and module-level variables are not put directly on
86  the stack, but instead stored in ``buckets,'' and an array of
87  accessible buckets is kept on the stack.  When a closure body needs to
88  access a global variable, the closure captures and later restores the
89  bucket array in the same way that it captured and restores a local
90  variable.  Mutable local variables are boxed similarly to global
91  variables, but individual boxes are referenced from the stack and
92  closures.}
93
94