changeset 200:49bca6487178

Add a save instruction around calls if there are caller-saved registers live at call-time. Fix to2Op for skipIf and save instructions.
author Mike Pavone <pavone@retrodev.com>
date Tue, 27 Aug 2013 23:02:19 -0700
parents 3b13ced3b562
children d2e0664ba73e
files modules/il.tp
diffstat 1 files changed, 55 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/modules/il.tp	Tue Aug 27 22:53:30 2013 -0700
+++ b/modules/il.tp	Tue Aug 27 23:02:19 2013 -0700
@@ -57,7 +57,7 @@
 				_inb recordUsage: tracker at: 0 | address withSize: _size
 				_out recordUsage: tracker at: 1 | address withSize: _size
 			}
-			assignRegs:withSource <- :assignments :regSrc {
+			assignRegs:at:withSource:andUsage <- :assignments :at :regSrc :usage {
 				newa <- if: (not: (_ina isInteger?)) {
 					_ina assign: assignments withSource: regSrc
 				} else: { _ina }
@@ -82,7 +82,7 @@
 				}
 				_out recordUsage: tracker at: 1 | address withSize: _size
 			}
-			assignRegs:withSource <- :assignments :regSrc {
+			assignRegs:at:withSource:andUsage <- :assignments :at :regSrc :usage {
 				newin <- if: (not: (_in isInteger?)) {
 					_in assign: assignments withSource: regSrc
 				} else: { _in }
@@ -104,7 +104,7 @@
 					_arg recordUsage: tracker at: address withSize: _size
 				}
 			}
-			assignRegs:withSource <- :assignments :regSrc {
+			assignRegs:at:withSource:andUsage <- :assignments :at :regSrc :usage {
 				newarg <- if: (not: (_arg isInteger?)) {
 					_arg assign: assignments withSource: regSrc
 				} else: { _arg }
@@ -350,7 +350,7 @@
 						arg recordUsage: tracker at: address withSize: q
 					}
 				}
-				assignRegs:withSource <- :assignments :regSrc {
+				assignRegs:at:withSource:andUsage <- :assignments :address :regSrc :usage {
 					newtarget <- if: (_target isString?) { _target } else: {
 						_target assign: assignments withSource: regSrc
 					}
@@ -359,9 +359,21 @@
 							arg assign: assignments withSource: regSrc
 						}
 					}
-					//TODO: Save caller-save regs if necessary
-					//TODO: Add instructions for moving arguments to proper regs/stack locations
-					call: newtarget withArgs: newargs
+					newcall <- call: newtarget withArgs: newargs
+					regSrc returnAll
+					raddress <- address reverse
+					foreach: (usage liveArgsAt: raddress) :_ arg {
+						regSrc allocArg: (arg num)
+					}
+					foreach: (usage liveRegsAt: raddress) :_ reg {
+						regSrc allocSpecific: (assignments get: reg)
+					}
+					tosave <- regSrc needSaveForCall
+					if: (tosave length) > 0 {
+						save: tosave #[newcall]
+					} else: {
+						newcall
+					}
 				}
 			}
 		}
@@ -388,12 +400,16 @@
 						inst recordUsage: tracker at: idx | address
 					}
 				}
-				assignRegs:withSource <- :assignments :regSrc {
-					newskip <- _toskip map: :inst {
-						inst assignRegs: assignments withSource: regSrc
+				assignRegs:at:withSource:andUsage <- :assignments :address :regSrc :usage {
+					newskip <- #[]
+					foreach: _toskip :idx inst {
+						newskip append: (inst assignRegs: assignments at: idx | address  withSource: regSrc andUsage: usage)
 					}
 					skipIf: _cond newskip
 				}
+				to2OpInst <- {
+					skipIf: _cond (to2Op: _toskip)
+				}
 			}
 		}
 		save <- :regs :scope{
@@ -408,6 +424,9 @@
 					}
 					name . " " . (regs join: " ") . " {" . block . "}"
 				}
+				to2OpInst <- {
+					save: regs (to2Op: scope)
+				}
 			}
 		}
 
@@ -435,6 +454,15 @@
 			}
 
 			_maxUses <- 0
+			liveFrom:to <- :regs :from :to {
+				live <- #[]
+				foreach: regs :reg usage {
+					if: ((usage lastUsage) addrGreatEq: from) && ((usage firstUsage) addrLessEq: to) {
+						live append: reg
+					}
+				}
+				live
+			}
 			regUsage <- #{
 				reg:usedAt:withSize <- :reg :address :size {
 					raddress <- address reverse
@@ -453,6 +481,14 @@
 					}
 					usage usedAt: raddress withSize: size
 				}
+
+				liveRegsAt <- :address {
+					_regMap liveFrom: address to: address
+				}
+				liveArgsAt <- :address {
+					_argMap liveFrom: address to: address
+				}
+
 				print <- {
 					foreach: _regMap :reg usage {
 						print: (string: reg) . " | " . (string: usage) . "\n"
@@ -501,16 +537,6 @@
 				greateq
 			}
 
-			liveFrom:to <- :regs :from :to {
-				live <- #[]
-				foreach: regs :reg usage {
-					if: ((usage lastUsage) addrGreatEq: from) && ((usage firstUsage) addrLessEq: to) {
-						live append: reg
-					}
-				}
-				live
-			}
-
 			_assignments <- dict linear
 			curuses <- _maxUses
 			while: { curuses > 0 && (_assignments length) < (_regMap length) } do: {
@@ -540,11 +566,11 @@
 				print: (string: reg) . " = " . assign . "\n"
 			}
 
-			withassign <- map: instarr :inst {
-				inst assignRegs: _assignments withSource: regSrc
+			withassign <- #[]
+			foreach: instarr :idx inst {
+				withassign append: (inst assignRegs: _assignments at: [idx] withSource: regSrc andUsage: regUsage)
 			}
 			psave <- regSrc needSaveProlog
-			print: "Regs that need saving in prolog: " . (psave join: ",") . "\n"
 			if: (psave length) > 0 {
 				withassign <- #[save: psave withassign]
 			}
@@ -573,7 +599,11 @@
 						}
 						newarr append: (op1: (inst opcode) val: (inst out) size: (inst size))
 					} else: {
-						newarr append: inst
+						if: (inst opcode) = _skipif || (inst opcode) = _save {
+							newarr append: (inst to2OpInst)
+						} else: {
+							newarr append: inst
+						}
 					}
 				}
 			}
@@ -598,7 +628,7 @@
 			}
 			print: "\n\nUsage:\n\n"
 			fiba <- allocRegs: fib withSource: (x86 regSource)
-			print: "\n\nAFter Assignment:\n\n"
+			print: "\n\nAfter Assignment:\n\n"
 			foreach: fiba :idx inst {
 				print: (string: inst) . "\n"
 			}