diff options
author | Araq <rumpf_a@web.de> | 2014-05-30 13:15:54 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2014-05-30 13:15:54 +0200 |
commit | ea16aca09ec47e3d4393437dea4f398922acaba0 (patch) | |
tree | 4c53b3178710a6afd6ad3a533f136116de1afcfd /compiler | |
parent | 6470bd8f87b860c555556a2a965f6c8077e993ad (diff) | |
download | Nim-ea16aca09ec47e3d4393437dea4f398922acaba0.tar.gz |
correct code generation for tforstmt
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/lowerings.nim | 54 |
1 files changed, 34 insertions, 20 deletions
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index 13d4bf60e..5636d423f 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -160,8 +160,8 @@ We generate roughly this: proc f_wrapper(args) = barrierEnter(args.barrier) # for parallel statement - var a = args.a # copy strings/seqs; thread transfer; not generated for - # the 'parallel' statement + var a = args.a # thread transfer; deepCopy or shallowCopy or no copy + # depending on whether we're in a 'parallel' statement var b = args.b args.prom = nimCreatePromise(thread, sizeof(T)) # optional @@ -199,9 +199,9 @@ proc createNimCreatePromiseCall(prom, threadParam: PNode): PNode = proc createWrapperProc(f: PNode; threadParam, argsParam: PSym; varSection, call, barrier, prom: PNode): PSym = var body = newNodeI(nkStmtList, f.info) - body.add varSection if barrier != nil: body.add callCodeGenProc("barrierEnter", barrier) + body.add varSection if prom != nil: body.add createNimCreatePromiseCall(prom, threadParam.newSymNode) if barrier == nil: @@ -248,6 +248,17 @@ proc createCastExpr(argsParam: PSym; objType: PType): PNode = result.typ = newType(tyPtr, objType.owner) result.typ.rawAddSon(objType) +proc addLocalVar(varSection: PNode; owner: PSym; typ: PType; v: PNode): PSym = + result = newSym(skTemp, getIdent(genPrefix), owner, varSection.info) + result.typ = typ + incl(result.flags, sfFromGeneric) + + var vpart = newNodeI(nkIdentDefs, varSection.info, 3) + vpart.sons[0] = newSymNode(result) + vpart.sons[1] = ast.emptyNode + vpart.sons[2] = v + varSection.add vpart + proc setupArgsForConcurrency(n: PNode; objType: PType; scratchObj: PSym, castExpr, call, varSection, result: PNode) = let formals = n[0].typ.n @@ -267,16 +278,8 @@ proc setupArgsForConcurrency(n: PNode; objType: PType; scratchObj: PSym, objType.addField(field) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[i]) - var temp = newSym(skTemp, tmpName, objType.owner, n.info) - temp.typ = argType - incl(temp.flags, sfFromGeneric) - - var vpart = newNodeI(nkIdentDefs, n.info, 3) - vpart.sons[0] = newSymNode(temp) - vpart.sons[1] = ast.emptyNode - vpart.sons[2] = indirectAccess(castExpr, field, n.info) - varSection.add vpart - + let temp = addLocalVar(varSection, objType.owner, argType, + indirectAccess(castExpr, field, n.info)) call.add(newSymNode(temp)) proc getRoot*(n: PNode): PSym = @@ -310,9 +313,11 @@ proc genHigh(n: PNode): PNode = result.sons[1] = n proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym; - castExpr, call, result: PNode) = + castExpr, call, varSection, result: PNode) = let formals = n[0].typ.n let tmpName = getIdent(genPrefix) + # we need to copy the foreign scratch object fields into local variables + # for correctness: These are called 'threadLocal' here. for i in 1 .. <n.len: let n = n[i] let argType = skipTypes(if i < formals.len: formals[i].typ else: n.typ, @@ -344,7 +349,9 @@ proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym; result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldA), n[2]) result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), n[3]) - slice.sons[2] = indirectAccess(castExpr, fieldA, n.info) + let threadLocal = addLocalVar(varSection, objType.owner, fieldA.typ, + indirectAccess(castExpr, fieldA, n.info)) + slice.sons[2] = threadLocal.newSymNode else: let a = genAddrOf(n) field.typ = a.typ @@ -353,9 +360,12 @@ proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym; result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), genHigh(n)) slice.sons[2] = newIntLit(0) - + # the array itself does not need to go through a thread local variable: slice.sons[1] = genDeref(indirectAccess(castExpr, field, n.info)) - slice.sons[3] = indirectAccess(castExpr, fieldB, n.info) + + let threadLocal = addLocalVar(varSection, objType.owner, fieldB.typ, + indirectAccess(castExpr, fieldB, n.info)) + slice.sons[3] = threadLocal.newSymNode call.add slice elif (let size = computeSize(argType); size < 0 or size > 16) and n.getRoot != nil: @@ -364,13 +374,17 @@ proc setupArgsForParallelism(n: PNode; objType: PType; scratchObj: PSym; field.typ = a.typ objType.addField(field) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a) - call.add(genDeref(indirectAccess(castExpr, field, n.info))) + let threadLocal = addLocalVar(varSection, objType.owner, field.typ, + indirectAccess(castExpr, field, n.info)) + call.add(genDeref(threadLocal.newSymNode)) else: # boring case field.typ = argType objType.addField(field) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n) - call.add(indirectAccess(castExpr, field, n.info)) + let threadLocal = addLocalVar(varSection, objType.owner, field.typ, + indirectAccess(castExpr, field, n.info)) + call.add(threadLocal.newSymNode) proc wrapProcForSpawn*(owner: PSym; n: PNode; retType: PType; barrier, dest: PNode = nil): PNode = @@ -438,7 +452,7 @@ proc wrapProcForSpawn*(owner: PSym; n: PNode; retType: PType; if barrier.isNil: setupArgsForConcurrency(n, objType, scratchObj, castExpr, call, varSection, result) else: - setupArgsForParallelism(n, objType, scratchObj, castExpr, call, result) + setupArgsForParallelism(n, objType, scratchObj, castExpr, call, varSection, result) var barrierAsExpr: PNode = nil if barrier != nil: |