f72f74c5e25b5c93f6b426bb09e51e3014b1df5e
[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 readable var _dump_locations: Bool
69 readable var _dump_line_numbers: Bool
70 var _ids: HashMap[Object, String] = new HashMap[Object, String]
71 var _last_value: Int = 0
72
73 init(dump_locations: Bool, dump_line_numbers: Bool) do
74 _dump_locations = dump_locations
75 _dump_line_numbers = dump_line_numbers
76 end
77
78 # Return the name of e
79 # If e is unknown, a new name is gived
80 fun register(e: IRegister): String
81 do
82 if _ids.has_key(e) then
83 return _ids[e]
84 else
85 var i = e.slot_index
86 if i == null then
87 _last_value += 1
88 var s = "r{_last_value}"
89 _ids[e] = s
90 return s
91 else
92 _last_value += 1
93 var s: String
94 if e.in_tag_slots then
95 s = "BREG{i}(r{_last_value})"
96 else if e.is_local then
97 s = "LREG{i}(r{_last_value})"
98 else
99 s = "REG{i}(r{_last_value})"
100 end
101 _ids[e] = s
102 return s
103 end
104 end
105 end
106
107 # Returns the names of es (separated with comma)
108 fun register_all(es: nullable Collection[IRegister]): String
109 do
110 if es == null then return ""
111 var a = new Array[String]
112 for e in es do
113 a.add(register(e))
114 end
115 return a.join(", ")
116 end
117
118 var _last_clos: Int = 0
119
120 # Return the name of e
121 # If e is unknown, a new name is gived
122 fun closdecl(e: IClosureDecl): String
123 do
124 if _ids.has_key(e) then
125 return _ids[e]
126 else
127 _last_clos += 1
128 var s = "clos{_last_clos}"
129 _ids[e] = s
130 return s
131 end
132 end
133
134 var _last_label: Int = 0
135 # Return the name of e
136 # If e is unknown, a new name is gived
137 fun lab(e: IEscapeMark): String
138 do
139 if _ids.has_key(e) then
140 return _ids[e]
141 else
142 _last_label += 1
143 var s = "[l{_last_label}]"
144 _ids[e] = s
145 return s
146 end
147 end
148
149 var _last_line: Int = 0
150 # Return the line index of e
151 fun line(e: ICode): String
152 do
153 if _ids.has_key(e) then
154 return _ids[e]
155 else
156 _last_line += 1
157 var s = "{_last_line}"
158 _ids[e] = s
159 return s
160 end
161 end
162
163 # Is the label e known? (because we goto to it)
164 fun has_lab(e: IEscapeMark): Bool
165 do
166 return _ids.has_key(e)
167 end
168
169 # Output something
170 fun write(s: String)
171 do
172 for i in [0.._indent_level[ do
173 printn " "
174 end
175 print s
176 end
177
178 readable var _indent_level: Int = 0
179
180 # Indent the next writes
181 fun indent do _indent_level += 1
182
183 # Outdent the next writes
184 fun unindent do _indent_level -= 1
185 end
186
187 redef class ICode
188 # Output the intermediate code representation
189 fun dump(icd: ICodeDumper)
190 do
191 var result = result
192 var s_loc = ""
193 var s_line = ""
194 var loc = location
195 if loc != null and icd.dump_locations then
196 s_loc = " ... {loc}"
197 end
198 if icd.dump_line_numbers then
199 s_line = "{icd.line(self)}: "
200 end
201 if result == null then
202 icd.write "{s_line}{dump_intern(icd)}{s_loc}"
203 else
204 icd.write "{s_line}{icd.register(result)} := {dump_intern(icd)}{s_loc}"
205 end
206 end
207
208 # Output the intermediate code representation (inner method)
209 fun dump_intern(icd: ICodeDumper): String do return "???"
210 end
211
212 redef class ICodeN
213 redef fun dump(icd: ICodeDumper)
214 do
215 super
216 var closure_defs = closure_defs
217 if closure_defs != null then
218 for clos in closure_defs do
219 if clos == null then
220 icd.write "CLOSURE = NULL"
221 else
222 icd.write "CLOSURE"
223 icd.indent
224 clos.dump(icd)
225 icd.unindent
226 end
227 end
228 end
229 end
230 end
231
232 redef class ISeq
233 redef fun dump(icd)
234 do
235 for ic in icodes do
236 ic.dump(icd)
237 end
238 var mark = iescape_mark
239 if mark != null and icd.has_lab(mark) then icd.write("{icd.lab(mark)}:")
240 end
241 end
242
243 redef class IIf
244 redef fun dump(icd)
245 do
246 icd.write "IF({icd.register(expr)}) \{"
247 icd.indent
248 then_seq.dump(icd)
249 icd.unindent
250 icd.write "} ELSE \{"
251 icd.indent
252 else_seq.dump(icd)
253 icd.unindent
254 icd.write "}"
255 end
256 end
257
258 redef class ILoop
259 redef fun dump(icd)
260 do
261 icd.write "LOOP \{"
262 icd.indent
263 for ic in icodes do
264 ic.dump(icd)
265 end
266 icd.unindent
267 icd.write "}"
268 var mark = iescape_mark
269 if mark != null and icd.has_lab(mark) then icd.write("{icd.lab(mark)}:")
270 end
271 end
272
273 redef class IEscape
274 redef fun dump_intern(icd)
275 do
276 return "ESCAPE {icd.lab(iescape_mark)}"
277 end
278 end
279
280 redef class IAbort
281 redef fun dump_intern(icd)
282 do
283 return "ABORT (\"{texts.join("\", \"")}\")"
284 end
285 end
286
287 redef class ICall
288 redef fun dump_intern(icd)
289 do
290 return "CALL {property.full_name}({icd.register_all(exprs)})"
291 end
292 end
293
294 redef class INew
295 redef fun dump_intern(icd)
296 do
297 return "NEW {stype}.{property.full_name}({icd.register_all(exprs)})"
298 end
299 end
300
301 redef class ISuper
302 redef fun dump_intern(icd)
303 do
304 return "SUPER {property.full_name}({icd.register_all(exprs)})"
305 end
306 end
307
308 redef class IStaticCall
309 redef fun dump_intern(icd)
310 do
311 return "STATIC_CALL {property.full_name}({icd.register_all(exprs)})"
312 end
313 end
314
315 redef class IAllocateInstance
316 redef fun dump_intern(icd)
317 do
318 return "ALLOCATE NEW_{stype}"
319 end
320 end
321
322 redef class ICheckInstance
323 redef fun dump_intern(icd)
324 do
325 return "CHECK_INSTANCE CHECKNEW_{stype}({icd.register(expr)})"
326 end
327 end
328
329 redef class IInitAttributes
330 redef fun dump_intern(icd)
331 do
332 return "INIT_ATTRIBUTES INIT_ATTRIBUTES_{stype}({icd.register(expr)})"
333 end
334 end
335
336 redef class IClosCall
337 redef fun dump_intern(icd)
338 do
339 return "CLOS_CALL {icd.closdecl(closure_decl)}({icd.register_all(exprs)})"
340 end
341 end
342
343 redef class IAttrRead
344 redef fun dump_intern(icd)
345 do
346 return "ATTR_READ {property.full_name}({icd.register(expr)})"
347 end
348 end
349
350 redef class IAttrWrite
351 redef fun dump_intern(icd)
352 do
353 return "ATTR_WRITE {property.full_name}({icd.register(expr1)}) := {icd.register(expr2)}"
354 end
355 end
356
357 redef class IAttrIsset
358 redef fun dump_intern(icd)
359 do
360 return "ATTR_ISSET {property.full_name}({icd.register(expr)})"
361 end
362 end
363
364 redef class ITypeCheck
365 redef fun dump_intern(icd)
366 do
367 return "CHECKTYPE {icd.register(expr)} isa {stype}"
368 end
369 end
370
371 redef class INative
372 redef fun dump_intern(icd)
373 do
374 return "NATIVE \"{method.full_name}\"({icd.register_all(exprs)})"
375 end
376 end
377
378 redef class IIntValue
379 redef fun dump_intern(icd)
380 do
381 return "INTVALUE {value}"
382 end
383 end
384
385 redef class IBoolValue
386 redef fun dump_intern(icd)
387 do
388 return "BOOLVALUE {value}"
389 end
390 end
391
392 redef class IStringValue
393 redef fun dump_intern(icd)
394 do
395 return "STRINGVALUE {value}"
396 end
397 end
398
399 redef class ICharValue
400 redef fun dump_intern(icd)
401 do
402 return "CHARVALUE {value}"
403 end
404 end
405
406 redef class IFloatValue
407 redef fun dump_intern(icd)
408 do
409 return "FLOATVALUE {value}"
410 end
411 end
412
413 redef class IMove
414 redef fun dump_intern(icd)
415 do
416 return "{icd.register(expr)}"
417 end
418 end
419
420 redef class IIs
421 redef fun dump_intern(icd)
422 do
423 return "{icd.register(expr1)} is {icd.register(expr2)}"
424 end
425 end
426
427 redef class INot
428 redef fun dump_intern(icd)
429 do
430 return "NOT {icd.register(expr)}"
431 end
432 end
433
434 redef class IOnce
435 redef fun dump(icd)
436 do
437 icd.write "{icd.register(result.as(not null))} := ONCE \{"
438 icd.indent
439 body.dump(icd)
440 icd.unindent
441 icd.write "}"
442 end
443 end
444
445 redef class IHasClos
446 redef fun dump_intern(icd)
447 do
448 return "HASCLOS {icd.closdecl(closure_decl)}"
449 end
450 end