diff options
Diffstat (limited to 'compiler/ccgexprs.nim')
-rw-r--r-- | compiler/ccgexprs.nim | 199 |
1 files changed, 121 insertions, 78 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index a1365ce07..348a9f375 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -59,7 +59,7 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): Rope = else: result = rope("NIM_NIL") of nkStrLit..nkTripleStrLit: - case skipTypes(ty, abstractVarRange + {tyStatic}).kind + case skipTypes(ty, abstractVarRange + {tyStatic, tyUserTypeClass, tyUserTypeClassInst}).kind of tyNil: result = genNilStringLiteral(p.module, n.info) of tyString: @@ -168,32 +168,12 @@ proc canMove(p: BProc, n: PNode): bool = # echo n.info, " optimized ", n # result = false -proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = - if dest.storage == OnStack or not usesWriteBarrier(p.config): +proc genRefAssign(p: BProc, dest, src: TLoc) = + if (dest.storage == OnStack and p.config.selectedGC != gcGo) or not usesWriteBarrier(p.config): linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) elif dest.storage == OnHeap: - # location is on heap - # now the writer barrier is inlined for performance: - # - # if afSrcIsNotNil in flags: - # UseMagic(p.module, 'nimGCref') - # lineF(p, cpsStmts, 'nimGCref($1);$n', [rdLoc(src)]) - # elif afSrcIsNil notin flags: - # UseMagic(p.module, 'nimGCref') - # lineF(p, cpsStmts, 'if ($1) nimGCref($1);$n', [rdLoc(src)]) - # if afDestIsNotNil in flags: - # UseMagic(p.module, 'nimGCunref') - # lineF(p, cpsStmts, 'nimGCunref($1);$n', [rdLoc(dest)]) - # elif afDestIsNil notin flags: - # UseMagic(p.module, 'nimGCunref') - # lineF(p, cpsStmts, 'if ($1) nimGCunref($1);$n', [rdLoc(dest)]) - # lineF(p, cpsStmts, '$1 = $2;$n', [rdLoc(dest), rdLoc(src)]) - if canFormAcycle(dest.t): - linefmt(p, cpsStmts, "#asgnRef((void**) $1, $2);$n", - addrLoc(p.config, dest), rdLoc(src)) - else: - linefmt(p, cpsStmts, "#asgnRefNoCycle((void**) $1, $2);$n", - addrLoc(p.config, dest), rdLoc(src)) + linefmt(p, cpsStmts, "#asgnRef((void**) $1, $2);$n", + addrLoc(p.config, dest), rdLoc(src)) else: linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);$n", addrLoc(p.config, dest), rdLoc(src)) @@ -261,11 +241,11 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = # (for objects, etc.): if p.config.selectedGC == gcDestructors: linefmt(p, cpsStmts, - "$1.len = $2.len; $1.p = $2.p;$n", + "$1 = $2;$n", rdLoc(dest), rdLoc(src)) elif needToCopy notin flags or tfShallow in skipTypes(dest.t, abstractVarRange).flags: - if dest.storage == OnStack or not usesWriteBarrier(p.config): + if (dest.storage == OnStack and p.config.selectedGC != gcGo) or not usesWriteBarrier(p.config): linefmt(p, cpsStmts, "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n", addrLoc(p.config, dest), addrLoc(p.config, src), rdLoc(dest)) @@ -286,12 +266,12 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = let ty = skipTypes(dest.t, abstractRange + tyUserTypeClasses + {tyStatic}) case ty.kind of tyRef: - genRefAssign(p, dest, src, flags) + genRefAssign(p, dest, src) of tySequence: if p.config.selectedGC == gcDestructors: genGenericAsgn(p, dest, src, flags) elif (needToCopy notin flags and src.storage != OnStatic) or canMove(p, src.lode): - genRefAssign(p, dest, src, flags) + genRefAssign(p, dest, src) else: linefmt(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n", addrLoc(p.config, dest), rdLoc(src), @@ -300,9 +280,9 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = if p.config.selectedGC == gcDestructors: genGenericAsgn(p, dest, src, flags) elif (needToCopy notin flags and src.storage != OnStatic) or canMove(p, src.lode): - genRefAssign(p, dest, src, flags) + genRefAssign(p, dest, src) else: - if dest.storage == OnStack or not usesWriteBarrier(p.config): + if (dest.storage == OnStack and p.config.selectedGC != gcGo) or not usesWriteBarrier(p.config): linefmt(p, cpsStmts, "$1 = #copyString($2);$n", dest.rdLoc, src.rdLoc) elif dest.storage == OnHeap: # we use a temporary to care for the dreaded self assignment: @@ -315,16 +295,16 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n", addrLoc(p.config, dest), rdLoc(src)) of tyProc: - if needsComplexAssignment(dest.t): + if containsGarbageCollectedRef(dest.t): # optimize closure assignment: let a = optAsgnLoc(dest, dest.t, "ClE_0".rope) let b = optAsgnLoc(src, dest.t, "ClE_0".rope) - genRefAssign(p, a, b, flags) + genRefAssign(p, a, b) linefmt(p, cpsStmts, "$1.ClP_0 = $2.ClP_0;$n", rdLoc(dest), rdLoc(src)) else: linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) of tyTuple: - if needsComplexAssignment(dest.t): + if containsGarbageCollectedRef(dest.t): if dest.t.len <= 4: genOptAsgnTuple(p, dest, src, flags) else: genGenericAsgn(p, dest, src, flags) else: @@ -335,7 +315,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) elif not isObjLackingTypeField(ty): genGenericAsgn(p, dest, src, flags) - elif needsComplexAssignment(ty): + elif containsGarbageCollectedRef(ty): if ty.sons[0].isNil and asgnComplexity(ty.n) <= 4: discard getTypeDesc(p.module, ty) internalAssert p.config, ty.n != nil @@ -345,7 +325,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = else: linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) of tyArray: - if needsComplexAssignment(dest.t): + if containsGarbageCollectedRef(dest.t): genGenericAsgn(p, dest, src, flags) else: linefmt(p, cpsStmts, @@ -354,7 +334,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = of tyOpenArray, tyVarargs: # open arrays are always on the stack - really? What if a sequence is # passed to an open array? - if needsComplexAssignment(dest.t): + if containsGarbageCollectedRef(dest.t): linefmt(p, cpsStmts, # XXX: is this correct for arrays? "#genericAssignOpenArray((void*)$1, (void*)$2, $1Len_0, $3);$n", addrLoc(p.config, dest), addrLoc(p.config, src), @@ -741,7 +721,7 @@ proc genAddr(p: BProc, e: PNode, d: var TLoc) = initLocExpr(p, e.sons[0], a) putIntoDest(p, d, e, "&" & a.r, a.storage) #Message(e.info, warnUser, "HERE NEW &") - elif mapType(p.config, e.sons[0].typ) == ctArray or isCppRef(p, e.sons[0].typ): + elif mapType(p.config, e.sons[0].typ) == ctArray or isCppRef(p, e.typ): expr(p, e.sons[0], d) else: var a: TLoc @@ -856,6 +836,15 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) = else: genRecordField(p, e.sons[0], d) +proc genUncheckedArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) = + var a, b: TLoc + initLocExpr(p, x, a) + initLocExpr(p, y, b) + var ty = skipTypes(a.t, abstractVarRange + abstractPtrs + tyUserTypeClasses) + d.inheritLocation(a) + putIntoDest(p, d, n, ropecg(p.module, "$1[$2]", rdLoc(a), rdCharLoc(b)), + a.storage) + proc genArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) = var a, b: TLoc initLocExpr(p, x, a) @@ -863,7 +852,7 @@ proc genArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) = var ty = skipTypes(a.t, abstractVarRange + abstractPtrs + tyUserTypeClasses) var first = intLiteral(firstOrd(p.config, ty)) # emit range check: - if optBoundsCheck in p.options and tfUncheckedArray notin ty.flags: + if optBoundsCheck in p.options and ty.kind != tyUncheckedArray: if not isConstExpr(y): # semantic pass has already checked for const index expressions if firstOrd(p.config, ty) == 0: @@ -900,11 +889,10 @@ proc genBoundsCheck(p: BProc; arr, a, b: TLoc) = rdLoc(a), rdLoc(b), rdLoc(arr)) of tyArray: let first = intLiteral(firstOrd(p.config, ty)) - if tfUncheckedArray notin ty.flags: - linefmt(p, cpsStmts, - "if ($2-$1 != -1 && " & - "($2-$1 < -1 || $1 < $3 || $1 > $4 || $2 < $3 || $2 > $4)) #raiseIndexError();$n", - rdCharLoc(a), rdCharLoc(b), first, intLiteral(lastOrd(p.config, ty))) + linefmt(p, cpsStmts, + "if ($2-$1 != -1 && " & + "($2-$1 < -1 || $1 < $3 || $1 > $4 || $2 < $3 || $2 > $4)) #raiseIndexError();$n", + rdCharLoc(a), rdCharLoc(b), first, intLiteral(lastOrd(p.config, ty))) of tySequence, tyString: linefmt(p, cpsStmts, "if ($2-$1 != -1 && " & @@ -949,6 +937,7 @@ proc genBracketExpr(p: BProc; n: PNode; d: var TLoc) = var ty = skipTypes(n.sons[0].typ, abstractVarRange + tyUserTypeClasses) if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.lastSon, abstractVarRange) case ty.kind + of tyUncheckedArray: genUncheckedArrayElem(p, n, n.sons[0], n.sons[1], d) of tyArray: genArrayElem(p, n, n.sons[0], n.sons[1], d) of tyOpenArray, tyVarargs: genOpenArrayElem(p, n, n.sons[0], n.sons[1], d) of tySequence, tyString: genSeqElem(p, n, n.sons[0], n.sons[1], d) @@ -1139,14 +1128,14 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) = genTypeInfo(p.module, seqType, e.info)]) # emit the write barrier if required, but we can always move here, so # use 'genRefAssign' for the seq. - genRefAssign(p, a, call, {}) + genRefAssign(p, a, call) #if bt != b.t: # echo "YES ", e.info, " new: ", typeToString(bt), " old: ", typeToString(b.t) initLoc(dest, locExpr, e.sons[2], OnHeap) getIntTemp(p, tmpL) lineCg(p, cpsStmts, "$1 = $2->$3++;$n", tmpL.r, rdLoc(a), lenField(p)) dest.r = ropecg(p.module, "$1$3[$2]", rdLoc(a), tmpL.r, dataField(p)) - genAssignment(p, dest, b, {needToCopy, afDestIsNil}) + genAssignment(p, dest, b, {needToCopy}) gcUsage(p.config, e) proc genReset(p: BProc, n: PNode) = @@ -1183,13 +1172,19 @@ proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) = let args = [getTypeDesc(p.module, typ), ti, sizeExpr] if a.storage == OnHeap and usesWriteBarrier(p.config): - # use newObjRC1 as an optimization if canFormAcycle(a.t): linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", a.rdLoc) else: linefmt(p, cpsStmts, "if ($1) { #nimGCunrefNoCycle($1); $1 = NIM_NIL; }$n", a.rdLoc) - b.r = ropecg(p.module, "($1) #newObjRC1($2, $3)", args) - linefmt(p, cpsStmts, "$1 = $2;$n", a.rdLoc, b.rdLoc) + if p.config.selectedGC == gcGo: + # newObjRC1() would clash with unsureAsgnRef() - which is used by gcGo to + # implement the write barrier + b.r = ropecg(p.module, "($1) #newObj($2, $3)", args) + linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);$n", addrLoc(p.config, a), b.rdLoc) + else: + # use newObjRC1 as an optimization + b.r = ropecg(p.module, "($1) #newObjRC1($2, $3)", args) + linefmt(p, cpsStmts, "$1 = $2;$n", a.rdLoc, b.rdLoc) else: b.r = ropecg(p.module, "($1) #newObj($2, $3)", args) genAssignment(p, a, b, {}) # set the object type: @@ -1219,8 +1214,13 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope; lenIsZero: bool) = else: linefmt(p, cpsStmts, "if ($1) { #nimGCunrefNoCycle($1); $1 = NIM_NIL; }$n", dest.rdLoc) if not lenIsZero: - call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", args) - linefmt(p, cpsStmts, "$1 = $2;$n", dest.rdLoc, call.rdLoc) + if p.config.selectedGC == gcGo: + # we need the write barrier + call.r = ropecg(p.module, "($1) #newSeq($2, $3)", args) + linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);$n", addrLoc(p.config, dest), call.rdLoc) + else: + call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", args) + linefmt(p, cpsStmts, "$1 = $2;$n", dest.rdLoc, call.rdLoc) else: if lenIsZero: call.r = rope"NIM_NIL" @@ -1339,9 +1339,17 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) = getTemp(p, n.typ, tmp) elif d.k == locNone: getTemp(p, n.typ, d) - # generate call to newSeq before adding the elements per hand: - genNewSeqAux(p, dest[], intLiteral(sonsLen(n)), - optNilSeqs notin p.options and n.len == 0) + + let l = intLiteral(sonsLen(n)) + if p.config.selectedGC == gcDestructors: + let seqtype = n.typ + linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n", + rdLoc dest[], l, getTypeDesc(p.module, seqtype.lastSon), + getSeqPayloadType(p.module, seqtype)) + else: + # generate call to newSeq before adding the elements per hand: + genNewSeqAux(p, dest[], l, + optNilSeqs notin p.options and n.len == 0) for i in countup(0, sonsLen(n) - 1): initLoc(arr, locExpr, n[i], OnHeap) arr.r = ropecg(p.module, "$1$3[$2]", rdLoc(dest[]), intLiteral(i), dataField(p)) @@ -1364,7 +1372,13 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) = getTemp(p, n.typ, d) # generate call to newSeq before adding the elements per hand: let L = int(lengthOrd(p.config, n.sons[1].typ)) - genNewSeqAux(p, d, intLiteral(L), optNilSeqs notin p.options and L == 0) + if p.config.selectedGC == gcDestructors: + let seqtype = n.typ + linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n", + rdLoc d, rope L, getTypeDesc(p.module, seqtype.lastSon), + getSeqPayloadType(p.module, seqtype)) + else: + genNewSeqAux(p, d, intLiteral(L), optNilSeqs notin p.options and L == 0) initLocExpr(p, n.sons[1], a) # bug #5007; do not produce excessive C source code: if L < 10: @@ -1374,7 +1388,7 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) = elem.storage = OnHeap # we know that sequences are on the heap initLoc(arr, locExpr, lodeTyp elemType(skipTypes(n.sons[1].typ, abstractInst)), a.storage) arr.r = ropecg(p.module, "$1[$2]", rdLoc(a), intLiteral(i)) - genAssignment(p, elem, arr, {afDestIsNil, needToCopy}) + genAssignment(p, elem, arr, {needToCopy}) else: var i: TLoc getTemp(p, getSysType(p.module.g.graph, unknownLineInfo(), tyInt), i) @@ -1385,7 +1399,7 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) = elem.storage = OnHeap # we know that sequences are on the heap initLoc(arr, locExpr, lodeTyp elemType(skipTypes(n.sons[1].typ, abstractInst)), a.storage) arr.r = ropecg(p.module, "$1[$2]", rdLoc(a), rdLoc(i)) - genAssignment(p, elem, arr, {afDestIsNil, needToCopy}) + genAssignment(p, elem, arr, {needToCopy}) lineF(p, cpsStmts, "}$n", []) @@ -1523,8 +1537,19 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) = var typ = skipTypes(a.typ, abstractVar + tyUserTypeClasses) case typ.kind of tyOpenArray, tyVarargs: - if op == mHigh: unaryExpr(p, e, d, "($1Len_0-1)") - else: unaryExpr(p, e, d, "$1Len_0") + # Bug #9279, len(toOpenArray()) has to work: + if a.kind in nkCallKinds and a[0].kind == nkSym and a[0].sym.magic == mSlice: + # magic: pass slice to openArray: + var b, c: TLoc + initLocExpr(p, a[2], b) + initLocExpr(p, a[3], c) + if op == mHigh: + putIntoDest(p, d, e, ropecg(p.module, "($2)-($1)", [rdLoc(b), rdLoc(c)])) + else: + putIntoDest(p, d, e, ropecg(p.module, "($2)-($1)+1", [rdLoc(b), rdLoc(c)])) + else: + if op == mHigh: unaryExpr(p, e, d, "($1Len_0-1)") + else: unaryExpr(p, e, d, "$1Len_0") of tyCString: if op == mHigh: unaryExpr(p, e, d, "($1 ? (#nimCStrLen($1)-1) : -1)") else: unaryExpr(p, e, d, "($1 ? #nimCStrLen($1) : 0)") @@ -1549,8 +1574,17 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) = else: putIntoDest(p, d, e, rope(lengthOrd(p.config, typ))) else: internalError(p.config, e.info, "genArrayLen()") +proc makePtrType(baseType: PType): PType = + result = newType(tyPtr, baseType.owner) + addSonSkipIntLit(result, baseType) + +proc makeAddr(n: PNode): PNode = + result = newTree(nkHiddenAddr, n) + result.typ = makePtrType(n.typ) + proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) = if p.config.selectedGc == gcDestructors: + e.sons[1] = makeAddr(e[1]) genCall(p, e, d) return var a, b, call: TLoc @@ -1732,7 +1766,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) = getTemp(p, getSysType(p.module.g.graph, unknownLineInfo(), tyInt), i) # our counter initLocExpr(p, e.sons[1], a) initLocExpr(p, e.sons[2], b) - if d.k == locNone: getTemp(p, a.t, d) + if d.k == locNone: getTemp(p, setType, d) lineF(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) $n" & " $3[$1] = $4[$1] $6 $5[$1];$n", [ @@ -1932,6 +1966,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mAppendStrStr: genStrAppend(p, e, d) of mAppendSeqElem: if p.config.selectedGc == gcDestructors: + e.sons[1] = makeAddr(e[1]) genCall(p, e, d) else: genSeqElemAppend(p, e, d) @@ -1976,8 +2011,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = frmt = "$1 = $2->len;$n" lineCg(p, cpsStmts, frmt, tmp.r, rdLoc(a)) putIntoDest(p, d, e, tmp.r) - of mGCref: unaryStmt(p, e, d, "#nimGCref($1);$n") - of mGCunref: unaryStmt(p, e, d, "#nimGCunref($1);$n") + of mGCref: unaryStmt(p, e, d, "if ($1) { #nimGCref($1); }$n") + of mGCunref: unaryStmt(p, e, d, "if ($1) { #nimGCunref($1); }$n") of mSetLengthStr: genSetLengthStr(p, e, d) of mSetLengthSeq: genSetLengthSeq(p, e, d) of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet, @@ -1999,8 +2034,11 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = let n = lowerings.wrapProcForSpawn(p.module.g.graph, p.module.module, e, e.typ, nil, nil) expr(p, n, d) of mParallel: - let n = semparallel.liftParallel(p.module.g.graph, p.module.module, e) - expr(p, n, d) + when defined(leanCompiler): + quit "compiler built without support for the 'parallel' statement" + else: + let n = semparallel.liftParallel(p.module.g.graph, p.module.module, e) + expr(p, n, d) of mDeepCopy: var a, b: TLoc let x = if e[1].kind in {nkAddr, nkHiddenAddr}: e[1][0] else: e[1] @@ -2010,6 +2048,10 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mDotDot, mEqCString: genCall(p, e, d) of mWasMoved: genWasMoved(p, e) of mMove: genMove(p, e, d) + of mDestroy: discard "ignore calls to the default destructor" + of mSlice: + localError(p.config, e.info, "invalid context for 'toOpenArray'; " & + " 'toOpenArray' is only valid within a call expression") else: when defined(debugMagics): echo p.prc.name.s, " ", p.prc.id, " ", p.prc.flags, " ", p.prc.ast[genericParamsPos].kind @@ -2079,7 +2121,7 @@ proc isConstClosure(n: PNode): bool {.inline.} = n.sons[1].kind == nkNilLit proc genClosure(p: BProc, n: PNode, d: var TLoc) = - assert n.kind == nkClosure + assert n.kind in {nkPar, nkTupleConstr, nkClosure} if isConstClosure(n): inc(p.module.labels) @@ -2337,7 +2379,9 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = else: genArrayConstr(p, n, d) of nkPar, nkTupleConstr: - if isDeepConstExpr(n) and n.len != 0: + if n.typ != nil and n.typ.kind == tyProc and n.len == 2: + genClosure(p, n, d) + elif isDeepConstExpr(n) and n.len != 0: exprComplexConst(p, n, d) else: genTupleConstr(p, n, d) @@ -2392,15 +2436,8 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = if ex.kind != nkEmpty: genLineDir(p, n) var a: TLoc - if ex.kind in nkCallKinds and (ex[0].kind != nkSym or - ex[0].sym.magic == mNone): - # bug #6037: do not assign to a temp in C++ mode: - incl a.flags, lfSingleUse - genCall(p, ex, a) - if lfSingleUse notin a.flags: - line(p, cpsStmts, a.r & ";\L") - else: - initLocExpr(p, ex, a) + initLocExprSingleUse(p, ex, a) + line(p, cpsStmts, "(void)(" & a.r & ");\L") of nkAsmStmt: genAsmStmt(p, n) of nkTryStmt: if p.module.compileToCpp and optNoCppExceptions notin p.config.globalOptions: @@ -2571,15 +2608,21 @@ proc genConstExpr(p: BProc, n: PNode): Rope = var t = skipTypes(n.typ, abstractInst) if t.kind == tySequence: result = genConstSeq(p, n, n.typ) - elif t.kind == tyProc and t.callConv == ccClosure and n.len > 0 and - n.sons[0].kind == nkNilLit and n.sons[1].kind == nkNilLit: + elif t.kind == tyProc and t.callConv == ccClosure and n.len > 1 and + n.sons[1].kind == nkNilLit: + # Conversion: nimcall -> closure. # this hack fixes issue that nkNilLit is expanded to {NIM_NIL,NIM_NIL} # this behaviour is needed since closure_var = nil must be # expanded to {NIM_NIL,NIM_NIL} # in VM closures are initialized with nkPar(nkNilLit, nkNilLit) # leading to duplicate code like this: # "{NIM_NIL,NIM_NIL}, {NIM_NIL,NIM_NIL}" - result = ~"{NIM_NIL,NIM_NIL}" + if n[0].kind == nkNilLit: + result = ~"{NIM_NIL,NIM_NIL}" + else: + var d: TLoc + initLocExpr(p, n[0], d) + result = "{(($1) $2),NIM_NIL}" % [getClosureType(p.module, t, clHalfWithEnv), rdLoc(d)] else: result = genConstSimpleList(p, n) of nkObjConstr: |