changeset 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 9cc019c98335
files code/gqc.tp
diffstat 1 files changed, 107 insertions(+), 76 deletions(-) [+]
line wrap: on
line diff
--- a/code/gqc.tp	Sun Jul 27 20:03:34 2014 -0700
+++ b/code/gqc.tp	Sun Jul 27 22:16:01 2014 -0700
@@ -1,14 +1,20 @@
 {
+	reg? <- :val {
+		(object does: val understand?: "isReg?") && (val isReg?)
+	}
+	mem? <- :val {
+		(object does: val understand?: "isMem?") && (val isMem?)
+	}
+	
 	mem <- :_addr {
 		#{
 			addr <- { _addr }
 			string <- { "[" . _addr . "]" }
 			isReg? <- { false }
+			!= <- :other { (not: (mem?: other)) || _addr != (other addr) }
+			= <- :other { (mem?: other) && _addr = (other addr) }
 		}
 	}
-	reg? <- :val {
-		(object does: val understand?: "isReg?") && (val isReg?)
-	}
 	reg <- :_num {
 		#{
 			num <- { _num }
@@ -94,6 +100,26 @@
 	]
 	_tempRegs <- _allTemp
 	
+	getTemp <- {
+		if: (_tempRegs empty?) {
+			//out of regs, use memory
+			loc <- _nextVar
+			_nextVar <- _nextVar + 1
+			mem: loc
+		} else: {
+			r <- _tempRegs value
+			_tempRegs <- _tempRegs tail
+			r
+		}
+	}
+	
+	preserveTemps <- :fun {
+		saveTempRegs <- _tempRegs
+		res <- fun:
+		_tempRegs <- saveTempRegs
+		res
+	}
+	
 	_exprHandlers <- dict hash
 	
 	compileExpr:syms <- :expr :syms {
@@ -118,19 +144,22 @@
 	_opNames set: "xor" "XOR"
 	
 	_exprHandlers set: (ast binary) :expr syms {
-		startTempRegs <- _tempRegs
-		l <- compileExpr: (expr left) syms: syms
-		r <- compileExpr: (expr right) syms: syms
+		l <- 0
+		r <- preserveTemps: {
+			l <- compileExpr: (expr left) syms: syms
+			compileExpr: (expr right) syms: syms
+		}
 		dest <- l
 		if: (reg?: l) {
-			_tempRegs <- startTempRegs filter: :r { r != l }
+			//reallocate temp register used by l
+			//not always safe, needs work
+			_tempRegs <- _tempRegs filter: :r { r != l }
 		} else: {		
-			dest <- startTempRegs value
+			dest <- getTemp:
 			prog add: (inst: "MOV" #[
 				dest
 				l
 			])
-			_tempRegs <- startTempRegs tail
 		}
 		_opNames ifget: (expr op) :i {
 			prog add: (inst: i #[
@@ -161,9 +190,9 @@
 		info <- syms find: (sym name) else: {
 			error: "this should never happen!"
 		}
-		startTempRegs <- _tempRegs
-		v <- compileExpr: (expr assign) syms: syms
-		_tempRegs <- startTempRegs
+		v <- preserveTemps: {
+			compileExpr: (expr assign) syms: syms
+		}
 		dest <- info def
 		prog add: (inst: "MOV" #[
 			dest
@@ -180,9 +209,9 @@
 	}
 	_funHandlers set: "direction!" :args syms {
 		dir <- args value
-		startTempRegs <- _tempRegs
-		v <- compileExpr: dir syms: syms
-		_tempRegs <- startTempRegs
+		v <- preserveTemps: {
+			compileExpr: dir syms: syms
+		}
 		if: (reg: 0) != v {	
 			prog add: (inst: "MOV" #[
 				reg: 0
@@ -208,9 +237,9 @@
 		intNum <- idx + 4
 		_funHandlers set: name :args syms {
 			ghostIdx <- args value
-			startTempRegs <- _tempRegs
-			v <- compileExpr: ghostIdx syms: syms
-			_tempRegs <- startTempRegs
+			v <- preserveTemps: {
+				compileExpr: ghostIdx syms: syms
+			}
 			if: (reg: 0) != v {	
 				prog add: (inst: "MOV" #[
 					reg: 0
@@ -224,10 +253,10 @@
 	_funHandlers set: "mapContentsAt" :args syms {
 		x <- args value
 		y <- (args tail) value
-		startTempRegs <- _tempRegs
-		x <- compileExpr: x syms: syms
-		y <- compileExpr: y syms: syms
-		_tempRegs <- startTempRegs
+		preserveTemps: {
+			x <- compileExpr: x syms: syms
+			y <- compileExpr: y syms: syms
+		}
 		if: (reg: 0) != x {
 			prog add: (inst: "MOV" #[	
 				reg: 0
@@ -247,8 +276,9 @@
 	//allow access to raw instructions
 	foreach: #["MOV" "INC" "DEC" "ADD" "SUB" "MUL" "DIV" "AND" "OR" "XOR" "JLT" "JEQ" "JGT" "HLT"] :idx instName {
 		_funHandlers set: instName :args syms {
-			saveTempRegs <- _tempRegs
-			args <- args map: :arg { compileExpr: arg syms: syms }
+			preserveTemps: {
+				args <- args map: :arg { compileExpr: arg syms: syms }
+			}
 			prog add: (inst: instName args)
 		}
 	}
@@ -262,10 +292,11 @@
 			end <- prog makeLabel: "loop_end"
 			prog setLabel: top
 			
-			saveTempRegs <- _tempRegs
-			l <- compileExpr: (cond left) syms: syms
-			r <- compileExpr: (cond right) syms: syms
-			_tempRegs <- saveTempRegs
+			l <- 0
+			r <- preserveTemps: {
+				l <- compileExpr: (cond left) syms: syms
+				compileExpr: (cond right) syms: syms
+			}
 			
 			ok <- true
 			//we need the inverse check in the instruction since a true condition
@@ -347,9 +378,9 @@
 						prog setLabel: lbl
 						syms define: (expr name) lbl
 					} else: {
-						saveTempRegsExpr <- _tempRegs
-						v <- compileExpr: expr syms: syms
-						_tempRegs <- saveTempRegsExpr
+						v <- preserveTemps: {
+							compileExpr: expr syms: syms
+						}
 					}
 				}
 				prog add: (inst: "MOV" #[
@@ -375,10 +406,11 @@
 			falseLbl <- prog makeLabel: "false"
 			endLbl <- prog makeLabel: "end"
 			
-			saveTempRegs <- _tempRegs
-			l <- compileExpr: (cond left) syms: syms
-			r <- compileExpr: (cond right) syms: syms
-			_tempRegs <- saveTempRegs
+			l <- 0
+			r <- preserveTemps: {
+				l <- compileExpr: (cond left) syms: syms
+				compileExpr: (cond right) syms: syms
+			}
 			
 			ok <- true
 			
@@ -454,9 +486,9 @@
 						prog setLabel: lbl
 						syms define: (expr name) lbl
 					} else: {
-						saveTempRegsExpr <- _tempRegs
-						v <- compileExpr: expr syms: syms
-						_tempRegs <- saveTempRegsExpr
+						v <- preserveTemps: {
+							compileExpr: expr syms: syms
+						}
 					}
 				}
 				prog add: (inst: "MOV" #[
@@ -472,9 +504,9 @@
 						prog setLabel: lbl
 						syms define: (expr name) lbl
 					} else: {
-						saveTempRegsExpr <- _tempRegs
-						v <- compileExpr: expr syms: syms
-						_tempRegs <- saveTempRegsExpr
+						v <- preserveTemps: {
+							compileExpr: expr syms: syms
+						}
 					}
 				}
 				prog setLabel: endLbl
@@ -493,9 +525,9 @@
 				handler: (expr args) syms
 			} else: {
 				syms ifDefined: (tc name) :info {
-					saveTempRegs <- _tempRegs
-					funArgs <- (expr args) map: :arg { compileExpr: arg syms: syms}
-					_tempRegs <- saveTempRegs
+					funArgs <- preserveTemps: {
+						(expr args) map: :arg { compileExpr: arg syms: syms}
+					}
 				
 					//save registers that need it
 					needSave <- _allTemp filter: :r {
@@ -562,41 +594,40 @@
 	_compileFun <- :fName fun globsyms {
 		syms <- symbols tableWithParent: globsyms
 		
-		saveTempRegs <- _tempRegs
-		foreach: (fun args) :idx arg {
-			argname <- (if: (arg startsWith?: ":") { arg from: 1 } else: { arg })
-			r <- _tempRegs value
-			_tempRegs <- _tempRegs tail
-			syms define: argname r
-		}
-		
-		lastexpr <- ((fun expressions) length) - 1
-		
-		//TODO: do 2 passes for labels to allow forward references
-		foreach: (fun expressions) :idx expr {
-			if: idx != lastexpr && (expr nodeType) = (ast sym) {
-				//allow using bare symbols to define labels
-				prog setLabel: (expr name)
-				syms define: (expr name) (expr name)
-			} else: {
-				saveTempRegsExpr <- _tempRegs
-				v <- compileExpr: expr syms: syms
-				_tempRegs <- saveTempRegsExpr
-				if: idx = lastexpr && (fName != "main") {
-					//move result to a register
-					prog add: (inst: "MOV" #[
-						reg: 0
-						v
-					])
-					//return instruction
-					prog add: (inst: "MOV" #[
-						reg: 8
-						mem: (reg: 7)
-					])
+		preserveTemps: {
+			foreach: (fun args) :idx arg {
+				argname <- (if: (arg startsWith?: ":") { arg from: 1 } else: { arg })
+				r <- getTemp:
+				syms define: argname r
+			}
+			
+			lastexpr <- ((fun expressions) length) - 1
+			
+			//TODO: do 2 passes for labels to allow forward references
+			foreach: (fun expressions) :idx expr {
+				if: idx != lastexpr && (expr nodeType) = (ast sym) {
+					//allow using bare symbols to define labels
+					prog setLabel: (expr name)
+					syms define: (expr name) (expr name)
+				} else: {
+					v <- preserveTemps: {
+						compileExpr: expr syms: syms
+					}
+					if: idx = lastexpr && (fName != "main") {
+						//move result to a register
+						prog add: (inst: "MOV" #[
+							reg: 0
+							v
+						])
+						//return instruction
+						prog add: (inst: "MOV" #[
+							reg: 8
+							mem: (reg: 7)
+						])
+					}
 				}
 			}
 		}
-		saveTempRegs <- _tempRegs
 	}
 	
 	#{