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