home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mitsch75.zip / scheme-7_5_17-src.zip / scheme-7.5.17 / src / microcode / cmpint.c < prev    next >
C/C++ Source or Header  |  2000-12-05  |  123KB  |  4,143 lines

  1. /* -*-C-*-
  2.  
  3. $Id: cmpint.c,v 1.92 2000/12/05 21:23:43 cph Exp $
  4.  
  5. Copyright (c) 1989-2000 Massachusetts Institute of Technology
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. /*
  23.  *
  24.  * Compiled code interface.  Portable version.
  25.  * This file requires a bit of assembly language from cmpaux-md.m4
  26.  * See also the files cmpint.txt, cmpgc.h, and cmpint-md.h .
  27.  *
  28.  */
  29.  
  30. /*
  31.  * Procedures in this file belong to the following categories:
  32.  *
  33.  * Local C procedures.  These are local procedures called only by
  34.  * other procedures in this file, and have been separated only for
  35.  * modularity reasons.  They are tagged with the C keyword `static'.
  36.  * They can return any C type.
  37.  *
  38.  * C utility procedures.  These procedures are called from C
  39.  * primitives and other subsystems and never leave the C world.  They
  40.  * constitute the compiled code data abstraction as far as other C
  41.  * parts of the Scheme "microcode" are concerned.  They are tagged
  42.  * with the noise word `C_UTILITY'.  They can return any C type.
  43.  *
  44.  * C interface entries.  These procedures are called from the
  45.  * interpreter (written in C) and ultimately enter the Scheme compiled
  46.  * code world by using the assembly language utility
  47.  * `C_to_interface'.  They are tagged with the noise word
  48.  * `C_TO_SCHEME'.  They MUST return a C long indicating what
  49.  * the interpreter should do next.
  50.  *
  51.  * Scheme interface utilities.  These procedures are called from the
  52.  * assembly language interface and return to it, and perform all the
  53.  * tasks that the compiler does not code inline.  They are referenced
  54.  * by compiled scheme code by index, and the assembly language
  55.  * interface fetches them from an array.  They are tagged with the
  56.  * noise word `SCHEME_UTILITY'.  They return a C structure (struct
  57.  * utility_result) which describes whether computation should proceed
  58.  * in the interpreter or in compiled code, and how.
  59.  *
  60.  */
  61.  
  62. /* Macro imports */
  63.  
  64. #include "config.h"
  65. #include <stdio.h>
  66. #ifdef STDC_HEADERS
  67. #  include <stdlib.h>
  68. #endif
  69. #include "dstack.h"    /* Dynamic-stack support */
  70. #include "outf.h"    /* error reporting */
  71. #include "types.h"      /* Needed by const.h */
  72. #include "const.h"      /* REGBLOCK_MINIMUM_LENGTH and PRIM_... codes */
  73. #include "object.h"     /* Making and destructuring Scheme objects */
  74. #include "intrpt.h"    /* Interrupt processing macros */
  75. #include "gc.h"        /* Request_GC, etc. */
  76. #include "sdata.h"    /* ENTITY_OPERATOR */
  77. #include "errors.h"     /* Error codes and Termination codes */
  78. #include "returns.h"    /* Return addresses in the interpreter */
  79. #include "fixobj.h"    /* To find the error handlers */
  80. #include "stack.h"    /* Stacks and stacklets */
  81. #include "interp.h"     /* Interpreter state and primitive destructuring */
  82. #include "default.h"    /* various definitions */
  83. #include "extern.h"    /* External decls (missing Cont_Debug, etc.) */
  84. #include "trap.h"       /* UNASSIGNED_OBJECT, TRAP_EXTENSION_TYPE */
  85. #include "prims.h"      /* LEXPR */
  86. #include "prim.h"    /* Primitive_Procedure_Table, etc. */
  87.  
  88. #define ENTRY_TO_OBJECT(entry)                        \
  89.   (MAKE_POINTER_OBJECT (TC_COMPILED_ENTRY, ((SCHEME_OBJECT *) (entry))))
  90.  
  91. #define IN_CMPINT_C
  92. #include "cmpgc.h"      /* Compiled code object relocation */
  93.  
  94. #ifdef HAS_COMPILER_SUPPORT
  95.  
  96. /* ASM_ENTRY_POINT, EXFNX, and DEFNX are for OS/2.  The IBM C Set++/2
  97.    compiler has several different external calling conventions.  The
  98.    default calling convention is called _Optlink, uses a combination
  99.    of registers and the stack, and is complicated.  The calling
  100.    convention used for operating system interface procedures is called
  101.    _System, uses only the stack, and is very similar to the calling
  102.    conventions used with our DOS compilers.  So, in order to simplify
  103.    the changes to the assembly language, we use _System conventions
  104.    for calling C procedures from the assembly language file.
  105.  
  106.    Since _Optlink is the default, we must somehow cause the relevant
  107.    procedures to be compiled using _System.  The easiest way to do
  108.    this is to force the use of _System everywhere, but that's
  109.    undesirable since _Optlink is generally more efficient.  Instead,
  110.    we use the ASM_ENTRY_POINT wrapper to cause each of the relevant
  111.    procedures to be tagged with the compiler's _System keyword.  The
  112.    relevant procedures are all of the SCHEME_UTILITY procedures,
  113.    C_to_interface, interface_to_C, and interface_to_scheme.  */
  114.  
  115. #ifndef ASM_ENTRY_POINT
  116. #  define ASM_ENTRY_POINT(name) name
  117. #endif
  118.  
  119. #ifdef STDC_HEADERS
  120. #define EXFNX(name, proto) ASM_ENTRY_POINT (name) proto
  121. #define DEFNX(name, arglist, args) ASM_ENTRY_POINT (name) (args)
  122. #define DEFNX_VOID(name) ASM_ENTRY_POINT (name) (void)
  123. #else
  124. #define EXFNX(name, proto) ASM_ENTRY_POINT (name) ()
  125. #define DEFNX(name, arglist, args) ASM_ENTRY_POINT (name) arglist args;
  126. #define DEFNX_VOID(name) ASM_ENTRY_POINT (name) ()
  127. #endif
  128.  
  129. /* Make noise words invisible to the C compiler. */
  130.  
  131. #define C_UTILITY
  132. #define C_TO_SCHEME
  133. #define SCHEME_UTILITY
  134.  
  135. /* For clarity */
  136.  
  137. typedef char instruction;
  138.  
  139. #ifndef CMPINT_USE_STRUCS
  140.  
  141. typedef instruction * utility_result;
  142.  
  143. /* Imports from assembly language */
  144.  
  145. extern void EXFNX (C_to_interface, (void *));
  146. extern utility_result interface_to_C_hook;
  147.  
  148. extern long C_return_value;
  149. long C_return_value;
  150.  
  151. /* Convenience macros */
  152.  
  153. #define RETURN_TO_C(code) do                        \
  154. {                                    \
  155.   C_return_value = (code);                        \
  156.   return (interface_to_C_hook);                        \
  157. } while (false)
  158.  
  159. #define RETURN_TO_SCHEME(ep)    return ((utility_result) (ep))
  160.  
  161. #define ENTER_SCHEME(ep) do                        \
  162. {                                    \
  163.   C_to_interface ((void *) (ep));                    \
  164.   return (C_return_value);                        \
  165. } while (false)
  166.  
  167. #else /* CMPINT_USE_STRUCS */
  168.  
  169. #ifdef C_FUNC_PTR_IS_CLOSURE
  170. #  define REFENTRY(name) (name)
  171. #  define VARENTRY(name) instruction *name
  172. #  define EXTENTRY(name) extern instruction *name
  173. #else
  174. #  define REFENTRY(name) ((void (*)()) name)
  175. #  define VARENTRY(name) void (*name)()
  176. #  define EXTENTRY(name) extern void EXFNX (name, (void))
  177. #endif
  178.  
  179. /* Structure returned by SCHEME_UTILITYs */
  180.  
  181. struct utility_result_s
  182. {
  183.   VARENTRY (interface_dispatch);
  184.   union additional_info
  185.   {
  186.     long                code_to_interpreter;
  187.     instruction        *entry_point;
  188.   } extra;
  189. };
  190.  
  191. typedef struct utility_result_s utility_result;
  192.  
  193. /* Imports from assembly language */
  194.  
  195. extern long EXFNX (C_to_interface, (void *));
  196.  
  197. EXTENTRY (interface_to_C);
  198. EXTENTRY (interface_to_scheme);
  199.  
  200. /* Convenience macros */
  201.  
  202. #define RETURN_TO_C(code) do                        \
  203. {                                    \
  204.   struct utility_result_s temp;                        \
  205.                                     \
  206.   temp.interface_dispatch = (REFENTRY (interface_to_C));        \
  207.   temp.extra.code_to_interpreter = (code);                \
  208.                                     \
  209.   return (temp);                            \
  210. } while (false)
  211.  
  212. #define RETURN_TO_SCHEME(ep) do                        \
  213. {                                    \
  214.   struct utility_result_s temp;                        \
  215.                                     \
  216.   temp.interface_dispatch = (REFENTRY (interface_to_scheme));        \
  217.   temp.extra.entry_point = ((instruction *) (ep));            \
  218.                                     \
  219.   return (temp);                            \
  220. } while (false)
  221.  
  222. #define ENTER_SCHEME(ep)    return (C_to_interface ((void *) (ep)))
  223.  
  224. #endif /* CMPINT_USE_STRUCS */
  225.  
  226. /* utility table entries. */
  227.  
  228. typedef utility_result EXFUN
  229.   ((*ASM_ENTRY_POINT(utility_table_entry)), (long, long, long, long));
  230.  
  231. #define RETURN_UNLESS_EXCEPTION(code, entry_point)                      \
  232. {                                                                       \
  233.   int return_code;                                                      \
  234.                                                                         \
  235.   return_code = (code);                                                 \
  236.   if (return_code == PRIM_DONE)                                         \
  237.   {                                                                     \
  238.     RETURN_TO_SCHEME (entry_point);                                     \
  239.   }                                                                     \
  240.   else                                                                  \
  241.   {                                                                     \
  242.     RETURN_TO_C (return_code);                                          \
  243.   }                                                                     \
  244. }
  245.  
  246. #define MAKE_CC_BLOCK(block_addr)                    \
  247.   (MAKE_POINTER_OBJECT (TC_COMPILED_CODE_BLOCK, block_addr))
  248.  
  249. /* Imports from the rest of the "microcode" */
  250.  
  251. extern long
  252.   EXFUN (compiler_cache_assignment, (SCHEME_OBJECT, SCHEME_OBJECT, long)),
  253.   EXFUN (compiler_cache_lookup, (SCHEME_OBJECT, SCHEME_OBJECT, long)),
  254.   EXFUN (compiler_cache_global_operator, (SCHEME_OBJECT, SCHEME_OBJECT, long)),
  255.   EXFUN (compiler_cache_operator, (SCHEME_OBJECT, SCHEME_OBJECT, long));
  256.  
  257. /* Exports to the rest of the "microcode" */
  258.  
  259. extern long
  260.   compiler_interface_version,
  261.   compiler_processor_type;
  262.  
  263. extern SCHEME_OBJECT
  264.   compiler_utilities,
  265.   return_to_interpreter;
  266.  
  267. extern C_UTILITY long
  268.   EXFUN (make_fake_uuo_link,
  269.      (SCHEME_OBJECT extension, SCHEME_OBJECT block, long offset)),
  270.   EXFUN (make_uuo_link,
  271.      (SCHEME_OBJECT value, SCHEME_OBJECT extension,
  272.       SCHEME_OBJECT block, long offset)),
  273.   EXFUN (compiled_block_closure_p, (SCHEME_OBJECT block)),
  274.   EXFUN (compiled_entry_closure_p, (SCHEME_OBJECT entry)),
  275.   EXFUN (compiled_entry_to_block_offset, (SCHEME_OBJECT entry)),
  276.   EXFUN (coerce_to_compiled,
  277.      (SCHEME_OBJECT object, long arity, SCHEME_OBJECT *location));
  278.  
  279. extern C_UTILITY SCHEME_OBJECT
  280.   EXFUN (extract_uuo_link, (SCHEME_OBJECT block, long offset)),
  281.   EXFUN (extract_variable_cache,
  282.      (SCHEME_OBJECT extension, long offset)),
  283.   EXFUN (compiled_block_debugging_info, (SCHEME_OBJECT block)),
  284.   EXFUN (compiled_block_environment, (SCHEME_OBJECT block)),
  285.   EXFUN (compiled_closure_to_entry, (SCHEME_OBJECT entry)),
  286.   EXFUN (compiled_entry_to_block, (SCHEME_OBJECT entry)),
  287.   EXFUN (apply_compiled_from_primitive, (int)),
  288.   EXFUN (compiled_with_interrupt_mask, (unsigned long,
  289.                     SCHEME_OBJECT,
  290.                     unsigned long)),
  291.   EXFUN (compiled_with_stack_marker, (SCHEME_OBJECT)),
  292.   * EXFUN (cons_c_code_table, (SCHEME_OBJECT *, SCHEME_OBJECT *, long *));
  293.  
  294. extern C_UTILITY Boolean
  295.   EXFUN (install_c_code_table, (SCHEME_OBJECT *, long));
  296.  
  297. extern C_UTILITY void
  298.   EXFUN (compiler_initialize, (long fasl_p)),
  299.   EXFUN (compiler_reset, (SCHEME_OBJECT new_block)),
  300.   EXFUN (store_variable_cache,
  301.      (SCHEME_OBJECT extension, SCHEME_OBJECT block, long offset)),
  302.   EXFUN (declare_compiled_code_block, (SCHEME_OBJECT block));  
  303.  
  304. extern utility_table_entry utility_table[];
  305.  
  306. static SCHEME_OBJECT reflect_to_interface;
  307.  
  308. /* Breakpoint stuff. */
  309.  
  310. extern C_UTILITY SCHEME_OBJECT EXFUN (bkpt_install, (PTR));
  311. extern C_UTILITY SCHEME_OBJECT EXFUN (bkpt_closure_install, (PTR));
  312. extern C_UTILITY Boolean EXFUN (bkpt_p, (PTR));
  313. extern C_UTILITY SCHEME_OBJECT EXFUN
  314.   (bkpt_proceed, (PTR, SCHEME_OBJECT, SCHEME_OBJECT));
  315. extern C_UTILITY void EXFUN (bkpt_remove, (PTR, SCHEME_OBJECT));
  316.  
  317. /* These definitions reflect the indices into the table above. */
  318.  
  319. #define TRAMPOLINE_K_RETURN            0x0
  320. #define TRAMPOLINE_K_APPLY            0x1
  321. #define TRAMPOLINE_K_ARITY            0x2
  322. #define TRAMPOLINE_K_ENTITY            0x3
  323. #define TRAMPOLINE_K_INTERPRETED        0x4
  324. #define TRAMPOLINE_K_LEXPR_PRIMITIVE        0x5
  325. #define TRAMPOLINE_K_PRIMITIVE            0x6
  326. #define TRAMPOLINE_K_LOOKUP            0x7
  327. #define TRAMPOLINE_K_1_0            0x8
  328. #define TRAMPOLINE_K_2_1            0x9
  329. #define TRAMPOLINE_K_2_0            0xa
  330. #define TRAMPOLINE_K_3_2            0xb
  331. #define TRAMPOLINE_K_3_1            0xc
  332. #define TRAMPOLINE_K_3_0            0xd
  333. #define TRAMPOLINE_K_4_3            0xe
  334. #define TRAMPOLINE_K_4_2            0xf
  335. #define TRAMPOLINE_K_4_1            0x10
  336. #define TRAMPOLINE_K_4_0            0x11
  337. #define TRAMPOLINE_K_REFLECT_TO_INTERFACE    0x3a
  338.  
  339. #define TRAMPOLINE_K_OTHER            TRAMPOLINE_K_INTERPRETED
  340.  
  341. /* Ways to bypass the interpreter */
  342.  
  343. #define REFLECT_CODE_INTERNAL_APPLY        0
  344. #define REFLECT_CODE_RESTORE_INTERRUPT_MASK    1
  345. #define REFLECT_CODE_STACK_MARKER        2
  346. #define REFLECT_CODE_CC_BKPT            3
  347.  
  348. /* Markers for special entry points */
  349.  
  350. #ifndef FORMAT_BYTE_EXPR
  351. #define FORMAT_BYTE_EXPR                    0xFF
  352. #endif
  353. #ifndef FORMAT_BYTE_COMPLR
  354. #define FORMAT_BYTE_COMPLR                  0xFE
  355. #endif
  356. #ifndef FORMAT_BYTE_CMPINT
  357. #define FORMAT_BYTE_CMPINT                  0xFD
  358. #endif
  359. #ifndef FORMAT_BYTE_DLINK
  360. #define FORMAT_BYTE_DLINK                   0xFC
  361. #endif
  362. #ifndef FORMAT_BYTE_RETURN
  363. #define FORMAT_BYTE_RETURN                  0xFB
  364. #endif
  365. #ifndef FORMAT_BYTE_CLOSURE
  366. #define FORMAT_BYTE_CLOSURE            0xFA
  367. #endif
  368. #ifndef FORMAT_BYTE_FRAMEMAX
  369. #define FORMAT_BYTE_FRAMEMAX                0x7F
  370. #endif
  371.  
  372. #ifndef FORMAT_WORD_EXPR
  373. #define FORMAT_WORD_EXPR        (MAKE_FORMAT_WORD (0xFF, FORMAT_BYTE_EXPR))
  374. #endif
  375. #ifndef FORMAT_WORD_CMPINT
  376. #define FORMAT_WORD_CMPINT      (MAKE_FORMAT_WORD (0xFF, FORMAT_BYTE_CMPINT))
  377. #endif
  378. #ifndef FORMAT_WORD_RETURN
  379. #define FORMAT_WORD_RETURN      (MAKE_FORMAT_WORD (0xFF, FORMAT_BYTE_RETURN))
  380. #endif
  381.  
  382. /* Utilities for application of compiled procedures. */
  383.  
  384. /* NOTE: In this file, the number of arguments (or minimum
  385.    number of arguments, etc.) is always 1 greater than the number of
  386.    arguments (it includes the procedure object).
  387.  */
  388.  
  389. /* open_gap: Default some optional parameters, and return the location
  390.    of the return address (one past the last actual argument location).
  391.  */
  392.  
  393. static SCHEME_OBJECT *
  394. DEFUN (open_gap,
  395.        (nactuals, delta),
  396.        register long nactuals AND register long delta)
  397. {
  398.   register SCHEME_OBJECT *gap_location, *source_location;
  399.  
  400.   /* Need to fill in optionals */
  401.  
  402.   gap_location = STACK_LOC (delta);
  403.   source_location = STACK_LOC (0);
  404.   Stack_Pointer = gap_location;
  405.   while ((--nactuals) > 0)
  406.   {
  407.     STACK_LOCATIVE_POP (gap_location) = STACK_LOCATIVE_POP (source_location);
  408.   }
  409.   delta = (- delta);
  410.   while ((--delta) >= 0)
  411.   {
  412.     STACK_LOCATIVE_POP (gap_location) = UNASSIGNED_OBJECT;
  413.   }
  414.   return (source_location);
  415. }
  416.  
  417. /* setup_lexpr_invocation: Setup a rest argument as appropriate. */
  418.  
  419. static long
  420. DEFUN (setup_lexpr_invocation,
  421.        (nactuals, nmax, entry_address),
  422.        register long nactuals AND register long nmax
  423.        AND instruction * entry_address)
  424. {
  425.   register long delta;
  426.  
  427.   /* nmax is negative! */
  428.  
  429.   delta = (nactuals + nmax);
  430.  
  431.   if (delta < 0)
  432.   {
  433.     /* Not enough arguments have been passed to allocate a list.
  434.        The missing optional arguments must be defaulted, and the
  435.        rest parameter needs to be set to the empty list.
  436.      */
  437.  
  438.     SCHEME_OBJECT *last_loc;
  439.  
  440.     last_loc = open_gap (nactuals, delta);
  441.     (STACK_LOCATIVE_PUSH (last_loc)) = EMPTY_LIST;
  442.     return (PRIM_DONE);
  443.   }
  444.   else if (delta == 0)
  445.   {
  446.     /* The number of arguments passed matches exactly the number of
  447.        formal paramters.  The last argument needs to be replaced by
  448.        a list containing it, but there is no need to pop anything
  449.        since the frame has the right size.
  450.        This does not check for gc!
  451.        The procedure should (and currently will) on entry.
  452.      */
  453.  
  454.     register SCHEME_OBJECT temp, *gap_location, *local_free;
  455.  
  456.     local_free = Free;
  457.     Free += 2;
  458.     gap_location = STACK_LOC (nactuals - 2);
  459.     temp = *gap_location;
  460.     *gap_location = (MAKE_POINTER_OBJECT (TC_LIST, local_free));
  461.     *local_free++ = temp;
  462.     *local_free = EMPTY_LIST;
  463.     return (PRIM_DONE);
  464.   }
  465.   else /* (delta > 0) */
  466.   {
  467.     /* The number of arguments passed is greater than the number of
  468.        formal parameters named by the procedure.  Excess arguments
  469.        need to be placed in a list passed at the last parameter
  470.        location. The extra arguments must then be popped from the stack.
  471.      */
  472.     long list_size;
  473.     register SCHEME_OBJECT *gap_location, *source_location;
  474.  
  475.     /* Allocate the list, and GC if necessary. */
  476.  
  477.     list_size = (2 * (delta + 1));
  478.     if (GC_Check (list_size))
  479.     {
  480.       Request_GC (list_size);
  481.       STACK_PUSH (ENTRY_TO_OBJECT (entry_address));
  482.       STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (nactuals));
  483.       return (PRIM_APPLY_INTERRUPT);
  484.     }
  485.     gap_location = &Free[list_size];
  486.     Free = gap_location;
  487.  
  488.     /* Place the arguments in the list, and link it. */
  489.  
  490.     source_location = (STACK_LOC (nactuals - 1));
  491.     (*(--gap_location)) = EMPTY_LIST;
  492.  
  493.     while ((--delta) >= 0)
  494.     {
  495.       gap_location -= 2;
  496.       (*(gap_location + 1)) = (STACK_LOCATIVE_PUSH (source_location));
  497.       (*(gap_location)) = (MAKE_POINTER_OBJECT (TC_LIST, (gap_location + 1)));
  498.     }
  499.  
  500.     (*(--gap_location)) = (STACK_LOCATIVE_PUSH (source_location));
  501.  
  502.     /* Place the list at the appropriate location in the stack. */
  503.  
  504.     STACK_LOCATIVE_REFERENCE (source_location, 0) =
  505.       (MAKE_POINTER_OBJECT (TC_LIST, (gap_location)));
  506.  
  507.     /* Now move the arguments into their correct location in the stack
  508.        popping any unneeded locations.
  509.      */
  510.  
  511.     gap_location = (STACK_LOC (nactuals - 1));
  512.     STACK_LOCATIVE_INCREMENT (source_location);
  513.  
  514.     /* Remember that nmax is originally negative! */
  515.  
  516.     for (nmax = ((-nmax) - 1); ((--nmax) >= 0); )
  517.     {
  518.       (STACK_LOCATIVE_PUSH (gap_location)) =
  519.         (STACK_LOCATIVE_PUSH (source_location));
  520.     }
  521.     Stack_Pointer = gap_location;
  522.     return (PRIM_DONE);
  523.   }
  524. }
  525.  
  526. /* setup_compiled_invocation: Prepare the application frame the way that
  527.    the called procedure expects it (optional arguments and rest argument
  528.    initialized.
  529.  */
  530.  
  531. static long
  532. DEFUN (setup_compiled_invocation,
  533.        (nactuals, compiled_entry_address),
  534.        long nactuals AND instruction * compiled_entry_address)
  535. {
  536.   long nmin, nmax, delta;               /* all +1 */
  537.  
  538.   nmax = (COMPILED_ENTRY_MAXIMUM_ARITY (compiled_entry_address));
  539.   if (nactuals == nmax)
  540.   {
  541.     /* Either the procedure takes exactly the number of arguments
  542.        given, or it has optional arguments, no rest argument, and
  543.        all the optional arguments have been provided.  Thus the
  544.        frame is in the right format and we are done.
  545.      */
  546.     return (PRIM_DONE);
  547.   }
  548.   nmin = (COMPILED_ENTRY_MINIMUM_ARITY (compiled_entry_address));
  549.   if (nmin < 0)
  550.   {
  551.     /* Not a procedure. */
  552.     STACK_PUSH (ENTRY_TO_OBJECT (compiled_entry_address));
  553.     STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (nactuals));
  554.     return (ERR_INAPPLICABLE_OBJECT);
  555.   }
  556.   if (nactuals < nmin)
  557.   {
  558.     /* Too few arguments. */
  559.     STACK_PUSH (ENTRY_TO_OBJECT (compiled_entry_address));
  560.     STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (nactuals));
  561.     return (ERR_WRONG_NUMBER_OF_ARGUMENTS);
  562.   }
  563.   delta = (nactuals - nmax);
  564.   if (delta <= 0)
  565.   {
  566.     /* The procedure takes optional arguments but no rest argument
  567.        and not all the optional arguments have been provided.
  568.        They must be defaulted.
  569.      */
  570.     ((void) (open_gap (nactuals, delta)));
  571.     return (PRIM_DONE);
  572.   }
  573.   if (nmax > 0)
  574.   {
  575.     /* Too many arguments */
  576.     STACK_PUSH (ENTRY_TO_OBJECT (compiled_entry_address));
  577.     STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (nactuals));
  578.     return (ERR_WRONG_NUMBER_OF_ARGUMENTS);
  579.   }
  580.   /* The procedure can take arbitrarily many arguments, ie.
  581.      it is a lexpr.
  582.    */
  583.   return (setup_lexpr_invocation (nactuals, nmax, compiled_entry_address));
  584. }
  585.  
  586. /* Main compiled code entry points.
  587.  
  588.    These are the primary entry points that the interpreter
  589.    uses to execute compiled code.
  590.    The other entry points are special purpose return
  591.    points to compiled code invoked after the interpreter has been
  592.    employed to take corrective action (interrupt, error, etc).
  593.    They are coded adjacent to the place where the interpreter
  594.    is invoked.
  595.  */
  596.  
  597. C_TO_SCHEME long
  598. DEFUN_VOID (enter_compiled_expression)
  599. {
  600.   instruction * compiled_entry_address;
  601.  
  602.   compiled_entry_address =
  603.     ((instruction *) (OBJECT_ADDRESS (Fetch_Expression ())));
  604.   if ((COMPILED_ENTRY_FORMAT_WORD (compiled_entry_address)) !=
  605.       FORMAT_WORD_EXPR)
  606.   {
  607.     /* It self evaluates. */
  608.     Val = (Fetch_Expression ());
  609.     ENTER_SCHEME (OBJECT_ADDRESS (STACK_POP ()));
  610.   }
  611.   ENTER_SCHEME (compiled_entry_address);
  612. }
  613.  
  614. C_TO_SCHEME long
  615. DEFUN_VOID (apply_compiled_procedure)
  616. {
  617.   SCHEME_OBJECT nactuals, procedure;
  618.   instruction * procedure_entry;
  619.   long result;
  620.  
  621.   nactuals = (STACK_POP ());
  622.   procedure = (STACK_POP ());
  623.   procedure_entry = ((instruction *) (OBJECT_ADDRESS (procedure)));
  624.   result = setup_compiled_invocation ((OBJECT_DATUM (nactuals)),
  625.                                       procedure_entry);
  626.   if (result == PRIM_DONE)
  627.     /* Go into compiled code. */
  628.     ENTER_SCHEME (procedure_entry);
  629.   else
  630.     return (result);
  631. }
  632.  
  633. /* Note that this does not check that compiled_entry_address
  634.    is a valid return address. -- Should it?
  635.  */
  636.  
  637. C_TO_SCHEME long
  638. DEFUN_VOID (return_to_compiled_code)
  639. {
  640.   instruction *compiled_entry_address;
  641.  
  642.   compiled_entry_address =
  643.     ((instruction *) (OBJECT_ADDRESS (STACK_POP ())));
  644.   ENTER_SCHEME (compiled_entry_address);
  645. }
  646.  
  647. C_UTILITY SCHEME_OBJECT
  648. DEFUN (apply_compiled_from_primitive, (arity), int arity)
  649. {
  650.   SCHEME_OBJECT frame_size, procedure;
  651.   long result;
  652.   
  653.   frame_size = (STACK_POP ());
  654.   procedure = (STACK_POP ());
  655.  
  656.   switch (OBJECT_TYPE (procedure))
  657.   {
  658.     case TC_ENTITY:
  659.     {
  660.       SCHEME_OBJECT data, operator;
  661.       unsigned long nactuals = (OBJECT_DATUM (frame_size));
  662.  
  663.       data = (MEMORY_REF (procedure, ENTITY_DATA));
  664.       if ((VECTOR_P (data))
  665.       && (nactuals < (VECTOR_LENGTH (data)))
  666.       && (COMPILED_CODE_ADDRESS_P (VECTOR_REF (data, nactuals)))
  667.       && ((VECTOR_REF (data, 0))
  668.           == (Get_Fixed_Obj_Slot (ARITY_DISPATCHER_TAG))))
  669.     procedure = (VECTOR_REF (data, nactuals));
  670.       else
  671.       {
  672.     operator = (MEMORY_REF (procedure, ENTITY_OPERATOR));
  673.     if (!COMPILED_CODE_ADDRESS_P (operator))
  674.       goto defer_application;
  675.     STACK_PUSH (procedure);
  676.     frame_size += 1;
  677.     procedure = operator;
  678.       }
  679.       /* fall through */
  680.     }
  681.  
  682.     case TC_COMPILED_ENTRY:
  683.     {
  684.       result = setup_compiled_invocation ((OBJECT_DATUM (frame_size)),
  685.                       ((instruction *)
  686.                        (OBJECT_ADDRESS (procedure))));
  687.       if (result == PRIM_DONE)
  688.       {
  689.     STACK_PUSH (procedure);
  690.     Stack_Pointer = (STACK_LOC (- arity));
  691.     return (SHARP_F);
  692.       }
  693.       else
  694.     break;
  695.     }
  696.  
  697.     case TC_PRIMITIVE:
  698.     /* For now, fall through */
  699.  
  700.     default:
  701. defer_application:
  702.       STACK_PUSH (procedure);
  703.       STACK_PUSH (frame_size);
  704.       break;
  705.   }
  706.  
  707.   STACK_PUSH (FIXNUM_ZERO + REFLECT_CODE_INTERNAL_APPLY);
  708.   STACK_PUSH (reflect_to_interface);
  709.   Stack_Pointer = (STACK_LOC (- arity));
  710.   return (SHARP_F);
  711. }
  712.  
  713. C_UTILITY SCHEME_OBJECT
  714. DEFUN (compiled_with_interrupt_mask, (old_mask, receiver, new_mask),
  715.        unsigned long old_mask
  716.        AND SCHEME_OBJECT receiver
  717.        AND unsigned long new_mask)
  718. {
  719.   long result;
  720.  
  721.   STACK_PUSH (LONG_TO_FIXNUM (old_mask));
  722.   STACK_PUSH (FIXNUM_ZERO + REFLECT_CODE_RESTORE_INTERRUPT_MASK);
  723.   STACK_PUSH (reflect_to_interface);
  724.  
  725.   STACK_PUSH (LONG_TO_FIXNUM (new_mask));
  726.   result = (setup_compiled_invocation (2,
  727.                        ((instruction *)
  728.                     (OBJECT_ADDRESS (receiver)))));
  729.   STACK_PUSH (receiver);
  730.  
  731.   if (result != PRIM_DONE)
  732.   {
  733.     STACK_PUSH (STACK_FRAME_HEADER + 1);
  734.     STACK_PUSH (FIXNUM_ZERO + REFLECT_CODE_INTERNAL_APPLY);
  735.     STACK_PUSH (reflect_to_interface);
  736.   }
  737.  
  738.   Stack_Pointer = (STACK_LOC (- 2));
  739.   return (SHARP_F);
  740. }
  741.  
  742. C_UTILITY SCHEME_OBJECT
  743. DEFUN (compiled_with_stack_marker, (thunk), SCHEME_OBJECT thunk)
  744. {
  745.   long result;
  746.  
  747.   STACK_PUSH (FIXNUM_ZERO + REFLECT_CODE_STACK_MARKER);
  748.   STACK_PUSH (reflect_to_interface);
  749.  
  750.   result = (setup_compiled_invocation (1,
  751.                        ((instruction *)
  752.                     (OBJECT_ADDRESS (thunk)))));
  753.   STACK_PUSH (thunk);
  754.  
  755.   if (result != PRIM_DONE)
  756.   {
  757.     STACK_PUSH (STACK_FRAME_HEADER);
  758.     STACK_PUSH (FIXNUM_ZERO + REFLECT_CODE_INTERNAL_APPLY);
  759.     STACK_PUSH (reflect_to_interface);
  760.   }
  761.  
  762.   Stack_Pointer = (STACK_LOC (- 3));
  763.   return (SHARP_F);
  764. }
  765.  
  766. /*
  767.   SCHEME_UTILITYs
  768.  
  769.   Here's a mass of procedures that are called (via scheme_to_interface,
  770.   an assembly language hook) by compiled code to do various jobs.
  771.  */
  772.  
  773. /*
  774.   This is how compiled Scheme code normally returns back to the
  775.   Scheme interpreter.
  776.   It is invoked by a trampoline, which passes the address of the
  777.   trampoline storage block (empty) to it.
  778.  */
  779.  
  780. SCHEME_UTILITY utility_result
  781. DEFNX (comutil_return_to_interpreter,
  782.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  783.        SCHEME_ADDR tramp_data_raw
  784.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  785. {
  786.   RETURN_TO_C (PRIM_DONE);
  787. }
  788.  
  789. #if (COMPILER_PROCESSOR_TYPE != COMPILER_IA32_TYPE)
  790.  
  791. #define INVOKE_RETURN_ADDRESS()                    \
  792.   RETURN_TO_SCHEME (OBJECT_ADDRESS (STACK_POP ()))
  793.  
  794. #else /* COMPILER_IA32_TYPE */
  795.  
  796. static utility_result
  797.   EXFUN (compiler_interrupt_common, (SCHEME_ADDR, SCHEME_OBJECT));
  798.  
  799. #define INVOKE_RETURN_ADDRESS() do                    \
  800. {                                    \
  801.   if (((long) (ADDR_TO_SCHEME_ADDR (Free)))                \
  802.       >= ((long) (Regs[REGBLOCK_MEMTOP])))                \
  803.     return (compiler_interrupt_common (0, Val));            \
  804.   else                                    \
  805.     RETURN_TO_SCHEME (OBJECT_ADDRESS (STACK_POP ()));            \
  806. } while (0)
  807.  
  808. #endif /* COMPILER_IA32_TYPE */
  809.  
  810. /*
  811.   comutil_primitive_apply is used to invoked a C primitive.
  812.   Note that some C primitives (the so called interpreter hooks)
  813.   will not return normally, but will "longjmp" to the interpreter
  814.   instead.  Thus the assembly language invoking this should have
  815.   set up the appropriate locations in case this happens.
  816.   After invoking the primitive, it pops the arguments off the
  817.   Scheme stack, and proceeds by invoking the continuation on top
  818.   of the stack.
  819.  */
  820.  
  821. SCHEME_UTILITY utility_result
  822. DEFNX (comutil_primitive_apply,
  823.        (primitive, ignore_2, ignore_3, ignore_4),
  824.        SCHEME_OBJECT primitive
  825.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  826.   PRIMITIVE_APPLY (Val, primitive);
  827.   POP_PRIMITIVE_FRAME (PRIMITIVE_ARITY (primitive));
  828.   INVOKE_RETURN_ADDRESS ();
  829. }
  830.  
  831. /*
  832.   comutil_primitive_lexpr_apply is like comutil_primitive_apply
  833.   except that it is used to invoke primitives that take
  834.   an arbitrary number of arguments.
  835.   The number of arguments is in the REGBLOCK_LEXPR_ACTUALS slot
  836.   of the register block.
  837.  */
  838.  
  839. SCHEME_UTILITY utility_result
  840. DEFNX (comutil_primitive_lexpr_apply,
  841.        (primitive, ignore_2, ignore_3, ignore_4),
  842.        SCHEME_OBJECT primitive
  843.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  844. {
  845.   PRIMITIVE_APPLY (Val, primitive);
  846.   POP_PRIMITIVE_FRAME (((long) Regs[REGBLOCK_LEXPR_ACTUALS]));
  847.   INVOKE_RETURN_ADDRESS ();
  848. }
  849.  
  850. /*
  851.   comutil_apply is used by compiled code to invoke an unknown
  852.   procedure.  It dispatches on its type to the correct place.  It
  853.   expects the procedure to invoke, and the number of arguments (+ 1).
  854.  */
  855.  
  856. SCHEME_UTILITY utility_result
  857. DEFNX (comutil_apply,
  858.        (procedure, nactuals, ignore_3, ignore_4),
  859.        SCHEME_OBJECT procedure
  860.        AND unsigned long nactuals
  861.        AND long ignore_3 AND long ignore_4)
  862. {
  863.   SCHEME_OBJECT orig_proc = procedure;
  864.  
  865. loop:
  866.   switch (OBJECT_TYPE (procedure))
  867.   {
  868.     case TC_COMPILED_ENTRY:
  869.     callee_is_compiled:
  870.     {
  871.       instruction * entry_point;
  872.  
  873.       entry_point = ((instruction *) (OBJECT_ADDRESS (procedure)));
  874.       RETURN_UNLESS_EXCEPTION
  875.         ((setup_compiled_invocation (nactuals, entry_point)),
  876.          entry_point);
  877.     }
  878.  
  879.     case TC_ENTITY:
  880.     {
  881.       SCHEME_OBJECT data, operator;
  882.  
  883.       data = (MEMORY_REF (procedure, ENTITY_DATA));
  884.       if ((VECTOR_P (data))
  885.       && (nactuals < (VECTOR_LENGTH (data)))
  886.       && ((VECTOR_REF (data, nactuals)) != SHARP_F)
  887.       && ((VECTOR_REF (data, 0))
  888.           == (Get_Fixed_Obj_Slot (ARITY_DISPATCHER_TAG))))
  889.       {
  890.     /* No loops allowed! */
  891.     SCHEME_OBJECT nproc = (VECTOR_REF (data, nactuals));
  892.  
  893.     if ((procedure == orig_proc) && (nproc != procedure))
  894.     {
  895.       procedure = nproc;
  896.       goto loop;
  897.     }
  898.     else
  899.       procedure = orig_proc;
  900.       }
  901.  
  902.       operator = (MEMORY_REF (procedure, ENTITY_OPERATOR));
  903.       if (!(COMPILED_CODE_ADDRESS_P (operator)))
  904.         goto callee_is_interpreted;
  905.  
  906.       STACK_PUSH (procedure);           /* The entity itself */
  907.       procedure = operator;
  908.       nactuals += 1;
  909.       goto callee_is_compiled;
  910.     }
  911.     case TC_PRIMITIVE:
  912.     {
  913.       /* This code depends on the fact that unimplemented
  914.          primitives map into a "fake" primitive which accepts
  915.          any number of arguments, thus the arity test will
  916.          fail for unimplemented primitives.
  917.        */
  918.  
  919.       long arity;
  920.  
  921.       arity = (PRIMITIVE_ARITY (procedure));
  922.       if (arity == ((long) (nactuals - 1)))
  923.         return (comutil_primitive_apply (procedure, 0, 0, 0));
  924.  
  925.       if (arity != LEXPR)
  926.       {
  927.         /* Wrong number of arguments. */
  928.         STACK_PUSH (procedure);
  929.         STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (nactuals));
  930.         RETURN_TO_C (ERR_WRONG_NUMBER_OF_ARGUMENTS);
  931.       }
  932.       if (!(IMPLEMENTED_PRIMITIVE_P (procedure)))
  933.         /* Let the interpreter handle it. */
  934.         goto callee_is_interpreted;
  935.  
  936.       /* "Lexpr" primitive. */
  937.       Regs[REGBLOCK_LEXPR_ACTUALS] = ((SCHEME_OBJECT) (nactuals - 1));
  938.       return (comutil_primitive_lexpr_apply (procedure, 0, 0, 0));
  939.     }
  940.  
  941.     callee_is_interpreted:
  942.     default:
  943.     {
  944.       STACK_PUSH (procedure);
  945.       STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (nactuals));
  946.       RETURN_TO_C (PRIM_APPLY);
  947.     }
  948.   }
  949. }
  950.  
  951. /*
  952.   comutil_error is used by compiled code to signal an error.  It
  953.   expects the arguments to the error procedure to be pushed on the
  954.   stack, and is passed the number of arguments (+ 1).
  955. */
  956.  
  957. SCHEME_UTILITY utility_result
  958. DEFNX (comutil_error,
  959.        (nactuals, ignore_2, ignore_3, ignore_4),
  960.        long nactuals AND
  961.        long ignore_2 AND long ignore_3 AND long ignore_4)
  962. {
  963.   SCHEME_OBJECT error_procedure;
  964.  
  965.   error_procedure = (Get_Fixed_Obj_Slot (Compiler_Err_Procedure));
  966.   return (comutil_apply (error_procedure, nactuals, 0, 0));
  967. }
  968.  
  969. /*
  970.   comutil_lexpr_apply is invoked to reformat the frame when compiled
  971.   code calls a known lexpr.  The actual arguments are on the stack,
  972.   and it is given the number of arguments (WITHOUT counting the entry
  973.   point being invoked), and the real entry point of the procedure.
  974.  
  975.   Important: This code assumes that it is always invoked with a valid
  976.   number of arguments (the compiler checked it), and will not check.
  977.  */
  978.  
  979. SCHEME_UTILITY utility_result
  980. DEFNX (comutil_lexpr_apply,
  981.        (entry_address_raw, nactuals, ignore_3, ignore_4),
  982.        SCHEME_ADDR entry_address_raw AND long nactuals
  983.        AND long ignore_3 AND long ignore_4)
  984. {
  985.   instruction * entry_address
  986.     = ((instruction *) (SCHEME_ADDR_TO_ADDR (entry_address_raw)));
  987.                  
  988.   RETURN_UNLESS_EXCEPTION
  989.     ((setup_lexpr_invocation
  990.       ((nactuals + 1),
  991.        (COMPILED_ENTRY_MAXIMUM_ARITY (entry_address)),
  992.        entry_address)),
  993.      entry_address);
  994. }
  995.  
  996. static long
  997. DEFUN (compiler_link_closure_pattern, (distance, block, offset),
  998.        SCHEME_OBJECT distance AND SCHEME_OBJECT block AND long offset)
  999. {
  1000.   long objdist = (FIXNUM_TO_LONG (distance));
  1001.   long nmv_length = (OBJECT_DATUM (MEMORY_REF (block, 1)));
  1002.   SCHEME_OBJECT * location = (MEMORY_LOC (block, offset));
  1003.   SCHEME_OBJECT * closptr = (location - objdist);
  1004.   SCHEME_OBJECT * end_closptr = (MEMORY_LOC (block, (2 + nmv_length)));
  1005.   SCHEME_OBJECT entry_offset, * area_end;
  1006.   char * word_ptr;
  1007.   long count;
  1008.  
  1009.   nmv_length -= (end_closptr - closptr);
  1010.   while (closptr < end_closptr)
  1011.   {
  1012.     while ((* closptr) == ((SCHEME_OBJECT) 0))
  1013.       closptr ++;
  1014.     closptr ++;
  1015.     count = (MANIFEST_CLOSURE_COUNT (closptr));
  1016.     word_ptr = (FIRST_MANIFEST_CLOSURE_ENTRY (closptr));
  1017.     area_end = (MANIFEST_CLOSURE_END (closptr, count));
  1018.     while ((--count) >= 0)
  1019.     {
  1020.       closptr = ((SCHEME_OBJECT *) word_ptr);
  1021.       word_ptr = (NEXT_MANIFEST_CLOSURE_ENTRY (word_ptr));
  1022.       EXTRACT_CLOSURE_ENTRY_ADDRESS (entry_offset, closptr);
  1023.       entry_offset = ((SCHEME_OBJECT)
  1024.               (((long) closptr) - ((long) entry_offset)));
  1025.       STORE_CLOSURE_ENTRY_ADDRESS (entry_offset, closptr);
  1026.     }
  1027.     closptr = &area_end[1];
  1028.   }
  1029.  
  1030.   MEMORY_SET (block, 1, (MAKE_OBJECT (TC_MANIFEST_NM_VECTOR, nmv_length)));
  1031.   return (PRIM_DONE);
  1032. }
  1033.  
  1034. static Boolean linking_cc_block_p = false;
  1035.  
  1036. static void
  1037. DEFUN (abort_link_cc_block, (ap), PTR ap)
  1038. {
  1039.   linking_cc_block_p = (* ((Boolean *) (ap)));
  1040.   return;
  1041. }
  1042.  
  1043. /* Core of comutil_link and comp_link_caches_restart. */
  1044.  
  1045. static long
  1046. DEFUN (link_cc_block,
  1047.        (block_address, offset, last_header_offset,
  1048.     sections, original_count, ret_add),
  1049.        register SCHEME_OBJECT * block_address AND
  1050.        register long offset AND
  1051.        long last_header_offset AND
  1052.        long sections AND
  1053.        long original_count AND
  1054.        instruction * ret_add)
  1055. {
  1056.   Boolean execute_p = false;
  1057.   register long entry_size, count;
  1058.   SCHEME_OBJECT block;
  1059.   SCHEME_OBJECT header;
  1060.   long result, kind, total_count;
  1061.   long EXFUN ((* cache_handler), (SCHEME_OBJECT, SCHEME_OBJECT, long));
  1062.  
  1063.   transaction_begin ();
  1064.   {
  1065.     Boolean * ap = (dstack_alloc (sizeof (Boolean)));
  1066.     *ap = linking_cc_block_p;
  1067.     transaction_record_action (tat_abort, abort_link_cc_block, ap);
  1068.   }
  1069.   linking_cc_block_p = true;
  1070.  
  1071.   result = PRIM_DONE;
  1072.   block = (MAKE_CC_BLOCK (block_address));
  1073.  
  1074.   while ((--sections) >= 0)
  1075.   {
  1076.     SCHEME_OBJECT * scan = &(block_address[last_header_offset]);
  1077.     header = (*scan);
  1078.  
  1079.     kind = (READ_LINKAGE_KIND (header));
  1080.     switch (kind)
  1081.     {
  1082.       case OPERATOR_LINKAGE_KIND:
  1083.     cache_handler = compiler_cache_operator;
  1084.  
  1085.       handle_operator:
  1086.         execute_p = true;
  1087.     entry_size = EXECUTE_CACHE_ENTRY_SIZE;
  1088.     START_OPERATOR_RELOCATION (scan);
  1089.     count = (READ_OPERATOR_LINKAGE_COUNT (header));
  1090.     break;
  1091.  
  1092.       case GLOBAL_OPERATOR_LINKAGE_KIND:
  1093.     cache_handler = compiler_cache_global_operator;
  1094.     goto handle_operator;
  1095.  
  1096.       case ASSIGNMENT_LINKAGE_KIND:
  1097.     cache_handler = compiler_cache_assignment;
  1098.     goto handle_reference;
  1099.  
  1100.       case REFERENCE_LINKAGE_KIND:
  1101.     cache_handler = compiler_cache_lookup;
  1102.       handle_reference:
  1103.     execute_p = false;
  1104.     entry_size = 1;
  1105.     count = (READ_CACHE_LINKAGE_COUNT (header));
  1106.     break;
  1107.  
  1108.       case CLOSURE_PATTERN_LINKAGE_KIND:
  1109.     cache_handler = compiler_link_closure_pattern;
  1110.     /* Not really a reference, but the same format. */
  1111.     goto handle_reference;
  1112.  
  1113.       default:
  1114.     offset += 1;
  1115.     total_count = (READ_CACHE_LINKAGE_COUNT (header));
  1116.     count = (total_count - 1);
  1117.     result = ERR_COMPILED_CODE_ERROR;
  1118.     goto back_out;
  1119.     }
  1120.  
  1121.     /* This accomodates the re-entry case after a GC.
  1122.        It undoes the effects of the "smash header" code below.
  1123.      */
  1124.  
  1125.     if ((OBJECT_TYPE (header)) == TC_LINKAGE_SECTION)
  1126.     {
  1127.       count = (original_count - count);
  1128.       total_count = original_count;
  1129.     }
  1130.     else
  1131.     {
  1132.       total_count = count;
  1133.       if (execute_p)
  1134.     offset += (FIRST_OPERATOR_LINKAGE_OFFSET - 1);
  1135.     }
  1136.  
  1137.     block_address[last_header_offset] =
  1138.       (MAKE_LINKAGE_SECTION_HEADER (kind, total_count));
  1139.     for (offset += 1; ((--count) >= 0); offset += entry_size)
  1140.     {
  1141.       SCHEME_OBJECT info;    /* A symbol or a fixnum */
  1142.  
  1143.       if (! execute_p)
  1144.     info = (block_address[offset]);
  1145.       else
  1146.     EXTRACT_EXECUTE_CACHE_SYMBOL (info, &(block_address[offset]));
  1147.  
  1148.       result = ((* cache_handler) (info, block, offset));
  1149.       if (result != PRIM_DONE)
  1150.       {
  1151.         /* Save enough state to continue.
  1152.        Note that offset is decremented to compensate for it being
  1153.        incremented by the for loop header.
  1154.        Similary sections and count are incremented to compensate
  1155.        for loop headers pre-decrementing.
  1156.        count is saved although it's not needed for re-entry to
  1157.        match the assembly language versions.
  1158.      */
  1159.  
  1160.   back_out:
  1161.     if (execute_p)
  1162.       END_OPERATOR_RELOCATION (&(block_address[offset]));
  1163.         STACK_PUSH (ENTRY_TO_OBJECT (ret_add));
  1164.         STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (sections + 1));
  1165.         STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (last_header_offset));
  1166.         STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (offset - 1));
  1167.         STACK_PUSH (block);
  1168.     STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (count + 1));
  1169.     STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (total_count));
  1170.  
  1171.         Store_Expression (SHARP_F);
  1172.         Store_Return (RC_COMP_LINK_CACHES_RESTART);
  1173.         Save_Cont ();
  1174.  
  1175.         /* Smash header for the garbage collector.
  1176.            It is smashed back on return.  See the comment above.
  1177.          */
  1178.  
  1179.         block_address[last_header_offset] =
  1180.           (MAKE_LINKAGE_SECTION_HEADER (kind, (total_count - (count + 1))));
  1181.     goto exit_proc;
  1182.       }
  1183.     }
  1184.     if (execute_p)
  1185.       END_OPERATOR_RELOCATION (&(block_address[offset - 1]));
  1186.     last_header_offset = offset;
  1187.   }
  1188.  
  1189. exit_proc:
  1190.   /* Rather than commit, since we want to undo */
  1191.   transaction_abort ();
  1192. #if defined(FLUSH_I_CACHE_REGION) || defined(PUSH_D_CACHE_REGION)
  1193.   {
  1194.     SCHEME_OBJECT * ret_add_block;
  1195.     unsigned long block_len = (((unsigned long) (* block_address)) + 1);
  1196.     
  1197.     Get_Compiled_Block (ret_add_block, ((SCHEME_OBJECT *) ret_add));
  1198.     if (ret_add_block == block_address)
  1199.       {
  1200. #ifdef FLUSH_I_CACHE_REGION
  1201.     FLUSH_I_CACHE_REGION (block_address, block_len);
  1202. #endif
  1203.       }
  1204.     else
  1205.       {
  1206. #ifdef PUSH_D_CACHE_REGION
  1207.     PUSH_D_CACHE_REGION (block_address, block_len);
  1208. #endif
  1209.       }
  1210.   }
  1211. #endif
  1212.   return (result);
  1213. }
  1214.  
  1215. /*
  1216.   comutil_link is used to initialize all the variable cache slots for
  1217.   a compiled code block.  It is called at load time, by the compiled
  1218.   code itself.  It assumes that the return address has been saved on
  1219.   the stack.
  1220.   If an error occurs during linking, or an interrupt must be processed
  1221.   (because of the need to GC, etc.), it backs out and sets up a return
  1222.   code that will invoke comp_link_caches_restart when the error/interrupt
  1223.   processing is done.
  1224. */
  1225.  
  1226. SCHEME_UTILITY utility_result
  1227. DEFNX (comutil_link,
  1228.        (ret_add_raw, block_address_raw, constant_address_raw, sections),
  1229.        SCHEME_ADDR ret_add_raw
  1230.        AND SCHEME_ADDR block_address_raw
  1231.        AND SCHEME_ADDR constant_address_raw
  1232.        AND long sections)
  1233. {
  1234.   instruction * ret_add
  1235.     = ((instruction *) (SCHEME_ADDR_TO_ADDR (ret_add_raw)));
  1236.   SCHEME_OBJECT * block_address
  1237.     = (SCHEME_ADDR_TO_ADDR (block_address_raw));
  1238.   SCHEME_OBJECT * constant_address
  1239.     = (SCHEME_ADDR_TO_ADDR (constant_address_raw));
  1240.   long offset;
  1241.  
  1242. #ifdef AUTOCLOBBER_BUG
  1243.   block_address[OBJECT_DATUM (* block_address)] = Regs[REGBLOCK_ENV];
  1244. #endif
  1245.  
  1246.   offset = (constant_address - block_address);
  1247.  
  1248.   RETURN_UNLESS_EXCEPTION
  1249.     ((link_cc_block (block_address,
  1250.                      offset,
  1251.                      offset,
  1252.                      sections,
  1253.                      -1,
  1254.                      ret_add)),
  1255.      ret_add);
  1256. }
  1257.  
  1258. /*
  1259.   comp_link_caches_restart is used to continue the linking process
  1260.   started by comutil_link after the garbage collector has run.
  1261.   It expects the top of the stack to be as left by link_cc_block.
  1262.  */
  1263.  
  1264. C_TO_SCHEME long
  1265. DEFUN_VOID (comp_link_caches_restart)
  1266. {
  1267.   SCHEME_OBJECT block, environment;
  1268.   long original_count, offset, last_header_offset, sections, code;
  1269.   instruction * ret_add;
  1270.  
  1271.   original_count = (OBJECT_DATUM (STACK_POP()));
  1272.   (void) STACK_POP ();        /* Loop count, for debugger */
  1273.   block = (STACK_POP ());
  1274.   environment = (compiled_block_environment (block));
  1275.   Store_Env (environment);
  1276.   offset = (OBJECT_DATUM (STACK_POP ()));
  1277.   last_header_offset = (OBJECT_DATUM (STACK_POP ()));
  1278.   sections = (OBJECT_DATUM (STACK_POP ()));
  1279.   ret_add = ((instruction *) (OBJECT_ADDRESS (STACK_POP ())));
  1280.   code = (link_cc_block ((OBJECT_ADDRESS (block)),
  1281.                          offset,
  1282.                          last_header_offset,
  1283.                          sections,
  1284.                          original_count,
  1285.                          ret_add));
  1286.   if (code == PRIM_DONE)
  1287.     /* Return to the block being linked. */
  1288.     ENTER_SCHEME (ret_add);
  1289.   else
  1290.   {
  1291.     /* Another GC or error.  We should be ready for back-out. */
  1292.     return (code);
  1293.   }
  1294. }
  1295.  
  1296. /* TRAMPOLINE code
  1297.    When a free variable appears in operator position in compiled code,
  1298.    there must be a directly callable procedure in the corresponding
  1299.    execute cache cell.  If, at link time, there is no appropriate
  1300.    value for the free variable, a fake compiled Scheme procedure that
  1301.    calls one of these procedures will be placed into the cell instead.
  1302.  
  1303.    The trampolines themselves are made by make_uuo_link,
  1304.    make_fake_uuo_link, and coerce_to_compiled.  The trampoline looks
  1305.    like a Scheme closure, containing some code to jump to one of
  1306.    these procedures and additional information to be used by the
  1307.    procedure.
  1308.  
  1309.    These procedures expect a single argument, the address of the
  1310.    information block where they can find the relevant data, typically
  1311.    the procedure to invoke and the number of arguments to invoke it
  1312.    with.
  1313. */
  1314.  
  1315. SCHEME_UTILITY utility_result
  1316. DEFNX (comutil_operator_apply_trap,
  1317.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  1318.        SCHEME_ADDR tramp_data_raw
  1319.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  1320. {
  1321.   SCHEME_OBJECT * tramp_data = (SCHEME_ADDR_TO_ADDR (tramp_data_raw));
  1322.  
  1323.   /* Used by coerce_to_compiled.  TRAMPOLINE_K_APPLY */
  1324.  
  1325.   return (comutil_apply ((tramp_data[0]),
  1326.              (OBJECT_DATUM (tramp_data[1])),
  1327.              0, 0));
  1328. }
  1329.  
  1330. SCHEME_UTILITY utility_result
  1331. DEFNX (comutil_operator_arity_trap,
  1332.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  1333.        SCHEME_ADDR tramp_data_raw
  1334.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  1335. {
  1336.   SCHEME_OBJECT * tramp_data = (SCHEME_ADDR_TO_ADDR (tramp_data_raw));
  1337.  
  1338.   /* Linker saw an argument count mismatch. TRAMPOLINE_K_ARITY */
  1339.  
  1340.   return (comutil_apply ((tramp_data[0]),
  1341.              (OBJECT_DATUM (tramp_data[1])),
  1342.              0, 0));
  1343. }
  1344.  
  1345. SCHEME_UTILITY utility_result
  1346. DEFNX (comutil_operator_entity_trap,
  1347.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  1348.        SCHEME_ADDR tramp_data_raw
  1349.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  1350. {
  1351.   SCHEME_OBJECT * tramp_data = (SCHEME_ADDR_TO_ADDR (tramp_data_raw));
  1352.  
  1353.   /* Linker saw an entity to be applied. TRAMPOLINE_K_ENTITY */
  1354.  
  1355.   return (comutil_apply ((tramp_data[0]),
  1356.              (OBJECT_DATUM (tramp_data[1])),
  1357.              0, 0));
  1358. }
  1359.  
  1360. SCHEME_UTILITY utility_result
  1361. DEFNX (comutil_operator_interpreted_trap,
  1362.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  1363.        SCHEME_ADDR tramp_data_raw
  1364.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  1365. {
  1366.   SCHEME_OBJECT * tramp_data = (SCHEME_ADDR_TO_ADDR (tramp_data_raw));
  1367.  
  1368.   /* Linker saw an interpreted procedure or a procedure that it cannot
  1369.      link directly.  TRAMPOLINE_K_INTERPRETED
  1370.    */
  1371.  
  1372.   return (comutil_apply ((tramp_data[0]),
  1373.              (OBJECT_DATUM (tramp_data[1])),
  1374.              0, 0));
  1375. }
  1376.  
  1377. SCHEME_UTILITY utility_result
  1378. DEFNX (comutil_operator_lexpr_trap,
  1379.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  1380.        SCHEME_ADDR tramp_data_raw
  1381.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  1382. {
  1383.   SCHEME_OBJECT * tramp_data = (SCHEME_ADDR_TO_ADDR (tramp_data_raw));
  1384.  
  1385.   /* Linker saw a primitive of arbitrary number of arguments.
  1386.      TRAMPOLINE_K_LEXPR_PRIMITIVE
  1387.    */
  1388.  
  1389.   Regs[REGBLOCK_LEXPR_ACTUALS] =
  1390.     ((SCHEME_OBJECT) ((OBJECT_DATUM (tramp_data[1])) - 1));
  1391.   return (comutil_primitive_lexpr_apply ((tramp_data[0]), 0, 0, 0));
  1392. }
  1393.  
  1394. SCHEME_UTILITY utility_result
  1395. DEFNX (comutil_operator_primitive_trap,
  1396.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  1397.        SCHEME_ADDR tramp_data_raw
  1398.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  1399. {
  1400.   SCHEME_OBJECT * tramp_data = (SCHEME_ADDR_TO_ADDR (tramp_data_raw));
  1401.  
  1402.   /* Linker saw a primitive of fixed matching arity. TRAMPOLINE_K_PRIMITIVE */
  1403.  
  1404.   return (comutil_primitive_apply ((tramp_data[0]), 0, 0, 0));
  1405. }
  1406.  
  1407. extern SCHEME_OBJECT EXFUN (compiler_var_error,
  1408.                 (SCHEME_OBJECT, SCHEME_OBJECT));
  1409.  
  1410. /* The linker either couldn't find a binding or the binding was
  1411.    unassigned, unbound, or a deep-bound (parallel processor) fluid.
  1412.    This must report the correct name of the missing variable and the
  1413.    environment in which the lookup begins for the error cases, or do
  1414.    the correct deep reference for fluids.
  1415.  
  1416.    "extension" is the linker object corresponding to the operator
  1417.    variable (it contains the actual value cell, the name, and linker
  1418.    tables). code_block and offset point to the cache cell in question.
  1419.    tramp_data contains extension, code_block, offset.  TRAMPOLINE_K_LOOKUP
  1420. */
  1421.  
  1422. SCHEME_UTILITY utility_result
  1423. DEFNX (comutil_operator_lookup_trap,
  1424.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  1425.        SCHEME_ADDR tramp_data_raw
  1426.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  1427. {
  1428.   extern long EXFUN (complr_operator_reference_trap,
  1429.              (SCHEME_OBJECT *, SCHEME_OBJECT));
  1430.   SCHEME_OBJECT * tramp_data = (SCHEME_ADDR_TO_ADDR (tramp_data_raw));
  1431.   SCHEME_OBJECT true_operator, * cache_cell;
  1432.   long code, nargs;
  1433.  
  1434.   code = (complr_operator_reference_trap (&true_operator, (tramp_data[0])));
  1435.   cache_cell = (MEMORY_LOC ((tramp_data[1]),
  1436.                 (OBJECT_DATUM (tramp_data[2]))));
  1437.   EXTRACT_EXECUTE_CACHE_ARITY (nargs, cache_cell);
  1438.   if (code == PRIM_DONE)
  1439.     return (comutil_apply (true_operator, nargs, 0, 0));
  1440.   else /* Error or interrupt */
  1441.   {
  1442.     SCHEME_OBJECT trampoline, environment, name;
  1443.  
  1444.     /* This could be done by bumpint tramp_data to the entry point.
  1445.        It would probably be better.
  1446.      */
  1447.     EXTRACT_EXECUTE_CACHE_ADDRESS (trampoline, cache_cell);
  1448.     environment = (compiled_block_environment (tramp_data[1]));
  1449.     name = (compiler_var_error ((tramp_data[0]), environment));
  1450.  
  1451.     STACK_PUSH (ENTRY_TO_OBJECT (SCHEME_ADDR_TO_ADDR (trampoline)));
  1452.     STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (nargs));    /* For debugger */
  1453.     STACK_PUSH (environment);                /* For debugger */
  1454.     STACK_PUSH (name);                    /* For debugger */
  1455.     Store_Expression (SHARP_F);
  1456.     Store_Return (RC_COMP_OP_REF_TRAP_RESTART);
  1457.     Save_Cont ();
  1458.     RETURN_TO_C (code);
  1459.   }
  1460. }
  1461.  
  1462. /*
  1463.   Re-start after processing an error/interrupt encountered in the previous
  1464.   utility.
  1465.   Extract the new trampoline or procedure (the user may have defined the
  1466.   missing variable) and invoke it.
  1467.  */
  1468.  
  1469. C_TO_SCHEME long
  1470. DEFUN_VOID (comp_op_lookup_trap_restart)
  1471. {
  1472.   SCHEME_OBJECT * old_trampoline, code_block, new_procedure;
  1473.   long offset;
  1474.  
  1475.   /* Discard name, env. and nargs */
  1476.  
  1477.   Stack_Pointer = (STACK_LOC (3));
  1478.   old_trampoline = (OBJECT_ADDRESS (STACK_POP ()));
  1479.   code_block = ((TRAMPOLINE_STORAGE (old_trampoline))[1]);
  1480.   offset = (OBJECT_DATUM ((TRAMPOLINE_STORAGE (old_trampoline))[2]));
  1481.   EXTRACT_EXECUTE_CACHE_ADDRESS (new_procedure,
  1482.                  (MEMORY_LOC (code_block, offset)));
  1483.   ENTER_SCHEME (SCHEME_ADDR_TO_ADDR (new_procedure));
  1484. }
  1485.  
  1486. /* ARITY Mismatch handling
  1487.    These receive the entry point as an argument and must fill the
  1488.    Scheme stack with the missing unassigned values.
  1489.    They are invoked by TRAMPOLINE_K_n_m where n and m are the same
  1490.    as in the name of the procedure.
  1491.    The single item of information in the trampoline data area is
  1492.    the real procedure to invoke.  All the arguments are on the
  1493.    Scheme stack.
  1494.  */
  1495.  
  1496. SCHEME_UTILITY utility_result
  1497. DEFNX (comutil_operator_1_0_trap,
  1498.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  1499.        SCHEME_ADDR tramp_data_raw
  1500.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  1501. {
  1502.   SCHEME_OBJECT * tramp_data = (SCHEME_ADDR_TO_ADDR (tramp_data_raw));
  1503.  
  1504.   STACK_PUSH (UNASSIGNED_OBJECT);
  1505.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1506. }
  1507.  
  1508. SCHEME_UTILITY utility_result
  1509. DEFNX (comutil_operator_2_1_trap,
  1510.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  1511.        SCHEME_ADDR tramp_data_raw
  1512.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  1513. {
  1514.   SCHEME_OBJECT Top;
  1515.   SCHEME_OBJECT * tramp_data = (SCHEME_ADDR_TO_ADDR (tramp_data_raw));
  1516.  
  1517.   Top = (STACK_POP ());
  1518.   STACK_PUSH (UNASSIGNED_OBJECT);
  1519.   STACK_PUSH (Top);
  1520.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1521. }
  1522.  
  1523. SCHEME_UTILITY utility_result
  1524. DEFNX (comutil_operator_2_0_trap,
  1525.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  1526.        SCHEME_ADDR tramp_data_raw
  1527.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  1528. {
  1529.   SCHEME_OBJECT * tramp_data = (SCHEME_ADDR_TO_ADDR (tramp_data_raw));
  1530.  
  1531.   STACK_PUSH (UNASSIGNED_OBJECT);
  1532.   STACK_PUSH (UNASSIGNED_OBJECT);
  1533.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1534. }
  1535.  
  1536. SCHEME_UTILITY utility_result
  1537. DEFNX (comutil_operator_3_2_trap,
  1538.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  1539.        SCHEME_ADDR tramp_data_raw
  1540.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  1541. {
  1542.   SCHEME_OBJECT Top, Next;
  1543.   SCHEME_OBJECT * tramp_data = (SCHEME_ADDR_TO_ADDR (tramp_data_raw));
  1544.  
  1545.   Top = (STACK_POP ());
  1546.   Next = (STACK_POP ());
  1547.   STACK_PUSH (UNASSIGNED_OBJECT);
  1548.   STACK_PUSH (Next);
  1549.   STACK_PUSH (Top);
  1550.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1551. }
  1552.  
  1553. SCHEME_UTILITY utility_result
  1554. DEFNX (comutil_operator_3_1_trap,
  1555.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  1556.        SCHEME_ADDR tramp_data_raw
  1557.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  1558. {
  1559.   SCHEME_OBJECT Top;
  1560.   SCHEME_OBJECT * tramp_data = (SCHEME_ADDR_TO_ADDR (tramp_data_raw));
  1561.  
  1562.   Top = (STACK_POP ());
  1563.   STACK_PUSH (UNASSIGNED_OBJECT);
  1564.   STACK_PUSH (UNASSIGNED_OBJECT);
  1565.   STACK_PUSH (Top);
  1566.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1567. }
  1568.  
  1569. SCHEME_UTILITY utility_result
  1570. DEFNX (comutil_operator_3_0_trap,
  1571.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  1572.        SCHEME_ADDR tramp_data_raw
  1573.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  1574. {
  1575.   SCHEME_OBJECT * tramp_data = (SCHEME_ADDR_TO_ADDR (tramp_data_raw));
  1576.  
  1577.   STACK_PUSH (UNASSIGNED_OBJECT);
  1578.   STACK_PUSH (UNASSIGNED_OBJECT);
  1579.   STACK_PUSH (UNASSIGNED_OBJECT);
  1580.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1581. }
  1582.  
  1583. SCHEME_UTILITY utility_result
  1584. DEFNX (comutil_operator_4_3_trap,
  1585.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  1586.        SCHEME_ADDR tramp_data_raw
  1587.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  1588. {
  1589.   SCHEME_OBJECT Top, Middle, Bottom;
  1590.   SCHEME_OBJECT * tramp_data = (SCHEME_ADDR_TO_ADDR (tramp_data_raw));
  1591.  
  1592.   Top = (STACK_POP ());
  1593.   Middle = (STACK_POP ());
  1594.   Bottom = (STACK_POP ());
  1595.  
  1596.   STACK_PUSH (UNASSIGNED_OBJECT);
  1597.   STACK_PUSH (Bottom);
  1598.   STACK_PUSH (Middle);
  1599.   STACK_PUSH (Top);
  1600.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1601. }
  1602.  
  1603. SCHEME_UTILITY utility_result
  1604. DEFNX (comutil_operator_4_2_trap,
  1605.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  1606.        SCHEME_ADDR tramp_data_raw
  1607.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  1608. {
  1609.   SCHEME_OBJECT Top, Next;
  1610.   SCHEME_OBJECT * tramp_data = (SCHEME_ADDR_TO_ADDR (tramp_data_raw));
  1611.  
  1612.   Top = (STACK_POP ());
  1613.   Next = (STACK_POP ());
  1614.   STACK_PUSH (UNASSIGNED_OBJECT);
  1615.   STACK_PUSH (UNASSIGNED_OBJECT);
  1616.   STACK_PUSH (Next);
  1617.   STACK_PUSH (Top);
  1618.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1619. }
  1620.  
  1621. SCHEME_UTILITY utility_result
  1622. DEFNX (comutil_operator_4_1_trap,
  1623.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  1624.        SCHEME_ADDR tramp_data_raw
  1625.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  1626. {
  1627.   SCHEME_OBJECT Top;
  1628.   SCHEME_OBJECT * tramp_data = (SCHEME_ADDR_TO_ADDR (tramp_data_raw));
  1629.  
  1630.   Top = (STACK_POP ());
  1631.   STACK_PUSH (UNASSIGNED_OBJECT);
  1632.   STACK_PUSH (UNASSIGNED_OBJECT);
  1633.   STACK_PUSH (UNASSIGNED_OBJECT);
  1634.   STACK_PUSH (Top);
  1635.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1636. }
  1637.  
  1638. SCHEME_UTILITY utility_result
  1639. DEFNX (comutil_operator_4_0_trap,
  1640.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  1641.        SCHEME_ADDR tramp_data_raw
  1642.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  1643. {
  1644.   SCHEME_OBJECT * tramp_data = (SCHEME_ADDR_TO_ADDR (tramp_data_raw));
  1645.  
  1646.   STACK_PUSH (UNASSIGNED_OBJECT);
  1647.   STACK_PUSH (UNASSIGNED_OBJECT);
  1648.   STACK_PUSH (UNASSIGNED_OBJECT);
  1649.   STACK_PUSH (UNASSIGNED_OBJECT);
  1650.   RETURN_TO_SCHEME (OBJECT_ADDRESS (tramp_data[0]));
  1651. }
  1652.  
  1653. /* INTERRUPT/GC from Scheme
  1654.  
  1655.    These procedures are called from compiled code at the start
  1656.    (respectively) of a procedure or continuation if an interrupt has
  1657.    been detected.  They must not be called unless there is an
  1658.    interrupt to be serviced.
  1659.  
  1660.    The code that handles RC_COMP_INTERRUPT_RESTART in "interp.c" will
  1661.    return control to comp_interrupt_restart (below).  This assumes
  1662.    that the Scheme stack contains a compiled code entry address
  1663.    (start of continuation, procedure, etc.).  The Expression register
  1664.    saved with the continuation is a piece of state that will be
  1665.    returned to Val and Env (both) upon return.
  1666.  */
  1667.  
  1668. #define MAYBE_REQUEST_INTERRUPTS()                    \
  1669. {                                    \
  1670.   if (Free >= MemTop)                            \
  1671.     Request_GC (Free - MemTop);                        \
  1672.   if (Stack_Pointer <= Stack_Guard)                    \
  1673.     REQUEST_INTERRUPT (INT_Stack_Overflow);                \
  1674. }
  1675.  
  1676. static utility_result
  1677. DEFUN (compiler_interrupt_common, (entry_point_raw, state),
  1678.        SCHEME_ADDR entry_point_raw AND
  1679.        SCHEME_OBJECT state)
  1680. {
  1681.   MAYBE_REQUEST_INTERRUPTS ();
  1682.   if (entry_point_raw != ((SCHEME_ADDR) 0))
  1683.   {
  1684.     instruction * entry_point
  1685.       = ((instruction *) (SCHEME_ADDR_TO_ADDR (entry_point_raw)));
  1686.     STACK_PUSH (ENTRY_TO_OBJECT (entry_point));
  1687.   }
  1688.   STACK_PUSH (state);
  1689.   Store_Expression (SHARP_F);
  1690.   Store_Return (RC_COMP_INTERRUPT_RESTART);
  1691.   Save_Cont ();
  1692.   RETURN_TO_C (PRIM_INTERRUPT);
  1693. }
  1694.  
  1695. SCHEME_UTILITY utility_result
  1696. DEFNX (comutil_interrupt_closure, (ignore_1, ignore_2, ignore_3, ignore_4),
  1697.        long ignore_1 AND
  1698.        long ignore_2 AND
  1699.        long ignore_3 AND
  1700.        long ignore_4)
  1701. {
  1702.   return (compiler_interrupt_common (0, SHARP_F));
  1703. }
  1704.  
  1705. SCHEME_UTILITY utility_result
  1706. DEFNX (comutil_interrupt_dlink,
  1707.        (entry_point_raw, dlink_raw, ignore_3, ignore_4),
  1708.        SCHEME_ADDR entry_point_raw AND
  1709.        SCHEME_ADDR dlink_raw AND
  1710.        long ignore_3 AND
  1711.        long ignore_4)
  1712. {
  1713.   SCHEME_OBJECT * dlink = (SCHEME_ADDR_TO_ADDR (dlink_raw));
  1714.   return
  1715.     (compiler_interrupt_common
  1716.      (entry_point_raw, (MAKE_POINTER_OBJECT (TC_STACK_ENVIRONMENT, dlink))));
  1717. }
  1718.  
  1719. SCHEME_UTILITY utility_result
  1720. DEFNX (comutil_interrupt_procedure,
  1721.        (entry_point_raw, ignore_2, ignore_3, ignore_4),
  1722.        SCHEME_ADDR entry_point_raw AND
  1723.        long ignore_2 AND
  1724.        long ignore_3 AND
  1725.        long ignore_4)
  1726. {
  1727.   return (compiler_interrupt_common (entry_point_raw, SHARP_F));
  1728. }
  1729.  
  1730. /* Val has live data, and there is no entry address on the stack */
  1731.  
  1732. SCHEME_UTILITY utility_result
  1733. DEFNX (comutil_interrupt_continuation,
  1734.        (return_address_raw, ignore_2, ignore_3, ignore_4),
  1735.        SCHEME_ADDR return_address_raw AND
  1736.        long ignore_2 AND
  1737.        long ignore_3 AND
  1738.        long ignore_4)
  1739. {
  1740.   return (compiler_interrupt_common (return_address_raw, Val));
  1741. }
  1742.  
  1743. /* Env has live data; no entry point on the stack */
  1744.  
  1745. SCHEME_UTILITY utility_result
  1746. DEFNX (comutil_interrupt_ic_procedure,
  1747.        (entry_point_raw, ignore_2, ignore_3, ignore_4),
  1748.        SCHEME_ADDR entry_point_raw AND
  1749.        long ignore_2 AND
  1750.        long ignore_3 AND
  1751.        long ignore_4)
  1752. {
  1753.   return (compiler_interrupt_common (entry_point_raw, (Fetch_Env ())));
  1754. }
  1755.  
  1756. SCHEME_UTILITY utility_result
  1757. DEFNX (comutil_interrupt_continuation_2,
  1758.        (ignore_1, ignore_2, ignore_3, ignore_4),
  1759.        long ignore_1 AND
  1760.        long ignore_2 AND
  1761.        long ignore_3 AND
  1762.        long ignore_4)
  1763. {
  1764.   return (compiler_interrupt_common (0, Val));
  1765. }
  1766.  
  1767. C_TO_SCHEME long
  1768. DEFUN_VOID (comp_interrupt_restart)
  1769. {
  1770.   SCHEME_OBJECT state;
  1771.  
  1772.   state = (STACK_POP ());
  1773.   Store_Env (state);
  1774.   Val = state;
  1775.   ENTER_SCHEME (OBJECT_ADDRESS (STACK_POP ()));
  1776. }
  1777.  
  1778. /* Other TRAPS */
  1779.  
  1780. /* Assigning a variable that has a trap in it (except unassigned) */
  1781.  
  1782. SCHEME_UTILITY utility_result
  1783. DEFNX (comutil_assignment_trap,
  1784.        (return_address_raw, extension_addr_raw, value, ignore_4),
  1785.        SCHEME_ADDR return_address_raw
  1786.        AND SCHEME_ADDR extension_addr_raw
  1787.        AND SCHEME_OBJECT value
  1788.        AND long ignore_4)
  1789. {
  1790.   extern long EXFUN (compiler_assignment_trap, (SCHEME_OBJECT, SCHEME_OBJECT));
  1791.   instruction * return_address
  1792.     = ((instruction *) (SCHEME_ADDR_TO_ADDR (return_address_raw)));
  1793.   SCHEME_OBJECT * extension_addr = (SCHEME_ADDR_TO_ADDR (extension_addr_raw));
  1794.   SCHEME_OBJECT extension;
  1795.   long code;
  1796.  
  1797.   extension = (MAKE_POINTER_OBJECT (TC_QUAD, extension_addr));
  1798.   code = (compiler_assignment_trap (extension, value));
  1799.   if (code == PRIM_DONE)
  1800.     RETURN_TO_SCHEME (return_address);
  1801.   else
  1802.   {
  1803.     SCHEME_OBJECT block, environment, name, sra;
  1804.  
  1805.     sra = (ENTRY_TO_OBJECT (return_address));
  1806.     STACK_PUSH (sra);
  1807.     STACK_PUSH (value);
  1808.     block = (compiled_entry_to_block (sra));
  1809.     environment = (compiled_block_environment (block));
  1810.     STACK_PUSH (environment);
  1811.     name = (compiler_var_error (extension, environment));
  1812.     STACK_PUSH (name);
  1813.     Store_Expression (SHARP_F);
  1814.     Store_Return (RC_COMP_ASSIGNMENT_TRAP_RESTART);
  1815.     Save_Cont ();
  1816.     RETURN_TO_C (code);
  1817.   }
  1818. }
  1819.  
  1820. C_TO_SCHEME long
  1821. DEFUN_VOID (comp_assignment_trap_restart)
  1822. {
  1823.   extern long EXFUN (Symbol_Lex_Set,
  1824.              (SCHEME_OBJECT, SCHEME_OBJECT, SCHEME_OBJECT));
  1825.   SCHEME_OBJECT name, environment, value;
  1826.   long code;
  1827.  
  1828.   name = (STACK_POP ());
  1829.   environment = (STACK_POP ());
  1830.   value = (STACK_POP ());
  1831.   code = (Symbol_Lex_Set (environment, name, value));
  1832.   if (code == PRIM_DONE)
  1833.     ENTER_SCHEME (OBJECT_ADDRESS (STACK_POP ()));
  1834.   else
  1835.   {
  1836.     STACK_PUSH (value);
  1837.     STACK_PUSH (environment);
  1838.     STACK_PUSH (name);
  1839.     Store_Expression (SHARP_F);
  1840.     Store_Return (RC_COMP_ASSIGNMENT_TRAP_RESTART);
  1841.     Save_Cont ();
  1842.     return (code);
  1843.   }
  1844. }
  1845.  
  1846. SCHEME_UTILITY utility_result
  1847. DEFNX (comutil_cache_lookup_apply,
  1848.        (extension_addr_raw, block_address_raw, nactuals, ignore_4),
  1849.        SCHEME_ADDR extension_addr_raw
  1850.        AND SCHEME_ADDR block_address_raw
  1851.        AND long nactuals
  1852.        AND long ignore_4)
  1853. {
  1854.   extern long EXFUN (compiler_lookup_trap, (SCHEME_OBJECT));
  1855.   SCHEME_OBJECT * extension_addr = (SCHEME_ADDR_TO_ADDR (extension_addr_raw));
  1856.   SCHEME_OBJECT * block_address = (SCHEME_ADDR_TO_ADDR (block_address_raw));
  1857.   SCHEME_OBJECT extension;
  1858.   long code;
  1859.  
  1860.   extension = (MAKE_POINTER_OBJECT (TC_QUAD, extension_addr));
  1861.   code = (compiler_lookup_trap (extension));
  1862.   if (code == PRIM_DONE)
  1863.     return (comutil_apply (Val, nactuals, 0, 0));
  1864.   else
  1865.   {
  1866.     SCHEME_OBJECT block, environment, name;
  1867.  
  1868.     block = (MAKE_CC_BLOCK (block_address));
  1869.     STACK_PUSH (block);
  1870.     STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (nactuals));
  1871.     environment = (compiled_block_environment (block));
  1872.     STACK_PUSH (environment);
  1873.     name = (compiler_var_error (extension, environment));
  1874.     STACK_PUSH (name);
  1875.     Store_Expression (SHARP_F);
  1876.     Store_Return (RC_COMP_CACHE_REF_APPLY_RESTART);
  1877.     Save_Cont ();
  1878.     RETURN_TO_C (code);
  1879.   }
  1880. }
  1881.  
  1882. C_TO_SCHEME long
  1883. DEFUN_VOID (comp_cache_lookup_apply_restart)
  1884. {
  1885.   extern long EXFUN (Symbol_Lex_Ref, (SCHEME_OBJECT, SCHEME_OBJECT));
  1886.   SCHEME_OBJECT name, environment;
  1887.   long code;
  1888.  
  1889.   name = (STACK_POP ());
  1890.   environment = (STACK_POP ());
  1891.   code = (Symbol_Lex_Ref (environment, name));
  1892.   if (code == PRIM_DONE)
  1893.   {
  1894.     /* Replace block with actual operator */
  1895.     (* (STACK_LOC (1))) = Val;
  1896.     if (COMPILED_CODE_ADDRESS_P (Val))
  1897.       return (apply_compiled_procedure ());
  1898.     else
  1899.       return (PRIM_APPLY);
  1900.   }
  1901.   else
  1902.   {
  1903.     STACK_PUSH (environment);
  1904.     STACK_PUSH (name);
  1905.     Store_Expression (SHARP_F);
  1906.     Store_Return (RC_COMP_CACHE_REF_APPLY_RESTART);
  1907.     Save_Cont ();
  1908.     return (code);
  1909.   }
  1910. }
  1911.  
  1912. /* Variable reference traps:
  1913.    Reference to a free variable that has a reference trap -- either a
  1914.    fluid or an error (unassigned / unbound)
  1915.  */
  1916.  
  1917. #define CMPLR_REF_TRAP(name, c_trap, ret_code, restart, c_lookup)    \
  1918. SCHEME_UTILITY utility_result                        \
  1919. DEFNX (name,                                \
  1920.        (return_address_raw, extension_addr_raw, ignore_3, ignore_4),    \
  1921.        SCHEME_ADDR return_address_raw                    \
  1922.        AND SCHEME_ADDR extension_addr_raw                \
  1923.        AND long ignore_3 AND long ignore_4)                \
  1924. {                                    \
  1925.   extern long EXFUN (c_trap, (SCHEME_OBJECT));                \
  1926.   instruction * return_address                        \
  1927.     = ((instruction *) (SCHEME_ADDR_TO_ADDR (return_address_raw)));    \
  1928.   SCHEME_OBJECT * extension_addr                    \
  1929.     = (SCHEME_ADDR_TO_ADDR (extension_addr_raw));            \
  1930.   SCHEME_OBJECT extension;                        \
  1931.   long code;                                \
  1932.                                     \
  1933.   extension = (MAKE_POINTER_OBJECT (TC_QUAD, extension_addr));        \
  1934.   code = c_trap (extension);                        \
  1935.   if (code == PRIM_DONE)                        \
  1936.     RETURN_TO_SCHEME (return_address);                    \
  1937.   else                                    \
  1938.   {                                    \
  1939.     SCHEME_OBJECT block, environment, name, sra;            \
  1940.                                     \
  1941.     sra = (ENTRY_TO_OBJECT (return_address));                \
  1942.     STACK_PUSH (sra);                            \
  1943.     block = (compiled_entry_to_block (sra));                \
  1944.     environment = (compiled_block_environment (block));            \
  1945.     STACK_PUSH (environment);                        \
  1946.     name = (compiler_var_error (extension, environment));        \
  1947.     STACK_PUSH (name);                            \
  1948.     Store_Expression (SHARP_F);                        \
  1949.     Store_Return (ret_code);                        \
  1950.     Save_Cont ();                            \
  1951.     RETURN_TO_C (code);                            \
  1952.   }                                    \
  1953. }                                    \
  1954.                                     \
  1955. C_TO_SCHEME long                            \
  1956. DEFUN_VOID (restart)                            \
  1957. {                                    \
  1958.   extern long EXFUN (c_lookup, (SCHEME_OBJECT, SCHEME_OBJECT));        \
  1959.   SCHEME_OBJECT name, environment;                    \
  1960.   long code;                                \
  1961.                                     \
  1962.   name = (Fetch_Expression ());                        \
  1963.   environment = (STACK_POP ());                        \
  1964.   code = (c_lookup (environment, name));                \
  1965.   if (code == PRIM_DONE)                        \
  1966.     ENTER_SCHEME (OBJECT_ADDRESS (STACK_POP ()));            \
  1967.   else                                    \
  1968.   {                                    \
  1969.     STACK_PUSH (environment);                        \
  1970.     STACK_PUSH (name);                            \
  1971.     Store_Expression (SHARP_F);                        \
  1972.     Store_Return (ret_code);                        \
  1973.     Save_Cont ();                            \
  1974.     return (code);                            \
  1975.   }                                    \
  1976. }
  1977.  
  1978. /* Actual traps */
  1979.  
  1980. CMPLR_REF_TRAP(comutil_lookup_trap,
  1981.                compiler_lookup_trap,
  1982.                RC_COMP_LOOKUP_TRAP_RESTART,
  1983.                comp_lookup_trap_restart,
  1984.                Symbol_Lex_Ref)
  1985.  
  1986. CMPLR_REF_TRAP(comutil_safe_lookup_trap,
  1987.                compiler_safe_lookup_trap,
  1988.                RC_COMP_SAFE_REF_TRAP_RESTART,
  1989.                comp_safe_lookup_trap_restart,
  1990.                safe_symbol_lex_ref)
  1991.  
  1992. CMPLR_REF_TRAP(comutil_unassigned_p_trap,
  1993.                compiler_unassigned_p_trap,
  1994.                RC_COMP_UNASSIGNED_TRAP_RESTART,
  1995.                comp_unassigned_p_trap_restart,
  1996.                Symbol_Lex_unassigned_p)
  1997.  
  1998.  
  1999. /* NUMERIC ROUTINES
  2000.    Invoke the arithmetic primitive in the fixed objects vector.
  2001.    The Scheme arguments are expected on the Scheme stack.
  2002.  */
  2003.  
  2004. #define COMPILER_ARITH_PRIM(name, fobj_index, arity)            \
  2005. SCHEME_UTILITY utility_result                        \
  2006. DEFNX (name,                                \
  2007.        (ignore_1, ignore_2, ignore_3, ignore_4),            \
  2008.        long ignore_1 AND long ignore_2                    \
  2009.        AND long ignore_3 AND long ignore_4)                \
  2010. {                                    \
  2011.   SCHEME_OBJECT handler;                        \
  2012.                                     \
  2013.   handler = (Get_Fixed_Obj_Slot (fobj_index));                \
  2014.   return (comutil_apply (handler, (arity), 0, 0));            \
  2015. }
  2016.  
  2017. COMPILER_ARITH_PRIM (comutil_decrement, GENERIC_TRAMPOLINE_PREDECESSOR, 2)
  2018. COMPILER_ARITH_PRIM (comutil_divide, GENERIC_TRAMPOLINE_DIVIDE, 3)
  2019. COMPILER_ARITH_PRIM (comutil_equal, GENERIC_TRAMPOLINE_EQUAL_P, 3)
  2020. COMPILER_ARITH_PRIM (comutil_greater, GENERIC_TRAMPOLINE_GREATER_P, 3)
  2021. COMPILER_ARITH_PRIM (comutil_increment, GENERIC_TRAMPOLINE_SUCCESSOR, 2)
  2022. COMPILER_ARITH_PRIM (comutil_less, GENERIC_TRAMPOLINE_LESS_P, 3)
  2023. COMPILER_ARITH_PRIM (comutil_minus, GENERIC_TRAMPOLINE_SUBTRACT, 3)
  2024. COMPILER_ARITH_PRIM (comutil_modulo, GENERIC_TRAMPOLINE_MODULO, 3)
  2025. COMPILER_ARITH_PRIM (comutil_multiply, GENERIC_TRAMPOLINE_MULTIPLY, 3)
  2026. COMPILER_ARITH_PRIM (comutil_negative, GENERIC_TRAMPOLINE_NEGATIVE_P, 2)
  2027. COMPILER_ARITH_PRIM (comutil_plus, GENERIC_TRAMPOLINE_ADD, 3)
  2028. COMPILER_ARITH_PRIM (comutil_positive, GENERIC_TRAMPOLINE_POSITIVE_P, 2)
  2029. COMPILER_ARITH_PRIM (comutil_quotient, GENERIC_TRAMPOLINE_QUOTIENT, 3)
  2030. COMPILER_ARITH_PRIM (comutil_remainder, GENERIC_TRAMPOLINE_REMAINDER, 3)
  2031. COMPILER_ARITH_PRIM (comutil_zero, GENERIC_TRAMPOLINE_ZERO_P, 2)
  2032.  
  2033. /*
  2034.   Obsolete SCHEME_UTILITYs used to handle first class environments.
  2035.   They have been superseded by the variable caching code.
  2036.   They are here for completeness, and because the code in the compiler
  2037.   that uses them has not yet been spliced out, although it is switched
  2038.   off.
  2039. */
  2040.  
  2041. #define CMPLR_REFERENCE(util_name, c_proc, ret_code, restart_name)    \
  2042. SCHEME_UTILITY utility_result                        \
  2043. DEFNX (util_name,                            \
  2044.        (ret_add_raw, environment, variable, ignore_4),            \
  2045.        SCHEME_ADDR ret_add_raw                        \
  2046.        AND SCHEME_OBJECT environment AND SCHEME_OBJECT variable        \
  2047.        AND long ignore_4)                        \
  2048. {                                    \
  2049.   extern long EXFUN (c_proc, (SCHEME_OBJECT, SCHEME_OBJECT));        \
  2050.   instruction * ret_add                            \
  2051.     = ((instruction *) (SCHEME_ADDR_TO_ADDR (ret_add_raw)));        \
  2052.   long code;                                \
  2053.                                     \
  2054.   code = (c_proc (environment, variable));                \
  2055.   if (code == PRIM_DONE)                        \
  2056.   {                                    \
  2057.     RETURN_TO_SCHEME (ret_add);                        \
  2058.   }                                    \
  2059.   else                                    \
  2060.   {                                    \
  2061.     STACK_PUSH (ENTRY_TO_OBJECT (ret_add));                \
  2062.     STACK_PUSH (variable);                        \
  2063.     STACK_PUSH (environment);                        \
  2064.     Store_Expression (SHARP_F);                        \
  2065.     Store_Return (ret_code);                        \
  2066.     Save_Cont ();                            \
  2067.     RETURN_TO_C (code);                            \
  2068.   }                                    \
  2069. }                                    \
  2070.                                     \
  2071. C_TO_SCHEME long                            \
  2072. DEFUN_VOID (restart_name)                        \
  2073. {                                    \
  2074.   extern long EXFUN (c_proc, (SCHEME_OBJECT, SCHEME_OBJECT));        \
  2075.   SCHEME_OBJECT environment, variable;                    \
  2076.   long code;                                \
  2077.                                     \
  2078.   environment = (STACK_POP ());                        \
  2079.   variable = (STACK_POP ());                        \
  2080.   code = (c_proc (environment, variable));                \
  2081.   if (code == PRIM_DONE)                        \
  2082.   {                                    \
  2083.     Regs[REGBLOCK_ENV] = environment;                    \
  2084.     ENTER_SCHEME (OBJECT_ADDRESS (STACK_POP ()));            \
  2085.   }                                    \
  2086.   else                                    \
  2087.   {                                    \
  2088.     STACK_PUSH (variable);                        \
  2089.     STACK_PUSH (environment);                        \
  2090.     Store_Expression (SHARP_F);                        \
  2091.     Store_Return (ret_code);                        \
  2092.     Save_Cont ();                            \
  2093.     return (code);                            \
  2094.   }                                    \
  2095. }
  2096.  
  2097. #define CMPLR_ASSIGNMENT(util_name, c_proc, ret_code, restart_name)    \
  2098. SCHEME_UTILITY utility_result                        \
  2099. DEFNX (util_name,                            \
  2100.        (ret_add_raw, environment, variable, value),            \
  2101.        SCHEME_ADDR ret_add_raw                        \
  2102.        AND SCHEME_OBJECT environment                    \
  2103.        AND SCHEME_OBJECT variable                    \
  2104.        AND SCHEME_OBJECT value)                        \
  2105. {                                    \
  2106.   extern long EXFUN (c_proc, (SCHEME_OBJECT, SCHEME_OBJECT,        \
  2107.                   SCHEME_OBJECT));                \
  2108.   instruction * ret_add                            \
  2109.     = ((instruction *) (SCHEME_ADDR_TO_ADDR (ret_add_raw)));        \
  2110.   long code;                                \
  2111.                                     \
  2112.   code = (c_proc (environment, variable, value));            \
  2113.   if (code == PRIM_DONE)                        \
  2114.     RETURN_TO_SCHEME (ret_add);                        \
  2115.   else                                    \
  2116.   {                                    \
  2117.     STACK_PUSH (ENTRY_TO_OBJECT (ret_add));                \
  2118.     STACK_PUSH (value);                            \
  2119.     STACK_PUSH (variable);                        \
  2120.     STACK_PUSH (environment);                        \
  2121.     Store_Expression (SHARP_F);                        \
  2122.     Store_Return (ret_code);                        \
  2123.     Save_Cont ();                            \
  2124.     RETURN_TO_C (code);                            \
  2125.   }                                    \
  2126. }                                    \
  2127.                                     \
  2128. C_TO_SCHEME long                            \
  2129. DEFUN_VOID (restart_name)                        \
  2130. {                                    \
  2131.   extern long EXFUN (c_proc, (SCHEME_OBJECT, SCHEME_OBJECT,        \
  2132.                   SCHEME_OBJECT));                \
  2133.   SCHEME_OBJECT environment, variable, value;                \
  2134.   long code;                                \
  2135.                                     \
  2136.   environment = (Fetch_Expression ());                    \
  2137.   variable = (STACK_POP ());                        \
  2138.   value = (STACK_POP ());                        \
  2139.   code = (c_proc (environment, variable, value));            \
  2140.   if (code == PRIM_DONE)                        \
  2141.   {                                    \
  2142.     Regs[REGBLOCK_ENV] = environment;                    \
  2143.     ENTER_SCHEME (OBJECT_ADDRESS (STACK_POP ()));            \
  2144.   }                                    \
  2145.   else                                    \
  2146.   {                                    \
  2147.     STACK_PUSH (value);                            \
  2148.     STACK_PUSH (variable);                        \
  2149.     STACK_PUSH (environment);                        \
  2150.     Store_Expression (SHARP_F);                        \
  2151.     Store_Return (ret_code);                        \
  2152.     Save_Cont ();                            \
  2153.     return (code);                            \
  2154.   }                                    \
  2155. }
  2156.  
  2157. CMPLR_REFERENCE(comutil_access,
  2158.         Symbol_Lex_Ref,
  2159.         RC_COMP_ACCESS_RESTART,
  2160.         comp_access_restart)
  2161.  
  2162. CMPLR_REFERENCE(comutil_reference,
  2163.         Lex_Ref,
  2164.         RC_COMP_REFERENCE_RESTART,
  2165.         comp_reference_restart)
  2166.  
  2167. CMPLR_REFERENCE(comutil_safe_reference,
  2168.         safe_lex_ref,
  2169.         RC_COMP_SAFE_REFERENCE_RESTART,
  2170.         comp_safe_reference_restart)
  2171.  
  2172. CMPLR_REFERENCE(comutil_unassigned_p,
  2173.         Symbol_Lex_unassigned_p,
  2174.         RC_COMP_UNASSIGNED_P_RESTART,
  2175.         comp_unassigned_p_restart)
  2176.  
  2177. CMPLR_REFERENCE(comutil_unbound_p,
  2178.         Symbol_Lex_unbound_p,
  2179.         RC_COMP_UNBOUND_P_RESTART,
  2180.         comp_unbound_p_restart)
  2181.  
  2182. CMPLR_ASSIGNMENT(comutil_assignment,
  2183.          Lex_Set,
  2184.          RC_COMP_ASSIGNMENT_RESTART,
  2185.          comp_assignment_restart)
  2186.  
  2187. CMPLR_ASSIGNMENT(comutil_definition,
  2188.          Local_Set,
  2189.          RC_COMP_DEFINITION_RESTART,
  2190.          comp_definition_restart)
  2191.  
  2192. SCHEME_UTILITY utility_result
  2193. DEFNX (comutil_lookup_apply,
  2194.        (environment, variable, nactuals, ignore_4),
  2195.        SCHEME_OBJECT environment AND SCHEME_OBJECT variable
  2196.        AND long nactuals AND long ignore_4)
  2197. {
  2198.   extern long EXFUN (Lex_Ref, (SCHEME_OBJECT, SCHEME_OBJECT));
  2199.   long code;
  2200.  
  2201.   code = (Lex_Ref (environment, variable));
  2202.   if (code == PRIM_DONE)
  2203.     return (comutil_apply (Val, nactuals, 0, 0));
  2204.   else
  2205.   {
  2206.     STACK_PUSH (LONG_TO_UNSIGNED_FIXNUM (nactuals));
  2207.     STACK_PUSH (variable);
  2208.     STACK_PUSH (environment);
  2209.     Store_Expression (SHARP_F);
  2210.     Store_Return (RC_COMP_LOOKUP_APPLY_RESTART);
  2211.     Save_Cont ();
  2212.     RETURN_TO_C (code);
  2213.   }
  2214. }
  2215.  
  2216. C_TO_SCHEME long
  2217. DEFUN_VOID (comp_lookup_apply_restart)
  2218. {
  2219.   extern long EXFUN (Lex_Ref, (SCHEME_OBJECT, SCHEME_OBJECT));
  2220.   SCHEME_OBJECT environment, variable;
  2221.   long code;
  2222.  
  2223.   environment = (STACK_POP ());
  2224.   variable = (STACK_POP ());
  2225.   code = (Lex_Ref (environment, variable));
  2226.   if (code == PRIM_DONE)
  2227.   {
  2228.     SCHEME_OBJECT nactuals;
  2229.  
  2230.     nactuals = (STACK_POP ());
  2231.     STACK_PUSH (Val);
  2232.     STACK_PUSH (nactuals);
  2233.     if (COMPILED_CODE_ADDRESS_P (Val))
  2234.       return (apply_compiled_procedure ());
  2235.     else
  2236.       return (PRIM_APPLY);
  2237.   }
  2238.   else
  2239.   {
  2240.     STACK_PUSH (variable);
  2241.     STACK_PUSH (environment);
  2242.     Store_Expression (SHARP_F);
  2243.     Store_Return (RC_COMP_LOOKUP_APPLY_RESTART);
  2244.     Save_Cont ();
  2245.     return (code);
  2246.   }
  2247. }
  2248.  
  2249. SCHEME_UTILITY utility_result
  2250. DEFNX (comutil_primitive_error,
  2251.        (ret_add_raw, primitive, ignore_3, ignore_4),
  2252.        SCHEME_ADDR ret_add_raw
  2253.        AND SCHEME_OBJECT primitive
  2254.        AND long ignore_3 AND long ignore_4)
  2255. {
  2256.   instruction * ret_add =
  2257.     ((instruction *) (SCHEME_ADDR_TO_ADDR (ret_add_raw)));
  2258.  
  2259.   STACK_PUSH (ENTRY_TO_OBJECT (ret_add));
  2260.   STACK_PUSH (primitive);
  2261.   Store_Expression (SHARP_F);
  2262.   Store_Return (RC_COMP_ERROR_RESTART);
  2263.   Save_Cont ();
  2264.   RETURN_TO_C (ERR_COMPILED_CODE_ERROR);
  2265. }
  2266.  
  2267. C_TO_SCHEME long
  2268. DEFUN_VOID (comp_error_restart)
  2269. {
  2270.   instruction * ret_add;
  2271.  
  2272.   (void) STACK_POP ();        /* primitive */
  2273.   ret_add = ((instruction *) (OBJECT_ADDRESS (STACK_POP ())));
  2274.   ENTER_SCHEME (ret_add);
  2275. }
  2276.  
  2277. /* Procedures to destructure compiled entries and closures. */
  2278.  
  2279. /*
  2280.   Extract the debugging information attached to `block'.  Usually
  2281.   this is a string which contains the filename where the debugging
  2282.   info is stored.
  2283.  */
  2284.  
  2285. C_UTILITY SCHEME_OBJECT
  2286. DEFUN (compiled_block_debugging_info,
  2287.        (block),
  2288.        SCHEME_OBJECT block)
  2289. {
  2290.   long length;
  2291.  
  2292.   length = (VECTOR_LENGTH (block));
  2293.   return (FAST_MEMORY_REF (block, (length - 1)));
  2294. }
  2295.  
  2296. /* Extract the environment where the `block' was "loaded". */
  2297.  
  2298. C_UTILITY SCHEME_OBJECT
  2299. DEFUN (compiled_block_environment,
  2300.        (block),
  2301.        SCHEME_OBJECT block)
  2302. {
  2303.   long length;
  2304.  
  2305.   length = (VECTOR_LENGTH (block));
  2306.   return (FAST_MEMORY_REF (block, length));
  2307. }
  2308.  
  2309. /*
  2310.   Given `entry', a Scheme object representing a compiled code entry point,
  2311.   it returns the address of the block to which it belongs.
  2312.  */
  2313.  
  2314. C_UTILITY SCHEME_OBJECT *
  2315. DEFUN (compiled_entry_to_block_address,
  2316.        (entry),
  2317.        SCHEME_OBJECT entry)
  2318. {
  2319.   SCHEME_OBJECT *block_address;
  2320.  
  2321.   Get_Compiled_Block (block_address, (OBJECT_ADDRESS (entry)));
  2322.   return (block_address);
  2323. }
  2324.  
  2325. C_UTILITY SCHEME_OBJECT
  2326. DEFUN (compiled_entry_to_block,
  2327.        (entry),
  2328.        SCHEME_OBJECT entry)
  2329. {
  2330.   SCHEME_OBJECT *block_address;
  2331.  
  2332.   Get_Compiled_Block (block_address, (OBJECT_ADDRESS (entry)));
  2333.   return (MAKE_CC_BLOCK (block_address));
  2334. }
  2335.  
  2336. /* Returns the offset from the block to the entry point. */
  2337.  
  2338. #ifndef CC_BLOCK_DISTANCE
  2339.  
  2340. #define CC_BLOCK_DISTANCE(block,entry)                    \
  2341.   (((char *) (entry)) - ((char *) (block)))
  2342.  
  2343. #endif /* CC_BLOCK_DISTANCE */
  2344.  
  2345. C_UTILITY long
  2346. DEFUN (compiled_entry_to_block_offset,
  2347.        (entry),
  2348.        SCHEME_OBJECT entry)
  2349. {
  2350.   SCHEME_OBJECT *entry_address, *block_address;
  2351.  
  2352.   entry_address = (OBJECT_ADDRESS (entry));
  2353.   Get_Compiled_Block (block_address, entry_address);
  2354.   return (CC_BLOCK_DISTANCE (block_address, entry_address));
  2355. }
  2356.  
  2357. /*
  2358.   Check whether the compiled code block whose address is `block_addr'
  2359.   is a compiled closure block.
  2360.  */
  2361.  
  2362. static long
  2363. DEFUN (block_address_closure_p,
  2364.        (block_addr),
  2365.        SCHEME_OBJECT * block_addr)
  2366. {
  2367.   SCHEME_OBJECT header_word;
  2368.  
  2369.   header_word = (*block_addr);
  2370.   return (((OBJECT_TYPE (header_word)) == TC_MANIFEST_CLOSURE));
  2371. }
  2372.  
  2373. /*
  2374.   Check whether the compiled code block `block' is a compiled closure block.
  2375.  */
  2376.  
  2377. C_UTILITY long
  2378. DEFUN (compiled_block_closure_p,
  2379.        (block),
  2380.        SCHEME_OBJECT block)
  2381. {
  2382.   return (block_address_closure_p (OBJECT_ADDRESS (block)));
  2383. }
  2384.  
  2385. /*
  2386.   Check whether the compiled entry point `entry' is a compiled closure.
  2387.  */
  2388.  
  2389. C_UTILITY long
  2390. DEFUN (compiled_entry_closure_p,
  2391.        (entry),
  2392.        SCHEME_OBJECT entry)
  2393. {
  2394.   return (block_address_closure_p (compiled_entry_to_block_address (entry)));
  2395. }
  2396.  
  2397. /*
  2398.   Extract the entry point ultimately invoked by the compiled closure
  2399.   represented by `entry'.
  2400.  */
  2401.  
  2402. C_UTILITY SCHEME_OBJECT
  2403. DEFUN (compiled_closure_to_entry,
  2404.        (entry),
  2405.        SCHEME_OBJECT entry)
  2406. {
  2407.   SCHEME_OBJECT real_entry;
  2408.  
  2409.   EXTRACT_CLOSURE_ENTRY_ADDRESS (real_entry, (OBJECT_ADDRESS (entry)));
  2410.   return (ENTRY_TO_OBJECT (SCHEME_ADDR_TO_ADDR (real_entry)));
  2411. }
  2412.  
  2413. /*
  2414.   Store the information for `entry' into `buffer'.
  2415.   This is used by the printer and debugging utilities.
  2416.  */
  2417.  
  2418. /* Kinds and subkinds of entries. */
  2419.  
  2420. #define KIND_PROCEDURE                          0
  2421. #define KIND_CONTINUATION                       1
  2422. #define KIND_EXPRESSION                         2
  2423. #define KIND_OTHER                              3
  2424. #define KIND_ILLEGAL                            4
  2425.  
  2426. /* Continuation subtypes */
  2427.  
  2428. #define CONTINUATION_NORMAL                     0
  2429. #define CONTINUATION_DYNAMIC_LINK               1
  2430. #define CONTINUATION_RETURN_TO_INTERPRETER      2
  2431.  
  2432. /* Other subtypes */
  2433.  
  2434. #define OTHER_CLOSURE                0
  2435. #define OTHER_RANDOM                1
  2436.  
  2437. C_UTILITY void
  2438. DEFUN (compiled_entry_type,
  2439.        (entry, buffer),
  2440.        SCHEME_OBJECT entry AND long * buffer)
  2441. {
  2442.   long kind, min_arity, max_arity, field1, field2;
  2443.   SCHEME_OBJECT * entry_address;
  2444.  
  2445.   entry_address = (OBJECT_ADDRESS (entry));
  2446.   max_arity = (COMPILED_ENTRY_MAXIMUM_ARITY (entry_address));
  2447.   min_arity = (COMPILED_ENTRY_MINIMUM_ARITY (entry_address));
  2448.   field1 = min_arity;
  2449.   field2 = max_arity;
  2450.   if (min_arity >= 0)
  2451.     kind = KIND_PROCEDURE;
  2452.   else if (max_arity >= 0)
  2453.     kind = KIND_ILLEGAL;
  2454.   else if ((((unsigned long) max_arity) & 0xff) < 0xe0)
  2455.   {
  2456.     /* Field2 is the offset to the next continuation */
  2457.  
  2458.     kind = KIND_CONTINUATION;
  2459.     field1 = CONTINUATION_NORMAL;
  2460.     field2 = (((((unsigned long) max_arity) & 0x3f) << 7)
  2461.           | (((unsigned long) min_arity) & 0x7f));
  2462.   }
  2463.   else if (min_arity != -1)
  2464.     kind = KIND_ILLEGAL;
  2465.  
  2466.   else
  2467.   {
  2468.     switch (((unsigned long) max_arity) & 0xff)
  2469.     {
  2470.       case FORMAT_BYTE_EXPR:
  2471.       {
  2472.         kind = KIND_EXPRESSION;
  2473.         break;
  2474.       }
  2475.       case FORMAT_BYTE_CLOSURE:
  2476.       {
  2477.         kind = KIND_OTHER;
  2478.     field1 = OTHER_CLOSURE;
  2479.         break;
  2480.       }
  2481.       case FORMAT_BYTE_COMPLR:
  2482.       case FORMAT_BYTE_CMPINT:
  2483.       {
  2484.         kind = KIND_OTHER;
  2485.     field1 = OTHER_RANDOM;
  2486.         break;
  2487.       }
  2488.       case FORMAT_BYTE_DLINK:
  2489.       {
  2490.         kind = KIND_CONTINUATION;
  2491.         field1 = CONTINUATION_DYNAMIC_LINK;
  2492.         field2 = -1;
  2493.         break;
  2494.       }
  2495.       case FORMAT_BYTE_RETURN:
  2496.       {
  2497.         kind = KIND_CONTINUATION;
  2498.         field1 = CONTINUATION_RETURN_TO_INTERPRETER;
  2499.         field2 = ((long) (entry != return_to_interpreter));
  2500.         break;
  2501.       }
  2502.       default:
  2503.       {
  2504.         kind = KIND_ILLEGAL;
  2505.         break;
  2506.       }
  2507.     }
  2508.   }
  2509.   buffer[0] = kind;
  2510.   buffer[1] = field1;
  2511.   buffer[2] = field2;
  2512. }
  2513.  
  2514. void
  2515. DEFUN (declare_compiled_code_block, (block), SCHEME_OBJECT block)
  2516. {
  2517. #ifdef PUSH_D_CACHE_REGION
  2518.   SCHEME_OBJECT * block_addr = (OBJECT_ADDRESS (block));
  2519.   PUSH_D_CACHE_REGION (block_addr, (1+ (OBJECT_DATUM (* block_addr))));
  2520. #endif
  2521. }
  2522.  
  2523. /* Destructuring free variable caches. */
  2524.  
  2525. C_UTILITY void
  2526. DEFUN (store_variable_cache,
  2527.        (extension, block, offset),
  2528.        SCHEME_OBJECT extension AND SCHEME_OBJECT block
  2529.        AND long offset)
  2530. {
  2531.   FAST_MEMORY_SET (block, offset,
  2532.                    ((SCHEME_OBJECT)
  2533.             (ADDR_TO_SCHEME_ADDR (OBJECT_ADDRESS (extension)))));
  2534. }
  2535.  
  2536. C_UTILITY SCHEME_OBJECT
  2537. DEFUN (extract_variable_cache,
  2538.        (block, offset),
  2539.        SCHEME_OBJECT block AND long offset)
  2540. {
  2541.   return (MAKE_POINTER_OBJECT (TRAP_EXTENSION_TYPE,
  2542.                                ((SCHEME_OBJECT *)
  2543.                 (SCHEME_ADDR_TO_ADDR
  2544.                  (FAST_MEMORY_REF (block, offset))))));
  2545. }
  2546.  
  2547. /* Get a compiled procedure from a cached operator reference. */
  2548.  
  2549. C_UTILITY SCHEME_OBJECT
  2550. DEFUN (extract_uuo_link,
  2551.        (block, offset),
  2552.        SCHEME_OBJECT block AND long offset)
  2553. {
  2554.   SCHEME_OBJECT * cache_address, compiled_entry_address;
  2555.  
  2556.   cache_address = (MEMORY_LOC (block, offset));
  2557.   EXTRACT_EXECUTE_CACHE_ADDRESS (compiled_entry_address, cache_address);
  2558.   return (ENTRY_TO_OBJECT (SCHEME_ADDR_TO_ADDR (compiled_entry_address)));
  2559. }
  2560.  
  2561. static void
  2562. DEFUN (store_uuo_link,
  2563.        (entry, cache_address),
  2564.        SCHEME_OBJECT entry AND SCHEME_OBJECT * cache_address)
  2565. {
  2566.   SCHEME_OBJECT * entry_address;
  2567.  
  2568.   entry_address = (OBJECT_ADDRESS (entry));
  2569.   STORE_EXECUTE_CACHE_CODE (cache_address);
  2570.   STORE_EXECUTE_CACHE_ADDRESS (cache_address,
  2571.                    (ADDR_TO_SCHEME_ADDR (entry_address)));
  2572. #ifdef FLUSH_I_CACHE_REGION
  2573.   if (!linking_cc_block_p)
  2574.     {
  2575.       /* The linker will flush the whole region afterwards. */
  2576.       FLUSH_I_CACHE_REGION (cache_address, EXECUTE_CACHE_ENTRY_SIZE);
  2577.     }
  2578. #endif
  2579. }
  2580.  
  2581. /* This makes a fake compiled procedure which traps to kind handler when
  2582.    invoked.
  2583.  */
  2584.  
  2585. #define TRAMPOLINE_SIZE    (TRAMPOLINE_ENTRY_SIZE + 2)
  2586.  
  2587. /* Enabled so that the profiler can distinguish trampolines */
  2588.  
  2589. #if 1 || defined(AUTOCLOBBER_BUG)
  2590. #  define TC_TRAMPOLINE_HEADER    TC_FIXNUM
  2591. #else
  2592. #  define TC_TRAMPOLINE_HEADER    TC_MANIFEST_VECTOR
  2593. #endif
  2594.  
  2595. static void
  2596. DEFUN (fill_trampoline,
  2597.        (block, entry_point, fmt_word, kind),
  2598.        SCHEME_OBJECT * block
  2599.        AND instruction * entry_point
  2600.        AND format_word fmt_word
  2601.        AND long kind)
  2602. {
  2603.   (COMPILED_ENTRY_FORMAT_WORD (entry_point)) = fmt_word;
  2604.   (COMPILED_ENTRY_OFFSET_WORD (entry_point)) =
  2605.     (MAKE_OFFSET_WORD (entry_point, block, false));
  2606.   STORE_TRAMPOLINE_ENTRY (entry_point, kind);
  2607.   return;
  2608. }
  2609.  
  2610. static long
  2611. DEFUN (make_trampoline,
  2612.        (slot, fmt_word, kind, size, value1, value2, value3),
  2613.        SCHEME_OBJECT * slot
  2614.        AND format_word fmt_word
  2615.        AND long kind AND long size
  2616.        AND SCHEME_OBJECT value1 AND SCHEME_OBJECT value2
  2617.        AND SCHEME_OBJECT value3)
  2618. {
  2619.   instruction * entry_point;
  2620.   SCHEME_OBJECT * ptr;
  2621.  
  2622.   if (GC_Check (TRAMPOLINE_SIZE + size))
  2623.   {
  2624.     Request_GC (TRAMPOLINE_SIZE + size);
  2625.     return (PRIM_INTERRUPT);
  2626.   }
  2627.  
  2628.   ptr = Free;
  2629.   Free += (TRAMPOLINE_SIZE + size);
  2630.   ptr[0] = (MAKE_OBJECT (TC_TRAMPOLINE_HEADER,
  2631.                 ((TRAMPOLINE_SIZE - 1) + size)));
  2632.   ptr[1] = (MAKE_OBJECT (TC_MANIFEST_NM_VECTOR,
  2633.                TRAMPOLINE_ENTRY_SIZE));
  2634.   entry_point = ((instruction *) (TRAMPOLINE_ENTRY_POINT (ptr)));
  2635.   fill_trampoline (ptr, entry_point, fmt_word, kind);
  2636.   *slot = (ENTRY_TO_OBJECT (entry_point));
  2637.   ptr = (TRAMPOLINE_STORAGE (entry_point));
  2638.   if ((--size) >= 0)
  2639.     *ptr++ = value1;
  2640.   if ((--size) >= 0)
  2641.     *ptr++ = value2;
  2642.   if ((--size) >= 0)
  2643.     *ptr++ = value3;
  2644.   return (PRIM_DONE);
  2645. }
  2646.  
  2647. /* Standard trampolines. */
  2648.  
  2649. static long
  2650. DEFUN (make_redirection_trampoline,
  2651.        (slot, kind, procedure),
  2652.        SCHEME_OBJECT * slot AND long kind AND SCHEME_OBJECT procedure)
  2653. {
  2654.   return (make_trampoline (slot,
  2655.                ((format_word) FORMAT_WORD_CMPINT),
  2656.                kind,
  2657.                1,
  2658.                procedure,
  2659.                SHARP_F,
  2660.                SHARP_F));
  2661. }
  2662.  
  2663. static long
  2664. DEFUN (make_apply_trampoline,
  2665.        (slot, kind, procedure, nactuals),
  2666.        SCHEME_OBJECT * slot AND long kind
  2667.        AND SCHEME_OBJECT procedure AND long nactuals)
  2668. {
  2669.   return (make_trampoline (slot,
  2670.                ((format_word) FORMAT_WORD_CMPINT),
  2671.                kind,
  2672.                2,
  2673.                procedure,
  2674.                (LONG_TO_UNSIGNED_FIXNUM (nactuals)),
  2675.                SHARP_F));
  2676. }
  2677.  
  2678. #define TRAMPOLINE_TABLE_SIZE   4
  2679.  
  2680. static long
  2681. trampoline_arity_table[TRAMPOLINE_TABLE_SIZE * TRAMPOLINE_TABLE_SIZE] =
  2682. {
  2683.   TRAMPOLINE_K_1_0,        /* 1_0 */
  2684.   TRAMPOLINE_K_ARITY,        /* 1_1 should not get here */
  2685.   TRAMPOLINE_K_ARITY,        /* 1_2 should not get here */
  2686.   TRAMPOLINE_K_ARITY,        /* 1_3 should not get here */
  2687.   TRAMPOLINE_K_2_0,        /* 2_0 */
  2688.   TRAMPOLINE_K_2_1,        /* 2_1 */
  2689.   TRAMPOLINE_K_ARITY,        /* 2_2 should not get here */
  2690.   TRAMPOLINE_K_ARITY,        /* 2_3 should not get here */
  2691.   TRAMPOLINE_K_3_0,        /* 3_0 */
  2692.   TRAMPOLINE_K_3_1,        /* 3_1 */
  2693.   TRAMPOLINE_K_3_2,        /* 3_2 */
  2694.   TRAMPOLINE_K_ARITY,        /* 3_3 should not get here */
  2695.   TRAMPOLINE_K_4_0,        /* 4_0 */
  2696.   TRAMPOLINE_K_4_1,        /* 4_1 */
  2697.   TRAMPOLINE_K_4_2,        /* 4_2 */
  2698.   TRAMPOLINE_K_4_3        /* 4_3 */
  2699. };
  2700.  
  2701. /*
  2702.   make_uuo_link is called by C and initializes a compiled procedure
  2703.   cache at a location given by a block and an offset.
  2704.  
  2705.   make_uuo_link checks its procedure argument, and:
  2706.  
  2707.   - If it is not a compiled procedure, an entity, or a primitive
  2708.   procedure with a matching number of arguments, it stores a fake
  2709.   compiled procedure which will invoke comutil_operator_interpreted_trap
  2710.   when invoked.
  2711.  
  2712.   - If its argument is an entity, it stores a fake compiled procedure
  2713.   which will invoke comutil_operator_entity_trap when invoked.
  2714.  
  2715.   - If its argument is a primitive, it stores a fake compiled procedure
  2716.   which will invoke comutil_operator_primitive_trap, or
  2717.   comutil_operator_lexpr_trap when invoked.
  2718.  
  2719.   - If its argument is a compiled procedure that expects more or
  2720.   less arguments than those provided, it stores a fake compiled
  2721.   procedure which will invoke comutil_operator_arity_trap, or one of
  2722.   its specialized versions when invoked.
  2723.  
  2724.   - Otherwise, the actual (compatible) operator is stored.
  2725. */
  2726.  
  2727. C_UTILITY long
  2728. DEFUN (make_uuo_link,
  2729.        (procedure, extension, block, offset),
  2730.        SCHEME_OBJECT procedure AND SCHEME_OBJECT extension
  2731.        AND SCHEME_OBJECT block AND long offset)
  2732. {
  2733.   long kind, result;
  2734.   unsigned long nactuals;
  2735.   SCHEME_OBJECT orig_proc, trampoline, *cache_address;
  2736.  
  2737.   cache_address = (MEMORY_LOC (block, offset));
  2738.   EXTRACT_EXECUTE_CACHE_ARITY (nactuals, cache_address);
  2739.   /* nactuals >= 0 */
  2740.  
  2741.   orig_proc = procedure;
  2742. loop:
  2743.   switch (OBJECT_TYPE (procedure))
  2744.   {
  2745.     case TC_COMPILED_ENTRY:
  2746.     {
  2747.       SCHEME_OBJECT * entry;
  2748.       long nmin, nmax;
  2749.  
  2750.       entry = (OBJECT_ADDRESS (procedure));
  2751.       nmax = (COMPILED_ENTRY_MAXIMUM_ARITY (entry));
  2752.       if (((long) nactuals) == nmax)
  2753.       {
  2754.         store_uuo_link (procedure, cache_address);
  2755.         return (PRIM_DONE);
  2756.       }
  2757.       nmin = (COMPILED_ENTRY_MINIMUM_ARITY (entry));
  2758.       if ((nmax > 1) && (nmin > 0) && (nmin <= ((long) nactuals)) &&
  2759.           (nactuals <= TRAMPOLINE_TABLE_SIZE) &&
  2760.           (nmax <= (TRAMPOLINE_TABLE_SIZE + 1)))
  2761.       {
  2762.         kind = (trampoline_arity_table[((nmax - 2) * TRAMPOLINE_TABLE_SIZE) +
  2763.                        (nactuals - 1)]);
  2764.     /* Paranoia */
  2765.     if (kind != TRAMPOLINE_K_ARITY)
  2766.     {
  2767.       nactuals = 0;
  2768.       break;
  2769.     }
  2770.       }
  2771.       kind = TRAMPOLINE_K_ARITY;
  2772.       break;
  2773.     }
  2774.  
  2775.     case TC_ENTITY:
  2776.     {
  2777.       SCHEME_OBJECT data;
  2778.  
  2779.       data = (MEMORY_REF (procedure, ENTITY_DATA));
  2780.       if ((VECTOR_P (data))
  2781.       && (nactuals < (VECTOR_LENGTH (data)))
  2782.       && ((VECTOR_REF (data, nactuals)) != SHARP_F)
  2783.       && ((VECTOR_REF (data, 0))
  2784.           == (Get_Fixed_Obj_Slot (ARITY_DISPATCHER_TAG))))
  2785.       {
  2786.     /* No loops allowed! */
  2787.     SCHEME_OBJECT nproc = (VECTOR_REF (data, nactuals));
  2788.  
  2789.     if ((procedure == orig_proc) && (nproc != procedure))
  2790.     {
  2791.       procedure = nproc;
  2792.       goto loop;
  2793.     }
  2794.     else
  2795.       procedure = orig_proc;
  2796.       }
  2797.       kind = TRAMPOLINE_K_ENTITY;
  2798.       break;
  2799.     }
  2800.  
  2801.     case TC_PRIMITIVE:
  2802.     {
  2803.       long arity;
  2804.  
  2805.       arity = (PRIMITIVE_ARITY (procedure));
  2806.       if (arity == ((long) (nactuals - 1)))
  2807.       {
  2808.     nactuals = 0;
  2809.         kind = TRAMPOLINE_K_PRIMITIVE;
  2810.       }
  2811.       else if (arity == LEXPR_PRIMITIVE_ARITY)
  2812.         kind = TRAMPOLINE_K_LEXPR_PRIMITIVE;
  2813.       else
  2814.         kind = TRAMPOLINE_K_OTHER;
  2815.       break;
  2816.     }
  2817.  
  2818.     case TC_PROCEDURE: /* and some others... */
  2819.     default:
  2820.     /* uuo_link_interpreted: */
  2821.     {
  2822.       kind = TRAMPOLINE_K_INTERPRETED;
  2823.       break;
  2824.     }
  2825.   }
  2826.   if (nactuals == 0)
  2827.     result = (make_redirection_trampoline (&trampoline, kind, procedure));
  2828.   else
  2829.     result = (make_apply_trampoline (&trampoline, kind, procedure, nactuals));
  2830.   if (result != PRIM_DONE)
  2831.     return (result);
  2832.   store_uuo_link (trampoline, cache_address);
  2833.   return (PRIM_DONE);
  2834. }
  2835.  
  2836. C_UTILITY long
  2837. DEFUN (make_fake_uuo_link,
  2838.        (extension, block, offset),
  2839.        SCHEME_OBJECT extension AND SCHEME_OBJECT block AND long offset)
  2840. {
  2841.   long result;
  2842.   SCHEME_OBJECT trampoline, *cache_address;
  2843.  
  2844.   result = (make_trampoline (&trampoline,
  2845.                  ((format_word) FORMAT_WORD_CMPINT),
  2846.                  TRAMPOLINE_K_LOOKUP,
  2847.                  3,
  2848.                  extension,
  2849.                  block,
  2850.                  (LONG_TO_UNSIGNED_FIXNUM (offset))));
  2851.   if (result != PRIM_DONE)
  2852.   {
  2853.     return (result);
  2854.   }
  2855.   cache_address = (MEMORY_LOC (block, offset));
  2856.   store_uuo_link (trampoline, cache_address);
  2857.   return (PRIM_DONE);
  2858. }
  2859.  
  2860. /* C_UTILITY long fake_uuo_link_p does not appear to be used anymore */
  2861.  
  2862. C_UTILITY long
  2863. DEFUN (coerce_to_compiled,
  2864.        (procedure, arity, location),
  2865.        SCHEME_OBJECT procedure AND long arity AND SCHEME_OBJECT * location)
  2866. {
  2867.   long frame_size;
  2868.  
  2869.   frame_size = (arity + 1);
  2870.   if ((!(COMPILED_CODE_ADDRESS_P (procedure))) ||
  2871.       (((long) (COMPILED_ENTRY_MAXIMUM_ARITY (OBJECT_ADDRESS (procedure)))) !=
  2872.        frame_size))
  2873.   {
  2874.     if (frame_size > FORMAT_BYTE_FRAMEMAX)
  2875.       return (ERR_WRONG_NUMBER_OF_ARGUMENTS);
  2876.     return (make_trampoline (location,
  2877.                  ((format_word)
  2878.                   (MAKE_FORMAT_WORD (frame_size, frame_size))),
  2879.                  TRAMPOLINE_K_APPLY,
  2880.                  2,
  2881.                  procedure,
  2882.                  (LONG_TO_UNSIGNED_FIXNUM (frame_size)),
  2883.                  SHARP_F));
  2884.   }
  2885.   (*location) = procedure;
  2886.   return (PRIM_DONE);
  2887. }
  2888.  
  2889. #ifndef HAVE_BKPT_SUPPORT
  2890.  
  2891. C_UTILITY SCHEME_OBJECT
  2892. DEFUN (bkpt_install, (ep), PTR ep)
  2893. {
  2894.   return (SHARP_F);
  2895. }
  2896.  
  2897. C_UTILITY SCHEME_OBJECT
  2898. DEFUN (bkpt_closure_install, (ep), PTR ep)
  2899. {
  2900.   return (SHARP_F);
  2901. }
  2902.  
  2903. C_UTILITY void
  2904. DEFUN (bkpt_remove, (ep, handle), PTR ep AND SCHEME_OBJECT handle)
  2905. {
  2906.   error_external_return ();
  2907. }
  2908.  
  2909. C_UTILITY Boolean
  2910. DEFUN (bkpt_p, (ep), PTR ep)
  2911. {
  2912.   return (FALSE);
  2913. }
  2914.  
  2915. C_UTILITY SCHEME_OBJECT
  2916. DEFUN (bkpt_proceed, (ep, handle, state),
  2917.        PTR ep AND SCHEME_OBJECT handle AND SCHEME_OBJECT state)
  2918. {
  2919.   error_external_return ();
  2920.   return (UNSPECIFIC);
  2921. }
  2922.  
  2923. C_UTILITY PTR
  2924. DEFUN (do_bkpt_proceed, (value), unsigned long * value)
  2925. {
  2926.   * value = ((unsigned long) ERR_EXTERNAL_RETURN);
  2927.   return (FALSE);
  2928. }
  2929.  
  2930. #else /* HAVE_BKPT_SUPPORT */
  2931.  
  2932. #define BKPT_PROCEED_FRAME_SIZE    3
  2933.  
  2934. C_UTILITY SCHEME_OBJECT
  2935. DEFUN (bkpt_proceed, (ep, handle, state),
  2936.        PTR ep AND SCHEME_OBJECT handle AND SCHEME_OBJECT state)
  2937. {
  2938.   if ((! (COMPILED_CODE_ADDRESS_P (STACK_REF (BKPT_PROCEED_FRAME_SIZE))))
  2939.       || ((OBJECT_ADDRESS (STACK_REF (BKPT_PROCEED_FRAME_SIZE)))
  2940.       != ((SCHEME_OBJECT *) ep)))
  2941.     error_external_return ();
  2942.  
  2943.   STACK_PUSH (FIXNUM_ZERO + REFLECT_CODE_CC_BKPT);
  2944.   STACK_PUSH (reflect_to_interface);
  2945.   Stack_Pointer = (STACK_LOC (- BKPT_PROCEED_FRAME_SIZE));
  2946.   return (SHARP_F);
  2947. }
  2948. #endif /* HAVE_BKPT_SUPPORT */
  2949.  
  2950. SCHEME_UTILITY utility_result
  2951. DEFNX (comutil_compiled_code_bkpt,
  2952.        (entry_point_raw, state_raw, ignore_3, ignore_4),
  2953.        SCHEME_ADDR entry_point_raw AND SCHEME_ADDR state_raw
  2954.        AND long ignore_3 AND long ignore_4)
  2955. {
  2956.   long type_info[3];
  2957.   instruction * entry_point_a
  2958.     = ((instruction *) (SCHEME_ADDR_TO_ADDR (entry_point_raw)));
  2959.   SCHEME_OBJECT entry_point = (ENTRY_TO_OBJECT (entry_point_a));
  2960.   SCHEME_OBJECT state;
  2961.   SCHEME_OBJECT stack_ptr;
  2962.  
  2963.   STACK_PUSH (entry_point);    /* return address */
  2964.  
  2965.   /* Potential bug: This does not preserve the environment for
  2966.      IC procedures.  There is no way to tell that we have
  2967.      an IC procedure in our hands.  It is not safe to preserve
  2968.      it in general because the contents of the register may
  2969.      be stale (predate the last GC).
  2970.      However, the compiler no longer generates IC procedures, and
  2971.      will probably never do it again.
  2972.    */
  2973.  
  2974.   compiled_entry_type (entry_point, &type_info[0]);
  2975.   if ((type_info[0] == KIND_OTHER) && (type_info[1] == OTHER_CLOSURE))
  2976.   {
  2977.     entry_point_a = ((instruction *) (SCHEME_ADDR_TO_ADDR (state_raw)));
  2978.     state = (ENTRY_TO_OBJECT (entry_point_a));
  2979.   }
  2980.   else if (type_info[0] != KIND_CONTINUATION)
  2981.     state = SHARP_F;
  2982.   else if (type_info[1] == CONTINUATION_DYNAMIC_LINK)
  2983.     state = (MAKE_POINTER_OBJECT
  2984.          (TC_STACK_ENVIRONMENT, (SCHEME_ADDR_TO_ADDR (state_raw))));
  2985.   else
  2986.     state = Val;
  2987.  
  2988.   stack_ptr = (MAKE_POINTER_OBJECT (TC_STACK_ENVIRONMENT, Stack_Pointer));
  2989.   STACK_PUSH (state);        /* state to preserve */
  2990.   STACK_PUSH (stack_ptr);    /* "Environment" pointer */
  2991.   STACK_PUSH (entry_point);    /* argument to handler */
  2992.   return (comutil_apply ((Get_Fixed_Obj_Slot (COMPILED_CODE_BKPT_HANDLER)),
  2993.              4, ignore_3, ignore_4));
  2994. }
  2995.  
  2996. SCHEME_UTILITY utility_result
  2997. DEFNX (comutil_compiled_closure_bkpt,
  2998.        (entry_point_raw, ignore_2, ignore_3, ignore_4),
  2999.        SCHEME_ADDR entry_point_raw
  3000.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  3001. {
  3002.   instruction * entry_point_a
  3003.     = ((instruction *) (SCHEME_ADDR_TO_ADDR (entry_point_raw)));
  3004.   SCHEME_OBJECT entry_point = (ENTRY_TO_OBJECT (entry_point_a));
  3005.   SCHEME_OBJECT stack_ptr;
  3006.  
  3007.   STACK_PUSH (entry_point);    /* return address */
  3008.  
  3009.   stack_ptr = (MAKE_POINTER_OBJECT (TC_STACK_ENVIRONMENT, Stack_Pointer));
  3010.   STACK_PUSH (SHARP_F);        /* state to preserve */
  3011.   STACK_PUSH (stack_ptr);    /* "Environment" pointer */
  3012.   STACK_PUSH (entry_point);    /* argument to handler */
  3013.   return (comutil_apply ((Get_Fixed_Obj_Slot (COMPILED_CODE_BKPT_HANDLER)),
  3014.              4, ignore_3, ignore_4));
  3015. }
  3016.  
  3017. SCHEME_UTILITY utility_result
  3018. DEFNX (comutil_reflect_to_interface,
  3019.        (tramp_data_raw, ignore_2, ignore_3, ignore_4),
  3020.        SCHEME_ADDR tramp_data_raw
  3021.        AND long ignore_2 AND long ignore_3 AND long ignore_4)
  3022. {
  3023.   SCHEME_OBJECT code = (STACK_POP ());
  3024.  
  3025.   switch (OBJECT_DATUM (code))
  3026.   {
  3027.     case REFLECT_CODE_INTERNAL_APPLY:
  3028.     {
  3029.       long frame_size = (OBJECT_DATUM (STACK_POP ()));
  3030.       SCHEME_OBJECT procedure = (STACK_POP ());
  3031.       
  3032.       return (comutil_apply (procedure, frame_size, ignore_3, ignore_4));
  3033.     }
  3034.  
  3035.     case REFLECT_CODE_RESTORE_INTERRUPT_MASK:
  3036.     {
  3037.       SET_INTERRUPT_MASK (OBJECT_DATUM (STACK_POP ()));
  3038.       INVOKE_RETURN_ADDRESS ();
  3039.     }
  3040.  
  3041.     case REFLECT_CODE_STACK_MARKER:
  3042.     {
  3043.       (void) STACK_POP ();    /* marker1 */
  3044.       (void) STACK_POP ();    /* marker2 */
  3045.       INVOKE_RETURN_ADDRESS ();
  3046.     }
  3047.  
  3048.     case REFLECT_CODE_CC_BKPT:
  3049.     {
  3050.       unsigned long value;
  3051.  
  3052.       /* Attempt to process interrupts before really proceeding. */
  3053.  
  3054.       if (((long) (ADDR_TO_SCHEME_ADDR (Free)))
  3055.       >= ((long) (Regs[REGBLOCK_MEMTOP])))
  3056.       {
  3057.     STACK_PUSH (FIXNUM_ZERO + REFLECT_CODE_CC_BKPT);
  3058.     STACK_PUSH (reflect_to_interface);
  3059.     return (compiler_interrupt_common (0, SHARP_F));
  3060.       }
  3061.  
  3062.       if (do_bkpt_proceed (& value))
  3063.     RETURN_TO_SCHEME (value);
  3064.       else
  3065.     RETURN_TO_C (value);
  3066.     }
  3067.  
  3068.     default:
  3069.       STACK_PUSH (code);
  3070.       RETURN_TO_C (ERR_EXTERNAL_RETURN);
  3071.   }
  3072. }
  3073.  
  3074. /*
  3075.   Utility table used by the assembly language interface to invoke
  3076.   the SCHEME_UTILITY procedures that appear in this file.
  3077.  
  3078.   Important: Do NOT reorder this table without changing the indices
  3079.   defined on the following page and the corresponding table in the
  3080.   compiler.
  3081.  
  3082.   In addition, this table must be declared before compiler_reset_internal.
  3083.  */
  3084.  
  3085. #define UTE(name) ((utility_table_entry) name)
  3086.  
  3087. utility_table_entry utility_table[] =
  3088. {
  3089.   UTE(comutil_return_to_interpreter),        /* 0x0 */
  3090.   UTE(comutil_operator_apply_trap),        /* 0x1 */
  3091.   UTE(comutil_operator_arity_trap),        /* 0x2 */
  3092.   UTE(comutil_operator_entity_trap),        /* 0x3 */
  3093.   UTE(comutil_operator_interpreted_trap),    /* 0x4 */
  3094.   UTE(comutil_operator_lexpr_trap),        /* 0x5 */
  3095.   UTE(comutil_operator_primitive_trap),        /* 0x6 */
  3096.   UTE(comutil_operator_lookup_trap),        /* 0x7 */
  3097.   UTE(comutil_operator_1_0_trap),        /* 0x8 */
  3098.   UTE(comutil_operator_2_1_trap),        /* 0x9 */
  3099.   UTE(comutil_operator_2_0_trap),        /* 0xa */
  3100.   UTE(comutil_operator_3_2_trap),        /* 0xb */
  3101.   UTE(comutil_operator_3_1_trap),        /* 0xc */
  3102.   UTE(comutil_operator_3_0_trap),        /* 0xd */
  3103.   UTE(comutil_operator_4_3_trap),        /* 0xe */
  3104.   UTE(comutil_operator_4_2_trap),        /* 0xf */
  3105.   UTE(comutil_operator_4_1_trap),        /* 0x10 */
  3106.   UTE(comutil_operator_4_0_trap),        /* 0x11 */
  3107.   UTE(comutil_primitive_apply),            /* 0x12 */
  3108.   UTE(comutil_primitive_lexpr_apply),        /* 0x13 */
  3109.   UTE(comutil_apply),                /* 0x14 */
  3110.   UTE(comutil_error),                /* 0x15 */
  3111.   UTE(comutil_lexpr_apply),            /* 0x16 */
  3112.   UTE(comutil_link),                /* 0x17 */
  3113.   UTE(comutil_interrupt_closure),        /* 0x18 */
  3114.   UTE(comutil_interrupt_dlink),            /* 0x19 */
  3115.   UTE(comutil_interrupt_procedure),        /* 0x1a */
  3116.   UTE(comutil_interrupt_continuation),        /* 0x1b */
  3117.   UTE(comutil_interrupt_ic_procedure),        /* 0x1c */
  3118.   UTE(comutil_assignment_trap),            /* 0x1d */
  3119.   UTE(comutil_cache_lookup_apply),        /* 0x1e */
  3120.   UTE(comutil_lookup_trap),            /* 0x1f */
  3121.   UTE(comutil_safe_lookup_trap),        /* 0x20 */
  3122.   UTE(comutil_unassigned_p_trap),        /* 0x21 */
  3123.   UTE(comutil_decrement),            /* 0x22 */
  3124.   UTE(comutil_divide),                /* 0x23 */
  3125.   UTE(comutil_equal),                /* 0x24 */
  3126.   UTE(comutil_greater),                /* 0x25 */
  3127.   UTE(comutil_increment),            /* 0x26 */
  3128.   UTE(comutil_less),                /* 0x27 */
  3129.   UTE(comutil_minus),                /* 0x28 */
  3130.   UTE(comutil_multiply),            /* 0x29 */
  3131.   UTE(comutil_negative),            /* 0x2a */
  3132.   UTE(comutil_plus),                /* 0x2b */
  3133.   UTE(comutil_positive),            /* 0x2c */
  3134.   UTE(comutil_zero),                /* 0x2d */
  3135.   UTE(comutil_access),                /* 0x2e */
  3136.   UTE(comutil_reference),            /* 0x2f */
  3137.   UTE(comutil_safe_reference),            /* 0x30 */
  3138.   UTE(comutil_unassigned_p),            /* 0x31 */
  3139.   UTE(comutil_unbound_p),            /* 0x32 */
  3140.   UTE(comutil_assignment),            /* 0x33 */
  3141.   UTE(comutil_definition),            /* 0x34 */
  3142.   UTE(comutil_lookup_apply),            /* 0x35 */
  3143.   UTE(comutil_primitive_error),            /* 0x36 */
  3144.   UTE(comutil_quotient),            /* 0x37 */
  3145.   UTE(comutil_remainder),            /* 0x38 */
  3146.   UTE(comutil_modulo),                /* 0x39 */
  3147.   UTE(comutil_reflect_to_interface),        /* 0x3a */
  3148.   UTE(comutil_interrupt_continuation_2),    /* 0x3b */
  3149.   UTE(comutil_compiled_code_bkpt),        /* 0x3c */
  3150.   UTE(comutil_compiled_closure_bkpt)        /* 0x3d */
  3151.   };
  3152.  
  3153. extern long MAX_TRAMPOLINE;
  3154. long MAX_TRAMPOLINE = ((sizeof (utility_table))
  3155.                / (sizeof (utility_table_entry)));
  3156.  
  3157. /* Support for trap handling. */
  3158.  
  3159. static void
  3160. DEFUN_VOID (end_of_utils)
  3161. {
  3162.   return;
  3163. }
  3164.  
  3165. struct util_descriptor_s
  3166. {
  3167.   PTR pc;
  3168.   char * name;
  3169. };
  3170.  
  3171. #ifdef STDC_HEADERS
  3172. #  define UTLD(name)  { ((PTR) name), #name }
  3173. #else
  3174. /* Hope that this works. */
  3175. #  define UTLD(name)  { ((PTR) name), "name" }
  3176. #endif
  3177.  
  3178. static
  3179. struct util_descriptor_s utility_descriptor_table[] =
  3180. {
  3181. #ifdef DECLARE_CMPINTMD_UTILITIES
  3182.   DECLARE_CMPINTMD_UTILITIES(),
  3183. #endif /* DECLARE_CMPINTMD_UTILITIES */
  3184.   UTLD(C_to_interface),
  3185.   UTLD(open_gap),
  3186.   UTLD(setup_lexpr_invocation),
  3187.   UTLD(setup_compiled_invocation),
  3188.   UTLD(enter_compiled_expression),
  3189.   UTLD(apply_compiled_procedure),
  3190.   UTLD(return_to_compiled_code),
  3191.   UTLD(apply_compiled_from_primitive),
  3192.   UTLD(compiled_with_interrupt_mask),
  3193.   UTLD(compiled_with_stack_marker),
  3194.   UTLD(comutil_return_to_interpreter),
  3195.   UTLD(comutil_primitive_apply),
  3196.   UTLD(comutil_primitive_lexpr_apply),
  3197.   UTLD(comutil_apply),
  3198.   UTLD(comutil_error),
  3199.   UTLD(comutil_lexpr_apply),
  3200.   UTLD(abort_link_cc_block),
  3201.   UTLD(link_cc_block),
  3202.   UTLD(comutil_link),
  3203.   UTLD(comp_link_caches_restart),
  3204.   UTLD(comutil_operator_apply_trap),
  3205.   UTLD(comutil_operator_arity_trap),
  3206.   UTLD(comutil_operator_entity_trap),
  3207.   UTLD(comutil_operator_interpreted_trap),
  3208.   UTLD(comutil_operator_lexpr_trap),
  3209.   UTLD(comutil_operator_primitive_trap),
  3210.   UTLD(comutil_operator_lookup_trap),
  3211.   UTLD(comp_op_lookup_trap_restart),
  3212.   UTLD(comutil_operator_1_0_trap),
  3213.   UTLD(comutil_operator_2_1_trap),
  3214.   UTLD(comutil_operator_2_0_trap),
  3215.   UTLD(comutil_operator_3_2_trap),
  3216.   UTLD(comutil_operator_3_1_trap),
  3217.   UTLD(comutil_operator_3_0_trap),
  3218.   UTLD(comutil_operator_4_3_trap),
  3219.   UTLD(comutil_operator_4_2_trap),
  3220.   UTLD(comutil_operator_4_1_trap),
  3221.   UTLD(comutil_operator_4_0_trap),
  3222.   UTLD(compiler_interrupt_common),
  3223.   UTLD(comutil_interrupt_closure),
  3224.   UTLD(comutil_interrupt_dlink),
  3225.   UTLD(comutil_interrupt_procedure),
  3226.   UTLD(comutil_interrupt_continuation),
  3227.   UTLD(comutil_interrupt_ic_procedure),
  3228.   UTLD(comutil_interrupt_continuation_2),
  3229.   UTLD(comp_interrupt_restart),
  3230.  
  3231.   UTLD(comutil_assignment_trap),
  3232.   UTLD(comp_assignment_trap_restart),
  3233.   UTLD(comutil_cache_lookup_apply),
  3234.   UTLD(comp_cache_lookup_apply_restart),
  3235.   UTLD(comutil_lookup_trap),
  3236.   UTLD(comp_lookup_trap_restart),
  3237.   UTLD(comutil_safe_lookup_trap),
  3238.   UTLD(comp_safe_lookup_trap_restart),
  3239.   UTLD(comutil_unassigned_p_trap),
  3240.   UTLD(comp_unassigned_p_trap_restart),
  3241.   UTLD(comutil_decrement),
  3242.   UTLD(comutil_divide),
  3243.   UTLD(comutil_equal),
  3244.   UTLD(comutil_greater),
  3245.   UTLD(comutil_increment),
  3246.   UTLD(comutil_less),
  3247.   UTLD(comutil_minus),
  3248.   UTLD(comutil_modulo),
  3249.   UTLD(comutil_multiply),
  3250.   UTLD(comutil_negative),
  3251.   UTLD(comutil_plus),
  3252.   UTLD(comutil_positive),
  3253.   UTLD(comutil_quotient),
  3254.   UTLD(comutil_remainder),
  3255.   UTLD(comutil_zero),
  3256.   UTLD(comutil_access),
  3257.   UTLD(comp_access_restart),
  3258.   UTLD(comutil_reference),
  3259.   UTLD(comp_reference_restart),
  3260.   UTLD(comutil_safe_reference),
  3261.   UTLD(comp_safe_reference_restart),
  3262.   UTLD(comutil_unassigned_p),
  3263.   UTLD(comp_unassigned_p_restart),
  3264.   UTLD(comutil_unbound_p),
  3265.   UTLD(comp_unbound_p_restart),
  3266.   UTLD(comutil_assignment),
  3267.   UTLD(comp_assignment_restart),
  3268.   UTLD(comutil_definition),
  3269.   UTLD(comp_definition_restart),
  3270.   UTLD(comutil_lookup_apply),
  3271.   UTLD(comp_lookup_apply_restart),
  3272.   UTLD(comutil_primitive_error),
  3273.   UTLD(comp_error_restart),
  3274.   UTLD(compiled_block_debugging_info),
  3275.   UTLD(compiled_block_environment),
  3276.   UTLD(compiled_entry_to_block_address),
  3277.   UTLD(compiled_entry_to_block),
  3278.   UTLD(compiled_entry_to_block_offset),
  3279.   UTLD(block_address_closure_p),
  3280.   UTLD(compiled_block_closure_p),
  3281.   UTLD(compiled_entry_closure_p),
  3282.   UTLD(compiled_closure_to_entry),
  3283.   UTLD(compiled_entry_type),
  3284.   UTLD(declare_compiled_code_block),
  3285.   UTLD(store_variable_cache),
  3286.   UTLD(extract_variable_cache),
  3287.   UTLD(extract_uuo_link),
  3288.   UTLD(store_uuo_link),
  3289.   UTLD(fill_trampoline),
  3290.   UTLD(make_trampoline),
  3291.   UTLD(make_redirection_trampoline),
  3292.   UTLD(make_apply_trampoline),
  3293.   UTLD(make_uuo_link),
  3294.   UTLD(make_fake_uuo_link),
  3295.   UTLD(coerce_to_compiled),
  3296. #ifndef HAVE_BKPT_SUPPORT
  3297.   UTLD(bkpt_install),
  3298.   UTLD(bkpt_closure_install),
  3299.   UTLD(bkpt_remove),
  3300.   UTLD(bkpt_p),
  3301.   UTLD(do_bkpt_proceed),
  3302. #endif 
  3303.   UTLD(bkpt_proceed),
  3304.   UTLD(comutil_compiled_code_bkpt),
  3305.   UTLD(comutil_compiled_closure_bkpt),
  3306.   UTLD(comutil_reflect_to_interface),
  3307.   UTLD(end_of_utils)
  3308. };
  3309.  
  3310. extern char * EXFUN (utility_index_to_name, (int));
  3311. extern int EXFUN (pc_to_utility_index, (unsigned long));
  3312.  
  3313. #define UTIL_TABLE_PC_REF_REAL(index)                    \
  3314.   ((unsigned long) (utility_descriptor_table[index].pc))
  3315.  
  3316. #ifndef UTIL_TABLE_PC_REF
  3317. #  define UTIL_TABLE_PC_REF(index)    (UTIL_TABLE_PC_REF_REAL (index))
  3318. #endif
  3319.  
  3320. static int last_util_table_index =
  3321.   (((sizeof (utility_descriptor_table)) / (sizeof (struct util_descriptor_s)))
  3322.    - 1);
  3323.  
  3324. char *
  3325. DEFUN (utility_index_to_name, (index), int index)
  3326. {
  3327.   if ((index < 0) || (index >= last_util_table_index))
  3328.     return ((char *) NULL);
  3329.   else
  3330.     return (utility_descriptor_table[index].name);
  3331. }
  3332.  
  3333. int
  3334. DEFUN (pc_to_utility_index, (pc), unsigned long pc)
  3335. {
  3336.   /* Binary search */
  3337.  
  3338.   extern int EXFUN (pc_to_builtin_index, (unsigned long));
  3339.  
  3340.   if ((pc < (UTIL_TABLE_PC_REF (0)))
  3341.       || (pc >= (UTIL_TABLE_PC_REF (last_util_table_index))))
  3342.     return (-1);
  3343.   else if (pc < (UTIL_TABLE_PC_REF (1)))
  3344.     return (((pc_to_builtin_index (pc)) == -1) ? 0 : -1);
  3345.   else
  3346.   {
  3347.     int low, high, middle;
  3348.  
  3349.     low = 0;
  3350.     high = last_util_table_index;
  3351.     while ((low + 1) < high)
  3352.     {
  3353.       middle = ((low + high) / 2);
  3354.       if (pc < (UTIL_TABLE_PC_REF (middle)))
  3355.     high = middle;
  3356.       else if (pc > (UTIL_TABLE_PC_REF (middle)))
  3357.     low = middle;
  3358.       else
  3359.     return (middle);
  3360.     }
  3361.     return ((pc == (UTIL_TABLE_PC_REF (high))) ? high : low);
  3362.   }
  3363. }
  3364.  
  3365. extern char * EXFUN (builtin_index_to_name, (int));
  3366. extern void EXFUN (declare_builtin, (unsigned long, char *));
  3367. extern int EXFUN (pc_to_builtin_index, (unsigned long));
  3368. extern unsigned long * builtins;
  3369.  
  3370. static int n_builtins = 0;
  3371. static int s_builtins = 0;
  3372. unsigned long * builtins = ((unsigned long *) NULL);
  3373. char ** builtin_names = ((char **) NULL);
  3374.  
  3375. void
  3376. DEFUN (declare_builtin, (builtin, name),
  3377.        unsigned long builtin AND char * name)
  3378. {
  3379.   if (n_builtins == s_builtins)
  3380.   {
  3381.     if (s_builtins == 0)
  3382.     {
  3383.       s_builtins = 30;
  3384.       builtins = ((unsigned long *)
  3385.           (malloc (s_builtins * (sizeof (unsigned long)))));
  3386.       builtin_names = ((char **) (malloc (s_builtins * (sizeof (char *)))));
  3387.     }
  3388.     else
  3389.     {
  3390.       s_builtins += s_builtins;
  3391.       builtins = ((unsigned long *)
  3392.           (realloc (builtins,
  3393.                 (s_builtins * (sizeof (unsigned long))))));
  3394.       builtin_names = ((char **)
  3395.                (realloc (builtin_names,
  3396.                  (s_builtins * (sizeof (char *))))));
  3397.     }
  3398.     if ((builtins == ((unsigned long *) NULL))
  3399.     || (builtin_names == ((char **) NULL)))
  3400.     {
  3401.       outf_fatal ("declare_builtin: malloc/realloc failed (size = %d).\n",
  3402.           s_builtins);
  3403.       termination_init_error ();
  3404.     }
  3405.   }
  3406.   {
  3407.     unsigned int low = 0;
  3408.     unsigned int high = n_builtins;
  3409.     while (1)
  3410.       {
  3411.     if (low < high)
  3412.       {
  3413.         unsigned int middle = ((low + high) / 2);
  3414.         if (builtin < (builtins[middle]))
  3415.           high = middle;
  3416.         else if (builtin > (builtins[middle]))
  3417.           low = (middle + 1);
  3418.         else
  3419.           {
  3420.         (builtin_names[middle]) = name;
  3421.         return;
  3422.           }
  3423.       }
  3424.     else
  3425.       {
  3426.         unsigned int scan = n_builtins;
  3427.         while (low < scan)
  3428.           {
  3429.         (builtins [scan]) = (builtins [scan - 1]);
  3430.         (builtin_names [scan]) = (builtin_names [scan - 1]);
  3431.         scan -= 1;
  3432.           }
  3433.         (builtins [low]) = builtin;
  3434.         (builtin_names [low]) = name;
  3435.         return;
  3436.       }
  3437.       }
  3438.   }
  3439. }
  3440.  
  3441. char *
  3442. DEFUN (builtin_index_to_name, (index), int index)
  3443. {
  3444.   if ((index < 0) || (index >= n_builtins))
  3445.     return ((char *) NULL);
  3446.   else
  3447.     return (builtin_names[index]);
  3448. }
  3449.  
  3450. int
  3451. DEFUN (pc_to_builtin_index, (pc), unsigned long pc)
  3452. {
  3453.   /* Binary search */
  3454.  
  3455.   if ((builtins == ((unsigned long *) NULL))
  3456.       || (pc < (builtins[0]))
  3457.       || (pc >= (builtins[n_builtins - 1])))
  3458.     return (-1);
  3459.   else
  3460.   {
  3461.     int low, high, middle;
  3462.  
  3463.     low = 0;
  3464.     high = (n_builtins - 1);
  3465.     while ((low + 1) < high)
  3466.     {
  3467.       middle = ((low + high) / 2);
  3468.       if (pc < (builtins[middle]))
  3469.     high = middle;
  3470.       else if (pc > (builtins[middle]))
  3471.     low = middle;
  3472.       else
  3473.     return (middle);
  3474.     }
  3475.     return ((pc == (builtins[high])) ? high : low);
  3476.   }
  3477. }
  3478.  
  3479. /* Initialization */
  3480.  
  3481. #define COMPILER_INTERFACE_VERSION        3
  3482.  
  3483. #ifndef COMPILER_REGBLOCK_N_FIXED
  3484. #  define COMPILER_REGBLOCK_N_FIXED        16
  3485. #endif
  3486.  
  3487. #ifndef COMPILER_REGBLOCK_N_TEMPS
  3488. #  define COMPILER_REGBLOCK_N_TEMPS        256
  3489. #endif
  3490.  
  3491. #ifndef COMPILER_REGBLOCK_EXTRA_SIZE
  3492. #  define COMPILER_REGBLOCK_EXTRA_SIZE        0
  3493. #endif
  3494.  
  3495. #if (REGBLOCK_MINIMUM_LENGTH > COMPILER_REGBLOCK_N_FIXED)
  3496. #  include "ERROR: cmpint.c and const.h disagree on REGBLOCK_MINIMUM_LENGTH!"
  3497. #endif
  3498.  
  3499. /* ((sizeof(SCHEME_OBJECT)) / (sizeof(SCHEME_OBJECT))) */
  3500.  
  3501. #define COMPILER_FIXED_SIZE    1
  3502.  
  3503. #ifndef COMPILER_TEMP_SIZE
  3504. #  define COMPILER_TEMP_SIZE    ((sizeof (double)) / (sizeof (SCHEME_OBJECT)))
  3505. #endif
  3506.  
  3507. #define REGBLOCK_LENGTH                            \
  3508.   ((COMPILER_REGBLOCK_N_FIXED * COMPILER_FIXED_SIZE) +            \
  3509.    (COMPILER_REGBLOCK_N_TEMPS * COMPILER_TEMP_SIZE) +            \
  3510.    COMPILER_REGBLOCK_EXTRA_SIZE)
  3511.  
  3512. #ifndef ASM_RESET_HOOK
  3513. #  define ASM_RESET_HOOK() NOP()
  3514. #endif
  3515.  
  3516. long
  3517.   compiler_processor_type,
  3518.   compiler_interface_version;
  3519.  
  3520. SCHEME_OBJECT
  3521.   compiler_utilities,
  3522.   return_to_interpreter;
  3523.  
  3524. #if !defined(REGBLOCK_ALLOCATED_BY_INTERFACE) && !defined(__WIN32__)
  3525. SCHEME_OBJECT
  3526.   Registers[REGBLOCK_LENGTH];
  3527. #endif
  3528.  
  3529. static void
  3530. DEFUN_VOID (compiler_reset_internal)
  3531. {
  3532.   long len;
  3533.   SCHEME_OBJECT * block;
  3534.  
  3535.   /* Other stuff can be placed here. */
  3536.  
  3537.   block = (OBJECT_ADDRESS (compiler_utilities));
  3538.   len = (OBJECT_DATUM (block[0]));
  3539.  
  3540.   return_to_interpreter =
  3541.     (ENTRY_TO_OBJECT (((char *) block)
  3542.               + ((unsigned long) (block [len - 1]))));
  3543.  
  3544.   reflect_to_interface =
  3545.     (ENTRY_TO_OBJECT (((char *) block)
  3546.               + ((unsigned long) (block [len]))));
  3547.  
  3548.   Regs[REGBLOCK_CLOSURE_FREE] = ((SCHEME_OBJECT) NULL);
  3549.   Regs[REGBLOCK_CLOSURE_SPACE] = ((SCHEME_OBJECT) 0);
  3550.   Regs[REGBLOCK_REFLECT_TO_INTERFACE] = reflect_to_interface;
  3551.  
  3552.   ASM_RESET_HOOK();
  3553.  
  3554.   return;
  3555. }
  3556.  
  3557. #define COMPILER_UTILITIES_N_ENTRIES    2
  3558. #define COMPILER_UTILITIES_LENGTH                    \
  3559.  ((COMPILER_UTILITIES_N_ENTRIES * (TRAMPOLINE_ENTRY_SIZE + 1)) + 2)
  3560.  
  3561. C_UTILITY void
  3562. DEFUN (compiler_initialize, (fasl_p), long fasl_p)
  3563. {
  3564.   /* Start-up of whole interpreter */
  3565.  
  3566.   Regs[REGBLOCK_PRIMITIVE] = SHARP_F;
  3567.   compiler_processor_type = COMPILER_PROCESSOR_TYPE;
  3568.   compiler_interface_version = COMPILER_INTERFACE_VERSION;
  3569.   if (fasl_p)
  3570.   {
  3571.     long len;
  3572.     instruction * tramp1, * tramp2;
  3573.     SCHEME_OBJECT * block;
  3574.     extern SCHEME_OBJECT * EXFUN (copy_to_constant_space,
  3575.                   (SCHEME_OBJECT *, long));
  3576.  
  3577.     len = COMPILER_UTILITIES_LENGTH;
  3578.     if (GC_Check (len))
  3579.     {
  3580.       outf_fatal ("compiler_initialize: Not enough space!\n");
  3581.       Microcode_Termination (TERM_NO_SPACE);
  3582.     }
  3583.  
  3584.     block = Free;
  3585.     Free += len;
  3586.     block[0] = (MAKE_OBJECT (TC_MANIFEST_VECTOR, (len - 1)));
  3587.     block[1] = (MAKE_OBJECT (TC_MANIFEST_NM_VECTOR,
  3588.                  (COMPILER_UTILITIES_N_ENTRIES
  3589.                   * TRAMPOLINE_ENTRY_SIZE)));
  3590.  
  3591.     tramp1 = ((instruction *) (TRAMPOLINE_ENTRY_POINT (block)));
  3592.     fill_trampoline (block, tramp1,
  3593.              ((format_word) FORMAT_WORD_RETURN),
  3594.              TRAMPOLINE_K_RETURN);
  3595.     block[len - 2] = (((char *) tramp1) - ((char *) block));
  3596.  
  3597.     tramp2 = ((instruction *)
  3598.           (((char *) tramp1)
  3599.            + (TRAMPOLINE_ENTRY_SIZE * (sizeof (SCHEME_OBJECT)))));
  3600.     fill_trampoline (block, tramp2,
  3601.              ((format_word) FORMAT_WORD_RETURN),
  3602.              TRAMPOLINE_K_REFLECT_TO_INTERFACE);
  3603.     block[len - 1] = (((char *) tramp2) - ((char *) block));
  3604.  
  3605.     block = (copy_to_constant_space (block, len));
  3606.     compiler_utilities = (MAKE_CC_BLOCK (block));
  3607.     compiler_reset_internal ();
  3608.   }
  3609.   else
  3610.   {
  3611.     /* Delay until after band-load, when compiler_reset will be invoked. */
  3612.     compiler_utilities = SHARP_F;
  3613.     return_to_interpreter = SHARP_F;
  3614. #ifdef sonyrisc
  3615.     /* On the Sony NEWS 3250, this procedure initializes the
  3616.        floating-point CPU control register to enable the IEEE traps.
  3617.        This is normally executed by `compiler_reset' from LOAD-BAND,
  3618.        but the Sony operating system saves the control register in
  3619.        `setjmp' and restores it on `longjmp', so we must initialize
  3620.        the register before `setjmp' is called.  */
  3621.     interface_initialize ();
  3622. #endif
  3623. #ifdef __OS2__
  3624.     /* Same as for Sony.  */
  3625.     i386_interface_initialize ();
  3626. #endif
  3627.   }
  3628.   return;
  3629. }
  3630.  
  3631. C_UTILITY void
  3632. DEFUN (compiler_reset,
  3633.        (new_block),
  3634.        SCHEME_OBJECT new_block)
  3635. {
  3636.   /* Called after a disk restore */
  3637.  
  3638.   if ((OBJECT_TYPE (new_block)) != TC_COMPILED_CODE_BLOCK)
  3639.   {
  3640.     extern void EXFUN (compiler_reset_error, (void));
  3641.  
  3642. lose:
  3643.     compiler_reset_error ();
  3644.     return;
  3645.   }
  3646.   else if ((MEMORY_REF (new_block, 0))
  3647.        != (MAKE_OBJECT (TC_MANIFEST_VECTOR,
  3648.                 (COMPILER_UTILITIES_LENGTH - 1))))
  3649.   {
  3650.     /* Backwards compatibility */
  3651.     if ((MEMORY_REF (new_block, 0))
  3652.     != (MAKE_OBJECT (TC_MANIFEST_NM_VECTOR,
  3653.              (COMPILER_UTILITIES_N_ENTRIES
  3654.               * (TRAMPOLINE_ENTRY_SIZE + 1)))))
  3655.       goto lose;
  3656.   }
  3657.   else if ((MEMORY_REF (new_block, 1))
  3658.        != (MAKE_OBJECT (TC_MANIFEST_NM_VECTOR,
  3659.                 (COMPILER_UTILITIES_N_ENTRIES
  3660.                  * TRAMPOLINE_ENTRY_SIZE))))
  3661.     goto lose;
  3662.  
  3663.   compiler_utilities = new_block;
  3664.   compiler_reset_internal ();
  3665.   return;
  3666. }
  3667.  
  3668. #ifndef NATIVE_CODE_IS_C
  3669.  
  3670. SCHEME_OBJECT *
  3671. DEFUN (cons_c_code_table, (start, limit, length),
  3672.        SCHEME_OBJECT * start
  3673.        AND SCHEME_OBJECT * limit
  3674.        AND long * length)
  3675. {
  3676.   * length = 0;
  3677.   return (start);
  3678. }
  3679.  
  3680. Boolean
  3681. DEFUN (install_c_code_table, (table, length),
  3682.        SCHEME_OBJECT * table AND long length)
  3683. {
  3684.   return (length == 0);
  3685. }
  3686.  
  3687. #endif /* NATIVE_CODE_IS_C */
  3688.  
  3689. #else    /* not HAS_COMPILER_SUPPORT */
  3690.  
  3691. /* Stubs for compiler utilities.
  3692.    All entries error out or kill the microcode.
  3693.  */
  3694.  
  3695. extern void EXFUN (Microcode_Termination, (int code));
  3696. extern void EXFUN (compiler_reset_error, (void));
  3697.  
  3698. extern long
  3699.   compiler_interface_version,
  3700.   compiler_processor_type;
  3701.  
  3702. extern SCHEME_OBJECT
  3703.   compiler_utilities,
  3704.   return_to_interpreter;
  3705.  
  3706. extern long
  3707.   EXFUN (enter_compiled_expression, (void)),
  3708.   EXFUN (apply_compiled_procedure, (void)),
  3709.   EXFUN (return_to_compiled_code, (void)),
  3710.   EXFUN (make_fake_uuo_link,
  3711.      (SCHEME_OBJECT extension, SCHEME_OBJECT block, long offset)),
  3712.   EXFUN (make_uuo_link,
  3713.      (SCHEME_OBJECT value, SCHEME_OBJECT extension,
  3714.       SCHEME_OBJECT block, long offset)),
  3715.   EXFUN (compiled_block_closure_p, (SCHEME_OBJECT block)),
  3716.   EXFUN (compiled_entry_closure_p, (SCHEME_OBJECT entry)),
  3717.   EXFUN (compiled_entry_to_block_offset, (SCHEME_OBJECT entry)),
  3718.   EXFUN (coerce_to_compiled,
  3719.      (SCHEME_OBJECT object, long arity, SCHEME_OBJECT *location));
  3720.  
  3721. extern SCHEME_OBJECT
  3722.   EXFUN (extract_uuo_link, (SCHEME_OBJECT block, long offset)),
  3723.   EXFUN (extract_variable_cache,
  3724.      (SCHEME_OBJECT extension, long offset)),
  3725.   EXFUN (compiled_block_debugging_info, (SCHEME_OBJECT block)),
  3726.   EXFUN (compiled_block_environment, (SCHEME_OBJECT block)),
  3727.   EXFUN (compiled_closure_to_entry, (SCHEME_OBJECT entry)),
  3728.   * EXFUN (compiled_entry_to_block_address, (SCHEME_OBJECT entry)),
  3729.   EXFUN (compiled_entry_to_block, (SCHEME_OBJECT entry)),
  3730.   EXFUN (apply_compiled_from_primitive, (int)),
  3731.   EXFUN (compiled_with_interrupt_mask, (unsigned long,
  3732.                     SCHEME_OBJECT,
  3733.                     unsigned long)),
  3734.   EXFUN (compiled_with_stack_marker, (SCHEME_OBJECT)),
  3735.   * EXFUN (cons_c_code_table, (SCHEME_OBJECT *, SCHEME_OBJECT *, long *));
  3736.  
  3737. extern Boolean
  3738.   EXFUN (install_c_code_table, (SCHEME_OBJECT *, long));
  3739.  
  3740. extern void
  3741.   EXFUN (compiler_reset, (SCHEME_OBJECT new_block)),
  3742.   EXFUN (compiler_initialize, (long fasl_p)),
  3743.   EXFUN (store_variable_cache,
  3744.      (SCHEME_OBJECT extension, SCHEME_OBJECT block, long offset)),
  3745.   EXFUN (compiled_entry_type, (SCHEME_OBJECT entry, long *buffer)),
  3746.   EXFUN (declare_compiled_code_block, (SCHEME_OBJECT block));
  3747.  
  3748. /* Breakpoint stuff. */
  3749.  
  3750. extern SCHEME_OBJECT EXFUN (bkpt_install, (PTR));
  3751. extern SCHEME_OBJECT EXFUN (bkpt_closure_install, (PTR));
  3752. extern Boolean EXFUN (bkpt_p, (PTR));
  3753. extern SCHEME_OBJECT EXFUN (bkpt_proceed, (PTR, SCHEME_OBJECT, SCHEME_OBJECT));
  3754. extern void EXFUN (bkpt_remove, (PTR, SCHEME_OBJECT));
  3755.  
  3756. SCHEME_OBJECT
  3757. #ifndef __WIN32__
  3758.   Registers[REGBLOCK_MINIMUM_LENGTH],
  3759. #endif
  3760.   compiler_utilities,
  3761.   return_to_interpreter;
  3762.  
  3763. long
  3764.   compiler_interface_version,
  3765.   compiler_processor_type;
  3766.  
  3767. long
  3768. DEFUN_VOID (enter_compiled_expression)
  3769. {
  3770.   return (ERR_EXECUTE_MANIFEST_VECTOR);
  3771. }
  3772.  
  3773. long
  3774. DEFUN_VOID (apply_compiled_procedure)
  3775. {
  3776.   return (ERR_INAPPLICABLE_OBJECT);
  3777. }
  3778.  
  3779. long
  3780. DEFUN_VOID (return_to_compiled_code)
  3781. {
  3782.   return (ERR_INAPPLICABLE_CONTINUATION);
  3783. }
  3784.  
  3785. SCHEME_OBJECT
  3786. DEFUN (apply_compiled_from_primitive, (arity), int arity)
  3787. {
  3788.   signal_error_from_primitive (ERR_INAPPLICABLE_CONTINUATION);
  3789.   /*NOTREACHED*/
  3790. }
  3791.  
  3792. SCHEME_OBJECT
  3793. DEFUN (compiled_with_interrupt_mask, (old_mask, receiver, new_mask),
  3794.        unsigned long old_mask
  3795.        AND SCHEME_OBJECT receiver
  3796.        AND unsigned long new_mask)
  3797. {
  3798.   signal_error_from_primitive (ERR_INAPPLICABLE_CONTINUATION);
  3799.   /*NOTREACHED*/
  3800. }
  3801.  
  3802. SCHEME_OBJECT
  3803. DEFUN (compiled_with_stack_marker, (thunk), SCHEME_OBJECT thunk)
  3804. {
  3805.   signal_error_from_primitive (ERR_INAPPLICABLE_CONTINUATION);
  3806.   /*NOTREACHED*/
  3807. }
  3808.  
  3809. SCHEME_OBJECT *
  3810. DEFUN (cons_c_code_table, (start, limit, length),
  3811.        SCHEME_OBJECT * start
  3812.        AND SCHEME_OBJECT * limit
  3813.        AND long * length)
  3814. {
  3815.   * length = 0;
  3816.   return (start);
  3817. }
  3818.  
  3819. Boolean
  3820. DEFUN (install_c_code_table, (table, length),
  3821.        SCHEME_OBJECT * table AND long length)
  3822. {
  3823.   return (length == 0);
  3824. }
  3825.  
  3826. /* Bad entry points. */
  3827.  
  3828. long
  3829. DEFUN (make_fake_uuo_link,
  3830.        (extension, block, offset),
  3831.        SCHEME_OBJECT extension AND SCHEME_OBJECT block AND
  3832.        long offset)
  3833. {
  3834.   Microcode_Termination (TERM_COMPILER_DEATH);
  3835.   /*NOTREACHED*/
  3836. }
  3837.  
  3838. long
  3839. DEFUN (make_uuo_link,
  3840.        (value, extension, block, offset),
  3841.        SCHEME_OBJECT value AND SCHEME_OBJECT extension AND
  3842.        SCHEME_OBJECT block AND long offset)
  3843. {
  3844.   Microcode_Termination (TERM_COMPILER_DEATH);
  3845.   /*NOTREACHED*/
  3846. }
  3847.  
  3848. SCHEME_OBJECT
  3849. DEFUN (extract_uuo_link,
  3850.        (block, offset),
  3851.        SCHEME_OBJECT block AND long offset)
  3852. {
  3853.   Microcode_Termination (TERM_COMPILER_DEATH);
  3854.   /*NOTREACHED*/
  3855. }
  3856.  
  3857. void
  3858. DEFUN (store_variable_cache,
  3859.        (extension, block, offset),
  3860.        SCHEME_OBJECT extension AND SCHEME_OBJECT block AND
  3861.        long offset)
  3862. {
  3863.   Microcode_Termination (TERM_COMPILER_DEATH);
  3864.   /*NOTREACHED*/
  3865. }
  3866.  
  3867. SCHEME_OBJECT
  3868. DEFUN (extract_variable_cache,
  3869.        (block, offset),
  3870.        SCHEME_OBJECT block AND
  3871.        long offset)
  3872. {
  3873.   Microcode_Termination (TERM_COMPILER_DEATH);
  3874.   /*NOTREACHED*/
  3875. }
  3876.  
  3877. SCHEME_OBJECT
  3878. DEFUN (compiled_block_debugging_info,
  3879.        (block),
  3880.        SCHEME_OBJECT block)
  3881. {
  3882.   Microcode_Termination (TERM_COMPILER_DEATH);
  3883.   /*NOTREACHED*/
  3884. }
  3885.  
  3886. SCHEME_OBJECT
  3887. DEFUN (compiled_block_environment,
  3888.        (block),
  3889.        SCHEME_OBJECT block)
  3890. {
  3891.   Microcode_Termination (TERM_COMPILER_DEATH);
  3892.   /*NOTREACHED*/
  3893. }
  3894.  
  3895. long
  3896. DEFUN (compiled_block_closure_p,
  3897.        (block),
  3898.        SCHEME_OBJECT block)
  3899. {
  3900.   Microcode_Termination (TERM_COMPILER_DEATH);
  3901.   /*NOTREACHED*/
  3902. }
  3903.  
  3904. SCHEME_OBJECT *
  3905. DEFUN (compiled_entry_to_block_address,
  3906.        (entry),
  3907.        SCHEME_OBJECT entry)
  3908. {
  3909.   Microcode_Termination (TERM_COMPILER_DEATH);
  3910.   /*NOTREACHED*/
  3911. }
  3912.  
  3913. long
  3914. DEFUN (compiled_entry_to_block_offset,
  3915.        (entry),
  3916.        SCHEME_OBJECT entry)
  3917. {
  3918.   Microcode_Termination (TERM_COMPILER_DEATH);
  3919.   /*NOTREACHED*/
  3920. }
  3921.  
  3922. SCHEME_OBJECT
  3923. DEFUN (compiled_entry_to_block,
  3924.        (entry),
  3925.        SCHEME_OBJECT entry)
  3926. {
  3927.   Microcode_Termination (TERM_COMPILER_DEATH);
  3928.   /*NOTREACHED*/
  3929. }
  3930.  
  3931.  
  3932. void
  3933. DEFUN (compiled_entry_type,
  3934.        (entry, buffer),
  3935.        SCHEME_OBJECT entry AND long *buffer)
  3936. {
  3937.   Microcode_Termination (TERM_COMPILER_DEATH);
  3938.   /*NOTREACHED*/
  3939. }
  3940.  
  3941. long
  3942. DEFUN (compiled_entry_closure_p,
  3943.        (entry),
  3944.        SCHEME_OBJECT entry)
  3945. {
  3946.   Microcode_Termination (TERM_COMPILER_DEATH);
  3947.   /*NOTREACHED*/
  3948. }
  3949.  
  3950. SCHEME_OBJECT
  3951. DEFUN (compiled_closure_to_entry, (entry), SCHEME_OBJECT entry)
  3952. {
  3953.   Microcode_Termination (TERM_COMPILER_DEATH);
  3954.   /*NOTREACHED*/
  3955. }
  3956.  
  3957. void
  3958. DEFUN (declare_compiled_code_block, (block), SCHEME_OBJECT block)
  3959. {
  3960.   return;
  3961. }
  3962.  
  3963. #define LOSING_RETURN_ADDRESS(name)                    \
  3964. extern long EXFUN (name, (void));                    \
  3965. long                                    \
  3966. DEFUN_VOID (name)                            \
  3967. {                                    \
  3968.   Microcode_Termination (TERM_COMPILER_DEATH);                \
  3969.   /*NOTREACHED*/                            \
  3970. }
  3971.  
  3972. LOSING_RETURN_ADDRESS (comp_interrupt_restart)
  3973. LOSING_RETURN_ADDRESS (comp_lookup_apply_restart)
  3974. LOSING_RETURN_ADDRESS (comp_reference_restart)
  3975. LOSING_RETURN_ADDRESS (comp_access_restart)
  3976. LOSING_RETURN_ADDRESS (comp_unassigned_p_restart)
  3977. LOSING_RETURN_ADDRESS (comp_unbound_p_restart)
  3978. LOSING_RETURN_ADDRESS (comp_assignment_restart)
  3979. LOSING_RETURN_ADDRESS (comp_definition_restart)
  3980. LOSING_RETURN_ADDRESS (comp_safe_reference_restart)
  3981. LOSING_RETURN_ADDRESS (comp_lookup_trap_restart)
  3982. LOSING_RETURN_ADDRESS (comp_assignment_trap_restart)
  3983. LOSING_RETURN_ADDRESS (comp_op_lookup_trap_restart)
  3984. LOSING_RETURN_ADDRESS (comp_cache_lookup_apply_restart)
  3985. LOSING_RETURN_ADDRESS (comp_safe_lookup_trap_restart)
  3986. LOSING_RETURN_ADDRESS (comp_unassigned_p_trap_restart)
  3987. LOSING_RETURN_ADDRESS (comp_link_caches_restart)
  3988. LOSING_RETURN_ADDRESS (comp_error_restart)
  3989.  
  3990. /* NOP entry points */
  3991.  
  3992. void
  3993. DEFUN (compiler_reset, (new_block), SCHEME_OBJECT new_block)
  3994. {
  3995.   extern void EXFUN (compiler_reset_error, (void));
  3996.  
  3997.   if (new_block != SHARP_F)
  3998.     compiler_reset_error ();
  3999.   return;
  4000. }
  4001.  
  4002. void
  4003. DEFUN (compiler_initialize, (fasl_p), long fasl_p)
  4004. {
  4005.   Regs[REGBLOCK_PRIMITIVE] = SHARP_F;
  4006.   compiler_processor_type = 0;
  4007.   compiler_interface_version = 0;
  4008.   compiler_utilities = SHARP_F;
  4009.   return_to_interpreter =
  4010.     (MAKE_OBJECT (TC_RETURN_CODE, RC_POP_FROM_COMPILED_CODE));
  4011.   return;
  4012. }
  4013.  
  4014. /* Identity procedure */
  4015.  
  4016. long
  4017. DEFUN (coerce_to_compiled,
  4018.        (object, arity, location),
  4019.        SCHEME_OBJECT object AND long arity AND SCHEME_OBJECT *location)
  4020. {
  4021.   *location = object;
  4022.   return (PRIM_DONE);
  4023. }
  4024.  
  4025. extern char * EXFUN (utility_index_to_name, (int));
  4026. extern void EXFUN (declare_builtin, (unsigned long));
  4027. extern char * EXFUN (builtin_index_to_name, (int));
  4028. extern int EXFUN (pc_to_utility_index, (unsigned long));
  4029. extern int EXFUN (pc_to_builtin_index, (unsigned long));
  4030.  
  4031. char *
  4032. DEFUN (utility_index_to_name, (index), int index)
  4033. {
  4034.   return ((char *) NULL);
  4035. }
  4036.  
  4037. void
  4038. DEFUN (declare_builtin, (builtin), unsigned long builtin)
  4039. {
  4040.   return;
  4041. }
  4042.  
  4043. char *
  4044. DEFUN (builtin_index_to_name, (index), int index)
  4045. {
  4046.   return ((char *) NULL);
  4047. }
  4048.  
  4049. int
  4050. DEFUN (pc_to_utility_index, (pc), unsigned long pc)
  4051. {
  4052.   return (-1);
  4053. }
  4054.  
  4055. int
  4056. DEFUN (pc_to_builtin_index, (pc), unsigned long pc)
  4057. {
  4058.   return (-1);
  4059. }
  4060.  
  4061. SCHEME_OBJECT
  4062. DEFUN (bkpt_install, (ep), PTR ep)
  4063. {
  4064.   return (SHARP_F);
  4065. }
  4066.  
  4067. SCHEME_OBJECT
  4068. DEFUN (bkpt_closure_install, (ep), PTR ep)
  4069. {
  4070.   return (SHARP_F);
  4071. }
  4072.  
  4073. void
  4074. DEFUN (bkpt_remove, (ep, handle), PTR ep AND SCHEME_OBJECT handle)
  4075. {
  4076.   error_external_return ();
  4077. }
  4078.  
  4079. Boolean
  4080. DEFUN (bkpt_p, (ep), PTR ep)
  4081. {
  4082.   return (SHARP_F);
  4083. }
  4084.  
  4085. SCHEME_OBJECT
  4086. DEFUN (bkpt_proceed, (ep, handle, state), 
  4087.        PTR ep AND SCHEME_OBJECT handle AND SCHEME_OBJECT state)
  4088. {
  4089.   error_external_return ();
  4090. }
  4091.  
  4092. #endif    /* HAS_COMPILER_SUPPORT */
  4093.  
  4094. #ifdef __WIN32__
  4095. #include "ntscmlib.h"
  4096.  
  4097. extern unsigned long * win32_catatonia_block;
  4098. extern void EXFUN (win32_allocate_registers, (void));
  4099. extern void EXFUN (win32_allocate_registers, (void));
  4100.  
  4101. #ifndef REGBLOCK_LENGTH
  4102. #  define REGBLOCK_LENGTH REGBLOCK_MINIMUM_LENGTH
  4103. #endif
  4104.  
  4105. typedef struct register_storage
  4106. {
  4107.   /* The following must be allocated consecutively */
  4108.   unsigned long catatonia_block[3];
  4109. #if (COMPILER_PROCESSOR_TYPE == COMPILER_IA32_TYPE)
  4110.   void * Regstart[32];    /* Negative byte offsets from &Registers[0] */
  4111. #endif
  4112.   SCHEME_OBJECT Registers [REGBLOCK_LENGTH];
  4113. } REGMEM;
  4114.  
  4115. SCHEME_OBJECT * RegistersPtr = ((SCHEME_OBJECT *) NULL);
  4116. unsigned long * win32_catatonia_block = ((unsigned long *) NULL);
  4117. static REGMEM regmem;
  4118.  
  4119. void
  4120. DEFUN_VOID (win32_allocate_registers)
  4121. {
  4122.   REGMEM * mem = & regmem;
  4123.  
  4124.   win32_catatonia_block = ((unsigned long *) &mem->catatonia_block[0]);
  4125.   RegistersPtr = mem->Registers;
  4126.   if (! (win32_system_utilities.lock_memory_area (mem, (sizeof (REGMEM)))))
  4127.   {
  4128.     outf_error ("Unable to lock registers\n");
  4129.     outf_flush_error ();
  4130.   }
  4131.   return;
  4132. }
  4133.  
  4134. void
  4135. DEFUN_VOID (win32_deallocate_registers)
  4136. {
  4137.   win32_system_utilities.unlock_memory_area (®mem, (sizeof (REGMEM)));
  4138.   return;
  4139. }
  4140.  
  4141. #endif /* __WIN32__ */
  4142.