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 /sml/trunk/compiler/ElabData/prim/primop.sig
ViewVC logotype

Diff of /sml/trunk/compiler/ElabData/prim/primop.sig

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

sml/trunk/compiler/FLINT/kernel/primop.sig revision 2162, Thu Nov 2 21:20:47 2006 UTC sml/trunk/compiler/ElabData/prim/primop.sig revision 4889, Sun Oct 14 13:02:19 2018 UTC
# Line 1  Line 1 
1  (* Copyright 1996 by AT&T Bell Laboratories *)  (* primop.sig
2  (* primop.sig *)   *
3     * COPYRIGHT (c) 2017 The Fellowship of SML/NJ (http://www.smlnj.org)
4  (*********************************************************************   * All rights reserved.
5                     Integer/Word Conversions Explained   *)
   
 All integer/word conversion operations are expressed using five  
 primitive conversion operators. Algebraic equations over these  
 operators are easy to define and can be used to simplify composition  
 of conversion operations.  
   
 The five basic conversion operators are (in all cases, we assume  
 that (n >= m):  
   
   TEST(n,m)     -- map an n-bit, 2's complement signed value to an  
                    m-bit, 2's complement signed value;  
                    raise Overflow if the value is too large.  
   
   TESTU(n,m)    -- map an unsigned n-bit value to an m-bit 2's  
                    complement value; raise Overflow if the value  
                    is too large.  
   
   EXTEND(m,n)   -- sign extend an m-bit value to a n-bit value  
   
   TRUNC(n,m)    -- truncate an n-bit value to an m-bit value.  
   
   COPY(m,n)     -- copy an m-bit value to an n-bit value.  
   
 TEST, TESTU, and TRUNC are used to go from large values to small  
 ones, and EXTEND and COPY are used to go from small values to  
 large. The operators EXTEND, TRUNC, and COPY are "pure," while TEST  
 and TESTU may raise Overflow.  
   
 Conversions where the sizes are the same can be simplified to copies:  
   
   TEST(n,n)     == COPY(n,n)  
   EXTEND(n,n)   == COPY(n,n)    Note: this does not apply to TESTU  
   TRUNC(n,n)    == COPY(n,n)  
   
 The translation of conversion operations in the Word32 and Word8  
 structures (for example) is given by:  
   
   Module        function     => Implemented by  
   ----------------------------------------------------------  
   Word32        toLargeInt    => TESTU(32,32)  
                 toLargeIntX   => EXTEND(32,32)          = COPY(32,32)  
                 fromLargeInt  => COPY(32,32)  
                 toInt         => TESTU(32,31)  
                 toIntX        => TEST(32,31)  
                 fromInt       => EXTEND(31,32)  
                 toLargeWord   => COPY(32,32)  
                 toLargeWordX  => EXTEND(32,32)          = COPY(32,32)  
                 fromLargeWord => TRUNC(32,32)           = COPY(32,32)  
   
   Word8         toLargeInt    => COPY(8,32)  
                 toLargeIntX   => EXTEND(8,32)  
                 fromLargeInt  => TRUNC(32,8)  
                 toInt         => COPY(8,31)  
                 toIntX        => EXTEND(8,31)  
                 fromInt       => TRUNC(31,8)  
                 toLargeWord   => COPY(8,32)  
                 toLargeWordX  => EXTEND(8,32)  
                 fromLargeWord => TRUNC(32,8)  
   
   
 Each operator composed with itself is itself, but with different parameters:  
   
   TEST(n,m) o TEST(p,n)         == TEST(p,m)  
   TESTU(n,m) o TESTU(p,n)       == TESTU(p,m)  
   EXTEND(n,m) o EXTEND(p,n)     == EXTEND(p,m)  
   TRUNC(n,m) o TRUNC(p,n)       == TRUNC(p,m)  
   COPY(n,m) o COPY(p,n)         == COPY(p,m)  
   
 The composition of these operators can be described by a simple algebra.  
   
   EXTEND(n,m) o COPY(p,n)       == COPY(p,m)   if (n > p)  
                                 == EXTEND(p,m) if (n = p)  
   COPY(n,m) o EXTEND(p,n)       == EXTEND(p,m) if (n = m)  
   
   TRUNC(n,m) o COPY(p,n)        == COPY(p,m)   if (m >= p)  
                                 == TRUNC(p,m)  if (m < p)  
   
   COPY(n,m) o TRUNC(p,n)        == TRUNC(p,m)  if (n = m)  
   
   TEST(n,m) o COPY(p,n)         == COPY(p,m)   if (m >= p)  
                                 == TEST(p,m)   if (m < p)  
   
   TESTU(n,m) o COPY(p,n)        == COPY(p,m)   if (m >= p)  
                                 == TESTU(p,m)  if (m < p)  
   
   COPY(n,m) o TEST(p,n)         == TEST(p,m)   if (n = m)  
   
   COPY(n,m) o TESTU(p,n)        == TESTU(p,m)  if (n = m)  
   
   TRUNC(n,m) o EXTEND(p,n)      == EXTEND(p,m) if (m >= p)  
                                 == TRUNC(p,m)  if (m < p)  
   
   TEST(n,m) o EXTEND(p,n)       == EXTEND(p,m) if (m >= p)  
                                 == TEST(p,m)   if (m < p)  
   
   TESTU(n,m) o EXTEND(p,n)      == EXTEND(p,m) if (m >= p)  
                                 == TESTU(p,m)  if (m < p)  
   
 For example, consider:  
         Word.toInt o Word.fromLargeWord o Word8.toLargeWord  
   
 This translates to:  
         TESTU(31,31) o TRUNC(32,31) o COPY(8,32)  
   
 and simplifies to:  
         TESTU(31,31) o COPY(8,31)  
   
 This further simplifies to:  
         COPY(8, 31)  
   
 Since both 8-bit and 31-bit quantities are tagged the same way, this  
 gets translated to a MOVE. With a smart register allocator that MOVE  
 can be eliminated.  
 *********************************************************************)  
6    
7  signature PRIM_OP =  signature PRIMOP =
8  sig  sig
9    
10  (* numkind includes kind and number of bits *)  (* numkind includes kind and number of bits *)
# Line 126  Line 12 
12    = INT of int    = INT of int
13    | UINT of int    | UINT of int
14    | FLOAT of int    | FLOAT of int
15    (* QUESTION: what about IntInf.int? *)
16    
17  datatype arithop  datatype arithop
18    = + | - | * | / | ~                           (* int or float *)        = ADD | SUB | MUL | NEG                   (* int or float *)
19    | ABS | FSQRT | FSIN | FCOS | FTAN            (* floating point only *)        | FDIV | ABS | FSQRT | FSIN | FCOS | FTAN (* floating point only *)
20    | LSHIFT | RSHIFT | RSHIFTL                   (* int only *)    | LSHIFT | RSHIFT | RSHIFTL                   (* int only *)
21    | ANDB | ORB | XORB | NOTB                    (* int only *)    | ANDB | ORB | XORB | NOTB                    (* int only *)
22    | REM | DIV | MOD                             (* int only *)        | DIV | MOD | QUOT | REM                  (* int only *)
   
 datatype cmpop = > | >= | < | <= | LEU | LTU | GEU | GTU | EQL | NEQ  
23    
24  (*      datatype cmpop
25   * Various primitive operations.  Those that are designated "inline" are        = GT | GTE | LT | LTE                     (* signed comparisons *)
26   * expanded into lambda code in terms of other operators,        | LEU | LTU | GEU | GTU                   (* unsigned comparisons *)
27   * as is the "checked=true" version of NUMSUBSCRIPT or NUMUPDATE.        | EQL | NEQ                               (* equality *)
28   * NUMSUBSCRIPT and NUMUPDATE are for arrays of floats or integers        | FSGN                                    (* floating point only *)
29   * stored WITHOUT boxing or tags.  
30      (* datatype primop:
31       * Various primitive operations. Those that are designated "inline" (L:) in
32       * the comments are expanded into lambda code in terms of other operators,
33       * as are the "checked=true" versions of NUMSUBSCRIPT and NUMUPDATE (L?:).
34       * "Environmental" primops (occurring in the InLine structure) are indicated
35       * by "E:" in the comment.
36       *
37       * See dev-notes/conversions.md for an explanation of the conversion operators.
38   *)   *)
39  datatype primop  datatype primop
40    = ARITH of {oper: arithop, overflow: bool, kind: numkind}        = ARITH of {                              (* E: arithmetic ops *)
41    | INLLSHIFT of numkind              oper: arithop, overflow: bool, kind: numkind
42    | INLRSHIFT of numkind            }
43    | INLRSHIFTL of numkind        | INLLSHIFT of numkind                    (* E: left shift *)
44    | CMP of {oper: cmpop, kind: numkind}        | INLRSHIFT of numkind                    (* E: right shift *)
45          | INLRSHIFTL of numkind                   (* E: right shift logical *)
46    | TESTU of int * int        | CMP of {oper: cmpop, kind: numkind}     (* E: generic compare *)
47    | TEST of int * int        | TESTU of int * int                      (* E: conversions to int, e.g. testu_31_31 *)
48    | TRUNC of int * int        | TEST of int * int                       (* E: conversions to int, e.g. test_32_31_w *)
49    | EXTEND of int * int        | TRUNC of int * int                      (* E: truncations to smaller int/word, e.g. trunc_32_31_i *)
50    | COPY of int * int        | EXTEND of int * int                     (* E: extensions to int32, word32 *)
51          | COPY of int * int                       (* E: conversions, e.g. copy_32_32_ii *)
52    | TEST_INF of int                     (* inf -> i *)        | TEST_INF of int                         (* E: intinf conversions, e.g. test_inf_31 *)
53    | TRUNC_INF of int                    (* inf -> i *)        | TRUNC_INF of int                        (* E: intinf truncations, e.g. trunc_inf_31 *)
54    | EXTEND_INF of int                   (* i -> inf *)        | EXTEND_INF of int                       (* E: intinf extensions, e.g. extend_8_inf *)
55    | COPY_INF of int                     (* i -> inf *)        | COPY_INF of int                         (* E: conversions to intinf, e.g. copy_8_inf *)
56          | ROUND of {                              (* E: floor, round *)
57    | ROUND of {floor: bool, fromkind: numkind, tokind: numkind}              floor: bool, fromkind: numkind, tokind: numkind
58    | REAL of {fromkind: numkind, tokind: numkind}            }
59          | REAL of {                               (* E: real, real32 *)
60    | NUMSUBSCRIPT of {kind: numkind, checked: bool, immutable: bool}              fromkind: numkind, tokind: numkind
61    | NUMUPDATE of {kind: numkind, checked: bool}            }
62          | NUMSUBSCRIPT of {                       (* E: L?: ordof, etc. *)
63    | SUBSCRIPT                  (* polymorphic array subscript *)              kind: numkind, checked: bool, immutable: bool
64    | SUBSCRIPTV                 (* poly vector subscript *)            }
65    | INLSUBSCRIPT               (* inline poly array subscript *)        | NUMUPDATE of {                          (* E: L?: store, etc. *)
66    | INLSUBSCRIPTV              (* inline poly vector subscript *)              kind: numkind, checked: bool
67    | INLMKARRAY                 (* inline poly array creation *)            }
68          | SUBSCRIPT                               (* E: polymorphic array subscript *)
69    | PTREQL | PTRNEQ            (* pointer equality *)        | SUBSCRIPTV                              (* E: poly vector subscript *)
70    | POLYEQL | POLYNEQ          (* polymorphic equality *)        | INLSUBSCRIPT                            (* E: L: poly array subscript *)
71    | BOXED | UNBOXED            (* boxity tests *)        | INLSUBSCRIPTV                           (* E: L: poly vector subscript *)
72    | LENGTH                     (* vector, string, array, ... length *)        | INLMKARRAY                              (* E: L: poly array creation *)
73    | OBJLENGTH                  (* length of arbitrary heap object *)        | PTREQL | PTRNEQ                         (* E: pointer equality *)
74    | CAST        | POLYEQL | POLYNEQ                       (* E: polymorphic equality *)
75    | WCAST        | BOXED | UNBOXED                         (* E: boxity tests *)
76    | GETRUNVEC                  (* get the pointer to the run-vector *)        | LENGTH                                  (* E: vector, string, array, ... length *)
77    | MARKEXN                    (* mark an exception value with a string *)        | OBJLENGTH                               (* E: length of arbitrary heap object *)
78    | GETHDLR | SETHDLR          (* get/set exn handler pointer *)        | CAST                                    (* E: cast *)
79    | GETVAR | SETVAR            (* get/set var register *)        | GETHDLR | SETHDLR                       (* E: get/set exn handler pointer *)
80    | GETPSEUDO | SETPSEUDO      (* get/set pseudo registers *)        | GETVAR | SETVAR                         (* E: get/set var register *)
81    | SETMARK | DISPOSE          (* capture/dispose frames *)        | MAKEREF                                 (* E: allocate a ref cell *)
82    | MAKEREF                    (* allocate a ref cell *)        | CALLCC | CAPTURE | THROW                (* E: continuation operations *)
83    | CALLCC | CAPTURE | THROW   (* continuation operations *)        | ISOLATE                                 (* E: isolating a function *)
84    | ISOLATE                    (* isolating a function *)        | DEREF                                   (* E: dereferencing *)
85    | DEREF                      (* dereferencing *)        | ASSIGN                                  (* E: assignment *)
86    | ASSIGN                     (* assignment *)        | UPDATE                                  (* E: array or reference update (maybe boxed) *)
87    | UNBOXEDASSIGN              (* assignment to integer reference *)        | INLUPDATE                               (* E: L: array update (maybe boxed) *)
88    | UPDATE                     (* array update (maybe boxed) *)        | UNBOXEDUPDATE                           (* E: update array of integers WITH tags
89    | INLUPDATE                  (* inline array update (maybe boxed) *)                                                   * removed by Zhong, put back by Matthias
90    | BOXEDUPDATE                (* boxed array update *)                                                   * (see FLINT/trans/primopmap.sml) *)
91    | UNBOXEDUPDATE              (* update array of integers WITH tags *)        | GETTAG                                  (* E: extract the tag portion of an
92                                                     * object's descriptor as an ML int *)
93    | GETTAG                     (* extract the tag portion of an *)        | MKSPECIAL                               (* E: make a special object *)
94                                 (* object's descriptor as an ML int *)        | SETSPECIAL                              (* E: set the state of a special object *)
95    | MKSPECIAL                  (* make a special object *)        | GETSPECIAL                              (* E: get the state of a special object *)
96    | SETSPECIAL                 (* set the state of a special object *)        | INLMIN of numkind                       (* E: L: min *)
97    | GETSPECIAL                 (* get the state of a special object *)        | INLMAX of numkind                       (* E: L: max *)
98    | USELVAR | DEFLVAR        | INLABS of numkind                       (* E: L: abs *)
99    | INLMIN of numkind          (* inline min *)        | INLNOT                                  (* E: L: bool not operator *)
100    | INLMAX of numkind          (* inline max *)        | INLCOMPOSE                              (* E: L: compose "op o"  operator *)
101    | INLABS of numkind          (* inline abs *)        | INLBEFORE                               (* E: L: "before" operator *)
102    | INLNOT                     (* inline bool not operator *)        | INLIGNORE                               (* E: L: "ignore" function *)
103    | INLCOMPOSE                 (* inline compose "op o"  operator *)      (* primops to support new array representations *)
104    | INLBEFORE                  (* inline "before" operator *)        | NEW_ARRAY0                              (* E: allocate zero-length array header *)
105    | INLIGNORE                  (* inline "ignore" function *)        | GET_SEQ_DATA                            (* E: get data pointer from arr/vec header *)
106    | INL_ARRAY                  (* inline polymorphic array allocation *)        | SUBSCRIPT_REC                           (* E: record subscript operation *)
107    | INL_VECTOR                 (* inline polymorphic vector allocation *)        | SUBSCRIPT_RAW64                         (* E: raw64 subscript operation *)
108    | INL_MONOARRAY of numkind   (* inline monomorphic array allocation *)        | INLIDENTITY                             (* E: polymorphic identity *)
109    | INL_MONOVECTOR of numkind  (* inline monomorphic vector allocation *)        | CVT64                                   (* E: convert between external and
110                                                     * internal representation of compiler
111    | MKETAG                     (* make a new exception tag *)                                                   * simulated 64-bit scalars, e.g. w64p *)
112    | WRAP                       (* box a value by wrapping it *)      (* Primops to support C FFI. *)
113    | UNWRAP                     (* unbox a value by unwrapping it *)        | RAW_LOAD of numkind                     (* E: load from arbitrary memory location *)
114  (* Primops to support new array representations *)        | RAW_STORE of numkind                    (* E: store to arbitrary memory location *)
115    | NEW_ARRAY0                  (* allocate zero-length array header *)      (* E: make a call to a C-function;
   | GET_SEQ_DATA                (* get data pointer from arr/vec header *)  
   | SUBSCRIPT_REC               (* record subscript operation *)  
   | SUBSCRIPT_RAW64             (* raw64 subscript operation *)  
 (* Primops to support new experimental C FFI. *)  
   | RAW_LOAD of numkind         (* load from arbitrary memory location *)  
   | RAW_STORE of numkind        (* store to arbitrary memory location *)  
     (* make a call to a C-function;  
116       * The primop carries C function prototype information and specifies       * The primop carries C function prototype information and specifies
117       * which of its (ML-) arguments are floating point. C prototype       * which of its (ML-) arguments are floating point. C prototype
118       * information is for use by the backend, ML information is for       * information is for use by the backend, ML information is for
119       * use by the CPS converter. *)       * use by the CPS converter. *)
120    | RAW_CCALL of { c_proto: CTypes.c_proto,        | RAW_CCALL of {
121                c_proto: PrimCTypes.c_proto,
122                     ml_args: ccall_type list,                     ml_args: ccall_type list,
123                     ml_res_opt: ccall_type option,                     ml_res_opt: ccall_type option,
124                     reentrant : bool                     reentrant : bool
# Line 239  Line 126 
126     (* Allocate uninitialized storage on the heap.     (* Allocate uninitialized storage on the heap.
127      * The record is meant to hold short-lived C objects, i.e., they      * The record is meant to hold short-lived C objects, i.e., they
128      * are not ML pointers.  The representation is      * are not ML pointers.  The representation is
129      * the same as RECORD with tag tag_raw32 (fblock = false),      * the same as RECORD with tag tag_raw32 or tag_fblock.
     * or tag_fblock (fblock = true).  
130      *)      *)
131    | RAW_RECORD of { fblock: bool }        | RAW_RECORD of { fblock: bool }  (* E: *)
132    
133        (* non-environmental primops (not found in InLine) *)
134          | UNBOXEDASSIGN                   (* assignment to integer reference *)
135    
136          | WCAST                           (* ? *)
137          | MARKEXN                         (* mark an exception value with a string *)
138    
139    | INLIDENTITY                         (* polymorphic identity *)        | INL_ARRAY                       (* L: polymorphic array allocation *)
140          | INL_VECTOR                      (* L: polymorphic vector allocation *)
141          | INL_MONOARRAY of numkind        (* L: monomorphic array allocation *)
142          | INL_MONOVECTOR of numkind       (* L: monomorphic vector allocation *)
143    
144    | CVT64                               (* convert between external and        | MKETAG                          (* make a new exception tag *)
145                                           * internal representation of        | WRAP                            (* box a value by wrapping it *)
146                                           * simulated 64-bit scalars *)        | UNWRAP                          (* unbox a value by unwrapping it *)
147    
148  and ccall_type =  and ccall_type =
149      CCI32 |                             (* passed as int32 *)      CCI32 |                             (* passed as int32 *)
# Line 269  Line 164 
164  val ILT : primop  val ILT : primop
165  val ILE : primop  val ILE : primop
166  val IGE : primop  val IGE : primop
167        val UIEQL : primop  (* for UINT kind, may not matter *)
168    
169        val mkIEQL : int -> primop   (* make equality primop for other sizes *)
170        val mkUIEQL : int -> primop  (* and for unsigned (kind = UINT) *)
171    
172  val prNumkind : numkind -> string  val prNumkind : numkind -> string
173  val prPrimop: primop -> string  val prPrimop: primop -> string
174  val mayRaise : primop -> bool  val mayRaise : primop -> bool
175    
176  (* This should return more than just a boolean.  (* This should return more than just a boolean.
177   * True means "can not be dead-code eliminated" *)   * True means "can not be dead-code eliminated" *)
178  val effect : primop -> bool  val effect : primop -> bool

Legend:
Removed from v.2162  
changed lines
  Added in v.4889

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