]> Joshua Wise's Git repositories - snipe.git/blob - trans/trans.sml
Add cast syntax.
[snipe.git] / trans / trans.sml
1 (* L3 Compiler
2  * AST -> IR Translator
3  * Author: Kaustuv Chaudhuri <kaustuv+@cs.cmu.edu>
4  * Modified by: Alex Vaynberg <alv@andrew.cmu.edu>
5  * Modified: Frank Pfenning <fp@cs.cmu.edu>
6  * Modified: Chris Lu <czl@andrew.cmu.edu>
7  * Modified: Joshua Wise <jwise@andrew.cmu.edu>
8  *)
9
10 signature TRANS =
11 sig
12   (* translate abstract syntax tree to IR tree *)
13   val translate : Ast.program -> Tree.program
14 end
15
16 structure Trans :> TRANS = 
17 struct
18
19   structure A = Ast
20   structure T = Tree
21   
22   fun trans_oper A.PLUS = T.ADD
23     | trans_oper A.MINUS = T.SUB
24     | trans_oper A.TIMES = T.MUL
25     | trans_oper A.DIVIDEDBY = T.DIV
26     | trans_oper A.MODULO = T.MOD
27     | trans_oper A.LSH = T.LSH
28     | trans_oper A.RSH = T.RSH
29     | trans_oper A.LOGOR = T.LOGOR
30     | trans_oper A.LOGAND = T.LOGAND
31     | trans_oper A.BITOR = T.BITOR
32     | trans_oper A.BITXOR = T.BITXOR
33     | trans_oper A.BITAND = T.BITAND
34     | trans_oper A.NEQ = T.NEQ
35     | trans_oper A.EQ = T.EQ
36     | trans_oper A.LT = T.LT
37     | trans_oper A.LE = T.LE
38     | trans_oper A.GE = T.GE
39     | trans_oper A.GT = T.GT
40     | trans_oper _ = raise ErrorMsg.InternalError "expected AST binop, got AST unop"
41
42   fun translate (defs, funcs) =
43     let
44       val funclist = Symbol.elemsi funcs
45       val _ = Type.alignment_reset()
46       val _ = Type.sizeof_reset()
47       fun sizeof a = Type.sizeof defs a
48       fun alignment a = Type.alignment defs a
49       fun align t curpos = Type.align defs t curpos
50
51       fun offset_s id (Type.Typedef(id')) =
52         let
53           val shit = Symbol.look' defs id'
54           fun eat (Type.Struct(l)) = l
55             | eat (Type.MarkedTypedef(a)) = eat (Mark.data a)
56           fun offset_s' ((id1,t)::l') curofs =
57             let
58               val a = align t curofs
59             in
60               if Symbol.compare(id,id1) = EQUAL
61                 then a
62               else offset_s' l' (a + sizeof t)
63             end
64             | offset_s' nil _ = raise ErrorMsg.InternalError "looking for offset of something that isn't in the structure"
65         in
66           offset_s' (eat shit) 0
67         end
68         | offset_s _ _ = raise ErrorMsg.InternalError "cannot find offset into non-typedef"
69       
70       fun type_s id (Type.Typedef id') =
71         let
72           val td = 
73             case Type.defdata (Symbol.look' defs id')
74             of Type.Struct d => d
75              | _ => raise ErrorMsg.InternalError "data didn't return struct"
76           fun type_s' ((id',t)::l) =
77             if (Symbol.compare (id, id') = EQUAL)
78             then t
79             else type_s' l
80             | type_s' nil = raise ErrorMsg.InternalError "struct member not found in type_s"
81         in
82           type_s' td
83         end
84         | type_s id _ = raise ErrorMsg.InternalError "cannot find internal type non-typedef"
85       
86       fun deref (Type.Pointer i) = i
87         | deref (Type.Array i) = i
88         | deref _ = raise ErrorMsg.InternalError "cannot deref non-pointer"
89
90       fun trans_unop A.NEGATIVE = T.NEG
91         | trans_unop A.BITNOT = T.BITNOT
92         | trans_unop A.BANG = T.BANG
93         | trans_unop _ = raise ErrorMsg.InternalError "expected AST unop, got AST binop"
94       
95       fun typeof' vartypes exp = TypeChecker.typeof (defs, funcs) vartypes NONE exp
96
97       fun trans_exp env vartypes (A.Var(id)) =
98         (* after type-checking, id must be declared; do not guard lookup *)
99             T.TEMP (Symbol.look' env id)
100         | trans_exp env vartypes (A.Cast (ty, e)) = trans_exp env vartypes e (* lurrr *)
101         | trans_exp env vartypes (A.ConstExp c) = T.CONST(c)
102         | trans_exp env vartypes (A.StringExp s) = T.STRING(Stringref.new s)
103         | trans_exp env vartypes (A.OpExp(oper, [e1, e2])) =
104             T.BINOP(trans_oper oper, trans_exp env vartypes e1, trans_exp env vartypes e2)
105         | trans_exp env vartypes (A.OpExp(oper, [e])) =
106             T.UNOP(trans_unop oper, trans_exp env vartypes e)
107         | trans_exp env vartypes (A.OpExp(oper, _)) =
108             raise ErrorMsg.InternalError "expected one or two operands, got it in the oven"
109         | trans_exp env vartypes (A.Marked(marked_exp)) =
110             trans_exp env vartypes (Mark.data marked_exp)
111         | trans_exp env vartypes (A.FuncCall(func, stms)) =
112             T.CALL(func,
113               List.map
114                 (fn exp => (trans_exp env vartypes exp))
115                 stms)
116         | trans_exp env vartypes (A.Member (exp, id)) =
117             let
118               val apk = T.BINOP (T.ADD, trans_exp env vartypes exp, T.CONST (Word32.fromInt (offset_s id (typeof' vartypes exp))))
119               val tipo = type_s id (typeof' vartypes exp)
120             in
121               if Type.issmall tipo
122               then T.MEMORY(apk)
123               else apk
124             end
125         | trans_exp env vartypes (A.DerefMember (exp, id)) =
126             trans_exp env vartypes (A.Member (A.Dereference (exp), id))
127         | trans_exp env vartypes (A.Dereference(exp)) =
128             if (Type.issmall (deref (typeof' vartypes exp)))
129             then T.MEMORY(trans_exp env vartypes exp)
130             else trans_exp env vartypes exp
131         | trans_exp env vartypes (A.ArrIndex(exp1, exp2)) =
132             let
133               val asubk = T.BINOP(T.ADD, trans_exp env vartypes exp1, 
134                                   if sizeof (deref (typeof' vartypes exp1)) = 1
135                                   then trans_exp env vartypes exp2
136                                   else T.BINOP(T.MUL, trans_exp env vartypes exp2,
137                                                T.CONST(Word32.fromInt(sizeof (deref (typeof' vartypes exp1))))
138                                               )
139                                  )
140               val tipo = deref (typeof' vartypes exp1)
141               val d =
142                 if not (Flag.isset Flags.safe)
143                 then asubk
144                 else T.COND (T.BINOP
145                               (T.BE,
146                                T.MEMORY (T.BINOP (
147                                  T.SUB,
148                                  trans_exp env vartypes exp1, 
149                                  T.CONST 0w8)),
150                                trans_exp env vartypes exp2),
151                              T.NULLPTR,
152                              asubk)
153             in
154               if Type.issmall tipo
155               then T.MEMORY(d)
156               else d
157             end
158         | trans_exp env vartypes (A.New(tipo)) =
159             let
160               val t1 = T.TEMP (Temp.new "result")
161             in
162               T.STMVAR (
163                 [T.MOVE (t1, T.ALLOC (T.CONST (Word32.fromInt(sizeof tipo)))),
164                  T.EFFECT (T.MEMORY (t1))],
165                 t1)
166             end
167         | trans_exp env vartypes (A.NewArr(tipo, exp)) =
168             let
169               val size = if (sizeof tipo) = 1
170                          then trans_exp env vartypes exp
171                          else T.BINOP(T.MUL, trans_exp env vartypes exp, T.CONST(Word32.fromInt(sizeof tipo)))
172               val t1 = T.TEMP (Temp.new "allocated address")
173               val ts = T.TEMP (Temp.new "size")
174             in
175               if not (Flag.isset Flags.safe)
176               then T.STMVAR ([T.MOVE (t1, T.ALLOC size),
177                               T.EFFECT (T.COND (T.BINOP (T.EQ, trans_exp env vartypes exp, T.CONST 0w0), T.CONST 0w0, T.MEMORY (t1)))],
178                              t1)
179               else T.COND (T.BINOP(T.EQ, size, T.CONST 0w0),
180                            T.NULLPTR,
181                            T.STMVAR (
182                              [T.MOVE(t1,
183                                 T.COND(
184                                   T.BINOP(T.LT, size, T.CONST 0w0),
185                                   T.NULLPTR,
186                                   T.ALLOC (T.BINOP (T.ADD, size, T.CONST 0w8)))
187                                 ),
188                               T.MOVE(T.MEMORY (t1), trans_exp env vartypes exp)],
189                              T.BINOP(T.ADD, t1, T.CONST 0w8)))
190             end
191         | trans_exp env vartypes (A.Null) = T.NULLPTR
192         | trans_exp env vartypes (A.Conditional(c,e1,e2)) = T.COND(trans_exp env vartypes c, trans_exp env vartypes e1, trans_exp env vartypes e2)
193
194         (* anything else should be impossible *)
195
196       (* trans_stms : Temp.temp Symbol.table -> (Label.label * Label.label) option -> A.stm list -> Tree.stm list
197        * translates a statement to the corresponding IR
198        * we pass around the environment and the current loop context, if any
199        * (usually called ls, which contains a continue label and a break label)
200        *)
201       fun trans_stms vars vartypes ls (A.Assign(e1,e2)::stms) = T.MOVE(trans_exp vars vartypes e1, trans_exp vars vartypes e2)::(trans_stms vars vartypes ls stms)
202         | trans_stms vars vartypes ls (A.AsnOp(oop,e1,e2)::stms) =
203           let
204             val te1 = trans_exp vars vartypes e1
205             val te2 = trans_exp vars vartypes e2
206             val t1 = T.TEMP (Temp.new "memory deref cache")
207           in
208             case te1
209             of T.MEMORY(m) => T.MOVE(t1, m) :: T.MOVE (T.MEMORY(t1), T.BINOP(trans_oper oop, T.MEMORY(t1), te2)) :: (trans_stms vars vartypes ls stms)
210              | _ => T.MOVE(te1, T.BINOP(trans_oper oop, te1, te2)) :: (trans_stms vars vartypes ls stms)
211           end
212         | trans_stms vars vartypes ls (A.Return e::stms) =
213           let
214             val remainder = trans_stms vars vartypes ls stms
215           in 
216             T.RETURN (trans_exp vars vartypes e)
217             :: remainder
218           end
219         | trans_stms vars vartypes ls (A.If(e, s, NONE)::stms) =
220           let
221             val l = Label.new ()
222             val strans = trans_stms vars vartypes ls s
223             val remainder = trans_stms vars vartypes ls stms
224           in
225             (T.JUMPIFN(trans_exp vars vartypes e, l)
226             :: strans
227             @ [T.LABEL (l)]
228             @ remainder)
229           end
230         | trans_stms vars vartypes ls (A.If(e, s, SOME s2)::stms) =
231           let
232             val l = Label.new ()
233             val l2 = Label.new ()
234             val s1trans = trans_stms vars vartypes ls s
235             val s2trans = trans_stms vars vartypes ls s2
236             val remainder = trans_stms vars vartypes ls stms
237           in
238             (T.JUMPIFN(trans_exp vars vartypes e, l)
239             :: s1trans
240             @ [T.JUMP (l2), T.LABEL (l)]
241             @ s2trans
242             @ [T.LABEL (l2)]
243             @ remainder)
244           end
245         | trans_stms vars vartypes ls (A.For(s1, e, s2, s)::stms) = 
246           let
247             val head = Label.new ()
248             val tail = Label.new ()
249             val loop = Label.new ()
250             val stm1 = if isSome s1 then trans_stms vars vartypes NONE [valOf s1] else nil
251             val strans = trans_stms vars vartypes (SOME(loop,tail)) s
252             val stm2 = if isSome s2 then trans_stms vars vartypes NONE [valOf s2] else nil
253             val remainder = trans_stms vars vartypes ls stms
254           in
255             (stm1
256             @ [T.LABEL head, T.JUMPIFN(trans_exp vars vartypes e, tail)]
257             @ strans
258             @ [T.LABEL loop]
259             @ stm2
260             @ [T.JUMP head, T.LABEL tail]
261             @ remainder)
262           end
263         | trans_stms vars vartypes ls (A.While(e, s)::stms) =
264           let
265             val head = Label.new ()
266             val tail = Label.new ()
267             val strans = trans_stms vars vartypes (SOME(head,tail)) s
268             val remainder = trans_stms vars vartypes ls stms
269           in
270             (T.LABEL head
271             :: T.JUMPIFN(trans_exp vars vartypes e, tail)
272             :: strans
273             @ [T.JUMP head, T.LABEL tail]
274             @ remainder)
275           end
276         | trans_stms vars vartypes ls (A.Effect(e)::stms) = (T.EFFECT (trans_exp vars vartypes e)) :: (trans_stms vars vartypes ls stms)
277         | trans_stms vars vartypes (SOME(b,e)) (A.Break::stms) =
278           let
279             val remainder = trans_stms vars vartypes (SOME(b,e)) stms
280           in
281             ((T.JUMP e) :: remainder)
282           end
283         | trans_stms vars vartypes  NONE       (A.Break::_) = raise ErrorMsg.InternalError "Break from invalid location... should have been caught in typechecker"
284         | trans_stms vars vartypes (SOME(b,e)) (A.Continue::stms) =
285           let
286             val remainder = trans_stms vars vartypes (SOME(b,e)) stms
287           in
288             ((T.JUMP b) :: remainder)
289           end
290         | trans_stms vars vartypes  NONE       (A.Continue::_) = raise ErrorMsg.InternalError "Continue from invalid location... should have been caught in typechecker"
291         | trans_stms vars vartypes ls (A.Nop::stms) = trans_stms vars vartypes ls stms
292         | trans_stms vars vartypes ls (A.MarkedStm m :: stms) = trans_stms vars vartypes ls ((Mark.data m) :: stms)
293         | trans_stms vars vartypes _ nil = nil
294
295       fun trans_funcs ((id, A.Extern(_, _))::l) = trans_funcs l
296         | trans_funcs ((id, A.MarkedFunction a)::l) = trans_funcs ((id, Mark.data a)::l)
297         | trans_funcs ((id, A.Function(t, args, vars, body))::l) =
298             let
299               val allvars = foldr
300                               (fn ((name, t),b) =>
301                                 Symbol.bind b (name, Temp.new (Symbol.name(name))))
302                               Symbol.empty
303                               (args @ vars)
304               val vartypes = foldr (fn ((i, t), b) => Symbol.bind b (i, t)) Symbol.empty (args @ vars)
305               val b = trans_stms allvars vartypes NONE body
306               val (argn,_) = ListPair.unzip args
307               val numberedargs = ListPair.zip (List.tabulate (length argn, fn x => x), argn)
308               val argmv = map
309                 (fn (n, argname) => T.MOVE(T.TEMP (Symbol.look' allvars argname), T.ARG (n)))
310                 numberedargs
311             in
312               (T.FUNCTION(id, argmv @ b)) :: (trans_funcs l)
313             end
314         | trans_funcs nil = nil
315
316     in
317       trans_funcs funclist
318     end
319 end
This page took 0.042681 seconds and 4 git commands to generate.