1(*
2    Copyright (c) 2012, 2016-20 David C.J. Matthews
3
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License version 2.1 as published by the Free Software Foundation.
7    
8    This library is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11    Lesser General Public License for more details.
12    
13    You should have received a copy of the GNU Lesser General Public
14    License along with this library; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16*)
17
18(* Intermediate code tree for the back end of the compiler. *)
19
20signature BackendIntermediateCodeSig =
21sig
22    type machineWord = Address.machineWord
23
24    datatype argumentType =
25        GeneralType
26    |   DoubleFloatType
27    |   SingleFloatType
28    
29    structure BuiltIns: BUILTINS
30    
31    datatype backendIC =
32        BICNewenv of bicCodeBinding list * backendIC (* Set of bindings with an expression. *)
33
34    |   BICConstnt of machineWord * Universal.universal list (* Load a constant *)
35
36    |   BICExtract of bicLoadForm (* Get a local variable, an argument or a closure value *)
37
38    |   BICField of {base: backendIC, offset: int }
39         (* Load a field from a tuple or record *)
40    
41    |   BICEval of (* Evaluate a function with an argument list. *)
42        {
43            function:  backendIC,
44            argList:   (backendIC * argumentType) list,
45            resultType: argumentType
46        }
47
48        (* Built-in functions. *)
49    |   BICNullary of {oper: BuiltIns.nullaryOps}
50    |   BICUnary of {oper: BuiltIns.unaryOps, arg1: backendIC}
51    |   BICBinary of {oper: BuiltIns.binaryOps, arg1: backendIC, arg2: backendIC}
52    
53    |   BICArbitrary of {oper: BuiltIns.arithmeticOperations, shortCond: backendIC, arg1: backendIC, arg2: backendIC, longCall: backendIC}
54
55    |   BICLambda of bicLambdaForm (* Lambda expressions. *)
56
57    |   BICCond of backendIC * backendIC * backendIC (* If-then-else expression *)
58
59    |   BICCase of (* Case expressions *)
60        {
61            cases   : backendIC option list, (* NONE means "jump to the default". *)
62            test    : backendIC,
63            default : backendIC,
64            isExhaustive: bool,
65            firstIndex: word
66        }
67    
68    |   BICBeginLoop of (* Start of tail-recursive inline function. *)
69        { loop: backendIC, arguments: (bicSimpleBinding * argumentType) list }
70
71    |   BICLoop of (backendIC * argumentType) list (* Jump back to start of tail-recursive function. *)
72
73    |   BICRaise of backendIC (* Raise an exception *)
74
75    |   BICHandle of (* Exception handler. *) { exp: backendIC, handler: backendIC, exPacketAddr: int }
76
77    |   BICTuple of backendIC list (* Tuple *)
78
79    |   BICSetContainer of (* Copy a tuple to a container. *)
80        {
81            container: backendIC,
82            tuple:     backendIC,
83            filter:    BoolVector.vector
84        }
85    
86    |   BICLoadContainer of {base: backendIC, offset: int } 
87
88    |   BICTagTest of { test: backendIC, tag: word, maxTag: word }
89
90    |   BICLoadOperation of { kind: loadStoreKind, address: bicAddress }
91    
92    |   BICStoreOperation of { kind: loadStoreKind, address: bicAddress, value: backendIC }
93    
94    |   BICBlockOperation of
95            { kind: blockOpKind, sourceLeft: bicAddress, destRight: bicAddress, length: backendIC }
96    
97    |   BICAllocateWordMemory of {numWords: backendIC, flags: backendIC, initial: backendIC}
98
99
100    and bicCodeBinding =
101        BICDeclar  of bicSimpleBinding (* Make a local declaration or push an argument *)
102    |   BICRecDecs of { addr: int, lambda: bicLambdaForm } list (* Set of mutually recursive declarations. *)
103    |   BICNullBinding of backendIC (* Just evaluate the expression and discard the result. *)
104    |   BICDecContainer of { addr: int, size: int } (* Create a container for a tuple on the stack. *)
105
106    and caseType =
107        CaseWord        (* Word or fixed-precision integer. *)
108    |   CaseTag of word
109
110    and bicLoadForm =
111        BICLoadLocal of int (* Local binding *)
112    |   BICLoadArgument of int (* Argument - 0 is first arg etc.*)
113    |   BICLoadClosure of int (* Closure - 0 is first closure item etc *)
114    |   BICLoadRecursive (* Recursive call *)
115
116    and loadStoreKind =
117        LoadStoreMLWord of {isImmutable: bool}     (* Load/Store an ML word in an ML word cell. *)
118    |   LoadStoreMLByte of {isImmutable: bool}     (* Load/Store a byte, tagging and untagging as appropriate, in an ML byte cell. *)
119    |   LoadStoreC8         (* Load/Store C values - The base address is a boxed SysWord.word value. *)
120    |   LoadStoreC16
121    |   LoadStoreC32
122    |   LoadStoreC64
123    |   LoadStoreCFloat
124    |   LoadStoreCDouble
125    |   LoadStoreUntaggedUnsigned
126
127    and blockOpKind =
128        BlockOpMove of {isByteMove: bool}
129    |   BlockOpEqualByte
130    |   BlockOpCompareByte
131
132    withtype bicSimpleBinding = 
133    { (* Declare a value or push an argument. *)
134        value:      backendIC,
135        addr:       int
136    }
137
138    and bicLambdaForm =
139    { (* Lambda expressions. *)
140        body          : backendIC,
141        name          : string,
142        closure       : bicLoadForm list,
143        argTypes      : argumentType list,
144        resultType    : argumentType,
145        localCount    : int,
146        heapClosure   : bool
147    }
148
149    and bicAddress =
150        (* Address form used in loads, store and block operations.  The base is an ML
151           address if this is to/from ML memory or a (boxed) SysWord.word if it is
152           to/from C memory.  The index is a value in units of the size of the item
153           being loaded/stored and the offset is always in bytes.
154           For ML memory accesses the index and offset are unsigned; for C values
155           they are signed. *)
156        {base: backendIC, index: backendIC option, offset: int}
157
158    type pretty
159    val pretty : backendIC -> pretty
160    
161    val loadStoreKindRepr: loadStoreKind -> string
162    and blockOpKindRepr: blockOpKind -> string
163
164    structure CodeTags:
165    sig
166        val tupleTag: Universal.universal list list Universal.tag
167        val mergeTupleProps:
168            Universal.universal list * Universal.universal list -> Universal.universal list
169    end
170
171    structure Sharing:
172    sig
173        type backendIC = backendIC
174        and  bicLoadForm = bicLoadForm
175        and  caseType = caseType
176        and  pretty = pretty
177        and  argumentType = argumentType
178        and  bicCodeBinding = bicCodeBinding
179        and  bicSimpleBinding = bicSimpleBinding
180        and  loadStoreKind = loadStoreKind
181        and  blockOpKind = blockOpKind
182        and  unaryOps = BuiltIns.unaryOps
183        and  binaryOps = BuiltIns.binaryOps
184        and  nullaryOps = BuiltIns.nullaryOps
185        and  testConditions = BuiltIns.testConditions
186        and  arithmeticOperations = BuiltIns.arithmeticOperations
187    end
188
189end;
190