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