diff options
-rw-r--r-- | compiler/nir/ast2ir.nim | 32 | ||||
-rw-r--r-- | compiler/nir/nirinsts.nim | 2 | ||||
-rw-r--r-- | compiler/nir/nirvm.nim | 81 |
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 |