changeset 352:f74ce841fd1e

Produce something resembling correct il from low level dialect
author Michael Pavone <pavone@retrodev.com>
date Mon, 13 Apr 2015 22:42:27 -0700
parents 04ba2118c5fe
children 95bc24c729e6
files modules/il.tp modules/llcompile.tp
diffstat 2 files changed, 228 insertions(+), 65 deletions(-) [+]
line wrap: on
line diff
--- a/modules/il.tp	Mon Apr 13 22:41:00 2015 -0700
+++ b/modules/il.tp	Mon Apr 13 22:42:27 2015 -0700
@@ -210,6 +210,14 @@
 		w <- { word }
 		l <- { long }
 		q <- { quad }
+		
+		sizeFromBytes <- :bytes {
+			if: bytes < 4 {
+				if: bytes = 1 { b } else: { w }
+			} else: {
+				if: bytes = 4 { l } else: { q }
+			}
+		}
 
 		eq <- { _eq }
 		neq <- { _neq }
@@ -296,7 +304,7 @@
 		}
 
 		cmp <- :ina inb size {
-			op2: _cmp a: ina out: inb size: size
+			op2: _cmp in: ina out: inb size: size
 		}
 
 		band <- :ina inb out size {
@@ -511,9 +519,11 @@
 				opcode <- { _bool }
 				cond <- { _cond }
 				out <- { _out }
-				name <- { _names get: _save }
+				name <- { _names get: _bool }
 				numops <- { 0 }
-
+				string <- {
+					name . " " . cond . " " . out
+				}
 			}
 		}
 
--- a/modules/llcompile.tp	Mon Apr 13 22:41:00 2015 -0700
+++ b/modules/llcompile.tp	Mon Apr 13 22:42:27 2015 -0700
@@ -7,16 +7,20 @@
 		}
 	}
 
-	_notError <- :vals ifnoterr {
+	_notError:else <- :vals ifnoterr iferror {
 		if: (object does: vals understand?: "find") {
 			maybeErr <- vals find: :val {
-				(object does: val understand?: "isError?") && val isError?
+				(object does: val understand?: "isError?") && (val isError?)
 			}
 			maybeErr value: :err {
-				err
+				iferror: err
 			} none: ifnoterr
 		} else: ifnoterr
 	}
+	
+	_notError <- :vals ifnoterr {
+		_notError: vals ifnoterr else: :e { e }
+	}
 
 	_ilFun <- :_name {
 		_buff <- #[]
@@ -43,6 +47,38 @@
 			buffer <- { _buff }
 		}
 	}
+	
+	_sizeMap <- dict hash
+	_sizeMap set: "8" (il b)
+	_sizeMap set: "16" (il w)
+	_sizeMap set: "32" (il l)
+	_sizeMap set: "64" (il q)
+	
+	_parseType <- :expr {
+		if: (expr nodeType) = (ast sym) {
+			name <- expr name
+			_signed? <- true
+			if: (name startsWith?: "u") {
+				_signed? <- false
+				name <- name from: 1
+			}
+			if: (name startsWith?: "int") &&  ((name length) <= 5) {
+				size <- name from: 3
+				_sizeMap ifget: size :llsize {
+					#{
+						size <- llsize
+						signed? <- _signed?
+					}
+				} else: {
+					_compileError: "LL integer type " . (expr name) . " has an invalid size"
+				}
+			} else: {
+				_compileError: "LL Type " . (expr name) . " not implemented yet"
+			}
+		} else: {
+			_compileError: "LL Type with node type " . (expr nodeType) . " not implemented yet"
+		}
+	}
 
 	_exprHandlers <- false
 	_compileExpr:syms:ilfun:dest <- :expr :syms :ilf :dst {
@@ -58,35 +94,51 @@
 
 	_compileBinary <- :expr syms ilf assignTo {
 		_assignSize? <- false
-		_asize <- 0
-		dest <- option value: assignTo :asn {
+		_asize <- il b
+		dest <- assignTo value: :asn {
 			_assignSize? <- true
 			_asize <- asn size
 			asn
 		} none: {
-			ilf getReg
+			#{
+				val <- ilf getReg
+				signed? <- true
+				size <- _asize
+			}
 		}
-		l <- _compileExpr: (expr left) syms: syms ilfun: ilf assign: (option value: dest)
-		r <- _compileExpr: (expr right) syms: syms ilfun: ilf assign: (option none)
+		l <- _compileExpr: (expr left) syms: syms ilfun: ilf dest: (option value: dest)
+		r <- _compileExpr: (expr right) syms: syms ilfun: ilf dest: (option none)
 		_notError: [(l) (r)] {
 			lv <- l val
 			ls <- l size
 			rv <- r val
 			rs <- r size
-			_size <- if: ls > rs { ls } else: { rs }
-			_signed <- (ls signed?) || (rs signed?)
+			_size <- if: ls > rs { 
+				ls
+				//TODO: sign/zero extend rv
+			} else: {
+				rs
+				//TODO: sign/zero extend lv if rs > ls
+			}
+			if: _assignSize? && _asize > _size {
+				_size <- _asize
+				//TODO: sign/zero extend result
+			}
+			_signed <- (l signed?) || (r signed?)
 			_opMap ifget: (expr op) :ingen {
 				ilf add: (ingen: lv rv (dest val) _size)
 				#{
-					val <- dest
+					val <- dest val
 					size <- _size
 					signed? <- _signed
 				}
 			} else: {
-				_compOps ifget: (expr op) :cond {
-					ilf add: (il bool: cond dest)
+				_compOps ifget: (expr op) :condFun {
+					ilf add: (il cmp: lv rv _size)
+					cond <- condFun: _signed
+					ilf add: (il bool: cond (dest val))
 					#{
-						val <- dest
+						val <- dest val
 						size <- il b
 						signed? <- false
 					}
@@ -100,11 +152,29 @@
 
 	}
 	_compileInt <- :expr syms ilf assignTo {
-		expr
+		sz <- il sizeFromBytes: (expr size)
+		assignTo value: :asn {
+			ilf add: (il mov: (expr val) (asn val) sz)
+			#{
+				val <- asn val
+				signed? <- expr signed?
+				size <- sz
+			}
+		} none: {
+			#{
+				val <- expr val
+				signed? <- expr signed?
+				size <- sz
+			}
+		}
 	}
 	_compileSym <- :expr syms ilf assignTo {
-		syms ifDefined: (expr name) :def {
-			def
+		syms ifDefined: (expr name) :syminfo {
+			if: (syminfo isLocal?) {
+				syminfo def
+			} else: {
+				print: "Symbol " . (expr name) . " is not local and other types are not yet supported in LL dialect\n"
+			}
 		} else: {
 			_compileError: "Symbol " . (expr name) . " is not defined in " . (ilf name)
 		}
@@ -120,21 +190,36 @@
 				if: (blockArg nodeType) != (ast lambda) {
 					_compileError: "second argument to if must be a lambda"
 				} else: {
-					ilf add: (il cmp: condArg 0 (condArg size))
-					//TODO: Deal with if in return position
+					ilf add: (il cmp: 0 (cond val) (cond size))
+					dest <- if: (assignTo none?) {
+						option value: #{
+							val <- ilf reg
+							//TODO: FIXME
+							size <- il q
+							signed? <- true
+						}
+					} else: {
+						assignTo
+					}
 					ilf startBlock
 					foreach: (blockArg expressions) :idx expr{
-						_compileExpr: expr syms: syms ilfun: ilf dest: (option none)
+						asn <- if: idx = ((blockArg expressions) length) - 1 {
+							dest
+						} else: {
+							option none
+						}
+						_compileExpr: expr syms: syms ilfun: ilf dest: asn
 					}
 					block <- ilf popBlock
 					ilf add: (il skipIf: (il neq) block)
+					dest value: :d { d } none: { _compileError: "Something went wrong" }
 				}
 			}
 		}
 	}
 	_compileIfElse <- :expr syms ilf assignTo {
-		if: ((expr args) length) != 2 {
-			_compileError: "if takes exactly 2 arguments" 0
+		if: ((expr args) length) != 3 {
+			_compileError: "if:else takes exactly 3 arguments" 0
 		} else: {
 			condArg <- (expr args) value
 			blockArg <- ((expr args) tail) value
@@ -147,19 +232,39 @@
 					if: (elseArg nodeType) != (ast lambda) {
 						_compileError: "third argument to if:else must be a lambda"
 					} else: {
-						ilf add: (il cmp: condArg 0 (condArg size))
-						//TODO: Deal with if:else in return position
+						ilf add: (il cmp: 0 (cond val) (cond size))
+						dest <- if: (assignTo none?) {
+							option value: #{
+								val <- ilf reg
+								//TODO: FIXME
+								size <- il q
+								signed? <- true
+							}
+						} else: {
+							assignTo
+						}
 						ilf startBlock
 						foreach: (blockArg expressions) :idx expr {
-							_compileExpr: expr syms: syms ilfun: ilf dest: (option none)
+							asn <- if: idx = ((blockArg expressions) length) - 1 {
+								dest
+							} else: {
+								option none
+							}
+							_compileExpr: expr syms: syms ilfun: ilf dest: asn
 						}
 						block <- ilf popBlock
 						ilf startBlock
 						foreach: (elseArg expressions) :idx expr {
+							asn <- if: idx = ((elseArg expressions) length) - 1 {
+								dest
+							} else: {
+								option none
+							}
 							_compileExpr: expr syms: syms ilfun: ilf dest: (option none)
 						}
 						elseblock <- ilf popBlock
 						ilf add: (il skipIf: (il neq) block else: elseblock)
+						dest value: :d { d } none: { _compileError: "Something went wrong" }
 					}
 				}
 			}
@@ -171,13 +276,29 @@
 			handler <- _funMap get: ((expr tocall) name) else: { false }
 			handler: expr syms ilf assignTo
 		} else: {
-			ctocall <- _compileExpr: (expr tocall) syms: syms ilfuN: ilf dest: (option none)
+			ctocall <- if: ((expr tocall) nodeType) = (ast sym) {
+				ctocall <- (expr tocall) name
+			} else: {
+				_compileExpr: (expr tocall) syms: syms ilfun: ilf dest: (option none)
+			}
 			cargs <- (expr args) map: :arg {
 				_compileExpr: arg syms: syms ilfun: ilf dest: (option none)
 			}
 			_notError: ctocall | cargs {
-				ilf add: (il call: ctocall withArgs: cargs)
-				il retr
+				ilf add: (il call: ctocall withArgs: (cargs map: :arg { arg val } ))
+				
+				retval <- assignTo value: :asn {
+					ilf add: (il mov: (il retr) (asn val) (asn size))
+					asn
+				} none: {
+					#{
+						val <- il retr
+						//TODO: Use correct values based on return type
+						size <- il q
+						signed? <- true
+					}
+				}
+				retval
 			}
 		}
 	}
@@ -188,7 +309,7 @@
 			value <- _compileExpr: (expr assign) syms: syms ilfun: ilf dest: dest
 			_notError: [value] {
 				//TODO: adjust size of value if necessary
-				ilf add: (il mov: (value val) (dest val) (dest size))
+				//ilf add: (il mov: (value val) (dest val) (dest size))
 				value
 			}
 		}
@@ -254,38 +375,54 @@
 				if: (arg startsWith?: ":") {
 					arg <- arg from: 1
 				}
-				argnames set: arg true
+				argnames set: arg idx
 			}
 			ilf <- _ilFun: name
 			_nextReg <- 0
-			foreach: vars :idx var {
+			varErrors <- (vars expressions) fold: [] with: :acc var {
 				type <- _parseType: (var assign)
-				varname <- ((var to) name)
-				v <- argnames ifget: varname :argnum {
-					il arg: argnum
-				} else: {
-					ilf getReg
-				}
-				syms define: varname #{
-					val <- v
-					size <- (type size)
+				_notError: [type] {
+					varname <- ((var to) name)
+					v <- argnames ifget: varname :argnum {
+						il arg: argnum
+					} else: {
+						ilf getReg
+					}
+					syms define: varname #{
+						val <- v
+						size <- (type size)
+						signed? <- (type signed?)
+					}
+					acc
+				} else: :err {
+					err | acc
 				}
 			}
-			last <- option none
-			numexprs <- code length
-			foreach: code :idx expr {
-				asn <- option none
-				if: idx = numexprs - 1 {
-					option value: (il retr)
+			if: (varErrors empty?) {
+				last <- option none
+				numexprs <- (code expressions) length
+				foreach: (code expressions) :idx expr {
+					asn <- if: idx = numexprs - 1 {
+						option value: #{
+							val <- ilf getReg
+							//TODO: FIxme
+							size <- il q
+							signed? <- true
+						}
+					} else: {
+						option none
+					}
+					last <- option value: (_compileExpr: expr syms: syms ilfun: ilf dest: asn)
 				}
-				last <- option value: (_compileExpr: expr syms: syms ilfun: ilf dest: asn)
+				last value: :v {
+					ilf add: (il return: (v val) (v size))
+				} none: {
+					ilf add: (il return: 0 (il l))
+				}
+				ilf
+			} else: {
+				varErrors
 			}
-			last value: :v {
-				ilf add: (il return: (v val) (v size))
-			} none: {
-				ilf add: (il return: 0 (il l))
-			}
-			ilf
 		}
 
 		compileText <- :text {
@@ -295,18 +432,19 @@
 				if: (tree nodeType) = obj {
 					errors <- []
 					syms <- symbols table
-					functions <- tree messages fold: [] :curfuncs msg {
+					functions <- (tree messages) fold: [] with: :curfuncs msg {
 						if: (msg nodeType) = call {
 							if: ((msg tocall) name) = "llFun:withVars:andCode" {
 								if: ((msg args) length) = 3 {
-									fname <- ((msg args) get: 0) name
+									fname <- ((msg args) value) name
 									syms define: fname #{
 										type <- "topfun"
 									}
+									rest <- (msg args) tail
 									#{
 										name <- fname
-										vars <- (msg args) get: 1
-										body <- (msg args) get: 2
+										vars <- rest value
+										body <- (rest tail) value
 									} | curfuncs
 								} else: {
 									errors <- (
@@ -328,15 +466,28 @@
 						}
 					}
 					if: (errors empty?) {
+						errors <- []
 						fmap <- functions fold: (dict hash) with: :acc func {
-							_notError: acc {
-								ilf <- llFun: (func name) syms: syms vars: (func vars) code: (func body)
-								_notError: ilf {
-									acc set: (func name) (ilf buffer)
+							ilf <- llFun: (func name) syms: syms vars: (func vars) code: (func body)
+							_notError: ilf {
+								acc set: (func name) (ilf buffer)
+							} else: {
+								errors <- ilf . errors
+							}
+							acc
+						}
+						if: (errors empty?) {
+							foreach: fmap :name instarr {
+								print: "Function: " . name . "\n"
+								foreach: instarr :_ inst {
+									print: "\t" . inst . "\n"
 								}
 							}
+							print: "Translating IL to x86\n"
+							il toBackend: fmap x86
+						} else: {
+							errors
 						}
-						fmap toBackend: x86
 					} else: {
 						errors
 					}
@@ -356,6 +507,8 @@
 					ba <- bytearray executableFromBytes: mcode
 					arg <- if: (length: args) > 2 { int32: (args get: 2) } else: {0}
 					ba runWithArg: (arg i64)
+				} else: :err {
+					(file stderr) write: (err msg) . "\n"
 				}
 			} else: {
 				(file stderr) write: "Usage: llcompile FILE\n"