icode: distinguish slots in dump
[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: ISeq): 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: ISeq): 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 if icd.has_lab(self) then icd.write("{icd.lab(self)}:")
228 end
229 end
230
231 redef class IIf
232 redef fun dump(icd)
233 do
234 icd.write "IF({icd.register(expr)}) \{"
235 icd.indent
236 then_seq.dump(icd)
237 icd.unindent
238 icd.write "} ELSE \{"
239 icd.indent
240 else_seq.dump(icd)
241 icd.unindent
242 icd.write "}"
243 end
244 end
245
246 redef class ILoop
247 redef fun dump(icd)
248 do
249 icd.write "LOOP \{"
250 icd.indent
251 for ic in icodes do
252 ic.dump(icd)
253 end
254 icd.unindent
255 icd.write "}"
256 if icd.has_lab(self) then icd.write("{icd.lab(self)}:")
257 end
258 end
259
260 redef class IEscape
261 redef fun dump_intern(icd)
262 do
263 return "ESCAPE {icd.lab(seq)}"
264 end
265 end
266
267 redef class IAbort
268 redef fun dump_intern(icd)
269 do
270 return "ABORT (\"{texts.join("\", \"")}\")"
271 end
272 end
273
274 redef class ICall
275 redef fun dump_intern(icd)
276 do
277 return "CALL {property.full_name}({icd.register_all(exprs)})"
278 end
279 end
280
281 redef class INew
282 redef fun dump_intern(icd)
283 do
284 return "NEW {stype}.{property.full_name}({icd.register_all(exprs)})"
285 end
286 end
287
288 redef class ISuper
289 redef fun dump_intern(icd)
290 do
291 return "SUPER {property.full_name}({icd.register_all(exprs)})"
292 end
293 end
294
295 redef class IStaticCall
296 redef fun dump_intern(icd)
297 do
298 return "STATIC_CALL {property.full_name}({icd.register_all(exprs)})"
299 end
300 end
301
302 redef class IAllocateInstance
303 redef fun dump_intern(icd)
304 do
305 return "ALLOCATE NEW_{stype}"
306 end
307 end
308
309 redef class ICheckInstance
310 redef fun dump_intern(icd)
311 do
312 return "CHECK_INSTANCE CHECKNEW_{stype}({icd.register(expr)})"
313 end
314 end
315
316 redef class IInitAttributes
317 redef fun dump_intern(icd)
318 do
319 return "INIT_ATTRIBUTES INIT_ATTRIBUTES_{stype}({icd.register(expr)})"
320 end
321 end
322
323 redef class IClosCall
324 redef fun dump_intern(icd)
325 do
326 return "CLOS_CALL {icd.closdecl(closure_decl)}({icd.register_all(exprs)})"
327 end
328 end
329
330 redef class IAttrRead
331 redef fun dump_intern(icd)
332 do
333 return "ATTR_READ {property.full_name}({icd.register(expr)})"
334 end
335 end
336
337 redef class IAttrWrite
338 redef fun dump_intern(icd)
339 do
340 return "ATTR_WRITE {property.full_name}({icd.register(expr1)}) := {icd.register(expr2)}"
341 end
342 end
343
344 redef class IAttrIsset
345 redef fun dump_intern(icd)
346 do
347 return "ATTR_ISSET {property.full_name}({icd.register(expr)})"
348 end
349 end
350
351 redef class ITypeCheck
352 redef fun dump_intern(icd)
353 do
354 return "CHECKTYPE {icd.register(expr)} isa {stype}"
355 end
356 end
357
358 redef class INative
359 redef fun dump_intern(icd)
360 do
361 if exprs.is_empty then
362 return "NATIVE \"{code}\""
363 else
364 return "NATIVE \"{code}\"({icd.register_all(exprs)})"
365 end
366 end
367 end
368
369 redef class IMove
370 redef fun dump_intern(icd)
371 do
372 return "{icd.register(expr)}"
373 end
374 end
375
376 redef class IIs
377 redef fun dump_intern(icd)
378 do
379 return "{icd.register(expr1)} is {icd.register(expr2)}"
380 end
381 end
382
383 redef class INot
384 redef fun dump_intern(icd)
385 do
386 return "NOT {icd.register(expr)}"
387 end
388 end
389
390 redef class IOnce
391 redef fun dump(icd)
392 do
393 icd.write "{icd.register(result.as(not null))} := ONCE \{"
394 icd.indent
395 body.dump(icd)
396 icd.unindent
397 icd.write "}"
398 end
399 end
400
401 redef class IHasClos
402 redef fun dump_intern(icd)
403 do
404 return "HASCLOS {icd.closdecl(closure_decl)}"
405 end
406 end