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