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 5022, Wed May 1 12:29:11 2019 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      (* arithmetic operations that may overflow; for the division operators,
18       * we assume that the second argument is never zero (i.e., an explicit
19       * test for zero is done before the operation).
20       *)
21  datatype arithop  datatype arithop
22    = + | - | * | / | ~                           (* int or float *)        = IADD | ISUB | IMUL | IDIV | IMOD | IQUOT | IREM | INEG
23    | ABS | FSQRT | FSIN | FCOS | FTAN            (* floating point only *)  
24    | LSHIFT | RSHIFT | RSHIFTL                   (* int only *)    (* arithmetic operations that do not overflow; for the division operators,
25    | ANDB | ORB | XORB | NOTB                    (* int only *)     * we assume that the second argument is never zero (i.e., an explicit
26    | REM | DIV | MOD                             (* int only *)     * test for zero is done before the operation).
27       *)
28  datatype cmpop = > | >= | < | <= | LEU | LTU | GEU | GTU | EQL | NEQ      datatype pureop
29          = ADD | SUB | MUL | QUOT | REM | NEG
30  (*        | LSHIFT | RSHIFT | RSHIFTL
31   * Various primitive operations.  Those that are designated "inline" are        | ORB | XORB | ANDB | NOTB
32   * expanded into lambda code in terms of other operators,        | FDIV | FABS | FSQRT | FSIN | FCOS | FTAN
33   * as is the "checked=true" version of NUMSUBSCRIPT or NUMUPDATE.  
34   * NUMSUBSCRIPT and NUMUPDATE are for arrays of floats or integers    (* comparison operators *)
35   * stored WITHOUT boxing or tags.      datatype cmpop
36          = GT | GTE | LT | LTE | EQL | NEQ
37    
38      (* datatype primop:
39       * Various primitive operations. Those that are designated "inline" (L:) in
40       * the comments are expanded into lambda code in terms of other operators,
41       * as are the "checked=true" versions of NUMSUBSCRIPT and NUMUPDATE (L?:).
42       * "Environmental" primops (occurring in the InLine structure) are indicated
43       * by "E:" in the comment.
44       *
45       * See dev-notes/conversions.md for an explanation of the conversion operators.
46   *)   *)
47  datatype primop  datatype primop
48    = ARITH of {oper: arithop, overflow: bool, kind: numkind}        = IARITH of {                             (* E: integer arithmetic ops *)
49    | INLLSHIFT of numkind              oper : arithop, sz : int            (* kind = INT sz *)
50    | INLRSHIFT of numkind            }
51    | INLRSHIFTL of numkind        | PURE_ARITH of {                         (* E: arithmetic ops *)
52    | CMP of {oper: cmpop, kind: numkind}              oper : pureop, kind : numkind
53              }
54    | TESTU of int * int        | INLDIV of numkind                       (* E: integer div *)
55    | TEST of int * int        | INLMOD of numkind                       (* E: integer mod *)
56    | TRUNC of int * int        | INLQUOT of numkind                      (* E: integer/word quot *)
57    | EXTEND of int * int        | INLREM of numkind                       (* E: integer/word rem *)
58    | COPY of int * int        | INLLSHIFT of numkind                    (* E: left shift *)
59          | INLRSHIFT of numkind                    (* E: right shift *)
60    | TEST_INF of int                     (* inf -> i *)        | INLRSHIFTL of numkind                   (* E: right shift logical *)
61    | TRUNC_INF of int                    (* inf -> i *)        | CMP of {oper: cmpop, kind: numkind}     (* E: generic compare *)
62    | EXTEND_INF of int                   (* i -> inf *)        | FSGN of int                             (* E: floating point sign test *)
63    | COPY_INF of int                     (* i -> inf *)        | INLCHR                                  (* E: inline int to char conversion *)
64          | TESTU of int * int                      (* E: conversions to int, e.g. testu_31_31 *)
65    | ROUND of {floor: bool, fromkind: numkind, tokind: numkind}        | TEST of int * int                       (* E: conversions to int, e.g. test_32_31_w *)
66    | REAL of {fromkind: numkind, tokind: numkind}        | TRUNC of int * int                      (* E: truncations to smaller int/word, e.g. trunc_32_31_i *)
67          | EXTEND of int * int                     (* E: extensions to int32, word32 *)
68    | NUMSUBSCRIPT of {kind: numkind, checked: bool, immutable: bool}        | COPY of int * int                       (* E: conversions, e.g. copy_32_32_ii *)
69    | NUMUPDATE of {kind: numkind, checked: bool}        | TEST_INF of int                         (* E: intinf conversions, e.g. test_inf_31 *)
70          | TRUNC_INF of int                        (* E: intinf truncations, e.g. trunc_inf_31 *)
71    | SUBSCRIPT                  (* polymorphic array subscript *)        | EXTEND_INF of int                       (* E: intinf extensions, e.g. extend_8_inf *)
72    | SUBSCRIPTV                 (* poly vector subscript *)        | COPY_INF of int                         (* E: conversions to intinf, e.g. copy_8_inf *)
73    | INLSUBSCRIPT               (* inline poly array subscript *)        | REAL_TO_INT of {                        (* E: floor, round *)
74    | INLSUBSCRIPTV              (* inline poly vector subscript *)              floor: bool, from: int, to: int
75    | INLMKARRAY                 (* inline poly array creation *)            }
76          | INT_TO_REAL of {                        (* E: real, real32 *)
77    | PTREQL | PTRNEQ            (* pointer equality *)              from: int, to: int
78    | POLYEQL | POLYNEQ          (* polymorphic equality *)            }
79    | BOXED | UNBOXED            (* boxity tests *)        | NUMSUBSCRIPT of {                       (* E: L?: ordof, etc. *)
80    | LENGTH                     (* vector, string, array, ... length *)              kind: numkind, checked: bool, immutable: bool
81    | OBJLENGTH                  (* length of arbitrary heap object *)            }
82    | CAST        | NUMUPDATE of {                          (* E: L?: store, etc. *)
83    | WCAST              kind: numkind, checked: bool
84    | GETRUNVEC                  (* get the pointer to the run-vector *)            }
85    | MARKEXN                    (* mark an exception value with a string *)        | SUBSCRIPT                               (* E: polymorphic array subscript *)
86    | GETHDLR | SETHDLR          (* get/set exn handler pointer *)        | SUBSCRIPTV                              (* E: poly vector subscript *)
87    | GETVAR | SETVAR            (* get/set var register *)        | INLSUBSCRIPT                            (* E: L: poly array subscript *)
88    | GETPSEUDO | SETPSEUDO      (* get/set pseudo registers *)        | INLSUBSCRIPTV                           (* E: L: poly vector subscript *)
89    | SETMARK | DISPOSE          (* capture/dispose frames *)        | INLMKARRAY                              (* E: L: poly array creation *)
90    | MAKEREF                    (* allocate a ref cell *)        | PTREQL | PTRNEQ                         (* E: pointer equality *)
91    | CALLCC | CAPTURE | THROW   (* continuation operations *)        | POLYEQL | POLYNEQ                       (* E: polymorphic equality *)
92    | ISOLATE                    (* isolating a function *)        | BOXED | UNBOXED                         (* E: boxity tests *)
93    | DEREF                      (* dereferencing *)        | LENGTH                                  (* E: vector, string, array, ... length *)
94    | ASSIGN                     (* assignment *)        | OBJLENGTH                               (* E: length of arbitrary heap object *)
95    | UNBOXEDASSIGN              (* assignment to integer reference *)        | CAST                                    (* E: cast *)
96    | UPDATE                     (* array update (maybe boxed) *)        | GETHDLR | SETHDLR                       (* E: get/set exn handler pointer *)
97    | INLUPDATE                  (* inline array update (maybe boxed) *)        | GETVAR | SETVAR                         (* E: get/set var register *)
98    | BOXEDUPDATE                (* boxed array update *)        | MAKEREF                                 (* E: allocate a ref cell *)
99    | UNBOXEDUPDATE              (* update array of integers WITH tags *)        | CALLCC | CAPTURE | THROW                (* E: continuation operations *)
100          | ISOLATE                                 (* E: isolating a function *)
101    | GETTAG                     (* extract the tag portion of an *)        | DEREF                                   (* E: dereferencing *)
102                                 (* object's descriptor as an ML int *)        | ASSIGN                                  (* E: assignment *)
103    | MKSPECIAL                  (* make a special object *)        | UPDATE                                  (* E: array or reference update (maybe boxed) *)
104    | SETSPECIAL                 (* set the state of a special object *)        | INLUPDATE                               (* E: L: array update (maybe boxed) *)
105    | GETSPECIAL                 (* get the state of a special object *)        | UNBOXEDUPDATE                           (* E: update array of integers WITH tags
106    | USELVAR | DEFLVAR                                                   * removed by Zhong, put back by Matthias
107    | INLMIN of numkind          (* inline min *)                                                   * (see FLINT/trans/primopmap.sml) *)
108    | INLMAX of numkind          (* inline max *)        | GETTAG                                  (* E: extract the tag portion of an
109    | INLABS of numkind          (* inline abs *)                                                   * object's descriptor as an ML int *)
110    | INLNOT                     (* inline bool not operator *)        | MKSPECIAL                               (* E: make a special object *)
111    | INLCOMPOSE                 (* inline compose "op o"  operator *)        | SETSPECIAL                              (* E: set the state of a special object *)
112    | INLBEFORE                  (* inline "before" operator *)        | GETSPECIAL                              (* E: get the state of a special object *)
113    | INLIGNORE                  (* inline "ignore" function *)        | INLMIN of numkind                       (* E: L: min *)
114    | INL_ARRAY                  (* inline polymorphic array allocation *)        | INLMAX of numkind                       (* E: L: max *)
115    | INL_VECTOR                 (* inline polymorphic vector allocation *)        | INLABS of numkind                       (* E: L: abs *)
116    | INL_MONOARRAY of numkind   (* inline monomorphic array allocation *)        | INLNOT                                  (* E: L: bool not operator *)
117    | INL_MONOVECTOR of numkind  (* inline monomorphic vector allocation *)        | INLCOMPOSE                              (* E: L: compose "op o"  operator *)
118          | INLBEFORE                               (* E: L: "before" operator *)
119    | MKETAG                     (* make a new exception tag *)        | INLIGNORE                               (* E: L: "ignore" function *)
120    | WRAP                       (* box a value by wrapping it *)      (* primops to support new array representations *)
121    | UNWRAP                     (* unbox a value by unwrapping it *)        | NEW_ARRAY0                              (* E: allocate zero-length array header *)
122  (* Primops to support new array representations *)        | GET_SEQ_DATA                            (* E: get data pointer from arr/vec header *)
123    | NEW_ARRAY0                  (* allocate zero-length array header *)        | SUBSCRIPT_REC                           (* E: record subscript operation *)
124    | GET_SEQ_DATA                (* get data pointer from arr/vec header *)        | SUBSCRIPT_RAW64                         (* E: raw64 subscript operation *)
125    | SUBSCRIPT_REC               (* record subscript operation *)        | INLIDENTITY                             (* E: polymorphic identity *)
126    | SUBSCRIPT_RAW64             (* raw64 subscript operation *)        | CVT64                                   (* E: convert between external and
127  (* Primops to support new experimental C FFI. *)                                                   * internal representation of compiler
128    | RAW_LOAD of numkind         (* load from arbitrary memory location *)                                                   * simulated 64-bit scalars, e.g. w64p *)
129    | RAW_STORE of numkind        (* store to arbitrary memory location *)      (* Primops to support C FFI. *)
130      (* make a call to a C-function;        | RAW_LOAD of numkind                     (* E: load from arbitrary memory location *)
131          | RAW_STORE of numkind                    (* E: store to arbitrary memory location *)
132        (* E: make a call to a C-function;
133       * The primop carries C function prototype information and specifies       * The primop carries C function prototype information and specifies
134       * which of its (ML-) arguments are floating point. C prototype       * which of its (ML-) arguments are floating point. C prototype
135       * information is for use by the backend, ML information is for       * information is for use by the backend, ML information is for
136       * use by the CPS converter. *)       * use by the CPS converter. *)
137    | RAW_CCALL of { c_proto: CTypes.c_proto,        | RAW_CCALL of {
138                c_proto: PrimCTypes.c_proto,
139                     ml_args: ccall_type list,                     ml_args: ccall_type list,
140                     ml_res_opt: ccall_type option,                     ml_res_opt: ccall_type option,
141                     reentrant : bool                     reentrant : bool
# Line 239  Line 143 
143     (* Allocate uninitialized storage on the heap.     (* Allocate uninitialized storage on the heap.
144      * 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
145      * are not ML pointers.  The representation is      * are not ML pointers.  The representation is
146      * the same as RECORD with tag tag_raw32 (fblock = false),      * the same as RECORD with tag tag_raw or tag_raw64.
     * or tag_fblock (fblock = true).  
147      *)      *)
148    | RAW_RECORD of { fblock: bool }        | RAW_RECORD of { align64 : bool }  (* E: *)
149    
150    | INLIDENTITY                         (* polymorphic identity *)      (* non-environmental primops (not found in InLine) *)
151          | UNBOXEDASSIGN                   (* assignment to integer reference *)
152    
153          | WCAST                           (* ? *)
154          | MARKEXN                         (* mark an exception value with a string *)
155    
156    | CVT64                               (* convert between external and        | INL_ARRAY                       (* L: polymorphic array allocation *)
157                                           * internal representation of        | INL_VECTOR                      (* L: polymorphic vector allocation *)
158                                           * simulated 64-bit scalars *)        | INL_MONOARRAY of numkind        (* L: monomorphic array allocation *)
159          | INL_MONOVECTOR of numkind       (* L: monomorphic vector allocation *)
160    
161          | MKETAG                          (* make a new exception tag *)
162          | WRAP                            (* box a value by wrapping it *)
163          | UNWRAP                          (* unbox a value by unwrapping it *)
164    
165  and ccall_type =  and ccall_type =
166      CCI32 |                             (* passed as int32 *)      CCI32 |                             (* passed as int32 *)
# Line 256  Line 168 
168      CCR64 |                             (* passed as real64 *)      CCR64 |                             (* passed as real64 *)
169      CCML                                (* passed as Unsafe.Object.object *)      CCML                                (* passed as Unsafe.Object.object *)
170    
 val IADD : primop  (* default integer addition *)  
 val ISUB : primop  (* default integer subtraction *)  
 val IMUL : primop  
 val IDIV : primop  
 val INEG : primop  
   
 val FEQLd : primop  
 val IEQL : primop  
 val INEQ : primop  
 val IGT : primop  
 val ILT : primop  
 val ILE : primop  
 val IGE : primop  
   
 val prNumkind : numkind -> string  
 val prPrimop: primop -> string  
 val mayRaise : primop -> bool  
 (* This should return more than just a boolean.  
  * True means "can not be dead-code eliminated" *)  
 val effect : primop -> bool  
   
171  end (* signature PRIM_OP *)  end (* signature PRIM_OP *)
   

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

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