26f5c0cea0843271a55987a651e5805b76a9825a
[nit.git] / src / analysis / icode_dump.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2009 Jean Privat <jean@pryen.org>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Output the intermediate code unded a textual representation
18 package icode_dump
19
20 import icode
21 import allocate_iregister_slots
22
23 redef class IRoutine
24 # Output the intermediate code representation of the iroutine
25 fun dump(icd: ICodeDumper)
26 do
27 if not params.is_empty then
28 var a = new Array[String]
29 for p in params do
30 a.add(icd.register(p))
31 end
32 icd.write "Parameters: {a.join(", ")}"
33 end
34 var r = result
35 if r != null then
36 icd.write "Result: {icd.register(r)}"
37 end
38 if std_slots_nb > 0 then
39 icd.write "StdSlots: {std_slots_nb}"
40 end
41 if tag_slots_nb > 0 then
42 icd.write "TagSlots: {tag_slots_nb}"
43 end
44 var closdecls = closure_decls
45 if closdecls != null then
46 for c in closdecls do
47 c.dump(icd)
48 end
49 end
50 body.dump(icd)
51 end
52 end
53
54 redef class IClosureDecl
55 # Output the intermediate code representation of the iclosuredecl
56 fun dump(icd: ICodeDumper)
57 do
58 icd.write "Closure: {icd.closdecl(self)}"
59 if default != null then
60 icd.indent
61 default.dump(icd)
62 icd.unindent
63 end
64 end
65 end
66
67 class ICodeDumper
68 var _ids: HashMap[Object, String] = new HashMap[Object, String]
69 var _last_value: Int = 0
70
71 # Return the name of e
72 # If e is unknown, a new name is gived
73 fun register(e: IRegister): String
74 do
75 if _ids.has_key(e) then
76 return _ids[e]
77 else
78 var i = e.slot_index
79 if i == null then
80 _last_value += 1
81 var s = "r{_last_value}"
82 _ids[e] = s
83 return s
84 else
85 _last_value += 1
86 var s: String
87 if e.in_tag_slots then
88 s = "BREG{i}(r{_last_value})"
89 else if e.is_local then
90 s = "LREG{i}(r{_last_value})"
91 else
92 s = "REG{i}(r{_last_value})"
93 end
94 _ids[e] = s
95 return s
96 end
97 end
98 end
99
100 # Returns the names of es (separated with comma)
101 fun register_all(es: nullable Collection[IRegister]): String
102 do
103 if es == null then return ""
104 var a = new Array[String]
105 for e in es do
106 a.add(register(e))
107 end
108 return a.join(", ")
109 end
110
111 var _last_clos: Int = 0
112
113 # Return the name of e
114 # If e is unknown, a new name is gived
115 fun closdecl(e: IClosureDecl): String
116 do
117 if _ids.has_key(e) then
118 return _ids[e]
119 else
120 _last_clos += 1
121 var s = "clos{_last_clos}"
122 _ids[e] = s
123 return s
124 end
125 end
126
127 var _last_label: Int = 0
128 # Return the name of e
129 # If e is unknown, a new name is gived
130 fun lab(e: IEscapeMark): String
131 do
132 if _ids.has_key(e) then
133 return _ids[e]
134 else
135 _last_label += 1
136 var s = "[l{_last_label}]"
137 _ids[e] = s
138 return s
139 end
140 end
141
142 var _last_line: Int = 0
143 # Return the line index of e
144 fun line(e: ICode): String
145 do
146 if _ids.has_key(e) then
147 return _ids[e]
148 else
149 _last_line += 1
150 var s = "{_last_line}"
151 _ids[e] = s
152 return s
153 end
154 end
155
156 # Is the label e known? (because we goto to it)
157 fun has_lab(e: IEscapeMark): Bool
158 do
159 return _ids.has_key(e)
160 end
161
162 # Output something
163 fun write(s: String)
164 do
165 for i in [0.._indent_level[ do
166 printn " "
167 end
168 print s
169 end
170
171 var _indent_level: Int = 0
172
173 # Indent the next writes
174 fun indent do _indent_level += 1
175
176 # Outdent the next writes
177 fun unindent do _indent_level -= 1
178 end
179
180 redef class ICode
181 # Output the intermediate code representation
182 fun dump(icd: ICodeDumper)
183 do
184 var result = result
185 var s = ""
186 var l = location
187 if l != null then
188 s = " ... {l}"
189 end
190 if result == null then
191 icd.write "{icd.line(self)}: {dump_intern(icd)}{s}"
192 else
193 icd.write "{icd.line(self)}: {icd.register(result)} := {dump_intern(icd)}{s}"
194 end
195 end
196
197 # Output the intermediate code representation (inner method)
198 fun dump_intern(icd: ICodeDumper): String do return "???"
199 end
200
201 redef class ICodeN
202 redef fun dump(icd: ICodeDumper)
203 do
204 super
205 var closure_defs = closure_defs
206 if closure_defs != null then
207 for clos in closure_defs do
208 if clos == null then
209 icd.write "CLOSURE = NULL"
210 else
211 icd.write "CLOSURE"
212 icd.indent
213 clos.dump(icd)
214 icd.unindent
215 end
216 end
217 end
218 end
219 end
220
221 redef class ISeq
222 redef fun dump(icd)
223 do
224 for ic in icodes do
225 ic.dump(icd)
226 end
227 var mark = iescape_mark
228 if mark != null and icd.has_lab(mark) then icd.write("{icd.lab(mark)}:")
229 end
230 end
231
232 redef class IIf
233 redef fun dump(icd)
234 do
235 icd.write "IF({icd.register(expr)}) \{"
236 icd.indent
237 then_seq.dump(icd)
238 icd.unindent
239 icd.write "} ELSE \{"
240 icd.indent
241 else_seq.dump(icd)
242 icd.unindent
243 icd.write "}"
244 end
245 end
246
247 redef class ILoop
248 redef fun dump(icd)
249 do
250 icd.write "LOOP \{"
251 icd.indent
252 for ic in icodes do
253 ic.dump(icd)
254 end
255 icd.unindent
256 icd.write "}"
257 var mark = iescape_mark
258 if mark != null and icd.has_lab(mark) then icd.write("{icd.lab(mark)}:")
259 end
260 end
261
262 redef class IEscape
263 redef fun dump_intern(icd)
264 do
265 return "ESCAPE {icd.lab(iescape_mark)}"
266 end
267 end
268
269 redef class IAbort
270 redef fun dump_intern(icd)
271 do
272 return "ABORT (\"{texts.join("\", \"")}\")"
273 end
274 end
275
276 redef class ICall
277 redef fun dump_intern(icd)
278 do
279 return "CALL {property.full_name}({icd.register_all(exprs)})"
280 end
281 end
282
283 redef class INew
284 redef fun dump_intern(icd)
285 do
286 return "NEW {stype}.{property.full_name}({icd.register_all(exprs)})"
287 end
288 end
289
290 redef class ISuper
291 redef fun dump_intern(icd)
292 do
293 return "SUPER {property.full_name}({icd.register_all(exprs)})"
294 end
295 end
296
297 redef class IStaticCall
298 redef fun dump_intern(icd)
299 do
300 return "STATIC_CALL {property.full_name}({icd.register_all(exprs)})"
301 end
302 end
303
304 redef class IAllocateInstance
305 redef fun dump_intern(icd)
306 do
307 return "ALLOCATE NEW_{stype}"
308 end
309 end
310
311 redef class ICheckInstance
312 redef fun dump_intern(icd)
313 do
314 return "CHECK_INSTANCE CHECKNEW_{stype}({icd.register(expr)})"
315 end
316 end
317
318 redef class IInitAttributes
319 redef fun dump_intern(icd)
320 do
321 return "INIT_ATTRIBUTES INIT_ATTRIBUTES_{stype}({icd.register(expr)})"
322 end
323 end
324
325 redef class IClosCall
326 redef fun dump_intern(icd)
327 do
328 return "CLOS_CALL {icd.closdecl(closure_decl)}({icd.register_all(exprs)})"
329 end
330 end
331
332 redef class IAttrRead
333 redef fun dump_intern(icd)
334 do
335 return "ATTR_READ {property.full_name}({icd.register(expr)})"
336 end
337 end
338
339 redef class IAttrWrite
340 redef fun dump_intern(icd)
341 do
342 return "ATTR_WRITE {property.full_name}({icd.register(expr1)}) := {icd.register(expr2)}"
343 end
344 end
345
346 redef class IAttrIsset
347 redef fun dump_intern(icd)
348 do
349 return "ATTR_ISSET {property.full_name}({icd.register(expr)})"
350 end
351 end
352
353 redef class ITypeCheck
354 redef fun dump_intern(icd)
355 do
356 return "CHECKTYPE {icd.register(expr)} isa {stype}"
357 end
358 end
359
360 redef class INative
361 redef fun dump_intern(icd)
362 do
363 if exprs.is_empty then
364 return "NATIVE \"{code}\""
365 else
366 return "NATIVE \"{code}\"({icd.register_all(exprs)})"
367 end
368 end
369 end
370
371 redef class IMove
372 redef fun dump_intern(icd)
373 do
374 return "{icd.register(expr)}"
375 end
376 end
377
378 redef class IIs
379 redef fun dump_intern(icd)
380 do
381 return "{icd.register(expr1)} is {icd.register(expr2)}"
382 end
383 end
384
385 redef class INot
386 redef fun dump_intern(icd)
387 do
388 return "NOT {icd.register(expr)}"
389 end
390 end
391
392 redef class IOnce
393 redef fun dump(icd)
394 do
395 icd.write "{icd.register(result.as(not null))} := ONCE \{"
396 icd.indent
397 body.dump(icd)
398 icd.unindent
399 icd.write "}"
400 end
401 end
402
403 redef class IHasClos
404 redef fun dump_intern(icd)
405 do
406 return "HASCLOS {icd.closdecl(closure_decl)}"
407 end
408 end