annotate modules/il.tp @ 253:697c2c562af2

Fix infinite loop in hash dict
author Michael Pavone <pavone@retrodev.com>
date Sat, 31 May 2014 21:27:03 -0700
parents 56b2100d9fff
children 2308336790d4
rev   line source
pavone@185 1 {
pavone@185 2 //commutative ops
pavone@185 3 _add <- 0
pavone@185 4 _and <- 1
pavone@185 5 _or <- 2
pavone@185 6 _xor <- 3
pavone@185 7 //non-commutative ops
pavone@185 8 _sub <- 4
pavone@185 9 _cmp <- 5
pavone@185 10 _not <- 6
pavone@185 11 _sl <- 7
pavone@185 12 _asr <- 8
pavone@185 13 _lsr <- 9
pavone@185 14 _rol <- 10
pavone@185 15 _ror <- 11
pavone@185 16 _mov <- 12
pavone@185 17 _call <- 13
pavone@185 18 _ret <- 14
pavone@185 19 _skipif <- 15
pavone@195 20 _save <- 16
pavone@185 21
pavone@185 22 _names <- #[
pavone@185 23 "add"
pavone@185 24 "and"
pavone@185 25 "or"
pavone@185 26 "xor"
pavone@185 27 "sub"
pavone@185 28 "cmp"
pavone@185 29 "not"
pavone@185 30 "sl"
pavone@185 31 "asr"
pavone@185 32 "lsr"
pavone@185 33 "rol"
pavone@185 34 "ror"
pavone@185 35 "mov"
pavone@185 36 "call"
pavone@185 37 "ret"
pavone@185 38 "skipIf"
pavone@195 39 "save"
pavone@185 40 ]
pavone@185 41
pavone@185 42 op3:a:b:out:size <- :_opcode :_ina :_inb :_out :_size {
pavone@185 43 #{
pavone@185 44 opcode <- { _opcode }
pavone@185 45 ina <- { _ina }
pavone@185 46 inb <- { _inb }
pavone@185 47 commutative? <- { _opcode < _sub }
pavone@185 48 out <- { _out }
pavone@185 49 size <- { _size }
pavone@185 50 numops <- { 3 }
pavone@185 51 name <- { _names get: _opcode }
pavone@185 52 string <- { name . " " . (string: _ina) . " " . (string: _inb) . " " . (string: _out) . " " . (string: _size) }
pavone@189 53 recordUsage:at <- :tracker :address {
pavone@189 54 if: (not: (_ina isInteger?)) {
pavone@189 55 _ina recordUsage: tracker at: 0 | address withSize: _size
pavone@189 56 }
pavone@189 57 _inb recordUsage: tracker at: 0 | address withSize: _size
pavone@189 58 _out recordUsage: tracker at: 1 | address withSize: _size
pavone@189 59 }
pavone@200 60 assignRegs:at:withSource:andUsage <- :assignments :at :regSrc :usage {
pavone@194 61 newa <- if: (not: (_ina isInteger?)) {
pavone@194 62 _ina assign: assignments withSource: regSrc
pavone@194 63 } else: { _ina }
pavone@194 64 newb <- _inb assign: assignments withSource: regSrc
pavone@194 65 newout <- _out assign: assignments withSource: regSrc
pavone@194 66 op3: _opcode a: newa b: newb out: newout size: _size
pavone@194 67 }
pavone@185 68 }
pavone@185 69 }
pavone@185 70 op2:in:out:size <- :_opcode :_in :_out :_size {
pavone@185 71 #{
pavone@185 72 opcode <- { _opcode }
pavone@185 73 in <- { _in }
pavone@185 74 out <- { _out }
pavone@185 75 size <- { _size }
pavone@185 76 numops <- { 2 }
pavone@185 77 name <- { _names get: _opcode }
pavone@185 78 string <- { name . " " . (string: _in) . " " . (string: _out) . " " . (string: _size) }
pavone@189 79 recordUsage:at <- :tracker :address {
pavone@189 80 if: (not: (_in isInteger?)) {
pavone@189 81 _in recordUsage: tracker at: 0 | address withSize: _size
pavone@189 82 }
pavone@189 83 _out recordUsage: tracker at: 1 | address withSize: _size
pavone@189 84 }
pavone@200 85 assignRegs:at:withSource:andUsage <- :assignments :at :regSrc :usage {
pavone@194 86 newin <- if: (not: (_in isInteger?)) {
pavone@194 87 _in assign: assignments withSource: regSrc
pavone@194 88 } else: { _in }
pavone@194 89 newout <- _out assign: assignments withSource: regSrc
pavone@194 90 op2: _opcode in: newin out: newout size: _size
pavone@194 91 }
pavone@185 92 }
pavone@185 93 }
pavone@185 94 op1:arg:size <- :_opcode :_arg :_size {
pavone@185 95 #{
pavone@185 96 opcode <- { _opcode }
pavone@185 97 arg <- { _arg }
pavone@185 98 size <- { _size }
pavone@185 99 numops <- { 1 }
pavone@185 100 name <- { _names get: _opcode }
pavone@185 101 string <- { name . " " . (string: _arg) . " " . (string: _size) }
pavone@189 102 recordUsage:at <- :tracker :address {
pavone@189 103 if: (not: (_arg isInteger?)) {
pavone@189 104 _arg recordUsage: tracker at: address withSize: _size
pavone@189 105 }
pavone@189 106 }
pavone@200 107 assignRegs:at:withSource:andUsage <- :assignments :at :regSrc :usage {
pavone@194 108 newarg <- if: (not: (_arg isInteger?)) {
pavone@194 109 _arg assign: assignments withSource: regSrc
pavone@194 110 } else: { _arg }
pavone@194 111 op1: _opcode arg: newarg size: _size
pavone@194 112 }
pavone@185 113 }
pavone@185 114 }
pavone@185 115
pavone@185 116 _sizenames <- #["b" "w" "l" "q"]
pavone@193 117 _size <- :_bytes {
pavone@185 118 #{
pavone@193 119 bytes <- { _bytes }
pavone@193 120 string <- {
pavone@193 121 idx <- if: _bytes = 8 { 3 } else: { _bytes / 2}
pavone@193 122 _sizenames get: idx
pavone@193 123 }
pavone@185 124 = <- :other {
pavone@193 125 _bytes = (other bytes)
pavone@185 126 }
pavone@185 127 <= <- :other {
pavone@193 128 _bytes <= (other bytes)
pavone@185 129 }
pavone@185 130 >= <- :other {
pavone@193 131 _bytes >= (other bytes)
pavone@185 132 }
pavone@185 133 > <- :other {
pavone@193 134 _bytes > (other bytes)
pavone@185 135 }
pavone@185 136 < <- :other {
pavone@193 137 _bytes < (other bytes)
pavone@185 138 }
pavone@185 139 }
pavone@185 140 }
pavone@193 141 byte <- _size: 1
pavone@193 142 word <- _size: 2
pavone@193 143 long <- _size: 4
pavone@193 144 quad <- _size: 8
pavone@185 145
pavone@185 146 _retr <- #{
pavone@185 147 isInteger? <- { false }
pavone@185 148 register? <- { true }
pavone@185 149 argument? <- { false }
pavone@185 150 return? <- { true }
pavone@185 151 string <- { "retr" }
pavone@185 152 = <- :other {
pavone@185 153 (not: (other isInteger?)) && (other register?) && (other return?)
pavone@185 154 }
pavone@189 155 != <- :other {
pavone@189 156 not: self = other
pavone@189 157 }
pavone@189 158 recordUsage:at:withSize <- :tracker :address :size {
pavone@189 159 //TODO: Figure out what tracking is necessary here
pavone@189 160 }
pavone@194 161 assign:withSource <- :assignments :regSrc {
pavone@194 162 regSrc allocRet
pavone@194 163 }
pavone@185 164 }
pavone@185 165
pavone@185 166 _condnames <- #[
pavone@185 167 "eq"
pavone@185 168 "neq"
pavone@185 169 "ge"
pavone@185 170 "le"
pavone@185 171 "gr"
pavone@185 172 "ls"
pavone@185 173 "uge"
pavone@185 174 "ule"
pavone@185 175 "ugr"
pavone@185 176 "uls"
pavone@185 177 ]
pavone@185 178 condition <- :num {
pavone@185 179 #{
pavone@185 180 cc <- { num }
pavone@185 181 string <- { _condnames get: num }
pavone@185 182 = <- :other { num = (other cc) }
pavone@185 183 }
pavone@185 184 }
pavone@185 185 _eq <- condition: 0
pavone@185 186 _neq <- condition: 1
pavone@185 187 _ge <- condition: 2
pavone@185 188 _le <- condition: 3
pavone@185 189 _gr <- condition: 4
pavone@185 190 _ls <- condition: 5
pavone@185 191 _uge <- condition: 6
pavone@185 192 _ule <- condition: 7
pavone@185 193 _ugr <- condition: 8
pavone@185 194 _uls <- condition: 9
pavone@185 195
pavone@185 196 #{
pavone@185 197 b <- { byte }
pavone@185 198 w <- { word }
pavone@185 199 l <- { long }
pavone@185 200 q <- { quad }
pavone@185 201
pavone@185 202 eq <- { _eq }
pavone@185 203 neq <- { _neq }
pavone@185 204
pavone@185 205 //signed conditions
pavone@185 206 ge <- { _ge }
pavone@185 207 le <- { _le }
pavone@185 208 gr <- { _gr }
pavone@185 209 ls <- { _ls }
pavone@185 210
pavone@185 211 //unsigned conditions
pavone@185 212 uge <- { _uge }
pavone@185 213 ule <- { _ule }
pavone@185 214 ugr <- { _ugr }
pavone@185 215 uls <- { _uls }
pavone@185 216
pavone@185 217
pavone@185 218 reg <- :num {
pavone@185 219 #{
pavone@185 220 isInteger? <- { false }
pavone@185 221 register? <- { true }
pavone@185 222 argument? <- { false }
pavone@185 223 return? <- { false }
pavone@185 224 regnum <- { num }
pavone@185 225 string <- { "r" . (string: num) }
pavone@185 226 = <- :other {
pavone@185 227 (not: (other isInteger?)) && (other register?) && (not: (other argument?)) && (not: (other return?)) && num = (other regnum)
pavone@185 228 }
pavone@189 229 != <- :other {
pavone@189 230 not: self = other
pavone@189 231 }
pavone@189 232 recordUsage:at:withSize <- :tracker :address :size {
pavone@189 233 tracker reg: self usedAt: address withSize: size
pavone@189 234 }
pavone@194 235 assign:withSource <- :assignments :regSrc {
pavone@194 236 assignments get: self
pavone@194 237 }
pavone@185 238 }
pavone@185 239 }
pavone@185 240 arg <- :num {
pavone@185 241 #{
pavone@185 242 isInteger? <- { false }
pavone@185 243 register? <- { true }
pavone@185 244 argument? <- { true }
pavone@185 245 return? <- { false }
pavone@185 246 argnum <- { num }
pavone@185 247 string <- { "a" . (string: num) }
pavone@185 248 = <- :other {
pavone@185 249 (not: (other isInteger?)) && (other register?) && (other argument?) && num = (other regnum)
pavone@185 250 }
pavone@189 251 != <- :other {
pavone@189 252 not: self = other
pavone@189 253 }
pavone@189 254 recordUsage:at:withSize <- :tracker :address :size {
pavone@189 255 tracker arg: self usedAt: address withSize: size
pavone@189 256 }
pavone@194 257 assign:withSource <- :assignments :regSrc {
pavone@194 258 regSrc allocArg: num
pavone@194 259 }
pavone@185 260 }
pavone@185 261 }
pavone@185 262 retr <- { _retr }
pavone@185 263
pavone@189 264 base:offset <- :_base :_offset {
pavone@189 265 #{
pavone@189 266 base <- { _base }
pavone@189 267 offset <- { _offset }
pavone@189 268 string <- {
pavone@189 269 start <- if: _offset = 0 { "" } else: { (string: _offset) }
pavone@189 270 start . "[" . (string: _base) . "]"
pavone@189 271 }
pavone@189 272 recordUsage:at:withSize <- :tracker :address :size {
pavone@189 273 _base recordUsage: tracker at: address withSize: size
pavone@189 274 }
pavone@189 275 }
pavone@189 276 }
pavone@189 277
pavone@185 278 add <- :ina inb out size {
pavone@185 279 op3: _add a: ina b: inb out: out size: size
pavone@185 280 }
pavone@185 281
pavone@185 282 sub <- :ina inb out size {
pavone@185 283 op3: _sub a: ina b: inb out: out size: size
pavone@185 284 }
pavone@185 285
pavone@185 286 cmp <- :ina inb out size {
pavone@185 287 op3: _cmp a: ina b: inb out: out size: size
pavone@185 288 }
pavone@185 289
pavone@185 290 and <- :ina inb out size {
pavone@185 291 op3: _and a: ina b: inb out: out size: size
pavone@185 292 }
pavone@185 293
pavone@185 294 or <- :ina inb out size {
pavone@185 295 op3: _or a: ina b: inb out: out size: size
pavone@185 296 }
pavone@185 297
pavone@185 298 xor <- :ina inb out size {
pavone@185 299 op3: _xor a: ina b: inb out: out size: size
pavone@185 300 }
pavone@185 301
pavone@185 302 bnot <- :in out size {
pavone@185 303 op2: _not in: in out: out size: size
pavone@185 304 }
pavone@185 305
pavone@185 306 sl <- :shift in out size {
pavone@185 307 op3: _sl a: shift b: in out: out size: size
pavone@185 308 }
pavone@185 309
pavone@185 310 asr <- :shift in out size {
pavone@185 311 op3: _asr a: shift b: in out: out size: size
pavone@185 312 }
pavone@185 313
pavone@185 314 lsr <- :shift in out size {
pavone@185 315 op3: _lsr a: shift b: in out: out size: size
pavone@185 316 }
pavone@185 317
pavone@185 318 rol <- :rot in out size {
pavone@185 319 op3: _rol a: rot b: in out: out size: size
pavone@185 320 }
pavone@185 321
pavone@185 322 ror <- :rot in out size {
pavone@185 323 op3: _ror a: rot b: in out: out size: size
pavone@185 324 }
pavone@185 325
pavone@185 326 mov <- :in out size {
pavone@185 327 op2: _mov in: in out: out size: size
pavone@185 328 }
pavone@185 329
pavone@185 330 call:withArgs <- :_target :_args {
pavone@185 331 #{
pavone@185 332 opcode <- { _call }
pavone@185 333 target <- { _target }
pavone@185 334 args <- { _args }
pavone@185 335 numops <- { 0 }
pavone@185 336 name <- { _names get: _call }
pavone@185 337 string <- {
pavone@185 338 argstr <- _args map: :el {
pavone@185 339 string: el
pavone@185 340 }
pavone@185 341 name . " " . (string: _target) . " " . (argstr join: " ")
pavone@185 342 }
pavone@189 343 recordUsage:at <- :tracker :address {
pavone@189 344 if: (not: (_target isString?)) {
pavone@189 345 //TODO: use size l for 32-bit targets or an abstract pointer size
pavone@189 346 _target recordUsage: tracker at: address withSize: q
pavone@189 347 }
pavone@189 348 foreach: _args :_ arg {
pavone@189 349 //TODO: have some mechanism for properly expressing sizes of arguments
pavone@189 350 arg recordUsage: tracker at: address withSize: q
pavone@189 351 }
pavone@189 352 }
pavone@200 353 assignRegs:at:withSource:andUsage <- :assignments :address :regSrc :usage {
pavone@194 354 newtarget <- if: (_target isString?) { _target } else: {
pavone@194 355 _target assign: assignments withSource: regSrc
pavone@194 356 }
pavone@194 357 newargs <- _args map: :arg {
pavone@194 358 if: (arg isInteger?) { arg } else: {
pavone@194 359 arg assign: assignments withSource: regSrc
pavone@194 360 }
pavone@194 361 }
pavone@200 362 newcall <- call: newtarget withArgs: newargs
pavone@200 363 regSrc returnAll
pavone@200 364 raddress <- address reverse
pavone@200 365 foreach: (usage liveArgsAt: raddress) :_ arg {
pavone@200 366 regSrc allocArg: (arg num)
pavone@200 367 }
pavone@200 368 foreach: (usage liveRegsAt: raddress) :_ reg {
pavone@200 369 regSrc allocSpecific: (assignments get: reg)
pavone@200 370 }
pavone@200 371 tosave <- regSrc needSaveForCall
pavone@200 372 if: (tosave length) > 0 {
pavone@200 373 save: tosave #[newcall]
pavone@200 374 } else: {
pavone@200 375 newcall
pavone@200 376 }
pavone@194 377 }
pavone@185 378 }
pavone@185 379 }
pavone@185 380
pavone@185 381 return <- :val size {
pavone@185 382 op1: _ret arg: val size: size
pavone@185 383 }
pavone@185 384 skipIf <- :_cond _toskip {
pavone@185 385 #{
pavone@185 386 opcode <- { _skipif }
pavone@185 387 toskip <- { _toskip }
pavone@185 388 cond <- { _cond }
pavone@185 389 numops <- { 0 }
pavone@185 390 name <- { _names get: _skipif }
pavone@185 391 string <- {
pavone@185 392 block <- (_toskip map: :el { string: el }) join: "\n\t"
pavone@185 393 if: (_toskip length) > 0 {
pavone@185 394 block <- "\n\t" . block . "\n"
pavone@185 395 }
pavone@185 396 name . " " . (string: _cond) . " {" . block . "}"
pavone@185 397 }
pavone@189 398 recordUsage:at <- :tracker :address {
pavone@189 399 foreach: _toskip :idx inst {
pavone@189 400 inst recordUsage: tracker at: idx | address
pavone@189 401 }
pavone@189 402 }
pavone@200 403 assignRegs:at:withSource:andUsage <- :assignments :address :regSrc :usage {
pavone@200 404 newskip <- #[]
pavone@200 405 foreach: _toskip :idx inst {
pavone@200 406 newskip append: (inst assignRegs: assignments at: idx | address withSource: regSrc andUsage: usage)
pavone@194 407 }
pavone@194 408 skipIf: _cond newskip
pavone@194 409 }
pavone@200 410 to2OpInst <- {
pavone@200 411 skipIf: _cond (to2Op: _toskip)
pavone@200 412 }
pavone@185 413 }
pavone@185 414 }
pavone@203 415 save <- :regs :_scope{
pavone@195 416 #{
pavone@195 417 opcode <- { _save }
pavone@195 418 numops <- { 0 }
pavone@195 419 name <- { _names get: _save }
pavone@203 420 tosave <- { regs }
pavone@203 421 scope <- { _scope }
pavone@195 422 string <- {
pavone@203 423 block <- _scope join: "\n\t"
pavone@203 424 if: (_scope length) > 0 {
pavone@195 425 block <- "\n\t" . block . "\n"
pavone@195 426 }
pavone@195 427 name . " " . (regs join: " ") . " {" . block . "}"
pavone@195 428 }
pavone@200 429 to2OpInst <- {
pavone@203 430 save: regs (to2Op: _scope)
pavone@200 431 }
pavone@195 432 }
pavone@195 433 }
pavone@185 434
pavone@189 435 allocRegs:withSource <- :instarr:regSrc {
pavone@189 436 _regMap <- dict linear
pavone@189 437 _argMap <- dict linear
pavone@189 438
pavone@189 439 _usageTracker <- :_firstUsage {
pavone@189 440 #{
pavone@189 441 firstUsage <- _firstUsage
pavone@189 442 lastUsage <- _firstUsage
pavone@189 443 useCount <- 0
pavone@189 444 maxSize <- byte
pavone@189 445 usedAt:withSize <- :address :size {
pavone@189 446 useCount <- useCount + 1
pavone@189 447 lastUsage <- address
pavone@189 448 if: size > maxSize {
pavone@189 449 maxSize <- size
pavone@189 450 }
pavone@189 451 }
pavone@189 452 string <- {
pavone@189 453 "Uses: " . useCount . ", FirstUse: " . (firstUsage join: ":") . ", Last Use: " . (lastUsage join: ":") . ", Max Size: " . maxSize
pavone@189 454 }
pavone@189 455 }
pavone@189 456 }
pavone@189 457
pavone@189 458 _maxUses <- 0
pavone@200 459 liveFrom:to <- :regs :from :to {
pavone@200 460 live <- #[]
pavone@200 461 foreach: regs :reg usage {
pavone@200 462 if: ((usage lastUsage) addrGreatEq: from) && ((usage firstUsage) addrLessEq: to) {
pavone@200 463 live append: reg
pavone@200 464 }
pavone@200 465 }
pavone@200 466 live
pavone@200 467 }
pavone@189 468 regUsage <- #{
pavone@189 469 reg:usedAt:withSize <- :reg :address :size {
pavone@193 470 raddress <- address reverse
pavone@189 471 usage <- _regMap get: reg elseSet: {
pavone@193 472 _usageTracker: raddress
pavone@189 473 }
pavone@193 474 usage usedAt: raddress withSize: size
pavone@189 475 if: (usage useCount) > _maxUses {
pavone@189 476 _maxUses <- usage useCount
pavone@189 477 }
pavone@189 478 }
pavone@189 479 arg:usedAt:withSize <- :arg :address :size {
pavone@193 480 raddress <- address reverse
pavone@189 481 usage <- _argMap get: arg elseSet: {
pavone@189 482 _usageTracker: [0 0]
pavone@189 483 }
pavone@193 484 usage usedAt: raddress withSize: size
pavone@189 485 }
pavone@200 486
pavone@200 487 liveRegsAt <- :address {
pavone@200 488 _regMap liveFrom: address to: address
pavone@200 489 }
pavone@200 490 liveArgsAt <- :address {
pavone@200 491 _argMap liveFrom: address to: address
pavone@200 492 }
pavone@200 493
pavone@189 494 print <- {
pavone@189 495 foreach: _regMap :reg usage {
pavone@189 496 print: (string: reg) . " | " . (string: usage) . "\n"
pavone@189 497 }
pavone@189 498 foreach: _argMap :arg usage {
pavone@189 499 print: (string: arg) . " | " . (string: usage) . "\n"
pavone@189 500 }
pavone@189 501 }
pavone@189 502 }
pavone@189 503 foreach: instarr :idx inst {
pavone@189 504 inst recordUsage: regUsage at: [idx]
pavone@189 505 }
pavone@189 506 print: regUsage
pavone@193 507
pavone@193 508 addrLessEq <- :left :right {
pavone@193 509 lesseq <- true
pavone@193 510 while: { lesseq && (not: (left empty?)) && (not: (right empty?)) } do: {
pavone@193 511 if: (left value) > (right value) {
pavone@193 512 lesseq <- false
pavone@193 513 } else: {
pavone@193 514 if: (left value) < (right value) {
pavone@193 515 left <- []
pavone@193 516 } else: {
pavone@193 517 left <- left tail
pavone@193 518 right <- right tail
pavone@193 519 }
pavone@193 520 }
pavone@193 521 }
pavone@193 522 lesseq
pavone@193 523 }
pavone@193 524
pavone@193 525 addrGreatEq <- :left :right {
pavone@193 526 greateq <- true
pavone@193 527 while: { greateq && (not: (left empty?)) && (not: (right empty?)) } do: {
pavone@193 528 if: (left value) < (right value) {
pavone@193 529 greateq <- false
pavone@193 530 } else: {
pavone@193 531 if: (left value) > (right value) {
pavone@193 532 left <- []
pavone@193 533 } else: {
pavone@193 534 left <- left tail
pavone@193 535 right <- right tail
pavone@193 536 }
pavone@193 537 }
pavone@193 538 }
pavone@193 539 greateq
pavone@193 540 }
pavone@193 541
pavone@193 542 _assignments <- dict linear
pavone@193 543 curuses <- _maxUses
pavone@193 544 while: { curuses > 0 && (_assignments length) < (_regMap length) } do: {
pavone@193 545 foreach: _regMap :reg usage {
pavone@193 546 if: (usage useCount) = curuses {
pavone@193 547 liveArgs <- _argMap liveFrom: (usage firstUsage) to: (usage lastUsage)
pavone@193 548 foreach: liveArgs :_ arg {
pavone@193 549 regSrc allocArg: (arg num)
pavone@193 550 }
pavone@193 551
pavone@193 552 liveRegs <- _regMap liveFrom: (usage firstUsage) to: (usage lastUsage)
pavone@193 553 print: (string: reg) . " | Live: " . (liveRegs join: ", ") . ", Live Args: " . (liveArgs join: ", ") . "\n"
pavone@193 554 foreach: liveRegs :_ reg {
pavone@193 555 if: (_assignments contains?: reg) {
pavone@193 556 regSrc allocSpecific: (_assignments get: reg)
pavone@193 557 }
pavone@193 558 }
pavone@193 559 _assignments set: reg (regSrc alloc: (usage maxSize))
pavone@193 560
pavone@193 561 regSrc returnAll
pavone@193 562 }
pavone@193 563 }
pavone@193 564 curuses <- curuses - 1
pavone@193 565 }
pavone@193 566 print: "\n\nAssignments:\n\n"
pavone@193 567 foreach: _assignments :reg assign {
pavone@193 568 print: (string: reg) . " = " . assign . "\n"
pavone@193 569 }
pavone@194 570
pavone@200 571 withassign <- #[]
pavone@200 572 foreach: instarr :idx inst {
pavone@200 573 withassign append: (inst assignRegs: _assignments at: [idx] withSource: regSrc andUsage: regUsage)
pavone@194 574 }
pavone@195 575 psave <- regSrc needSaveProlog
pavone@195 576 if: (psave length) > 0 {
pavone@195 577 withassign <- #[save: psave withassign]
pavone@195 578 }
pavone@195 579 withassign
pavone@189 580 }
pavone@189 581
pavone@185 582 //used to convert IL to a format suitable for a 2-operand architecture
pavone@185 583 //should be run after register allocation (I think....)
pavone@185 584 to2Op <- :instarr {
pavone@185 585 instarr fold: #[] with: :newarr inst {
pavone@185 586 if: (inst numops) = 3 {
pavone@185 587 if: (inst inb) = (inst out) {
pavone@185 588 newarr append: (op2: (inst opcode) in: (inst ina) out: (inst out) size: (inst size))
pavone@185 589 } else: {
pavone@185 590 if: (inst commutative?) && (inst ina) = (inst out) {
pavone@185 591 newarr append: (op2: (inst opcode) in: (inst inb) out: (inst out) size: (inst size))
pavone@185 592 } else: {
pavone@185 593 newarr append: (mov: (inst inb) (inst out) (inst size))
pavone@185 594 newarr append: (op2: (inst opcode) in: (inst ina) out: (inst out) size: (inst size))
pavone@185 595 }
pavone@185 596 }
pavone@185 597 } else: {
pavone@185 598 if: (inst numops) = 2 && (inst opcode) != _mov {
pavone@185 599 if: (inst in) != (inst out) {
pavone@185 600 newarr append: (mov: (inst in) (inst out) (inst size))
pavone@185 601 }
pavone@185 602 newarr append: (op1: (inst opcode) val: (inst out) size: (inst size))
pavone@185 603 } else: {
pavone@200 604 if: (inst opcode) = _skipif || (inst opcode) = _save {
pavone@200 605 newarr append: (inst to2OpInst)
pavone@200 606 } else: {
pavone@200 607 newarr append: inst
pavone@200 608 }
pavone@185 609 }
pavone@185 610 }
pavone@185 611 }
pavone@185 612 }
pavone@185 613
pavone@203 614 toBackend <- :program :backend {
pavone@203 615 prepped <- program map: :fun {
pavone@203 616 backend adjustIL: fun
pavone@203 617 }
pavone@203 618 labels <- prepped map: :_ {
pavone@203 619 backend label
pavone@203 620 }
pavone@203 621 outprog <- #[]
pavone@203 622 foreach: prepped :name instarr {
pavone@203 623 outprog append: (labels get: name)
pavone@203 624 foreach: instarr :_ inst {
pavone@203 625 backend convertIL: inst to: outprog withLabels: labels
pavone@203 626 }
pavone@203 627 }
pavone@203 628 outprog
pavone@203 629 }
pavone@203 630
pavone@185 631 main <- {
pavone@203 632 prog <- dict linear
pavone@203 633
pavone@185 634 fib <- #[
pavone@185 635 sub: 2 (arg: 0) (reg: 0) q
pavone@185 636 skipIf: ge #[
pavone@185 637 return: 1 q
pavone@185 638 ]
pavone@185 639 call: "fib" withArgs: #[reg: 0]
pavone@185 640 mov: retr (reg: 1) q
pavone@185 641 add: 1 (reg: 0) (reg: 2) q
pavone@185 642 call: "fib" withArgs: #[reg: 2]
pavone@185 643 add: retr (reg: 1) (reg: 3) q
pavone@185 644 return: (reg: 3) q
pavone@185 645 ]
pavone@185 646 print: "Original:\n\n"
pavone@185 647 foreach: fib :idx inst {
pavone@185 648 print: (string: inst) . "\n"
pavone@185 649 }
pavone@203 650 prog set: "fib" fib
pavone@203 651
pavone@203 652 mprog <- prog toBackend: x86
pavone@203 653 ba <- bytearray executableFromBytes: mprog
pavone@203 654 res <- ba runWithArg: 30u64
pavone@203 655 print: (string: res) . "\n"
pavone@203 656 0
pavone@185 657 }
pavone@185 658 }
pavone@185 659 }