/polyml.5.4.1/mlsource/MLCompiler/Boot/Address.ML

# · OCaml · 239 lines · 121 code · 48 blank · 70 comment · 6 complexity · aeeff8750bd37c52c276eaccc8ca813c MD5 · raw file

  1. (*
  2. Copyright (c) 2000
  3. Cambridge University Technical Services Limited
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  15. *)
  16. (*
  17. TODO: This duplicates some of the Word structure although it adds certain
  18. "unsafe" and Poly-specific functions. It probably should be rewritten now
  19. that we have the standard basis library. DCJM June 2000.
  20. *)
  21. structure Address :>
  22. (*****************************************************************************)
  23. (* Address export signature *)
  24. (*****************************************************************************)
  25. sig
  26. type machineWord
  27. type address
  28. type handler
  29. type short = Word.word
  30. val wordEq : 'a * 'a -> bool
  31. val isShort : 'a -> bool
  32. exception Cast of string;
  33. val unsafeCast: 'a -> 'b
  34. val toMachineWord : 'a -> machineWord
  35. val toShort : 'a -> short
  36. val toAddress : 'a -> address
  37. val loadByte: (address * Word.word) -> Word8.word
  38. val loadWord: (address * Word.word) -> machineWord
  39. val assignByte: (address * Word.word * Word8.word) -> unit
  40. val assignWord: (address * Word.word * machineWord) -> unit
  41. val alloc: (short * Word8.word * machineWord) -> address
  42. val maxAllocation: word
  43. val lock: address -> unit
  44. val length: address -> short
  45. val flags: address -> Word8.word
  46. val setFlags: address * Word8.word -> unit
  47. val getFlags: address -> Word8.word
  48. val wordSize: int
  49. val F_words : Word8.word
  50. val F_bytes : Word8.word
  51. val F_code : Word8.word
  52. val F_stack : Word8.word
  53. val F_negative : Word8.word
  54. val F_mutable : Word8.word
  55. val F_gc : Word8.word
  56. val F_noOverwrite : Word8.word
  57. val F_weak : Word8.word
  58. val isWords : address -> bool;
  59. val isBytes : address -> bool;
  60. val isCode : address -> bool;
  61. val isStack : address -> bool;
  62. val isMutable:address -> bool;
  63. val call: (address * machineWord) -> machineWord
  64. val isIoAddress : address -> bool
  65. (* The following function is VERY unsafe and should only be *)
  66. (* used by the Poly/ML code generator (ML version). *)
  67. val offsetAddr : address * short -> handler
  68. end =
  69. let
  70. open RuntimeCalls;
  71. in
  72. (*****************************************************************************)
  73. (* Address structure body *)
  74. (*****************************************************************************)
  75. struct
  76. type machineWord = word (* a legal ML object (tag = 0 or 1) *)
  77. and address = word (* a normal pointer (tag = 0) *)
  78. and handler = word (* pointer to exception handler (tag = 2!) *)
  79. and short = word; (* a 31/63-bit int (tag = 1) *)
  80. (* pointer equality *)
  81. val wordEq = PolyML.pointerEq
  82. val unsafeCast : 'a -> 'b = RunCall.unsafeCast;
  83. local
  84. val short : machineWord->bool = RunCall.run_call1 POLY_SYS_is_short
  85. in
  86. fun isShort (x:'a): bool = unsafeCast short x
  87. end
  88. (* The following cast is always safe *)
  89. val toMachineWord : 'a -> machineWord = unsafeCast;
  90. (* The following casts need checking *)
  91. exception Cast of string;
  92. fun toShort (w:'a) : short =
  93. if isShort w then unsafeCast w else raise Cast "toShort";
  94. fun toAddress (w:'a) : address =
  95. if isShort w then raise Cast "toAddress" else unsafeCast w;
  96. (* Note:
  97. assignByte should *not* be used with word-objects
  98. (we might copy half a pointer into the object,
  99. then call the garbage collector)
  100. loadWord should *not* be used with byte-objects
  101. (we might load something that's not a valid ML value,
  102. then call the garbage collector)
  103. Violating these assertions may corrupt the heap and cause unpredictable
  104. behaviour.
  105. It's safe to use assignWord with a byte-object or loadByte
  106. with a word-object but it may not do what you expect.
  107. One difference is that loadWord / assignWord leave the tag bits
  108. unchanged but loadByte / assignByte strip and replace them.
  109. Another difference is that the offset for the
  110. "Word" functions is in words, whereas the offset for the
  111. "Byte" functions is in bytes.
  112. *)
  113. val loadByte: (address * Word.word) -> Word8.word =
  114. RunCall.run_call2 POLY_SYS_load_byte;
  115. val loadWord: (address * Word.word) -> machineWord =
  116. RunCall.run_call2 POLY_SYS_load_word;
  117. val assignByte: (address * Word.word * Word8.word) -> unit =
  118. RunCall.run_call3 POLY_SYS_assign_byte;
  119. val assignWord: (address * Word.word * machineWord) -> unit =
  120. RunCall.run_call3 POLY_SYS_assign_word;
  121. val maxAllocation: word = RunCall.run_call2 POLY_SYS_process_env(100, ())
  122. fun alloc(len: word, flags: Word8.word, initial: machineWord): address =
  123. (* Zero sized-objects are not allowed. Check that the size is within
  124. the acceptable range. *)
  125. if len = 0w0 orelse len >= maxAllocation
  126. then raise Size
  127. else RunCall.run_call3 POLY_SYS_alloc_store(len, flags, initial)
  128. val lock: address -> unit =
  129. RunCall.run_call1 POLY_SYS_lockseg;
  130. val getFlags: address -> Word8.word =
  131. RunCall.run_call1 POLY_SYS_get_flags;
  132. val setFlags: address * Word8.word -> unit =
  133. RunCall.run_call2 POLY_SYS_code_flags;
  134. val wordSize: int =
  135. RunCall.run_call0 POLY_SYS_bytes_per_word ();
  136. val length: address -> Word.word =
  137. RunCall.run_call1 POLY_SYS_get_length;
  138. val flags: address -> Word8.word =
  139. RunCall.run_call1 POLY_SYS_get_flags;
  140. (* "call" added SPF 7/7/94, corrected 13/7/94, 8/9/94 *)
  141. (* call takes the address of the code of a function [N.B. *NOT* *)
  142. (* the closure for the function] that uses Poly parameter *)
  143. (* conventions (values in registers e.g. an ML secondary entry *)
  144. (* point) and applies it to the address of a single ML tuple. *)
  145. (* N.B. it MUST be a tuple, even if there's only one parameter. *)
  146. (* However, since unit is a "short" not an "address", the type *)
  147. (* of the second parameter has to be "word" (not "address"). *)
  148. (* The run-time system functions all use Poly convention. *)
  149. val call: (address * machineWord) -> machineWord =
  150. RunCall.run_call1 POLY_SYS_callcode_tupled;
  151. val F_words : Word8.word = 0wx00 (* word object - contains pointers and/or tagged values. *)
  152. val F_bytes : Word8.word = 0wx01 (* byte object (contains no pointers) *)
  153. val F_code : Word8.word = 0wx02 (* code object (mixed bytes and words) *)
  154. val F_stack : Word8.word = 0wx03 (* stack object - may contain internal pointers *)
  155. val F_noOverwrite : Word8.word = 0wx08 (* don't overwrite when loading - mutables only. *)
  156. val F_negative : Word8.word = 0wx10 (* sign bit for arbitrary precision ints *)
  157. val F_weak : Word8.word = 0wx20 (* object contains weak references to option values. *)
  158. val F_mutable : Word8.word = 0wx40 (* object is mutable *)
  159. val F_gc : Word8.word = 0wx80 (* object is (pointer or depth) tombstone *)
  160. local
  161. val doCall: int*address -> bool
  162. = RunCall.run_call2 RuntimeCalls.POLY_SYS_process_env
  163. in
  164. fun isIoAddress (a: address) : bool = doCall(102, a)
  165. end
  166. (* The following function is VERY unsafe and should only be *)
  167. (* used by the Poly/ML code generator (ML version). *)
  168. val offsetAddr : address * short -> handler =
  169. RunCall.run_call2 POLY_SYS_offset_address;
  170. local
  171. val typeMask : Word8.word = 0wx03;
  172. fun isType (t: Word8.word) (a: address):bool =
  173. Word8.andb(flags a, typeMask) = t
  174. in
  175. val isWords = isType F_words;
  176. val isBytes = isType F_bytes;
  177. val isCode = isType F_code;
  178. val isStack = isType F_stack;
  179. (* The mutable flag may be used with any of the others. *)
  180. fun isMutable a = Word8.andb(flags a, F_mutable) = F_mutable
  181. end;
  182. end
  183. end; (* open RuntimeCalls *)