diff --git a/doc/Makefile.am b/doc/Makefile.am index 712ece34a..0a6b14ed5 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with Automake to create Makefile.in ## -## Copyright (C) 1998, 2002, 2006, 2008 Free Software Foundation, Inc. +## Copyright (C) 1998, 2002, 2006, 2008, 2009 Free Software Foundation, Inc. ## ## This file is part of GUILE. ## @@ -43,5 +43,3 @@ include $(top_srcdir)/am/maintainer-dirs guile-api.alist: guile-api.alist-FORCE ( cd $(top_builddir) ; $(mscripts)/update-guile-api.alist ) guile-api.alist-FORCE: - -info_TEXINFOS = guile-vm.texi diff --git a/doc/guile-vm.texi b/doc/guile-vm.texi deleted file mode 100644 index 927c09e88..000000000 --- a/doc/guile-vm.texi +++ /dev/null @@ -1,1042 +0,0 @@ -\input texinfo @c -*-texinfo-*- -@c %**start of header -@setfilename guile-vm.info -@settitle Guile VM Specification -@footnotestyle end -@setchapternewpage odd -@c %**end of header - -@set EDITION 0.6 -@set VERSION 0.6 -@set UPDATED 2005-04-26 - -@c Macro for instruction definitions. -@macro insn{} -Instruction -@end macro - -@c For Scheme procedure definitions. -@macro scmproc{} -Scheme Procedure -@end macro - -@c Scheme records. -@macro scmrec{} -Record -@end macro - -@ifinfo -@dircategory Scheme Programming -@direntry -* Guile VM: (guile-vm). Guile's Virtual Machine. -@end direntry - -This file documents Guile VM. - -Copyright @copyright{} 2000 Keisuke Nishida -Copyright @copyright{} 2005 Ludovic Court`es - -Permission is granted to make and distribute verbatim copies of this -manual provided the copyright notice and this permission notice are -preserved on all copies. - -@ignore -Permission is granted to process this file through TeX and print the -results, provided the printed document carries a copying permission -notice identical to this one except for the removal of this paragraph -(this paragraph not being relevant to the printed manual). - -@end ignore -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided that the -entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - -Permission is granted to copy and distribute translations of this manual -into another language, under the above conditions for modified versions, -except that this permission notice may be stated in a translation -approved by the Free Software Foundation. -@end ifinfo - -@titlepage -@title Guile VM Specification -@subtitle for Guile VM @value{VERSION} -@author Keisuke Nishida - -@page -@vskip 0pt plus 1filll -Edition @value{EDITION} @* -Updated for Guile VM @value{VERSION} @* -@value{UPDATED} @* - -Copyright @copyright{} 2000 Keisuke Nishida -Copyright @copyright{} 2005 Ludovic Court`es - -Permission is granted to make and distribute verbatim copies of this -manual provided the copyright notice and this permission notice are -preserved on all copies. - -Permission is granted to copy and distribute modified versions of this -manual under the conditions for verbatim copying, provided that the -entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - -Permission is granted to copy and distribute translations of this manual -into another language, under the above conditions for modified versions, -except that this permission notice may be stated in a translation -approved by the Free Software Foundation. -@end titlepage - -@contents - -@c ********************************************************************* -@node Top, Introduction, (dir), (dir) -@top Guile VM Specification - -This document would like to correspond to Guile VM @value{VERSION}. -However, be warned that important parts still correspond to version -0.0 and are not valid anymore. - -@menu -* Introduction:: -* Variable Management:: -* Instruction Set:: -* The Compiler:: -* Concept Index:: -* Function and Instruction Index:: -* Command and Variable Index:: - -@detailmenu - --- The Detailed Node Listing --- - -Instruction Set - -* Environment Control Instructions:: -* Branch Instructions:: -* Subprogram Control Instructions:: -* Data Control Instructions:: - -The Compiler - -* Overview:: -* The Language Front-Ends:: -* GHIL:: -* Compiling Scheme Code:: -* GLIL:: -* The Assembler:: - -@end detailmenu -@end menu - -@c ********************************************************************* -@node Introduction, Variable Management, Top, Top -@chapter What is Guile VM? - -A Guile VM has a set of registers and its own stack memory. Guile may -have more than one VM's. Each VM may execute at most one program at a -time. Guile VM is a CISC system so designed as to execute Scheme and -other languages efficiently. - -@unnumberedsubsec Registers - -@itemize -@item pc - Program counter ;; ip (instruction poiner) is better? -@item sp - Stack pointer -@item bp - Base pointer -@item ac - Accumulator -@end itemize - -@unnumberedsubsec Engine - -A VM may have one of three engines: reckless, regular, or debugging. -Reckless engine is fastest but dangerous. Regular engine is normally -fail-safe and reasonably fast. Debugging engine is safest and -functional but very slow. - -@unnumberedsubsec Memory - -Stack is the only memory that each VM owns. The other memory is shared -memory that is shared among every VM and other part of Guile. - -@unnumberedsubsec Program - -A VM program consists of a bytecode that is executed and an environment -in which execution is done. Each program is allocated in the shared -memory and may be executed by any VM. A program may call other programs -within a VM. - -@unnumberedsubsec Instruction - -Guile VM has dozens of system instructions and (possibly) hundreds of -functional instructions. Some Scheme procedures such as cons and car -are implemented as VM's builtin functions, which are very efficient. -Other procedures defined outside of the VM are also considered as VM's -functional features, since they do not change the state of VM. -Procedures defined within the VM are called subprograms. - -Most instructions deal with the accumulator (ac). The VM stores all -results from functions in ac, instead of pushing them into the stack. -I'm not sure whether this is a good thing or not. - -@node Variable Management, Instruction Set, Introduction, Top -@chapter Variable Management - -FIXME: This chapter needs to be reviewed so that it matches reality. -A more up-to-date description of the mechanisms described in this -section is given in @ref{Instruction Set}. - -A program may have access to local variables, external variables, and -top-level variables. - -@section Local/external variables - -A stack is logically divided into several blocks during execution. A -"block" is such a unit that maintains local variables and dynamic chain. -A "frame" is an upper level unit that maintains subprogram calls. - -@example - Stack - dynamic | | | | - chain +==========+ - = - | |local vars| | | - `-|block data| | block | - /|frame data| | | - | +----------+ - | - | |local vars| | | frame - `-|block data| | | - /+----------+ - | - | |local vars| | | - `-|block data| | | - /+==========+ - = - | |local vars| | | - `-|block data| | | - /|frame data| | | - | +----------+ - | - | | | | | -@end example - -The first block of each frame may look like this: - -@example - Address Data - ------- ---- - xxx0028 Local variable 2 - xxx0024 Local variable 1 - bp ->xxx0020 Local variable 0 - xxx001c Local link (block data) - xxx0018 External link (block data) - xxx0014 Stack pointer (block data) - xxx0010 Return address (frame data) - xxx000c Parent program (frame data) -@end example - -The base pointer (bp) always points to the lowest address of local -variables of the recent block. Local variables are referred as "bp[n]". -The local link field has a pointer to the dynamic parent of the block. -The parent's variables are referred as "bp[-1][n]", and grandparent's -are "bp[-1][-1][n]". Thus, any local variable is represented by its -depth and offset from the current bp. - -A variable may be "external", which is allocated in the shared memory. -The external link field of a block has a pointer to such a variable set, -which I call "fragment" (what should I call?). A fragment has a set of -variables and its own chain. - -@example - local external - chain| | chain - | +-----+ .--------, | - `-|block|--+->|external|-' - /+-----+ | `--------'\, - `-|block|--' | - /+-----+ .--------, | - `-|block|---->|external|-' - +-----+ `--------' - | | -@end example - -An external variable is referred as "bp[-2]->variables[n]" or -"bp[-2]->link->...->variables[n]". This is also represented by a pair -of depth and offset. At any point of execution, the value of bp -determines the current local link and external link, and thus the -current environment of a program. - -Other data fields are described later. - -@section Top-level variables - -Guile VM uses the same top-level variables as the regular Guile. A -program may have direct access to vcells. Currently this is done by -calling scm_intern0, but a program is possible to have any top-level -environment defined by the current module. - -@section Scheme and VM variable - -Let's think about the following Scheme code as an example: - -@example - (define (foo a) - (lambda (b) (list foo a b))) -@end example - -In the lambda expression, "foo" is a top-level variable, "a" is an -external variable, and "b" is a local variable. - -When a VM executes foo, it allocates a block for "a". Since "a" may be -externally referred from the closure, the VM creates a fragment with a -copy of "a" in it. When the VM evaluates the lambda expression, it -creates a subprogram (closure), associating the fragment with the -subprogram as its external environment. When the closure is executed, -its environment will look like this: - -@example - block Top-level: foo - +-------------+ - |local var: b | fragment - +-------------+ .-----------, - |external link|---->|variable: a| - +-------------+ `-----------' -@end example - -The fragment remains as long as the closure exists. - -@section Addressing mode - -Guile VM has five addressing modes: - -@itemize -@item Real address -@item Local position -@item External position -@item Top-level location -@item Constant object -@end itemize - -Real address points to the address in the real program and is only used -with the program counter (pc). - -Local position and external position are represented as a pair of depth -and offset from bp, as described above. These are base relative -addresses, and the real address may vary during execution. - -Top-level location is represented as a Guile's vcell. This location is -determined at loading time, so the use of this address is efficient. - -Constant object is not an address but gives an instruction an Scheme -object directly. - -[ We'll also need dynamic scope addressing to support Emacs Lisp? ] - - -Overall procedure: - -@enumerate -@item A source program is compiled into a bytecode. -@item A bytecode is given an environment and becomes a program. -@item A VM starts execution, creating a frame for it. -@item Whenever a program calls a subprogram, a new frame is created for it. -@item When a program finishes execution, it returns a value, and the VM - continues execution of the parent program. -@item When all programs terminated, the VM returns the final value and stops. -@end enumerate - - -@node Instruction Set, The Compiler, Variable Management, Top -@chapter Instruction Set - -The Guile VM instruction set is roughly divided two groups: system -instructions and functional instructions. System instructions control -the execution of programs, while functional instructions provide many -useful calculations. - -@menu -* Environment Control Instructions:: -* Branch Instructions:: -* Subprogram Control Instructions:: -* Data Control Instructions:: -@end menu - -@node Environment Control Instructions, Branch Instructions, Instruction Set, Instruction Set -@section Environment Control Instructions - -@deffn @insn{} link binding-name -Look up @var{binding-name} (a string) in the current environment and -push the corresponding variable object onto the stack. If -@var{binding-name} is not bound yet, then create a new binding and -push its variable object. -@end deffn - -@deffn @insn{} variable-ref -Dereference the variable object which is on top of the stack and -replace it by the value of the variable it represents. -@end deffn - -@deffn @insn{} variable-set -Set the value of the variable on top of the stack (at @code{sp[0]}) to -the object located immediately before (at @code{sp[-1]}). -@end deffn - -As an example, let us look at what a simple function call looks like: - -@example -(+ 2 3) -@end example - -This call yields the following sequence of instructions: - -@example -(link "+") ;; lookup binding "+" -(variable-ref) ;; dereference it -(make-int8 2) ;; push immediate value `2' -(make-int8 3) ;; push immediate value `3' -(tail-call 2) ;; call the proc at sp[-3] with two args -@end example - -@deffn @insn{} local-ref offset -Push onto the stack the value of the local variable located at -@var{offset} within the current stack frame. -@end deffn - -@deffn @insn{} local-set offset -Pop the Scheme object located on top of the stack and make it the new -value of the local variable located at @var{offset} within the current -stack frame. -@end deffn - -@deffn @insn{} external-ref offset -Push the value of the closure variable located at position -@var{offset} within the program's list of external variables. -@end deffn - -@deffn @insn{} external-set offset -Pop the Scheme object located on top of the stack and make it the new -value of the closure variable located at @var{offset} within the -program's list of external variables. -@end deffn - -@deffn @insn{} make-closure -Pop the program object from the stack and assign it the current -closure variable list as its closure. Push the result program -object. -@end deffn - -Let's illustrate this: - -@example -(let ((x 2)) - (lambda () - (let ((x++ (+ 1 x))) - (set! x x++) - x++))) -@end example - -The resulting program has one external (closure) variable, i.e. its -@var{nexts} is set to 1 (@pxref{Subprogram Control Instructions}). -This yields the following code: - -@example - ;; the traditional program prologue with NLOCS = 0 and NEXTS = 1 - - 0 (make-int8 2) - 2 (external-set 0) - 4 (make-int8 4) - 6 (link "+") ;; lookup `+' - 9 (vector 1) ;; create the external variable vector for - ;; later use by `object-ref' and `object-set' - ... - 40 (load-program ##34#) - 59 (make-closure) ;; assign the current closure to the program - ;; just pushed by `load-program' - 60 (return) -@end example - -The program loaded here by @var{load-program} contains the following -sequence of instructions: - -@example - 0 (object-ref 0) ;; push the variable for `+' - 2 (variable-ref) ;; dereference `+' - 3 (make-int8:1) ;; push 1 - 4 (external-ref 0) ;; push the value of `x' - 6 (call 2) ;; call `+' and push the result - 8 (local-set 0) ;; make it the new value of `x++' - 10 (local-ref 0) ;; push the value of `x++' - 12 (external-set 0) ;; make it the new value of `x' - 14 (local-ref 0) ;; push the value of `x++' - 16 (return) ;; return it -@end example - -At this point, you should know pretty much everything about the three -types of variables a program may need to access. - - -@node Branch Instructions, Subprogram Control Instructions, Environment Control Instructions, Instruction Set -@section Branch Instructions - -All the conditional branch instructions described below work in the -same way: - -@itemize -@item They take the Scheme object located on the stack and use it as -the branch condition; -@item If the condition if false, then program execution continues with -the next instruction; -@item If the condition is true, then the instruction pointer is -increased by the offset passed as an argument to the branch -instruction; -@item Finally, when the instruction finished, the condition object is -removed from the stack. -@end itemize - -Note that the offset passed to the instruction is encoded on two 8-bit -integers which are then combined by the VM as one 16-bit integer. - -@deffn @insn{} br offset -Jump to @var{offset}. -@end deffn - -@deffn @insn{} br-if offset -Jump to @var{offset} if the condition on the stack is not false. -@end deffn - -@deffn @insn{} br-if-not offset -Jump to @var{offset} if the condition on the stack is false. -@end deffn - -@deffn @insn{} br-if-eq offset -Jump to @var{offset} if the two objects located on the stack are -equal in the sense of @var{eq?}. Note that, for this instruction, the -stack pointer is decremented by two Scheme objects instead of only -one. -@end deffn - -@deffn @insn{} br-if-not-eq offset -Same as @var{br-if-eq} for non-equal objects. -@end deffn - -@deffn @insn{} br-if-null offset -Jump to @var{offset} if the object on the stack is @code{'()}. -@end deffn - -@deffn @insn{} br-if-not-null offset -Jump to @var{offset} if the object on the stack is not @code{'()}. -@end deffn - - -@node Subprogram Control Instructions, Data Control Instructions, Branch Instructions, Instruction Set -@section Subprogram Control Instructions - -Programs (read: ``compiled procedure'') may refer to external -bindings, like variables or functions defined outside the program -itself, in the environment in which it will evaluate at run-time. In -a sense, a program's environment and its bindings are an implicit -parameter of every program. - -@cindex object table -In order to handle such bindings, each program has an @dfn{object -table} associated to it. This table (actually a Scheme vector) -contains all constant objects referenced by the program. The object -table of a program is initialized right before a program is loaded -with @var{load-program}. - -Variable objects are one such type of constant object: when a global -binding is defined, a variable object is associated to it and that -object will remain constant over time, even if the value bound to it -changes. Therefore, external bindings only need to be looked up once -when the program is loaded. References to the corresponding external -variables from within the program are then performed via the -@var{object-ref} instruction and are almost as fast as local variable -references. - -Let us consider the following program (procedure) which references -external bindings @code{frob} and @var{%magic}: - -@example -(lambda (x) - (frob x %magic)) -@end example - -This yields the following assembly code: - -@example -(make-int8 64) ;; number of args, vars, etc. (see below) -(link "frob") -(link "%magic") -(vector 2) ;; object table (external bindings) -... -(load-program #u8(20 0 23 21 0 20 1 23 36 2)) -(return) -@end example - -All the instructions occurring before @var{load-program} (some were -omitted for simplicity) form a @dfn{prologue} which, among other -things, pushed an object table (a vector) that contains the variable -objects for the variables bound to @var{frob} and @var{%magic}. This -vector and other data pushed onto the stack are then popped by the -@var{load-program} instruction. - -Besides, the @var{load-program} instruction takes one explicit -argument which is the bytecode of the program itself. Disassembled, -this bytecode looks like: - -@example -(object-ref 0) ;; push the variable object of `frob' -(variable-ref) ;; dereference it -(local-ref 0) ;; push the value of `x' -(object-ref 1) ;; push the variable object of `%magic' -(variable-ref) ;; dereference it -(tail-call 2) ;; call `frob' with two parameters -@end example - -This clearly shows that there is little difference between references -to local variables and references to externally bound variables since -lookup of externally bound variables if performed only once before the -program is run. - -@deffn @insn{} load-program bytecode -Load the program whose bytecode is @var{bytecode} (a u8vector), pop -its meta-information from the stack, and push a corresponding program -object onto the stack. The program's meta-information may consist of -(in the order in which it should be pushed onto the stack): - -@itemize -@item optionally, a pair representing meta-data (see the -@var{program-meta} procedure); [FIXME: explain their meaning] -@item optionally, a vector which is the program's object table (a -program that does not reference external bindings does not need an -object table); -@item either one immediate integer or four immediate integers -representing respectively the number of arguments taken by the -function (@var{nargs}), the number of @dfn{rest arguments} -(@var{nrest}, 0 or 1), the number of local variables (@var{nlocs}) and -the number of external variables (@var{nexts}) (@pxref{Environment -Control Instructions}). -@end itemize - -@end deffn - -@deffn @insn{} object-ref offset -Push the variable object for the external variable located at -@var{offset} within the program's object table. -@end deffn - -@deffn @insn{} return -Free the program's frame. -@end deffn - -@deffn @insn{} call nargs -Call the procedure, continuation or program located at -@code{sp[-nargs]} with the @var{nargs} arguments located from -@code{sp[0]} to @code{sp[-nargs + 1]}. The -procedure/continuation/program and its arguments are dropped from the -stack and the result is pushed. When calling a program, the -@code{call} instruction reserves room for its local variables on the -stack, and initializes its list of closure variables and its vector of -externally bound variables. -@end deffn - -@deffn @insn{} tail-call nargs -Same as @code{call} except that, for tail-recursive calls to a -program, the current stack frame is re-used, as required by RnRS. -This instruction is otherwise similar to @code{call}. -@end deffn - - -@node Data Control Instructions, , Subprogram Control Instructions, Instruction Set -@section Data Control Instructions - -@deffn @insn{} make-int8 value -Push @var{value}, an 8-bit integer, onto the stack. -@end deffn - -@deffn @insn{} make-int8:0 -Push the immediate value @code{0} onto the stack. -@end deffn - -@deffn @insn{} make-int8:1 -Push the immediate value @code{1} onto the stack. -@end deffn - -@deffn @insn{} make-false -Push @code{#f} onto the stack. -@end deffn - -@deffn @insn{} make-true -Push @code{#t} onto the stack. -@end deffn - -@itemize -@item %push -@item %pushi -@item %pushl, %pushl:0:0, %pushl:0:1, %pushl:0:2, %pushl:0:3 -@item %pushe, %pushe:0:0, %pushe:0:1, %pushe:0:2, %pushe:0:3 -@item %pusht -@end itemize - -@itemize -@item %loadi -@item %loadl, %loadl:0:0, %loadl:0:1, %loadl:0:2, %loadl:0:3 -@item %loade, %loade:0:0, %loade:0:1, %loade:0:2, %loade:0:3 -@item %loadt -@end itemize - -@itemize -@item %savei -@item %savel, %savel:0:0, %savel:0:1, %savel:0:2, %savel:0:3 -@item %savee, %savee:0:0, %savee:0:1, %savee:0:2, %savee:0:3 -@item %savet -@end itemize - -@section Flow control instructions - -@itemize -@item %br-if -@item %br-if-not -@item %jump -@end itemize - -@section Function call instructions - -@itemize -@item %func, %func0, %func1, %func2 -@end itemize - -@section Scheme built-in functions - -@itemize -@item cons -@item car -@item cdr -@end itemize - -@section Mathematical buitin functions - -@itemize -@item 1+ -@item 1- -@item add, add2 -@item sub, sub2, minus -@item mul2 -@item div2 -@item lt2 -@item gt2 -@item le2 -@item ge2 -@item num-eq2 -@end itemize - - - -@node The Compiler, Concept Index, Instruction Set, Top -@chapter The Compiler - -This section describes Guile-VM's compiler and the compilation process -to produce bytecode executable by the VM itself (@pxref{Instruction -Set}). - -@menu -* Overview:: -* The Language Front-Ends:: -* GHIL:: -* Compiling Scheme Code:: -* GLIL:: -* The Assembler:: -@end menu - -@node Overview, The Language Front-Ends, The Compiler, The Compiler -@section Overview - -Compilation in Guile-VM is a three-stage process: - -@cindex intermediate language -@cindex assembler -@cindex compiler -@cindex GHIL -@cindex GLIL -@cindex bytecode - -@enumerate -@item the source programming language (e.g. R5RS Scheme) is read and -translated into GHIL, @dfn{Guile's High-Level Intermediate Language}; -@item GHIL code is then translated into a lower-level intermediate -language call GLIL, @dfn{Guile's Low-Level Intermediate Language}; -@item finally, GLIL is @dfn{assembled} into the VM's assembly language -(@pxref{Instruction Set}) and bytecode. -@end enumerate - -The use of two separate intermediate languages eases the -implementation of front-ends since the gap between high-level -languages like Scheme and GHIL is relatively small. - -@vindex guilec -From an end-user viewpoint, compiling a Guile program into bytecode -can be done either by using the @command{guilec} command-line tool, or -by using the @code{compile-file} procedure exported by the -@code{(system base compile)} module. - -@deffn @scmproc{} compile-file file . opts -Compile Scheme source code from file @var{file} using compilation -options @var{opts}. The resulting file, a Guile object file, will be -name according the application of the @code{compiled-file-name} -procedure to @var{file}. The possible values for @var{opts} are the -same as for the @code{compile-in} procedure (see below, @pxref{The Language -Front-Ends}). -@end deffn - -@deffn @scmproc{} compiled-file-name file -Given source file name @var{file} (a string), return a string that -denotes the name of the Guile object file corresponding to -@var{file}. By default, the file name returned is @var{file} minus -its extension and plus the @code{.go} file extension. -@end deffn - -@cindex self-hosting -It is worth noting, as you might have already guessed, that Guile-VM's -compiler is written in Guile Scheme and is @dfn{self-hosted}: it can -compile itself. - -@node The Language Front-Ends, GHIL, Overview, The Compiler -@section The Language Front-Ends - -Guile-VM comes with a number of @dfn{language front-ends}, that is, -code that can read a given high-level programming language like R5RS -Scheme, and translate it into a lower-level representation suitable to -the compiler. - -Each language front-end provides a @dfn{specification} and a -@dfn{translator} to GHIL. Both of them come in the @code{language} -module hierarchy. As an example, the front-end for Scheme is located -in the @code{(language scheme spec)} and @code{(language scheme -translate)} modules. Language front-ends can then be retrieved using -the @code{lookup-language} procedure of the @code{(system base -language)} module. - -@deftp @scmrec{} name title version reader printer read-file expander translator evaluator environment -Denotes a language front-end specification a various methods used by -the compiler to handle source written in that language. Of particular -interest is the @code{translator} slot (@pxref{GHIL}). -@end deftp - -@deffn @scmproc{} lookup-language lang -Look for a language front-end named @var{lang}, a symbol (e.g, -@code{scheme}), and return the @code{} record describing it -if found. If @var{lang} does not denote a language front-end, an -error is raised. Note that this procedure assumes that language -@var{lang} exists if there exist a @code{(language @var{lang} spec)} -module. -@end deffn - -The @code{(system base compile)} module defines a procedure similar to -@code{compile-file} but that is not limited to the Scheme language: - -@deffn @scmproc{} compile-in expr env lang . opts -Compile expression @var{expr}, which is written in language @var{lang} -(a @code{} object), using compilation options @var{opts}, -and return bytecode as produced by the assembler (@pxref{The -Assembler}). - -Options @var{opts} may contain the following keywords: - -@table @code -@item :e -compilation will stop after the code expansion phase. -@item :t -compilation will stop after the code translation phase, i.e. after -code in the source language @var{lang} has been translated into GHIL -(@pxref{GHIL}). -@item :c -compilation will stop after the compilation phase and before the -assembly phase, i.e. once GHIL has been translated into GLIL -(@pxref{GLIL}). -@end table - -Additionally, @var{opts} may contain any option understood by the -GHIL-to-GLIL compiler described in @xref{GLIL}. -@end deffn - - -@node GHIL, Compiling Scheme Code, The Language Front-Ends, The Compiler -@section Guile's High-Level Intermediate Language - -GHIL has constructs almost equivalent to those found in Scheme. -However, unlike Scheme, it is meant to be read only by the compiler -itself. Therefore, a sequence of GHIL code is only a sequence of GHIL -@emph{objects} (records), as opposed to symbols, each of which -represents a particular language feature. These records are all -defined in the @code{(system il ghil)} module and are named -@code{}. - -Each GHIL record has at least two fields: one containing the -environment (Guile module) in which it is considered, and one -containing its location [FIXME: currently seems to be unused]. Below -is a list of the main GHIL object types and their fields: - -@example -;; Objects -( env loc) -( env loc obj) -( env loc exp) -( env loc exp) -( env loc exp) -;; Variables -( env loc var) -( env loc var val) -( env loc var val) -;; Controls -( env loc test then else) -( env loc exps) -( env loc exps) -( env loc exps) -( env loc vars vals body) -( env loc vars rest body) -( env loc proc args) -( env loc inline args) -@end example - -As can be seen from this examples, the constructs in GHIL are pretty -close to the fundamental primitives of Scheme. - -It is the role of front-end language translators (@pxref{The Language -Front-Ends}) to produce a sequence of GHIL objects from the -human-readable, source programming language. The next section -describes the translator for the Scheme language. - -@node Compiling Scheme Code, GLIL, GHIL, The Compiler -@section Compiling Scheme Code - -The language object for Scheme, as returned by @code{(lookup-language -'scheme)} (@pxref{The Language Front-Ends}), defines a translator -procedure that returns a sequence of GHIL objects given Scheme code. -Before actually performing this operation, the Scheme translator -expands macros in the original source code. - -The macros that may be expanded can come from different sources: - -@itemize -@item core Guile macros, such as @code{false-if-exception}; -@item macros defined in modules used by the module being compiled, -e.g., @code{receive} in @code{(ice-9 receive)}; -@item macros defined within the module being compiled. -@end itemize - -@cindex macro -@cindex syntax transformer -@findex define-macro -@findex defmacro -The main complexity in handling macros at compilation time is that -Guile's macros are first-class objects. For instance, when using -@code{define-macro}, one actually defines a @emph{procedure} that -returns code; of course, unlike a ``regular'' procedure, it is -executed when an S-exp is @dfn{memoized} by the evaluator, i.e., -before the actual evaluation takes place. Worse, it is possible to -turn a procedure into a macro, or @dfn{syntax transformer}, thus -removing, to some extent, the boundary between the macro expansion and -evaluation phases, @inforef{Internal Macros, , guile}. - -[FIXME: explain limitations, etc.] - - -@node GLIL, The Assembler, Compiling Scheme Code, The Compiler -@section Guile's Low-Level Intermediate Language - -A GHIL instruction sequence can be compiled into GLIL using the -@code{compile} procedure exported by the @code{(system il compile)} -module. During this translation process, various optimizations may -also be performed. - -The module @code{(system il glil)} defines record types representing -various low-level abstractions. Compared to GHIL, the flow control -primitives in GLIL are much more low-level: only @code{}, -@code{} and @code{} are available, no -@code{lambda}, @code{if}, etc. - - -@deffn @scmproc{} compile ghil environment . opts -Compile @var{ghil}, a GHIL instruction sequence, within -environment/module @var{environment}, and return the resulting GLIL -instruction sequence. The option list @var{opts} may be either the -empty list or a list containing the @code{:O} keyword in which case -@code{compile} will first go through an optimization stage of -@var{ghil}. - -Note that the @code{:O} option may be passed at a higher-level to the -@code{compile-file} and @code{compile-in} procedures (@pxref{The -Language Front-Ends}). -@end deffn - -@deffn @scmproc{} pprint-glil glil . port -Print @var{glil}, a GLIL sequence instructions, in a human-readable -form. If @var{port} is passed, it will be used as the output port. -@end deffn - - -Let's consider the following Scheme expression: - -@example -(lambda (x) (+ x 1)) -@end example - -The corresponding (unoptimized) GLIL code, as shown by -@code{pprint-glil}, looks like this: - -@example -(@@asm (0 0 0 0) - (@@asm (1 0 0 0) ;; expect one arg. - (@@bind (x argument 0)) ;; debugging info - (module-ref #f +) ;; lookup `+' - (argument-ref 0) ;; push the argument onto - ;; the stack - (const 1) ;; push `1' - (tail-call 2) ;; call `+', with 2 args, - ;; using the same stack frame - (@@source 15 33)) ;; additional debugging info - (return 0)) -@end example - -This is not unlike the VM's assembly language described in -@ref{Instruction Set}. - -@node The Assembler, , GLIL, The Compiler -@section The Assembler - -@findex code->bytes - -The final compilation step consists in converting the GLIL instruction -sequence into VM bytecode. This is what the @code{assemble} procedure -defined in the @code{(system vm assemble)} module is for. It relies -on the @code{code->bytes} procedure of the @code{(system vm conv)} -module to convert instructions (represented as lists whose @code{car} -is a symbol naming the instruction, e.g. @code{object-ref}, -@pxref{Instruction Set}) into binary code, or @dfn{bytecode}. -Bytecode itself is represented using SRFI-4 byte vectors, -@inforef{SRFI-4, SRFI-4 homogeneous numeric vectors, guile}. - - -@deffn @scmproc{} assemble glil environment . opts -Return a binary representation of @var{glil} (bytecode), either in the -form of an SRFI-4 @code{u8vector} or a @code{} object. -[FIXME: Why is that?] -@end deffn - - - -@c ********************************************************************* -@node Concept Index, Function and Instruction Index, The Compiler, Top -@unnumbered Concept Index -@printindex cp - -@node Function and Instruction Index, Command and Variable Index, Concept Index, Top -@unnumbered Function and Instruction Index -@printindex fn - -@node Command and Variable Index, , Function and Instruction Index, Top -@unnumbered Command and Variable Index -@printindex vr - -@bye - -@c Local Variables: -@c ispell-local-dictionary: "american"; -@c End: - -@c LocalWords: bytecode