1 /* -*-C-*-
2 
3 Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
4     1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
5     2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Massachusetts
6     Institute of Technology
7 
8 This file is part of MIT/GNU Scheme.
9 
10 MIT/GNU Scheme is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or (at
13 your option) any later version.
14 
15 MIT/GNU Scheme is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with MIT/GNU Scheme; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
23 USA.
24 
25 */
26 
27 /* Compiled-code interface */
28 
29 #ifndef SCM_CMPINT_H
30 #define SCM_CMPINT_H 1
31 
32 #include "config.h"
33 #include "object.h"
34 
35 #define COMPILER_INTERFACE_VERSION 3
36 
37 typedef struct cc_entry_type_s cc_entry_type_t;
38 typedef struct cc_entry_offset_s cc_entry_offset_t;
39 
40 #include "cmpintmd.h"
41 
42 #ifdef NO_CC_SUPPORT_P
43 #  undef CC_SUPPORT_P
44 #else
45 #  define CC_SUPPORT_P 1
46 
47 /* ASM_ENTRY_POINT is for OS/2, but it could also be used for any
48    compiler that supports multiple calling conventions, such as GCC.
49 
50    The IBM C Set++/2 compiler has several different external calling
51    conventions.  The default calling convention is called _Optlink,
52    uses a combination of registers and the stack, and is complicated.
53    The calling convention used for operating system interface
54    procedures is called _System, uses only the stack, and is very
55    similar to the calling conventions used with our DOS compilers.
56    So, in order to simplify the changes to the assembly language, we
57    use _System conventions for calling C procedures from the assembly
58    language file.
59 
60    Since _Optlink is the default, we must somehow cause the relevant
61    procedures to be compiled using _System.  The easiest way to do
62    this is to force the use of _System everywhere, but that's
63    undesirable since _Optlink is generally more efficient.  Instead,
64    we use the ASM_ENTRY_POINT wrapper to cause each of the relevant
65    procedures to be tagged with the compiler's _System keyword.  The
66    relevant procedures are all of the SCHEME_UTILITY procedures,
67    C_to_interface, interface_to_C, and interface_to_scheme.  */
68 
69 #ifndef ASM_ENTRY_POINT
70 #  define ASM_ENTRY_POINT(name) name
71 #endif
72 
73 /* The following code handles compiled entry points, where the
74    addresses point to the "middle" of the code vector.  From the entry
75    address, the offset word can be extracted, and this offset allows
76    us to find the beginning of the block, so it can be copied as a
77    whole.  The broken heart for the whole block lives in its usual
78    place (first word in the vector).
79 
80    The offset word contains an encoding of the offset and an encoding
81    of whether the resulting pointer points to the beginning of the
82    block or is another entry, so the process may have to be repeated.  */
83 
84 typedef enum
85 {
86   CET_PROCEDURE,
87   CET_CONTINUATION,
88   CET_EXPRESSION,
89   CET_INTERNAL_PROCEDURE,
90   CET_INTERNAL_CONTINUATION,
91   CET_TRAMPOLINE,
92   CET_RETURN_TO_INTERPRETER,
93   CET_CLOSURE
94 } cc_entry_type_marker_t;
95 
96 struct cc_entry_type_s
97 {
98   cc_entry_type_marker_t marker;
99   union
100     {
101       struct
102 	{
103 	  unsigned int n_required;
104 	  unsigned int n_optional;
105 	  bool rest_p;
106 	} for_procedure;
107       struct
108 	{
109 	  /* This number is in insn_t units.  A value of zero means
110 	     that the offset is unknown.  */
111 	  unsigned long offset;
112 	} for_continuation;
113     } args;
114 };
115 
116 extern void make_compiled_procedure_type
117   (cc_entry_type_t *, unsigned int, unsigned int, bool);
118 extern void make_compiled_continuation_type (cc_entry_type_t *, unsigned long);
119 extern void make_cc_entry_type (cc_entry_type_t *, cc_entry_type_marker_t);
120 
121 extern bool read_cc_entry_type (cc_entry_type_t *, insn_t *);
122 extern bool write_cc_entry_type (cc_entry_type_t *, insn_t *);
123 
124 extern bool decode_old_style_format_word (cc_entry_type_t *, unsigned short);
125 extern bool encode_old_style_format_word (cc_entry_type_t *, unsigned short *);
126 
127 /* If continued_p is false, then offset is the distance in insn_t
128    units between the entry and the CC block.  Otherwise, offset is the
129    distance in insn_t units between this entry and a preceding one.
130    */
131 struct cc_entry_offset_s
132 {
133   unsigned long offset;
134   bool continued_p;
135 };
136 
137 extern bool read_cc_entry_offset (cc_entry_offset_t *, insn_t *);
138 extern bool write_cc_entry_offset (cc_entry_offset_t *, insn_t *);
139 
140 #define CC_ENTRY_ADDRESS(obj) ((insn_t *) (OBJECT_ADDRESS (obj)))
141 #define MAKE_CC_ENTRY(addr)						\
142   (MAKE_POINTER_OBJECT (TC_COMPILED_ENTRY, ((SCHEME_OBJECT *) (addr))))
143 
144 #define CC_ENTRY_NEW_ADDRESS(entry, address)				\
145   (OBJECT_NEW_ADDRESS ((entry), ((insn_t *) (address))))
146 
147 #define CC_ENTRY_NEW_BLOCK(entry, new_block, old_block)			\
148   (CC_ENTRY_NEW_ADDRESS ((entry),					\
149 			 (((insn_t *) (new_block))			\
150 			  + ((CC_ENTRY_ADDRESS (entry))			\
151 			     - ((insn_t *) (old_block))))))
152 
153 #define MAKE_CC_BLOCK(address)						\
154   (MAKE_POINTER_OBJECT (TC_COMPILED_CODE_BLOCK, (address)))
155 
156 #define MAKE_CC_STACK_ENV(address)					\
157   (MAKE_POINTER_OBJECT (TC_STACK_ENVIRONMENT, (address)))
158 
159 #define CC_BLOCK_LENGTH(block) (CC_BLOCK_ADDR_LENGTH (OBJECT_ADDRESS (block)))
160 #define CC_BLOCK_END(block) (CC_BLOCK_ADDR_END (OBJECT_ADDRESS (block)))
161 #define CC_BLOCK_ADDR_LENGTH(addr) ((OBJECT_DATUM (*addr)) + 1)
162 #define CC_BLOCK_ADDR_END(addr) ((addr) + (CC_BLOCK_ADDR_LENGTH (addr)))
163 
164 #define CC_ENTRY_P(object) ((OBJECT_TYPE (object)) == TC_COMPILED_ENTRY)
165 #define CC_BLOCK_P(object) ((OBJECT_TYPE (object)) == TC_COMPILED_CODE_BLOCK)
166 #define CC_STACK_ENV_P(object) ((OBJECT_TYPE (object)) == TC_STACK_ENVIRONMENT)
167 
168 extern unsigned long cc_entry_to_block_offset (SCHEME_OBJECT);
169 extern SCHEME_OBJECT cc_entry_to_block (SCHEME_OBJECT);
170 extern SCHEME_OBJECT * cc_entry_to_block_address (SCHEME_OBJECT);
171 extern SCHEME_OBJECT * cc_entry_address_to_block_address (insn_t *);
172 extern int plausible_cc_block_p (SCHEME_OBJECT *);
173 
174 /* Linkage sections
175 
176    Linkage sections implement free-variable references in compiled
177    code.  They are built to be very fast, and are customized to
178    particular uses of the free variables.
179 
180    If a compiled-code block has linkage sections, they appear at the
181    very beginning of the block's constants area (i.e. immediately
182    following the non-marked code segment).  There are two basic kinds
183    of sections: (1) a reference section is used to read or write a
184    variable's value; and (2) an execution section is used to call a
185    variable's value.
186 
187    Each linkage section has a header word, with type
188    TC_LINKAGE_SECTION.  The bottom 16 bits of the header word's datum
189    contains the number of words in the rest of the linkage section
190    (i.e. its length, as if it were a vector).  The bits above that
191    contain the linkage section's type, which must be one of the values
192    listed below.
193 
194    Prior to linking, the header word has type TC_FIXNUM.  Each entry
195    in a reference section is a symbol, which is the name of the free
196    variable being referred to.  Each entry in an execution section has
197    two words: (1) a non-negative fixnum, which is the number of
198    arguments to be passed to the procedure; and (2) a symbol, which is
199    the name of the variable.
200 
201    After linking, the header word has type TC_LINKAGE_SECTION.  Each
202    entry in a reference section is the address (SCHEME_OBJECT*) of a
203    TC_HUNK3 object.  Each entry in an execution section is an
204    architecture-specific instruction sequence that jumps to the called
205    procedure (a "UUO link").  */
206 
207 typedef enum
208 {
209   LINKAGE_SECTION_TYPE_OPERATOR,
210   LINKAGE_SECTION_TYPE_REFERENCE,
211   LINKAGE_SECTION_TYPE_ASSIGNMENT,
212   LINKAGE_SECTION_TYPE_GLOBAL_OPERATOR,
213   N_LINKAGE_SECTION_TYPES
214 } linkage_section_type_t;
215 
216 extern linkage_section_type_t linkage_section_type (SCHEME_OBJECT);
217 extern unsigned long linkage_section_count (SCHEME_OBJECT);
218 extern SCHEME_OBJECT make_linkage_section_marker
219   (linkage_section_type_t, unsigned long);
220 
221 extern long make_uuo_link
222   (SCHEME_OBJECT, SCHEME_OBJECT, SCHEME_OBJECT, unsigned long);
223 extern long coerce_to_compiled (SCHEME_OBJECT, unsigned int, SCHEME_OBJECT *);
224 extern SCHEME_OBJECT read_uuo_link (SCHEME_OBJECT, unsigned long);
225 
226 extern SCHEME_OBJECT read_uuo_symbol (SCHEME_OBJECT *);
227 extern insn_t * read_uuo_target_no_reloc (SCHEME_OBJECT *);
228 extern void write_uuo_target (insn_t *, SCHEME_OBJECT *);
229 
230 extern unsigned int read_uuo_frame_size (SCHEME_OBJECT *);
231 
232 extern void write_variable_cache (SCHEME_OBJECT, SCHEME_OBJECT, unsigned long);
233 
234 /* Compiled closures
235 
236    A manifest closure header is followed by a (positive) count N,
237    which is followed by N closure entries.  Each entry consists of a
238    GC offset and a type followed by the machine code for the closure
239    (typically a call-like instruction).  The entries are tightly
240    packed so that the end address of one entry is the start address of
241    the next.  After the end address of the last entry there is
242    optional padding, followed by the closure's marked objects.
243 
244    When EMBEDDED_CLOSURE_ADDRS_P is defined, the target address of a
245    closure is embedded in the closure's code, and must be specially
246    managed by the garbage collector.  When undefined, the targets are
247    stored in the marked objects section of the closure, and so need no
248    special treatment.
249 
250    When EMBEDDED_CLOSURE_ADDRS_P is defined, the following macros are
251    used to read and write closure targets.
252 
253    READ_COMPILED_CLOSURE_TARGET(start, ref) returns the target of
254    'start' as a SCHEME_OBJECT, using 'ref' as the relocation
255    reference.  */
256 
257 /* Given the address of the word past the manifest closure header,
258    returns the number of closure entries in the block.  The returned
259    value must be positive.  */
260 extern unsigned long compiled_closure_count (SCHEME_OBJECT *);
261 
262 /* Given the address of the word past the manifest closure header,
263    returns the address of the first closure entry in the block.  */
264 extern insn_t * compiled_closure_start (SCHEME_OBJECT *);
265 
266 /* Given the address of the word past the manifest closure header,
267    returns the address of the first marked object.  */
268 extern SCHEME_OBJECT * compiled_closure_objects (SCHEME_OBJECT *);
269 
270 /* Given the address of a closure entry, returns the invocation
271    address for the corresponding closure.  */
272 extern insn_t * compiled_closure_entry (insn_t *);
273 
274 /* Given the address of a closure entry, returns the address of the
275    next closure entry.  (Which is also the end address of the given
276    closure entry.)  */
277 extern insn_t * compiled_closure_next (insn_t *);
278 
279 /* Given the address of the end of the last closure entry, returns the
280    address of the first marked object.  */
281 extern SCHEME_OBJECT * skip_compiled_closure_padding (insn_t *);
282 
283 /* Given the address of a closure entry, returns the compiled-code
284    entry that this closure invokes.  */
285 extern SCHEME_OBJECT compiled_closure_entry_to_target (insn_t *);
286 
287 /* Given a compiled-code entry point and the address of a closure
288    entry, modifies the closure to invoke the entry point.  */
289 extern void write_compiled_closure_target (insn_t *, insn_t *);
290 
291 /* Given a compiled-code block, returns true iff it is a closure's
292    block.  */
293 extern bool cc_block_closure_p (SCHEME_OBJECT);
294 
295 /* Given a compiled-code entry, returns true iff it is a closure.  */
296 extern bool cc_entry_closure_p (SCHEME_OBJECT);
297 
298 /* Given a compiled-code closure, returns the compiled-code entry that
299    it calls.  */
300 extern SCHEME_OBJECT cc_closure_to_entry (SCHEME_OBJECT);
301 
302 /* Trampolines
303 
304    Trampolines are "closures" that call code in the compiled-code
305    interface rather than compiled code.  They have an
306    architecture-specific calling sequence and a marked storage area.
307 
308    The architecture description must define TRAMPOLINE_ENTRY_SIZE to
309    be the number of words occupied by the instruction sequence,
310    including the compiled-code entry header.  The instruction sequence
311    must be padded, if necessary, to use an integral number of words.
312 
313    Here is a diagram of a trampoline on a 32-bit machine:
314 
315    0x00		TC_FIXNUM | 2 + trampoline_entry_size() + n
316    0x04		TC_MANIFEST_NM_VECTOR | trampoline_entry_size() == k
317    0x08		trampoline entry (k words)
318    0x08+k*4	trampoline storage (n words)
319 
320  */
321 
322 /* Given the number of trampoline entries, returns the number of words
323    needed to hold the instruction sequences for those entries.  */
324 extern unsigned long trampoline_entry_size (unsigned long);
325 
326 /* Given the address of a trampoline block and an entry index, returns
327    the address of the specified entry point.  */
328 extern insn_t * trampoline_entry_addr (SCHEME_OBJECT *, unsigned long);
329 
330 /* Given the address of a trampoline entry and the code for the
331    trampoline to be invoked, stores the appropriate instruction
332    sequence in the trampoline.  */
333 extern bool store_trampoline_insns (insn_t *, byte_t);
334 
335 /* Give the address of a trampoline block, returns a pointer to the
336    start of the trampoline's storage area.  */
337 extern SCHEME_OBJECT * trampoline_storage (SCHEME_OBJECT *);
338 
339 typedef enum
340 {
341   TRAMPOLINE_K_RETURN_TO_INTERPRETER,
342   TRAMPOLINE_K_APPLY,
343   TRAMPOLINE_K_ARITY,		/* unused */
344   TRAMPOLINE_K_ENTITY,		/* unused */
345   TRAMPOLINE_K_INTERPRETED,	/* unused */
346   TRAMPOLINE_K_LEXPR_PRIMITIVE,
347   TRAMPOLINE_K_PRIMITIVE,
348   TRAMPOLINE_K_LOOKUP,
349   TRAMPOLINE_K_1_0,
350   TRAMPOLINE_K_2_1,
351   TRAMPOLINE_K_2_0,
352   TRAMPOLINE_K_3_2,
353   TRAMPOLINE_K_3_1,
354   TRAMPOLINE_K_3_0,
355   TRAMPOLINE_K_4_3,
356   TRAMPOLINE_K_4_2,
357   TRAMPOLINE_K_4_1,
358   TRAMPOLINE_K_4_0,
359   TRAMPOLINE_K_REFLECT_TO_INTERFACE = 0x3A
360 } trampoline_type_t;
361 
362 #ifndef UTILITY_RESULT_DEFINED
363 #ifdef CMPINT_USE_STRUCS
364 
365 typedef struct
366 {
367   void * interface_dispatch;
368   union
369     {
370       long code_to_interpreter;
371       insn_t * entry_point;
372     } extra;
373 } utility_result_t;
374 
375 #else
376 
377 typedef insn_t * utility_result_t;
378 extern long C_return_value;
379 
380 #endif
381 #endif
382 
383 typedef void ASM_ENTRY_POINT (utility_proc_t)
384   (utility_result_t *, unsigned long, unsigned long, unsigned long,
385    unsigned long);
386 extern utility_proc_t * utility_table [];
387 
388 #ifndef FLUSH_I_CACHE
389 #  define FLUSH_I_CACHE() do {} while (false)
390 #endif
391 
392 #if !defined(PUSH_D_CACHE_REGION) && defined(FLUSH_I_CACHE_REGION)
393 #  define PUSH_D_CACHE_REGION(addr, nwords) FLUSH_I_CACHE_REGION(addr, nwords)
394 #endif
395 
396 extern unsigned int compiler_interface_version;
397 extern cc_arch_t compiler_processor_type;
398 extern unsigned long max_trampoline;
399 
400 extern SCHEME_OBJECT compiler_utilities;
401 extern SCHEME_OBJECT return_to_interpreter;
402 extern SCHEME_OBJECT reflect_to_interface;
403 
404 extern SCHEME_OBJECT cc_block_debugging_info (SCHEME_OBJECT);
405 extern SCHEME_OBJECT cc_block_environment (SCHEME_OBJECT);
406 extern SCHEME_OBJECT cc_block_linkage_info (SCHEME_OBJECT);
407 
408 extern long enter_compiled_expression (void);
409 extern void guarantee_cc_return (unsigned long);
410 extern void guarantee_interp_return (void);
411 extern long apply_compiled_procedure (void);
412 extern long return_to_compiled_code (void);
413 
414 extern void apply_compiled_from_primitive (unsigned long, SCHEME_OBJECT);
415 extern void compiled_with_interrupt_mask
416   (unsigned long, SCHEME_OBJECT, unsigned long);
417 extern void compiled_with_stack_marker (SCHEME_OBJECT);
418 
419 extern void compiler_initialize (bool);
420 extern void compiler_reset (SCHEME_OBJECT);
421 
422 extern void declare_compiled_code_block (SCHEME_OBJECT);
423 
424 extern void compiler_interrupt_common
425   (utility_result_t *, insn_t *, SCHEME_OBJECT);
426 
427 extern long comp_link_caches_restart (void);
428 extern long comp_op_lookup_trap_restart (void);
429 extern long comp_interrupt_restart (void);
430 extern long comp_assignment_trap_restart (void);
431 extern long comp_cache_lookup_apply_restart (void);
432 extern long comp_lookup_trap_restart (void);
433 extern long comp_safe_lookup_trap_restart (void);
434 extern long comp_unassigned_p_trap_restart (void);
435 extern long comp_error_restart (void);
436 
437 extern SCHEME_OBJECT bkpt_install (insn_t *);
438 extern SCHEME_OBJECT bkpt_closure_install (insn_t *);
439 extern bool bkpt_p (insn_t *);
440 extern SCHEME_OBJECT bkpt_proceed (insn_t *, SCHEME_OBJECT, SCHEME_OBJECT);
441 extern long do_bkpt_proceed (insn_t **);
442 extern void bkpt_remove (insn_t *, SCHEME_OBJECT);
443 
444 extern int pc_to_utility_index (unsigned long);
445 extern const char * utility_index_to_name (unsigned int);
446 extern int pc_to_builtin_index (unsigned long);
447 extern const char * builtin_index_to_name (unsigned int);
448 extern void declare_builtin (unsigned long, const char *);
449 
450 extern utility_proc_t comutil_return_to_interpreter;
451 extern utility_proc_t comutil_operator_apply_trap;
452 extern utility_proc_t comutil_operator_arity_trap;
453 extern utility_proc_t comutil_operator_entity_trap;
454 extern utility_proc_t comutil_operator_interpreted_trap;
455 extern utility_proc_t comutil_operator_lexpr_trap;
456 extern utility_proc_t comutil_operator_primitive_trap;
457 extern utility_proc_t comutil_operator_lookup_trap;
458 extern utility_proc_t comutil_operator_1_0_trap;
459 extern utility_proc_t comutil_operator_2_1_trap;
460 extern utility_proc_t comutil_operator_2_0_trap;
461 extern utility_proc_t comutil_operator_3_2_trap;
462 extern utility_proc_t comutil_operator_3_1_trap;
463 extern utility_proc_t comutil_operator_3_0_trap;
464 extern utility_proc_t comutil_operator_4_3_trap;
465 extern utility_proc_t comutil_operator_4_2_trap;
466 extern utility_proc_t comutil_operator_4_1_trap;
467 extern utility_proc_t comutil_operator_4_0_trap;
468 extern utility_proc_t comutil_primitive_apply;
469 extern utility_proc_t comutil_primitive_lexpr_apply;
470 extern utility_proc_t comutil_apply;
471 extern utility_proc_t comutil_error;
472 extern utility_proc_t comutil_lexpr_apply;
473 extern utility_proc_t comutil_link;
474 extern utility_proc_t comutil_interrupt_closure;
475 extern utility_proc_t comutil_interrupt_dlink;
476 extern utility_proc_t comutil_interrupt_procedure;
477 extern utility_proc_t comutil_interrupt_continuation;
478 extern utility_proc_t comutil_interrupt_ic_procedure;
479 extern utility_proc_t comutil_assignment_trap;
480 extern utility_proc_t comutil_cache_lookup_apply;
481 extern utility_proc_t comutil_lookup_trap;
482 extern utility_proc_t comutil_safe_lookup_trap;
483 extern utility_proc_t comutil_unassigned_p_trap;
484 extern utility_proc_t comutil_decrement;
485 extern utility_proc_t comutil_divide;
486 extern utility_proc_t comutil_equal;
487 extern utility_proc_t comutil_greater;
488 extern utility_proc_t comutil_increment;
489 extern utility_proc_t comutil_less;
490 extern utility_proc_t comutil_minus;
491 extern utility_proc_t comutil_multiply;
492 extern utility_proc_t comutil_negative;
493 extern utility_proc_t comutil_plus;
494 extern utility_proc_t comutil_positive;
495 extern utility_proc_t comutil_zero;
496 extern utility_proc_t comutil_primitive_error;
497 extern utility_proc_t comutil_quotient;
498 extern utility_proc_t comutil_remainder;
499 extern utility_proc_t comutil_modulo;
500 extern utility_proc_t comutil_reflect_to_interface;
501 extern utility_proc_t comutil_interrupt_continuation_2;
502 extern utility_proc_t comutil_compiled_code_bkpt;
503 extern utility_proc_t comutil_compiled_closure_bkpt;
504 
505 #endif /* !NO_CC_SUPPORT_P */
506 #endif /* !SCM_CMPINT_H */
507