diff options
Diffstat (limited to 'compiler/ccgexprs.nim')
-rw-r--r-- | compiler/ccgexprs.nim | 550 |
1 files changed, 288 insertions, 262 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index e46a0470d..545d43ae8 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -112,11 +112,6 @@ proc genLiteral(p: BProc, n: PNode, ty: PType; result: var Rope) = proc genLiteral(p: BProc, n: PNode; result: var Rope) = genLiteral(p, n, n.typ, result) -proc bitSetToWord(s: TBitSet, size: int): BiggestUInt = - result = 0 - for j in 0..<size: - if j < s.len: result = result or (BiggestUInt(s[j]) shl (j * 8)) - proc genRawSetData(cs: TBitSet, size: int; result: var Rope) = if size > 8: var res = "{\n" @@ -226,10 +221,11 @@ proc asgnComplexity(n: PNode): int = proc optAsgnLoc(a: TLoc, t: PType, field: Rope): TLoc = assert field != "" - result.k = locField - result.storage = a.storage - result.lode = lodeTyp t - result.r = rdLoc(a) & "." & field + result = TLoc(k: locField, + storage: a.storage, + lode: lodeTyp t, + snippet: rdLoc(a) & "." & field + ) proc genOptAsgnTuple(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = let newflags = @@ -240,8 +236,7 @@ proc genOptAsgnTuple(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = else: flags let t = skipTypes(dest.t, abstractInst).getUniqueType() - for i in 0..<t.len: - let t = t[i] + for i, t in t.ikids: let field = "Field$1" % [i.rope] genAssignment(p, optAsgnLoc(dest, t, field), optAsgnLoc(src, t, field), newflags) @@ -259,9 +254,9 @@ proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags, case t.kind of nkSym: let field = t.sym - if field.loc.r == "": fillObjectFields(p.module, typ) - genAssignment(p, optAsgnLoc(dest, field.typ, field.loc.r), - optAsgnLoc(src, field.typ, field.loc.r), newflags) + if field.loc.snippet == "": fillObjectFields(p.module, typ) + genAssignment(p, optAsgnLoc(dest, field.typ, field.loc.snippet), + optAsgnLoc(src, field.typ, field.loc.snippet), newflags) of nkRecList: for child in items(t): genOptAsgnObject(p, dest, src, newflags, child, typ) else: discard @@ -290,15 +285,22 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = linefmt(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n", [addrLoc(p.config, dest), addrLoc(p.config, src), genTypeInfoV1(p.module, dest.t, dest.lode.info)]) -proc genOpenArrayConv(p: BProc; d: TLoc; a: TLoc) = +proc genOpenArrayConv(p: BProc; d: TLoc; a: TLoc; flags: TAssignmentFlags) = assert d.k != locNone # getTemp(p, d.t, d) case a.t.skipTypes(abstractVar).kind of tyOpenArray, tyVarargs: if reifiedOpenArray(a.lode): - linefmt(p, cpsStmts, "$1.Field0 = $2.Field0; $1.Field1 = $2.Field1;$n", - [rdLoc(d), a.rdLoc]) + if needTempForOpenArray in flags: + var tmp: TLoc = getTemp(p, a.t) + linefmt(p, cpsStmts, "$2 = $1; $n", + [a.rdLoc, tmp.rdLoc]) + linefmt(p, cpsStmts, "$1.Field0 = $2.Field0; $1.Field1 = $2.Field1;$n", + [rdLoc(d), tmp.rdLoc]) + else: + linefmt(p, cpsStmts, "$1.Field0 = $2.Field0; $1.Field1 = $2.Field1;$n", + [rdLoc(d), a.rdLoc]) else: linefmt(p, cpsStmts, "$1.Field0 = $2; $1.Field1 = $2Len_0;$n", [rdLoc(d), a.rdLoc]) @@ -341,15 +343,14 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = of tyString: if optSeqDestructors in p.config.globalOptions: genGenericAsgn(p, dest, src, flags) - elif (needToCopy notin flags and src.storage != OnStatic) or canMove(p, src.lode, dest): + elif ({needToCopy, needToCopySinkParam} * flags == {} and src.storage != OnStatic) or canMove(p, src.lode, dest): genRefAssign(p, dest, src) else: 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: - var tmp: TLoc - getTemp(p, ty, tmp) + var tmp: TLoc = getTemp(p, ty) linefmt(p, cpsStmts, "$3 = $1; $1 = #copyStringRC1($2);$n", [dest.rdLoc, src.rdLoc, tmp.rdLoc]) linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", [tmp.rdLoc]) @@ -367,7 +368,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) of tyTuple: if containsGarbageCollectedRef(dest.t): - if dest.t.len <= 4: genOptAsgnTuple(p, dest, src, flags) + if dest.t.kidsLen <= 4: genOptAsgnTuple(p, dest, src, flags) else: genGenericAsgn(p, dest, src, flags) else: linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) @@ -378,7 +379,8 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = elif not isObjLackingTypeField(ty): genGenericAsgn(p, dest, src, flags) elif containsGarbageCollectedRef(ty): - if ty[0].isNil and asgnComplexity(ty.n) <= 4: + if ty[0].isNil and asgnComplexity(ty.n) <= 4 and + needAssignCall notin flags: # calls might contain side effects discard getTypeDesc(p.module, ty) internalAssert p.config, ty.n != nil genOptAsgnObject(p, dest, src, flags, ty.n, ty) @@ -397,7 +399,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = # open arrays are always on the stack - really? What if a sequence is # passed to an open array? if reifiedOpenArray(dest.lode): - genOpenArrayConv(p, dest, src) + genOpenArrayConv(p, dest, src, flags) elif containsGarbageCollectedRef(dest.t): linefmt(p, cpsStmts, # XXX: is this correct for arrays? "#genericAssignOpenArray((void*)$1, (void*)$2, $1Len_0, $3);$n", @@ -431,8 +433,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = proc genDeepCopy(p: BProc; dest, src: TLoc) = template addrLocOrTemp(a: TLoc): Rope = if a.k == locExpr: - var tmp: TLoc - getTemp(p, a.t, tmp) + var tmp: TLoc = getTemp(p, a.t) genAssignment(p, tmp, a, {}) addrLoc(p.config, tmp) else: @@ -482,7 +483,7 @@ proc putDataIntoDest(p: BProc, d: var TLoc, n: PNode, r: Rope) = if d.k != locNone: var a: TLoc = initLoc(locData, n, OnStatic) # need to generate an assignment here - a.r = r + a.snippet = r if lfNoDeepCopy in d.flags: genAssignment(p, d, a, {}) else: genAssignment(p, d, a, {needToCopy}) else: @@ -490,13 +491,13 @@ proc putDataIntoDest(p: BProc, d: var TLoc, n: PNode, r: Rope) = # the flags field! d.k = locData d.lode = n - d.r = r + d.snippet = r proc putIntoDest(p: BProc, d: var TLoc, n: PNode, r: Rope; s=OnUnknown) = if d.k != locNone: # need to generate an assignment here var a: TLoc = initLoc(locExpr, n, s) - a.r = r + a.snippet = r if lfNoDeepCopy in d.flags: genAssignment(p, d, a, {}) else: genAssignment(p, d, a, {needToCopy}) else: @@ -504,7 +505,7 @@ proc putIntoDest(p: BProc, d: var TLoc, n: PNode, r: Rope; s=OnUnknown) = # the flags field! d.k = locExpr d.lode = n - d.r = r + d.snippet = r proc binaryStmt(p: BProc, e: PNode, d: var TLoc, op: string) = if d.k != locNone: internalError(p.config, e.info, "binaryStmt") @@ -589,7 +590,7 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) = # skipping 'range' is correct here as we'll generate a proper range check # later via 'chckRange' let t = e.typ.skipTypes(abstractRange) - if optOverflowCheck notin p.options: + if optOverflowCheck notin p.options or (m in {mSucc, mPred} and t.kind in {tyUInt..tyUInt64}): let res = "($1)($2 $3 $4)" % [getTypeDesc(p.module, e.typ), rdLoc(a), rope(opr[m]), rdLoc(b)] putIntoDest(p, d, e, res) else: @@ -611,7 +612,7 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) = if t.kind == tyInt64: prc64[m] else: prc[m]) putIntoDest(p, d, e, "($#)($#)" % [getTypeDesc(p.module, e.typ), res]) else: - let res = "($1)($2 $3 $4)" % [getTypeDesc(p.module, e.typ), rdLoc(a), rope(opr[m]), rdLoc(b)] + let res = "($1)(($2) $3 ($4))" % [getTypeDesc(p.module, e.typ), rdLoc(a), rope(opr[m]), rdLoc(b)] putIntoDest(p, d, e, res) proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) = @@ -755,7 +756,7 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc) = var a: TLoc var typ = e[0].typ if typ.kind in {tyUserTypeClass, tyUserTypeClassInst} and typ.isResolvedUserTypeClass: - typ = typ.lastSon + typ = typ.last typ = typ.skipTypes(abstractInstOwned) if typ.kind in {tyVar} and tfVarIsPtr notin typ.flags and p.module.compileToCpp and e[0].kind == nkHiddenAddr: d = initLocExprSingleUse(p, e[0][0]) @@ -808,10 +809,12 @@ proc genAddr(p: BProc, e: PNode, d: var TLoc) = # careful 'addr(myptrToArray)' needs to get the ampersand: if e[0].typ.skipTypes(abstractInstOwned).kind in {tyRef, tyPtr}: var a: TLoc = initLocExpr(p, e[0]) - putIntoDest(p, d, e, "&" & a.r, a.storage) + putIntoDest(p, d, e, "&" & a.snippet, a.storage) #Message(e.info, warnUser, "HERE NEW &") elif mapType(p.config, e[0].typ, mapTypeChooser(e[0]) == skParam) == ctArray or isCppRef(p, e.typ): expr(p, e[0], d) + # bug #19497 + d.lode = e else: var a: TLoc = initLocExpr(p, e[0]) putIntoDest(p, d, e, addrLoc(p.config, a), a.storage) @@ -858,6 +861,12 @@ proc lookupFieldAgain(p: BProc, ty: PType; field: PSym; r: var Rope; proc genRecordField(p: BProc, e: PNode, d: var TLoc) = var a: TLoc = default(TLoc) + if p.module.compileToCpp and e.kind == nkDotExpr and e[1].kind == nkSym and e[1].typ.kind == tyPtr: + # special case for C++: we need to pull the type of the field as member and friends require the complete type. + let typ = e[1].typ.elementType + if typ.itemId in p.module.g.graph.memberProcsPerType: + discard getTypeDesc(p.module, typ) + genRecordFieldAux(p, e, d, a) var r = rdLoc(a) var f = e[1].sym @@ -871,10 +880,10 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) = else: var rtyp: PType = nil let field = lookupFieldAgain(p, ty, f, r, addr rtyp) - if field.loc.r == "" and rtyp != nil: fillObjectFields(p.module, rtyp) - if field.loc.r == "": internalError(p.config, e.info, "genRecordField 3 " & typeToString(ty)) + if field.loc.snippet == "" and rtyp != nil: fillObjectFields(p.module, rtyp) + if field.loc.snippet == "": internalError(p.config, e.info, "genRecordField 3 " & typeToString(ty)) r.add "." - r.add field.loc.r + r.add field.loc.snippet putIntoDest(p, d, e, r, a.storage) r.freeze @@ -893,10 +902,10 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) = test = initLoc(locNone, it, OnStack) u = initLocExpr(p, it[1]) v = initLoc(locExpr, disc, OnUnknown) - v.r = newRopeAppender() - v.r.add obj - v.r.add(".") - v.r.add(disc.sym.loc.r) + v.snippet = newRopeAppender() + v.snippet.add obj + v.snippet.add(".") + v.snippet.add(disc.sym.loc.snippet) genInExprAux(p, it, u, v, test) var msg = "" if optDeclaredLocs in p.config.globalOptions: @@ -954,12 +963,12 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) = var r = rdLoc(a) let f = e[0][1].sym let field = lookupFieldAgain(p, ty, f, r) - if field.loc.r == "": fillObjectFields(p.module, ty) - if field.loc.r == "": + if field.loc.snippet == "": fillObjectFields(p.module, ty) + if field.loc.snippet == "": internalError(p.config, e.info, "genCheckedRecordField") # generate the checks: genFieldCheck(p, e, r, field) r.add(".") - r.add field.loc.r + r.add field.loc.snippet putIntoDest(p, d, e[0], r, a.storage) r.freeze else: @@ -1013,8 +1022,8 @@ proc genCStringElem(p: BProc, n, x, y: PNode, d: var TLoc) = putIntoDest(p, d, n, ropecg(p.module, "$1[$2]", [rdLoc(a), rdCharLoc(b)]), a.storage) -proc genBoundsCheck(p: BProc; arr, a, b: TLoc) = - let ty = skipTypes(arr.t, abstractVarRange) +proc genBoundsCheck(p: BProc; arr, a, b: TLoc; arrTyp: PType) = + let ty = arrTyp case ty.kind of tyOpenArray, tyVarargs: if reifiedOpenArray(arr.lode): @@ -1083,7 +1092,8 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) = var b = initLocExpr(p, y) var ty = skipTypes(a.t, abstractVarRange) if ty.kind in {tyRef, tyPtr}: - ty = skipTypes(ty.lastSon, abstractVarRange) # emit range check: + ty = skipTypes(ty.elementType, abstractVarRange) + # emit range check: if optBoundsCheck in p.options: linefmt(p, cpsStmts, "if ($1 < 0 || $1 >= $2){ #raiseIndexError2($1,$2-1); ", @@ -1093,7 +1103,7 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) = if d.k == locNone: d.storage = OnHeap if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}: - a.r = ropecg(p.module, "(*$1)", [a.r]) + a.snippet = ropecg(p.module, "(*$1)", [a.snippet]) if lfPrepareForMutation in d.flags and ty.kind == tyString and optSeqDestructors in p.config.globalOptions: @@ -1103,7 +1113,7 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) = proc genBracketExpr(p: BProc; n: PNode; d: var TLoc) = var ty = skipTypes(n[0].typ, abstractVarRange + tyUserTypeClasses) - if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.lastSon, abstractVarRange) + if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.elementType, abstractVarRange) case ty.kind of tyUncheckedArray: genUncheckedArrayElem(p, n, n[0], n[1], d) of tyArray: genArrayElem(p, n, n[0], n[1], d) @@ -1159,9 +1169,9 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) = var tmpB = initLocExprSingleUse(p, e[2]) tmpB.k = locExpr if m == mOr: - tmpB.r = "((" & rdLoc(tmpA) & ")||(" & rdLoc(tmpB) & "))" + tmpB.snippet = "((" & rdLoc(tmpA) & ")||(" & rdLoc(tmpB) & "))" else: - tmpB.r = "((" & rdLoc(tmpA) & ")&&(" & rdLoc(tmpB) & "))" + tmpB.snippet = "((" & rdLoc(tmpA) & ")&&(" & rdLoc(tmpB) & "))" if d.k == locNone: d = tmpB else: @@ -1169,8 +1179,7 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) = else: var L: TLabel - tmp: TLoc - getTemp(p, e.typ, tmp) # force it into a temp! + var tmp: TLoc = getTemp(p, e.typ) # force it into a temp! inc p.splitDecls expr(p, e[1], tmp) L = getLabel(p) @@ -1248,8 +1257,7 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) = # asgn(s, tmp0); # } var a: TLoc - var tmp: TLoc - getTemp(p, e.typ, tmp) + var tmp: TLoc = getTemp(p, e.typ) var L = 0 var appends: Rope = "" var lens: Rope = "" @@ -1266,7 +1274,7 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) = lens.add(lenExpr(p, a)) lens.add(" + ") appends.add(ropecg(p.module, "#appendString($1, $2);$n", [strLoc(p, tmp), rdLoc(a)])) - linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);$n", [tmp.r, lens, L]) + linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);$n", [tmp.snippet, lens, L]) p.s(cpsStmts).add appends if d.k == locNone: d = tmp @@ -1312,7 +1320,7 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) = [byRefLoc(p, dest), lens, L]) else: call = initLoc(locCall, e, OnHeap) - call.r = ropecg(p.module, "#resizeString($1, $2$3)", [rdLoc(dest), lens, L]) + call.snippet = ropecg(p.module, "#resizeString($1, $2$3)", [rdLoc(dest), lens, L]) genAssignment(p, dest, call, {}) gcUsage(p.config, e) p.s(cpsStmts).add appends @@ -1321,19 +1329,18 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) = # seq &= x --> # seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x)); # seq->data[seq->len-1] = x; - var tmpL: TLoc = default(TLoc) var a = initLocExpr(p, e[1]) var b = initLocExpr(p, e[2]) let seqType = skipTypes(e[1].typ, {tyVar}) var call = initLoc(locCall, e, OnHeap) if not p.module.compileToCpp: const seqAppendPattern = "($2) #incrSeqV3((TGenericSeq*)($1), $3)" - call.r = ropecg(p.module, seqAppendPattern, [rdLoc(a), + call.snippet = ropecg(p.module, seqAppendPattern, [rdLoc(a), getTypeDesc(p.module, e[1].typ), genTypeInfoV1(p.module, seqType, e.info)]) else: const seqAppendPattern = "($2) #incrSeqV3($1, $3)" - call.r = ropecg(p.module, seqAppendPattern, [rdLoc(a), + call.snippet = ropecg(p.module, seqAppendPattern, [rdLoc(a), getTypeDesc(p.module, e[1].typ), genTypeInfoV1(p.module, seqType, e.info)]) # emit the write barrier if required, but we can always move here, so @@ -1342,22 +1349,14 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) = #if bt != b.t: # echo "YES ", e.info, " new: ", typeToString(bt), " old: ", typeToString(b.t) var dest = initLoc(locExpr, e[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)]) + var tmpL = getIntTemp(p) + lineCg(p, cpsStmts, "$1 = $2->$3++;$n", [tmpL.snippet, rdLoc(a), lenField(p)]) + dest.snippet = ropecg(p.module, "$1$3[$2]", [rdLoc(a), tmpL.snippet, dataField(p)]) genAssignment(p, dest, b, {needToCopy}) gcUsage(p.config, e) -proc genReset(p: BProc, n: PNode) = - var a: TLoc = initLocExpr(p, n[1]) - specializeReset(p, a) - when false: - linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n", - [addrLoc(p.config, a), - genTypeInfoV1(p.module, skipTypes(a.t, {tyVar}), n.info)]) - proc genDefault(p: BProc; n: PNode; d: var TLoc) = - if d.k == locNone: getTemp(p, n.typ, d, needsInit=true) + if d.k == locNone: d = getTemp(p, n.typ, needsInit=true) else: resetLoc(p, d) proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope; needsInit: bool) = @@ -1366,16 +1365,16 @@ proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope; needsInit: bool) = var b: TLoc = initLoc(locExpr, a.lode, OnHeap) let refType = typ.skipTypes(abstractInstOwned) assert refType.kind == tyRef - let bt = refType.lastSon + let bt = refType.elementType if sizeExpr == "": sizeExpr = "sizeof($1)" % [getTypeDesc(p.module, bt)] if optTinyRtti in p.config.globalOptions: if needsInit: - b.r = ropecg(p.module, "($1) #nimNewObj($2, NIM_ALIGNOF($3))", + b.snippet = ropecg(p.module, "($1) #nimNewObj($2, NIM_ALIGNOF($3))", [getTypeDesc(p.module, typ), sizeExpr, getTypeDesc(p.module, bt)]) else: - b.r = ropecg(p.module, "($1) #nimNewObjUninit($2, NIM_ALIGNOF($3))", + b.snippet = ropecg(p.module, "($1) #nimNewObjUninit($2, NIM_ALIGNOF($3))", [getTypeDesc(p.module, typ), sizeExpr, getTypeDesc(p.module, bt)]) genAssignment(p, a, b, {}) else: @@ -1400,15 +1399,15 @@ proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope; needsInit: bool) = 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)", [getTypeDesc(p.module, typ), ti, sizeExpr]) + b.snippet = ropecg(p.module, "($1) #newObj($2, $3)", [getTypeDesc(p.module, typ), ti, sizeExpr]) 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)", [getTypeDesc(p.module, typ), ti, sizeExpr]) + b.snippet = ropecg(p.module, "($1) #newObjRC1($2, $3)", [getTypeDesc(p.module, typ), ti, sizeExpr]) linefmt(p, cpsStmts, "$1 = $2;$n", [a.rdLoc, b.rdLoc]) else: - b.r = ropecg(p.module, "($1) #newObj($2, $3)", [getTypeDesc(p.module, typ), ti, sizeExpr]) + b.snippet = ropecg(p.module, "($1) #newObj($2, $3)", [getTypeDesc(p.module, typ), ti, sizeExpr]) genAssignment(p, a, b, {}) # set the object type: genObjectInit(p, cpsStmts, bt, a, constructRefObj) @@ -1434,18 +1433,18 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope; lenIsZero: bool) = if not lenIsZero: if p.config.selectedGC == gcGo: # we need the write barrier - call.r = ropecg(p.module, "($1) #newSeq($2, $3)", [getTypeDesc(p.module, seqtype), + call.snippet = ropecg(p.module, "($1) #newSeq($2, $3)", [getTypeDesc(p.module, seqtype), genTypeInfoV1(p.module, seqtype, dest.lode.info), length]) linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);$n", [addrLoc(p.config, dest), call.rdLoc]) else: - call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", [getTypeDesc(p.module, seqtype), + call.snippet = ropecg(p.module, "($1) #newSeqRC1($2, $3)", [getTypeDesc(p.module, seqtype), genTypeInfoV1(p.module, seqtype, dest.lode.info), length]) linefmt(p, cpsStmts, "$1 = $2;$n", [dest.rdLoc, call.rdLoc]) else: if lenIsZero: - call.r = rope"NIM_NIL" + call.snippet = rope"NIM_NIL" else: - call.r = ropecg(p.module, "($1) #newSeq($2, $3)", [getTypeDesc(p.module, seqtype), + call.snippet = ropecg(p.module, "($1) #newSeq($2, $3)", [getTypeDesc(p.module, seqtype), genTypeInfoV1(p.module, seqtype, dest.lode.info), length]) genAssignment(p, dest, call, {}) @@ -1456,7 +1455,7 @@ proc genNewSeq(p: BProc, e: PNode) = let seqtype = skipTypes(e[1].typ, abstractVarRange) linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3), NIM_ALIGNOF($3));$n", [a.rdLoc, b.rdLoc, - getTypeDesc(p.module, seqtype.lastSon), + getTypeDesc(p.module, seqtype.elementType), getSeqPayloadType(p.module, seqtype)]) else: let lenIsZero = e[2].kind == nkIntLit and e[2].intVal == 0 @@ -1467,12 +1466,13 @@ proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) = let seqtype = skipTypes(e.typ, abstractVarRange) var a: TLoc = initLocExpr(p, e[1]) if optSeqDestructors in p.config.globalOptions: - if d.k == locNone: getTemp(p, e.typ, d, needsInit=false) - linefmt(p, cpsStmts, "$1.len = 0; $1.p = ($4*) #newSeqPayload($2, sizeof($3), NIM_ALIGNOF($3));$n", - [d.rdLoc, a.rdLoc, getTypeDesc(p.module, seqtype.lastSon), + if d.k == locNone: d = getTemp(p, e.typ, needsInit=false) + linefmt(p, cpsStmts, "$1.len = 0; $1.p = ($4*) #newSeqPayloadUninit($2, sizeof($3), NIM_ALIGNOF($3));$n", + [d.rdLoc, a.rdLoc, getTypeDesc(p.module, seqtype.elementType), getSeqPayloadType(p.module, seqtype), ]) else: + if d.k == locNone: d = getTemp(p, e.typ, needsInit=false) # bug #22560 putIntoDest(p, d, e, ropecg(p.module, "($1)#nimNewSeqOfCap($2, $3)", [ getTypeDesc(p.module, seqtype), @@ -1487,9 +1487,13 @@ proc rawConstExpr(p: BProc, n: PNode; d: var TLoc) = if id == p.module.labels: # expression not found in the cache: inc(p.module.labels) - p.module.s[cfsData].addf("static NIM_CONST $1 $2 = ", [getTypeDesc(p.module, t), d.r]) - genBracedInit(p, n, isConst = true, t, p.module.s[cfsData]) - p.module.s[cfsData].addf(";$n", []) + var data = "static NIM_CONST $1 $2 = " % [getTypeDesc(p.module, t), d.snippet] + # bug #23627; when generating const object fields, it's likely that + # we need to generate type infos for the object, which may be an object with + # custom hooks. We need to generate potential consts in the hooks first. + genBracedInit(p, n, isConst = true, t, data) + data.addf(";$n", []) + p.module.s[cfsData].add data proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool = if d.k == locNone and n.len > ord(n.kind == nkObjConstr) and n.isDeepConstExpr: @@ -1498,8 +1502,31 @@ proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool = else: result = false + +proc genFieldObjConstr(p: BProc; ty: PType; useTemp, isRef: bool; nField, val, check: PNode; d: var TLoc; r: Rope; info: TLineInfo) = + var tmp2 = TLoc(snippet: r) + let field = lookupFieldAgain(p, ty, nField.sym, tmp2.snippet) + if field.loc.snippet == "": fillObjectFields(p.module, ty) + if field.loc.snippet == "": internalError(p.config, info, "genFieldObjConstr") + if check != nil and optFieldCheck in p.options: + genFieldCheck(p, check, r, field) + tmp2.snippet.add(".") + tmp2.snippet.add(field.loc.snippet) + if useTemp: + tmp2.k = locTemp + tmp2.storage = if isRef: OnHeap else: OnStack + else: + tmp2.k = d.k + tmp2.storage = if isRef: OnHeap else: d.storage + tmp2.lode = val + if nField.typ.skipTypes(abstractVar).kind in {tyOpenArray, tyVarargs}: + var tmp3 = getTemp(p, val.typ) + expr(p, val, tmp3) + genOpenArrayConv(p, tmp2, tmp3, {}) + else: + expr(p, val, tmp2) + proc genObjConstr(p: BProc, e: PNode, d: var TLoc) = - #echo renderTree e, " ", e.isDeepConstExpr # inheritance in C++ does not allow struct initialization so # we skip this step here: if not p.module.compileToCpp and optSeqDestructors notin p.config.globalOptions: @@ -1520,42 +1547,33 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) = (d.k notin {locTemp,locLocalVar,locGlobalVar,locParam,locField}) or (isPartOf(d.lode, e) != arNo) - var tmp: TLoc = TLoc() + var tmp: TLoc = default(TLoc) var r: Rope + let needsZeroMem = p.config.selectedGC notin {gcArc, gcAtomicArc, gcOrc} or nfAllFieldsSet notin e.flags if useTemp: - getTemp(p, t, tmp) + tmp = getTemp(p, t) r = rdLoc(tmp) if isRef: rawGenNew(p, tmp, "", needsInit = nfAllFieldsSet notin e.flags) - t = t.lastSon.skipTypes(abstractInstOwned) + t = t.elementType.skipTypes(abstractInstOwned) r = "(*$1)" % [r] gcUsage(p.config, e) - else: + elif needsZeroMem: constructLoc(p, tmp) + else: + genObjectInit(p, cpsStmts, t, tmp, constructObj) else: - resetLoc(p, d) + if needsZeroMem: resetLoc(p, d) + else: genObjectInit(p, cpsStmts, d.t, d, if isRef: constructRefObj else: constructObj) r = rdLoc(d) discard getTypeDesc(p.module, t) let ty = getUniqueType(t) for i in 1..<e.len: - let it = e[i] - var tmp2: TLoc = default(TLoc) - tmp2.r = r - let field = lookupFieldAgain(p, ty, it[0].sym, tmp2.r) - if field.loc.r == "": fillObjectFields(p.module, ty) - if field.loc.r == "": internalError(p.config, e.info, "genObjConstr") - if it.len == 3 and optFieldCheck in p.options: - genFieldCheck(p, it[2], r, field) - tmp2.r.add(".") - tmp2.r.add(field.loc.r) - if useTemp: - tmp2.k = locTemp - tmp2.storage = if isRef: OnHeap else: OnStack - else: - tmp2.k = d.k - tmp2.storage = if isRef: OnHeap else: d.storage - tmp2.lode = it[1] - expr(p, it[1], tmp2) + var check: PNode = nil + if e[i].len == 3 and optFieldCheck in p.options: + check = e[i][2] + genFieldObjConstr(p, ty, useTemp, isRef, e[i][0], e[i][1], check, d, r, e.info) + if useTemp: if d.k == locNone: d = tmp @@ -1574,16 +1592,16 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) = let doesAlias = lhsDoesAlias(d.lode, n) let dest = if doesAlias: addr(tmp) else: addr(d) if doesAlias: - getTemp(p, n.typ, tmp) + tmp = getTemp(p, n.typ) elif d.k == locNone: - getTemp(p, n.typ, d) + d = getTemp(p, n.typ) var lit = newRopeAppender() intLiteral(n.len, lit) if optSeqDestructors in p.config.globalOptions: let seqtype = n.typ linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3), NIM_ALIGNOF($3));$n", - [rdLoc dest[], lit, getTypeDesc(p.module, seqtype.lastSon), + [rdLoc dest[], lit, getTypeDesc(p.module, seqtype.elementType), getSeqPayloadType(p.module, seqtype)]) else: # generate call to newSeq before adding the elements per hand: @@ -1592,7 +1610,7 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) = arr = initLoc(locExpr, n[i], OnHeap) var lit = newRopeAppender() intLiteral(i, lit) - arr.r = ropecg(p.module, "$1$3[$2]", [rdLoc(dest[]), lit, dataField(p)]) + arr.snippet = ropecg(p.module, "$1$3[$2]", [rdLoc(dest[]), lit, dataField(p)]) arr.storage = OnHeap # we know that sequences are on the heap expr(p, n[i], arr) gcUsage(p.config, n) @@ -1609,14 +1627,14 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) = genSeqConstr(p, n[1], d) return if d.k == locNone: - getTemp(p, n.typ, d) + d = getTemp(p, n.typ) var a = initLocExpr(p, n[1]) # generate call to newSeq before adding the elements per hand: let L = toInt(lengthOrd(p.config, n[1].typ)) if optSeqDestructors in p.config.globalOptions: let seqtype = n.typ linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3), NIM_ALIGNOF($3));$n", - [rdLoc d, L, getTypeDesc(p.module, seqtype.lastSon), + [rdLoc d, L, getTypeDesc(p.module, seqtype.elementType), getSeqPayloadType(p.module, seqtype)]) else: var lit = newRopeAppender() @@ -1628,20 +1646,19 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) = elem = initLoc(locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), OnHeap) var lit = newRopeAppender() intLiteral(i, lit) - elem.r = ropecg(p.module, "$1$3[$2]", [rdLoc(d), lit, dataField(p)]) + elem.snippet = ropecg(p.module, "$1$3[$2]", [rdLoc(d), lit, dataField(p)]) elem.storage = OnHeap # we know that sequences are on the heap arr = initLoc(locExpr, lodeTyp elemType(skipTypes(n[1].typ, abstractInst)), a.storage) - arr.r = ropecg(p.module, "$1[$2]", [rdLoc(a), lit]) + arr.snippet = ropecg(p.module, "$1[$2]", [rdLoc(a), lit]) genAssignment(p, elem, arr, {needToCopy}) else: - var i: TLoc - getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), i) - linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n", [i.r, L]) + var i: TLoc = getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt)) + linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n", [i.snippet, L]) elem = initLoc(locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), OnHeap) - elem.r = ropecg(p.module, "$1$3[$2]", [rdLoc(d), rdLoc(i), dataField(p)]) + elem.snippet = ropecg(p.module, "$1$3[$2]", [rdLoc(d), rdLoc(i), dataField(p)]) elem.storage = OnHeap # we know that sequences are on the heap arr = initLoc(locExpr, lodeTyp elemType(skipTypes(n[1].typ, abstractInst)), a.storage) - arr.r = ropecg(p.module, "$1[$2]", [rdLoc(a), rdLoc(i)]) + arr.snippet = ropecg(p.module, "$1[$2]", [rdLoc(a), rdLoc(i)]) genAssignment(p, elem, arr, {needToCopy}) lineF(p, cpsStmts, "}$n", []) @@ -1657,11 +1674,11 @@ proc genNewFinalize(p: BProc, e: PNode) = b = initLoc(locExpr, a.lode, OnHeap) ti = genTypeInfo(p.config, p.module, refType, e.info) p.module.s[cfsTypeInit3].addf("$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)]) - b.r = ropecg(p.module, "($1) #newObj($2, sizeof($3))", [ + b.snippet = ropecg(p.module, "($1) #newObj($2, sizeof($3))", [ getTypeDesc(p.module, refType), - ti, getTypeDesc(p.module, skipTypes(refType.lastSon, abstractRange))]) + ti, getTypeDesc(p.module, skipTypes(refType.elementType, abstractRange))]) genAssignment(p, a, b, {}) # set the object type: - bt = skipTypes(refType.lastSon, abstractRange) + bt = skipTypes(refType.elementType, abstractRange) genObjectInit(p, cpsStmts, bt, a, constructRefObj) gcUsage(p.config, e) @@ -1693,12 +1710,12 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) = if t.kind notin {tyVar, tyLent}: nilCheck = r if t.kind notin {tyVar, tyLent} or not p.module.compileToCpp: r = ropecg(p.module, "(*$1)", [r]) - t = skipTypes(t.lastSon, typedescInst+{tyOwned}) + t = skipTypes(t.elementType, typedescInst+{tyOwned}) discard getTypeDesc(p.module, t) if not p.module.compileToCpp: - while t.kind == tyObject and t[0] != nil: + while t.kind == tyObject and t.baseClass != nil: r.add(".Sup") - t = skipTypes(t[0], skipPtrs) + t = skipTypes(t.baseClass, skipPtrs) if isObjLackingTypeField(t): globalError(p.config, x.info, "no 'of' operator available for pure objects") @@ -1782,13 +1799,13 @@ proc rdMType(p: BProc; a: TLoc; nilCheck: var Rope; result: var Rope; enforceV1 if t.kind notin {tyVar, tyLent}: nilCheck = derefs if t.kind notin {tyVar, tyLent} or not p.module.compileToCpp: derefs = "(*$1)" % [derefs] - t = skipTypes(t.lastSon, abstractInst) + t = skipTypes(t.elementType, abstractInst) result.add derefs discard getTypeDesc(p.module, t) if not p.module.compileToCpp: - while t.kind == tyObject and t[0] != nil: + while t.kind == tyObject and t.baseClass != nil: result.add(".Sup") - t = skipTypes(t[0], skipPtrs) + t = skipTypes(t.baseClass, skipPtrs) result.add ".m_type" if optTinyRtti in p.config.globalOptions and enforceV1: result.add "->typeInfoV1" @@ -1822,9 +1839,9 @@ proc genAccessTypeField(p: BProc; e: PNode; d: var TLoc) = template genDollar(p: BProc, n: PNode, d: var TLoc, frmt: string) = var a: TLoc = initLocExpr(p, n[1]) - a.r = ropecg(p.module, frmt, [rdLoc(a)]) + a.snippet = ropecg(p.module, frmt, [rdLoc(a)]) a.flags.excl lfIndirect # this flag should not be propagated here (not just for HCR) - if d.k == locNone: getTemp(p, n.typ, d) + if d.k == locNone: d = getTemp(p, n.typ) genAssignment(p, d, a, {}) gcUsage(p.config, n) @@ -1841,11 +1858,11 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) = var b = initLocExpr(p, a[2]) var c = initLocExpr(p, a[3]) if optBoundsCheck in p.options: - genBoundsCheck(p, m, b, c) + genBoundsCheck(p, m, b, c, skipTypes(m.t, abstractVarRange)) if op == mHigh: - putIntoDest(p, d, e, ropecg(p.module, "($2)-($1)", [rdLoc(b), rdLoc(c)])) + 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)])) + putIntoDest(p, d, e, ropecg(p.module, "(($2)-($1)+1)", [rdLoc(b), rdLoc(c)])) else: if not reifiedOpenArray(a): if op == mHigh: unaryExpr(p, e, d, "($1Len_0-1)") @@ -1863,8 +1880,8 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) = else: unaryExpr(p, e, d, "$1.Field1") of tyCstring: - if op == mHigh: unaryExpr(p, e, d, "($1 ? (#nimCStrLen($1)-1) : -1)") - else: unaryExpr(p, e, d, "($1 ? #nimCStrLen($1) : 0)") + if op == mHigh: unaryExpr(p, e, d, "(#nimCStrLen($1)-1)") + else: unaryExpr(p, e, d, "#nimCStrLen($1)") of tyString: var a: TLoc = initLocExpr(p, e[1]) var x = lenExpr(p, a) @@ -1872,26 +1889,18 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) = putIntoDest(p, d, e, x) of tySequence: # we go through a temporary here because people write bullshit code. - var tmp: TLoc = default(TLoc) + var tmp: TLoc = getIntTemp(p) var a = initLocExpr(p, e[1]) - getIntTemp(p, tmp) var x = lenExpr(p, a) if op == mHigh: x = "($1-1)" % [x] - lineCg(p, cpsStmts, "$1 = $2;$n", [tmp.r, x]) - putIntoDest(p, d, e, tmp.r) + lineCg(p, cpsStmts, "$1 = $2;$n", [tmp.snippet, x]) + putIntoDest(p, d, e, tmp.snippet) of tyArray: # YYY: length(sideeffect) is optimized away incorrectly? if op == mHigh: putIntoDest(p, d, e, rope(lastOrd(p.config, typ))) else: putIntoDest(p, d, e, rope(lengthOrd(p.config, typ))) else: internalError(p.config, e.info, "genArrayLen()") -proc makeAddr(n: PNode; idgen: IdGenerator): PNode = - if n.kind == nkHiddenAddr: - result = n - else: - result = newTree(nkHiddenAddr, n) - result.typ = makePtrType(n.typ, idgen) - proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) = if optSeqDestructors in p.config.globalOptions: e[1] = makeAddr(e[1], p.module.idgen) @@ -1907,13 +1916,13 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) = var call = initLoc(locCall, e, OnHeap) if not p.module.compileToCpp: const setLenPattern = "($3) #setLengthSeqV2(($1)?&($1)->Sup:NIM_NIL, $4, $2)" - call.r = ropecg(p.module, setLenPattern, [ + call.snippet = ropecg(p.module, setLenPattern, [ rdLoc(a), rdLoc(b), getTypeDesc(p.module, t), genTypeInfoV1(p.module, t.skipTypes(abstractInst), e.info)]) else: const setLenPattern = "($3) #setLengthSeqV2($1, $4, $2)" - call.r = ropecg(p.module, setLenPattern, [ + call.snippet = ropecg(p.module, setLenPattern, [ rdLoc(a), rdLoc(b), getTypeDesc(p.module, t), genTypeInfoV1(p.module, t.skipTypes(abstractInst), e.info)]) @@ -1929,7 +1938,7 @@ proc genSetLengthStr(p: BProc, e: PNode, d: var TLoc) = var b = initLocExpr(p, e[2]) var call = initLoc(locCall, e, OnHeap) - call.r = ropecg(p.module, "#setLengthStr($1, $2)", [ + call.snippet = ropecg(p.module, "#setLengthStr($1, $2)", [ rdLoc(a), rdLoc(b)]) genAssignment(p, a, call, {}) gcUsage(p.config, e) @@ -1941,8 +1950,7 @@ proc genSwap(p: BProc, e: PNode, d: var TLoc) = # b = temp cowBracket(p, e[1]) cowBracket(p, e[2]) - var tmp: TLoc - getTemp(p, skipTypes(e[1].typ, abstractVar), tmp) + var tmp: TLoc = getTemp(p, skipTypes(e[1].typ, abstractVar)) var a = initLocExpr(p, e[1]) # eval a var b = initLocExpr(p, e[2]) # eval b genAssignment(p, tmp, a, {}) @@ -2007,23 +2015,23 @@ proc genInOp(p: BProc, e: PNode, d: var TLoc) = a = initLocExpr(p, ea) b = initLoc(locExpr, e, OnUnknown) if e[1].len > 0: - b.r = rope("(") + b.snippet = rope("(") for i in 0..<e[1].len: let it = e[1][i] if it.kind == nkRange: x = initLocExpr(p, it[0]) y = initLocExpr(p, it[1]) - b.r.addf("$1 >= $2 && $1 <= $3", + b.snippet.addf("$1 >= $2 && $1 <= $3", [rdCharLoc(a), rdCharLoc(x), rdCharLoc(y)]) else: x = initLocExpr(p, it) - b.r.addf("$1 == $2", [rdCharLoc(a), rdCharLoc(x)]) - if i < e[1].len - 1: b.r.add(" || ") - b.r.add(")") + b.snippet.addf("$1 == $2", [rdCharLoc(a), rdCharLoc(x)]) + if i < e[1].len - 1: b.snippet.add(" || ") + b.snippet.add(")") else: # handle the case of an empty set - b.r = rope("0") - putIntoDest(p, d, e, b.r) + b.snippet = rope("0") + putIntoDest(p, d, e, b.snippet) else: assert(e[1].typ != nil) assert(e[2].typ != nil) @@ -2083,12 +2091,12 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mExcl: binaryStmtInExcl(p, e, d, "$1[(NU)($2)>>3] &= ~(1U<<($2&7U));$n") of mCard: var a: TLoc = initLocExpr(p, e[1]) - putIntoDest(p, d, e, ropecg(p.module, "#cardSet($1, $2)", [addrLoc(p.config, a), size])) + putIntoDest(p, d, e, ropecg(p.module, "#cardSet($1, $2)", [rdCharLoc(a), size])) of mLtSet, mLeSet: - getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), i) # our counter + i = getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt)) # our counter a = initLocExpr(p, e[1]) b = initLocExpr(p, e[2]) - if d.k == locNone: getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyBool), d) + if d.k == locNone: d = getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyBool)) if op == mLtSet: linefmt(p, cpsStmts, lookupOpr[mLtSet], [rdLoc(i), size, rdLoc(d), rdLoc(a), rdLoc(b)]) @@ -2103,10 +2111,10 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) = putIntoDest(p, d, e, ropecg(p.module, "(#nimCmpMem($1, $2, $3)==0)", [a.rdCharLoc, b.rdCharLoc, size])) of mMulSet, mPlusSet, mMinusSet: # we inline the simple for loop for better code generation: - getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), i) # our counter + i = getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt)) # our counter a = initLocExpr(p, e[1]) b = initLocExpr(p, e[2]) - if d.k == locNone: getTemp(p, setType, d) + if d.k == locNone: d = getTemp(p, setType) lineF(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) $n" & " $3[$1] = $4[$1] $6 $5[$1];$n", [ @@ -2161,7 +2169,7 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) = inc(p.labels) var lbl = p.labels.rope var tmp: TLoc = default(TLoc) - tmp.r = "LOC$1.source" % [lbl] + tmp.snippet = "LOC$1.source" % [lbl] let destsize = getSize(p.config, destt) let srcsize = getSize(p.config, srct) @@ -2226,12 +2234,16 @@ proc genRangeChck(p: BProc, n: PNode, d: var TLoc) = raiseInstr(p, p.s(cpsStmts)) linefmt p, cpsStmts, "}$n", [] - putIntoDest(p, d, n, "(($1) ($2))" % + if sameBackendTypeIgnoreRange(dest, n[0].typ): + # don't cast so an address can be taken for `var` conversions + putIntoDest(p, d, n, "($1)" % [rdCharLoc(a)], a.storage) + else: + putIntoDest(p, d, n, "(($1) ($2))" % [getTypeDesc(p.module, dest), rdCharLoc(a)], a.storage) proc genConv(p: BProc, e: PNode, d: var TLoc) = let destType = e.typ.skipTypes({tyVar, tyLent, tyGenericInst, tyAlias, tySink}) - if sameBackendType(destType, e[1].typ): + if sameBackendTypeIgnoreRange(destType, e[1].typ): expr(p, e[1], d) else: genSomeCast(p, e, d) @@ -2245,9 +2257,15 @@ proc convStrToCStr(p: BProc, n: PNode, d: var TLoc) = proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) = var a: TLoc = initLocExpr(p, n[0]) - putIntoDest(p, d, n, - ropecg(p.module, "#cstrToNimstr($1)", [rdLoc(a)]), - a.storage) + if p.module.compileToCpp: + # fixes for const qualifier; bug #12703; bug #19588 + putIntoDest(p, d, n, + ropecg(p.module, "#cstrToNimstr((NCSTRING) $1)", [rdLoc(a)]), + a.storage) + else: + putIntoDest(p, d, n, + ropecg(p.module, "#cstrToNimstr($1)", [rdLoc(a)]), + a.storage) gcUsage(p.config, n) proc genStrEquals(p: BProc, e: PNode, d: var TLoc) = @@ -2288,9 +2306,6 @@ proc binaryFloatArith(p: BProc, e: PNode, d: var TLoc, m: TMagic) = else: binaryArith(p, e, d, m) -proc skipAddr(n: PNode): PNode = - result = if n.kind in {nkAddr, nkHiddenAddr}: n[0] else: n - proc genWasMoved(p: BProc; n: PNode) = var a: TLoc let n1 = n[1].skipAddr @@ -2311,19 +2326,39 @@ proc genMove(p: BProc; n: PNode; d: var TLoc) = genStmts(p, n[3]) linefmt(p, cpsStmts, "}$n$1.len = $2.len; $1.p = $2.p;$n", [rdLoc(a), rdLoc(src)]) else: - if d.k == locNone: getTemp(p, n.typ, d) + if d.k == locNone: d = getTemp(p, n.typ) if p.config.selectedGC in {gcArc, gcAtomicArc, gcOrc}: genAssignment(p, d, a, {}) var op = getAttachedOp(p.module.g.graph, n.typ, attachedWasMoved) if op == nil: resetLoc(p, a) else: - let addrExp = makeAddr(n[1], p.module.idgen) - let wasMovedCall = newTreeI(nkCall, n.info, newSymNode(op), addrExp) - genCall(p, wasMovedCall, d) + var b = initLocExpr(p, newSymNode(op)) + case skipTypes(a.t, abstractVar+{tyStatic}).kind + of tyOpenArray, tyVarargs: # todo fixme generated `wasMoved` hooks for + # openarrays, but it probably shouldn't? + var s: string + if reifiedOpenArray(a.lode): + if a.t.kind in {tyVar, tyLent}: + s = "$1->Field0, $1->Field1" % [rdLoc(a)] + else: + s = "$1.Field0, $1.Field1" % [rdLoc(a)] + else: + s = "$1, $1Len_0" % [rdLoc(a)] + linefmt(p, cpsStmts, "$1($2);$n", [rdLoc(b), s]) + else: + if p.module.compileToCpp: + linefmt(p, cpsStmts, "$1($2);$n", [rdLoc(b), rdLoc(a)]) + else: + linefmt(p, cpsStmts, "$1($2);$n", [rdLoc(b), byRefLoc(p, a)]) else: - let flags = if not canMove(p, n[1], d): {needToCopy} else: {} - genAssignment(p, d, a, flags) + if n[1].kind == nkSym and isSinkParam(n[1].sym): + var tmp = getTemp(p, n[1].typ.skipTypes({tySink})) + genAssignment(p, tmp, a, {needToCopySinkParam}) + genAssignment(p, d, tmp, {}) + resetLoc(p, tmp) + else: + genAssignment(p, d, a, {}) resetLoc(p, a) proc genDestroy(p: BProc; n: PNode) = @@ -2346,7 +2381,7 @@ proc genDestroy(p: BProc; n: PNode) = linefmt(p, cpsStmts, "if ($1.p && !($1.p->cap & NIM_STRLIT_FLAG)) {$n" & " #alignedDealloc($1.p, NIM_ALIGNOF($2));$n" & "}$n", - [rdLoc(a), getTypeDesc(p.module, t.lastSon)]) + [rdLoc(a), getTypeDesc(p.module, t.elementType)]) else: discard "nothing to do" else: let t = n[1].typ.skipTypes(abstractVar) @@ -2357,7 +2392,7 @@ proc genDestroy(p: BProc; n: PNode) = proc genDispose(p: BProc; n: PNode) = when false: - let elemType = n[1].typ.skipTypes(abstractVar).lastSon + let elemType = n[1].typ.skipTypes(abstractVar).elementType var a: TLoc = initLocExpr(p, n[1].skipAddr) @@ -2372,11 +2407,11 @@ proc genDispose(p: BProc; n: PNode) = lineCg(p, cpsStmts, ["#nimDestroyAndDispose($#)", rdLoc(a)]) proc genSlice(p: BProc; e: PNode; d: var TLoc) = - let (x, y) = genOpenArraySlice(p, e, e.typ, e.typ.lastSon, + let (x, y) = genOpenArraySlice(p, e, e.typ, e.typ.elementType, prepareForMutation = e[1].kind == nkHiddenDeref and e[1].typ.skipTypes(abstractInst).kind == tyString and p.config.selectedGC in {gcArc, gcAtomicArc, gcOrc}) - if d.k == locNone: getTemp(p, e.typ, d) + if d.k == locNone: d = getTemp(p, e.typ) linefmt(p, cpsStmts, "$1.Field0 = $2; $1.Field1 = $3;$n", [rdLoc(d), x, y]) when false: localError(p.config, e.info, "invalid context for 'toOpenArray'; " & @@ -2431,7 +2466,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = var call = initLoc(locCall, e, OnHeap) var dest = initLocExpr(p, e[1]) var b = initLocExpr(p, e[2]) - call.r = ropecg(p.module, "#addChar($1, $2)", [rdLoc(dest), rdLoc(b)]) + call.snippet = ropecg(p.module, "#addChar($1, $2)", [rdLoc(dest), rdLoc(b)]) genAssignment(p, dest, call, {}) of mAppendStrStr: genStrAppend(p, e, d) of mAppendSeqElem: @@ -2444,16 +2479,14 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mLeStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) <= 0)") of mLtStr: binaryExpr(p, e, d, "(#cmpStrings($1, $2) < 0)") of mIsNil: genIsNil(p, e, d) - of mIntToStr: genDollar(p, e, d, "#nimIntToStr($1)") - of mInt64ToStr: genDollar(p, e, d, "#nimInt64ToStr($1)") of mBoolToStr: genDollar(p, e, d, "#nimBoolToStr($1)") of mCharToStr: genDollar(p, e, d, "#nimCharToStr($1)") - of mFloatToStr: - if e[1].typ.skipTypes(abstractInst).kind == tyFloat32: - genDollar(p, e, d, "#nimFloat32ToStr($1)") + of mCStrToStr: + if p.module.compileToCpp: + # fixes for const qualifier; bug #12703; bug #19588 + genDollar(p, e, d, "#cstrToNimstr((NCSTRING) $1)") else: - genDollar(p, e, d, "#nimFloatToStr($1)") - of mCStrToStr: genDollar(p, e, d, "#cstrToNimstr($1)") + genDollar(p, e, d, "#cstrToNimstr($1)") of mStrToStr, mUnown: expr(p, e[1], d) of generatedMagics: genCall(p, e, d) of mEnumToStr: @@ -2497,14 +2530,18 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = let member = if t.kind == tyTuple: "Field" & rope(dotExpr[1].sym.position) - else: dotExpr[1].sym.loc.r + else: dotExpr[1].sym.loc.snippet putIntoDest(p,d,e, "((NI)offsetof($1, $2))" % [tname, member]) of mChr: genSomeCast(p, e, d) of mOrd: genOrd(p, e, d) of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray: genArrayLen(p, e, d, op) - of mGCref: unaryStmt(p, e, d, "if ($1) { #nimGCref($1); }$n") - of mGCunref: unaryStmt(p, e, d, "if ($1) { #nimGCunref($1); }$n") + of mGCref: + # only a magic for the old GCs + unaryStmt(p, e, d, "if ($1) { #nimGCref($1); }$n") + of mGCunref: + # only a magic for the old GCs + 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, @@ -2516,8 +2553,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = # - not sure, and it wouldn't work if the symbol behind the magic isn't # somehow forward-declared from some other usage, but it is *possible* if lfNoDecl notin opr.loc.flags: - let prc = magicsys.getCompilerProc(p.module.g.graph, $opr.loc.r) - assert prc != nil, $opr.loc.r + let prc = magicsys.getCompilerProc(p.module.g.graph, $opr.loc.snippet) + assert prc != nil, $opr.loc.snippet # HACK: # Explicitly add this proc as declared here so the cgsym call doesn't # add a forward declaration - without this we could end up with the same @@ -2530,14 +2567,13 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = let wasDeclared = containsOrIncl(p.module.declaredProtos, prc.id) # Make the function behind the magic get actually generated - this will # not lead to a forward declaration! The genCall will lead to one. - cgsym(p.module, $opr.loc.r) + cgsym(p.module, $opr.loc.snippet) # make sure we have pointer-initialising code for hot code reloading if not wasDeclared and p.hcrOn: p.module.s[cfsDynLibInit].addf("\t$1 = ($2) hcrGetProc($3, \"$1\");$n", [mangleDynLibProc(prc), getTypeDesc(p.module, prc.loc.t), getModuleDllPath(p.module, prc)]) genCall(p, e, d) of mDefault, mZeroDefault: genDefault(p, e, d) - of mReset: genReset(p, e) of mEcho: genEcho(p, e[1].skipConv) of mArrToSeq: genArrToSeq(p, e, d) of mNLen..mNError, mSlurp..mQuoteAst: @@ -2573,6 +2609,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mTrace: discard "no code to generate" of mEnsureMove: expr(p, e[1], d) + of mDup: + expr(p, e[1], d) else: when defined(debugMagics): echo p.prc.name.s, " ", p.prc.id, " ", p.prc.flags, " ", p.prc.ast[genericParamsPos].kind @@ -2591,14 +2629,14 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) = genSetNode(p, e, elem) putIntoDest(p, d, e, elem) else: - if d.k == locNone: getTemp(p, e.typ, d) + if d.k == locNone: d = getTemp(p, e.typ) if getSize(p.config, e.typ) > 8: # big set: linefmt(p, cpsStmts, "#nimZeroMem($1, sizeof($2));$n", [rdLoc(d), getTypeDesc(p.module, e.typ)]) for it in e.sons: if it.kind == nkRange: - getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), idx) # our counter + idx = getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt)) # our counter a = initLocExpr(p, it[0]) b = initLocExpr(p, it[1]) var aa = newRopeAppender() @@ -2620,7 +2658,7 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) = lineF(p, cpsStmts, "$1 = 0;$n", [rdLoc(d)]) for it in e.sons: if it.kind == nkRange: - getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), idx) # our counter + idx = getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt)) # our counter a = initLocExpr(p, it[0]) b = initLocExpr(p, it[1]) var aa = newRopeAppender() @@ -2650,15 +2688,15 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) = let doesAlias = lhsDoesAlias(d.lode, n) let dest = if doesAlias: addr(tmp) else: addr(d) if doesAlias: - getTemp(p, n.typ, tmp) + tmp = getTemp(p, n.typ) elif d.k == locNone: - getTemp(p, n.typ, d) + d = getTemp(p, n.typ) for i in 0..<n.len: var it = n[i] if it.kind == nkExprColonExpr: it = it[1] rec = initLoc(locExpr, it, dest[].storage) - rec.r = "$1.Field$2" % [rdLoc(dest[]), rope(i)] + rec.snippet = "$1.Field$2" % [rdLoc(dest[]), rope(i)] rec.flags.incl(lfEnforceDeref) expr(p, it, rec) @@ -2695,7 +2733,7 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) = linefmt(p, cpsStmts, "$1.ClP_0 = $2; $1.ClE_0 = $3;$n", [d.rdLoc, a.rdLoc, b.rdLoc]) else: - getTemp(p, n.typ, tmp) + tmp = getTemp(p, n.typ) linefmt(p, cpsStmts, "$1.ClP_0 = $2; $1.ClE_0 = $3;$n", [tmp.rdLoc, a.rdLoc, b.rdLoc]) putLocIntoDest(p, d, tmp) @@ -2703,17 +2741,17 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) = proc genArrayConstr(p: BProc, n: PNode, d: var TLoc) = var arr: TLoc if not handleConstExpr(p, n, d): - if d.k == locNone: getTemp(p, n.typ, d) + if d.k == locNone: d = getTemp(p, n.typ) for i in 0..<n.len: arr = initLoc(locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), d.storage) var lit = newRopeAppender() intLiteral(i, lit) - arr.r = "$1[$2]" % [rdLoc(d), lit] + arr.snippet = "$1[$2]" % [rdLoc(d), lit] expr(p, n[i], arr) proc genComplexConst(p: BProc, sym: PSym, d: var TLoc) = requestConstImpl(p, sym) - assert((sym.loc.r != "") and (sym.loc.t != nil)) + assert((sym.loc.snippet != "") and (sym.loc.t != nil)) putLocIntoDest(p, d, sym.loc) template genStmtListExprImpl(exprOrStmt) {.dirty.} = @@ -2845,24 +2883,24 @@ proc genConstSetup(p: BProc; sym: PSym): bool = result = lfNoDecl notin sym.loc.flags proc genConstHeader(m, q: BModule; p: BProc, sym: PSym) = - if sym.loc.r == "": + if sym.loc.snippet == "": if not genConstSetup(p, sym): return - assert(sym.loc.r != "", $sym.name.s & $sym.itemId) + assert(sym.loc.snippet != "", $sym.name.s & $sym.itemId) if m.hcrOn: - m.s[cfsVars].addf("static $1* $2;$n", [getTypeDesc(m, sym.loc.t, dkVar), sym.loc.r]); + m.s[cfsVars].addf("static $1* $2;$n", [getTypeDesc(m, sym.loc.t, dkVar), sym.loc.snippet]); m.initProc.procSec(cpsLocals).addf( - "\t$1 = ($2*)hcrGetGlobal($3, \"$1\");$n", [sym.loc.r, + "\t$1 = ($2*)hcrGetGlobal($3, \"$1\");$n", [sym.loc.snippet, getTypeDesc(m, sym.loc.t, dkVar), getModuleDllPath(q, sym)]) else: let headerDecl = "extern NIM_CONST $1 $2;$n" % - [getTypeDesc(m, sym.loc.t, dkVar), sym.loc.r] + [getTypeDesc(m, sym.loc.t, dkVar), sym.loc.snippet] m.s[cfsData].add(headerDecl) if sfExportc in sym.flags and p.module.g.generatedHeader != nil: p.module.g.generatedHeader.s[cfsData].add(headerDecl) proc genConstDefinition(q: BModule; p: BProc; sym: PSym) = # add a suffix for hcr - will later init the global pointer with this data - let actualConstName = if q.hcrOn: sym.loc.r & "_const" else: sym.loc.r + let actualConstName = if q.hcrOn: sym.loc.snippet & "_const" else: sym.loc.snippet var data = newRopeAppender() data.addf("N_LIB_PRIVATE NIM_CONST $1 $2 = ", [getTypeDesc(q, sym.typ), actualConstName]) @@ -2871,16 +2909,16 @@ proc genConstDefinition(q: BModule; p: BProc; sym: PSym) = q.s[cfsData].add data if q.hcrOn: # generate the global pointer with the real name - q.s[cfsVars].addf("static $1* $2;$n", [getTypeDesc(q, sym.loc.t, dkVar), sym.loc.r]) + q.s[cfsVars].addf("static $1* $2;$n", [getTypeDesc(q, sym.loc.t, dkVar), sym.loc.snippet]) # register it (but ignore the boolean result of hcrRegisterGlobal) q.initProc.procSec(cpsLocals).addf( "\thcrRegisterGlobal($1, \"$2\", sizeof($3), NULL, (void**)&$2);$n", - [getModuleDllPath(q, sym), sym.loc.r, rdLoc(sym.loc)]) + [getModuleDllPath(q, sym), sym.loc.snippet, rdLoc(sym.loc)]) # always copy over the contents of the actual constant with the _const # suffix ==> this means that the constant is reloadable & updatable! q.initProc.procSec(cpsLocals).add(ropecg(q, "\t#nimCopyMem((void*)$1, (NIM_CONST void*)&$2, sizeof($3));$n", - [sym.loc.r, actualConstName, rdLoc(sym.loc)])) + [sym.loc.snippet, actualConstName, rdLoc(sym.loc)])) proc genConstStmt(p: BProc, n: PNode) = # This code is only used in the new DCE implementation. @@ -2920,7 +2958,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = genProcPrototype(p.module, sym) else: genProc(p.module, sym) - if sym.loc.r == "" or sym.loc.lode == nil: + if sym.loc.snippet == "" or sym.loc.lode == nil: internalError(p.config, n.info, "expr: proc not init " & sym.name.s) putLocIntoDest(p, d, sym.loc) of skConst: @@ -2930,7 +2968,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = putIntoDest(p, d, n, lit, OnStatic) elif useAliveDataFromDce in p.module.flags: genConstHeader(p.module, p.module, p, sym) - assert((sym.loc.r != "") and (sym.loc.t != nil)) + assert((sym.loc.snippet != "") and (sym.loc.t != nil)) putLocIntoDest(p, d, sym.loc) else: genComplexConst(p, sym, d) @@ -2945,14 +2983,14 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = if sfCompileTime in sym.flags: genSingleVar(p, sym, n, astdef(sym)) - if sym.loc.r == "" or sym.loc.t == nil: + if sym.loc.snippet == "" or sym.loc.t == nil: #echo "FAILED FOR PRCO ", p.prc.name.s #echo renderTree(p.prc.ast, {renderIds}) internalError p.config, n.info, "expr: var not init " & sym.name.s & "_" & $sym.id if sfThread in sym.flags: accessThreadLocalVar(p, sym) if emulatedThreadVars(p.config): - putIntoDest(p, d, sym.loc.lode, "NimTV_->" & sym.loc.r) + putIntoDest(p, d, sym.loc.lode, "NimTV_->" & sym.loc.snippet) else: putLocIntoDest(p, d, sym.loc) else: @@ -2960,17 +2998,17 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = of skTemp: when false: # this is more harmful than helpful. - if sym.loc.r == "": + if sym.loc.snippet == "": # we now support undeclared 'skTemp' variables for easier # transformations in other parts of the compiler: assignLocalVar(p, n) - if sym.loc.r == "" or sym.loc.t == nil: + if sym.loc.snippet == "" or sym.loc.t == nil: #echo "FAILED FOR PRCO ", p.prc.name.s #echo renderTree(p.prc.ast, {renderIds}) internalError(p.config, n.info, "expr: temp not init " & sym.name.s & "_" & $sym.id) putLocIntoDest(p, d, sym.loc) of skParam: - if sym.loc.r == "" or sym.loc.t == nil: + if sym.loc.snippet == "" or sym.loc.t == nil: # echo "FAILED FOR PRCO ", p.prc.name.s # debug p.prc.typ.n # echo renderTree(p.prc.ast, {renderIds}) @@ -3060,7 +3098,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = of nkLambdaKinds: var sym = n[namePos].sym genProc(p.module, sym) - if sym.loc.r == "" or sym.loc.lode == nil: + if sym.loc.snippet == "" or sym.loc.lode == nil: internalError(p.config, n.info, "expr: proc not init " & sym.name.s) putLocIntoDest(p, d, sym.loc) of nkClosure: genClosure(p, n, d) @@ -3091,7 +3129,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = if ex.kind != nkEmpty: genLineDir(p, n) var a: TLoc = initLocExprSingleUse(p, ex) - line(p, cpsStmts, "(void)(" & a.r & ");\L") + line(p, cpsStmts, "(void)(" & a.snippet & ");\L") of nkAsmStmt: genAsmStmt(p, n) of nkTryStmt, nkHiddenTryStmt: case p.config.exc @@ -3178,17 +3216,17 @@ proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo; result: var Rope) = result.add "}" of tyTuple: result.add "{" - if p.vccAndC and t.len == 0: + if p.vccAndC and t.isEmptyTupleType: result.add "0" - for i in 0..<t.len: + for i, a in t.ikids: if i > 0: result.add ", " - getDefaultValue(p, t[i], info, result) + getDefaultValue(p, a, info, result) result.add "}" of tyArray: result.add "{" - for i in 0..<toInt(lengthOrd(p.config, t.sons[0])): + for i in 0..<toInt(lengthOrd(p.config, t.indexType)): if i > 0: result.add ", " - getDefaultValue(p, t.sons[1], info, result) + getDefaultValue(p, t.elementType, info, result) result.add "}" #result = rope"{}" of tyOpenArray, tyVarargs: @@ -3199,22 +3237,6 @@ proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo; result: var Rope) = else: globalError(p.config, info, "cannot create null element for: " & $t.kind) -proc caseObjDefaultBranch(obj: PNode; branch: Int128): int = - result = 0 - for i in 1 ..< obj.len: - for j in 0 .. obj[i].len - 2: - if obj[i][j].kind == nkRange: - let x = getOrdValue(obj[i][j][0]) - let y = getOrdValue(obj[i][j][1]) - if branch >= x and branch <= y: - return i - elif getOrdValue(obj[i][j]) == branch: - return i - if obj[i].len == 1: - # else branch - return i - assert(false, "unreachable") - proc isEmptyCaseObjectBranch(n: PNode): bool = for it in n: if it.kind == nkSym and not isEmptyType(it.sym.typ): return false @@ -3229,7 +3251,8 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode, getNullValueAux(p, t, it, constOrNil, result, count, isConst, info) of nkRecCase: getNullValueAux(p, t, obj[0], constOrNil, result, count, isConst, info) - if count > 0: result.add ", " + var res = "" + if count > 0: res.add ", " var branch = Zero if constOrNil != nil: ## find kind value, default is zero if not specified @@ -3243,18 +3266,21 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode, break let selectedBranch = caseObjDefaultBranch(obj, branch) - result.add "{" + res.add "{" var countB = 0 let b = lastSon(obj[selectedBranch]) # designated initilization is the only way to init non first element of unions # branches are allowed to have no members (b.len == 0), in this case they don't need initializer if b.kind == nkRecList and not isEmptyCaseObjectBranch(b): - result.add "._" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch & " = {" - getNullValueAux(p, t, b, constOrNil, result, countB, isConst, info) - result.add "}" + res.add "._" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch & " = {" + getNullValueAux(p, t, b, constOrNil, res, countB, isConst, info) + res.add "}" elif b.kind == nkSym: - result.add "." & mangleRecFieldName(p.module, b.sym) & " = " - getNullValueAux(p, t, b, constOrNil, result, countB, isConst, info) + res.add "." & mangleRecFieldName(p.module, b.sym) & " = " + getNullValueAux(p, t, b, constOrNil, res, countB, isConst, info) + else: + return + result.add res result.add "}" of nkSym: @@ -3279,7 +3305,7 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode, proc getNullValueAuxT(p: BProc; orig, t: PType; obj, constOrNil: PNode, result: var Rope; count: var int; isConst: bool, info: TLineInfo) = - var base = t[0] + var base = t.baseClass let oldRes = result let oldcount = count if base != nil: @@ -3311,7 +3337,7 @@ proc genConstObjConstr(p: BProc; n: PNode; isConst: bool; result: var Rope) = proc genConstSimpleList(p: BProc, n: PNode; isConst: bool; result: var Rope) = result.add "{" if p.vccAndC and n.len == 0 and n.typ.kind == tyArray: - getDefaultValue(p, n.typ[1], n.info, result) + getDefaultValue(p, n.typ.elementType, n.info, result) for i in 0..<n.len: let it = n[i] if i > 0: result.add ",\n" @@ -3428,7 +3454,7 @@ proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType; resul genConstSimpleList(p, n, isConst, data) let payload = getTempName(p.module) - let ctype = getTypeDesc(p.module, typ[0]) + let ctype = getTypeDesc(p.module, typ.elementType) let arrLen = n.len appcg(p.module, cfsStrData, "static $5 $1 $3[$2] = $4;$n", [ |