mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-04 19:04:46 +00:00
NIR: progress (#22884)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user