source: trunk/source/doc/src/14-modifying.xml @ 8567

Last change on this file since 8567 was 8567, checked in by rme, 13 years ago

Break up monolithic openmcl-documentation.xml file into chapters. Add file
top.xml, which includes all the chapters via xi:xinclude.

File size: 20.9 KB
1<?xml version="1.0" encoding="utf-8"?>
2<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "" [
3<!ENTITY rest "<varname>&amp;rest</varname>">
4<!ENTITY key "<varname>&amp;key</varname>">
5<!ENTITY optional "<varname>&amp;optional</varname>">
6<!ENTITY body "<varname>&amp;body</varname>">
7<!ENTITY aux "<varname>&amp;aux</varname>">
8<!ENTITY allow-other-keys "<varname>&amp;allow-other-keys</varname>">
11  <chapter id="Modifying-OpenMCL">
12    <title>Modifying OpenMCL</title>
14    <sect1 id="Contributing-Code-Back-to-the-OpenMCL-Project">
15      <title>Contributing Code Back to the OpenMCL Project</title>
16      <para>This section is a placeholder, added as of August 2004.  The
17      full text is being written, and will be added as soon as it is
18      available.</para>
19    </sect1>
21    <sect1 id="Using-OpenMCL-in--development--and-in--user--mode">
22      <title>Using OpenMCL in "development" and in  "user" mode</title>
24      <para>As it's distributed, OpenMCL starts up with *PACKAGE* set
25      to the CL-USER package and with most predefined functions and
26      methods protected against accidental redefinition.  The package
27      setting is of course a requirement of ANSI CL, while the
28      protection protection is intended to catch certain types of
29      programming errors (accidentally redefining a CL or CCL
30      function) before those errors have a chance to do much
31      damage.</para>
32      <para>These settings may make using OpenMCL to develop OpenMCL a
33      bit more awkward, since much of that process assumes that the
34      CCL package is current (and a primary purpose of that process is
35      to redefine some "predefined, builtin functions".) The standard,
36      "routine" ways of building OpenMCL from sources (see ) -
38      the "CCL" package and enable the redefinition of predefined
39      functions; the symbols COMPILE-CCL, XCOMPILE-CCL, and
40      XLOAD-LEVEL-0 are additionally now exported from the "CCL"
41      package.</para>
42      <para>Some other (more ad-hoc) ways of doing development on
43      OpenMCL - compiling and/or loading individual files,
44      incrementally redefining individual functions - may be awkward
45      unless one reverts to the mode of operation which was
46      traditionally offered in OpenMCL. (Some OpenMCL source files -
47      especially those that comprise the bootstrapping image sources
48      and the first few files in the "cold load" sequence - are
49      compiled and loaded in the "CCL" package but don't contain
50      (IN-PACKAGE "CCL") forms, since IN-PACKAGE doesn't work until
51      later in the cold load sequence.)</para>
52      <para>The somewhat bizarre behavior of both SET-USER-ENVIRONMENT
53      and SET-DEVELOPMENT-ENVIRONMENT with respect to the special
54      variables they affect is intended to allow those constructs to
55      take effect when the read-eval-print loop next returns to a
56      top-level '? ' prompt; the constructs can meaningfully be used
57      inside LOAD, for instance (recall that LOAD binds *PACKAGE*),
58      though using both constructs within the same LOAD call would
59      likely be pretty confusing.</para>
60      <para>"user" and "development" are otherwise very generic terms;
61      here they're intended to enforce the distinction between "using"
62      OpenMCL and "developing" it.</para>
63      <para>The initial environment from which OpenMCL images are
64      saved is one where (SET-USER-ENVIRONMENT T) has just been
65      called; in previous versions, it was effectively as if
66      (SET-DEVELOPMENT-ENVIRONMENT T) had just been called.</para>
67      <para>Hopefully, most users of OpenMCL can safely ignore these
68      issues most of the time. Note that doing (SET-USER-ENVIRONMENT
69      T) after loading one's own code (or 3rd-party code) into OpenMCL
70      would protect that code (as well as OpenMCL's) from accidental
71      redefinition; that may be useful in some cases.</para>
72    </sect1>
74    <sect1 id="Debugging-facilities-in-the-lisp-kernel">
75      <title>Debugging facilities in the lisp kernel</title>
76      <para> In a perfect world, something like this couldn't
77      happen:</para>
78      <programlisting>
79Welcome to OpenMCL Version x.y!
80? (defun foo (x)
81    (declare (cons x))
82    (cdr x))
85? (foo -1) ;Oops. Too late ...
86Unhandled exception 11 at 0x300e90c8, context->regs at #x7ffff6b8
87Continue/Debugger/eXit &lt;enter&gt;?
89      <para>As you may have noticed, it's not a perfect world; it's rare
90that the cause (attempting to reference the CDR of -1, and therefore
91accessing unmapped memory near location 0) of this effect (an
92"Unhandled exception ..." message) is so obvious.</para>
93      <para>The addresses printed in the message above aren't very useful
94unless you're debugging the kernel with GDB (and they're often
95very useful if you are.)</para>
96      <para>Aside from causing an exception that the lisp kernel doesn't
97know how to handle, one can also enter the kernel debugger (more)
99      <programlisting>
100? (defun classify (n)
101     (cond ((&gt; n 0) "Greater")
102           ((&lt; n 0) "Less")
103           (t
104            ;;; Sheesh ! What else could it be ?
105            (ccl::bug "I give up. How could this happen ?"))))
108? (classify 0)
109Bug in OpenMCL system code:
110I give up. How could this happen ?
111? for help
112[12345] OpenMCL kernel debugger:
113      </programlisting>
114      <para>CCL::BUG isn't quite the right tool for this example (a
115      call to BREAK or PRINT might do a better job of clearing up the
116      mystery), but it's sometimes helpful when those other tools
117      can't be used.  The lisp error system notices, for instance, if
118      attempts to signal errors themselves cause errors to be
119      signaled; this sort of thing can happen if CLOS or the I/O
120      system are broken or missing. After some small number of
121      recursive errors, the error system gives up and calls
122      CCL::BUG.</para>
123      <para>If one enters a '?' at the kernel debugger prompt, one
124      will see output like:</para>
125      <programlisting>
126(S)  Find and describe symbol matching specified name
127(B)  Show backtrace
128(X)  Exit from this debugger, asserting that any exception was handled
129(K)  Kill OpenMCL process
130(?)  Show this help
132      <para>CCL::BUG just does an FF-CALL into the lisp kernel.  If
133      the kernel debugger was invoked because of an unhandled
134      exception (such as an illegal memory reference) the OS kernel
135      saves the machine state ("context") in a data structure for us,
136      and in that case some additional options can be used to display
137      the contents of the registers at the point of the
138      exception. Another function - CCL::DBG - causes a special
139      exception to be generated and enters the lisp kernel debugger
140      with a non-null "context":</para>
141      <programlisting>
142? (defun classify2 (n)
143  (cond ((&gt; n 0) "Greater")
144        ((&lt; n 0) "Less")
145        (t (dbg n))))
148? (classify2 0)
149Lisp Breakpoint
150 While executing: #&lt;Function CLASSIFY2 #x08476cfe>
151? for help
152[12345] OpenMCL kernel debugger: ?
153(G)  Set specified GPR to new value
154(A)  Advance the program counter by one instruction (use with caution!)
155(D)  Describe the current exception in greater detail
156(R)  Show raw GPR/SPR register values
157(L)  Show Lisp values of tagged registers
158(F)  Show FPU registers
159(S)  Find and describe symbol matching specified name
160(B)  Show backtrace
161(X)  Exit from this debugger, asserting that any exception was handled
162(P)  Propagate the exception to another handler (debugger or OS)
163(K)  Kill OpenMCL process
164(?)  Show this help
166      <para>CCL::DBG takes an argument, whose value is copied into the register
167that OpenMCL uses to return a function's primary value (arg_z, which
168is r23 on the PowerPC). If we were to choose the (L) option at this point,
169we'd see a dislay like:</para>
170      <programlisting>rnil = 0x01836015
171nargs = 0
172r16 (fn) = #&lt;Function CLASSIFY2 #x30379386>
173r23 (arg_z) = 0
174r22 (arg_y) = 0
175r21 (arg_x) = 0
176r20 (temp0) = #&lt;26-element vector subtag = 2F @#x303793ee>
177r19 (temp1/next_method_context) = 6393788
178r18 (temp2/nfn) = #&lt;Function CLASSIFY2 #x30379386>
179r17 (temp3/fname) = CLASSIFY2
180r31 (save0) = 0
181r30 (save1) = *TERMINAL-IO*
182r29 (save2) = 0
183r28 (save3) = (#&lt;RESTART @#x01867f2e> #&lt;RESTART @#x01867f56>)
184r27 (save4) = ()
185r26 (save5) = ()
186r25 (save6) = ()
187r24 (save7) = ()
189      <para>From this we can conclude that the problematic argument to CLASSIFY2
190was 0 (see r23/arg_z), and that I need to work on a better example.</para>
191      <para>The R option shows the values of the ALU (and PPC branch unit)
192registers in hex; the F option shows the values of the FPU registers.</para>
193      <para>The (B) option shows a raw stack backtrace; it'll try to
194identify foreign functions as well as lisp functions. (Foreign function
195names are guesses based on the nearest preceding exported symbol.)</para>
196      <para>If you ever unexpectedly find yourself in the "lisp kernel
197debugger", the output of the (L) and (B) options are often the most
198helpful things to include in a bug report.</para>
199    </sect1>
201    <sect1 id="Using-AltiVec-in-OpenMCL-LAP-functions">
202      <title>Using AltiVec in OpenMCL LAP functions</title>
204      <sect2 id="Overview--16-">
205        <title>Overview</title>
206        <para>It's now possible to use AltiVec instructions in PPC LAP
207        (assembler) functions.</para>
208        <para>The lisp kernel detects the presence or absence of
209        AltiVec and preserves AltiVec state on lisp thread switch and
210        in response to exceptions, but the implementation doesn't
211        otherwise use vector operations.</para>
212        <para>This document doesn't document PPC LAP programming in
213        general.  Ideally, there would be some document that
214        did.</para>
215        <para>This document does explain AltiVec register-usage
216        conventions in OpenMCL and explains the use of some lap macros
217        that help to enforce those conventions.</para>
218        <para>All of the global symbols described below are exported
219        from the CCL package. Note that lap macro names, ppc
220        instruction names, and (in most cases) register names are
221        treated as strings, so this only applies to functions and
222        global variable names.</para>
223        <para>Much of the OpenMCL support for AltiVec LAP programming
224        is based on work contributed to MCL by Shannon Spires.</para>
225      </sect2>
227      <sect2 id="Register-usage-conventions">
228        <title>Register usage conventions</title>
229        <para>OpenMCL LAP functions that use AltiVec instructions must
230        interoperate with each other and with C functions; that
231        suggests that they follow C AltiVec register usage
232        conventions. (vr0-vr1 scratch, vr2-vr13 parameters/return
233        value, vr14-vr19 temporaries, vr20-vr31 callee-save
234        non-volatile registers.)</para>
235        <para>The EABI (Embedded Application Binary Interface) used in
236        LinuxPPC doesn't ascribe particular significance to the vrsave
237        special-purpose register; on other platforms (notably MacOS),
238        it's used as a bitmap which indicates to system-level code
239        which vector registers contain meaningful values.</para>
240        <para>The WITH-ALTIVEC-REGISTERS lapmacro generates code which
241        which saves, updates, and restores VRSAVE on platforms where
242        this is required (as indicated by the value of the special
243        variable which controls this) and ignores VRSAVE on platforms
244        that don't require it to be maintained.</para>
245        <para>On all PPC platforms, it's necessary to save any non-volatile
246vector registers (vr20 .. vr31) before assigning to them and to restore
247such registers before returning to the caller.</para>
248        <para>On platforms that require that VRSAVE be maintained, it's not
249necessary to mention the "use" of vector registers that're
250used as incoming parameters. It's not incorrect to mention their use
251in a WITH-ALTIVEC-REGISTERS form, but it may be unneccessary in many
252interesting cases. One can likewise assume that the caller of any function
253that returns a vector value (in vr2 has already set the apropriate bit in
254VRSAVE to indicate that this register is live. One could therefore write a
255leaf function that added the bytes in vr3 and vr2 and returned the result
256in vr2 as:</para>
257        <programlisting>
258(defppclapfunction vaddubs ((y vr3) (z vr2))
259  (vaddubs z y z)
260  (blr))
262        <para>When vector registers that aren't incoming parameters are used
263in a LAP function, WITH-ALTIVEC-REGISTERS takes care of maintaining VRSAVE
264and of saving/restoring any non-volatile vector registers:</para>
265        <programlisting>
266(defppclapfunction load-array ((n arg_z))
267  (check-nargs 1)
268  (with-altivec-registers (vr1 vr2 vr3 vr27) ; Clobbers imm0
269    (li imm0 arch::misc-data-offset)
270    (lvx vr1 arg_z imm0) ; load MSQ
271    (lvsl vr27 arg_z imm0) ; set the permute vector
272    (addi imm0 imm0 16) ; address of LSQ
273    (lvx vr2 arg_z imm0) ; load LSQ
274    (vperm vr3 vr1 vr2 vr27) ; aligned result appears in VR3
275    (dbg t)) ; Look at result in some debugger
276  (blr))
278        <para>AltiVec registers are not preserved by CATCH and UNWIND-PROTECT.
279Since AltiVec is only accessible from LAP in OpenMCL and since LAP
280functions rarely use high- level control structures, this should rarely be
281a problem in practice.</para>
282        <para>LAP functions which use non-volatile vector registers and which call
283(Lisp ?) code which may use CATCH or UNWIND-PROTECT should save those
284vector registers before such a call and restore them on return. This is
285one of the intended uses of the WITH-VECTOR-BUFFER lap macro.</para>
286      </sect2>
287    </sect1>
289    <sect1 id="Development-Mode-Dictionary">
290      <title>Development-Mode Dictionary</title>
292      <refentry id="v_warn-if-redefine-kernel">
293        <indexterm zone="v_warn-if-redefine-kernel">
294          <primary>*warn-if-redefine-kernel</primary>
295        </indexterm>
297        <refnamediv>
298          <refname>*WARN-IF-REDEFINE-KERNEL*</refname>
299          <refpurpose></refpurpose>
300          <refclass>Variable</refclass>
301        </refnamediv>
303        <refsect1>
304          <title>Description</title>
306          <para>When true, attempts to redefine (via DEFUN or DEFMETHOD)
307          functions and methods that are marked as being
308          &#34;predefined&#34; signal continuable errors.</para>
310          <para>Note that these are CERRORs, not warnings, and that
311          no lisp functions or methods have been defined in the kernel
312          in MCL or OpenMCL since 1987 or so.</para>
313        </refsect1>
314      </refentry>
316      <refentry id="f_set-development-environment">
317        <indexterm zone="f_set-development-environment">
318          <primary>set-development-environment</primary>
319        </indexterm>
321        <refnamediv>
322          <refname>SET-DEVELOPMENT-ENVIRONMENT</refname>
323          <refpurpose></refpurpose>
324          <refclass>Function</refclass>
325        </refnamediv>
327        <refsynopsisdiv>
328          <synopsis><function>set-development-environment</function>
329          &optional;
330          unmark-builtin-functions</synopsis>
331        </refsynopsisdiv>
333        <refsect1>
334          <title>Description</title>
336          <para>Arranges that the outermost special bindings of *PACKAGE*
337          and *WARN-IF-REDEFINE-KERNEL* restore values of the &#34;CCL&#34;
338          package and NIL to these variables, respectively. If the optional
339          argument is true, marks all globally defined functions and methods
340          as being &#34;not predefined&#34; (this is a fairly expensive
341          operation.)</para>
342        </refsect1>
343      </refentry>
345      <refentry id="f_set-user-environment">
346        <indexterm zone="f_set-user-environment">
347          <primary>set-user-environment</primary>
348        </indexterm>
350        <refnamediv>
351          <refname>SET-USER-ENVIRONMENT</refname>
352          <refpurpose></refpurpose>
353          <refclass>Function</refclass>
354        </refnamediv>
356        <refsynopsisdiv>
357          <synopsis><function>set-user-environment</function>
358          &optional; mark-builtin-functions</synopsis>
359        </refsynopsisdiv>
361        <refsect1>
362          <title>Description</title>
364          <para>Arranges that the outermost special bindings of *PACKAGE*
365          and *WARN-IF-REDEFINE-KERNEL* restore values of the
366          &#34;CL-USER&#34; package and T to these variables, respectively.
367          If the optional argument is true, marks all globally defined
368          functions and methods as being &#34;predefined&#34; (this is a
369          fairly expensive operation.)</para>
370        </refsect1>
371      </refentry>
372      <refentry id="v_altivec-available">
373        <indexterm zone="v_altivec-available">
374          <primary>*altivec-available*</primary>
375        </indexterm>
377        <refnamediv>
378          <refname>*ALTIVEC-AVAILABLE*</refname>
379          <refpurpose></refpurpose>
380          <refclass>Variable</refclass>
381        </refnamediv>
383        <refsect1>
384          <title>Description</title>
385          <para>This variable is intitialized each time an OpenMCL session
386          starts based on information provided by the lisp kernel. Its value
387          is true if AltiVec is present and false otherwise. This variable
388          shouldn't be set by user code.</para>
389        </refsect1>
390      </refentry>
392      <refentry id="f_altivec-available-p">
393        <indexterm zone="f_altivec-available-p">
394          <primary>altivec-available-p</primary>
395        </indexterm>
397        <refnamediv>
398          <refname>ALTIVEC-AVAILABLE-P</refname>
399          <refpurpose></refpurpose>
400          <refclass>Function</refclass>
401        </refnamediv>
403        <refsynopsisdiv>
404          <synopsis><function>altivec-available-p</function></synopsis>
405        </refsynopsisdiv>
407        <refsect1>
408          <title>Description</title>
410          <para>Returns non-NIL if AltiVec is available.</para>
411        </refsect1>
412      </refentry>
414      <refentry id="v_altivec-lapmacros-maintain-vrsave-p">
415        <indexterm zone="v_altivec-lapmacros-maintain-vrsave-p">
416          <primary>*altivec-lapmacros-maintain-vrsave-p*</primary>
417        </indexterm>
419        <refnamediv>
420          <refname>*ALTIVEC-LAPMACROS-MAINTAIN-VRSAVE-P*</refname>
421          <refpurpose></refpurpose>
422          <refclass>Variable</refclass>
423        </refnamediv>
425        <refsect1>
426          <title>Description</title>
428          <para>Intended to control the expansion of certain lap macros.
429          Initialized to NIL on LinuxPPC; initialized to T on platforms
430          (such as MacOS X/Darwin) that require that the VRSAVE SPR contain
431          a bitmask of active vector registers at all times.</para>
432        </refsect1>
433      </refentry>
435      <refentry id="lapm_with-altivec-registers">
436        <indexterm zone="lapm_with-altivec-registers">
437          <primary>with-altivec-registers</primary>
438        </indexterm>
440        <refnamediv>
441          <refname>WITH-ALTIVEC-REGISTERS</refname>
442          <refpurpose></refpurpose>
443          <refclass>LAP Macro</refclass>
444        </refnamediv>
446        <refsynopsisdiv>
447          <synopsis><function>with-altivec-registers</function>
448          reglist &body; body</synopsis>
449        </refsynopsisdiv>
451        <refsect1>
452          <title>Arguments and Values</title>
454          <variablelist>
455            <varlistentry>
456              <term>reglist</term>
458              <listitem>
459                <para>A list of vector register names (vr0 .. vr31).</para>
460              </listitem>
461            </varlistentry>
463            <varlistentry>
464              <term>body</term>
466              <listitem>
467                <para>A sequence of PPC LAP instructions.</para>
468              </listitem>
469            </varlistentry>
470          </variablelist>
471        </refsect1>
473        <refsect1>
474          <title>Description</title>
476          <para>Specifies the set of AltiVec registers used in body. If
477          *altivec-lapmacros-maintain-vrsave-p* is true when the macro is
478          expanded, generates code to save the VRSAVE SPR and updates VRSAVE
479          to incude a bitmask generated from the specified register list.
480          Generates code which saves any non-volatile vector registers which
481          appear in the register list, executes body, and restores the saved
482          non-volatile vector registers (and, if
483          *altivec-lapmacros-maintain-vrsave-p* is true, restores VRSAVE as
484          well. Uses the IMM0 register (r3) as a temporary.</para>
485        </refsect1>
486      </refentry>
488      <refentry id="lapm_with-vector-buffer">
489        <indexterm zone="lapm_with-vector-buffer">
490          <primary>with-vector-buffer</primary>
491        </indexterm>
493        <refnamediv>
494          <refname>WITH-VECTOR-BUFFER</refname>
495          <refpurpose></refpurpose>
496          <refclass>LAP Macro</refclass>
497        </refnamediv>
499        <refsynopsisdiv>
500          <synopsis>with-vector-buffer base n &body; body</synopsis>
501        </refsynopsisdiv>
503        <refsect1>
504          <title>Arguments and Values</title>
506          <variablelist>
507            <varlistentry>
508              <term>base</term>
510              <listitem>
511                <para>Any available general-purpose register.</para>
512              </listitem>
513            </varlistentry>
515            <varlistentry>
516              <term>n</term>
518              <listitem>
519                <para>An integer between 1 and 254, inclusive. (Should
520                typically be much, much closer to 1.) Specifies the size of
521                the buffer, in 16-byte units.</para>
522              </listitem>
523            </varlistentry>
525            <varlistentry>
526              <term>body</term>
528              <listitem>
529                <para>A sequence of PPC LAP instructions.</para>
530              </listitem>
531            </varlistentry>
532          </variablelist>
533        </refsect1>
535        <refsect1>
536          <title>Description</title>
537          <para>Generates code which allocates a 16-byte aligned buffer
538          large enough to contain N vector registers; the GPR base points to
539          the lowest address of this buffer. After processing body, the
540          buffer will be deallocated. The body should preserve the value of
541          base as long as it needs to reference the buffer. It's
542          intended that base be used as a base register in stvx and lvx
543          instructions within the body.</para>
544        </refsect1>
545      </refentry>
546    </sect1>
547  </chapter>
Note: See TracBrowser for help on using the repository browser.