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 / cmpgc.h < prev    next >
C/C++ Source or Header  |  2000-12-05  |  17KB  |  507 lines

  1. /* -*-C-*-
  2.  
  3. $Id: cmpgc.h,v 1.31 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. Utilities to relocate compiled code in garbage collection-like processes. 
  25.  
  26. This file is included by gccode.h.
  27.  
  28. See cmpint.txt, cmpint.c, cmpint-md.h, and cmpaux-md.m4 for more details.
  29. */
  30.  
  31. #ifndef CMPGC_H_INCLUDED
  32. #define CMPGC_H_INCLUDED
  33.  
  34. #define NOP() do {} while (0) /* A useful macro */
  35.  
  36. /* These are needed whether or not there is a compiler,
  37.    so their definition must be outside the HAS_COMPILER_SUPPORT ifdef.
  38.  */
  39.  
  40. #define OPERATOR_LINKAGE_KIND            0x000000
  41. #define REFERENCE_LINKAGE_KIND            0x010000
  42. #define ASSIGNMENT_LINKAGE_KIND            0x020000
  43. #define GLOBAL_OPERATOR_LINKAGE_KIND        0x030000
  44. #define CLOSURE_PATTERN_LINKAGE_KIND        0x040000
  45.  
  46. #ifdef HAS_COMPILER_SUPPORT
  47.  
  48. #include "cmpintmd.h"
  49.  
  50. /*
  51.   The following is a kludge which is used to get return_to_interpreter
  52.   to work.  The return to interpreter block is never dumped on normal
  53.   bin files, but is dumped in complete bands.  As long as it does not
  54.   change in position with respect to the beginning of constant space,
  55.   it will be relocated correctly on reload.
  56. */
  57.  
  58. #ifndef In_Fasdump
  59.  
  60. #define COMPILED_CODE_PRE_TEST(then_what)
  61.  
  62. #else
  63.  
  64. extern SCHEME_OBJECT compiler_utilities;
  65.  
  66. #define COMPILED_CODE_PRE_TEST(then_what)                \
  67. if (Old == (OBJECT_ADDRESS (compiler_utilities)))            \
  68.   then_what;                                \
  69. else
  70.  
  71. #endif
  72.  
  73. /*
  74.    The following code handles compiled entry points, where the
  75.    addresses point to the "middle" of the code vector.  From the entry
  76.    address, the offset word can be extracted, and this offset allows
  77.    us to find the beginning of the block, so it can be copied as a
  78.    whole.  The broken heart for the whole block lives in its usual
  79.    place (first word in the vector).
  80.  
  81.    The offset word contains an encoding of the offset and an encoding
  82.    of whether the resulting pointer points to the beginning of the
  83.    block or is another entry, so the process may have to be repeated.
  84.  
  85.    Pointers to char are used here because compiled entry points do not
  86.    in general point to Pointer boundaries.
  87.  */
  88.  
  89. #define Get_Compiled_Block(var, address)                \
  90. {                                    \
  91.   long offset_word;                            \
  92.                                     \
  93.   var = (address);                            \
  94.                                     \
  95.   do                                    \
  96.   {                                    \
  97.     offset_word = (COMPILED_ENTRY_OFFSET_WORD(var));            \
  98.     var = ((SCHEME_OBJECT *)                        \
  99.        (((char *) (var))                        \
  100.         - ((long) (OFFSET_WORD_TO_BYTE_OFFSET(offset_word)))));    \
  101.   } while (OFFSET_WORD_CONTINUATION_P (offset_word));            \
  102. }
  103.  
  104. #define RELOCATE_COMPILED_INTERNAL(addr, new_block, old_block)        \
  105.   ((SCHEME_OBJECT *)                            \
  106.    (((char *) new_block)                        \
  107.     + (((char *) (addr)) - ((char *) old_block))))
  108.  
  109. #define RELOCATE_COMPILED_RAW_ADDRESS(addr, new_block, old_block)    \
  110.   (ADDR_TO_SCHEME_ADDR                            \
  111.    (RELOCATE_COMPILED_INTERNAL ((SCHEME_ADDR_TO_ADDR (addr)),        \
  112.                 new_block, old_block)))
  113.  
  114. #define RELOCATE_COMPILED_ADDRESS(object, new_block, old_block)        \
  115.   ((SCHEME_OBJECT *)                            \
  116.    (RELOCATE_COMPILED_INTERNAL ((OBJECT_ADDRESS (object)),        \
  117.                 new_block, old_block)))
  118.  
  119. #define RELOCATE_COMPILED(object, new_block, old_block)            \
  120. MAKE_POINTER_OBJECT ((OBJECT_TYPE (object)),                \
  121.              (RELOCATE_COMPILED_ADDRESS (object, new_block,    \
  122.                          old_block)))
  123.  
  124. #define Compiled_BH(In_GC, then_what)                    \
  125. {                                    \
  126.   /* Has it already been relocated? */                    \
  127.                                     \
  128.   Get_Compiled_Block (Old, Old);                    \
  129.   COMPILED_CODE_PRE_TEST (then_what)                    \
  130.   if (BROKEN_HEART_P (* Old))                        \
  131.   {                                    \
  132.     Temp = (RELOCATE_COMPILED (Temp, (OBJECT_ADDRESS (* Old)), Old));    \
  133.     then_what;                                \
  134.   }                                    \
  135. }
  136.  
  137. #define RAW_COMPILED_BH(In_GC, then_what)                \
  138. {                                    \
  139.   Get_Compiled_Block (Old, Old);                    \
  140.   COMPILED_CODE_PRE_TEST (then_what)                    \
  141.   if (BROKEN_HEART_P (* Old))                        \
  142.   {                                    \
  143.     Temp = (RELOCATE_COMPILED_RAW_ADDRESS (Temp,            \
  144.                        (OBJECT_ADDRESS (* Old)),    \
  145.                        Old));            \
  146.     then_what;                                \
  147.   }                                    \
  148. }
  149.  
  150. #ifdef AUTOCLOBBER_BUG
  151.  
  152. # define AUTOCLOBBER_BUMP(Old, To) do                    \
  153. {                                    \
  154.   if ((OBJECT_TYPE (* Old)) == TC_MANIFEST_VECTOR)            \
  155.   {                                    \
  156.     *To = (MAKE_OBJECT (TC_MANIFEST_NM_VECTOR,                \
  157.             ((PAGE_SIZE / (sizeof (SCHEME_OBJECT)))        \
  158.              - 1)));                    \
  159.     To += (PAGE_SIZE / (sizeof (SCHEME_OBJECT)));            \
  160.   }                                    \
  161. } while (0)
  162.  
  163. #else
  164.  
  165. # define AUTOCLOBBER_BUMP(Old, To) do { } while (0)
  166.  
  167. #endif
  168.  
  169. #define Transport_Compiled() do                        \
  170. {                                    \
  171.   SCHEME_OBJECT * Saved_Old = Old;                    \
  172.                                     \
  173.   Real_Transport_Vector ();                        \
  174.   AUTOCLOBBER_BUMP (Saved_Old, To);                    \
  175.   *Saved_Old = New_Address;                        \
  176.   Temp = (RELOCATE_COMPILED (Temp,                    \
  177.                  (OBJECT_ADDRESS (New_Address)),        \
  178.                  Saved_Old));                \
  179. } while (0)
  180.  
  181. #define TRANSPORT_RAW_COMPILED() do                    \
  182. {                                    \
  183.   SCHEME_OBJECT * Saved_Old = Old;                    \
  184.                                     \
  185.   Real_Transport_Vector ();                        \
  186.   AUTOCLOBBER_BUMP (Saved_Old, To);                    \
  187.   *Saved_Old = New_Address;                        \
  188.   Temp = (RELOCATE_COMPILED_RAW_ADDRESS                    \
  189.       (Temp,                            \
  190.        (OBJECT_ADDRESS (New_Address)),                \
  191.        Saved_Old));                            \
  192. } while (0)
  193.  
  194. /* Manifest and implied types */
  195.  
  196. /* Manifest closures */
  197.  
  198. /* A manifest closure header is followed by one or more closure entry
  199.    points.  Each entry point consist of a pair of machine words (16
  200.    bits each) that contain a format word and a GC offset followed by
  201.    the machine code for the closure (typically a jsr-type
  202.    instruction).  If there is only one entry point to a closure, the
  203.    GC offset will be 8 bytes, pointing back to the manifest closure
  204.    header itself.  Otherwise what would have been the first GC offset
  205.    is 0, and what would have been the first format word is the count
  206.    in entry points.  The format word and GC offset for the first entry
  207.    follow this additional word.  After the entry points there are the
  208.    values of the variables closed over:
  209.  
  210.           >=1 Entry Point          =1 Entry Point
  211.    (offset in bytes from 1st instruction of 1st (only) entry)
  212.  
  213.      -12: Manifest Closure | tot. length
  214.      - 8: Count format word (with 0 GC)  Manifest Closure | tot. length
  215.      - 4: Format word, 1st entry         Format word, only entry
  216.      - 2: GC offset to -12               GC offset to -8
  217.        0: jsr instr., 1st entry         jsr instr.
  218.       xx: more instructions if needed    same
  219.         : Format word, 2nd entry         closed over variable values
  220.         : GC offset to -16
  221.      ...: etc.
  222.      ...: closed over variable values
  223.  
  224.    The following five macros are the only ones used outside of this
  225.    file to deal with closures.  They can be overridden for specific
  226.    machines that use different formats.
  227.  
  228.    MANIFEST_CLOSURE_COUNT receives the address of the word past the
  229.    manifest closure header and extracts the count of entry points
  230.    in the closure block.
  231.  
  232.    FIRST_MANIFEST_CLOSURE_ENTRY receives the address of the word past
  233.    the manifest closure header (-4 for single entry point closures in
  234.    the above picture).  It bumps it to the first entry point (i.e. to
  235.    0 above), past the format word and the gc offset and the count
  236.    formart word if present.
  237.  
  238.    NEXT_MANIFEST_CLOSURE_ENTRY given an entry point in a multiclosure,
  239.    bump to the immediately following entry point
  240.  
  241.    CLOSURE_ENTRY_END given an entry point, return the address of the
  242.    first byte past the code in this entry point.
  243.  
  244.    MANIFEST_CLOSURE_END receives the address of the word past
  245.    the manifest closure header (-4 for single entry point closures in
  246.    the above picture).  Returns the address of the word that precedes
  247.    the first free variable in the closure.
  248.  
  249.    CLOSURE_HEADER_TO_ENTRY is the distance (in bytes) from the
  250.    manifest closure header to the 1st instruction of the (1st) entry.
  251.  */
  252.  
  253. #define CLOSURE_HEADER_TO_ENTRY                        \
  254. ((sizeof (SCHEME_OBJECT)) + (2 * (sizeof (format_word))))
  255.  
  256. #define CLOSURE_HEADER_TO_ENTRY_WORD                    \
  257. ((format_word) (BYTE_OFFSET_TO_OFFSET_WORD (CLOSURE_HEADER_TO_ENTRY)))
  258.  
  259. #ifndef MANIFEST_CLOSURE_COUNT
  260. #define MANIFEST_CLOSURE_COUNT(scan)                    \
  261. (((((format_word *) (scan))[1]) ==                    \
  262.   CLOSURE_HEADER_TO_ENTRY_WORD) ?                    \
  263.  1 :                                    \
  264.  ((long) (((format_word *) (scan))[0])))
  265. #endif
  266.  
  267. #ifndef FIRST_MANIFEST_CLOSURE_ENTRY
  268. #define FIRST_MANIFEST_CLOSURE_ENTRY(scan)                \
  269. (((((format_word *) (scan))[1]) == CLOSURE_HEADER_TO_ENTRY_WORD)    \
  270.  ? (((char *) (scan)) + (2 * (sizeof (format_word))))            \
  271.  : (((char *) (scan)) + (4 * (sizeof (format_word)))))
  272. #endif
  273.  
  274. #ifndef NEXT_MANIFEST_CLOSURE_ENTRY
  275. #define NEXT_MANIFEST_CLOSURE_ENTRY(word_ptr)                \
  276.   (((char *) (word_ptr)) + (COMPILED_CLOSURE_ENTRY_SIZE))
  277. #endif
  278.  
  279. /* Where this closure entry ends with respect to the entry point.
  280.    Since an entry point is preceded by a format word and a gc offset,
  281.    it is the address of the next entry minus these two words.
  282.  */
  283.  
  284. #ifndef CLOSURE_ENTRY_END
  285. #define CLOSURE_ENTRY_END(word_ptr)                    \
  286.   (((char *) (word_ptr)) +                        \
  287.    ((COMPILED_CLOSURE_ENTRY_SIZE) - (2 * (sizeof (format_word)))))
  288. #endif
  289.  
  290. #define CHAR_TO_SCHEME_OBJECT(chars)                    \
  291. (((chars) + ((sizeof (SCHEME_OBJECT)) - 1)) / (sizeof (SCHEME_OBJECT)))
  292.  
  293. /* This takes into account the fact that the relocation loop increments
  294.    by 1 on each major iteration.
  295.    Note: It also assumes that closures with exactly one entry point
  296.    are always represented in short format.
  297.  */
  298.  
  299. #ifndef MANIFEST_CLOSURE_END
  300. #define MANIFEST_CLOSURE_END(start, count)                \
  301. (((SCHEME_OBJECT *) (start))                        \
  302.  + ((CHAR_TO_SCHEME_OBJECT (((count) * COMPILED_CLOSURE_ENTRY_SIZE)    \
  303.                 + (((count) == 1)                \
  304.                    ? 0                    \
  305.                    : (2 * sizeof(format_word)))))        \
  306.     - 1))
  307. #endif
  308.  
  309. /* Linkage sections */
  310.  
  311. #define READ_LINKAGE_KIND(header)                    \
  312.   ((header) & 0xff0000)
  313.  
  314. #define READ_CACHE_LINKAGE_COUNT(header)                \
  315.   ((header) & 0xffff)
  316.  
  317. #ifndef FIRST_OPERATOR_LINKAGE_OFFSET
  318. #  define FIRST_OPERATOR_LINKAGE_OFFSET 1
  319. #endif
  320.  
  321. #define READ_OPERATOR_LINKAGE_COUNT(header)                \
  322.   (EXECUTE_CACHE_COUNT_TO_ENTRIES                    \
  323.    (((header) & 0xffff) - (FIRST_OPERATOR_LINKAGE_OFFSET - 1)))
  324.   
  325. #define MAKE_LINKAGE_SECTION_HEADER(kind, count)            \
  326.   (MAKE_OBJECT(TC_LINKAGE_SECTION,                    \
  327.            ((kind)                            \
  328.         | ((((kind) == OPERATOR_LINKAGE_KIND)            \
  329.             || ((kind) == GLOBAL_OPERATOR_LINKAGE_KIND))    \
  330.            ? ((EXECUTE_CACHE_ENTRIES_TO_COUNT (count))        \
  331.               + (FIRST_OPERATOR_LINKAGE_OFFSET - 1))        \
  332.            : (count)))))
  333.  
  334. /* This takes into account the 1 added by the main loop of the
  335.    relocators.
  336.  */
  337.  
  338. #ifndef END_OPERATOR_LINKAGE_AREA
  339. #  define END_OPERATOR_LINKAGE_AREA(scan, count)            \
  340.   (((SCHEME_OBJECT *) (scan))                        \
  341.    + (((count) * EXECUTE_CACHE_ENTRY_SIZE))                \
  342.    + (FIRST_OPERATOR_LINKAGE_OFFSET - 1))
  343. #endif
  344.  
  345. #define FIRST_OPERATOR_LINKAGE_ENTRY(scan)                \
  346.   ((char *) (((SCHEME_OBJECT *) (scan)) + FIRST_OPERATOR_LINKAGE_OFFSET))
  347.  
  348. #define NEXT_LINKAGE_OPERATOR_ENTRY(word_ptr)                \
  349.   ((char *) (((SCHEME_OBJECT *) (word_ptr)) +                \
  350.          EXECUTE_CACHE_ENTRY_SIZE))
  351.  
  352. #ifndef EXTRACT_OPERATOR_LINKAGE_ADDRESS
  353. #  define EXTRACT_OPERATOR_LINKAGE_ADDRESS(target, source)        \
  354. {                                    \
  355.   EXTRACT_EXECUTE_CACHE_ADDRESS (target, source);            \
  356. }
  357. #endif
  358.  
  359. #ifndef STORE_OPERATOR_LINKAGE_ADDRESS
  360. # define STORE_OPERATOR_LINKAGE_ADDRESS(source, target)            \
  361. {                                    \
  362.   STORE_EXECUTE_CACHE_ADDRESS (target, source);                \
  363. }
  364. #endif
  365.  
  366. /* Heuristic recovery aid. See uxtrap.c for its use.
  367.    block is the address of a vector header followed by a non-marked
  368.    header (the way that compiled blocks start).
  369.    PLAUSIBLE_CC_BLOCK_P returns true if it is likely that compiled
  370.    code is contained in the header.  This is done by checking whether
  371.    an entry is the first thing in the compiled code section.
  372.    There are two kinds of "possible entries": expressions (first thing
  373.    in the block) and procedures/continuations, which follow an interrupt
  374.    check.
  375.  */
  376.  
  377. #define PLAUSIBLE_CC_BLOCK_P(block)                    \
  378.  (((PLAUSIBLE_BLOCK_START_P((block), CC_BLOCK_FIRST_ENTRY_OFFSET)) ||    \
  379.    (PLAUSIBLE_BLOCK_START_P((block),                    \
  380.                         (CC_BLOCK_FIRST_ENTRY_OFFSET +        \
  381.                 ENTRY_PREFIX_LENGTH))))            \
  382.   &&                                    \
  383.   (PLAUSIBLE_BLOCK_SPAN_AND_END_P(block,                \
  384.                   (VECTOR_LOC((SCHEME_OBJECT)block,            \
  385.                           ((VECTOR_LENGTH((SCHEME_OBJECT)block)) - 1))))))
  386.  
  387. #define PLAUSIBLE_BLOCK_START_P(addr, offset)                \
  388. ((*((format_word *)                            \
  389.     (((char *) (addr)) + ((offset) - (sizeof (format_word)))))) ==    \
  390.    ((BYTE_OFFSET_TO_OFFSET_WORD(offset))))
  391.  
  392. #define PLAUSIBLE_BLOCK_SPAN_AND_END_P(addr,end)            \
  393.   (((ADDRESS_HEAP_P(addr)     && ADDRESS_HEAP_P(end)) ||        \
  394.     (ADDRESS_CONSTANT_P(addr) && ADDRESS_CONSTANT_P(end)))        \
  395.    &&                                    \
  396.    (ENVIRONMENT_P (*(SCHEME_OBJECT *) end)))
  397.  
  398. #else /* not HAS_COMPILER_SUPPORT */
  399.  
  400. /* This can be anything. */
  401.  
  402. typedef unsigned short format_word;
  403.  
  404. /* Is there anything else that can be done here? */
  405.  
  406. #define GC_NO_COMPILER_STMT()                        \
  407.   gc_death                                \
  408.     (TERM_COMPILER_DEATH,                        \
  409.      "relocate_compiled: No compiler support!",                \
  410.      0, 0)
  411.  
  412. #define GC_NO_COMPILER_EXPR(value_type)                    \
  413.   ((GC_NO_COMPILER_STMT ()), (value_type 0))
  414.  
  415. #define RELOCATE_COMPILED(obj, nb, ob)                    \
  416.   (GC_NO_COMPILER_EXPR ((SCHEME_OBJECT)))
  417. #define RELOCATE_COMPILED_INTERNAL(ad,nb,ob)                \
  418.   (GC_NO_COMPILER_EXPR ((SCHEME_OBJECT)))
  419. #define RELOCATE_COMPILED_RAW_ADDRESS(ad,nb,ob)                \
  420.   (GC_NO_COMPILER_EXPR ((SCHEME_OBJECT)))
  421.  
  422. #define Transport_Compiled() (GC_NO_COMPILER_STMT ())
  423. #define TRANSPORT_RAW_COMPILED() (GC_NO_COMPILER_STMT ())
  424. #define Compiled_BH(flag, then_what) (GC_NO_COMPILER_STMT ())
  425. #define RAW_COMPILED_BH(flag, then_what) (GC_NO_COMPILER_STMT ())
  426. #define Get_Compiled_Block(var, address) (GC_NO_COMPILER_STMT ())
  427.  
  428. #define FIRST_MANIFEST_CLOSURE_ENTRY(scan)                \
  429.   (GC_NO_COMPILER_EXPR ((char *)))
  430.  
  431. #define MANIFEST_CLOSURE_COUNT(scan)                    \
  432.   (GC_NO_COMPILER_EXPR ((long)))
  433.  
  434. #define NEXT_MANIFEST_CLOSURE_ENTRY(word_ptr)                \
  435.   (GC_NO_COMPILER_EXPR ((char *)))
  436.  
  437. #define CLOSURE_ENTRY_END(word_ptr)                    \
  438.   (GC_NO_COMPILER_EXPR ((char *)))
  439.  
  440. #define MANIFEST_CLOSURE_END(end, start)                \
  441.   (GC_NO_COMPILER_EXPR ((SCHEME_OBJECT *)))
  442.  
  443. #define EXTRACT_CLOSURE_ENTRY_ADDRESS(target, source)            \
  444.   (GC_NO_COMPILER_STMT ())
  445.  
  446. #define STORE_CLOSURE_ENTRY_ADDRESS(source, target)            \
  447.   (GC_NO_COMPILER_STMT ())
  448.  
  449. #define READ_LINKAGE_KIND(header)                    \
  450.   (GC_NO_COMPILER_EXPR ((int)))
  451.  
  452. #define READ_CACHE_LINKAGE_COUNT(header)                \
  453.   (GC_NO_COMPILER_EXPR ((int)))
  454.  
  455. #define READ_OPERATOR_LINKAGE_COUNT(header)                \
  456.   (GC_NO_COMPILER_EXPR ((int)))
  457.  
  458. #define END_OPERATOR_LINKAGE_AREA(scan, count)                \
  459.   (GC_NO_COMPILER_EXPR ((SCHEME_OBJECT *)))
  460.  
  461. #define FIRST_OPERATOR_LINKAGE_ENTRY(scan)                \
  462.   (GC_NO_COMPILER_EXPR ((char *)))
  463.  
  464. #define NEXT_LINKAGE_OPERATOR_ENTRY(ptr)                \
  465.   (GC_NO_COMPILER_EXPR ((char *)))
  466.  
  467. #define EXTRACT_OPERATOR_LINKAGE_ADDRESS(target, source)        \
  468.   (GC_NO_COMPILER_STMT ())
  469.  
  470. #define STORE_OPERATOR_LINKAGE_ADDRESS(source, target)            \
  471.   (GC_NO_COMPILER_STMT ())
  472.  
  473. #endif /* HAS_COMPILER_SUPPORT */
  474.  
  475. #ifndef FLUSH_I_CACHE
  476. #  define FLUSH_I_CACHE() do {} while (0)
  477. #endif
  478.  
  479. #if !defined(PUSH_D_CACHE_REGION) && defined(FLUSH_I_CACHE_REGION)
  480. #  define PUSH_D_CACHE_REGION(addr, nwords) FLUSH_I_CACHE_REGION(addr, nwords)
  481. #endif
  482.  
  483. #ifndef COMPILER_TRANSPORT_END
  484. #  define COMPILER_TRANSPORT_END() do                    \
  485. {                                    \
  486.   Registers[REGBLOCK_CLOSURE_SPACE] = ((SCHEME_OBJECT) 0);        \
  487.   Registers[REGBLOCK_CLOSURE_FREE] = ((SCHEME_OBJECT) NULL);        \
  488.   FLUSH_I_CACHE ();                            \
  489. } while (0)
  490. #endif /* COMPILER_TRANSPORT_END */
  491.  
  492. #ifndef START_CLOSURE_RELOCATION
  493. #  define START_CLOSURE_RELOCATION(scan) do { } while (0)
  494. #endif
  495. #ifndef END_CLOSURE_RELOCATION
  496. #  define END_CLOSURE_RELOCATION(scan) do { } while (0)
  497. #endif
  498.  
  499. #ifndef START_OPERATOR_RELOCATION
  500. #  define START_OPERATOR_RELOCATION(scan) do { } while (0)
  501. #endif
  502. #ifndef END_OPERATOR_RELOCATION
  503. #  define END_OPERATOR_RELOCATION(scan) do { } while (0)
  504. #endif
  505.  
  506. #endif /* CMPGC_H_INCLUDED */
  507.