diff --git a/compiler/asmgen.nim b/compiler/asmgen.nim new file mode 100644 index 000000000..14ba06c06 --- /dev/null +++ b/compiler/asmgen.nim @@ -0,0 +1,258 @@ +# +# +# The Nim Compiler +# (c) Copyright 2015 Dominik Picheta +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# +import cgendata, ast, strutils, os, extccomp, options, ropes, strutils, astalgo +import msgs + +type + OpCode = enum + opcPush, opcMov, opcPop, opcRet, opcAdd, opcSub, opcLeave, opcCmp, opcJe, + opcJmp, opcJne + + Register = enum + regRAX, regRDI, regRSI, regRDX, regRCX, regR8, regR9, + regRBP, regRSP + + ProcSection = enum + prcHeader, prcBody + + AsmProc = ref object + stackSlotsCounter: int ## How many stack slots have been used by vars. + owner: PSym ## The owning nkProcDef + code: array[ProcSection, string] + ifStmtNum: int + elifStmtNum: int + +const + noOperand = {opcRet, opcLeave} + oneOperand = {opcPush, opcPop, opcJe, opcJmp, opcJne} + twoOperands = {opcMov, opcAdd, opcSub, opcCmp} + +template codeBody(): expr = + context.code[prcBody] + +template codeHeader(): expr = + context.code[prcHeader] + +proc `$`(opc: OpCode): string = + result = system.`$`(opc)[3 .. -1].toUpper + +proc addN(s: var string, y: string) = + s.add y & "\n" + +proc addIndentN(s: var string, y: string) = + s.addN "\t" & y + +proc emit(s: var string, opc: OpCode) = + assert opc in noOperand + s.addIndentN($opc) + +proc emit(s: var string, opc: OpCode, x: string) = + assert opc in oneOperand + s.addIndentN($opc & " " & x) + +proc emit(s: var string, opc: OpCode, x, y: string) = + assert opc in twoOperands + s.addIndentN($opc & " " & x & ", " & y) + +proc `$`(reg: Register): string = + result = system.`$`(reg)[3 .. -1].toUpper + +proc getProcName(context: AsmProc): string = + context.owner.loc.r.ropeToStr + +proc getRegisterParam(pos: int): Register = + # TODO Windows + const paramToRegister = [regRDI, regRSI, regRDX, regRCX, regR8, regR9] + if pos > 5: internalError("TODO: Too many proc params") + return paramToRegister[pos] + +proc getBlockLabel(context: AsmProc, sym: PSym): string = + context.getProcName() & '.' & sym.name.s & '_' & sym.id + +proc toOperand(n: PNode): string = + case n.kind + of nkSym: + case n.sym.kind + of skParam: + return $getRegisterParam(n.sym.position) + of skVar: + let name = n.sym.name.s & '_' & $n.sym.id + return "[" & $regRSP & "+" & name & "]" + else: + assert false, $n.sym.kind + of nkIntLit: + return $n.intVal + else: + assert false, $n.kind + +proc genAsgn(context: AsmProc, n: PNode, dest: Register) +proc genMagicExpr(context: AsmProc, magic: TMagic, args: seq[PNode], + dest: Register) = + for i in 0 ..