diff options
Diffstat (limited to 'compiler/lowerings.nim')
-rw-r--r-- | compiler/lowerings.nim | 71 |
1 files changed, 43 insertions, 28 deletions
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index 5b61a9cae..e1fb09e44 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -56,6 +56,7 @@ proc lowerTupleUnpacking*(n: PNode; owner: PSym): PNode = result.add newAsgnStmt(newSymNode(temp), value) for i in 0 .. n.len-3: + if n.sons[i].kind == nkSym: v.addVar(n.sons[i]) result.add newAsgnStmt(n.sons[i], newTupleAccess(value, i)) proc createObj*(owner: PSym, info: TLineInfo): PType = @@ -122,8 +123,8 @@ proc indirectAccess*(a: PNode, b: string, info: TLineInfo): PNode = if t == nil: break t = t.skipTypes(abstractInst) #if field == nil: + # echo "FIELD ", b # debug deref.typ - # echo deref.typ.id internalAssert field != nil addSon(deref, a) result = newNodeI(nkDotExpr, info) @@ -185,14 +186,14 @@ proc callProc(a: PNode): PNode = # - a proc returning non GC'ed memory --> pass as hidden 'var' parameter # - not in a parallel environment --> requires a flowVar for memory safety type - TSpawnResult = enum + TSpawnResult* = enum srVoid, srFlowVar, srByVar TFlowVarKind = enum fvInvalid # invalid type T for 'FlowVar[T]' fvGC # FlowVar of a GC'ed type fvBlob # FlowVar of a blob type -proc spawnResult(t: PType; inParallel: bool): TSpawnResult = +proc spawnResult*(t: PType; inParallel: bool): TSpawnResult = if t.isEmptyType: srVoid elif inParallel and not containsGarbageCollectedRef(t): srByVar else: srFlowVar @@ -202,7 +203,8 @@ proc flowVarKind(t: PType): TFlowVarKind = elif containsGarbageCollectedRef(t): fvInvalid else: fvBlob -proc addLocalVar(varSection: PNode; owner: PSym; typ: PType; v: PNode): PSym = +proc addLocalVar(varSection, varInit: PNode; owner: PSym; typ: PType; + v: PNode): PSym = result = newSym(skTemp, getIdent(genPrefix), owner, varSection.info) result.typ = typ incl(result.flags, sfFromGeneric) @@ -210,8 +212,14 @@ proc addLocalVar(varSection: PNode; owner: PSym; typ: PType; v: PNode): PSym = var vpart = newNodeI(nkIdentDefs, varSection.info, 3) vpart.sons[0] = newSymNode(result) vpart.sons[1] = ast.emptyNode - vpart.sons[2] = v + vpart.sons[2] = if varInit.isNil: v else: ast.emptyNode varSection.add vpart + if varInit != nil: + let deepCopyCall = newNodeI(nkCall, varInit.info, 3) + deepCopyCall.sons[0] = newSymNode(createMagic("deepCopy", mDeepCopy)) + deepCopyCall.sons[1] = newSymNode(result) + deepCopyCall.sons[2] = v + varInit.add deepCopyCall discard """ We generate roughly this: @@ -244,24 +252,24 @@ stmtList: """ proc createWrapperProc(f: PNode; threadParam, argsParam: PSym; - varSection, call, barrier, fv: PNode; + varSection, varInit, call, barrier, fv: PNode; spawnKind: TSpawnResult): PSym = var body = newNodeI(nkStmtList, f.info) var threadLocalBarrier: PSym if barrier != nil: - var varSection = newNodeI(nkVarSection, barrier.info) - threadLocalBarrier = addLocalVar(varSection, argsParam.owner, + var varSection2 = newNodeI(nkVarSection, barrier.info) + threadLocalBarrier = addLocalVar(varSection2, nil, argsParam.owner, barrier.typ, barrier) - body.add varSection + body.add varSection2 body.add callCodeGenProc("barrierEnter", threadLocalBarrier.newSymNode) var threadLocalProm: PSym if spawnKind == srByVar: - threadLocalProm = addLocalVar(varSection, argsParam.owner, fv.typ, fv) + threadLocalProm = addLocalVar(varSection, nil, argsParam.owner, fv.typ, fv) elif fv != nil: internalAssert fv.typ.kind == tyGenericInst - threadLocalProm = addLocalVar(varSection, argsParam.owner, fv.typ, fv) - + threadLocalProm = addLocalVar(varSection, nil, argsParam.owner, fv.typ, fv) body.add varSection + body.add varInit if fv != nil and spawnKind != srByVar: # generate: # fv.owner = threadParam @@ -314,7 +322,8 @@ proc createCastExpr(argsParam: PSym; objType: PType): PNode = result.typ.rawAddSon(objType) proc setupArgsForConcurrency(n: PNode; objType: PType; scratchObj: PSym, - castExpr, call, varSection, result: PNode) = + castExpr, call, + varSection, varInit, result: PNode) = let formals = n[0].typ.n let tmpName = getIdent(genPrefix) for i in 1 .. <n.len: @@ -323,8 +332,8 @@ proc setupArgsForConcurrency(n: PNode; objType: PType; scratchObj: PSym, var argType = n[i].typ.skipTypes(abstractInst) if i < formals.len and formals[i].typ.kind == tyVar: localError(n[i].info, "'spawn'ed function cannot have a 'var' parameter") - elif containsTyRef(argType): - localError(n[i].info, "'spawn'ed function cannot refer to 'ref'/closure") + #elif containsTyRef(argType): + # localError(n[i].info, "'spawn'ed function cannot refer to 'ref'/closure") let fieldname = if i < formals.len: formals[i].sym.name else: tmpName var field = newSym(skField, fieldname, objType.owner, n.info) @@ -332,8 +341,8 @@ proc setupArgsForConcurrency(n: PNode; objType: PType; scratchObj: PSym, objType.addField(field) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[i]) - let temp = addLocalVar(varSection, objType.owner, argType, - indirectAccess(castExpr, field, n.info)) + let temp = addLocalVar(varSection, varInit, objType.owner, argType, + indirectAccess(castExpr, field, n.info)) call.add(newSymNode(temp)) proc getRoot*(n: PNode): PSym = @@ -367,7 +376,8 @@ proc genHigh(n: PNode): PNode = result.sons[1] = n proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym; - castExpr, call, varSection, result: PNode) = + castExpr, call, + varSection, varInit, result: PNode) = let formals = n[0].typ.n let tmpName = getIdent(genPrefix) # we need to copy the foreign scratch object fields into local variables @@ -376,8 +386,8 @@ proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym; let n = n[i] let argType = skipTypes(if i < formals.len: formals[i].typ else: n.typ, abstractInst) - if containsTyRef(argType): - localError(n.info, "'spawn'ed function cannot refer to 'ref'/closure") + #if containsTyRef(argType): + # localError(n.info, "'spawn'ed function cannot refer to 'ref'/closure") let fieldname = if i < formals.len: formals[i].sym.name else: tmpName var field = newSym(skField, fieldname, objType.owner, n.info) @@ -403,7 +413,7 @@ proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym; result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldA), n[2]) result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), n[3]) - let threadLocal = addLocalVar(varSection, objType.owner, fieldA.typ, + let threadLocal = addLocalVar(varSection,nil, objType.owner, fieldA.typ, indirectAccess(castExpr, fieldA, n.info)) slice.sons[2] = threadLocal.newSymNode else: @@ -417,7 +427,7 @@ proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym; # the array itself does not need to go through a thread local variable: slice.sons[1] = genDeref(indirectAccess(castExpr, field, n.info)) - let threadLocal = addLocalVar(varSection, objType.owner, fieldB.typ, + let threadLocal = addLocalVar(varSection,nil, objType.owner, fieldB.typ, indirectAccess(castExpr, fieldB, n.info)) slice.sons[3] = threadLocal.newSymNode call.add slice @@ -428,7 +438,7 @@ proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym; field.typ = a.typ objType.addField(field) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a) - let threadLocal = addLocalVar(varSection, objType.owner, field.typ, + let threadLocal = addLocalVar(varSection,nil, objType.owner, field.typ, indirectAccess(castExpr, field, n.info)) call.add(genDeref(threadLocal.newSymNode)) else: @@ -436,7 +446,8 @@ proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym; field.typ = argType objType.addField(field) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n) - let threadLocal = addLocalVar(varSection, objType.owner, field.typ, + let threadLocal = addLocalVar(varSection, varInit, + objType.owner, field.typ, indirectAccess(castExpr, field, n.info)) call.add(threadLocal.newSymNode) @@ -504,10 +515,13 @@ proc wrapProcForSpawn*(owner: PSym; spawnExpr: PNode; retType: PType; call.add(fn) var varSection = newNodeI(nkVarSection, n.info) + var varInit = newNodeI(nkStmtList, n.info) if barrier.isNil: - setupArgsForConcurrency(n, objType, scratchObj, castExpr, call, varSection, result) - else: - setupArgsForParallelism(n, objType, scratchObj, castExpr, call, varSection, result) + setupArgsForConcurrency(n, objType, scratchObj, castExpr, call, + varSection, varInit, result) + else: + setupArgsForParallelism(n, objType, scratchObj, castExpr, call, + varSection, varInit, result) var barrierAsExpr: PNode = nil if barrier != nil: @@ -539,7 +553,8 @@ proc wrapProcForSpawn*(owner: PSym; spawnExpr: PNode; retType: PType; fvAsExpr = indirectAccess(castExpr, field, n.info) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), genAddrOf(dest)) - let wrapper = createWrapperProc(fn, threadParam, argsParam, varSection, call, + let wrapper = createWrapperProc(fn, threadParam, argsParam, + varSection, varInit, call, barrierAsExpr, fvAsExpr, spawnKind) result.add callCodeGenProc("nimSpawn", wrapper.newSymNode, genAddrOf(scratchObj.newSymNode)) |