NIR: progress (#22884)

This commit is contained in:
Andreas Rumpf
2023-10-29 21:53:28 +01:00
committed by GitHub
parent e17237ce9d
commit 403e0118ae
3 changed files with 96 additions and 19 deletions

View File

@@ -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

View File

@@ -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:

View File

@@ -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