Mercurial > repos > tabletprog
comparison modules/il.tp @ 189:a45e535f7742
Determine live ranges for logical registers as part of initial work on register allocator
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 26 Aug 2013 18:23:05 -0700 |
parents | 181d8754a2ae |
children | 4293c725394c |
comparison
equal
deleted
inserted
replaced
188:7e313849ab41 | 189:a45e535f7742 |
---|---|
46 out <- { _out } | 46 out <- { _out } |
47 size <- { _size } | 47 size <- { _size } |
48 numops <- { 3 } | 48 numops <- { 3 } |
49 name <- { _names get: _opcode } | 49 name <- { _names get: _opcode } |
50 string <- { name . " " . (string: _ina) . " " . (string: _inb) . " " . (string: _out) . " " . (string: _size) } | 50 string <- { name . " " . (string: _ina) . " " . (string: _inb) . " " . (string: _out) . " " . (string: _size) } |
51 recordUsage:at <- :tracker :address { | |
52 if: (not: (_ina isInteger?)) { | |
53 _ina recordUsage: tracker at: 0 | address withSize: _size | |
54 } | |
55 _inb recordUsage: tracker at: 0 | address withSize: _size | |
56 _out recordUsage: tracker at: 1 | address withSize: _size | |
57 } | |
51 } | 58 } |
52 } | 59 } |
53 op2:in:out:size <- :_opcode :_in :_out :_size { | 60 op2:in:out:size <- :_opcode :_in :_out :_size { |
54 #{ | 61 #{ |
55 opcode <- { _opcode } | 62 opcode <- { _opcode } |
57 out <- { _out } | 64 out <- { _out } |
58 size <- { _size } | 65 size <- { _size } |
59 numops <- { 2 } | 66 numops <- { 2 } |
60 name <- { _names get: _opcode } | 67 name <- { _names get: _opcode } |
61 string <- { name . " " . (string: _in) . " " . (string: _out) . " " . (string: _size) } | 68 string <- { name . " " . (string: _in) . " " . (string: _out) . " " . (string: _size) } |
69 recordUsage:at <- :tracker :address { | |
70 if: (not: (_in isInteger?)) { | |
71 _in recordUsage: tracker at: 0 | address withSize: _size | |
72 } | |
73 _out recordUsage: tracker at: 1 | address withSize: _size | |
74 } | |
62 } | 75 } |
63 } | 76 } |
64 op1:arg:size <- :_opcode :_arg :_size { | 77 op1:arg:size <- :_opcode :_arg :_size { |
65 #{ | 78 #{ |
66 opcode <- { _opcode } | 79 opcode <- { _opcode } |
67 arg <- { _arg } | 80 arg <- { _arg } |
68 size <- { _size } | 81 size <- { _size } |
69 numops <- { 1 } | 82 numops <- { 1 } |
70 name <- { _names get: _opcode } | 83 name <- { _names get: _opcode } |
71 string <- { name . " " . (string: _arg) . " " . (string: _size) } | 84 string <- { name . " " . (string: _arg) . " " . (string: _size) } |
85 recordUsage:at <- :tracker :address { | |
86 if: (not: (_arg isInteger?)) { | |
87 _arg recordUsage: tracker at: address withSize: _size | |
88 } | |
89 } | |
72 } | 90 } |
73 } | 91 } |
74 | 92 |
75 _sizenames <- #["b" "w" "l" "q"] | 93 _sizenames <- #["b" "w" "l" "q"] |
76 _size <- :_num { | 94 _size <- :_num { |
105 argument? <- { false } | 123 argument? <- { false } |
106 return? <- { true } | 124 return? <- { true } |
107 string <- { "retr" } | 125 string <- { "retr" } |
108 = <- :other { | 126 = <- :other { |
109 (not: (other isInteger?)) && (other register?) && (other return?) | 127 (not: (other isInteger?)) && (other register?) && (other return?) |
128 } | |
129 != <- :other { | |
130 not: self = other | |
131 } | |
132 recordUsage:at:withSize <- :tracker :address :size { | |
133 //TODO: Figure out what tracking is necessary here | |
110 } | 134 } |
111 } | 135 } |
112 | 136 |
113 _condnames <- #[ | 137 _condnames <- #[ |
114 "eq" | 138 "eq" |
171 regnum <- { num } | 195 regnum <- { num } |
172 string <- { "r" . (string: num) } | 196 string <- { "r" . (string: num) } |
173 = <- :other { | 197 = <- :other { |
174 (not: (other isInteger?)) && (other register?) && (not: (other argument?)) && (not: (other return?)) && num = (other regnum) | 198 (not: (other isInteger?)) && (other register?) && (not: (other argument?)) && (not: (other return?)) && num = (other regnum) |
175 } | 199 } |
200 != <- :other { | |
201 not: self = other | |
202 } | |
203 recordUsage:at:withSize <- :tracker :address :size { | |
204 tracker reg: self usedAt: address withSize: size | |
205 } | |
176 } | 206 } |
177 } | 207 } |
178 arg <- :num { | 208 arg <- :num { |
179 #{ | 209 #{ |
180 isInteger? <- { false } | 210 isInteger? <- { false } |
184 argnum <- { num } | 214 argnum <- { num } |
185 string <- { "a" . (string: num) } | 215 string <- { "a" . (string: num) } |
186 = <- :other { | 216 = <- :other { |
187 (not: (other isInteger?)) && (other register?) && (other argument?) && num = (other regnum) | 217 (not: (other isInteger?)) && (other register?) && (other argument?) && num = (other regnum) |
188 } | 218 } |
219 != <- :other { | |
220 not: self = other | |
221 } | |
222 recordUsage:at:withSize <- :tracker :address :size { | |
223 tracker arg: self usedAt: address withSize: size | |
224 } | |
189 } | 225 } |
190 } | 226 } |
191 retr <- { _retr } | 227 retr <- { _retr } |
228 | |
229 base:offset <- :_base :_offset { | |
230 #{ | |
231 base <- { _base } | |
232 offset <- { _offset } | |
233 string <- { | |
234 start <- if: _offset = 0 { "" } else: { (string: _offset) } | |
235 start . "[" . (string: _base) . "]" | |
236 } | |
237 recordUsage:at:withSize <- :tracker :address :size { | |
238 _base recordUsage: tracker at: address withSize: size | |
239 } | |
240 } | |
241 } | |
192 | 242 |
193 add <- :ina inb out size { | 243 add <- :ina inb out size { |
194 op3: _add a: ina b: inb out: out size: size | 244 op3: _add a: ina b: inb out: out size: size |
195 } | 245 } |
196 | 246 |
252 string <- { | 302 string <- { |
253 argstr <- _args map: :el { | 303 argstr <- _args map: :el { |
254 string: el | 304 string: el |
255 } | 305 } |
256 name . " " . (string: _target) . " " . (argstr join: " ") | 306 name . " " . (string: _target) . " " . (argstr join: " ") |
307 } | |
308 recordUsage:at <- :tracker :address { | |
309 if: (not: (_target isString?)) { | |
310 //TODO: use size l for 32-bit targets or an abstract pointer size | |
311 _target recordUsage: tracker at: address withSize: q | |
312 } | |
313 foreach: _args :_ arg { | |
314 //TODO: have some mechanism for properly expressing sizes of arguments | |
315 arg recordUsage: tracker at: address withSize: q | |
316 } | |
257 } | 317 } |
258 } | 318 } |
259 } | 319 } |
260 | 320 |
261 return <- :val size { | 321 return <- :val size { |
273 if: (_toskip length) > 0 { | 333 if: (_toskip length) > 0 { |
274 block <- "\n\t" . block . "\n" | 334 block <- "\n\t" . block . "\n" |
275 } | 335 } |
276 name . " " . (string: _cond) . " {" . block . "}" | 336 name . " " . (string: _cond) . " {" . block . "}" |
277 } | 337 } |
278 } | 338 recordUsage:at <- :tracker :address { |
339 foreach: _toskip :idx inst { | |
340 inst recordUsage: tracker at: idx | address | |
341 } | |
342 } | |
343 } | |
344 } | |
345 | |
346 allocRegs:withSource <- :instarr:regSrc { | |
347 _regMap <- dict linear | |
348 _argMap <- dict linear | |
349 | |
350 _usageTracker <- :_firstUsage { | |
351 #{ | |
352 firstUsage <- _firstUsage | |
353 lastUsage <- _firstUsage | |
354 useCount <- 0 | |
355 maxSize <- byte | |
356 usedAt:withSize <- :address :size { | |
357 useCount <- useCount + 1 | |
358 lastUsage <- address | |
359 if: size > maxSize { | |
360 maxSize <- size | |
361 } | |
362 } | |
363 string <- { | |
364 "Uses: " . useCount . ", FirstUse: " . (firstUsage join: ":") . ", Last Use: " . (lastUsage join: ":") . ", Max Size: " . maxSize | |
365 } | |
366 } | |
367 } | |
368 | |
369 _maxUses <- 0 | |
370 _maxUseReg <- false | |
371 regUsage <- #{ | |
372 reg:usedAt:withSize <- :reg :address :size { | |
373 usage <- _regMap get: reg elseSet: { | |
374 _usageTracker: address | |
375 } | |
376 usage usedAt: address withSize: size | |
377 if: (usage useCount) > _maxUses { | |
378 _maxUses <- usage useCount | |
379 _maxUseReg <- reg | |
380 } | |
381 } | |
382 arg:usedAt:withSize <- :arg :address :size { | |
383 usage <- _argMap get: arg elseSet: { | |
384 _usageTracker: [0 0] | |
385 } | |
386 usage usedAt: address withSize: size | |
387 } | |
388 print <- { | |
389 foreach: _regMap :reg usage { | |
390 print: (string: reg) . " | " . (string: usage) . "\n" | |
391 } | |
392 foreach: _argMap :arg usage { | |
393 print: (string: arg) . " | " . (string: usage) . "\n" | |
394 } | |
395 } | |
396 } | |
397 foreach: instarr :idx inst { | |
398 inst recordUsage: regUsage at: [idx] | |
399 } | |
400 print: regUsage | |
279 } | 401 } |
280 | 402 |
281 //used to convert IL to a format suitable for a 2-operand architecture | 403 //used to convert IL to a format suitable for a 2-operand architecture |
282 //should be run after register allocation (I think....) | 404 //should be run after register allocation (I think....) |
283 to2Op <- :instarr { | 405 to2Op <- :instarr { |
321 ] | 443 ] |
322 print: "Original:\n\n" | 444 print: "Original:\n\n" |
323 foreach: fib :idx inst { | 445 foreach: fib :idx inst { |
324 print: (string: inst) . "\n" | 446 print: (string: inst) . "\n" |
325 } | 447 } |
448 print: "\n\nUsage:\n\n" | |
449 allocRegs: fib withSource: false | |
326 fib2 <- to2Op: fib | 450 fib2 <- to2Op: fib |
327 print: "\n\n2-Operand:\n\n" | 451 print: "\n\n2-Operand:\n\n" |
328 foreach: fib2 :idx inst { | 452 foreach: fib2 :idx inst { |
329 print: (string: inst) . "\n" | 453 print: (string: inst) . "\n" |
330 } | 454 } |