Check there are no side effects before optimizing away compile time expressions. (#9934)
This commit is contained in:
parent
bcbe317d17
commit
e87910197a
3 changed files with 56 additions and 8 deletions
|
|
@ -710,7 +710,9 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
|
||||||
let a = getConstExpr(c.module, n.sons[i], c.graph)
|
let a = getConstExpr(c.module, n.sons[i], c.graph)
|
||||||
if a == nil: return n
|
if a == nil: return n
|
||||||
call.add(a)
|
call.add(a)
|
||||||
|
|
||||||
#echo "NOW evaluating at compile time: ", call.renderTree
|
#echo "NOW evaluating at compile time: ", call.renderTree
|
||||||
|
if c.inStaticContext == 0 or sfNoSideEffect in callee.flags:
|
||||||
if sfCompileTime in callee.flags:
|
if sfCompileTime in callee.flags:
|
||||||
result = evalStaticExpr(c.module, c.graph, call, c.p.owner)
|
result = evalStaticExpr(c.module, c.graph, call, c.p.owner)
|
||||||
if result.isNil:
|
if result.isNil:
|
||||||
|
|
@ -720,6 +722,8 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
|
||||||
result = evalConstExpr(c.module, c.graph, call)
|
result = evalConstExpr(c.module, c.graph, call)
|
||||||
if result.isNil: result = n
|
if result.isNil: result = n
|
||||||
else: result = fixupTypeAfterEval(c, result, n)
|
else: result = fixupTypeAfterEval(c, result, n)
|
||||||
|
else:
|
||||||
|
result = n
|
||||||
#if result != n:
|
#if result != n:
|
||||||
# echo "SUCCESS evaluated at compile time: ", call.renderTree
|
# echo "SUCCESS evaluated at compile time: ", call.renderTree
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -548,6 +548,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||||
|
|
||||||
proc semConst(c: PContext, n: PNode): PNode =
|
proc semConst(c: PContext, n: PNode): PNode =
|
||||||
result = copyNode(n)
|
result = copyNode(n)
|
||||||
|
inc c.inStaticContext
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var a = n.sons[i]
|
var a = n.sons[i]
|
||||||
if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
|
if c.config.cmd == cmdIdeTools: suggestStmt(c, a)
|
||||||
|
|
@ -607,6 +608,7 @@ proc semConst(c: PContext, n: PNode): PNode =
|
||||||
v.ast = def[j]
|
v.ast = def[j]
|
||||||
b.sons[j] = newSymNode(v)
|
b.sons[j] = newSymNode(v)
|
||||||
addSon(result,b)
|
addSon(result,b)
|
||||||
|
dec c.inStaticContext
|
||||||
|
|
||||||
include semfields
|
include semfields
|
||||||
|
|
||||||
|
|
|
||||||
42
tests/vm/tcompiletimesideeffects.nim
Normal file
42
tests/vm/tcompiletimesideeffects.nim
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
discard """
|
||||||
|
output:
|
||||||
|
'''
|
||||||
|
@[0, 1, 2]
|
||||||
|
@[3, 4, 5]
|
||||||
|
@[0, 1, 2]
|
||||||
|
3
|
||||||
|
4
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
template runNTimes(n: int, f : untyped) : untyped =
|
||||||
|
var accum: seq[type(f)]
|
||||||
|
for i in 0..n-1:
|
||||||
|
accum.add(f)
|
||||||
|
accum
|
||||||
|
|
||||||
|
var state {.compileTime.} : int = 0
|
||||||
|
proc fill(): int {.compileTime.} =
|
||||||
|
result = state
|
||||||
|
inc state
|
||||||
|
|
||||||
|
# invoke fill() at compile time as a compile time expression
|
||||||
|
const C1 = runNTimes(3, fill())
|
||||||
|
echo C1
|
||||||
|
|
||||||
|
# invoke fill() at compile time as a set of compile time statements
|
||||||
|
const C2 =
|
||||||
|
block:
|
||||||
|
runNTimes(3, fill())
|
||||||
|
echo C2
|
||||||
|
|
||||||
|
# invoke fill() at compile time after a compile time reset of state
|
||||||
|
const C3 =
|
||||||
|
block:
|
||||||
|
state = 0
|
||||||
|
runNTimes(3, fill())
|
||||||
|
echo C3
|
||||||
|
|
||||||
|
# evaluate fill() at compile time and use the results at runtime
|
||||||
|
echo fill()
|
||||||
|
echo fill()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue