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 }