Field checks for everybody (#8957)

* Field checks for JS backend

* Clean nkCall nodes with no arguments

Generating a nkEmpty in place of no arguments makes no sense form the
AST point of view and also trips up the VM codegen.

* Field checks for VM backend

* Test case for #6612

This patchset fixes #6612

* Add test case for LHS double evaluation

* Prevent LHS double-eval for JS backend

* Prevent double evaluation in VM backend
This commit is contained in:
LemonBoy 2018-10-09 19:54:12 +02:00 • committed by Andreas Rumpf
commit ee14ace5d3
10 changed files with 223 additions and 43 deletions

View file

@ -281,15 +281,16 @@ proc genDeref*(n: PNode): PNode =
n.typ.skipTypes(abstractInst).sons[0])
result.add n
proc callCodegenProc*(g: ModuleGraph; name: string, arg1: PNode;
arg2, arg3, optionalArgs: PNode = nil): PNode =
result = newNodeI(nkCall, arg1.info)
proc callCodegenProc*(g: ModuleGraph; name: string;
info: TLineInfo = unknownLineInfo();
arg1, arg2, arg3, optionalArgs: PNode = nil): PNode =
result = newNodeI(nkCall, info)
let sym = magicsys.getCompilerProc(g, name)
if sym == nil:
localError(g.config, arg1.info, "system module needs: " & name)
localError(g.config, info, "system module needs: " & name)
else:
result.add newSymNode(sym)
result.add arg1
if arg1 != nil: result.add arg1
if arg2 != nil: result.add arg2
if arg3 != nil: result.add arg3
if optionalArgs != nil:
@ -410,7 +411,8 @@ proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym;
threadLocalBarrier = addLocalVar(g, varSection2, nil, argsParam.owner,
barrier.typ, barrier)
body.add varSection2
body.add callCodegenProc(g, "barrierEnter", threadLocalBarrier.newSymNode)
body.add callCodegenProc(g, "barrierEnter", threadLocalBarrier.info,
threadLocalBarrier.newSymNode)
var threadLocalProm: PSym
if spawnKind == srByVar:
threadLocalProm = addLocalVar(g, varSection, nil, argsParam.owner, fv.typ, fv)
@ -425,7 +427,8 @@ proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym;
body.add newAsgnStmt(indirectAccess(threadLocalProm.newSymNode,
"owner", fv.info, g.cache), threadParam.newSymNode)
body.add callCodegenProc(g, "nimArgsPassingDone", threadParam.newSymNode)
body.add callCodegenProc(g, "nimArgsPassingDone", threadParam.info,
threadParam.newSymNode)
if spawnKind == srByVar:
body.add newAsgnStmt(genDeref(threadLocalProm.newSymNode), call)
elif fv != nil:
@ -444,11 +447,13 @@ proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym;
if barrier == nil:
# by now 'fv' is shared and thus might have beeen overwritten! we need
# to use the thread-local view instead:
body.add callCodegenProc(g, "nimFlowVarSignal", threadLocalProm.newSymNode)
body.add callCodegenProc(g, "nimFlowVarSignal", threadLocalProm.info,
threadLocalProm.newSymNode)
else:
body.add call
if barrier != nil:
body.add callCodegenProc(g, "barrierLeave", threadLocalBarrier.newSymNode)
body.add callCodegenProc(g, "barrierLeave", threadLocalBarrier.info,
threadLocalBarrier.newSymNode)
var params = newNodeI(nkFormalParams, f.info)
params.add newNodeI(nkEmpty, f.info)
@ -710,7 +715,8 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P
# create flowVar:
result.add newFastAsgnStmt(fvField, callProc(spawnExpr[^1]))
if barrier == nil:
result.add callCodegenProc(g, "nimFlowVarCreateSemaphore", fvField)
result.add callCodegenProc(g, "nimFlowVarCreateSemaphore", fvField.info,
fvField)
elif spawnKind == srByVar:
var field = newSym(skField, getIdent(g.cache, "fv"), owner, n.info, g.config.options)
@ -723,7 +729,7 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P
let wrapper = createWrapperProc(g, fn, threadParam, argsParam,
varSection, varInit, call,
barrierAsExpr, fvAsExpr, spawnKind)
result.add callCodegenProc(g, "nimSpawn" & $spawnExpr.len, wrapper.newSymNode,
genAddrOf(scratchObj.newSymNode), nil, spawnExpr)
result.add callCodegenProc(g, "nimSpawn" & $spawnExpr.len, wrapper.info,
wrapper.newSymNode, genAddrOf(scratchObj.newSymNode), nil, spawnExpr)
if spawnKind == srFlowVar: result.add fvField