Mercurial > repos > icfp2014
comparison code/gqc.tp @ 65:2a5d7308e1df
Cleanup handling of temporaries in gqc
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 27 Jul 2014 22:16:01 -0700 |
parents | d35601d47db1 |
children | 76570158a6e9 |
comparison
equal
deleted
inserted
replaced
58:d35601d47db1 | 65:2a5d7308e1df |
---|---|
1 { | 1 { |
2 reg? <- :val { | |
3 (object does: val understand?: "isReg?") && (val isReg?) | |
4 } | |
5 mem? <- :val { | |
6 (object does: val understand?: "isMem?") && (val isMem?) | |
7 } | |
8 | |
2 mem <- :_addr { | 9 mem <- :_addr { |
3 #{ | 10 #{ |
4 addr <- { _addr } | 11 addr <- { _addr } |
5 string <- { "[" . _addr . "]" } | 12 string <- { "[" . _addr . "]" } |
6 isReg? <- { false } | 13 isReg? <- { false } |
7 } | 14 != <- :other { (not: (mem?: other)) || _addr != (other addr) } |
8 } | 15 = <- :other { (mem?: other) && _addr = (other addr) } |
9 reg? <- :val { | 16 } |
10 (object does: val understand?: "isReg?") && (val isReg?) | |
11 } | 17 } |
12 reg <- :_num { | 18 reg <- :_num { |
13 #{ | 19 #{ |
14 num <- { _num } | 20 num <- { _num } |
15 string <- { (#["a" "b" "c" "d" "e" "f" "g" "h" "pc"]) get: _num } | 21 string <- { (#["a" "b" "c" "d" "e" "f" "g" "h" "pc"]) get: _num } |
92 reg: 5 | 98 reg: 5 |
93 reg: 6 | 99 reg: 6 |
94 ] | 100 ] |
95 _tempRegs <- _allTemp | 101 _tempRegs <- _allTemp |
96 | 102 |
103 getTemp <- { | |
104 if: (_tempRegs empty?) { | |
105 //out of regs, use memory | |
106 loc <- _nextVar | |
107 _nextVar <- _nextVar + 1 | |
108 mem: loc | |
109 } else: { | |
110 r <- _tempRegs value | |
111 _tempRegs <- _tempRegs tail | |
112 r | |
113 } | |
114 } | |
115 | |
116 preserveTemps <- :fun { | |
117 saveTempRegs <- _tempRegs | |
118 res <- fun: | |
119 _tempRegs <- saveTempRegs | |
120 res | |
121 } | |
122 | |
97 _exprHandlers <- dict hash | 123 _exprHandlers <- dict hash |
98 | 124 |
99 compileExpr:syms <- :expr :syms { | 125 compileExpr:syms <- :expr :syms { |
100 _exprHandlers ifget: (expr nodeType) :handler { | 126 _exprHandlers ifget: (expr nodeType) :handler { |
101 handler: expr syms | 127 handler: expr syms |
116 _opNames set: "and" "AND" | 142 _opNames set: "and" "AND" |
117 _opNames set: "or" "OR" | 143 _opNames set: "or" "OR" |
118 _opNames set: "xor" "XOR" | 144 _opNames set: "xor" "XOR" |
119 | 145 |
120 _exprHandlers set: (ast binary) :expr syms { | 146 _exprHandlers set: (ast binary) :expr syms { |
121 startTempRegs <- _tempRegs | 147 l <- 0 |
122 l <- compileExpr: (expr left) syms: syms | 148 r <- preserveTemps: { |
123 r <- compileExpr: (expr right) syms: syms | 149 l <- compileExpr: (expr left) syms: syms |
150 compileExpr: (expr right) syms: syms | |
151 } | |
124 dest <- l | 152 dest <- l |
125 if: (reg?: l) { | 153 if: (reg?: l) { |
126 _tempRegs <- startTempRegs filter: :r { r != l } | 154 //reallocate temp register used by l |
155 //not always safe, needs work | |
156 _tempRegs <- _tempRegs filter: :r { r != l } | |
127 } else: { | 157 } else: { |
128 dest <- startTempRegs value | 158 dest <- getTemp: |
129 prog add: (inst: "MOV" #[ | 159 prog add: (inst: "MOV" #[ |
130 dest | 160 dest |
131 l | 161 l |
132 ]) | 162 ]) |
133 _tempRegs <- startTempRegs tail | |
134 } | 163 } |
135 _opNames ifget: (expr op) :i { | 164 _opNames ifget: (expr op) :i { |
136 prog add: (inst: i #[ | 165 prog add: (inst: i #[ |
137 dest | 166 dest |
138 r | 167 r |
159 _nextVar <- _nextVar + 1 | 188 _nextVar <- _nextVar + 1 |
160 } | 189 } |
161 info <- syms find: (sym name) else: { | 190 info <- syms find: (sym name) else: { |
162 error: "this should never happen!" | 191 error: "this should never happen!" |
163 } | 192 } |
164 startTempRegs <- _tempRegs | 193 v <- preserveTemps: { |
165 v <- compileExpr: (expr assign) syms: syms | 194 compileExpr: (expr assign) syms: syms |
166 _tempRegs <- startTempRegs | 195 } |
167 dest <- info def | 196 dest <- info def |
168 prog add: (inst: "MOV" #[ | 197 prog add: (inst: "MOV" #[ |
169 dest | 198 dest |
170 v | 199 v |
171 ]) | 200 ]) |
178 prog add: (inst: "INT" #[8]) | 207 prog add: (inst: "INT" #[8]) |
179 0 | 208 0 |
180 } | 209 } |
181 _funHandlers set: "direction!" :args syms { | 210 _funHandlers set: "direction!" :args syms { |
182 dir <- args value | 211 dir <- args value |
183 startTempRegs <- _tempRegs | 212 v <- preserveTemps: { |
184 v <- compileExpr: dir syms: syms | 213 compileExpr: dir syms: syms |
185 _tempRegs <- startTempRegs | 214 } |
186 if: (reg: 0) != v { | 215 if: (reg: 0) != v { |
187 prog add: (inst: "MOV" #[ | 216 prog add: (inst: "MOV" #[ |
188 reg: 0 | 217 reg: 0 |
189 v | 218 v |
190 ]) | 219 ]) |
206 } | 235 } |
207 foreach: #["ghostStartPos" "ghostPos" "ghostStatus"] :idx name { | 236 foreach: #["ghostStartPos" "ghostPos" "ghostStatus"] :idx name { |
208 intNum <- idx + 4 | 237 intNum <- idx + 4 |
209 _funHandlers set: name :args syms { | 238 _funHandlers set: name :args syms { |
210 ghostIdx <- args value | 239 ghostIdx <- args value |
211 startTempRegs <- _tempRegs | 240 v <- preserveTemps: { |
212 v <- compileExpr: ghostIdx syms: syms | 241 compileExpr: ghostIdx syms: syms |
213 _tempRegs <- startTempRegs | 242 } |
214 if: (reg: 0) != v { | 243 if: (reg: 0) != v { |
215 prog add: (inst: "MOV" #[ | 244 prog add: (inst: "MOV" #[ |
216 reg: 0 | 245 reg: 0 |
217 v | 246 v |
218 ]) | 247 ]) |
222 } | 251 } |
223 } | 252 } |
224 _funHandlers set: "mapContentsAt" :args syms { | 253 _funHandlers set: "mapContentsAt" :args syms { |
225 x <- args value | 254 x <- args value |
226 y <- (args tail) value | 255 y <- (args tail) value |
227 startTempRegs <- _tempRegs | 256 preserveTemps: { |
228 x <- compileExpr: x syms: syms | 257 x <- compileExpr: x syms: syms |
229 y <- compileExpr: y syms: syms | 258 y <- compileExpr: y syms: syms |
230 _tempRegs <- startTempRegs | 259 } |
231 if: (reg: 0) != x { | 260 if: (reg: 0) != x { |
232 prog add: (inst: "MOV" #[ | 261 prog add: (inst: "MOV" #[ |
233 reg: 0 | 262 reg: 0 |
234 x | 263 x |
235 ]) | 264 ]) |
245 } | 274 } |
246 | 275 |
247 //allow access to raw instructions | 276 //allow access to raw instructions |
248 foreach: #["MOV" "INC" "DEC" "ADD" "SUB" "MUL" "DIV" "AND" "OR" "XOR" "JLT" "JEQ" "JGT" "HLT"] :idx instName { | 277 foreach: #["MOV" "INC" "DEC" "ADD" "SUB" "MUL" "DIV" "AND" "OR" "XOR" "JLT" "JEQ" "JGT" "HLT"] :idx instName { |
249 _funHandlers set: instName :args syms { | 278 _funHandlers set: instName :args syms { |
250 saveTempRegs <- _tempRegs | 279 preserveTemps: { |
251 args <- args map: :arg { compileExpr: arg syms: syms } | 280 args <- args map: :arg { compileExpr: arg syms: syms } |
281 } | |
252 prog add: (inst: instName args) | 282 prog add: (inst: instName args) |
253 } | 283 } |
254 } | 284 } |
255 | 285 |
256 _funHandlers set: "while:do" :args syms { | 286 _funHandlers set: "while:do" :args syms { |
260 if: (cond nodeType) = (ast binary) { | 290 if: (cond nodeType) = (ast binary) { |
261 top <- prog makeLabel: "loop_top" | 291 top <- prog makeLabel: "loop_top" |
262 end <- prog makeLabel: "loop_end" | 292 end <- prog makeLabel: "loop_end" |
263 prog setLabel: top | 293 prog setLabel: top |
264 | 294 |
265 saveTempRegs <- _tempRegs | 295 l <- 0 |
266 l <- compileExpr: (cond left) syms: syms | 296 r <- preserveTemps: { |
267 r <- compileExpr: (cond right) syms: syms | 297 l <- compileExpr: (cond left) syms: syms |
268 _tempRegs <- saveTempRegs | 298 compileExpr: (cond right) syms: syms |
299 } | |
269 | 300 |
270 ok <- true | 301 ok <- true |
271 //we need the inverse check in the instruction since a true condition | 302 //we need the inverse check in the instruction since a true condition |
272 //means continue the loop, whereas we need a jump instruction that jumps | 303 //means continue the loop, whereas we need a jump instruction that jumps |
273 //only when it is time to exit | 304 //only when it is time to exit |
345 //allow using bare symbols to define labels | 376 //allow using bare symbols to define labels |
346 lbl <- prog makeLabel: (expr name) | 377 lbl <- prog makeLabel: (expr name) |
347 prog setLabel: lbl | 378 prog setLabel: lbl |
348 syms define: (expr name) lbl | 379 syms define: (expr name) lbl |
349 } else: { | 380 } else: { |
350 saveTempRegsExpr <- _tempRegs | 381 v <- preserveTemps: { |
351 v <- compileExpr: expr syms: syms | 382 compileExpr: expr syms: syms |
352 _tempRegs <- saveTempRegsExpr | 383 } |
353 } | 384 } |
354 } | 385 } |
355 prog add: (inst: "MOV" #[ | 386 prog add: (inst: "MOV" #[ |
356 reg: 8 | 387 reg: 8 |
357 top | 388 top |
373 if: (cond nodeType) = (ast binary) { | 404 if: (cond nodeType) = (ast binary) { |
374 trueLbl <- prog makeLabel: "true" | 405 trueLbl <- prog makeLabel: "true" |
375 falseLbl <- prog makeLabel: "false" | 406 falseLbl <- prog makeLabel: "false" |
376 endLbl <- prog makeLabel: "end" | 407 endLbl <- prog makeLabel: "end" |
377 | 408 |
378 saveTempRegs <- _tempRegs | 409 l <- 0 |
379 l <- compileExpr: (cond left) syms: syms | 410 r <- preserveTemps: { |
380 r <- compileExpr: (cond right) syms: syms | 411 l <- compileExpr: (cond left) syms: syms |
381 _tempRegs <- saveTempRegs | 412 compileExpr: (cond right) syms: syms |
413 } | |
382 | 414 |
383 ok <- true | 415 ok <- true |
384 | 416 |
385 if: (cond op) = ">=" { | 417 if: (cond op) = ">=" { |
386 prog add: (inst: "JLT" #[ | 418 prog add: (inst: "JLT" #[ |
452 //allow using bare symbols to define labels | 484 //allow using bare symbols to define labels |
453 lbl <- prog makeLabel: (expr name) | 485 lbl <- prog makeLabel: (expr name) |
454 prog setLabel: lbl | 486 prog setLabel: lbl |
455 syms define: (expr name) lbl | 487 syms define: (expr name) lbl |
456 } else: { | 488 } else: { |
457 saveTempRegsExpr <- _tempRegs | 489 v <- preserveTemps: { |
458 v <- compileExpr: expr syms: syms | 490 compileExpr: expr syms: syms |
459 _tempRegs <- saveTempRegsExpr | 491 } |
460 } | 492 } |
461 } | 493 } |
462 prog add: (inst: "MOV" #[ | 494 prog add: (inst: "MOV" #[ |
463 reg: 8 | 495 reg: 8 |
464 endLbl | 496 endLbl |
470 //allow using bare symbols to define labels | 502 //allow using bare symbols to define labels |
471 lbl <- prog makeLabel: (expr name) | 503 lbl <- prog makeLabel: (expr name) |
472 prog setLabel: lbl | 504 prog setLabel: lbl |
473 syms define: (expr name) lbl | 505 syms define: (expr name) lbl |
474 } else: { | 506 } else: { |
475 saveTempRegsExpr <- _tempRegs | 507 v <- preserveTemps: { |
476 v <- compileExpr: expr syms: syms | 508 compileExpr: expr syms: syms |
477 _tempRegs <- saveTempRegsExpr | 509 } |
478 } | 510 } |
479 } | 511 } |
480 prog setLabel: endLbl | 512 prog setLabel: endLbl |
481 } else: { | 513 } else: { |
482 error: "Condition parameter to if:else must be a comparison operator expression" | 514 error: "Condition parameter to if:else must be a comparison operator expression" |
491 if: (tc nodeType) = (ast sym) { | 523 if: (tc nodeType) = (ast sym) { |
492 _funHandlers ifget: (tc name) :handler { | 524 _funHandlers ifget: (tc name) :handler { |
493 handler: (expr args) syms | 525 handler: (expr args) syms |
494 } else: { | 526 } else: { |
495 syms ifDefined: (tc name) :info { | 527 syms ifDefined: (tc name) :info { |
496 saveTempRegs <- _tempRegs | 528 funArgs <- preserveTemps: { |
497 funArgs <- (expr args) map: :arg { compileExpr: arg syms: syms} | 529 (expr args) map: :arg { compileExpr: arg syms: syms} |
498 _tempRegs <- saveTempRegs | 530 } |
499 | 531 |
500 //save registers that need it | 532 //save registers that need it |
501 needSave <- _allTemp filter: :r { | 533 needSave <- _allTemp filter: :r { |
502 not: (_tempRegs contains?: r) | 534 not: (_tempRegs contains?: r) |
503 } | 535 } |
560 | 592 |
561 | 593 |
562 _compileFun <- :fName fun globsyms { | 594 _compileFun <- :fName fun globsyms { |
563 syms <- symbols tableWithParent: globsyms | 595 syms <- symbols tableWithParent: globsyms |
564 | 596 |
565 saveTempRegs <- _tempRegs | 597 preserveTemps: { |
566 foreach: (fun args) :idx arg { | 598 foreach: (fun args) :idx arg { |
567 argname <- (if: (arg startsWith?: ":") { arg from: 1 } else: { arg }) | 599 argname <- (if: (arg startsWith?: ":") { arg from: 1 } else: { arg }) |
568 r <- _tempRegs value | 600 r <- getTemp: |
569 _tempRegs <- _tempRegs tail | 601 syms define: argname r |
570 syms define: argname r | 602 } |
571 } | 603 |
572 | 604 lastexpr <- ((fun expressions) length) - 1 |
573 lastexpr <- ((fun expressions) length) - 1 | 605 |
574 | 606 //TODO: do 2 passes for labels to allow forward references |
575 //TODO: do 2 passes for labels to allow forward references | 607 foreach: (fun expressions) :idx expr { |
576 foreach: (fun expressions) :idx expr { | 608 if: idx != lastexpr && (expr nodeType) = (ast sym) { |
577 if: idx != lastexpr && (expr nodeType) = (ast sym) { | 609 //allow using bare symbols to define labels |
578 //allow using bare symbols to define labels | 610 prog setLabel: (expr name) |
579 prog setLabel: (expr name) | 611 syms define: (expr name) (expr name) |
580 syms define: (expr name) (expr name) | 612 } else: { |
581 } else: { | 613 v <- preserveTemps: { |
582 saveTempRegsExpr <- _tempRegs | 614 compileExpr: expr syms: syms |
583 v <- compileExpr: expr syms: syms | 615 } |
584 _tempRegs <- saveTempRegsExpr | 616 if: idx = lastexpr && (fName != "main") { |
585 if: idx = lastexpr && (fName != "main") { | 617 //move result to a register |
586 //move result to a register | 618 prog add: (inst: "MOV" #[ |
587 prog add: (inst: "MOV" #[ | 619 reg: 0 |
588 reg: 0 | 620 v |
589 v | 621 ]) |
590 ]) | 622 //return instruction |
591 //return instruction | 623 prog add: (inst: "MOV" #[ |
592 prog add: (inst: "MOV" #[ | 624 reg: 8 |
593 reg: 8 | 625 mem: (reg: 7) |
594 mem: (reg: 7) | 626 ]) |
595 ]) | 627 } |
596 } | 628 } |
597 } | 629 } |
598 } | 630 } |
599 saveTempRegs <- _tempRegs | |
600 } | 631 } |
601 | 632 |
602 #{ | 633 #{ |
603 compile <- :code { | 634 compile <- :code { |
604 res <- parser top: code | 635 res <- parser top: code |