mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-17 00:24:16 +00:00
so close... (#22885)
This commit is contained in:
@@ -201,7 +201,9 @@ proc commandCompileToJS(graph: ModuleGraph) =
|
||||
proc commandInteractive(graph: ModuleGraph; useNir: bool) =
|
||||
graph.config.setErrorMaxHighMaybe
|
||||
initDefines(graph.config.symbols)
|
||||
if not useNir:
|
||||
if useNir:
|
||||
defineSymbol(graph.config.symbols, "noSignalHandler")
|
||||
else:
|
||||
defineSymbol(graph.config.symbols, "nimscript")
|
||||
# note: seems redundant with -d:nimHasLibFFI
|
||||
when hasFFI: defineSymbol(graph.config.symbols, "nimffi")
|
||||
|
||||
@@ -92,6 +92,7 @@ type
|
||||
importDeps*: Table[FileIndex, seq[FileIndex]] # explicit import module dependencies
|
||||
suggestMode*: bool # whether we are in nimsuggest mode or not.
|
||||
invalidTransitiveClosure: bool
|
||||
interactive*: bool
|
||||
inclToMod*: Table[FileIndex, FileIndex] # mapping of include file to the
|
||||
# first module that included it
|
||||
importStack*: seq[FileIndex] # The current import stack. Used for detecting recursive
|
||||
|
||||
@@ -205,7 +205,7 @@ proc xjmp(c: var ProcCon; n: PNode; jk: JmpKind; v: Value): LabelId =
|
||||
c.code.copyTree Tree(v)
|
||||
build c.code, info, SelectPair:
|
||||
build c.code, info, SelectValue:
|
||||
c.code.boolVal(info, jk == opcTJmp)
|
||||
c.code.boolVal(c.lit.numbers, info, jk == opcTJmp)
|
||||
c.code.gotoLabel info, Goto, result
|
||||
|
||||
proc patch(c: var ProcCon; n: PNode; L: LabelId) =
|
||||
@@ -311,8 +311,7 @@ proc tempToDest(c: var ProcCon; n: PNode; d: var Value; tmp: Value) =
|
||||
d = tmp
|
||||
else:
|
||||
let info = toLineInfo(c, n.info)
|
||||
build c.code, info, Asgn:
|
||||
c.code.addTyped info, typeToIr(c.m, n.typ)
|
||||
buildTyped c.code, info, Asgn, typeToIr(c.m, n.typ):
|
||||
c.code.copyTree d
|
||||
c.code.copyTree tmp
|
||||
freeTemp(c, tmp)
|
||||
@@ -362,7 +361,7 @@ template buildCond(useNegation: bool; cond: typed; body: untyped) =
|
||||
c.code.copyTree cond
|
||||
build c.code, info, SelectPair:
|
||||
build c.code, info, SelectValue:
|
||||
c.code.boolVal(info, useNegation)
|
||||
c.code.boolVal(c.lit.numbers, info, useNegation)
|
||||
c.code.gotoLabel info, Goto, lab
|
||||
|
||||
body
|
||||
@@ -381,7 +380,7 @@ template buildIfThenElse(cond: typed; then, otherwise: untyped) =
|
||||
c.code.copyTree cond
|
||||
build c.code, info, SelectPair:
|
||||
build c.code, info, SelectValue:
|
||||
c.code.boolVal(info, false)
|
||||
c.code.boolVal(c.lit.numbers, info, false)
|
||||
c.code.gotoLabel info, Goto, lelse
|
||||
|
||||
then()
|
||||
@@ -406,8 +405,7 @@ proc genCase(c: var ProcCon; n: PNode; d: var Value) =
|
||||
let ending = newLabel(c.labelGen)
|
||||
let info = toLineInfo(c, n.info)
|
||||
withTemp(tmp, n[0]):
|
||||
build c.code, info, Select:
|
||||
c.code.addTyped info, typeToIr(c.m, n[0].typ)
|
||||
buildTyped c.code, info, Select, typeToIr(c.m, n[0].typ):
|
||||
c.gen(n[0], tmp)
|
||||
for i in 1..<n.len:
|
||||
let section = newLabel(c.labelGen)
|
||||
@@ -432,8 +430,7 @@ proc genCase(c: var ProcCon; n: PNode; d: var Value) =
|
||||
c.code.addLabel info, Label, ending
|
||||
|
||||
proc rawCall(c: var ProcCon; info: PackedLineInfo; opc: Opcode; t: TypeId; args: var openArray[Value]) =
|
||||
build c.code, info, opc:
|
||||
c.code.addTyped info, t
|
||||
buildTyped c.code, info, opc, t:
|
||||
if opc in {CheckedCall, CheckedIndirectCall}:
|
||||
c.code.addLabel info, CheckedGoto, c.exitLabel
|
||||
for a in mitems(args):
|
||||
@@ -479,8 +476,7 @@ proc genCall(c: var ProcCon; n: PNode; d: var Value) =
|
||||
if not isEmptyType(n.typ):
|
||||
if isEmpty(d): d = getTemp(c, n)
|
||||
# XXX Handle problematic aliasing here: `a = f_canRaise(a)`.
|
||||
build c.code, info, Asgn:
|
||||
c.code.addTyped info, tb
|
||||
buildTyped c.code, info, Asgn, tb:
|
||||
c.code.copyTree d
|
||||
rawCall c, info, opc, tb, args
|
||||
else:
|
||||
@@ -492,8 +488,7 @@ proc genRaise(c: var ProcCon; n: PNode) =
|
||||
let tb = typeToIr(c.m, n[0].typ)
|
||||
|
||||
let d = genx(c, n[0])
|
||||
build c.code, info, SetExc:
|
||||
c.code.addTyped info, tb
|
||||
buildTyped c.code, info, SetExc, tb:
|
||||
c.code.copyTree d
|
||||
c.freeTemp(d)
|
||||
c.code.addLabel info, Goto, c.exitLabel
|
||||
@@ -583,10 +578,10 @@ proc genIndex(c: var ProcCon; n: PNode; arr: PType; d: var Value) =
|
||||
if optBoundsCheck in c.options:
|
||||
let idx = move d
|
||||
build d, info, CheckedIndex:
|
||||
d.Tree.addLabel info, CheckedGoto, c.exitLabel
|
||||
copyTree d.Tree, idx
|
||||
let x = toInt64 lengthOrd(c.config, arr)
|
||||
d.addIntVal c.lit.numbers, info, c.m.nativeIntId, x
|
||||
d.Tree.addLabel info, CheckedGoto, c.exitLabel
|
||||
|
||||
proc rawGenNew(c: var ProcCon; d: Value; refType: PType; ninfo: TLineInfo; needsInit: bool) =
|
||||
assert refType.kind == tyRef
|
||||
@@ -715,7 +710,7 @@ proc genBinaryOp(c: var ProcCon; n: PNode; d: var Value; opc: Opcode) =
|
||||
let t = typeToIr(c.m, n.typ)
|
||||
template body(target) =
|
||||
buildTyped target, info, opc, t:
|
||||
if optOverflowCheck in c.options and opc in {CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, CheckedMod}:
|
||||
if opc in {CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, CheckedMod}:
|
||||
target.addLabel info, CheckedGoto, c.exitLabel
|
||||
copyTree target, tmp
|
||||
copyTree target, tmp2
|
||||
@@ -756,6 +751,8 @@ proc genIncDec(c: var ProcCon; n: PNode; opc: Opcode) =
|
||||
buildTyped c.code, info, Asgn, t:
|
||||
copyTree c.code, d
|
||||
buildTyped c.code, info, opc, t:
|
||||
if opc in {CheckedAdd, CheckedSub}:
|
||||
c.code.addLabel info, CheckedGoto, c.exitLabel
|
||||
copyTree c.code, d
|
||||
copyTree c.code, tmp
|
||||
c.freeTemp(tmp)
|
||||
@@ -974,7 +971,7 @@ proc genInSet(c: var ProcCon; n: PNode; d: var Value) =
|
||||
if ex == nil:
|
||||
let info = toLineInfo(c, n.info)
|
||||
template body(target) =
|
||||
boolVal target, info, false
|
||||
boolVal target, c.lit.numbers, info, false
|
||||
intoDest d, info, Bool8Id, body
|
||||
else:
|
||||
gen c, ex, d
|
||||
@@ -1062,7 +1059,7 @@ proc beginCountLoop(c: var ProcCon; info: PackedLineInfo; first, last: int): (Sy
|
||||
c.code.addIntVal c.lit.numbers, info, c.m.nativeIntId, last
|
||||
build c.code, info, SelectPair:
|
||||
build c.code, info, SelectValue:
|
||||
c.code.boolVal(info, false)
|
||||
c.code.boolVal(c.lit.numbers, info, false)
|
||||
c.code.gotoLabel info, Goto, result[2]
|
||||
|
||||
proc beginCountLoop(c: var ProcCon; info: PackedLineInfo; first, last: Value): (SymId, LabelId, LabelId) =
|
||||
@@ -1080,7 +1077,7 @@ proc beginCountLoop(c: var ProcCon; info: PackedLineInfo; first, last: Value): (
|
||||
copyTree c.code, last
|
||||
build c.code, info, SelectPair:
|
||||
build c.code, info, SelectValue:
|
||||
c.code.boolVal(info, false)
|
||||
c.code.boolVal(c.lit.numbers, info, false)
|
||||
c.code.gotoLabel info, Goto, result[2]
|
||||
|
||||
proc endLoop(c: var ProcCon; info: PackedLineInfo; s: SymId; back, exit: LabelId) =
|
||||
@@ -1126,7 +1123,7 @@ proc genLeSet(c: var ProcCon; n: PNode; d: var Value) =
|
||||
c.code.copyTree d
|
||||
build c.code, info, SelectPair:
|
||||
build c.code, info, SelectValue:
|
||||
c.code.boolVal(info, false)
|
||||
c.code.boolVal(c.lit.numbers, info, false)
|
||||
c.code.gotoLabel info, Goto, endLabel
|
||||
|
||||
endLoop(c, info, idx, backLabel, endLabel)
|
||||
@@ -1462,6 +1459,7 @@ proc genStrConcat(c: var ProcCon; n: PNode; d: var Value) =
|
||||
buildTyped c.code, info, Asgn, c.m.nativeIntId:
|
||||
c.code.addSymUse info, tmpLen
|
||||
buildTyped c.code, info, CheckedAdd, c.m.nativeIntId:
|
||||
c.code.addLabel info, CheckedGoto, c.exitLabel
|
||||
c.code.addSymUse info, tmpLen
|
||||
buildTyped c.code, info, FieldAt, typeToIr(c.m, n.typ):
|
||||
copyTree c.code, a
|
||||
@@ -1539,7 +1537,7 @@ proc genMove(c: var ProcCon; n: PNode; d: var Value) =
|
||||
|
||||
build c.code, info, SelectPair:
|
||||
build c.code, info, SelectValue:
|
||||
c.code.boolVal(info, true)
|
||||
c.code.boolVal(c.lit.numbers, info, true)
|
||||
c.code.gotoLabel info, Goto, lab1
|
||||
|
||||
gen(c, n[3])
|
||||
@@ -1636,6 +1634,7 @@ proc genIndexCheck(c: var ProcCon; n: PNode; a: Value; kind: IndexFor; arr: PTyp
|
||||
result = default(Value)
|
||||
let idx = genx(c, n)
|
||||
build result, info, CheckedIndex:
|
||||
result.Tree.addLabel info, CheckedGoto, c.exitLabel
|
||||
copyTree result.Tree, idx
|
||||
case kind
|
||||
of ForSeq, ForStr:
|
||||
@@ -1649,7 +1648,6 @@ proc genIndexCheck(c: var ProcCon; n: PNode; a: Value; kind: IndexFor; arr: PTyp
|
||||
of ForArray:
|
||||
let x = toInt64 lengthOrd(c.config, arr)
|
||||
result.addIntVal c.lit.numbers, info, c.m.nativeIntId, x
|
||||
result.Tree.addLabel info, CheckedGoto, c.exitLabel
|
||||
freeTemp c, idx
|
||||
else:
|
||||
result = genx(c, n)
|
||||
@@ -1669,7 +1667,7 @@ proc addSliceFields(c: var ProcCon; target: var Tree; info: PackedLineInfo;
|
||||
buildTyped target, info, ObjConstr, typeToIr(c.m, n.typ):
|
||||
target.addImmediateVal info, 0
|
||||
buildTyped target, info, AddrOf, elemType:
|
||||
buildTyped target, info, ArrayAt, pay[1]:
|
||||
buildTyped target, info, DerefArrayAt, pay[1]:
|
||||
buildTyped target, info, FieldAt, typeToIr(c.m, arrType):
|
||||
copyTree target, x
|
||||
target.addImmediateVal info, 1 # (len, p)-pair
|
||||
@@ -1716,7 +1714,7 @@ proc addSliceFields(c: var ProcCon; target: var Tree; info: PackedLineInfo;
|
||||
buildTyped target, info, ObjConstr, typeToIr(c.m, n.typ):
|
||||
target.addImmediateVal info, 0
|
||||
buildTyped target, info, AddrOf, elemType:
|
||||
buildTyped target, info, ArrayAt, pay:
|
||||
buildTyped target, info, DerefArrayAt, pay:
|
||||
buildTyped target, info, FieldAt, typeToIr(c.m, arrType):
|
||||
copyTree target, x
|
||||
target.addImmediateVal info, 0 # (p, len)-pair
|
||||
@@ -1751,14 +1749,14 @@ proc genMagic(c: var ProcCon; n: PNode; d: var Value; m: TMagic) =
|
||||
case m
|
||||
of mAnd: c.genAndOr(n, opcFJmp, d)
|
||||
of mOr: c.genAndOr(n, opcTJmp, d)
|
||||
of mPred, mSubI: c.genBinaryOp(n, d, CheckedSub)
|
||||
of mSucc, mAddI: c.genBinaryOp(n, d, CheckedAdd)
|
||||
of mPred, mSubI: c.genBinaryOp(n, d, if optOverflowCheck in c.options: CheckedSub else: Sub)
|
||||
of mSucc, mAddI: c.genBinaryOp(n, d, if optOverflowCheck in c.options: CheckedAdd else: Add)
|
||||
of mInc:
|
||||
unused(c, n, d)
|
||||
c.genIncDec(n, CheckedAdd)
|
||||
c.genIncDec(n, if optOverflowCheck in c.options: CheckedAdd else: Add)
|
||||
of mDec:
|
||||
unused(c, n, d)
|
||||
c.genIncDec(n, CheckedSub)
|
||||
c.genIncDec(n, if optOverflowCheck in c.options: CheckedSub else: Sub)
|
||||
of mOrd, mChr, mUnown:
|
||||
c.gen(n[1], d)
|
||||
of generatedMagics:
|
||||
@@ -1773,9 +1771,9 @@ proc genMagic(c: var ProcCon; n: PNode; d: var Value; m: TMagic) =
|
||||
of mNewString, mNewStringOfCap, mExit: c.genCall(n, d)
|
||||
of mLengthOpenArray, mLengthArray, mLengthSeq, mLengthStr:
|
||||
genArrayLen(c, n, d)
|
||||
of mMulI: genBinaryOp(c, n, d, CheckedMul)
|
||||
of mDivI: genBinaryOp(c, n, d, CheckedDiv)
|
||||
of mModI: genBinaryOp(c, n, d, CheckedMod)
|
||||
of mMulI: genBinaryOp(c, n, d, if optOverflowCheck in c.options: CheckedMul else: Mul)
|
||||
of mDivI: genBinaryOp(c, n, d, if optOverflowCheck in c.options: CheckedDiv else: Div)
|
||||
of mModI: genBinaryOp(c, n, d, if optOverflowCheck in c.options: CheckedMod else: Mod)
|
||||
of mAddF64: genBinaryOp(c, n, d, Add)
|
||||
of mSubF64: genBinaryOp(c, n, d, Sub)
|
||||
of mMulF64: genBinaryOp(c, n, d, Mul)
|
||||
@@ -1977,7 +1975,7 @@ proc addAddrOfFirstElem(c: var ProcCon; target: var Tree; info: PackedLineInfo;
|
||||
let t = typeToIr(c.m, typ)
|
||||
target.addImmediateVal info, 0
|
||||
buildTyped target, info, AddrOf, elemType:
|
||||
buildTyped target, info, ArrayAt, c.m.strPayloadId[1]:
|
||||
buildTyped target, info, DerefArrayAt, c.m.strPayloadId[1]:
|
||||
buildTyped target, info, FieldAt, typeToIr(c.m, arrType):
|
||||
copyTree target, tmp
|
||||
target.addImmediateVal info, 1 # (len, p)-pair
|
||||
@@ -1992,7 +1990,7 @@ proc addAddrOfFirstElem(c: var ProcCon; target: var Tree; info: PackedLineInfo;
|
||||
let t = typeToIr(c.m, typ)
|
||||
target.addImmediateVal info, 0
|
||||
buildTyped target, info, AddrOf, elemType:
|
||||
buildTyped target, info, ArrayAt, seqPayloadPtrType(c.m.types, c.m.nirm.types, typ)[1]:
|
||||
buildTyped target, info, DerefArrayAt, seqPayloadPtrType(c.m.types, c.m.nirm.types, typ)[1]:
|
||||
buildTyped target, info, FieldAt, typeToIr(c.m, arrType):
|
||||
copyTree target, tmp
|
||||
target.addImmediateVal info, 1 # (len, p)-pair
|
||||
@@ -2102,10 +2100,11 @@ proc genSeqConstr(c: var ProcCon; n: PNode; d: var Value) =
|
||||
|
||||
for i in 0..<n.len:
|
||||
var dd = default(Value)
|
||||
buildTyped dd, info, ArrayAt, seqPayloadPtrType(c.m.types, c.m.nirm.types, seqtype)[1]:
|
||||
buildTyped dd, info, DerefArrayAt, seqPayloadPtrType(c.m.types, c.m.nirm.types, seqtype)[1]:
|
||||
buildTyped dd, info, FieldAt, typeToIr(c.m, seqtype):
|
||||
copyTree Tree(dd), d
|
||||
dd.addIntVal c.lit.numbers, info, c.m.nativeIntId, i
|
||||
dd.addImmediateVal info, 1 # (len, p)-pair
|
||||
dd.addIntVal c.lit.numbers, info, c.m.nativeIntId, i
|
||||
gen(c, n[i], dd)
|
||||
|
||||
freeTemp c, d
|
||||
@@ -2242,10 +2241,10 @@ proc genRangeCheck(c: var ProcCon; n: PNode; d: var Value) =
|
||||
let b = c.genx n[2]
|
||||
template body(target) =
|
||||
buildTyped target, info, CheckedRange, typeToIr(c.m, n.typ):
|
||||
target.addLabel info, CheckedGoto, c.exitLabel
|
||||
copyTree target, tmp
|
||||
copyTree target, a
|
||||
copyTree target, b
|
||||
target.addLabel info, CheckedGoto, c.exitLabel
|
||||
valueIntoDest c, info, d, n.typ, body
|
||||
freeTemp c, tmp
|
||||
freeTemp c, a
|
||||
@@ -2263,7 +2262,7 @@ proc genArrAccess(c: var ProcCon; n: PNode; d: var Value; flags: GenFlags) =
|
||||
let b = genIndexCheck(c, n[1], a, ForStr, arrayType)
|
||||
let t = typeToIr(c.m, n.typ)
|
||||
template body(target) =
|
||||
buildTyped target, info, ArrayAt, c.m.strPayloadId[1]:
|
||||
buildTyped target, info, DerefArrayAt, c.m.strPayloadId[1]:
|
||||
buildTyped target, info, FieldAt, typeToIr(c.m, arrayType):
|
||||
copyTree target, a
|
||||
target.addImmediateVal info, 1 # (len, p)-pair
|
||||
@@ -2276,7 +2275,7 @@ proc genArrAccess(c: var ProcCon; n: PNode; d: var Value; flags: GenFlags) =
|
||||
let a = genx(c, n[0], flags)
|
||||
let b = genx(c, n[1])
|
||||
template body(target) =
|
||||
buildTyped target, info, ArrayAt, typeToIr(c.m, arrayType):
|
||||
buildTyped target, info, DerefArrayAt, typeToIr(c.m, arrayType):
|
||||
copyTree target, a
|
||||
copyTree target, b
|
||||
valueIntoDest c, info, d, n.typ, body
|
||||
@@ -2298,7 +2297,7 @@ proc genArrAccess(c: var ProcCon; n: PNode; d: var Value; flags: GenFlags) =
|
||||
let b = genIndexCheck(c, n[1], a, ForOpenArray, arrayType)
|
||||
let t = typeToIr(c.m, n.typ)
|
||||
template body(target) =
|
||||
buildTyped target, info, ArrayAt, openArrayPayloadType(c.m.types, c.m.nirm.types, n[0].typ):
|
||||
buildTyped target, info, DerefArrayAt, openArrayPayloadType(c.m.types, c.m.nirm.types, n[0].typ):
|
||||
buildTyped target, info, FieldAt, typeToIr(c.m, arrayType):
|
||||
copyTree target, a
|
||||
target.addImmediateVal info, 0 # (p, len)-pair
|
||||
@@ -2324,7 +2323,7 @@ proc genArrAccess(c: var ProcCon; n: PNode; d: var Value; flags: GenFlags) =
|
||||
let b = genIndexCheck(c, n[1], a, ForSeq, arrayType)
|
||||
let t = typeToIr(c.m, n.typ)
|
||||
template body(target) =
|
||||
buildTyped target, info, ArrayAt, seqPayloadPtrType(c.m.types, c.m.nirm.types, n[0].typ)[1]:
|
||||
buildTyped target, info, DerefArrayAt, seqPayloadPtrType(c.m.types, c.m.nirm.types, n[0].typ)[1]:
|
||||
buildTyped target, info, FieldAt, t:
|
||||
copyTree target, a
|
||||
target.addImmediateVal info, 1 # (len, p)-pair
|
||||
@@ -2337,10 +2336,18 @@ proc genArrAccess(c: var ProcCon; n: PNode; d: var Value; flags: GenFlags) =
|
||||
|
||||
proc genObjAccess(c: var ProcCon; n: PNode; d: var Value; flags: GenFlags) =
|
||||
let info = toLineInfo(c, n.info)
|
||||
let a = genx(c, n[0], flags)
|
||||
|
||||
var n0 = n[0]
|
||||
var opc = FieldAt
|
||||
if n0.kind == nkDotExpr:
|
||||
# obj[].a --> DerefFieldAt instead of FieldAt:
|
||||
n0 = n[0]
|
||||
opc = DerefFieldAt
|
||||
|
||||
let a = genx(c, n0, flags)
|
||||
|
||||
template body(target) =
|
||||
buildTyped target, info, FieldAt, typeToIr(c.m, n[0].typ):
|
||||
buildTyped target, info, opc, typeToIr(c.m, n0.typ):
|
||||
copyTree target, a
|
||||
genField c, n[1], Value(target)
|
||||
|
||||
@@ -2353,6 +2360,11 @@ proc genParams(c: var ProcCon; params: PNode; prc: PSym) =
|
||||
let res = resNode.sym # get result symbol
|
||||
c.code.addSummon toLineInfo(c, res.info), toSymId(c, res),
|
||||
typeToIr(c.m, res.typ), SummonResult
|
||||
elif prc.typ.len > 0 and not isEmptyType(prc.typ[0]) and not isCompileTimeOnly(prc.typ[0]):
|
||||
# happens for procs without bodies:
|
||||
let t = typeToIr(c.m, prc.typ[0])
|
||||
let tmp = allocTemp(c, t)
|
||||
c.code.addSummon toLineInfo(c, params.info), tmp, t, SummonResult
|
||||
|
||||
for i in 1..<params.len:
|
||||
let s = params[i].sym
|
||||
|
||||
@@ -57,6 +57,7 @@ proc evalStmt(c: PCtx; n: PNode) =
|
||||
#res.add "\n--------------------------\n"
|
||||
#toString res, c.m.types.g
|
||||
if pc.int < c.m.nirm.code.len:
|
||||
c.bytecode.interactive = c.m.graph.interactive
|
||||
execCode c.bytecode, c.m.nirm.code, pc
|
||||
#echo res
|
||||
|
||||
|
||||
@@ -63,8 +63,10 @@ type
|
||||
Kill, # `Kill x`: scope end for `x`
|
||||
|
||||
AddrOf,
|
||||
ArrayAt, # addr(a[i])
|
||||
FieldAt, # addr(obj.field)
|
||||
ArrayAt, # a[i]
|
||||
DerefArrayAt, # a[i] where `a` is a PtrArray; `a[][i]`
|
||||
FieldAt, # obj.field
|
||||
DerefFieldAt, # obj[].field
|
||||
|
||||
Load, # a[]
|
||||
Store, # a[] = b
|
||||
@@ -162,7 +164,9 @@ const
|
||||
AddrOf,
|
||||
Load,
|
||||
ArrayAt,
|
||||
DerefArrayAt,
|
||||
FieldAt,
|
||||
DerefFieldAt,
|
||||
TestOf
|
||||
}
|
||||
|
||||
@@ -240,6 +244,8 @@ proc next*(tree: Tree; pos: var NodePos) {.inline.} = nextChild tree, int(pos)
|
||||
|
||||
template firstSon*(n: NodePos): NodePos = NodePos(n.int+1)
|
||||
|
||||
template skipTyped*(n: NodePos): NodePos = NodePos(n.int+2)
|
||||
|
||||
iterator sons*(tree: Tree; n: NodePos): NodePos =
|
||||
var pos = n.int
|
||||
assert tree.nodes[pos].kind > LastAtomicValue
|
||||
@@ -259,6 +265,17 @@ iterator sonsFrom1*(tree: Tree; n: NodePos): NodePos =
|
||||
yield NodePos pos
|
||||
nextChild tree, pos
|
||||
|
||||
iterator sonsFromN*(tree: Tree; n: NodePos; toSkip = 2): NodePos =
|
||||
var pos = n.int
|
||||
assert tree.nodes[pos].kind > LastAtomicValue
|
||||
let last = pos + tree.nodes[pos].rawSpan
|
||||
inc pos
|
||||
for i in 1..toSkip:
|
||||
nextChild tree, pos
|
||||
while pos < last:
|
||||
yield NodePos pos
|
||||
nextChild tree, pos
|
||||
|
||||
template `[]`*(t: Tree; n: NodePos): Instr = t.nodes[n.int]
|
||||
|
||||
proc span(tree: Tree; pos: int): int {.inline.} =
|
||||
@@ -327,9 +344,6 @@ proc addNewLabel*(t: var Tree; labelGen: var int; info: PackedLineInfo; k: Opcod
|
||||
t.nodes.add Instr(x: toX(k, uint32(result)), info: info)
|
||||
inc labelGen
|
||||
|
||||
proc boolVal*(t: var Tree; info: PackedLineInfo; b: bool) =
|
||||
t.nodes.add Instr(x: toX(ImmediateVal, uint32(b)), info: info)
|
||||
|
||||
proc gotoLabel*(t: var Tree; info: PackedLineInfo; k: Opcode; L: LabelId) =
|
||||
assert k in {Goto, GotoLoop, CheckedGoto}
|
||||
t.nodes.add Instr(x: toX(k, uint32(L)), info: info)
|
||||
@@ -367,6 +381,10 @@ proc addIntVal*(t: var Tree; integers: var BiTable[int64]; info: PackedLineInfo;
|
||||
buildTyped t, info, NumberConv, typ:
|
||||
t.nodes.add Instr(x: toX(IntVal, uint32(integers.getOrIncl(x))), info: info)
|
||||
|
||||
proc boolVal*(t: var Tree; integers: var BiTable[int64]; info: PackedLineInfo; b: bool) =
|
||||
buildTyped t, info, NumberConv, Bool8Id:
|
||||
t.nodes.add Instr(x: toX(IntVal, uint32(integers.getOrIncl(ord b))), info: info)
|
||||
|
||||
proc addStrVal*(t: var Tree; strings: var BiTable[string]; info: PackedLineInfo; s: string) =
|
||||
t.nodes.add Instr(x: toX(StrVal, uint32(strings.getOrIncl(s))), info: info)
|
||||
|
||||
|
||||
@@ -48,7 +48,9 @@ type
|
||||
|
||||
AddrOfM,
|
||||
ArrayAtM, # (elemSize, addr(a), i)
|
||||
DerefArrayAtM,
|
||||
FieldAtM, # addr(obj.field)
|
||||
DerefFieldAtM,
|
||||
|
||||
LoadM, # a[]
|
||||
AsgnM, # a = b
|
||||
@@ -60,7 +62,6 @@ type
|
||||
CheckedIndexM,
|
||||
|
||||
CallM,
|
||||
CheckedCallM, # call that can raise
|
||||
CheckedAddM, # with overflow checking etc.
|
||||
CheckedSubM,
|
||||
CheckedMulM,
|
||||
@@ -107,6 +108,14 @@ template toIns(k: OpcodeM; operand: uint32): Instr =
|
||||
template toIns(k: OpcodeM; operand: LitId): Instr =
|
||||
Instr(uint32(k) or (operand.uint32 shl OpcodeBits))
|
||||
|
||||
type
|
||||
NimStrPayloadVM = object
|
||||
cap: int
|
||||
data: UncheckedArray[char]
|
||||
NimStringVM = object
|
||||
len: int
|
||||
p: ptr NimStrPayloadVM
|
||||
|
||||
const
|
||||
GlobalsSize = 1024*24
|
||||
|
||||
@@ -119,7 +128,8 @@ type
|
||||
debug: seq[PackedLineInfo]
|
||||
m: ref NirModule
|
||||
procs: Table[SymId, CodePos]
|
||||
globals: Table[SymId, uint32]
|
||||
globals: Table[SymId, (uint32, int)]
|
||||
strings: Table[LitId, NimStringVM]
|
||||
globalData: pointer
|
||||
globalsAddr: uint32
|
||||
typeImpls: Table[string, TypeId]
|
||||
@@ -127,6 +137,7 @@ type
|
||||
sizes: Table[TypeId, (int, int)] # (size, alignment)
|
||||
oldTypeLen: int
|
||||
procUsagesToPatch: Table[SymId, seq[CodePos]]
|
||||
interactive*: bool
|
||||
|
||||
Universe* = object ## all units: For interpretation we need that
|
||||
units: seq[Bytecode]
|
||||
@@ -325,7 +336,7 @@ proc toString*(t: Bytecode; pos: CodePos;
|
||||
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:
|
||||
of LoadLocalM, LoadGlobalM, LoadProcM, AllocLocals, SummonParamM:
|
||||
r.add $t[pos].kind
|
||||
r.add ' '
|
||||
r.add $t[pos].operand
|
||||
@@ -361,7 +372,7 @@ type
|
||||
u: ref Universe
|
||||
known: Table[LabelId, CodePos]
|
||||
toPatch: Table[LabelId, seq[CodePos]]
|
||||
locals: Table[SymId, uint32]
|
||||
locals: Table[SymId, (uint32, int)] # address, size
|
||||
thisModule: uint32
|
||||
localsAddr: uint32
|
||||
markedWithLabel: IntSet
|
||||
@@ -382,15 +393,23 @@ type
|
||||
AddrMode = enum
|
||||
InDotExpr, WantAddr
|
||||
|
||||
template maybeDeref(doDeref: bool; body: untyped) =
|
||||
template maybeDeref(doDeref: bool; size: int; body: untyped) =
|
||||
var pos = PatchPos(-1)
|
||||
if doDeref:
|
||||
pos = prepare(bc, info, LoadM)
|
||||
bc.add info, TypedM, 0'u32
|
||||
bc.add info, ImmediateValM, uint32 size
|
||||
body
|
||||
if doDeref:
|
||||
patch(bc, pos)
|
||||
|
||||
proc toReadonlyString(s: string): NimStringVM =
|
||||
if s.len == 0:
|
||||
result = NimStringVM(len: 0, p: nil)
|
||||
else:
|
||||
result = NimStringVM(len: s.len, p: cast[ptr NimStrPayloadVM](alloc(s.len+1+sizeof(int))))
|
||||
copyMem(addr result.p.data[0], addr s[0], s.len+1)
|
||||
result.p.cap = s.len or (1 shl (8 * 8 - 2)) # see also NIM_STRLIT_FLAG
|
||||
|
||||
const
|
||||
ForwardedProc = 10_000_000'u32
|
||||
|
||||
@@ -409,19 +428,24 @@ proc preprocess(c: var Preprocessing; bc: var Bytecode; t: Tree; n: NodePos; fla
|
||||
of IntVal:
|
||||
bc.add info, IntValM, t[n].rawOperand
|
||||
of StrVal:
|
||||
let litId = LitId t[n].rawOperand
|
||||
if not bc.strings.hasKey(litId):
|
||||
bc.strings[litId] = toReadonlyString(bc.m.lit.strings[litId])
|
||||
bc.add info, StrValM, t[n].rawOperand
|
||||
of SymDef:
|
||||
discard "happens for proc decls. Don't copy the node as we don't need it"
|
||||
of SymUse:
|
||||
let s = t[n].symId
|
||||
if c.locals.hasKey(s):
|
||||
maybeDeref(WantAddr notin flags):
|
||||
bc.add info, LoadLocalM, c.locals[s]
|
||||
let (address, size) = c.locals[s]
|
||||
maybeDeref(WantAddr notin flags, size):
|
||||
bc.add info, LoadLocalM, address
|
||||
elif bc.procs.hasKey(s):
|
||||
bc.add info, LoadProcM, uint32 bc.procs[s]
|
||||
elif bc.globals.hasKey(s):
|
||||
maybeDeref(WantAddr notin flags):
|
||||
bc.add info, LoadGlobalM, uint32 s
|
||||
let (address, size) = bc.globals[s]
|
||||
maybeDeref(WantAddr notin flags, size):
|
||||
bc.add info, LoadGlobalM, address
|
||||
else:
|
||||
let here = CodePos(bc.code.len)
|
||||
bc.add info, LoadProcM, ForwardedProc + uint32(s)
|
||||
@@ -452,7 +476,7 @@ proc preprocess(c: var Preprocessing; bc: var Bytecode; t: Tree; n: NodePos; fla
|
||||
bc.add info, NilValM, t[n].rawOperand
|
||||
of LoopLabel, Label:
|
||||
let lab = t[n].label
|
||||
let here = CodePos(bc.code.len-1)
|
||||
let here = CodePos(bc.code.len)
|
||||
c.known[lab] = here
|
||||
var p: seq[CodePos] = @[]
|
||||
if c.toPatch.take(lab, p):
|
||||
@@ -506,7 +530,7 @@ proc preprocess(c: var Preprocessing; bc: var Bytecode; t: Tree; n: NodePos; fla
|
||||
let (size, alignment) = computeSize(bc, tid)
|
||||
|
||||
let global = align(bc.globalsAddr, uint32 alignment)
|
||||
bc.globals[s] = global
|
||||
bc.globals[s] = (global, size)
|
||||
bc.globalsAddr += uint32 size
|
||||
assert bc.globalsAddr < GlobalsSize
|
||||
|
||||
@@ -518,7 +542,7 @@ proc preprocess(c: var Preprocessing; bc: var Bytecode; t: Tree; n: NodePos; fla
|
||||
let (size, alignment) = computeSize(bc, tid)
|
||||
|
||||
let local = align(c.localsAddr, uint32 alignment)
|
||||
c.locals[s] = local
|
||||
c.locals[s] = (local, size)
|
||||
c.localsAddr += uint32 size
|
||||
# allocation is combined into the frame allocation so there is no
|
||||
# instruction to emit
|
||||
@@ -530,7 +554,7 @@ proc preprocess(c: var Preprocessing; bc: var Bytecode; t: Tree; n: NodePos; fla
|
||||
let (size, alignment) = computeSize(bc, tid)
|
||||
|
||||
let local = align(c.localsAddr, uint32 alignment)
|
||||
c.locals[s] = local
|
||||
c.locals[s] = (local, size)
|
||||
c.localsAddr += uint32 size
|
||||
bc.add info, SummonParamM, local
|
||||
bc.add info, ImmediateValM, uint32 size
|
||||
@@ -545,39 +569,30 @@ proc preprocess(c: var Preprocessing; bc: var Bytecode; t: Tree; n: NodePos; fla
|
||||
let (arrayType, a, i) = sons3(t, n)
|
||||
let tid = t[arrayType].typeId
|
||||
let size = uint32 computeElemSize(bc, tid)
|
||||
if t[a].kind == Load:
|
||||
let (_, arg) = sons2(t, a)
|
||||
build bc, info, LoadM:
|
||||
bc.add info, ImmediateValM, size
|
||||
build bc, info, ArrayAtM:
|
||||
bc.add info, ImmediateValM, size
|
||||
preprocess(c, bc, t, arg, {WantAddr})
|
||||
preprocess(c, bc, t, i, {WantAddr})
|
||||
else:
|
||||
build bc, info, ArrayAtM:
|
||||
bc.add info, ImmediateValM, size
|
||||
preprocess(c, bc, t, a, {WantAddr})
|
||||
preprocess(c, bc, t, i, {WantAddr})
|
||||
build bc, info, ArrayAtM:
|
||||
bc.add info, ImmediateValM, size
|
||||
preprocess(c, bc, t, a, {WantAddr})
|
||||
preprocess(c, bc, t, i, {WantAddr})
|
||||
of DerefArrayAt:
|
||||
let (arrayType, a, i) = sons3(t, n)
|
||||
let tid = t[arrayType].typeId
|
||||
let size = uint32 computeElemSize(bc, tid)
|
||||
build bc, info, DerefArrayAtM:
|
||||
bc.add info, ImmediateValM, size
|
||||
preprocess(c, bc, t, a, {WantAddr})
|
||||
preprocess(c, bc, t, i, {WantAddr})
|
||||
of FieldAt:
|
||||
# a[] conceptually loads a block of size of T. But when applied to an object selector
|
||||
# only a subset of the data is really requested so `(a[] : T).field`
|
||||
# becomes `(a+offset(field))[] : T_Field`
|
||||
# And now if this is paired with `addr` the deref disappears, as usual: `addr x.field[]`
|
||||
# is `(x+offset(field))`.
|
||||
let (typ, a, b) = sons3(t, n)
|
||||
if t[a].kind == Load:
|
||||
let (_, arg) = sons2(t, a)
|
||||
build bc, info, LoadM:
|
||||
bc.add info, ImmediateValM, uint32 computeSize(bc, t[typ].typeId)[0]
|
||||
let offset = bc.offsets[t[typ].typeId][t[b].immediateVal][0]
|
||||
build bc, info, FieldAtM:
|
||||
preprocess(c, bc, t, arg, flags+{WantAddr})
|
||||
bc.add info, ImmediateValM, uint32(offset)
|
||||
else:
|
||||
let offset = bc.offsets[t[typ].typeId][t[b].immediateVal][0]
|
||||
build bc, info, FieldAtM:
|
||||
preprocess(c, bc, t, a, flags+{WantAddr})
|
||||
bc.add info, ImmediateValM, uint32(offset)
|
||||
let offset = bc.offsets[t[typ].typeId][t[b].immediateVal][0]
|
||||
build bc, info, FieldAtM:
|
||||
preprocess(c, bc, t, a, flags+{WantAddr})
|
||||
bc.add info, ImmediateValM, uint32(offset)
|
||||
of DerefFieldAt:
|
||||
let (typ, a, b) = sons3(t, n)
|
||||
let offset = bc.offsets[t[typ].typeId][t[b].immediateVal][0]
|
||||
build bc, info, DerefFieldAtM:
|
||||
preprocess(c, bc, t, a, flags+{WantAddr})
|
||||
bc.add info, ImmediateValM, uint32(offset)
|
||||
of Load:
|
||||
let (elemType, a) = sons2(t, n)
|
||||
let tid = t[elemType].typeId
|
||||
@@ -593,14 +608,16 @@ 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, src.skipTyped, {WantAddr})
|
||||
preprocess(c, bc, t, dest, {WantAddr})
|
||||
for ch in sonsFrom1(t, src): preprocess(c, bc, t, ch, {WantAddr})
|
||||
for ch in sonsFromN(t, src, 2): preprocess(c, bc, t, ch, {WantAddr})
|
||||
elif t[src].kind in {CheckedCall, CheckedIndirectCall}:
|
||||
build bc, info, CheckedCallM:
|
||||
preprocess(c, bc, t, src.firstSon, {WantAddr})
|
||||
let (_, gotoInstr, fn) = sons3(t, src)
|
||||
build bc, info, CallM:
|
||||
preprocess(c, bc, t, fn, {WantAddr})
|
||||
preprocess(c, bc, t, dest, {WantAddr})
|
||||
for ch in sonsFrom1(t, src): preprocess(c, bc, t, ch, {WantAddr})
|
||||
for ch in sonsFromN(t, src, 3): preprocess(c, bc, t, ch, {WantAddr})
|
||||
preprocess c, bc, t, gotoInstr, {}
|
||||
elif t[dest].kind == Load:
|
||||
let (typ, a) = sons2(t, dest)
|
||||
let s = computeSize(bc, tid)[0]
|
||||
@@ -628,8 +645,11 @@ 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 CheckedCall, CheckedIndirectCall:
|
||||
# avoid the Typed thing at position 0:
|
||||
build bc, info, CheckedCallM:
|
||||
for ch in sonsFrom1(t, n): preprocess(c, bc, t, ch, {WantAddr})
|
||||
let (_, gotoInstr, fn) = sons3(t, n)
|
||||
build bc, info, CallM:
|
||||
preprocess(c, bc, t, fn, {WantAddr})
|
||||
for ch in sonsFromN(t, n, 3): preprocess(c, bc, t, ch, {WantAddr})
|
||||
preprocess c, bc, t, gotoInstr, {WantAddr}
|
||||
of CheckedAdd:
|
||||
recurse CheckedAddM
|
||||
of CheckedSub:
|
||||
@@ -696,7 +716,7 @@ proc preprocess(c: var Preprocessing; bc: var Bytecode; t: Tree; n: NodePos; fla
|
||||
for ch in sons(t, n): preprocess(c2, bc, t, ch, {})
|
||||
bc.code[toPatch] = toIns(AllocLocals, c2.localsAddr)
|
||||
when false:
|
||||
if here.int == 40192:
|
||||
if here.int == 39850:
|
||||
debug bc, t, n
|
||||
debug bc, here
|
||||
|
||||
@@ -776,6 +796,10 @@ proc evalAddr(c: Bytecode; pc: CodePos; s: StackFrame): pointer =
|
||||
let (x, offset) = sons2(c.code, pc)
|
||||
result = evalAddr(c, x, s)
|
||||
result = result +! c.code[offset].operand
|
||||
of DerefFieldAtM:
|
||||
let (x, offset) = sons2(c.code, pc)
|
||||
let p = evalAddr(c, x, s)
|
||||
result = cast[ptr pointer](p)[] +! c.code[offset].operand
|
||||
of ArrayAtM:
|
||||
let (e, a, i) = sons3(c.code, pc)
|
||||
let elemSize = c.code[e].operand
|
||||
@@ -783,10 +807,13 @@ proc evalAddr(c: Bytecode; pc: CodePos; s: StackFrame): pointer =
|
||||
var idx: int = 0
|
||||
eval(c, i, s, addr idx, sizeof(int))
|
||||
result = result +! (uint32(idx) * elemSize)
|
||||
of LoadM:
|
||||
let (_, arg) = sons2(c.code, pc)
|
||||
let p = evalAddr(c, arg, s)
|
||||
result = cast[ptr pointer](p)[]
|
||||
of DerefArrayAtM:
|
||||
let (e, a, i) = sons3(c.code, pc)
|
||||
let elemSize = c.code[e].operand
|
||||
var p = evalAddr(c, a, s)
|
||||
var idx: int = 0
|
||||
eval(c, i, s, addr idx, sizeof(int))
|
||||
result = cast[ptr pointer](p)[] +! (uint32(idx) * elemSize)
|
||||
of LoadGlobalM:
|
||||
result = c.globalData +! c.code[pc].operand
|
||||
else:
|
||||
@@ -897,23 +924,29 @@ proc evalSelect(c: Bytecode; pc: CodePos; s: StackFrame): CodePos =
|
||||
for pair in sonsFrom2(c, pc):
|
||||
assert c.code[pair].kind == SelectPairM
|
||||
let (values, action) = sons2(c.code, pair)
|
||||
assert c.code[values].kind == SelectListM
|
||||
for v in sons(c, values):
|
||||
case c.code[v].kind
|
||||
of SelectValueM:
|
||||
var a = default(typ)
|
||||
eval c, v.firstSon, s, addr a, sizeof(typ)
|
||||
if selector == a:
|
||||
return CodePos c.code[action].operand
|
||||
of SelectRangeM:
|
||||
let (va, vb) = sons2(c.code, v)
|
||||
var a = default(typ)
|
||||
eval c, va, s, addr a, sizeof(typ)
|
||||
var b = default(typ)
|
||||
eval c, vb, s, addr a, sizeof(typ)
|
||||
if a <= selector and selector <= b:
|
||||
return CodePos c.code[action].operand
|
||||
else: raiseAssert "unreachable"
|
||||
if c.code[values].kind == SelectValueM:
|
||||
var a = default(typ)
|
||||
eval c, values.firstSon, s, addr a, sizeof(typ)
|
||||
if selector == a:
|
||||
return CodePos c.code[action].operand
|
||||
else:
|
||||
assert c.code[values].kind == SelectListM, $c.code[values].kind
|
||||
for v in sons(c, values):
|
||||
case c.code[v].kind
|
||||
of SelectValueM:
|
||||
var a = default(typ)
|
||||
eval c, v.firstSon, s, addr a, sizeof(typ)
|
||||
if selector == a:
|
||||
return CodePos c.code[action].operand
|
||||
of SelectRangeM:
|
||||
let (va, vb) = sons2(c.code, v)
|
||||
var a = default(typ)
|
||||
eval c, va, s, addr a, sizeof(typ)
|
||||
var b = default(typ)
|
||||
eval c, vb, s, addr a, sizeof(typ)
|
||||
if a <= selector and selector <= b:
|
||||
return CodePos c.code[action].operand
|
||||
else: raiseAssert "unreachable"
|
||||
result = CodePos(-1)
|
||||
|
||||
let (t, sel) = sons2(c.code, pc)
|
||||
@@ -932,11 +965,18 @@ proc evalSelect(c: Bytecode; pc: CodePos; s: StackFrame): CodePos =
|
||||
proc eval(c: Bytecode; pc: CodePos; s: StackFrame; result: pointer; size: int) =
|
||||
case c.code[pc].kind
|
||||
of LoadLocalM:
|
||||
let dest = s.locals +! c.code[pc].operand
|
||||
copyMem dest, result, size
|
||||
of FieldAtM, ArrayAtM, LoadM:
|
||||
let dest = evalAddr(c, pc, s)
|
||||
copyMem dest, result, size
|
||||
let src = s.locals +! c.code[pc].operand
|
||||
copyMem result, src, size
|
||||
of FieldAtM, DerefFieldAtM, ArrayAtM, DerefArrayAtM, LoadGlobalM:
|
||||
let src = evalAddr(c, pc, s)
|
||||
copyMem result, src, size
|
||||
of LoadProcM:
|
||||
let procAddr = c.code[pc].operand
|
||||
cast[ptr pointer](result)[] = cast[pointer](procAddr)
|
||||
of LoadM:
|
||||
let (_, arg) = sons2(c.code, pc)
|
||||
let src = evalAddr(c, arg, s)
|
||||
copyMem result, src, size
|
||||
of CheckedAddM: checkedBinop `+`
|
||||
of CheckedSubM: checkedBinop `-`
|
||||
of CheckedMulM: checkedBinop `*`
|
||||
@@ -958,8 +998,7 @@ proc eval(c: Bytecode; pc: CodePos; s: StackFrame; result: pointer; size: int) =
|
||||
|
||||
of StrValM:
|
||||
# binary compatible and no deep copy required:
|
||||
copyMem(cast[ptr string](result), addr(c.m.lit.strings[c[pc].litId]), sizeof(string))
|
||||
# XXX not correct!
|
||||
copyMem(cast[ptr string](result), addr(c.strings[c[pc].litId]), sizeof(string))
|
||||
of ObjConstrM:
|
||||
for offset, size, val in triples(c, pc):
|
||||
eval c, val, s, result+!offset, size
|
||||
@@ -1013,31 +1052,41 @@ proc evalProc(c: Bytecode; pc: CodePos; s: StackFrame): CodePos =
|
||||
assert procSym < ForwardedProc
|
||||
result = CodePos(procSym)
|
||||
|
||||
proc echoImpl(c: Bytecode; pc: CodePos; s: StackFrame) =
|
||||
type StringArray = object
|
||||
len: int
|
||||
data: ptr UncheckedArray[string]
|
||||
var sa = default(StringArray)
|
||||
proc echoImpl(c: Bytecode; pc: CodePos; frame: StackFrame) =
|
||||
var s = default(NimStringVM)
|
||||
for a in sonsFrom1(c, pc):
|
||||
eval(c, a, s, addr(sa), sizeof(sa))
|
||||
for i in 0..<sa.len:
|
||||
stdout.write sa.data[i]
|
||||
assert c[a].kind == ArrayConstrM
|
||||
let elemSize = c.code[a.firstSon].operand.int
|
||||
for ch in sonsFrom1(c, a):
|
||||
eval c, ch, frame, addr s, elemSize
|
||||
if s.len > 0:
|
||||
discard stdout.writeBuffer(addr(s.p.data[0]), s.len)
|
||||
stdout.write "\n"
|
||||
stdout.flushFile()
|
||||
|
||||
proc evalBuiltin(c: Bytecode; pc: CodePos; s: StackFrame; prc: CodePos; didEval: var bool): CodePos =
|
||||
type
|
||||
EvalBuiltinState = enum
|
||||
DidNothing, DidEval, DidError
|
||||
|
||||
proc evalBuiltin(c: Bytecode; pc: CodePos; s: StackFrame; prc: CodePos; state: var EvalBuiltinState): CodePos =
|
||||
var prc = prc
|
||||
while true:
|
||||
case c[prc].kind
|
||||
of PragmaPairM:
|
||||
let (x, y) = sons2(c.code, prc)
|
||||
if cast[PragmaKey](c[x]) == CoreName:
|
||||
let key = cast[PragmaKey](c[x].operand)
|
||||
case key
|
||||
of CoreName:
|
||||
let lit = c[y].litId
|
||||
case c.m.lit.strings[lit]
|
||||
of "echoBinSafe": echoImpl(c, pc, s)
|
||||
else: discard
|
||||
echo "running compilerproc: ", c.m.lit.strings[lit]
|
||||
didEval = true
|
||||
else:
|
||||
raiseAssert "cannot eval: " & c.m.lit.strings[lit]
|
||||
state = DidEval
|
||||
of HeaderImport, DllImport:
|
||||
let lit = c[y].litId
|
||||
raiseAssert "cannot eval: " & c.m.lit.strings[lit]
|
||||
else: discard
|
||||
of PragmaIdM, AllocLocals: discard
|
||||
else: break
|
||||
next c, prc
|
||||
@@ -1045,52 +1094,63 @@ proc evalBuiltin(c: Bytecode; pc: CodePos; s: StackFrame; prc: CodePos; didEval:
|
||||
|
||||
proc exec(c: Bytecode; pc: CodePos; u: ref Universe) =
|
||||
var pc = pc
|
||||
var s = StackFrame(u: u)
|
||||
var frame = StackFrame(u: u)
|
||||
while pc.int < c.code.len:
|
||||
when false: # c.interactive:
|
||||
echo "running: ", pc.int
|
||||
debug c, pc
|
||||
|
||||
case c.code[pc].kind
|
||||
of GotoM:
|
||||
pc = CodePos(c.code[pc].operand)
|
||||
of AsgnM:
|
||||
let (sz, a, b) = sons3(c.code, pc)
|
||||
let dest = evalAddr(c, a, s)
|
||||
eval(c, b, s, dest, c.code[sz].operand.int)
|
||||
let dest = evalAddr(c, a, frame)
|
||||
eval(c, b, frame, dest, c.code[sz].operand.int)
|
||||
next c, pc
|
||||
of StoreM:
|
||||
let (sz, a, b) = sons3(c.code, pc)
|
||||
let destPtr = evalAddr(c, a, s)
|
||||
let destPtr = evalAddr(c, a, frame)
|
||||
let dest = cast[ptr pointer](destPtr)[]
|
||||
eval(c, b, s, dest, c.code[sz].operand.int)
|
||||
eval(c, b, frame, dest, c.code[sz].operand.int)
|
||||
next c, pc
|
||||
of CallM:
|
||||
# No support for return values, these are mapped to `var T` parameters!
|
||||
var prc = evalProc(c, pc.firstSon, s)
|
||||
var prc = evalProc(c, pc.firstSon, frame)
|
||||
assert c.code[prc.firstSon].kind == AllocLocals
|
||||
let frameSize = int c.code[prc.firstSon].operand
|
||||
# skip stupid stuff:
|
||||
var didEval = false
|
||||
prc = evalBuiltin(c, pc, s, prc.firstSon, didEval)
|
||||
if didEval:
|
||||
var evalState = DidNothing
|
||||
prc = evalBuiltin(c, pc, frame, prc.firstSon, evalState)
|
||||
if evalState != DidNothing:
|
||||
next c, pc
|
||||
if pc.int < c.code.len and c.code[pc].kind == CheckedGotoM:
|
||||
if evalState == DidEval:
|
||||
next c, pc
|
||||
else:
|
||||
pc = CodePos(c.code[pc].operand)
|
||||
else:
|
||||
# setup storage for the proc already:
|
||||
let callInstr = pc
|
||||
next c, pc
|
||||
let s2 = newStackFrame(frameSize, s, pc)
|
||||
let s2 = newStackFrame(frameSize, frame, pc)
|
||||
for a in sonsFrom1(c, callInstr):
|
||||
assert c[prc].kind == SummonParamM
|
||||
let paramAddr = c[prc].operand
|
||||
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
|
||||
eval(c, a, s2, s2.locals +! paramAddr, paramSize)
|
||||
frame = s2
|
||||
pc = prc
|
||||
of RetM:
|
||||
pc = s.returnAddr
|
||||
s = popStackFrame(s)
|
||||
pc = frame.returnAddr
|
||||
if c.code[pc].kind == CheckedGotoM:
|
||||
pc = frame.jumpTo
|
||||
frame = popStackFrame(frame)
|
||||
of SelectM:
|
||||
let pc2 = evalSelect(c, pc, s)
|
||||
let pc2 = evalSelect(c, pc, frame)
|
||||
if pc2.int >= 0:
|
||||
pc = pc2
|
||||
else:
|
||||
@@ -1107,8 +1167,9 @@ 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
|
||||
#if bc.interactive:
|
||||
# echo "RUnning: "
|
||||
# debug bc, t, pc
|
||||
preprocess c, bc, t, pc, {}
|
||||
next t, pc
|
||||
exec bc, start, nil
|
||||
|
||||
@@ -148,9 +148,10 @@ proc processPipelineModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator
|
||||
if s == nil:
|
||||
rawMessage(graph.config, errCannotOpenFile, filename.string)
|
||||
return false
|
||||
graph.interactive = false
|
||||
else:
|
||||
s = stream
|
||||
|
||||
graph.interactive = stream.kind == llsStdIn
|
||||
while true:
|
||||
syntaxes.openParser(p, fileIdx, s, graph.cache, graph.config)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user