|
| 1 | +# |
| 2 | +# |
| 3 | +# The Nim Compiler |
| 4 | +# (c) Copyright 2020 Andreas Rumpf |
| 5 | +# |
| 6 | +# See the file "copying.txt", included in this |
| 7 | +# distribution, for details about the copyright. |
| 8 | +# |
| 9 | + |
| 10 | +# included from cgen.nim |
| 11 | + |
| 12 | +## Code specialization instead of the old, incredibly slow 'genericReset' |
| 13 | +## implementation. |
| 14 | + |
| 15 | +proc specializeResetT(p: BProc, accessor: Rope, typ: PType) |
| 16 | + |
| 17 | +proc specializeResetN(p: BProc, accessor: Rope, n: PNode; |
| 18 | + typ: PType) = |
| 19 | + if n == nil: return |
| 20 | + case n.kind |
| 21 | + of nkRecList: |
| 22 | + for i in 0..<n.len: |
| 23 | + specializeResetN(p, accessor, n[i], typ) |
| 24 | + of nkRecCase: |
| 25 | + if (n[0].kind != nkSym): internalError(p.config, n.info, "specializeResetN") |
| 26 | + let disc = n[0].sym |
| 27 | + if disc.loc.r == nil: fillObjectFields(p.module, typ) |
| 28 | + if disc.loc.t == nil: |
| 29 | + internalError(p.config, n.info, "specializeResetN()") |
| 30 | + lineF(p, cpsStmts, "switch ($1.$2) {$n", [accessor, disc.loc.r]) |
| 31 | + for i in 1..<n.len: |
| 32 | + let branch = n[i] |
| 33 | + assert branch.kind in {nkOfBranch, nkElse} |
| 34 | + if branch.kind == nkOfBranch: |
| 35 | + genCaseRange(p, branch) |
| 36 | + else: |
| 37 | + lineF(p, cpsStmts, "default:$n", []) |
| 38 | + specializeResetN(p, accessor, lastSon(branch), typ) |
| 39 | + lineF(p, cpsStmts, "break;$n", []) |
| 40 | + lineF(p, cpsStmts, "} $n", []) |
| 41 | + specializeResetT(p, "$1.$2" % [accessor, disc.loc.r], disc.loc.t) |
| 42 | + of nkSym: |
| 43 | + let field = n.sym |
| 44 | + if field.typ.kind == tyVoid: return |
| 45 | + if field.loc.r == nil: fillObjectFields(p.module, typ) |
| 46 | + if field.loc.t == nil: |
| 47 | + internalError(p.config, n.info, "specializeResetN()") |
| 48 | + specializeResetT(p, "$1.$2" % [accessor, field.loc.r], field.loc.t) |
| 49 | + else: internalError(p.config, n.info, "specializeResetN()") |
| 50 | + |
| 51 | +proc specializeResetT(p: BProc, accessor: Rope, typ: PType) = |
| 52 | + if typ == nil: return |
| 53 | + |
| 54 | + case typ.kind |
| 55 | + of tyGenericInst, tyGenericBody, tyTypeDesc, tyAlias, tyDistinct, tyInferred, |
| 56 | + tySink, tyOwned: |
| 57 | + specializeResetT(p, accessor, lastSon(typ)) |
| 58 | + of tyArray: |
| 59 | + let arraySize = lengthOrd(p.config, typ[0]) |
| 60 | + var i: TLoc |
| 61 | + getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), i) |
| 62 | + linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n", |
| 63 | + [i.r, arraySize]) |
| 64 | + specializeResetT(p, ropecg(p.module, "$1[$2]", [accessor, i.r]), typ[1]) |
| 65 | + lineF(p, cpsStmts, "}$n", []) |
| 66 | + of tyObject: |
| 67 | + for i in 0..<typ.len: |
| 68 | + var x = typ[i] |
| 69 | + if x != nil: x = x.skipTypes(skipPtrs) |
| 70 | + specializeResetT(p, accessor.parentObj(p.module), x) |
| 71 | + if typ.n != nil: specializeResetN(p, accessor, typ.n, typ) |
| 72 | + of tyTuple: |
| 73 | + let typ = getUniqueType(typ) |
| 74 | + for i in 0..<typ.len: |
| 75 | + specializeResetT(p, ropecg(p.module, "$1.Field$2", [accessor, i]), typ[i]) |
| 76 | + |
| 77 | + of tyString, tyRef, tySequence: |
| 78 | + lineCg(p, cpsStmts, "#unsureAsgnRef((void**)&$1, NIM_NIL);$n", [accessor]) |
| 79 | + |
| 80 | + of tyProc: |
| 81 | + if typ.callConv == ccClosure: |
| 82 | + lineCg(p, cpsStmts, "#unsureAsgnRef((void**)&$1.ClE_0, NIM_NIL);$n", [accessor]) |
| 83 | + lineCg(p, cpsStmts, "$1.ClP_0 = NIM_NIL;$n", [accessor]) |
| 84 | + else: |
| 85 | + lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [accessor]) |
| 86 | + of tyChar, tyBool, tyEnum, tyInt..tyUInt64: |
| 87 | + lineCg(p, cpsStmts, "$1 = 0;$n", [accessor]) |
| 88 | + of tyCString, tyPointer, tyPtr, tyVar, tyLent: |
| 89 | + lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [accessor]) |
| 90 | + else: |
| 91 | + discard |
| 92 | + |
| 93 | +proc specializeReset(p: BProc, a: TLoc) = |
| 94 | + specializeResetT(p, rdLoc(a), a.t) |
0 commit comments