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

SCM Repository

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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 4961, Thu Apr 18 10:18:12 2019 UTC revision 5099, Sat May 4 13:31:54 2019 UTC
# Line 14  Line 14 
14      datatypes used to represent primitive operations internally in the      datatypes used to represent primitive operations internally in the
15      front-end of the compiler.  The main type is `Primop.primop`.      front-end of the compiler.  The main type is `Primop.primop`.
16    
17    * `compiler/ElabData/prim/primop.sml`<br/>    * `compiler/ElabData/prim/primop.sig`<br/>
18      this file defines the `PRIMOP` signature use for the `Primop` structure.      this file defines the `PRIMOP` signature use for the `Primop` structure.
19    
20    * `compiler/Semant/prim/primop-bindings.sml`<br/>    * `compiler/Semant/prim/primop-bindings.sml`<br/>
# Line 41  Line 41 
41    * "`real32`" -- 32-bit real numbers (not yet supported)    * "`real32`" -- 32-bit real numbers (not yet supported)
42    * "`real64`" -- 64-bit real numbers    * "`real64`" -- 64-bit real numbers
43    * "`ptr`" -- machine address    * "`ptr`" -- machine address
   * "`barr`" -- bytearray (used for arrays of `Word8.word` and `char`)  
   * "`bvec`" -- bytevector (used for strings and vectors of `Word8.word`)  
44    * "`arr`" -- polymorphic arrays    * "`arr`" -- polymorphic arrays
45    * "`vec`" -- polymorphic vectors    * "`vec`" -- polymorphic vectors
46    * "`seq`" -- sequence types (arrays and vectors)    * "`seq`" -- sequence types (arrays and vectors)
47      * "`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    
53    Following the type prefix may one or more attributes, which highlight properties
54    of the operation.
55    
56  We use the attribute "`raw`" to denote direct machine operations that are not  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  directly accesible in the Basis Library (*e.g.*, shift operations, where the basis
# Line 102  Line 108 
108    
109  #### Equality tests  #### Equality tests
110    * `= : ''a * ''a -> bool`<br/>    * `= : ''a * ''a -> bool`<br/>
111        Polymorphic equality.<br/>
112      `P.POLYEQL`      `P.POLYEQL`
113    
114    * `<> : ''a * ''a -> bool`<br/>    * `<> : ''a * ''a -> bool`<br/>
115        Polymorphic inequality.<br/>
116      `P.POLYNEQ`      `P.POLYNEQ`
117    
118    * `ptr_eql : 'a * 'a -> bool`<br/>    * `ptr_eql : 'a * 'a -> bool`<br/>
119        Pointer equality.<br/>
120      `P.PTREQL`      `P.PTREQL`
121    
122    * `ptr_neq : 'a * 'a -> bool`<br/>    * `ptr_neq : 'a * 'a -> bool`<br/>
123        Pointer inequality.<br/>
124      `P.PTRNEQ`      `P.PTRNEQ`
125    
126    
# Line 140  Line 150 
150      `P.GETTAG`      `P.GETTAG`
151    
152    * `objlength : 'a -> int`<br/>    * `objlength : 'a -> int`<br/>
153      extracts the length field from an object's header word.      extracts the length field from an object's header word.<br/>
154      `P.OBJLENGTH`      `P.OBJLENGTH`
155    
156    
157  #### Inline operations  #### Inline operations
158  These primops are Basis Library functions that should be inlined for efficiency.  These primops are Basis Library functions that should be inlined for efficiency.
159    * `compose : ('b -> 'c) * ('a -> 'b) -> 'a -> 'c`<br/>    * `inl_compose : ('b -> 'c) * ('a -> 'b) -> 'a -> 'c`<br/>
160        Inline function composition.<br/>
161      `P.INLCOMPOSE`      `P.INLCOMPOSE`
162    
163    * `before : 'a * 'b -> 'a`<br/>    * `inl_before : 'a * 'b -> 'a`<br/>
164        Inline `before` operator.<br/>
165      `P.INLBEFORE`      `P.INLBEFORE`
166    
167    * `ignore : 'a -> unit`<br/>    * `inl_ignore : 'a -> unit`<br/>
168        Inline `ignore` function.<br/>
169      `P.INLIGNORE`      `P.INLIGNORE`
170    
171    * `identity : 'a -> 'a`<br/>    * `inl_identity : 'a -> 'a`<br/>
172        Inline identity function.<br/>
173      `P.INLIDENTITY`      `P.INLIDENTITY`
174    
175    * `bool_not : bool -> bool`<br/>    * `inl_bool_not : bool -> bool`<br/>
176        Inline boolean negation operator.
177      `P.INLNOT`      `P.INLNOT`
178    
179  Some additional candidates for inlined operations include `hd`, `tl`, `null`, `chr`, and `ord`.    * `inl_chr : int -> char`<br/>
180  If the compiler had the `option` and `order` datatypes builtin (like `bool` and `list`),      Inline `chr` function.<br/>
181  then `valOf`, `isSome`, `isNone` and some of the `compare` functions could be inlined.       `P.INLCHR`
   
   
 #### Bytearray and bytevector operations  
 Operations on byte/char array/vectors.  We renamed these to make it clear  
 which operations do bounds checking and which do not.  
   
   * `bvec_unsafe_sub : 'a * int -> 'b`<br/>  
     subscript from byte vector without bounds checking  
     (`P.NUMSUBSCRIPT{kind=P.INT 8, checked=false, immutable=true}`)  
182    
183    * `barr_unsafe_sub : 'a * int -> 'b`<br/>    * `inl_ord : char -> int`<br/>
184      subscript from byte array without bounds checking      Inline `ord` function.<br/>
185      (`P.NUMSUBSCRIPT{kind=P.INT 8, checked=false, immutable=false}`)       `P.CAST`
   
   * `barr_unsafe_update : 'a * int * 'b -> unit`<br/>  
     update byte array without bounds checking  
     (`P.NUMUPDATE{kind=P.INT 8, checked=false}`)  
186    
187    * `bvec_sub : 'a * int -> 'b`<br/>  Some additional candidates for inlined operations include `hd`, `tl`, and `null`.
     subscript from byte vector  
     (`P.NUMSUBSCRIPT{kind=P.INT 8, checked=true, immutable=true}`)  
188    
189    * `barr_sub : 'a * int -> 'b`<br/>  If the compiler had the `option` and `order` datatypes builtin (like `bool` and `list`),
190      subscript from byte array  then `valOf`, `isSome`, `isNone` and some of the `compare` functions could also
191      (`P.NUMSUBSCRIPT{kind=P.INT 8, checked=true, immutable=false}`)  be inlined.
192    
193    * `barr_update : 'a * int * 'b -> unit`<br/>  In the long run, however, a better way to support inlining library functions would
194      update byte array  be through a reliable cross-module inliner.
     (`P.NUMUPDATE{kind=P.INT 8, checked=true}`)  
195    
196    ### Operations on sequences
197    
198  #### Polymorphic array and vector  #### Polymorphic array and vector
199    * `mkarray : int * 'a -> 'a array`<br/>    * `mkarray : int * 'a -> 'a array`<br/>
200      create a polymorphic array      create a polymorphic array; this primop is required to support the
201      (`P.INLMKARRAY`)      dictionary-passing representation of polymorphic arrays.<br/>
202        `P.INLMKARRAY`
203    
204    * `arr_unsafe_sub : 'a array * int -> 'a`<br/>    * `arr_unsafe_sub : 'a array * int -> 'a`<br/>
205      subscript from polymorphic array without bounds checking      subscript from polymorphic array without bounds checking.<br/>
206      (`P.SUBSCRIPT`)      `P.SUBSCRIPT`
207    
208    * `arr_sub : 'a array * int -> 'a`<br/>    * `arr_sub : 'a array * int -> 'a`<br/>
209      subscript from polymorphic array      subscript from polymorphic array.<br/>
210      (`P.INLSUBSCRIPT`)      `P.INLSUBSCRIPT`
211    
212    * `vec_unsafe_sub : 'a vector * int -> 'a`<br/>    * `vec_unsafe_sub : 'a vector * int -> 'a`<br/>
213      subscript from polymorphic vector without bounds checking      subscript from polymorphic vector without bounds checking.<br/>
214      (`P.SUBSCRIPTV`)      `P.SUBSCRIPTV`
215    
216    * `vec_sub : 'a vector * int -> 'a`<br/>    * `vec_sub : 'a vector * int -> 'a`<br/>
217      subscript from polymorphic vector      subscript from polymorphic vector.<br/>
218      (`P.INLSUBSCRIPTV`)      `P.INLSUBSCRIPTV`
219    
220    * `arr_unsafe_update : 'a array * int * 'a -> unit`<br/>    * `arr_unsafe_update : 'a array * int * 'a -> unit`<br/>
221      update a polymorphic array without bounds checking      update a polymorphic array without bounds checking.<br/>
222      (`P.UPDATE`)      `P.UPDATE`
223    
224    * `arr_update : 'a array * int * 'a -> unit`<br/>    * `arr_update : 'a array * int * 'a -> unit`<br/>
225      update a polymorphic array      update a polymorphic array.<br/>
226      (`P.INLUPDATE`)      `P.INLUPDATE`
227    
228    * `arr_unboxed_update : 'a array * int * 'a -> unit`<br/>    * `arr_unboxed_update : 'a array * int * 'a -> unit`<br/>
229      update a polymorphic array with an unboxed value, which means that there is      update a polymorphic array with an unboxed value, which means that there is
230      no store-list entry created for the update.      no store-list entry created for the update.<br/>
231      `P.UNBOXEDUPDATE`      `P.UNBOXEDUPDATE`
232    
   
233  #### Sequence operations  #### Sequence operations
234  Sequence values (*e.g.*, `string`, `'a array`, `RealVector.vector`, *etc*.)  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  are represented by a header consisting of a length (in elements) and a data
# Line 239  Line 239 
239      `P.NEW_ARRAY0`      `P.NEW_ARRAY0`
240    
241    * `seq_length : 'a -> int`<br/>    * `seq_length : 'a -> int`<br/>
242      get the length field from a sequence header      get the length field from a sequence header.<br/>
243      `P.LENGTH`      `P.LENGTH`
244    
245    * `seq_data : 'a -> 'b`<br/>    * `seq_data : 'a -> 'b`<br/>
246      get the length field from a sequence header      get the length field from a sequence header.<br/>
247      `P.GET_SEQ_DATA`      `P.GET_SEQ_DATA`
248    
   * `unsafe_record_sub : 'a * int -> 'b`<br/>  
     `P.SUBSCRIPT_REC`  
   
249    * `raw64Sub : 'a * int -> real64`<br/>    * `raw64Sub : 'a * int -> real64`<br/>
250      Unclear what purpose this primop serves      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      `P.SUBSCRIPT_RAW64`      `P.SUBSCRIPT_RAW64`
254    
255      * `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    
260    #### 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  ### Numeric primops  ### Numeric primops
346    
# Line 262  Line 350 
350    
351    * `int_add : int * int -> int`<br/>    * `int_add : int * int -> int`<br/>
352      Signed integer addition with overflow checking.      Signed integer addition with overflow checking.
353      `P.ARITH{oper=P.ADD, overflow=true, kind=P.INT <int-size>}`      (`P.IARITH{oper=P.IADD, sz=<int-size>}`)
   
   * `int_unsafe_add : int * int -> int`<br/>  
     Signed integer addition *without* overflow checking.  
     `P.ARITH{oper=P.ADD, overflow=false, kind=P.INT <int-size>}`  
354    
355    * `int_sub : int * int -> int`<br/>    * `int_sub : int * int -> int`<br/>
356      Signed integer subtraction with overflow checking.      Signed integer subtraction with overflow checking.
357      `P.ARITH{oper=P.SUB, overflow=true, kind=P.INT <int-size>}`      (`P.IARITH{oper=P.ISUB, sz=<int-size>}`)
   
   * `int_unsafe_sub : int * int -> int`<br/>  
     Signed integer subtraction *without* overflow checking.  
     `P.ARITH{oper=P.SUB, overflow=false, kind=P.INT <int-size>}`  
358    
359    * `int_mul : int * int -> int`<br/>    * `int_mul : int * int -> int`<br/>
360      `P.ARITH{oper=P.MUL, overflow=true, kind=P.INT <int-size>}`      `P.IARITH{oper=P.IMUL, sz=<int-size>}`
361    
362    * `int_div : int * int -> int`<br/>    * `int_div : int * int -> int`<br/>
363      `P.ARITH{oper=P.QUOT, overflow=true, kind=P.INT <int-size>}`      `P.INLDIV(P.INT <int-size>)`
364    
365    * `int_mod : int * int -> int`<br/>    * `int_mod : int * int -> int`<br/>
366      `P.ARITH{oper=P.REM, overflow=true, kind=P.INT <int-size>}`      `P.INLMOD(P.INT <int-size>)`
367    
368    * `int_quot : int * int -> int`<br/>    * `int_quot : int * int -> int`<br/>
369      `P.ARITH{oper=P.QUOT, overflow=true, kind=P.INT <int-size>}`      `P.INLQUOT(P.INT <int-size>)`
370    
371    * `int_rem : int * int -> int`<br/>    * `int_rem : int * int -> int`<br/>
372      `P.ARITH{oper=P.REM, overflow=true, kind=P.INT <int-size>}`      `P.INLREM(P.INT <int-size>)`
   
   * `int_orb : int * int -> int`<br/>  
     `P.ARITH{oper=P.ORB, overflow=false, kind=P.INT <int-size>}`  
   
   * `int_xorb : int * int -> int`<br/>  
     `P.ARITH{oper=P.XORB, overflow=false, kind=P.INT <int-size>}`  
   
   * `int_andb : int * int -> int`<br/>  
     `P.ARITH{oper=P.ANDB, overflow=false, kind=P.INT <int-size>}`  
373    
374    * `int_neg : word32 -> word32`<br/>    * `int_neg : word32 -> word32`<br/>
375      `P.ARITH{oper=P.NEG, overflow=true, kind=P.INT <int-size>}`      `P.IARITH{oper=P.INEG, sz=<int-size>}`
376    
377    * `int_raw_rshift : int * word -> int`<br/>    * `int_lt : int * int -> bool`<br/>
378      `P.ARITH{oper=P.RSHIFT, overflow=false, kind=P.INT <int-size>}`      `P.CMP{oper=P.LT, kind=P.INT <int-size>}`
379    
380    * `int_raw_lshift : int * word -> int`<br/>    * `int_le : int * int -> bool`<br/>
381      `P.ARITH{oper=P.LSHIFT, overflow=false, kind=P.INT <int-size>}`      `P.CMP{oper=P.LTE, kind=P.INT <int-size>}`
382    
383    * `int_gt : int * int -> bool`<br/>    * `int_gt : int * int -> bool`<br/>
384      `P.CMP{oper=P.GT, kind=P.INT <int-size>}`      `P.CMP{oper=P.GT, kind=P.INT <int-size>}`
# Line 315  Line 386 
386    * `int_ge : int * int -> bool`<br/>    * `int_ge : int * int -> bool`<br/>
387      `P.CMP{oper=P.GTE, kind=P.INT <int-size>}`      `P.CMP{oper=P.GTE, kind=P.INT <int-size>}`
388    
   * `int_lt : int * int -> bool`<br/>  
     `P.CMP{oper=P.LT, kind=P.INT <int-size>}`  
   
   * `int_le : int * int -> bool`<br/>  
     `P.CMP{oper=P.LTE, kind=P.INT <int-size>}`  
   
389    * `int_eql : int * int -> bool`<br/>    * `int_eql : int * int -> bool`<br/>
390      `P.CMP{oper=P.EQL, kind=P.INT <int-size>}`      `P.CMP{oper=P.EQL, kind=P.INT <int-size>}`
391    
# Line 333  Line 398 
398    * `int_max : int * int -> int`<br/>    * `int_max : int * int -> int`<br/>
399      `P.INLMAX (P.INT <int-size>)`      `P.INLMAX (P.INT <int-size>)`
400    
401    * `int_abs : word32 -> word32`<br/>    * `int_abs : int -> int`<br/>
402      `P.INLABS (P.INT <int-size>)`      `P.INLABS (P.INT <int-size>)`
403    
404    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        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    
412      * `int_unsafe_sub : int * int -> int`<br/>
413        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    
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      * `int_notb : int -> int`<br/>
427        `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      * `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  #### Default tagged word operations  #### Default tagged word operations
444  These are the primitive operations on the default tagged word  These are the primitive operations on the default tagged word
445  type (`Word.word`).  type (`Word.word`).
446    
447      * `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    * `word_mul : word * word -> word`<br/>    * `word_mul : word * word -> word`<br/>
454      `P.ARITH{oper=P.MUL, overflow=false, kind=P.INT <int-size>}`      `P.PURE_ARITH{oper=P.MUL, kind=P.UINT <int-size>}`
455    
456    * `word_div : word * word -> word`<br/>    * `word_div : word * word -> word`<br/>
457      `P.ARITH{oper=P.QUOT, overflow=false, kind=P.INT <int-size>}`      `P.INLQUOT(P.UINT <int-size>)`
458    
459    * `word_mod : word * word -> word`<br/>    * `word_mod : word * word -> word`<br/>
460      `P.ARITH{oper=P.REM, overflow=false, kind=P.INT <int-size>}`      `P.INLREM(P.UINT <int-size>)`
   
   * `word_add : word * word -> word`<br/>  
     `P.ARITH{oper=P.ADD, overflow=false, kind=P.INT <int-size>}`  
   
   * `word_sub : word * word -> word`<br/>  
     `P.ARITH{oper=P.SUB, overflow=false, kind=P.INT <int-size>}`  
461    
462    * `word_orb : word * word -> word`<br/>    * `word_orb : word * word -> word`<br/>
463      `P.ARITH{oper=P.ORB, overflow=false, kind=P.INT <int-size>}`      `P.PURE_ARITH{oper=P.ORB, kind=P.UINT <int-size>}`
464    
465    * `word_xorb : word * word -> word`<br/>    * `word_xorb : word * word -> word`<br/>
466      `P.ARITH{oper=P.XORB, overflow=false, kind=P.INT <int-size>}`      `P.PURE_ARITH{oper=P.XORB, kind=P.UINT <int-size>}`
467    
468    * `word_andb : word * word -> word`<br/>    * `word_andb : word * word -> word`<br/>
469      `P.ARITH{oper=P.ANDB, overflow=false, kind=P.INT <int-size>}`      `P.PURE_ARITH{oper=P.ANDB, kind=P.UINT <int-size>}`
470    
471    * `word_notb : word -> word`<br/>    * `word_notb : word -> word`<br/>
472      `P.ARITH{oper=P.NOTB, overflow=false, kind=P.INT <int-size>}`      `P.PURE_ARITH{oper=P.NOTB, kind=P.UINT <int-size>}`
473    
474    * `word_neg : word -> word`<br/>    * `word_neg : word -> word`<br/>
475      `P.ARITH{oper=P.NEG, overflow=false, kind=P.INT <int-size>}`      `P.PURE_ARITH{oper=P.NEG, kind=P.UINT <int-size>}`
476    
477    * `word_rshift : word * word -> word`<br/>    * `word_rshift : word * word -> word`<br/>
478      `P.ARITH{oper=P.RSHIFT, overflow=false, kind=P.INT <int-size>}`      `P.INLRSHIFT(P.UINT <int-size>)`
479    
480    * `word_rshiftl : word * word -> word`<br/>    * `word_rshiftl : word * word -> word`<br/>
481      `P.ARITH{oper=P.RSHIFTL, overflow=false, kind=P.INT <int-size>}`      `P.INLRSHIFTL(P.UINT <int-size>)`
482    
483    * `word_lshift : word * word -> word`<br/>    * `word_lshift : word * word -> word`<br/>
484      `P.ARITH{oper=P.LSHIFT, overflow=false, kind=P.INT <int-size>}`      `P.PURE_ARITH{oper=P.LSHIFT, kind=P.UINT <int-size>}`
485    
486      * `word_raw_rshift : word * word -> word`<br/>
487        `P.INLLSHIFT(P.UINT <int-size>)`
488    
489      * `word_raw_rshiftl : word * word -> word`<br/>
490        `P.PURE_ARITH{oper=P.RSHIFTL, kind=P.UINT <int-size>}`
491    
492      * `word_raw_lshift : word * word -> word`<br/>
493        `P.PURE_ARITH{oper=P.RSHIFT, kind=P.UINT <int-size>}`
494    
495    * `word_gt : word * word -> bool`<br/>    * `word_gt : word * word -> bool`<br/>
496      `P.CMP{oper=P.GT, kind=P.UINT <int-size>}`      `P.CMP{oper=P.GT, kind=P.UINT <int-size>}`
# Line 397  Line 510 
510    * `word_neq : word * word -> bool`<br/>    * `word_neq : word * word -> bool`<br/>
511      `P.CMP{oper=P.NEQ, kind=P.UINT <int-size>}`      `P.CMP{oper=P.NEQ, kind=P.UINT <int-size>}`
512    
   * `word_raw_rshift : word * word -> word`<br/>  
     `P.INLRSHIFT(P.UINT <int-size>)`  
   
   * `word_raw_rshiftl : word * word -> word`<br/>  
     `P.INLRSHIFTL(P.UINT <int-size>)`  
   
   * `word_raw_lshift : word * word -> word`<br/>  
     `P.INLLSHIFT(P.UINT <int-size>)`  
   
513    * `word_min : word * word -> word`<br/>    * `word_min : word * word -> word`<br/>
514      `P.INLMIN (P.UINT <int-size>)`      `P.INLMIN (P.UINT <int-size>)`
515    
516    * `word_max : word * word -> word`<br/>    * `word_max : word * word -> word`<br/>
517      `P.INLMAX (P.UINT <int-size>)`      `P.INLMAX (P.UINT <int-size>)`
518    
 #### 8-bit word operations  
   
519  #### 32-bit integer operations  #### 32-bit integer operations
520    * `int32_add : int32 * int32 -> int32`<br/>    * `int32_add : int32 * int32 -> int32`<br/>
521      `P.ARITH{oper=P.ADD, overflow=true, kind=P.INT 32}`      `P.IARITH{oper=P.IADD, sz=32}`
522    
523    * `int32_sub : int32 * int32 -> int32`<br/>    * `int32_sub : int32 * int32 -> int32`<br/>
524      `P.ARITH{oper=P.SUB, overflow=true, kind=P.INT 32}`      `P.IARITH{oper=P.ISUB, sz=32}`
525    
526    * `int32_mul : int32 * int32 -> int32`<br/>    * `int32_mul : int32 * int32 -> int32`<br/>
527      `P.ARITH{oper=P.MUL, overflow=true, kind=P.INT 32}`      `P.IARITH{oper=P.IMUL, sz=32}`
528    
529    * `int32_div : int32 * int32 -> int32`<br/>    * `int32_div : int32 * int32 -> int32`<br/>
530      `P.ARITH{oper=P.QUOT, overflow=true, kind=P.INT 32}`      `P.IARITH{oper=P.IQUOT, sz=32}`
531    
532    * `int32_mod : int32 * int32 -> int32`<br/>    * `int32_mod : int32 * int32 -> int32`<br/>
533      `P.ARITH{oper=P.REM, overflow=true, kind=P.INT 32}`      `P.IARITH{oper=P.IREM, sz=32}`
534    
535    * `int32_quot : int32 * int32 -> int32`<br/>    * `int32_quot : int32 * int32 -> int32`<br/>
536      `P.ARITH{oper=P.QUOT, overflow=true, kind=P.INT 32}`      `P.IARITH{oper=P.IQUOT, sz=32}`
537    
538    * `int32_rem : int32 * int32 -> int32`<br/>    * `int32_rem : int32 * int32 -> int32`<br/>
539      `P.ARITH{oper=P.REM, overflow=true, kind=P.INT 32}`      `P.IARITH{oper=P.IREM, sz=32}`
   
   * `int32_orb : int32 * int32 -> int32`<br/>  
     `P.ARITH{oper=P.ORB, overflow=false, kind=P.INT 32}`  
   
   * `int32_xorb : int32 * int32 -> int32`<br/>  
     `P.ARITH{oper=P.XORB, overflow=false, kind=P.INT 32}`  
   
   * `int32_andb : int32 * int32 -> int32`<br/>  
     `P.ARITH{oper=P.ANDB, overflow=false, kind=P.INT 32}`  
540    
541    * `int32_neg : word32 -> word32`<br/>    * `int32_neg : word32 -> word32`<br/>
542      `P.ARITH{oper=P.NEG, overflow=true, kind=P.INT 32}`      `P.IARITH{oper=P.INEG, sz=32}`
   
   * `int32_raw_rshift : int32 * word -> int32`<br/>  
     `P.ARITH{oper=P.RSHIFT, overflow=false, kind=P.INT 32}`  
   
   * `int32_raw_lshift : int32 * word -> int32`<br/>  
     `P.ARITH{oper=P.LSHIFT, overflow=false, kind=P.INT 32}`  
543    
544    * `int32_gt : int32 * int32 -> bool`<br/>    * `int32_gt : int32 * int32 -> bool`<br/>
545      `P.CMP{oper=P.GT, kind=P.INT 32}`      `P.CMP{oper=P.GT, kind=P.INT 32}`
# Line 478  Line 565 
565    * `int32_max : int32 * int32 -> int32`<br/>    * `int32_max : int32 * int32 -> int32`<br/>
566      `P.INLMAX (P.INT 32)`      `P.INLMAX (P.INT 32)`
567    
568    * `int32_abs : word32 -> word32`<br/>    * `int32_abs : int32 -> int32`<br/>
569      `P.INLABS (P.INT 32)`      `P.INLABS (P.INT 32)`
570    
571    #### 8-bit word operations
572    
573      * `word8_mul : word8 * word8 -> word8`<br/>
574        `P.PURE_ARITH{oper=P.MUL, kind=P.UINT 8}`
575    
576      * `word8_div : word8 * word8 -> word8`<br/>
577        `P.PURE_ARITH{oper=P.QUOT, kind=P.UINT 8}`
578    
579      * `word8_mod : word8 * word8 -> word8`<br/>
580        `P.PURE_ARITH{oper=P.REM, kind=P.UINT 8}`
581    
582      * `word8_add : word8 * word8 -> word8`<br/>
583        `P.PURE_ARITH{oper=P.ADD, kind=P.UINT 8}`
584    
585      * `word8_sub : word8 * word8 -> word8`<br/>
586        `P.PURE_ARITH{oper=P.SUB, kind=P.UINT 8}`
587    
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  #### 32-bit word operations  #### 32-bit word operations
646    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    
650      * `word32_mul : word32 * word32 -> word32`<br/>
651        `P.PURE_ARITH{oper=P.MUL, kind=P.UINT 32}`
652    
653      * `word32_div : word32 * word32 -> word32`<br/>
654        `P.PURE_ARITH{oper=P.QUOT, kind=P.UINT 32}`
655    
656      * `word32_mod : word32 * word32 -> word32`<br/>
657        `P.PURE_ARITH{oper=P.REM, kind=P.UINT 32}`
658    
659      * `word32_add : word32 * word32 -> word32`<br/>
660        `P.PURE_ARITH{oper=P.ADD, kind=P.UINT 32}`
661    
662      * `word32_sub : word32 * word32 -> word32`<br/>
663        `P.PURE_ARITH{oper=P.SUB, kind=P.UINT 32}`
664    
665      * `word32_orb : word32 * word32 -> word32`<br/>
666        `P.PURE_ARITH{oper=P.ORB, kind=P.UINT 32}`
667    
668      * `word32_xorb : word32 * word32 -> word32`<br/>
669        `P.PURE_ARITH{oper=P.XORB, kind=P.UINT 32}`
670    
671      * `word32_andb : word32 * word32 -> word32`<br/>
672        `P.PURE_ARITH{oper=P.ANDB, kind=P.UINT 32}`
673    
674      * `word32_notb : word32 -> word32`<br/>
675        `P.PURE_ARITH{oper=P.NOTB, kind=P.UINT 32}`
676    
677      * `word32_neg : word32 -> word32`<br/>
678        `P.PURE_ARITH{oper=P.NEG, kind=P.UINT 32}`
679    
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        `P.PURE_ARITH{oper=P.RSHIFT, kind=P.UINT 32}`
691    
692      * `word32_raw_rshiftl : word32 * word -> word`<br/>
693        `P.PURE_ARITH{oper=P.RSHIFTL, kind=P.UINT 32}`
694    
695      * `word32_raw_lshift : word32 * word -> word`<br/>
696        `P.PURE_ARITH{oper=P.LSHIFT, kind=P.UINT 32}`
697    
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  #### 64-bit integer operations  #### 64-bit integer operations
723    **Note:** 64-bit integer operations are currently not supported in the compiler,
724    but we expect to add them in 110.88.
725    
726    * `int64_add : int64 * int64 -> int64`<br/>    * `int64_add : int64 * int64 -> int64`<br/>
727      `P.ARITH{oper=P.ADD, overflow=true, kind=P.INT 64}`      `P.IARITH{oper=P.IADD, sz=64}`
728    
729    * `int64_sub : int64 * int64 -> int64`<br/>    * `int64_sub : int64 * int64 -> int64`<br/>
730      `P.ARITH{oper=P.SUB, overflow=true, kind=P.INT 64}`      `P.IARITH{oper=P.ISUB, sz=64}`
731    
732    * `int64_mul : int64 * int64 -> int64`<br/>    * `int64_mul : int64 * int64 -> int64`<br/>
733      `P.ARITH{oper=P.MUL, overflow=true, kind=P.INT 64}`      `P.IARITH{oper=P.IMUL, sz=64}`
734    
735    * `int64_div : int64 * int64 -> int64`<br/>    * `int64_div : int64 * int64 -> int64`<br/>
736      `P.ARITH{oper=P.QUOT, overflow=true, kind=P.INT 64}`      `P.IARITH{oper=P.IQUOT, sz=64}`
737    
738    * `int64_mod : int64 * int64 -> int64`<br/>    * `int64_mod : int64 * int64 -> int64`<br/>
739      `P.ARITH{oper=P.REM, overflow=true, kind=P.INT 64}`      `P.IARITH{oper=P.IREM, sz=64}`
740    
741    * `int64_quot : int64 * int64 -> int64`<br/>    * `int64_quot : int64 * int64 -> int64`<br/>
742      `P.ARITH{oper=P.QUOT, overflow=true, kind=P.INT 64}`      `P.IARITH{oper=P.IQUOT, sz=64}`
743    
744    * `int64_rem : int64 * int64 -> int64`<br/>    * `int64_rem : int64 * int64 -> int64`<br/>
745      `P.ARITH{oper=P.REM, overflow=true, kind=P.INT 64}`      `P.IARITH{oper=P.IREM, sz=64}`
   
   * `int64_orb : int64 * int64 -> int64`<br/>  
     `P.ARITH{oper=P.ORB, overflow=false, kind=P.INT 64}`  
   
   * `int64_xorb : int64 * int64 -> int64`<br/>  
     `P.ARITH{oper=P.XORB, overflow=false, kind=P.INT 64}`  
   
   * `int64_andb : int64 * int64 -> int64`<br/>  
     `P.ARITH{oper=P.ANDB, overflow=false, kind=P.INT 64}`  
746    
747    * `int64_neg : word32 -> word32`<br/>    * `int64_neg : word32 -> word32`<br/>
748      `P.ARITH{oper=P.NEG, overflow=true, kind=P.INT 64}`      `P.IARITH{oper=P.INEG, sz=64}`
   
   * `int64_raw_rshift : int64 * word -> int64`<br/>  
     `P.ARITH{oper=P.RSHIFT, overflow=false, kind=P.INT 64}`  
   
   * `int64_raw_lshift : int64 * word -> int64`<br/>  
     `P.ARITH{oper=P.LSHIFT, overflow=false, kind=P.INT 64}`  
749    
750    * `int64_gt : int64 * int64 -> bool`<br/>    * `int64_gt : int64 * int64 -> bool`<br/>
751      `P.CMP{oper=P.GT, kind=P.INT 64}`      `P.CMP{oper=P.GT, kind=P.INT 64}`
# Line 547  Line 771 
771    * `int64_max : int64 * int64 -> int64`<br/>    * `int64_max : int64 * int64 -> int64`<br/>
772      `P.INLMAX (P.INT 64)`      `P.INLMAX (P.INT 64)`
773    
774    * `int64_abs : word32 -> word32`<br/>    * `int64_abs : int64 -> int64`<br/>
775      `P.INLABS (P.INT 64)`      `P.INLABS (P.INT 64)`
776    
777  #### 64-bit word operations  #### 64-bit word operations
778    **Note:** 64-bit word operations are currently not supported in the compiler,
779    but we expect to add them in 110.88.
780    
781      * `word64_mul : word64 * word64 -> word64`<br/>
782        `P.PURE_ARITH{oper=P.MUL, kind=P.UINT 64}`
783    
784      * `word64_div : word64 * word64 -> word64`<br/>
785        `P.PURE_ARITH{oper=P.QUOT, kind=P.UINT 64}`
786    
787      * `word64_mod : word64 * word64 -> word64`<br/>
788        `P.PURE_ARITH{oper=P.REM, kind=P.UINT 64}`
789    
790      * `word64_add : word64 * word64 -> word64`<br/>
791        `P.PURE_ARITH{oper=P.ADD, kind=P.UINT 64}`
792    
793      * `word64_sub : word64 * word64 -> word64`<br/>
794        `P.PURE_ARITH{oper=P.SUB, kind=P.UINT 64}`
795    
796      * `word64_orb : word64 * word64 -> word64`<br/>
797        `P.PURE_ARITH{oper=P.ORB, kind=P.UINT 64}`
798    
799      * `word64_xorb : word64 * word64 -> word64`<br/>
800        `P.PURE_ARITH{oper=P.XORB, kind=P.UINT 64}`
801    
802      * `word64_andb : word64 * word64 -> word64`<br/>
803        `P.PURE_ARITH{oper=P.ANDB, kind=P.UINT 64}`
804    
805      * `word64_notb : word64 -> word64`<br/>
806        `P.PURE_ARITH{oper=P.NOTB, kind=P.UINT 64}`
807    
808      * `word64_neg : word64 -> word64`<br/>
809        `P.PURE_ARITH{oper=P.NEG, kind=P.UINT 64}`
810    
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        `P.PURE_ARITH{oper=P.RSHIFT, kind=P.UINT 64}`
822    
823      * `word64_raw_rshiftl : word64 * word -> word`<br/>
824        `P.PURE_ARITH{oper=P.RSHIFTL, kind=P.UINT 64}`
825    
826      * `word64_raw_lshift : word64 * word -> word`<br/>
827        `P.PURE_ARITH{oper=P.LSHIFT, kind=P.UINT 64}`
828    
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  #### 64-bit real operations  #### 64-bit real operations
854      * `real64_add : real64 * real64 -> real64`<br/>
855        `P.PURE_ARITH{oper=P.ADD, overflow=true, kind=P.FLOAT 64}`
856    
857      * `real64_sub : real64 * real64 -> real64`<br/>
858        `P.PURE_ARITH{oper=P.SUB, overflow=true, kind=P.FLOAT 64}`
859    
860      * `real64_mul : real64 * real64 -> real64`<br/>
861        `P.PURE_ARITH{oper=P.MUL, overflow=true, kind=P.FLOAT 64}`
862    
863      * `real64_div : real64 * real64 -> real64`<br/>
864        `P.PURE_ARITH{oper=P.QUOT, overflow=true, kind=P.FLOAT 64}`
865    
866      * `real64_neg : word32 -> word32`<br/>
867        `P.PURE_ARITH{oper=P.NEG, overflow=true, kind=P.FLOAT 64}`
868    
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      * `real64_ge : real64 * real64 -> bool`<br/>
879        `P.CMP{oper=P.GTE, kind=P.FLOAT 64}`
880    
881      * `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        `P.FSGN 64`
889    
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      * `real64_abs : real64 -> real64`<br/>
897        `P.ARITH{oper=P.FABS, kind=P.FLOAT 64}`
898    
899      * `real64_sin : real64 -> real64`<br/>
900        `P.PURE_ARITH{oper=P.FSIN, kind=P.FLOAT 64}`
901    
902      * `real64_cos : real64 -> real64`<br/>
903        `P.PURE_ARITH{oper=P.FCOS, kind=P.FLOAT 64}`
904    
905      * `real64_tan : real64 -> real64`<br/>
906        `P.PURE_ARITH{oper=P.FTAN, kind=P.FLOAT 64}`
907    
908      * `real64_sqrt : real64 -> real64`<br/>
909        `P.PURE_ARITH{oper=P.FSQRT, kind=P.FLOAT 64}`
910    
911    
912  ### Conversions  ### Conversions
913    
914    We use the following operation-prefixes for conversions between integer and
915    word types:
916    
917      * `unsigned_` -- for word to integer conversions where the resulting
918        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      * `signed_` -- for word to integer conversions where the resulting
923        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      * no prefix for integer-to-integer, integer-to-word, and word-to-word,
929        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    #### 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      * `int_to_word : int -> word`<br />
958        `P.COPY(<int-size>, <int-size>)`
959    
960      * `unsigned_word_to_int : word -> int`<br />
961        `P.TESTU(<int-size>, <int-size>)`
962    
963      * `signed_word_to_int : word -> int`<br />
964        `P.COPY(<int-size>, <int-size>)`
965    
966      * `unsigned_word_to_intinf : word -> intinf`<br/>
967        `P.COPY_INF <int-size>`
968    
969      * `signed_word_to_intinf : word -> intinf`<br/>
970        `P.EXTEND_INF <int-size>`
971    
972      * `intinf_to_word : intinf -> word`<br/>
973        `P.TRUNC_INF <int-size>`
974    
975    #### Conversions for 32-bit integers and words
976    
977      * `int32_to_int : int32 -> int`<br/>
978        `P.TEST(32, 31)` (32-bit target) or
979        `P.EXTEND(32, 63)` (64-bit target).
980    
981      * `word32_to_word : word32 -> word`<br/>
982        `P.TRUNC(32, 31)` (32-bit target) or
983        `P.COPY(32, 63)` (64-bit target).
984    
985      * `int_to_int32 : int -> int32`<br/>
986        `P.EXTEND(31, 32)` (32-bit target) or
987        `P.TEST(63, 32)` (64-bit target).
988    
989      * `word_to_word32 : word -> word32`<br/>
990        `P.COPY(31, 32)` (32-bit target) or
991        `P.TRUNC(63, 32)` (64-bit target).
992    
993      * `int32_to_intinf : int32 -> intinf`<br/>
994        `P.EXTEND_INF 32`
995    
996      * `intinf_to_int32 : intinf -> int32`<br/>
997        `P.TEST_INF 32`
998    
999      * `int_to_word32 : int -> word32`<br/>
1000        `P.EXTEND(31, 32)` (32-bit target) or
1001        `P.TRUNC(63, 32)` (64-bit target).
1002    
1003      * `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    
1007      * `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    
1011      * `unsigned_word32_to_intinf : word32 -> intinf`<br/>
1012        `P.COPY_INF 32`
1013    
1014      * `signed_word32_to_intinf : word32 -> intinf`<br/>
1015        `P.EXTEND_INF 32`
1016    
1017      * `intinf_to_word32 : intinf -> word32`<br/>
1018        `P.TRUNC_INF 32`
1019    
1020    Note that if the `LargeWord.word` type is 64-bits (which it should be), the
1021    we have the following additional operations:
1022    
1023      * `word64_to_word32 : word64 -> word32`<br />
1024        Large word to word conversion<br/>
1025        `P.TRUNC(64, 32)`
1026    
1027      * `unsigned_word32_to_word64 : word32 -> word64`<br/>
1028        Unsigned word to large word conversion<br/>
1029        `P.COPY(32, 64)`
1030    
1031      * `signed_word32_to_word64 : word32 -> word64`<br/>
1032        Signed word to large word conversion<br/>
1033        `P.EXTEND(32, 64)`
1034    
1035    
1036    #### Conversions for 64-bit integers and words
1037    
1038      * `int64_to_int : int64 -> int`<br/>
1039        `P.TEST(64, <int-sz>)`.
1040    
1041      * `word64_to_word : word64 -> word`<br/>
1042        `P.TRUNC(64, <int-sz>)`.
1043    
1044      * `int_to_int64 : int -> int64`<br/>
1045        `P.EXTEND(<int-sz>, 64)`.
1046    
1047      * `word_to_word64 : word -> word64`<br/>
1048        Large word to word conversion<br/>
1049        `P.COPY(<int-sz>, 64)`.
1050    
1051      * `signed_word64_to_word32 : word64 -> word32`<br/>
1052        Unsigned word to large word conversion<br/>
1053        `P.TRUNC(64, 32)`.
1054    
1055      * `unsigned_word64_to_word32 : word64 -> word32`<br/>
1056        Signed word to large word conversion<br/>
1057        `P.COPY(32, 64)`.
1058    
1059      * `word32_to_word64 : word32 -> word64`<br/>
1060        `P.EXTEND(32, 64)`.
1061    
1062      * `int64_to_intinf : int64 -> intinf`<br/>
1063        `P.EXTEND_INF 64`
1064    
1065      * `intinf_to_int64 : intinf -> int64`<br/>
1066        `P.TEST_INF 64`
1067    
1068      * `int_to_word64 : int -> word64`<br/>
1069        `P.EXTEND(31, 64)` (64-bit target) or
1070        `P.TRUNC(63, 64)` (64-bit target).
1071    
1072      * `unsigned_word64_to_int : word64 -> int`<br/>
1073        `P.TESTU(64, 31)` (64-bit target) or
1074        `P.COPY(64, 63)` (64-bit target).
1075    
1076      * `signed_word64_to_int : word64 -> int`<br/>
1077        `P.TEST(64, 31)` (64-bit target) or
1078        `P.EXTEND(64, 63)` (64-bit target).
1079    
1080      * `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        `P.COPY(8, 32)`
1100    
1101      * `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        `P.TRUNC(32, intSz)`
1128    
1129      * `copy_int32_to_word32 : int32 -> word32`<br/>
1130        `P.COPY(32, 32)`
1131    
1132      * `copy_word_to_int32 : word32 -> int32`<br/>
1133        `P.COPY(intSz, 32)`
1134    
1135      * `copy_word32_to_int32 : word32 -> int32`<br/>
1136        `P.COPY(32, 32)`
1137    
1138    #### Additional conversions for 64-bit targets
1139    
1140    
1141    #### Conversions to support 64-bit integers/words on 32-bit targets.
1142    These operations are only present on 32-bit targets and are used to
1143    get access to the concrete representation of 64-bit integer and word
1144    values.
1145    
1146      * `int64_to_pair : int64 -> word32 * word32`<br/>
1147        `P.CVT64`
1148    
1149      * `int64_from_pair : word32 * word32 -> int64`<br/>
1150        `P.CVT64`
1151    
1152      * `word64_to_pair : word64 -> word32 * word32`<br/>
1153        `P.CVT64`
1154    
1155      * `word64_from_pair : word32 * word32 -> word64`<br/>
1156        `P.CVT64`
1157    
1158    
1159    #### Conversions between integers and reals
1160    
1161      * `int_to_real64 : int -> real64`<br />
1162        `P.INT_TO_REAL{from=<int-size>, to=64}`
1163    
1164      * `int32_to_real64 : int32 -> real64`<br />
1165        `P.INT_TO_REAL{from=32, to=64}` (32-bit targets only)
1166    
1167      * `int64_to_real64 : int64 -> real64`<br />
1168        `P.INT_TO_REAL{from=64, to=64}` (64-bit targets only)
1169    
1170      * `floor_real64_to_int : real64 -> int`<br />
1171        `P.REAL_TO_INT{floor=true, from=64, to=<int-size>}`
1172    
1173      * `round_real64_to_int : real64 -> int`<br />
1174        `P.REAL_TO_INT{floor=false, from=64, to=<int-size>}`
1175    
1176    Note: the real to integer conversions should be revised
1177    to directly support the various rounding modes (floor,
1178    ceiling, truncation, and round).
1179    
1180    ### Character comparisons
1181    
1182      * `char_lt : char * char -> bool`<br />
1183        `P.CMP{oper=P.LT, kind=P.UINT <int-size>}`
1184    
1185      * `char_lt : char * char -> bool`<br />
1186        `P.CMP{oper=P.LTE, kind=P.UINT <int-size>}`
1187    
1188      * `char_gt : char * char -> bool`<br />
1189        `P.CMP{oper=P.GT, kind=P.UINT <int-size>}`
1190    
1191      * `char_gt : char * char -> bool`<br />
1192        `P.CMP{oper=P.GTE, kind=P.UINT <int-size>}`
1193    
1194      * `char_eql : char * char -> bool`<br/>
1195        `P.CMP{oper=P.EQL, kind=P.UINT <int-size>}`
1196    
1197      * `char_neq : char * char -> bool`<br/>
1198        `P.CMP{oper=P.NEQ, kind=P.UINT <int-size>}`
1199    
1200    ### FFI support
1201    
1202    The following primops work on raw memory addresses and are included to support
1203    interaction with **C** code using the **NLFFI** infrastructure.
1204    
1205    We use the type `raw_ptr` here to represent the type of a pointer to a **C**
1206    object; it is a word type that is the same size as a machine address
1207    (*i.e.*, `Word32.word32` or `Word64.word`).  Eventually, it should be made
1208    abstract and be supported by the compiler.
1209    
1210    Note also that the `RAW_LOAD` and `RAW_STORE` primops are used with different
1211    numbers of arguments (*e.g.*, `RAW_LOAD` has one argument for `raw_load_int16`,
1212    but two arguments for `raw_sub_int16`, where the extra argument is the offset).
1213    
1214      * `raw_ccall : raw_ptr * 'a * 'b -> 'c`<br />
1215        This primop is a call to a **C** function via a function pointer (the
1216        first argument).  The primop cannot be used without having `'a`, `'b`,
1217        and `'c` monomorphically instantiated.  In particular, `'a` will be
1218        the type of the ML argument list, `'c` will be the type of the result,
1219        and `'b` will be a type of fake arguments.  The idea is that `'b` is
1220        instantiated with an ML type that encodes the type of the actual
1221        **C** function in order to be able to generate code according to the **C**
1222        calling convention. <br/>
1223        In other words, 'b will be a completely ad-hoc encoding of a `CTypes.c_proto`
1224        value in ML types.  The encoding also contains information about
1225        calling conventions and reentrancy. <br />
1226        `P.RAW_CCALL NONE`
1227    
1228      * `raw_record : int -> 'a`<br />
1229        Allocates an uninitialized **C** object of the given size on the ML heap;
1230        the object will be word-size aligned.
1231        We use the `raw_sub_xxx` and `raw_update_xxx` primops (see below)
1232        to access and update the record.  The `'a` result type is to guarantee
1233        that the compiler will treat the record as a ML object, in case it passes
1234        thru a gc boundary. <br/>
1235        `P.RAW_RECORD { align64 = false }`
1236    
1237      * `raw_record64 : int -> 'a`<br />
1238        Allocates an uninitialized **C** object of the given size on the ML heap;
1239        the object will be 64-bit aligned. <br/>
1240        `P.RAW_RECORD { align64 = true }`
1241    
1242      * `raw_load_int8 : raw_ptr -> int32`<br />
1243        `P.RAW_LOAD(P.INT 8)`
1244    
1245      * `raw_load_word8 : raw_ptr -> word32`<br />
1246        `P.RAW_LOAD(P.UINT 8)`
1247    
1248      * `raw_load_int16 : raw_ptr -> int32`<br />
1249        `P.RAW_LOAD(P.INT 16)`
1250    
1251      * `raw_load_word16 : raw_ptr -> word32`<br />
1252        `P.RAW_LOAD(P.UINT 16)`
1253    
1254      * `raw_load_int32 : raw_ptr -> int32`<br />
1255        `P.RAW_LOAD(P.INT 32)`
1256    
1257      * `raw_load_word32 : raw_ptr -> word32`<br />
1258        `P.RAW_LOAD(P.UINT 32)`
1259    
1260      * `raw_load_float32 : raw_ptr -> real`<br />
1261        `P.RAW_LOAD(P.FLOAT 32)`
1262    
1263      * `raw_load_float64 : raw_ptr -> real`<br />
1264        `P.RAW_LOAD(P.FLOAT 32)`
1265    
1266      * `raw_store_int8 : raw_ptr * int32 -> unit`<br />
1267        `P.RAW_STORE(P.INT 8)`
1268    
1269      * `raw_store_word8 : raw_ptr * word32 -> unit`<br />
1270        `P.RAW_STORE(P.UINT 8)`
1271    
1272      * `raw_store_int16 : raw_ptr * int32 -> unit`<br />
1273        `P.RAW_STORE(P.INT 16)`
1274    
1275      * `raw_store_word16 : raw_ptr * word32 -> unit`<br />
1276        `P.RAW_STORE(P.UINT 16)`
1277    
1278      * `raw_store_int32 : raw_ptr * int32 -> unit`<br />
1279        `P.RAW_STORE(P.INT 32)`
1280    
1281      * `raw_store_word32 : raw_ptr * word32 -> unit`<br />
1282        `P.RAW_STORE(P.UINT 32)`
1283    
1284      * `raw_store_float32 : raw_ptr * real -> unit`<br />
1285        `P.RAW_STORE(P.FLOAT 32)`
1286    
1287      * `raw_store_float64 : raw_ptr * real -> unit`<br />
1288        `P.RAW_STORE(P.FLOAT 32)`
1289    
1290      * `raw_sub_int8 : 'a * raw_ptr -> int32`<br />
1291        `P.RAW_LOAD(P.INT 8)`
1292    
1293      * `raw_sub_word8 : 'a * raw_ptr -> word32`<br />
1294        `P.RAW_LOAD(P.UINT 8)`
1295    
1296      * `raw_sub_int16 : 'a * raw_ptr -> int32`<br />
1297        `P.RAW_LOAD(P.INT 16)`
1298    
1299      * `raw_sub_word16 : 'a * raw_ptr -> word32`<br />
1300        `P.RAW_LOAD(P.UINT 16)`
1301    
1302      * `raw_sub_int32 : 'a * raw_ptr -> int32`<br />
1303        `P.RAW_LOAD(P.INT 32)`
1304    
1305      * `raw_sub_word32 : 'a * raw_ptr -> word32`<br />
1306        `P.RAW_LOAD(P.UINT 32)`
1307    
1308      * `raw_sub_float32 : 'a * raw_ptr -> real`<br />
1309        `P.RAW_LOAD(P.FLOAT 32)`
1310    
1311      * `raw_sub_float64 : 'a * raw_ptr -> real`<br />
1312        `P.RAW_LOAD(P.FLOAT 32)`
1313    
1314      * `raw_update_int8 : 'a * raw_ptr * int32 -> unit`<br />
1315        `P.RAW_STORE(P.INT 8)`
1316    
1317      * `raw_update_word8 : 'a * raw_ptr * word32 -> unit`<br />
1318        `P.RAW_STORE(P.INT 8)`
1319    
1320      * `raw_update_int16 : 'a * raw_ptr * int32 -> unit`<br />
1321        `P.RAW_STORE(P.INT 8)`
1322    
1323      * `raw_update_word16 : 'a * raw_ptr * word32 -> unit`<br />
1324        `P.RAW_STORE(P.UINT 16)`
1325    
1326      * `raw_update_int32 : 'a * raw_ptr * int32 -> unit`<br />
1327        `P.RAW_STORE(P.INT 32)`
1328    
1329      * `raw_update_word32 : 'a * raw_ptr * word32 -> unit`<br />
1330        `P.RAW_STORE(P.UINT 32)`
1331    
1332      * `raw_update_float32 : 'a * raw_ptr * real -> unit`<br />
1333        `P.RAW_STORE(P.FLOAT 32)`
1334    
1335      * `raw_update_float64 : 'a * raw_ptr * real -> unit`<br />
1336        `P.RAW_STORE(P.FLOAT 64)`

Legend:
Removed from v.4961  
changed lines
  Added in v.5099

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