fixed bug in prepareStackForAbsOpt (rtemgr.c).
[bugg-scheme-compiler.git] / src / sml / pseudo-gene.sml
blob3d145bfa707adc63838de3b43f7838ce14ce45e0
7 (* ******************************************************************* Pseudo *)
8 (* pseudocode abstraction for our architecture *)
9 structure Pseudo = struct
11 (* int to C string, handles negative numbers *)
12 fun Int_toCString i = if i>=0 then Int.toString i else "-" ^ (Int.toString (~i))
14 (* code and data labels are just strings: *)
15 type clabel = string (* code label is a goto target *)
16 type dlabel = string (* data label is a global variable of function *)
18 (* processor registers: three special purpose registers and some general ones *)
19 structure R = struct
21 datatype t = BP (* stack base *)
22 | SP (* stack pointer *)
23 | RET (* return value of every expression *)
24 | REG of int (* one of a few general purpose registers, numbered from 0 *)
26 fun toString BP = "fp"
27 | toString SP = "sp"
28 | toString RET = "r_res"
29 | toString (REG i) = "r["^(Int.toString i)^"]"
31 end
33 (* addresses (places): different addressing modes *)
34 structure A = struct
36 datatype t = Lbl of dlabel (* address of the data the label points to *)
37 | Reg of R.t (* a register *)
38 | Ind of t (* address referenced by place *)
39 | Ofs of (t*int) (* offset from address referenced by place *)
41 fun toString (Lbl l) = l (* global variables are pointers *)
42 | toString (Reg r) = R.toString r
43 | toString (Ind a) = "*(void**)" ^ (toString a)
44 | toString (Ofs (a,i)) = "*((void**)" ^ (toString a) ^ " + " ^ (Int_toCString i) ^ ")"
46 end
48 (* value is
49 - a place's value,
50 - a place's address,
51 - or a constant *)
52 structure V = struct
54 datatype t = Val of A.t (* address of the place *)
55 | Adr of A.t (* value in the place *)
56 | Cst of int (* constant *)
57 | ConstStr of string (* constant string *)
59 fun toString (Val a) = A.toString a
60 | toString (Adr a) = "(void*)&" ^ (A.toString a)
61 | toString (Cst i) = Int_toCString i
62 | toString (ConstStr s) = "\""^s^"\""
64 end
66 (* instructions: be very CISCy, allow all places to be targets *)
67 structure I = struct
69 datatype t = Move of A.t*V.t (* move value to place *)
70 | Push of V.t (* push value onto stack *)
71 | Pop of A.t (* pop from stack to place *)
72 | Label of clabel (* put a code label *)
73 | Goto of clabel (* goto code label *)
74 | Goif of V.t*clabel (* go if value if not true *)
75 | Call of clabel*clabel (* call function (first, return is second) *)
76 | Ret (* return from function *)
77 | Add of A.t*V.t (* add value to place *)
78 | Sub of A.t*V.t (* subtract value from place *)
79 | Mul of A.t*V.t (* multiply place by value *)
80 | Div of A.t*V.t (* divide place by value *)
81 | Ccall of string * V.t list (* call a C function, an analogue of a system call *)
82 | Cfunc of A.t * string * V.t list
83 | Comment of string (* comment *)
84 | Pass (* do nothing, for labeling *)
86 fun seq insts = String.concatWith "\n" (List.map indent insts) (* serialize a sequence of instructions *)
88 (* indent instructions by a tab *)
89 and indent (i as (Label _)) = toString i (* but outdent labels *)
90 | indent i = "\t" ^ (toString i)
92 (* convert an instruction to a piece of C code, the final newline is omitted and added in seq *)
93 and toString (Move (a,v)) = (A.toString a) ^ " = " ^ (V.toString v) ^ ";"
95 | toString (Push v) = seq [Move (A.Reg R.SP, V.Adr (A.Ofs (A.Reg R.SP, ~1))),
96 Move (A.Ind (A.Reg R.SP), v)]
97 | toString (Pop a) = seq [Move (a, V.Val (A.Ind (A.Reg R.SP))),
98 Move (A.Reg R.SP, V.Adr (A.Ofs (A.Reg R.SP, 1)))]
100 | toString (Push v) = toString (Ccall ("push",[v]))
101 | toString (Pop a) = toString (Ccall ("pop",[V.Adr a]))
102 | toString (Label l) = l ^ ":"
103 | toString (Goto l) = "goto " ^ l ^ ";"
104 | toString (Goif (v,l)) = "if (" ^ (V.toString v) ^ ") goto " ^ l ^ ";"
105 | toString (Add (a,v)) = (A.toString a) ^ " += " ^ (V.toString v) ^ ";"
106 | toString (Sub (a,v)) = (A.toString a) ^ " -= " ^ (V.toString v) ^ ";"
107 | toString (Mul (a,v)) = (A.toString a) ^ " *= " ^ (V.toString v) ^ ";"
108 | toString (Div (a,v)) = (A.toString a) ^ " /= " ^ (V.toString v) ^ ";"
109 | toString (Ccall (f,vs)) = f ^ "(" ^
110 (String.concatWith "," (List.map V.toString vs)) ^
111 ");"
112 | toString (Cfunc (a,f,vs)) = (A.toString a) ^ " = " ^ f ^ "(" ^
113 (String.concatWith "," (List.map V.toString vs)) ^
114 ");"
115 | toString (Comment s) = "// " ^ s
116 | toString Pass = ";"
119 (* boots the pseudo-processor: allocates registers and stack
120 fun boot (nregs, stacksize) =
121 "struct {int bp, sp, ret, reg[" ^ (Int.toString nregs) ^ "];\n" ^
122 " int stack[" ^ (Int.toString stacksize) ^ "]; } a;\n" ^
123 "\n" ^
124 "void boot() {\n" ^
125 " a.bp = (int)(a.stack+" ^ (Int.toString stacksize) ^ ");\n" ^
126 " a.sp = a.bp;\n" ^
127 "}\n"
130 fun mkInitArchitecture(nregs,stacksize) =
131 "initArchitecture("^Int.toString(nregs)^","^Int.toString(stacksize)^");\n";
135 (* ******************************************************************** Gene *)
137 structure Gene: sig
139 val reset: unit -> unit
140 val add: Expr -> unit
141 val emit: (int*int) -> string
143 end = struct (* code generation *)
145 open Reader
146 open TagParser
147 open Pseudo
150 structure Free: sig
151 val add: string -> string
152 val emit: unit -> string
153 val reset: unit -> unit
154 end = struct
156 val (freevars: (string*string) list ref) = ref []
158 (* add a new free variable, or use an existing one *)
159 fun add varname =
160 case List.find (fn vn=>(#1 vn)=varname) (!freevars)
161 of SOME (v,n) => n
162 | NONE =>
164 (* val name = new_name ("sv_" ^ varname) *)
165 val name = varname
167 freevars := (varname, name) :: (!freevars)
168 ; name
171 (* fun emit_free (v,n) = "void* " ^ n ^ " = (void* )&sc_undef;\n" *)
172 fun emit_free (v,n) = ""
174 (* all free variables initially equal (int)&sc_undef *)
175 fun emit () = String.concat (map emit_free (List.rev (!freevars)))
177 fun reset () = freevars := []
179 end (* struct *)
184 val initial_code = []
185 val (code: I.t list ref) = ref initial_code
187 local
188 (* add single instr to the code *)
189 fun % i = code := i :: (!code)
191 (* add expression's code to the code list *)
192 fun add (Const sexpr) = (* value is address of constant *)
193 let val cname = Const.add(sexpr)
194 in % (I.Move ((A.Reg R.RET), V.Adr (A.Lbl cname))) end
195 | add (Var _) = raise Match (* can't be here, must have been resolved earlier *)
196 | add (VarFree name) = (* value is variable *)
197 let val vname = Free.add(name)
198 in (
199 (* % (I.Move ((A.Reg R.RET), V.Val (A.Lbl vname))) *)
200 % (I.Cfunc ((A.Reg R.RET), "probeSymbolDefined", [V.ConstStr vname, V.Val (A.Lbl "topLevel")]))
201 (* add: check if defined or not *)
202 ;% (I.Move ((A.Reg R.RET), V.Val (A.Lbl "((SymbolEntry*)r_res)->sob")))
205 | add (If (i, t, e)) =
206 let val then_label = new_name "THEN"
207 val else_label = new_name "ELSE"
208 val fi_label = new_name "ENDIF"
210 add i
211 ; % (I.Sub ((A.Reg R.RET), V.Adr (A.Lbl (Const.add (Bool false))))) (* difference between value and #f *)
212 ; % (I.Goif (V.Val (A.Reg R.RET), then_label)) (* if different, goto the true branch *)
213 ; % (I.Goto else_label) (* otherwise, goto the false branch *)
214 ; % (I.Label then_label) (* the true branch *)
215 ; add t
216 ; % (I.Goto fi_label)
217 ; % (I.Label else_label) (* the false branch *)
218 ; add e
219 ; % (I.Label fi_label)
221 | add _ = ()
222 end (* local *)
224 (* Adds the free variables for the built-in procedures. The variables
225 themselves are initialized in initBuiltins() *)
226 fun addBuiltinsFreeVars() =
227 (map (fn(n)=>Free.add n)
228 ["apply", "binary-add", "binary-div", "binary<?",
229 "binary-mul", "binary=?", "binary-sub",
230 "boolean?", "car", "cdr", "char?", "char->integer",
231 "cons", "eq?", "integer->char",
232 "make-string", "make-vector", "null?", "number?",
233 "pair?", "procedure?", "remainder", "set-car!",
234 "set-cdr!", "string-length", "string-ref", "string?",
235 "string-set!", "vector-length",
236 "vector-ref", "vector?", "vector-set!", "zero?"]
237 ;());
239 fun mkInitBuiltins() = "initBuiltins();";
241 fun emit (nregs, stacksize) =
242 (addBuiltinsFreeVars();
243 "\n/* COMP091 Scheme->C Compiler Generated Code */\n\n" ^
244 "#include \"scheme.h\"\n" ^
245 "#include \"assertions.h\"\n" ^
246 "#include \"arch.h\"\n" ^
247 "#include \"builtins.h\"\n" ^
248 "extern SymbolNode *topLevel;\n"^
249 "\n/* Constants */\n" ^
250 (Const.emit ()) ^
251 "\n/* Free variables */\n" ^
252 (Free.emit ()) ^
253 "\n/* Code */\n" ^
254 "void schemeCompiledFunction() {\n" ^
255 "\t"^mkInitArchitecture(nregs,stacksize)^"\n" ^
256 "\t"^mkInitBuiltins()^"\n" ^
257 "\n" ^
258 (I.seq (List.rev (!code))) ^
259 "\n}\n"
262 fun reset () =
263 ( names := initial_names
264 ; Const.reset ()
265 ; Free.reset ()
266 ; code := initial_code )
268 end (* struct *)