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