File: Address.ML

package info (click to toggle)
polyml 5.2.1-1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 19,692 kB
  • ctags: 17,567
  • sloc: cpp: 37,221; sh: 9,591; asm: 4,120; ansic: 428; makefile: 203; ml: 191; awk: 91; sed: 10
file content (226 lines) | stat: -rw-r--r-- 7,632 bytes parent folder | download | duplicates (2)
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 *)