summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2023-10-29 21:53:28 +0100
committerGitHub <noreply@github.com>2023-10-29 21:53:28 +0100
commit403e0118ae8d099384e9bd6a046c2114538503b8 (patch)
treeadbd902dd6bd2f527c4da61ebd1ae548e292037d
parente17237ce9dbf5410623e9d510217e7817bf4fd89 (diff)
downloadNim-403e0118ae8d099384e9bd6a046c2114538503b8.tar.gz
NIR: progress (#22884)
-rw-r--r--compiler/nir/ast2ir.nim32
-rw-r--r--compiler/nir/nirinsts.nim2
-rw-r--r--compiler/nir/nirvm.nim81
3 files changed, 96 insertions, 19 deletions
diff --git a/compiler/nir/ast2ir.nim b/compiler/nir/ast2ir.nim
index b1a90e9bf..f3b68474b 100644
--- a/compiler/nir/ast2ir.nim
+++ b/compiler/nir/ast2ir.nim
@@ -26,7 +26,6 @@ type
     types: TypesCon
     module*: PSym
     graph*: ModuleGraph
-    symnames*: SymNames
     nativeIntId, nativeUIntId: TypeId
     strPayloadId: (TypeId, TypeId)
     idgen: IdGenerator
@@ -72,10 +71,11 @@ proc initModuleCon*(graph: ModuleGraph; config: ConfigRef; idgen: IdGenerator; m
   result.strPayloadId = strPayloadPtrType(result.types, result.nirm.types)
 
 proc initProcCon*(m: ModuleCon; prc: PSym; config: ConfigRef): ProcCon =
-  ProcCon(m: m, sm: initSlotManager({}), prc: prc, config: config,
+  result = ProcCon(m: m, sm: initSlotManager({}), prc: prc, config: config,
     lit: m.nirm.lit, idgen: m.idgen,
     options: if prc != nil: prc.options
              else: config.options)
+  result.exitLabel = newLabel(result.labelGen)
 
 proc toLineInfo(c: var ProcCon; i: TLineInfo): PackedLineInfo =
   var val: LitId
@@ -121,6 +121,9 @@ proc freeTemp(c: var ProcCon; tmp: Value) =
   if s != SymId(-1):
     freeTemp(c.sm, s)
 
+proc freeTemps(c: var ProcCon; tmps: openArray[Value]) =
+  for t in tmps: freeTemp(c, t)
+
 proc typeToIr(m: ModuleCon; t: PType): TypeId =
   typeToIr(m.types, m.nirm.types, t)
 
@@ -482,6 +485,7 @@ proc genCall(c: var ProcCon; n: PNode; d: var Value) =
       rawCall c, info, opc, tb, args
   else:
     rawCall c, info, opc, tb, args
+  freeTemps c, args
 
 proc genRaise(c: var ProcCon; n: PNode) =
   let info = toLineInfo(c, n.info)
@@ -694,6 +698,16 @@ template valueIntoDest(c: var ProcCon; info: PackedLineInfo; d: var Value; typ:
       copyTree c.code, d
       body(c.code)
 
+template constrIntoDest(c: var ProcCon; info: PackedLineInfo; d: var Value; typ: PType; body: untyped) =
+  var tmp = default(Value)
+  body(Tree tmp)
+  if isEmpty(d):
+    d = tmp
+  else:
+    buildTyped c.code, info, Asgn, typeToIr(c.m, typ):
+      copyTree c.code, d
+      copyTree c.code, tmp
+
 proc genBinaryOp(c: var ProcCon; n: PNode; d: var Value; opc: Opcode) =
   let info = toLineInfo(c, n.info)
   let tmp = c.genx(n[1])
@@ -702,7 +716,7 @@ proc genBinaryOp(c: var ProcCon; n: PNode; d: var Value; opc: Opcode) =
   template body(target) =
     buildTyped target, info, opc, t:
       if optOverflowCheck in c.options and opc in {CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, CheckedMod}:
-        c.code.addLabel info, CheckedGoto, c.exitLabel
+        target.addLabel info, CheckedGoto, c.exitLabel
       copyTree target, tmp
       copyTree target, tmp2
   intoDest d, info, t, body
@@ -2060,7 +2074,7 @@ proc genObjOrTupleConstr(c: var ProcCon; n: PNode; d: var Value; t: PType) =
         target.addImmediateVal info, 1 # "name" field is at position after the "parent". See system.nim
         target.addStrVal c.lit.strings, info, t.skipTypes(abstractInst).sym.name.s
 
-  valueIntoDest c, info, d, t, body
+  constrIntoDest c, info, d, t, body
 
 proc genRefObjConstr(c: var ProcCon; n: PNode; d: var Value) =
   if isEmpty(d): d = getTemp(c, n)
@@ -2110,7 +2124,7 @@ proc genArrayConstr(c: var ProcCon; n: PNode, d: var Value) =
         copyTree target, tmp
         c.freeTemp(tmp)
 
-  valueIntoDest c, info, d, n.typ, body
+  constrIntoDest c, info, d, n.typ, body
 
 proc genAsgn2(c: var ProcCon; a, b: PNode) =
   assert a != nil
@@ -2140,7 +2154,7 @@ proc genVarSection(c: var ProcCon; n: PNode) =
         #assert t.int >= 0, typeToString(s.typ) & (c.config $ n.info)
         let symId = toSymId(c, s)
         c.code.addSummon toLineInfo(c, a.info), symId, t, opc
-        c.m.symnames[symId] = c.lit.strings.getOrIncl(s.name.s)
+        c.m.nirm.symnames[symId] = c.lit.strings.getOrIncl(s.name.s)
         if a[2].kind != nkEmpty:
           genAsgn2(c, vn, a[2])
       else:
@@ -2347,7 +2361,7 @@ proc genParams(c: var ProcCon; params: PNode; prc: PSym) =
       assert t.int != -1, typeToString(s.typ)
       let symId = toSymId(c, s)
       c.code.addSummon toLineInfo(c, params[i].info), symId, t, SummonParam
-      c.m.symnames[symId] = c.lit.strings.getOrIncl(s.name.s)
+      c.m.nirm.symnames[symId] = c.lit.strings.getOrIncl(s.name.s)
 
 proc addCallConv(c: var ProcCon; info: PackedLineInfo; callConv: TCallingConvention) =
   template ann(s: untyped) = c.code.addPragmaId info, s
@@ -2380,7 +2394,7 @@ proc genProc(cOuter: var ProcCon; prc: PSym) =
   build c.code, info, ProcDecl:
     let symId = toSymId(c, prc)
     addSymDef c.code, info, symId
-    c.m.symnames[symId] = c.lit.strings.getOrIncl(prc.name.s)
+    c.m.nirm.symnames[symId] = c.lit.strings.getOrIncl(prc.name.s)
     addCallConv c, info, prc.typ.callConv
     if sfCompilerProc in prc.flags:
       build c.code, info, PragmaPair:
@@ -2412,6 +2426,8 @@ proc genProc(cOuter: var ProcCon; prc: PSym) =
     genParams(c, prc.typ.n, prc)
     gen(c, body)
     patch c, body, c.exitLabel
+    build c.code, info, Ret:
+      discard
 
   #copyTree cOuter.code, c.code
   dec cOuter.m.inProc
diff --git a/compiler/nir/nirinsts.nim b/compiler/nir/nirinsts.nim
index 7b281e876..873004408 100644
--- a/compiler/nir/nirinsts.nim
+++ b/compiler/nir/nirinsts.nim
@@ -380,7 +380,7 @@ proc addNilVal*(t: var Tree; info: PackedLineInfo; typ: TypeId) =
 proc store*(r: var RodFile; t: Tree) = storeSeq r, t.nodes
 proc load*(r: var RodFile; t: var Tree) = loadSeq r, t.nodes
 
-proc escapeToNimLit(s: string; result: var string) =
+proc escapeToNimLit*(s: string; result: var string) =
   result.add '"'
   for c in items s:
     if c < ' ' or int(c) >= 128:
diff --git a/compiler/nir/nirvm.nim b/compiler/nir/nirvm.nim
index b58f48272..1f2f4e326 100644
--- a/compiler/nir/nirvm.nim
+++ b/compiler/nir/nirvm.nim
@@ -30,6 +30,8 @@ type
     TypedM,   # with type ID
     PragmaIdM, # with Pragma ID, possible values: see PragmaKey enum
     NilValM,
+    AllocLocals,
+    SummonParamM,
     GotoM,
     CheckedGotoM, # last atom
 
@@ -43,8 +45,6 @@ type
     SelectListM,  # (values...)
     SelectValueM, # (value)
     SelectRangeM, # (valueA..valueB)
-    AllocLocals,
-    SummonParamM,
 
     AddrOfM,
     ArrayAtM, # (elemSize, addr(a), i)
@@ -144,6 +144,11 @@ proc debug(bc: Bytecode; info: PackedLineInfo) =
   let (litId, line, col) = bc.m.man.unpack(info)
   echo bc.m.lit.strings[litId], ":", line, ":", col
 
+proc debug(bc: Bytecode; t: Tree; n: NodePos) =
+  var buf = ""
+  toString(t, n, bc.m.lit.strings, bc.m.lit.numbers, bc.m.symnames, buf)
+  echo buf
+
 template `[]`(t: seq[Instr]; n: CodePos): Instr = t[n.int]
 
 proc traverseObject(b: var Bytecode; t, offsetKey: TypeId) =
@@ -307,6 +312,50 @@ iterator triples*(bc: Bytecode; n: CodePos): (uint32, int, CodePos) =
     yield (offset, size, val)
     nextChild bc, pos
 
+proc toString*(t: Bytecode; pos: CodePos;
+               r: var string; nesting = 0) =
+  if r.len > 0 and r[r.len-1] notin {' ', '\n', '(', '[', '{'}:
+    r.add ' '
+
+  case t[pos].kind
+  of ImmediateValM:
+    r.add $t[pos].operand
+  of IntValM:
+    r.add "IntVal "
+    r.add $t.m.lit.numbers[LitId t[pos].operand]
+  of StrValM:
+    escapeToNimLit(t.m.lit.strings[LitId t[pos].operand], r)
+  of LoadLocalM, LoadGlobalM, LoadProcM, AllocLocals:
+    r.add $t[pos].kind
+    r.add ' '
+    r.add $t[pos].operand
+  of PragmaIdM:
+    r.add $cast[PragmaKey](t[pos].operand)
+  of TypedM:
+    r.add "T<"
+    r.add $t[pos].operand
+    r.add ">"
+  of NilValM:
+    r.add "NilVal"
+  of GotoM, CheckedGotoM:
+    r.add $t[pos].kind
+    r.add " L"
+    r.add $t[pos].operand
+  else:
+    r.add $t[pos].kind
+    r.add "{\n"
+    for i in 0..<(nesting+1)*2: r.add ' '
+    for p in sons(t, pos):
+      toString t, p, r, nesting+1
+    r.add "\n"
+    for i in 0..<nesting*2: r.add ' '
+    r.add "}"
+
+proc debug(b: Bytecode; pos: CodePos) =
+  var buf = ""
+  toString(b, pos, buf)
+  echo buf
+
 type
   Preprocessing = object
     u: ref Universe
@@ -421,6 +470,7 @@ proc preprocess(c: var Preprocessing; bc: var Bytecode; t: Tree; n: NodePos; fla
       for ch in sonsFrom1(t, n):
         preprocess(c, bc, t, ch, {WantAddr})
   of ObjConstr:
+    #debug bc, t, n
     var i = 0
     let typ = t[n.firstSon].typeId
     build bc, info, ObjConstrM:
@@ -543,8 +593,9 @@ proc preprocess(c: var Preprocessing; bc: var Bytecode; t: Tree; n: NodePos; fla
     if t[src].kind in {Call, IndirectCall}:
       # No support for return values, these are mapped to `var T` parameters!
       build bc, info, CallM:
+        preprocess(c, bc, t, src.firstSon, {WantAddr})
         preprocess(c, bc, t, dest, {WantAddr})
-        for ch in sons(t, src): preprocess(c, bc, t, ch, {WantAddr})
+        for ch in sonsFrom1(t, src): preprocess(c, bc, t, ch, {WantAddr})
     elif t[src].kind in {CheckedCall, CheckedIndirectCall}:
       build bc, info, CheckedCallM:
         preprocess(c, bc, t, src.firstSon, {WantAddr})
@@ -644,6 +695,11 @@ proc preprocess(c: var Preprocessing; bc: var Bytecode; t: Tree; n: NodePos; fla
       bc.add info, AllocLocals, 0'u32
       for ch in sons(t, n): preprocess(c2, bc, t, ch, {})
       bc.code[toPatch] = toIns(AllocLocals, c2.localsAddr)
+    when false:
+      if here.int == 40192:
+        debug bc, t, n
+        debug bc, here
+
   of PragmaPair:
     recurse PragmaPairM
 
@@ -739,7 +795,7 @@ proc evalAddr(c: Bytecode; pc: CodePos; s: StackFrame): pointer =
 proc `div`(x, y: float32): float32 {.inline.} = x / y
 proc `div`(x, y: float64): float64 {.inline.} = x / y
 
-from math import `mod`
+from std / math import `mod`
 
 template binop(opr) {.dirty.} =
   template impl(typ) {.dirty.} =
@@ -930,13 +986,15 @@ proc eval(c: Bytecode; pc: CodePos; s: StackFrame; result: pointer; size: int) =
     of UInt16Id: impl uint16
     of UInt32Id: impl uint32
     of UInt64Id: impl uint64
+    of Float32Id: impl float32
+    of Float64Id: impl float64
     else:
       case c.m.types[tid].kind
       of ProcTy, UPtrTy, APtrTy, AArrayPtrTy, UArrayPtrTy:
         # the VM always uses 64 bit pointers:
         impl uint64
       else:
-        raiseAssert "cannot happen"
+        raiseAssert "cannot happen: " & $c.m.types[tid].kind
   else:
     #debug c, c.debug[pc.int]
     raiseAssert "cannot happen: " & $c.code[pc].kind
@@ -980,7 +1038,7 @@ proc evalBuiltin(c: Bytecode; pc: CodePos; s: StackFrame; prc: CodePos; didEval:
         else: discard
         echo "running compilerproc: ", c.m.lit.strings[lit]
         didEval = true
-    of PragmaIdM: discard
+    of PragmaIdM, AllocLocals: discard
     else: break
     next c, prc
   result = prc
@@ -1021,10 +1079,10 @@ proc exec(c: Bytecode; pc: CodePos; u: ref Universe) =
         for a in sonsFrom1(c, callInstr):
           assert c[prc].kind == SummonParamM
           let paramAddr = c[prc].operand
-          assert c[prc.firstSon].kind == ImmediateValM
-          let paramSize = c[prc.firstSon].operand.int
-          eval(c, a, s2, s2.locals +! paramAddr, paramSize)
           next c, prc
+          assert c[prc].kind == ImmediateValM
+          let paramSize = c[prc].operand.int
+          eval(c, a, s2, s2.locals +! paramAddr, paramSize)
           next c, prc
         s = s2
         pc = prc
@@ -1040,7 +1098,8 @@ proc exec(c: Bytecode; pc: CodePos; u: ref Universe) =
     of ProcDeclM:
       next c, pc
     else:
-      raiseAssert "unreachable"
+      #debug c, c.debug[pc.int]
+      raiseAssert "unreachable: " & $c.code[pc].kind
 
 proc execCode*(bc: var Bytecode; t: Tree; n: NodePos) =
   traverseTypes bc
@@ -1048,6 +1107,8 @@ proc execCode*(bc: var Bytecode; t: Tree; n: NodePos) =
   let start = CodePos(bc.code.len)
   var pc = n
   while pc.int < t.len:
+    #echo "RUnning: "
+    #debug bc, t, pc
     preprocess c, bc, t, pc, {}
     next t, pc
   exec bc, start, nil