Skip to content

Commit b4093ff

Browse files
authored
Merge branch 'devel' into earlier-top-level-emit-handling
2 parents a57c929 + c86adbf commit b4093ff

File tree

8 files changed

+108
-46
lines changed

8 files changed

+108
-46
lines changed

compiler/backend/ccgexprs.nim

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -515,32 +515,6 @@ proc genCStringElem(p: BProc, n, x, y: CgNode, d: var TLoc) =
515515
putIntoDest(p, d, n,
516516
ropecg(p.module, "$1[$2]", [rdLoc(a), rdCharLoc(b)]), a.storage)
517517

518-
proc genBoundsCheck(p: BProc; arr, a, b: TLoc, exit: CgNode) =
519-
# types that map to C pointers need to be skipped here too, since no
520-
# dereference is generated for ``ptr array`` and the like
521-
let ty = skipTypes(arr.t, abstractVarRange + {tyPtr, tyRef, tyLent})
522-
case ty.kind
523-
of tyOpenArray, tyVarargs:
524-
if reifiedOpenArray(p, arr.lode):
525-
linefmt(p, cpsStmts,
526-
"if ($2-$1 != -1 && " &
527-
"((NU)($1) >= (NU)($3.Field1) || (NU)($2) >= (NU)($3.Field1))){ #raiseIndexError(); $4}$n",
528-
[rdLoc(a), rdLoc(b), rdLoc(arr), raiseInstr(p, exit)])
529-
else:
530-
linefmt(p, cpsStmts,
531-
"if ($2-$1 != -1 && " &
532-
"((NU)($1) >= (NU)($3Len_0) || (NU)($2) >= (NU)($3Len_0))){ #raiseIndexError(); $4}$n",
533-
[rdLoc(a), rdLoc(b), rdLoc(arr), raiseInstr(p, exit)])
534-
of tySequence, tyString:
535-
linefmt(p, cpsStmts,
536-
"if ($2-$1 != -1 && " &
537-
"((NU)($1) >= (NU)$3 || (NU)($2) >= (NU)$3)){ #raiseIndexError(); $4}$n",
538-
[rdLoc(a), rdLoc(b), lenExpr(p, arr), raiseInstr(p, exit)])
539-
of tyUncheckedArray, tyCstring:
540-
discard "no checks are used"
541-
else:
542-
unreachable(ty.kind)
543-
544518
proc genOpenArrayElem(p: BProc, n, x, y: CgNode, d: var TLoc) =
545519
var a, b: TLoc
546520
initLocExpr(p, x, a)
@@ -1416,12 +1390,6 @@ proc genMagicExpr(p: BProc, e: CgNode, d: var TLoc, op: TMagic) =
14161390
typ.add "*"
14171391

14181392
linefmt(p, cpsStmts, "$1 = ($2)($3);$n", [a.r, typ, rdLoc(b)])
1419-
of mChckBounds:
1420-
var arr, a, b: TLoc
1421-
initLocExpr(p, e[1], arr)
1422-
initLocExpr(p, e[2], a)
1423-
initLocExpr(p, e[3], b)
1424-
genBoundsCheck(p, arr, a, b, e.exit)
14251393
of mSamePayload:
14261394
var a, b: TLoc
14271395
initLocExpr(p, e[1], a)

compiler/backend/ccgstmts.nim

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,6 @@ proc genIf(p: BProc, n: CgNode) =
9595
lineF(p, cpsStmts, "if ($1)$n", [rdLoc(a)])
9696
startBlock(p)
9797

98-
proc exit(n: CgNode): CgNode =
99-
# XXX: exists as a convenience for overflow check, index check, etc.
100-
# code gen. Should be removed once those are fully lowered prior
101-
# to code generation
102-
case n.kind
103-
of cnkCheckedCall: n[^1]
104-
else: nil
105-
10698
proc raiseInstr(p: BProc, n: CgNode): Rope =
10799
if n != nil:
108100
case n.kind

compiler/mir/rtchecks.nim

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,35 @@ proc emitCheckedFloatOp(tree; call; graph; env; bu): Value =
564564
bu.emitCall(tree, call, env.addCompilerProc(graph, "raiseFloatOverflow")):
565565
bu.emitByVal result
566566

567+
proc emitBoundCheck(tree; call; graph; env; bu) =
568+
## Emits the lowered version of a bound check.
569+
case env.types.headerFor(tree[tree.argument(call, 0)].typ, Canonical).kind
570+
of tkSeq, tkString, tkOpenArray:
571+
let len = bu.wrapTemp env.types.sizeType:
572+
# note: lengthOpenArray works for all containers
573+
bu.buildMagicCall mLengthOpenArray, env.types.sizeType:
574+
bu.subTree mnkArg:
575+
bu.emitFrom(tree, NodePosition tree.argument(call, 0))
576+
577+
bu.emitCall(tree, call, env.addCompilerProc(graph, "chckBounds")):
578+
bu.emitByVal len
579+
bu.subTree mnkArg:
580+
bu.emitFrom(tree, NodePosition tree.argument(call, 1))
581+
bu.subTree mnkArg:
582+
bu.emitFrom(tree, NodePosition tree.argument(call, 2))
583+
of tkCstring:
584+
# TODO: don't emit a ``mChckBounds`` call for cstrings in the first place
585+
if tree[call].kind == mnkCheckedCall and
586+
tree[tree.last(call)].kind != mnkUnwind:
587+
# emit ``if false: raise``, so that the target label isn't unused
588+
bu.buildIf (bu.use env.makeLiteral(mnkUIntLit, Zero, BoolType)):
589+
bu.subTree mnkRaise:
590+
bu.emitFrom(tree, tree.last(call))
591+
else:
592+
discard "no local handler -> nothing to do"
593+
else:
594+
unreachable()
595+
567596
proc lowerChecks*(body; graph; env; changes: var Changeset) =
568597
## Lowers all magic calls implementing the run-time checks.
569598
template tree: MirTree = body.code
@@ -599,6 +628,10 @@ proc lowerChecks*(body; graph; env; changes: var Changeset) =
599628
let call = tree.parent(i)
600629
changes.replaceMulti(tree, tree.parent(call), bu):
601630
emitObjectCheck(tree, call, graph, env, bu)
631+
of mChckBounds:
632+
let call = tree.parent(i)
633+
changes.replaceMulti(tree, tree.parent(call), bu):
634+
emitBoundCheck(tree, call, graph, env, bu)
602635

603636
of mAddI, mSubI, mMulI, mModI, mDivI:
604637
let call = tree.parent(i)

compiler/mir/utils.nim

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ func add(result: var string, id: LabelId) =
189189
result.add 'L'
190190
result.addInt id.uint32
191191

192+
proc constToStr(nodes: MirTree, i: var int, result: var string, c: RenderCtx)
193+
192194
proc singleToStr(n: MirNode, result: var string, c: RenderCtx) =
193195
case n.kind
194196
of mnkParam:
@@ -197,7 +199,12 @@ proc singleToStr(n: MirNode, result: var string, c: RenderCtx) =
197199
result.addLocalName(n.local, "<L", c)
198200
of mnkConst:
199201
if isAnon(n.cnst):
200-
idToStr(result, extract(n.cnst), "<D") # "D" for "Data"
202+
if c.env.isNil:
203+
idToStr(result, extract(n.cnst), "<D") # "D" for "Data"
204+
else:
205+
result.add "<const> "
206+
var i = 0
207+
constToStr(c.env[][extract(n.cnst)], i, result, c)
201208
else:
202209
result.addName(n.cnst, "<C", c)
203210
of mnkGlobal:
@@ -483,6 +490,62 @@ proc exprToStr(nodes: MirTree, i: var int, result: var string, c: RenderCtx) =
483490
template exprToStr() =
484491
exprToStr(nodes, i, result, c)
485492

493+
proc constToStr(nodes: MirTree, i: var int, result: var string, c: RenderCtx) =
494+
template arg() =
495+
inc i # skip the operand descriptor
496+
constToStr(nodes, i, result, c)
497+
498+
template tree(start: string, body: untyped) =
499+
result.add start
500+
body
501+
502+
let n {.cursor.} = next(nodes, i)
503+
case n.kind
504+
of mnkNilLit, mnkIntLit, mnkUIntLit, mnkFloatLit, mnkStrLit, mnkProcVal,
505+
mnkAstLit:
506+
singleToStr(n, result, c)
507+
of mnkObjConstr, mnkRefConstr:
508+
let typ = n.typ
509+
tree "(":
510+
commaSeparated n.len:
511+
tree "":
512+
fieldToStr(next(nodes, i).field, typ, result, c)
513+
result.add ": "
514+
constToStr(nodes, i, result, c)
515+
result.add ")"
516+
of mnkArrayConstr:
517+
tree "[":
518+
commaSeparated n.len:
519+
arg()
520+
result.add "]"
521+
of mnkSeqConstr:
522+
tree "@[":
523+
commaSeparated n.len:
524+
arg()
525+
result.add "]"
526+
of mnkTupleConstr:
527+
tree "(":
528+
commaSeparated n.len:
529+
arg()
530+
result.add ")"
531+
of mnkClosureConstr:
532+
tree "closure (":
533+
commaSeparated n.len:
534+
arg()
535+
result.add ")"
536+
of mnkSetConstr:
537+
tree "{":
538+
commaSeparated n.len:
539+
constToStr(nodes, i, result, c)
540+
result.add "}"
541+
of mnkRange:
542+
tree "":
543+
constToStr(nodes, i, result, c)
544+
result.add " .. "
545+
constToStr(nodes, i, result, c)
546+
else:
547+
result.error(n)
548+
486549
proc renderNameWithType(tree: MirTree, i: var int, result: var string,
487550
c: RenderCtx) =
488551
let n {.cursor.} = next(tree, i)

lib/system/chcks.nim

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,9 @@ proc chckNil(p: pointer) =
122122
when defined(nimV2):
123123
proc raiseObjectCaseTransition() {.compilerproc.} =
124124
sysFatal(FieldDefect, "assignment to discriminant changes object branch")
125+
126+
proc chckBounds(len: int, lo, hi: int) {.compilerproc, inline.} =
127+
## Bounds check for integer-sized containers.
128+
let ulen = cast[uint](len)
129+
if hi-lo != -1 and (cast[uint](lo) >= ulen or cast[uint](hi) >= ulen):
130+
raiseIndexError()

tests/arc/topt_cursor.nim

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ discard """
44
nimout: '''--expandArc: main
55
66
scope:
7-
def_cursor x: (string, int) = <D0>
7+
def_cursor x: (string, int) = <const> ("hi", 5)
88
scope:
99
if cond:
1010
scope:
11-
x = <D1>
11+
x = <const> ("different", 54)
1212
goto [L1]
1313
scope:
14-
x = <D2>
14+
x = <const> ("string here", 80)
1515
L1:
1616
def_cursor _3: (string, int) = x
1717
def _4: string = $(arg _3) -> [Unwind]

tests/exception/truntime_check_panics.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ scope:
1616
def _7: int = addI(arg i, arg i)
1717
def _8: int = unaryMinusI(arg i)
1818
def _9: range 0..1(int) = chckRange(arg i, arg 0, arg 1)
19-
chckField(arg <D0>, arg o.kind, arg false, arg "field \'x\' is not accessible for type \'Object\' using \'kind = ")
19+
chckField(arg <const> {true}, arg o.kind, arg false, arg "field \'x\' is not accessible for type \'Object\' using \'kind = ")
2020
discard o.kind.x
2121
def _11: bool = isNil(arg r)
2222
def _10: bool = not(arg _11)

tests/optimization/tno_unnecessary_bound_check_for_contains.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ scope:
66
def _2: bool
77
def _3: bool = leI(arg 0'i8, arg x)
88
if _3:
9-
_2 := inSet(arg <D0>, arg x)
9+
_2 := inSet(arg <const> {1, 2, 3}, arg x)
1010
result = _2
1111
goto [L1]
1212
L1:

0 commit comments

Comments
 (0)