Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Annotation of /dev-notes/primop-list.md
ViewVC logotype

Annotation of /dev-notes/primop-list.md

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5160 - (view) (download)

1 : jhr 4876 # SML/NJ Primitive Operations
2 :    
3 :     This document describes the primitive operators (primops) that the
4 :     compiler exposes. These are used to define the `InlineT` structure,
5 :     which, in turn is used in the implementation of the Basis Library.
6 :     With the addition of 64-bit targets, the mapping from primop to
7 :     internal representation becomes target-specific in many cases.
8 :    
9 :    
10 :     ## Relavant source files
11 :    
12 :     * `compiler/ElabData/prim/primop.sml`<br/>
13 :     this file defines the `Primop` structure, which includes the various
14 :     datatypes used to represent primitive operations internally in the
15 :     front-end of the compiler. The main type is `Primop.primop`.
16 :    
17 : jhr 4985 * `compiler/ElabData/prim/primop.sig`<br/>
18 : jhr 4876 this file defines the `PRIMOP` signature use for the `Primop` structure.
19 :    
20 :     * `compiler/Semant/prim/primop-bindings.sml`<br/>
21 :     this file defines the bindings between the SML variables
22 :     exposed by the compiler and the internal `Primop.primop`
23 :     type.
24 :    
25 :     * `system/smlnj/init/built-in32.sml`<br/>
26 :     this file defines the `InlineT` structure for 32-bit targets
27 :    
28 :    
29 :     ## Naming conventions
30 :    
31 : jhr 4879 Operations that "belong" to a specific type (*e.g.*, addition) have an initial
32 :     prefix that specifies the type as follows:
33 :    
34 :     * "`int`" -- default tagged integer type (*i.e.*, either `Int31.int` or `Int63.int`)
35 :     * "`word`" -- default tagged word type (*i.e.*, either `Word31.word` or `Word63.word`)
36 :     * "`int32`" -- 32-bit integers
37 :     * "`word32`" -- 32-bit words
38 :     * "`int64`" -- 64-bit integers
39 :     * "`word64`" -- 64-bit words
40 :     * "`intinf`" -- arbitrary precision integers
41 :     * "`real32`" -- 32-bit real numbers (not yet supported)
42 :     * "`real64`" -- 64-bit real numbers
43 :     * "`ptr`" -- machine address
44 :     * "`arr`" -- polymorphic arrays
45 :     * "`vec`" -- polymorphic vectors
46 : jhr 4880 * "`seq`" -- sequence types (arrays and vectors)
47 : jhr 5099 * "`word8_arr`" -- used for arrays of `Word8.word`
48 :     * "`word8_vec`" -- vectors of `Word8.word`
49 :     * "`char_arr`" -- arrays of `char`
50 :     * "`char_vec`" -- vectors of `char` (*i.e.*, strings)
51 :     * "`real64_arr`" -- arrays of `Real64.real`
52 : jhr 4879
53 : jhr 4978 Following the type prefix may one or more attributes, which highlight properties
54 :     of the operation.
55 :    
56 : jhr 4879 We use the attribute "`raw`" to denote direct machine operations that are not
57 :     directly accesible in the Basis Library (*e.g.*, shift operations, where the basis
58 :     versions clamp the shift amount to the word size, but the raw versions do not).
59 :    
60 :     We use the attribute "`unsafe`" for operations that could potentially result in
61 :     a crash (*e.g.*, array subscript operations that do not check the index against
62 :     the array bounds).
63 :    
64 : jhr 4876 ## Primitive operators
65 :    
66 :     ### Size-independent primops
67 :    
68 :     #### Continuation operators
69 :     * `callcc : ('a cont -> 'a) -> 'a`<br/>
70 :     `P.CALLCC`
71 :    
72 :     * `throw : 'a cont -> 'a -> 'b`<br/>
73 :     `P.THROW`
74 :    
75 :     * `capture : ('a control_cont -> 'a) -> 'a`<br/>
76 :     `P.CAPTURE`
77 :    
78 :     * `isolate : ('a -> unit) -> 'a cont`<br/>
79 :     `P.ISOLATE`
80 :    
81 :     * `cthrow : 'a control_cont -> 'a -> 'b`<br/>
82 :     `P.THROW`
83 :    
84 :    
85 :     #### Reference operations
86 :     * `! : 'a ref -> 'a`<br/>
87 :     `P.DEREF`
88 :    
89 : jhr 4879 * `:= : 'a ref * 'a -> unit`<br/>
90 : jhr 4876 `P.ASSIGN`
91 :    
92 :     * `makeref : 'a ref * 'a -> unit`<br/>
93 :     `P.MAKEREF`
94 :    
95 :    
96 :     #### Boxity tests
97 :     * `boxed : 'a -> bool`<br/>
98 :     `P.BOXED`
99 :    
100 :     * `unboxed : 'a -> bool`<br/>
101 :     `P.UNBOXED`
102 :    
103 :    
104 :     #### Type cast
105 :     * `cast : 'a -> 'b`<br/>
106 :     `P.CAST`
107 :    
108 :    
109 :     #### Equality tests
110 :     * `= : ''a * ''a -> bool`<br/>
111 : jhr 5099 Polymorphic equality.<br/>
112 : jhr 4876 `P.POLYEQL`
113 :    
114 :     * `<> : ''a * ''a -> bool`<br/>
115 : jhr 5099 Polymorphic inequality.<br/>
116 : jhr 4876 `P.POLYNEQ`
117 :    
118 : jhr 4885 * `ptr_eql : 'a * 'a -> bool`<br/>
119 : jhr 5099 Pointer equality.<br/>
120 : jhr 4876 `P.PTREQL`
121 :    
122 : jhr 4885 * `ptr_neq : 'a * 'a -> bool`<br/>
123 : jhr 5099 Pointer inequality.<br/>
124 : jhr 4876 `P.PTRNEQ`
125 :    
126 :    
127 :     #### Runtime hooks
128 :     * `getvar : unit -> 'a`<br/>
129 :     `P.GETVAR`
130 :    
131 :     * `setvar : 'a -> unit`<br/>
132 :     `P.SETVAR`
133 :    
134 :     * `mkspecial : int * 'a -> 'b`<br/>
135 :     `P.MKSPECIAL`
136 :    
137 :     * `getspecial : 'a -> int`<br/>
138 :     `P.GETSPECIAL`
139 :    
140 :     * `setspecial : 'a * int -> unit`<br/>
141 :     `P.SETSPECIAL`
142 :    
143 :     * `gethdlr : unit -> 'a cont`<br/>
144 :     `P.GETHDLR`
145 :    
146 :     * `sethdlr : 'a cont -> unit`<br/>
147 :     `P.SETHDLR`
148 :    
149 :     * `gettag : 'a -> int`<br/>
150 :     `P.GETTAG`
151 :    
152 : jhr 4888 * `objlength : 'a -> int`<br/>
153 : jhr 5099 extracts the length field from an object's header word.<br/>
154 :     `P.OBJLENGTH`
155 : jhr 4876
156 :    
157 :     #### Inline operations
158 : jhr 4888 These primops are Basis Library functions that should be inlined for efficiency.
159 : jhr 5020 * `inl_compose : ('b -> 'c) * ('a -> 'b) -> 'a -> 'c`<br/>
160 : jhr 5099 Inline function composition.<br/>
161 : jhr 4876 `P.INLCOMPOSE`
162 :    
163 : jhr 5020 * `inl_before : 'a * 'b -> 'a`<br/>
164 : jhr 5099 Inline `before` operator.<br/>
165 : jhr 4876 `P.INLBEFORE`
166 :    
167 : jhr 5020 * `inl_ignore : 'a -> unit`<br/>
168 : jhr 5099 Inline `ignore` function.<br/>
169 : jhr 4876 `P.INLIGNORE`
170 :    
171 : jhr 5020 * `inl_identity : 'a -> 'a`<br/>
172 : jhr 5099 Inline identity function.<br/>
173 : jhr 4876 `P.INLIDENTITY`
174 :    
175 : jhr 5020 * `inl_bool_not : bool -> bool`<br/>
176 : jhr 5099 Inline boolean negation operator.
177 : jhr 4876 `P.INLNOT`
178 :    
179 : jhr 5020 * `inl_chr : int -> char`<br/>
180 : jhr 5099 Inline `chr` function.<br/>
181 : jhr 5019 `P.INLCHR`
182 : jhr 4978
183 : jhr 5099 * `inl_ord : char -> int`<br/>
184 :     Inline `ord` function.<br/>
185 : jhr 5020 `P.CAST`
186 :    
187 : jhr 5019 Some additional candidates for inlined operations include `hd`, `tl`, and `null`.
188 :    
189 : jhr 4888 If the compiler had the `option` and `order` datatypes builtin (like `bool` and `list`),
190 : jhr 4978 then `valOf`, `isSome`, `isNone` and some of the `compare` functions could also
191 :     be inlined.
192 : jhr 4876
193 : jhr 4978 In the long run, however, a better way to support inlining library functions would
194 :     be through a reliable cross-module inliner.
195 : jhr 4888
196 : jhr 5099 ### Operations on sequences
197 : jhr 4876
198 :     #### Polymorphic array and vector
199 :     * `mkarray : int * 'a -> 'a array`<br/>
200 : jhr 5096 create a polymorphic array; this primop is required to support the
201 : jhr 5099 dictionary-passing representation of polymorphic arrays.<br/>
202 :     `P.INLMKARRAY`
203 : jhr 4876
204 : jhr 4879 * `arr_unsafe_sub : 'a array * int -> 'a`<br/>
205 : jhr 5099 subscript from polymorphic array without bounds checking.<br/>
206 :     `P.SUBSCRIPT`
207 : jhr 4876
208 : jhr 4879 * `arr_sub : 'a array * int -> 'a`<br/>
209 : jhr 5099 subscript from polymorphic array.<br/>
210 :     `P.INLSUBSCRIPT`
211 : jhr 4876
212 : jhr 4879 * `vec_unsafe_sub : 'a vector * int -> 'a`<br/>
213 : jhr 5099 subscript from polymorphic vector without bounds checking.<br/>
214 :     `P.SUBSCRIPTV`
215 : jhr 4876
216 : jhr 4879 * `vec_sub : 'a vector * int -> 'a`<br/>
217 : jhr 5099 subscript from polymorphic vector.<br/>
218 :     `P.INLSUBSCRIPTV`
219 : jhr 4876
220 : jhr 4879 * `arr_unsafe_update : 'a array * int * 'a -> unit`<br/>
221 : jhr 5099 update a polymorphic array without bounds checking.<br/>
222 :     `P.UPDATE`
223 : jhr 4876
224 : jhr 4879 * `arr_update : 'a array * int * 'a -> unit`<br/>
225 : jhr 5099 update a polymorphic array.<br/>
226 :     `P.INLUPDATE`
227 : jhr 4876
228 : jhr 4879 * `arr_unboxed_update : 'a array * int * 'a -> unit`<br/>
229 :     update a polymorphic array with an unboxed value, which means that there is
230 : jhr 5099 no store-list entry created for the update.<br/>
231 :     `P.UNBOXEDUPDATE`
232 : jhr 4876
233 :     #### Sequence operations
234 : jhr 4880 Sequence values (*e.g.*, `string`, `'a array`, `RealVector.vector`, *etc*.)
235 :     are represented by a header consisting of a length (in elements) and a data
236 :     pointer to the raw sequence data.
237 :    
238 : jhr 4876 * `newArray0 : unit -> 'a`<br/>
239 :     `P.NEW_ARRAY0`
240 :    
241 : jhr 4880 * `seq_length : 'a -> int`<br/>
242 : jhr 5099 get the length field from a sequence header.<br/>
243 :     `P.LENGTH`
244 : jhr 4880
245 :     * `seq_data : 'a -> 'b`<br/>
246 : jhr 5099 get the length field from a sequence header.<br/>
247 :     `P.GET_SEQ_DATA`
248 : jhr 4876
249 :     * `raw64Sub : 'a * int -> real64`<br/>
250 : jhr 4978 gets an element from a packed tuple of 64-bit reals. The only use of
251 :     this function is in the implementation of the `Unsafe.Object.nth`
252 :     function. <br/>
253 : jhr 5099 `P.SUBSCRIPT_RAW64`
254 : jhr 4876
255 : jhr 5099 * `recordSub : 'a * int -> 'b`<br/>
256 :     gets an element from a record object. This is used by the `Unsafe.Object`
257 :     and `SMLofNJ.Weak` structures to access the components of records. <br/>
258 :     `P.P.SUBSCRIPT_REC`.
259 : jhr 4876
260 : jhr 5099 #### Byte-array and byte-vector operations
261 :     Operations on arrays/vectors of unsigned bytes.
262 :    
263 :     * `word8_vec_sub : word8vector * int -> word8`<br/>
264 :     subscript from byte vector.<br/>
265 :     `P.INLNUMSUBSCRIPTV(P.UINT 8)`
266 :    
267 :     * `word8_vec_unsafe_sub : word8vector * int -> word8`<br/>
268 :     subscript from byte vector without bounds checking.<br/>
269 :     `P.NUMSUBSCRIPTV(P.UINT 8)`
270 :    
271 :     * `word8_vec_unsafe_update : word8vector * int * word8 -> unit`<br/>
272 :     destructive update of a vector without bounds checking.
273 :     This operation is used to implement vector initialization.<br/>
274 :     `P.NUMUPDATE(P.UINT 8)`
275 :    
276 :     * `word8_arr_sub : word8array * int -> word8`<br/>
277 :     subscript from byte array.<br/>
278 :     `P.INLNUMSUBSCRIPT(P.UINT 8)`
279 :    
280 :     * `word8_arr_update : word8array * int * word8 -> unit`<br/>
281 :     update byte array.<br/>
282 :     `P.INLNUMUPDATE(P.UINT 8)`
283 :    
284 :     * `word8_arr_unsafe_sub : word8array * int -> word8`<br/>
285 :     subscript from byte array without bounds checking.<br/>
286 :     `P.NUMSUBSCRIPT(P.UINT 8)`
287 :    
288 :     * `word8_arr_unsafe_update : word8array * int * word8 -> unit`<br/>
289 :     update byte array without bounds checking.<br/>
290 :     `P.NUMUPDATE(P.UINT 8)`
291 :    
292 :     #### Char-array and char-vector operations
293 :     Operations on arrays/vectors of 8-bit characters.
294 :    
295 :     * `char_vec_sub : charvector * int -> char`<br/>
296 :     subscript from byte vector.<br/>
297 :     `P.INLNUMSUBSCRIPTV(P.UINT 8)`
298 :    
299 :     * `char_vec_unsafe_sub : charvector * int -> char`<br/>
300 :     subscript from byte vector without bounds checking.<br/>
301 :     `P.NUMSUBSCRIPTV(P.UINT 8)`
302 :    
303 :     * `char_vec_unsafe_update : charvector * int * char -> unit`<br/>
304 :     destructive update of a vector without bounds checking.
305 :     This operation is used to implement vector initialization.<br/>
306 :     `P.NUMUPDATE(P.UINT 8)`
307 :    
308 :     * `char_arr_sub : chararray * int -> char`<br/>
309 :     subscript from byte array.<br/>
310 :     `P.INLNUMSUBSCRIPT(P.UINT 8)`
311 :    
312 :     * `char_arr_update : chararray * int * char -> unit`<br/>
313 :     update byte array.<br/>
314 :     `P.INLNUMUPDATE(P.UINT 8)`
315 :    
316 :     * `char_arr_unsafe_sub : chararray * int -> char`<br/>
317 :     subscript from byte array without bounds checking.<br/>
318 :     `P.NUMSUBSCRIPT(P.UINT 8)`
319 :    
320 :     * `char_arr_unsafe_update : chararray * int * char -> unit`<br/>
321 :     update byte array without bounds checking.<br/>
322 :     `P.NUMUPDATE(P.UINT 8)`
323 :    
324 :     #### Real-array operations
325 :     Operations on arrays of 64-bit reals. Currently the real vector type is
326 :     implemented using polymorphic vectors, but eventually we should support
327 :     a packed representation for it too.
328 :    
329 :     * `real64_arr_sub : real64array * int -> real64`<br/>
330 :     subscript from byte array.<br/>
331 :     `P.INLNUMSUBSCRIPT(P.UINT 8)`
332 :    
333 :     * `real64_arr_update : real64array * int * real64 -> unit`<br/>
334 :     update byte array.<br/>
335 :     `P.INLNUMUPDATE(P.UINT 8)`
336 :    
337 :     * `real64_arr_unsafe_sub : real64array * int -> real64`<br/>
338 :     subscript from byte array without bounds checking.<br/>
339 :     `P.NUMSUBSCRIPT(P.UINT 8)`
340 :    
341 :     * `real64_arr_unsafe_update : real64array * int * real64 -> unit`<br/>
342 :     update byte array without bounds checking.<br/>
343 :     `P.NUMUPDATE(P.UINT 8)`
344 :    
345 : jhr 4876 ### Numeric primops
346 :    
347 :     #### Default tagged integer operations
348 : jhr 4879 These are the primitive operations on the default tagged integer
349 :     type (`Int.int`).
350 :    
351 : jhr 4876 * `int_add : int * int -> int`<br/>
352 : jhr 4884 Signed integer addition with overflow checking.
353 : jhr 5019 (`P.IARITH{oper=P.IADD, sz=<int-size>}`)
354 : jhr 4876
355 :     * `int_sub : int * int -> int`<br/>
356 : jhr 4884 Signed integer subtraction with overflow checking.
357 : jhr 5019 (`P.IARITH{oper=P.ISUB, sz=<int-size>}`)
358 : jhr 4876
359 :     * `int_mul : int * int -> int`<br/>
360 : jhr 5019 `P.IARITH{oper=P.IMUL, sz=<int-size>}`
361 : jhr 4876
362 :     * `int_div : int * int -> int`<br/>
363 : jhr 5020 `P.INLDIV(P.INT <int-size>)`
364 : jhr 4876
365 :     * `int_mod : int * int -> int`<br/>
366 : jhr 5020 `P.INLMOD(P.INT <int-size>)`
367 : jhr 4876
368 :     * `int_quot : int * int -> int`<br/>
369 : jhr 5020 `P.INLQUOT(P.INT <int-size>)`
370 : jhr 4876
371 :     * `int_rem : int * int -> int`<br/>
372 : jhr 5020 `P.INLREM(P.INT <int-size>)`
373 : jhr 4876
374 :     * `int_neg : word32 -> word32`<br/>
375 : jhr 5019 `P.IARITH{oper=P.INEG, sz=<int-size>}`
376 : jhr 4876
377 : jhr 5020 * `int_lt : int * int -> bool`<br/>
378 :     `P.CMP{oper=P.LT, kind=P.INT <int-size>}`
379 : jhr 4876
380 : jhr 5020 * `int_le : int * int -> bool`<br/>
381 :     `P.CMP{oper=P.LTE, kind=P.INT <int-size>}`
382 : jhr 4876
383 :     * `int_gt : int * int -> bool`<br/>
384 :     `P.CMP{oper=P.GT, kind=P.INT <int-size>}`
385 :    
386 :     * `int_ge : int * int -> bool`<br/>
387 :     `P.CMP{oper=P.GTE, kind=P.INT <int-size>}`
388 :    
389 : jhr 4885 * `int_eql : int * int -> bool`<br/>
390 : jhr 4876 `P.CMP{oper=P.EQL, kind=P.INT <int-size>}`
391 :    
392 : jhr 4885 * `int_neq : int * int -> bool`<br/>
393 : jhr 4876 `P.CMP{oper=P.NEQ, kind=P.INT <int-size>}`
394 :    
395 :     * `int_min : int * int -> int`<br/>
396 :     `P.INLMIN (P.INT <int-size>)`
397 :    
398 :     * `int_max : int * int -> int`<br/>
399 :     `P.INLMAX (P.INT <int-size>)`
400 :    
401 : jhr 4985 * `int_abs : int -> int`<br/>
402 : jhr 4876 `P.INLABS (P.INT <int-size>)`
403 :    
404 : jhr 5020 For the default integer type, we add some additional operations that help
405 :     simplify the **Basis Library** implementation.
406 :    
407 :     * `int_unsafe_add : int * int -> int`<br/>
408 : jhr 5099 Signed integer addition *without* overflow checking. This operation
409 :     is used for index computations on sequences.<br/>
410 :     `P.PURE_ARITH{oper=P.ADD, kind=P.UINT <int-size>}`
411 : jhr 5020
412 :     * `int_unsafe_sub : int * int -> int`<br/>
413 : jhr 5099 Signed integer subtraction *without* overflow checking. This operation
414 :     is used for index computations on sequences.<br/>
415 :     `P.PURE_ARITH{oper=P.SUB, kind=P.UINT <int-size>}`
416 : jhr 5020
417 :     * `int_orb : int * int -> int`<br/>
418 :     `P.PURE_ARITH{oper=P.ORB, kind=P.UINT <int-size>}`
419 :    
420 :     * `int_xorb : int * int -> int`<br/>
421 :     `P.PURE_ARITH{oper=P.XORB, kind=P.UINT <int-size>}`
422 :    
423 :     * `int_andb : int * int -> int`<br/>
424 :     `P.PURE_ARITH{oper=P.ANDB, kind=P.UINT <int-size>}`
425 :    
426 : jhr 5099 * `int_notb : int -> int`<br/>
427 : jhr 5020 `P.PURE_ARITH{oper=P.NOTB, sz=P.UINT <int-size>}`
428 :    
429 :     * `int_raw_rshift : int * word -> int`<br/>
430 :     `P.PURE_ARITH{oper=P.RSHIFT, kind=P.UINT <int-size>}`
431 :    
432 :     * `int_raw_lshift : int * word -> int`<br/>
433 :     `P.PURE_ARITH{oper=P.LSHIFT, kind=P.UINT <int-size>}`
434 :    
435 : jhr 5099 * `int_ltu : int * int -> bool`<br/>
436 :     Unsigned comparison of integers (used for bounds checking).<br/>
437 :     `P.CMP{oper=P.GTE, kind=P.UINT <int-size>}`
438 :    
439 :     * `int_geu : int * int -> bool`<br/>
440 :     Unsigned comparison of integers (used for bounds checking).<br/>
441 :     `P.CMP{oper=P.GTE, kind=P.UINT <int-size>}`
442 :    
443 : jhr 4876 #### Default tagged word operations
444 : jhr 4879 These are the primitive operations on the default tagged word
445 :     type (`Word.word`).
446 :    
447 : jhr 5020 * `word_add : word * word -> word`<br/>
448 :     `P.PURE_ARITH{oper=P.ADD, kind=P.UINT <int-size>}`
449 :    
450 :     * `word_sub : word * word -> word`<br/>
451 :     `P.PURE_ARITH{oper=P.SUB, kind=P.UINT <int-size>}`
452 :    
453 : jhr 4876 * `word_mul : word * word -> word`<br/>
454 : jhr 5019 `P.PURE_ARITH{oper=P.MUL, kind=P.UINT <int-size>}`
455 : jhr 4876
456 :     * `word_div : word * word -> word`<br/>
457 : jhr 5020 `P.INLQUOT(P.UINT <int-size>)`
458 : jhr 4876
459 :     * `word_mod : word * word -> word`<br/>
460 : jhr 5020 `P.INLREM(P.UINT <int-size>)`
461 : jhr 4876
462 :     * `word_orb : word * word -> word`<br/>
463 : jhr 5019 `P.PURE_ARITH{oper=P.ORB, kind=P.UINT <int-size>}`
464 : jhr 4876
465 :     * `word_xorb : word * word -> word`<br/>
466 : jhr 5019 `P.PURE_ARITH{oper=P.XORB, kind=P.UINT <int-size>}`
467 : jhr 4876
468 :     * `word_andb : word * word -> word`<br/>
469 : jhr 5019 `P.PURE_ARITH{oper=P.ANDB, kind=P.UINT <int-size>}`
470 : jhr 4876
471 :     * `word_notb : word -> word`<br/>
472 : jhr 5019 `P.PURE_ARITH{oper=P.NOTB, kind=P.UINT <int-size>}`
473 : jhr 4876
474 :     * `word_neg : word -> word`<br/>
475 : jhr 5019 `P.PURE_ARITH{oper=P.NEG, kind=P.UINT <int-size>}`
476 : jhr 4876
477 :     * `word_rshift : word * word -> word`<br/>
478 : jhr 4985 `P.INLRSHIFT(P.UINT <int-size>)`
479 : jhr 4876
480 :     * `word_rshiftl : word * word -> word`<br/>
481 : jhr 4985 `P.INLRSHIFTL(P.UINT <int-size>)`
482 : jhr 4876
483 :     * `word_lshift : word * word -> word`<br/>
484 : jhr 5019 `P.PURE_ARITH{oper=P.LSHIFT, kind=P.UINT <int-size>}`
485 : jhr 4876
486 : jhr 4985 * `word_raw_rshift : word * word -> word`<br/>
487 :     `P.INLLSHIFT(P.UINT <int-size>)`
488 :    
489 :     * `word_raw_rshiftl : word * word -> word`<br/>
490 : jhr 5019 `P.PURE_ARITH{oper=P.RSHIFTL, kind=P.UINT <int-size>}`
491 : jhr 4985
492 :     * `word_raw_lshift : word * word -> word`<br/>
493 : jhr 5019 `P.PURE_ARITH{oper=P.RSHIFT, kind=P.UINT <int-size>}`
494 : jhr 4985
495 : jhr 4876 * `word_gt : word * word -> bool`<br/>
496 :     `P.CMP{oper=P.GT, kind=P.UINT <int-size>}`
497 :    
498 :     * `word_ge : word * word -> bool`<br/>
499 :     `P.CMP{oper=P.GTE, kind=P.UINT <int-size>}`
500 :    
501 :     * `word_lt : word * word -> bool`<br/>
502 :     `P.CMP{oper=P.LT, kind=P.UINT <int-size>}`
503 :    
504 :     * `word_le : word * word -> bool`<br/>
505 :     `P.CMP{oper=P.LTE, kind=P.UINT <int-size>}`
506 :    
507 : jhr 4885 * `word_eql : word * word -> bool`<br/>
508 : jhr 4876 `P.CMP{oper=P.EQL, kind=P.UINT <int-size>}`
509 :    
510 : jhr 4885 * `word_neq : word * word -> bool`<br/>
511 : jhr 4876 `P.CMP{oper=P.NEQ, kind=P.UINT <int-size>}`
512 :    
513 :     * `word_min : word * word -> word`<br/>
514 :     `P.INLMIN (P.UINT <int-size>)`
515 :    
516 :     * `word_max : word * word -> word`<br/>
517 :     `P.INLMAX (P.UINT <int-size>)`
518 :    
519 :     #### 32-bit integer operations
520 :     * `int32_add : int32 * int32 -> int32`<br/>
521 : jhr 5019 `P.IARITH{oper=P.IADD, sz=32}`
522 : jhr 4876
523 :     * `int32_sub : int32 * int32 -> int32`<br/>
524 : jhr 5019 `P.IARITH{oper=P.ISUB, sz=32}`
525 : jhr 4876
526 :     * `int32_mul : int32 * int32 -> int32`<br/>
527 : jhr 5019 `P.IARITH{oper=P.IMUL, sz=32}`
528 : jhr 4876
529 :     * `int32_div : int32 * int32 -> int32`<br/>
530 : jhr 5160 `P.INLDIV(P.INT 32)`
531 : jhr 4876
532 :     * `int32_mod : int32 * int32 -> int32`<br/>
533 : jhr 5160 `P.INLMOD(P.INT 32)`
534 : jhr 4876
535 :     * `int32_quot : int32 * int32 -> int32`<br/>
536 : jhr 5160 `P.INLQUOT(P.INT 32)`
537 : jhr 4876
538 :     * `int32_rem : int32 * int32 -> int32`<br/>
539 : jhr 5160 `P.INLREM(P.INT 32)`
540 : jhr 4876
541 :     * `int32_neg : word32 -> word32`<br/>
542 : jhr 5019 `P.IARITH{oper=P.INEG, sz=32}`
543 : jhr 4876
544 :     * `int32_gt : int32 * int32 -> bool`<br/>
545 :     `P.CMP{oper=P.GT, kind=P.INT 32}`
546 :    
547 :     * `int32_ge : int32 * int32 -> bool`<br/>
548 :     `P.CMP{oper=P.GTE, kind=P.INT 32}`
549 :    
550 :     * `int32_lt : int32 * int32 -> bool`<br/>
551 :     `P.CMP{oper=P.LT, kind=P.INT 32}`
552 :    
553 :     * `int32_le : int32 * int32 -> bool`<br/>
554 :     `P.CMP{oper=P.LTE, kind=P.INT 32}`
555 :    
556 : jhr 4885 * `int32_eql : int32 * int32 -> bool`<br/>
557 : jhr 4876 `P.CMP{oper=P.EQL, kind=P.INT 32}`
558 :    
559 : jhr 4885 * `int32_neq : int32 * int32 -> bool`<br/>
560 : jhr 4876 `P.CMP{oper=P.NEQ, kind=P.INT 32}`
561 :    
562 :     * `int32_min : int32 * int32 -> int32`<br/>
563 :     `P.INLMIN (P.INT 32)`
564 :    
565 :     * `int32_max : int32 * int32 -> int32`<br/>
566 :     `P.INLMAX (P.INT 32)`
567 :    
568 : jhr 4985 * `int32_abs : int32 -> int32`<br/>
569 : jhr 4876 `P.INLABS (P.INT 32)`
570 :    
571 : jhr 5099 #### 8-bit word operations
572 :    
573 : jhr 5160 * `word8_add : word8 * word8 -> word8`<br/>
574 :     `P.PURE_ARITH{oper=P.ADD, kind=P.UINT 8}`
575 :    
576 :     * `word8_sub : word8 * word8 -> word8`<br/>
577 :     `P.PURE_ARITH{oper=P.SUB, kind=P.UINT 8}`
578 :    
579 : jhr 5099 * `word8_mul : word8 * word8 -> word8`<br/>
580 :     `P.PURE_ARITH{oper=P.MUL, kind=P.UINT 8}`
581 :    
582 :     * `word8_div : word8 * word8 -> word8`<br/>
583 : jhr 5160 `P.INLQUOT(P.UINT 8)`
584 : jhr 5099
585 :     * `word8_mod : word8 * word8 -> word8`<br/>
586 : jhr 5160 `P.INLREM(P.UINT 8)`
587 : jhr 5099
588 :     * `word8_orb : word8 * word8 -> word8`<br/>
589 :     `P.PURE_ARITH{oper=P.ORB, kind=P.UINT 8}`
590 :    
591 :     * `word8_xorb : word8 * word8 -> word8`<br/>
592 :     `P.PURE_ARITH{oper=P.XORB, kind=P.UINT 8}`
593 :    
594 :     * `word8_andb : word8 * word8 -> word8`<br/>
595 :     `P.PURE_ARITH{oper=P.ANDB, kind=P.UINT 8}`
596 :    
597 :     * `word8_notb : word8 -> word8`<br/>
598 :     `P.PURE_ARITH{oper=P.NOTB, kind=P.UINT 8}`
599 :    
600 :     * `word8_neg : word8 -> word8`<br/>
601 :     `P.PURE_ARITH{oper=P.NEG, kind=P.UINT 8}`
602 :    
603 :     * `word8_rshift : word8 * word -> word`<br/>
604 :     `P.INLRSHIFT(P.UINT 8)`
605 :    
606 :     * `word8_rshiftl : word8 * word -> word`<br/>
607 :     `P.INLRSHIFTL(P.UINT 8)`
608 :    
609 :     * `word8_lshift : word8 * word -> word`<br/>
610 :     `P.INLLSHIFT(P.UINT 8)`
611 :    
612 :     * `word8_raw_rshift : word8 * word -> word`<br/>
613 :     `P.PURE_ARITH{oper=P.RSHIFT, kind=P.UINT 8}`
614 :    
615 :     * `word8_raw_rshiftl : word8 * word -> word`<br/>
616 :     `P.PURE_ARITH{oper=P.RSHIFTL, kind=P.UINT 8}`
617 :    
618 :     * `word8_raw_lshift : word8 * word -> word`<br/>
619 :     `P.PURE_ARITH{oper=P.LSHIFT, kind=P.UINT 8}`
620 :    
621 :     * `word8_gt : word8 * word8 -> bool`<br/>
622 :     `P.CMP{oper=P.GT, kind=P.UINT 8}`
623 :    
624 :     * `word8_ge : word8 * word8 -> bool`<br/>
625 :     `P.CMP{oper=P.GTE, kind=P.UINT 8}`
626 :    
627 :     * `word8_lt : word8 * word8 -> bool`<br/>
628 :     `P.CMP{oper=P.LT, kind=P.UINT 8}`
629 :    
630 :     * `word8_le : word8 * word8 -> bool`<br/>
631 :     `P.CMP{oper=P.LTE, kind=P.UINT 8}`
632 :    
633 :     * `word8_eql : word8 * word8 -> bool`<br/>
634 :     `P.CMP{oper=P.EQL, kind=P.UINT 8}`
635 :    
636 :     * `word8_neq : word8 * word8 -> bool`<br/>
637 :     `P.CMP{oper=P.NEQ, kind=P.UINT 8}`
638 :    
639 :     * `word8_min : word8 * word8 -> word8`<br/>
640 :     `P.INLMIN (P.UINT 8)`
641 :    
642 :     * `word8_max : word8 * word8 -> word8`<br/>
643 :     `P.INLMAX (P.UINT 8)`
644 :    
645 : jhr 4876 #### 32-bit word operations
646 : jhr 4985 These operations work on the boxed 32-bit word type on 32-bit
647 :     machines and are just wrappers for 63-bit tagged word operations
648 :     on 64-bit machines.
649 : jhr 4876
650 : jhr 5160 * `word32_add : word32 * word32 -> word32`<br/>
651 :     `P.PURE_ARITH{oper=P.ADD, kind=P.UINT 32}`
652 :    
653 :     * `word32_sub : word32 * word32 -> word32`<br/>
654 :     `P.PURE_ARITH{oper=P.SUB, kind=P.UINT 32}`
655 :    
656 : jhr 4985 * `word32_mul : word32 * word32 -> word32`<br/>
657 : jhr 5019 `P.PURE_ARITH{oper=P.MUL, kind=P.UINT 32}`
658 : jhr 4985
659 :     * `word32_div : word32 * word32 -> word32`<br/>
660 : jhr 5160 `P.INLQUOT(P.UINT 32)`
661 : jhr 4985
662 :     * `word32_mod : word32 * word32 -> word32`<br/>
663 : jhr 5160 `P.INLREM(P.UINT 32)`
664 : jhr 4985
665 :     * `word32_orb : word32 * word32 -> word32`<br/>
666 : jhr 5019 `P.PURE_ARITH{oper=P.ORB, kind=P.UINT 32}`
667 : jhr 4985
668 :     * `word32_xorb : word32 * word32 -> word32`<br/>
669 : jhr 5019 `P.PURE_ARITH{oper=P.XORB, kind=P.UINT 32}`
670 : jhr 4985
671 :     * `word32_andb : word32 * word32 -> word32`<br/>
672 : jhr 5019 `P.PURE_ARITH{oper=P.ANDB, kind=P.UINT 32}`
673 : jhr 4985
674 :     * `word32_notb : word32 -> word32`<br/>
675 : jhr 5019 `P.PURE_ARITH{oper=P.NOTB, kind=P.UINT 32}`
676 : jhr 4985
677 :     * `word32_neg : word32 -> word32`<br/>
678 : jhr 5019 `P.PURE_ARITH{oper=P.NEG, kind=P.UINT 32}`
679 : jhr 4985
680 :     * `word32_rshift : word32 * word -> word`<br/>
681 :     `P.INLRSHIFT(P.UINT 32)`
682 :    
683 :     * `word32_rshiftl : word32 * word -> word`<br/>
684 :     `P.INLRSHIFTL(P.UINT 32)`
685 :    
686 :     * `word32_lshift : word32 * word -> word`<br/>
687 :     `P.INLLSHIFT(P.UINT 32)`
688 :    
689 :     * `word32_raw_rshift : word32 * word -> word`<br/>
690 : jhr 5019 `P.PURE_ARITH{oper=P.RSHIFT, kind=P.UINT 32}`
691 : jhr 4985
692 :     * `word32_raw_rshiftl : word32 * word -> word`<br/>
693 : jhr 5019 `P.PURE_ARITH{oper=P.RSHIFTL, kind=P.UINT 32}`
694 : jhr 4985
695 :     * `word32_raw_lshift : word32 * word -> word`<br/>
696 : jhr 5019 `P.PURE_ARITH{oper=P.LSHIFT, kind=P.UINT 32}`
697 : jhr 4985
698 :     * `word32_gt : word32 * word32 -> bool`<br/>
699 :     `P.CMP{oper=P.GT, kind=P.UINT 32}`
700 :    
701 :     * `word32_ge : word32 * word32 -> bool`<br/>
702 :     `P.CMP{oper=P.GTE, kind=P.UINT 32}`
703 :    
704 :     * `word32_lt : word32 * word32 -> bool`<br/>
705 :     `P.CMP{oper=P.LT, kind=P.UINT 32}`
706 :    
707 :     * `word32_le : word32 * word32 -> bool`<br/>
708 :     `P.CMP{oper=P.LTE, kind=P.UINT 32}`
709 :    
710 :     * `word32_eql : word32 * word32 -> bool`<br/>
711 :     `P.CMP{oper=P.EQL, kind=P.UINT 32}`
712 :    
713 :     * `word32_neq : word32 * word32 -> bool`<br/>
714 :     `P.CMP{oper=P.NEQ, kind=P.UINT 32}`
715 :    
716 :     * `word32_min : word32 * word32 -> word32`<br/>
717 :     `P.INLMIN (P.UINT 32)`
718 :    
719 :     * `word32_max : word32 * word32 -> word32`<br/>
720 :     `P.INLMAX (P.UINT 32)`
721 :    
722 : jhr 4876 #### 64-bit integer operations
723 : jhr 5099 **Note:** 64-bit integer operations are currently not supported in the compiler,
724 :     but we expect to add them in 110.88.
725 :    
726 : jhr 4876 * `int64_add : int64 * int64 -> int64`<br/>
727 : jhr 5019 `P.IARITH{oper=P.IADD, sz=64}`
728 : jhr 4876
729 :     * `int64_sub : int64 * int64 -> int64`<br/>
730 : jhr 5019 `P.IARITH{oper=P.ISUB, sz=64}`
731 : jhr 4876
732 :     * `int64_mul : int64 * int64 -> int64`<br/>
733 : jhr 5019 `P.IARITH{oper=P.IMUL, sz=64}`
734 : jhr 4876
735 :     * `int64_div : int64 * int64 -> int64`<br/>
736 : jhr 5160 `P.INLDIV(P.INT 64)`
737 : jhr 4876
738 :     * `int64_mod : int64 * int64 -> int64`<br/>
739 : jhr 5160 `P.INLMOD(P.INT 64)`
740 : jhr 4876
741 :     * `int64_quot : int64 * int64 -> int64`<br/>
742 : jhr 5160 `P.INLQUOT(P.INT 64)`
743 : jhr 4876
744 :     * `int64_rem : int64 * int64 -> int64`<br/>
745 : jhr 5160 `P.INLREM(P.INT 64)`
746 : jhr 4876
747 :     * `int64_neg : word32 -> word32`<br/>
748 : jhr 5019 `P.IARITH{oper=P.INEG, sz=64}`
749 : jhr 4876
750 :     * `int64_gt : int64 * int64 -> bool`<br/>
751 :     `P.CMP{oper=P.GT, kind=P.INT 64}`
752 :    
753 :     * `int64_ge : int64 * int64 -> bool`<br/>
754 :     `P.CMP{oper=P.GTE, kind=P.INT 64}`
755 :    
756 :     * `int64_lt : int64 * int64 -> bool`<br/>
757 :     `P.CMP{oper=P.LT, kind=P.INT 64}`
758 :    
759 :     * `int64_le : int64 * int64 -> bool`<br/>
760 :     `P.CMP{oper=P.LTE, kind=P.INT 64}`
761 :    
762 : jhr 4885 * `int64_eql : int64 * int64 -> bool`<br/>
763 : jhr 4876 `P.CMP{oper=P.EQL, kind=P.INT 64}`
764 :    
765 : jhr 4885 * `int64_neq : int64 * int64 -> bool`<br/>
766 : jhr 4876 `P.CMP{oper=P.NEQ, kind=P.INT 64}`
767 :    
768 :     * `int64_min : int64 * int64 -> int64`<br/>
769 :     `P.INLMIN (P.INT 64)`
770 :    
771 :     * `int64_max : int64 * int64 -> int64`<br/>
772 :     `P.INLMAX (P.INT 64)`
773 :    
774 : jhr 4985 * `int64_abs : int64 -> int64`<br/>
775 : jhr 4876 `P.INLABS (P.INT 64)`
776 :    
777 :     #### 64-bit word operations
778 : jhr 5099 **Note:** 64-bit word operations are currently not supported in the compiler,
779 :     but we expect to add them in 110.88.
780 : jhr 4876
781 : jhr 5160 * `word64_add : word64 * word64 -> word64`<br/>
782 :     `P.PURE_ARITH{oper=P.ADD, kind=P.UINT 64}`
783 :    
784 :     * `word64_sub : word64 * word64 -> word64`<br/>
785 :     `P.PURE_ARITH{oper=P.SUB, kind=P.UINT 64}`
786 :    
787 : jhr 4985 * `word64_mul : word64 * word64 -> word64`<br/>
788 : jhr 5019 `P.PURE_ARITH{oper=P.MUL, kind=P.UINT 64}`
789 : jhr 4985
790 :     * `word64_div : word64 * word64 -> word64`<br/>
791 : jhr 5160 `P.INLQUOT(P.UINT 32)`
792 : jhr 4985
793 :     * `word64_mod : word64 * word64 -> word64`<br/>
794 : jhr 5160 `P.INLREM(P.UINT 32)`
795 : jhr 4985
796 :     * `word64_orb : word64 * word64 -> word64`<br/>
797 : jhr 5019 `P.PURE_ARITH{oper=P.ORB, kind=P.UINT 64}`
798 : jhr 4985
799 :     * `word64_xorb : word64 * word64 -> word64`<br/>
800 : jhr 5019 `P.PURE_ARITH{oper=P.XORB, kind=P.UINT 64}`
801 : jhr 4985
802 :     * `word64_andb : word64 * word64 -> word64`<br/>
803 : jhr 5019 `P.PURE_ARITH{oper=P.ANDB, kind=P.UINT 64}`
804 : jhr 4985
805 :     * `word64_notb : word64 -> word64`<br/>
806 : jhr 5019 `P.PURE_ARITH{oper=P.NOTB, kind=P.UINT 64}`
807 : jhr 4985
808 :     * `word64_neg : word64 -> word64`<br/>
809 : jhr 5019 `P.PURE_ARITH{oper=P.NEG, kind=P.UINT 64}`
810 : jhr 4985
811 :     * `word64_rshift : word64 * word -> word`<br/>
812 :     `P.INLRSHIFT(P.UINT 64)`
813 :    
814 :     * `word64_rshiftl : word64 * word -> word`<br/>
815 :     `P.INLRSHIFTL(P.UINT 64)`
816 :    
817 :     * `word64_lshift : word64 * word -> word`<br/>
818 :     `P.INLLSHIFT(P.UINT 64)`
819 :    
820 :     * `word64_raw_rshift : word64 * word -> word`<br/>
821 : jhr 5019 `P.PURE_ARITH{oper=P.RSHIFT, kind=P.UINT 64}`
822 : jhr 4985
823 :     * `word64_raw_rshiftl : word64 * word -> word`<br/>
824 : jhr 5019 `P.PURE_ARITH{oper=P.RSHIFTL, kind=P.UINT 64}`
825 : jhr 4985
826 :     * `word64_raw_lshift : word64 * word -> word`<br/>
827 : jhr 5019 `P.PURE_ARITH{oper=P.LSHIFT, kind=P.UINT 64}`
828 : jhr 4985
829 :     * `word64_gt : word64 * word64 -> bool`<br/>
830 :     `P.CMP{oper=P.GT, kind=P.UINT 64}`
831 :    
832 :     * `word64_ge : word64 * word64 -> bool`<br/>
833 :     `P.CMP{oper=P.GTE, kind=P.UINT 64}`
834 :    
835 :     * `word64_lt : word64 * word64 -> bool`<br/>
836 :     `P.CMP{oper=P.LT, kind=P.UINT 64}`
837 :    
838 :     * `word64_le : word64 * word64 -> bool`<br/>
839 :     `P.CMP{oper=P.LTE, kind=P.UINT 64}`
840 :    
841 :     * `word64_eql : word64 * word64 -> bool`<br/>
842 :     `P.CMP{oper=P.EQL, kind=P.UINT 64}`
843 :    
844 :     * `word64_neq : word64 * word64 -> bool`<br/>
845 :     `P.CMP{oper=P.NEQ, kind=P.UINT 64}`
846 :    
847 :     * `word64_min : word64 * word64 -> word64`<br/>
848 :     `P.INLMIN (P.UINT 64)`
849 :    
850 :     * `word64_max : word64 * word64 -> word64`<br/>
851 :     `P.INLMAX (P.UINT 64)`
852 :    
853 : jhr 4876 #### 64-bit real operations
854 : jhr 4985 * `real64_add : real64 * real64 -> real64`<br/>
855 : jhr 5020 `P.PURE_ARITH{oper=P.ADD, overflow=true, kind=P.FLOAT 64}`
856 : jhr 4876
857 : jhr 4985 * `real64_sub : real64 * real64 -> real64`<br/>
858 : jhr 5020 `P.PURE_ARITH{oper=P.SUB, overflow=true, kind=P.FLOAT 64}`
859 : jhr 4985
860 :     * `real64_mul : real64 * real64 -> real64`<br/>
861 : jhr 5020 `P.PURE_ARITH{oper=P.MUL, overflow=true, kind=P.FLOAT 64}`
862 : jhr 4985
863 :     * `real64_div : real64 * real64 -> real64`<br/>
864 : jhr 5020 `P.PURE_ARITH{oper=P.QUOT, overflow=true, kind=P.FLOAT 64}`
865 : jhr 4985
866 :     * `real64_neg : word32 -> word32`<br/>
867 : jhr 5020 `P.PURE_ARITH{oper=P.NEG, overflow=true, kind=P.FLOAT 64}`
868 : jhr 4985
869 :     * `real64_gt : real64 * real64 -> bool`<br/>
870 :     `P.CMP{oper=P.GT, kind=P.FLOAT 64}`
871 :    
872 :     * `real64_lt : real64 * real64 -> bool`<br/>
873 :     `P.CMP{oper=P.LT, kind=P.FLOAT 64}`
874 :    
875 :     * `real64_le : real64 * real64 -> bool`<br/>
876 :     `P.CMP{oper=P.LTE, kind=P.FLOAT 64}`
877 :    
878 : jhr 5020 * `real64_ge : real64 * real64 -> bool`<br/>
879 :     `P.CMP{oper=P.GTE, kind=P.FLOAT 64}`
880 :    
881 : jhr 4985 * `real64_eql : real64 * real64 -> bool`<br/>
882 :     `P.CMP{oper=P.EQL, kind=P.FLOAT 64}`
883 :    
884 :     * `real64_neq : real64 * real64 -> bool`<br/>
885 :     `P.CMP{oper=P.NEQ, kind=P.FLOAT 64}`
886 :    
887 :     * `real64_sgn : real64 -> bool`<br/>
888 : jhr 5020 `P.FSGN 64`
889 : jhr 4985
890 :     * `real64_min : real64 * real64 -> real64`<br/>
891 :     `P.INLMIN (P.FLOAT 64)`
892 :    
893 :     * `real64_max : real64 * real64 -> real64`<br/>
894 :     `P.INLMAX (P.FLOAT 64)`
895 :    
896 : jhr 5020 * `real64_abs : real64 -> real64`<br/>
897 :     `P.ARITH{oper=P.FABS, kind=P.FLOAT 64}`
898 : jhr 4985
899 :     * `real64_sin : real64 -> real64`<br/>
900 : jhr 5020 `P.PURE_ARITH{oper=P.FSIN, kind=P.FLOAT 64}`
901 : jhr 4985
902 :     * `real64_cos : real64 -> real64`<br/>
903 : jhr 5020 `P.PURE_ARITH{oper=P.FCOS, kind=P.FLOAT 64}`
904 : jhr 4985
905 :     * `real64_tan : real64 -> real64`<br/>
906 : jhr 5020 `P.PURE_ARITH{oper=P.FTAN, kind=P.FLOAT 64}`
907 : jhr 4985
908 :     * `real64_sqrt : real64 -> real64`<br/>
909 : jhr 5020 `P.PURE_ARITH{oper=P.FSQRT, kind=P.FLOAT 64}`
910 : jhr 4985
911 :    
912 :     ### Conversions
913 :    
914 :     We use the following operation-prefixes for conversions between integer and
915 :     word types:
916 :    
917 : jhr 5096 * `unsigned_` -- for word to integer conversions where the resulting
918 : jhr 4985 integer will be non-negative (*i.e.*, represent the same number as the
919 :     argument). These operations raise `Overflow` if the argument it not
920 :     representable as an integer of the specified size.
921 :    
922 : jhr 5096 * `signed_` -- for word to integer conversions where the resulting
923 : jhr 4985 integer will have the same bit representation as the argument. These
924 :     operations raise `Overflow` if the argument (interpreted as a signed
925 :     2's complement number) is not representable as an integer of the specified
926 :     size.
927 :    
928 : jhr 5096 * no prefix for integer-to-integer, integer-to-word, and word-to-word,
929 : jhr 4985 conversions. In the case of integer-to-integer conversions, the
930 :     operation will raise `Overflow` if the argument is too large to
931 :     represent in the result type.
932 :    
933 :     For conversions between integer and word types, there are five basic
934 :     primitive operations (**TEST**, **TESTU**, **EXTEND**, **TRUNC**, and **COPY**),
935 :     which are described in the `conversions.md` file.
936 :    
937 : jhr 5099 #### Conversions for tagged integers and words
938 :    
939 :     * `word32_to_word : word32 -> word`<br />
940 :     Large word to word conversion (32-bit large word)<br/>
941 :     `P.TRUNC(32, 31)`
942 :    
943 :     * `unsigned_word_to_word32 : word -> word32`<br/>
944 :     Word to large word conversion (32-bit large word)<br/>
945 :     `P.COPY(31, 32)`
946 :    
947 :     * `signed_word_to_word32 : word -> word32`<br/>
948 :     Word to large word conversion (32-bit large word)<br/>
949 :     `P.EXTEND(31, 32)`
950 :    
951 :     * `int_to_intinf : int -> intinf`<br/>
952 :     `P.EXTEND_INF <int-size>`
953 :    
954 :     * `intinf_to_int : intinf -> int`<br/>
955 :     `P.TEST_INF <int-size>`
956 :    
957 : jhr 5096 * `int_to_word : int -> word`<br />
958 : jhr 4985 `P.COPY(<int-size>, <int-size>)`
959 :    
960 : jhr 5099 * `unsigned_word_to_int : word -> int`<br />
961 :     `P.TESTU(<int-size>, <int-size>)`
962 :    
963 : jhr 5096 * `signed_word_to_int : word -> int`<br />
964 : jhr 4985 `P.COPY(<int-size>, <int-size>)`
965 :    
966 : jhr 5099 * `unsigned_word_to_intinf : word -> intinf`<br/>
967 :     `P.COPY_INF <int-size>`
968 : jhr 4985
969 : jhr 5099 * `signed_word_to_intinf : word -> intinf`<br/>
970 :     `P.EXTEND_INF <int-size>`
971 : jhr 4985
972 : jhr 5099 * `intinf_to_word : intinf -> word`<br/>
973 :     `P.TRUNC_INF <int-size>`
974 : jhr 4985
975 : jhr 5099 #### Conversions for 32-bit integers and words
976 : jhr 4985
977 : jhr 5099 * `int32_to_int : int32 -> int`<br/>
978 :     `P.TEST(32, 31)` (32-bit target) or
979 :     `P.EXTEND(32, 63)` (64-bit target).
980 : jhr 4985
981 : jhr 5099 * `word32_to_word : word32 -> word`<br/>
982 :     `P.TRUNC(32, 31)` (32-bit target) or
983 :     `P.COPY(32, 63)` (64-bit target).
984 : jhr 4985
985 : jhr 5099 * `int_to_int32 : int -> int32`<br/>
986 :     `P.EXTEND(31, 32)` (32-bit target) or
987 :     `P.TEST(63, 32)` (64-bit target).
988 : jhr 4985
989 : jhr 5099 * `word_to_word32 : word -> word32`<br/>
990 :     `P.COPY(31, 32)` (32-bit target) or
991 :     `P.TRUNC(63, 32)` (64-bit target).
992 : jhr 4985
993 : jhr 5099 * `int32_to_intinf : int32 -> intinf`<br/>
994 :     `P.EXTEND_INF 32`
995 : jhr 4985
996 : jhr 5099 * `intinf_to_int32 : intinf -> int32`<br/>
997 :     `P.TEST_INF 32`
998 : jhr 4985
999 : jhr 5099 * `int_to_word32 : int -> word32`<br/>
1000 :     `P.EXTEND(31, 32)` (32-bit target) or
1001 :     `P.TRUNC(63, 32)` (64-bit target).
1002 : jhr 4985
1003 : jhr 5099 * `unsigned_word32_to_int : word32 -> int`<br/>
1004 :     `P.TESTU(32, 31)` (32-bit target) or
1005 :     `P.COPY(32, 63)` (64-bit target).
1006 : jhr 4985
1007 : jhr 5099 * `signed_word32_to_int : word32 -> int`<br/>
1008 :     `P.TEST(32, 31)` (32-bit target) or
1009 :     `P.EXTEND(32, 63)` (64-bit target).
1010 : jhr 4985
1011 : jhr 5099 * `unsigned_word32_to_intinf : word32 -> intinf`<br/>
1012 :     `P.COPY_INF 32`
1013 : jhr 4985
1014 : jhr 5099 * `signed_word32_to_intinf : word32 -> intinf`<br/>
1015 :     `P.EXTEND_INF 32`
1016 : jhr 4985
1017 : jhr 5099 * `intinf_to_word32 : intinf -> word32`<br/>
1018 :     `P.TRUNC_INF 32`
1019 : jhr 4985
1020 : jhr 5099 Note that if the `LargeWord.word` type is 64-bits (which it should be), the
1021 :     we have the following additional operations:
1022 : jhr 4985
1023 : jhr 5099 * `word64_to_word32 : word64 -> word32`<br />
1024 :     Large word to word conversion<br/>
1025 :     `P.TRUNC(64, 32)`
1026 : jhr 4985
1027 : jhr 5099 * `unsigned_word32_to_word64 : word32 -> word64`<br/>
1028 :     Unsigned word to large word conversion<br/>
1029 :     `P.COPY(32, 64)`
1030 : jhr 4985
1031 : jhr 5099 * `signed_word32_to_word64 : word32 -> word64`<br/>
1032 :     Signed word to large word conversion<br/>
1033 :     `P.EXTEND(32, 64)`
1034 : jhr 4985
1035 :    
1036 : jhr 5099 #### Conversions for 64-bit integers and words
1037 : jhr 4985
1038 : jhr 5099 * `int64_to_int : int64 -> int`<br/>
1039 :     `P.TEST(64, <int-sz>)`.
1040 : jhr 4985
1041 : jhr 5099 * `word64_to_word : word64 -> word`<br/>
1042 :     `P.TRUNC(64, <int-sz>)`.
1043 : jhr 4985
1044 : jhr 5099 * `int_to_int64 : int -> int64`<br/>
1045 :     `P.EXTEND(<int-sz>, 64)`.
1046 : jhr 4985
1047 : jhr 5099 * `word_to_word64 : word -> word64`<br/>
1048 :     Large word to word conversion<br/>
1049 :     `P.COPY(<int-sz>, 64)`.
1050 : jhr 4985
1051 : jhr 5099 * `signed_word64_to_word32 : word64 -> word32`<br/>
1052 :     Unsigned word to large word conversion<br/>
1053 :     `P.TRUNC(64, 32)`.
1054 : jhr 4985
1055 : jhr 5099 * `unsigned_word64_to_word32 : word64 -> word32`<br/>
1056 :     Signed word to large word conversion<br/>
1057 :     `P.COPY(32, 64)`.
1058 : jhr 4985
1059 : jhr 5099 * `word32_to_word64 : word32 -> word64`<br/>
1060 :     `P.EXTEND(32, 64)`.
1061 : jhr 4985
1062 : jhr 5099 * `int64_to_intinf : int64 -> intinf`<br/>
1063 :     `P.EXTEND_INF 64`
1064 : jhr 4985
1065 : jhr 5099 * `intinf_to_int64 : intinf -> int64`<br/>
1066 :     `P.TEST_INF 64`
1067 : jhr 4985
1068 : jhr 5099 * `int_to_word64 : int -> word64`<br/>
1069 : jhr 5160 `P.EXTEND(31, 64)` (32-bit target) or
1070 : jhr 5099 `P.TRUNC(63, 64)` (64-bit target).
1071 : jhr 4985
1072 : jhr 5099 * `unsigned_word64_to_int : word64 -> int`<br/>
1073 : jhr 5160 `P.TESTU(64, 31)` (32-bit target) or
1074 : jhr 5099 `P.COPY(64, 63)` (64-bit target).
1075 : jhr 4985
1076 : jhr 5099 * `signed_word64_to_int : word64 -> int`<br/>
1077 : jhr 5160 `P.TEST(64, 31)` (32-bit target) or
1078 : jhr 5099 `P.EXTEND(64, 63)` (64-bit target).
1079 : jhr 4985
1080 : jhr 5099 * `unsigned_word64_to_intinf : word64 -> intinf`<br/>
1081 :     `P.COPY_INF 64`
1082 :    
1083 :     * `signed_word64_to_intinf : word64 -> intinf`<br/>
1084 :     `P.EXTEND_INF 64`
1085 :    
1086 :     * `intinf_to_word64 : intinf -> word64`<br/>
1087 :     `P.TRUNC_INF 64`
1088 :    
1089 :    
1090 :     #### Conversions for 8-bit words
1091 :     **NOTE:** currently the compiler does not support 8-bit integers, so this set
1092 :     of conversions is limited to just the `word8` type.
1093 :     * `word32_to_word8 : word32 -> word8`<br />
1094 :     Large word to word conversion (32-bit large word)<br/>
1095 :     `P.TRUNC(32, 8)`
1096 :    
1097 :     * `unsigned_word8_to_word32 : word8 -> word32`<br/>
1098 :     Unsigned word to large word conversion (32-bit large word)<br/>
1099 : jhr 4985 `P.COPY(8, 32)`
1100 :    
1101 : jhr 5099 * `signed_word8_to_word32 : word8 -> word32`<br/>
1102 :     Signed word to large word conversion (32-bit large word)<br/>
1103 :     `P.EXTEND(8, 32)`
1104 :    
1105 :     * `int_to_word8 : int -> word8`<br/>
1106 :    
1107 :     * `unsigned_word8_to_int : word8 -> int`<br/>
1108 :    
1109 :     * `signed_word8_to_int : word8 -> int`<br/>
1110 :    
1111 :     * `unsigned_word8_to_intinf : word8 -> intinf`<br/>
1112 :     `P.COPY_INF 8`
1113 :    
1114 :     * `signed_word8_to_intinf : word8 -> intinf`<br/>
1115 :     `P.EXTEND_INF 8`
1116 :    
1117 :     * `intinf_to_word8 : intinf -> word8`<br/>
1118 :     `P.TRUNC_INF 8`
1119 :    
1120 :    
1121 :     #### Additional conversions for 32-bit targets
1122 :    
1123 :     Additional conversions that are used in `system/smlnj/init/core-intinf.sml`
1124 :     `system/smlnj/init/core-int64.sml`, and `system/smlnj/init/core-word64.sml`.
1125 :    
1126 :     * `trunc_int32_to_word : int32 -> word`<br/>
1127 : jhr 5160 `P.TRUNC(32, 31)`
1128 : jhr 5099
1129 : jhr 5160 * `trunc_word32_to_int : word32 -> int`<br/>
1130 :     `P.TRUNC(32, 31)`
1131 :    
1132 : jhr 5099 * `copy_int32_to_word32 : int32 -> word32`<br/>
1133 : jhr 4985 `P.COPY(32, 32)`
1134 :    
1135 : jhr 5099 * `copy_word_to_int32 : word32 -> int32`<br/>
1136 :     `P.COPY(intSz, 32)`
1137 : jhr 4985
1138 : jhr 5099 * `copy_word32_to_int32 : word32 -> int32`<br/>
1139 :     `P.COPY(32, 32)`
1140 : jhr 4985
1141 : jhr 5099 #### Additional conversions for 64-bit targets
1142 : jhr 4985
1143 :    
1144 : jhr 5099 #### Conversions to support 64-bit integers/words on 32-bit targets.
1145 :     These operations are only present on 32-bit targets and are used to
1146 :     get access to the concrete representation of 64-bit integer and word
1147 :     values.
1148 : jhr 4985
1149 : jhr 5099 * `int64_to_pair : int64 -> word32 * word32`<br/>
1150 :     `P.CVT64`
1151 : jhr 4985
1152 : jhr 5099 * `int64_from_pair : word32 * word32 -> int64`<br/>
1153 :     `P.CVT64`
1154 : jhr 4985
1155 : jhr 5099 * `word64_to_pair : word64 -> word32 * word32`<br/>
1156 :     `P.CVT64`
1157 : jhr 4985
1158 : jhr 5099 * `word64_from_pair : word32 * word32 -> word64`<br/>
1159 :     `P.CVT64`
1160 :    
1161 :    
1162 : jhr 4985 #### Conversions between integers and reals
1163 :    
1164 : jhr 5096 * `int_to_real64 : int -> real64`<br />
1165 : jhr 4993 `P.INT_TO_REAL{from=<int-size>, to=64}`
1166 : jhr 4989
1167 : jhr 5096 * `int32_to_real64 : int32 -> real64`<br />
1168 :     `P.INT_TO_REAL{from=32, to=64}` (32-bit targets only)
1169 : jhr 4989
1170 : jhr 5096 * `int64_to_real64 : int64 -> real64`<br />
1171 :     `P.INT_TO_REAL{from=64, to=64}` (64-bit targets only)
1172 :    
1173 : jhr 4989 * `floor_real64_to_int : real64 -> int`<br />
1174 : jhr 5096 `P.REAL_TO_INT{floor=true, from=64, to=<int-size>}`
1175 : jhr 4985
1176 : jhr 4989 * `round_real64_to_int : real64 -> int`<br />
1177 : jhr 5096 `P.REAL_TO_INT{floor=false, from=64, to=<int-size>}`
1178 : jhr 5019
1179 : jhr 5096 Note: the real to integer conversions should be revised
1180 :     to directly support the various rounding modes (floor,
1181 :     ceiling, truncation, and round).
1182 :    
1183 : jhr 5019 ### Character comparisons
1184 :    
1185 :     * `char_lt : char * char -> bool`<br />
1186 :     `P.CMP{oper=P.LT, kind=P.UINT <int-size>}`
1187 :    
1188 : jhr 5099 * `char_lt : char * char -> bool`<br />
1189 : jhr 5019 `P.CMP{oper=P.LTE, kind=P.UINT <int-size>}`
1190 :    
1191 :     * `char_gt : char * char -> bool`<br />
1192 :     `P.CMP{oper=P.GT, kind=P.UINT <int-size>}`
1193 :    
1194 : jhr 5099 * `char_gt : char * char -> bool`<br />
1195 : jhr 5019 `P.CMP{oper=P.GTE, kind=P.UINT <int-size>}`
1196 : jhr 5096
1197 : jhr 5099 * `char_eql : char * char -> bool`<br/>
1198 :     `P.CMP{oper=P.EQL, kind=P.UINT <int-size>}`
1199 :    
1200 :     * `char_neq : char * char -> bool`<br/>
1201 :     `P.CMP{oper=P.NEQ, kind=P.UINT <int-size>}`
1202 :    
1203 : jhr 5096 ### FFI support
1204 :    
1205 :     The following primops work on raw memory addresses and are included to support
1206 :     interaction with **C** code using the **NLFFI** infrastructure.
1207 :    
1208 : jhr 5099 We use the type `raw_ptr` here to represent the type of a pointer to a **C**
1209 :     object; it is a word type that is the same size as a machine address
1210 : jhr 5096 (*i.e.*, `Word32.word32` or `Word64.word`). Eventually, it should be made
1211 : jhr 5099 abstract and be supported by the compiler.
1212 : jhr 5096
1213 : jhr 5099 Note also that the `RAW_LOAD` and `RAW_STORE` primops are used with different
1214 :     numbers of arguments (*e.g.*, `RAW_LOAD` has one argument for `raw_load_int16`,
1215 :     but two arguments for `raw_sub_int16`, where the extra argument is the offset).
1216 : jhr 5096
1217 : jhr 5099 * `raw_ccall : raw_ptr * 'a * 'b -> 'c`<br />
1218 :     This primop is a call to a **C** function via a function pointer (the
1219 :     first argument). The primop cannot be used without having `'a`, `'b`,
1220 :     and `'c` monomorphically instantiated. In particular, `'a` will be
1221 :     the type of the ML argument list, `'c` will be the type of the result,
1222 :     and `'b` will be a type of fake arguments. The idea is that `'b` is
1223 :     instantiated with an ML type that encodes the type of the actual
1224 :     **C** function in order to be able to generate code according to the **C**
1225 :     calling convention. <br/>
1226 :     In other words, 'b will be a completely ad-hoc encoding of a `CTypes.c_proto`
1227 :     value in ML types. The encoding also contains information about
1228 :     calling conventions and reentrancy. <br />
1229 :     `P.RAW_CCALL NONE`
1230 : jhr 5096
1231 : jhr 5099 * `raw_record : int -> 'a`<br />
1232 :     Allocates an uninitialized **C** object of the given size on the ML heap;
1233 :     the object will be word-size aligned.
1234 :     We use the `raw_sub_xxx` and `raw_update_xxx` primops (see below)
1235 :     to access and update the record. The `'a` result type is to guarantee
1236 :     that the compiler will treat the record as a ML object, in case it passes
1237 :     thru a gc boundary. <br/>
1238 :     `P.RAW_RECORD { align64 = false }`
1239 : jhr 5096
1240 : jhr 5099 * `raw_record64 : int -> 'a`<br />
1241 :     Allocates an uninitialized **C** object of the given size on the ML heap;
1242 :     the object will be 64-bit aligned. <br/>
1243 :     `P.RAW_RECORD { align64 = true }`
1244 :    
1245 : jhr 5096 * `raw_load_int8 : raw_ptr -> int32`<br />
1246 : jhr 5099 `P.RAW_LOAD(P.INT 8)`
1247 : jhr 5096
1248 :     * `raw_load_word8 : raw_ptr -> word32`<br />
1249 : jhr 5099 `P.RAW_LOAD(P.UINT 8)`
1250 : jhr 5096
1251 :     * `raw_load_int16 : raw_ptr -> int32`<br />
1252 : jhr 5099 `P.RAW_LOAD(P.INT 16)`
1253 : jhr 5096
1254 :     * `raw_load_word16 : raw_ptr -> word32`<br />
1255 : jhr 5099 `P.RAW_LOAD(P.UINT 16)`
1256 : jhr 5096
1257 :     * `raw_load_int32 : raw_ptr -> int32`<br />
1258 : jhr 5099 `P.RAW_LOAD(P.INT 32)`
1259 : jhr 5096
1260 :     * `raw_load_word32 : raw_ptr -> word32`<br />
1261 : jhr 5099 `P.RAW_LOAD(P.UINT 32)`
1262 : jhr 5096
1263 : jhr 5099 * `raw_load_float32 : raw_ptr -> real`<br />
1264 :     `P.RAW_LOAD(P.FLOAT 32)`
1265 :    
1266 : jhr 5096 * `raw_load_float64 : raw_ptr -> real`<br />
1267 : jhr 5099 `P.RAW_LOAD(P.FLOAT 32)`
1268 : jhr 5096
1269 :     * `raw_store_int8 : raw_ptr * int32 -> unit`<br />
1270 : jhr 5099 `P.RAW_STORE(P.INT 8)`
1271 : jhr 5096
1272 :     * `raw_store_word8 : raw_ptr * word32 -> unit`<br />
1273 : jhr 5099 `P.RAW_STORE(P.UINT 8)`
1274 : jhr 5096
1275 :     * `raw_store_int16 : raw_ptr * int32 -> unit`<br />
1276 : jhr 5099 `P.RAW_STORE(P.INT 16)`
1277 : jhr 5096
1278 :     * `raw_store_word16 : raw_ptr * word32 -> unit`<br />
1279 : jhr 5099 `P.RAW_STORE(P.UINT 16)`
1280 : jhr 5096
1281 :     * `raw_store_int32 : raw_ptr * int32 -> unit`<br />
1282 : jhr 5099 `P.RAW_STORE(P.INT 32)`
1283 : jhr 5096
1284 :     * `raw_store_word32 : raw_ptr * word32 -> unit`<br />
1285 : jhr 5099 `P.RAW_STORE(P.UINT 32)`
1286 : jhr 5096
1287 : jhr 5099 * `raw_store_float32 : raw_ptr * real -> unit`<br />
1288 :     `P.RAW_STORE(P.FLOAT 32)`
1289 :    
1290 : jhr 5096 * `raw_store_float64 : raw_ptr * real -> unit`<br />
1291 : jhr 5099 `P.RAW_STORE(P.FLOAT 32)`
1292 : jhr 5096
1293 :     * `raw_sub_int8 : 'a * raw_ptr -> int32`<br />
1294 : jhr 5099 `P.RAW_LOAD(P.INT 8)`
1295 : jhr 5096
1296 :     * `raw_sub_word8 : 'a * raw_ptr -> word32`<br />
1297 : jhr 5099 `P.RAW_LOAD(P.UINT 8)`
1298 : jhr 5096
1299 :     * `raw_sub_int16 : 'a * raw_ptr -> int32`<br />
1300 : jhr 5099 `P.RAW_LOAD(P.INT 16)`
1301 : jhr 5096
1302 :     * `raw_sub_word16 : 'a * raw_ptr -> word32`<br />
1303 : jhr 5099 `P.RAW_LOAD(P.UINT 16)`
1304 : jhr 5096
1305 :     * `raw_sub_int32 : 'a * raw_ptr -> int32`<br />
1306 : jhr 5099 `P.RAW_LOAD(P.INT 32)`
1307 : jhr 5096
1308 :     * `raw_sub_word32 : 'a * raw_ptr -> word32`<br />
1309 : jhr 5099 `P.RAW_LOAD(P.UINT 32)`
1310 : jhr 5096
1311 : jhr 5099 * `raw_sub_float32 : 'a * raw_ptr -> real`<br />
1312 :     `P.RAW_LOAD(P.FLOAT 32)`
1313 :    
1314 : jhr 5096 * `raw_sub_float64 : 'a * raw_ptr -> real`<br />
1315 : jhr 5099 `P.RAW_LOAD(P.FLOAT 32)`
1316 : jhr 5096
1317 :     * `raw_update_int8 : 'a * raw_ptr * int32 -> unit`<br />
1318 : jhr 5099 `P.RAW_STORE(P.INT 8)`
1319 : jhr 5096
1320 :     * `raw_update_word8 : 'a * raw_ptr * word32 -> unit`<br />
1321 : jhr 5099 `P.RAW_STORE(P.INT 8)`
1322 : jhr 5096
1323 :     * `raw_update_int16 : 'a * raw_ptr * int32 -> unit`<br />
1324 : jhr 5099 `P.RAW_STORE(P.INT 8)`
1325 : jhr 5096
1326 :     * `raw_update_word16 : 'a * raw_ptr * word32 -> unit`<br />
1327 : jhr 5099 `P.RAW_STORE(P.UINT 16)`
1328 : jhr 5096
1329 :     * `raw_update_int32 : 'a * raw_ptr * int32 -> unit`<br />
1330 : jhr 5099 `P.RAW_STORE(P.INT 32)`
1331 : jhr 5096
1332 :     * `raw_update_word32 : 'a * raw_ptr * word32 -> unit`<br />
1333 : jhr 5099 `P.RAW_STORE(P.UINT 32)`
1334 : jhr 5096
1335 : jhr 5099 * `raw_update_float32 : 'a * raw_ptr * real -> unit`<br />
1336 :     `P.RAW_STORE(P.FLOAT 32)`
1337 :    
1338 : jhr 5096 * `raw_update_float64 : 'a * raw_ptr * real -> unit`<br />
1339 : jhr 5099 `P.RAW_STORE(P.FLOAT 64)`
1340 : jhr 5160
1341 :    
1342 :     ## Changes to support 64-bit targets
1343 :    
1344 :     While most of the 32-bit dependencies have been eliminated in Version 110.87,
1345 :     there are still a few cases where the primop names for 32-bit and 64-bit
1346 :     targets will be different. To address this issue, we should introduce two
1347 :     type aliases:
1348 :    
1349 :     * `type lint` -- this should be the `FixedInt.int` type.
1350 :    
1351 :     * `type lword` -- this should be the `LargeWord.word` type.
1352 :    
1353 :     Then we can replace uses of `int32` and `word32` with these where it makes sense.

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0