diff options
-rw-r--r-- | compiler/ccgexprs.nim | 375 | ||||
-rw-r--r-- | compiler/ccgliterals.nim | 2 | ||||
-rw-r--r-- | compiler/ccgstmts.nim | 105 | ||||
-rw-r--r-- | compiler/ccgthreadvars.nim | 2 | ||||
-rw-r--r-- | compiler/ccgtrav.nim | 21 | ||||
-rw-r--r-- | compiler/ccgtypes.nim | 14 | ||||
-rw-r--r-- | compiler/cgen.nim | 281 |
7 files changed, 451 insertions, 349 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 442c9a91b..00afd04fa 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -171,13 +171,13 @@ proc canMove(p: BProc, n: PNode): bool = 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)) + linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) elif dest.storage == OnHeap: linefmt(p, cpsStmts, "#asgnRef((void**) $1, $2);$n", - addrLoc(p.config, dest), rdLoc(src)) + [addrLoc(p.config, dest), rdLoc(src)]) else: linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);$n", - addrLoc(p.config, dest), rdLoc(src)) + [addrLoc(p.config, dest), rdLoc(src)]) proc asgnComplexity(n: PNode): int = if n != nil: @@ -243,26 +243,26 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = if p.config.selectedGC == gcDestructors: linefmt(p, cpsStmts, "$1 = $2;$n", - rdLoc(dest), rdLoc(src)) + [rdLoc(dest), rdLoc(src)]) elif needToCopy notin flags or tfShallow in skipTypes(dest.t, abstractVarRange).flags: 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)) + [addrLoc(p.config, dest), addrLoc(p.config, src), rdLoc(dest)]) else: linefmt(p, cpsStmts, "#genericShallowAssign((void*)$1, (void*)$2, $3);$n", - addrLoc(p.config, dest), addrLoc(p.config, src), genTypeInfo(p.module, dest.t, dest.lode.info)) + [addrLoc(p.config, dest), addrLoc(p.config, src), genTypeInfo(p.module, dest.t, dest.lode.info)]) else: linefmt(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n", - addrLoc(p.config, dest), addrLoc(p.config, src), genTypeInfo(p.module, dest.t, dest.lode.info)) + [addrLoc(p.config, dest), addrLoc(p.config, src), genTypeInfo(p.module, dest.t, dest.lode.info)]) proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = # This function replaces all other methods for generating # the assignment operation in C. if src.t != nil and src.t.kind == tyPtr: # little HACK to support the new 'var T' as return type: - linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) + linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) return let ty = skipTypes(dest.t, abstractRange + tyUserTypeClasses + {tyStatic}) case ty.kind @@ -275,8 +275,8 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = genRefAssign(p, dest, src) else: linefmt(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n", - addrLoc(p.config, dest), rdLoc(src), - genTypeInfo(p.module, dest.t, dest.lode.info)) + [addrLoc(p.config, dest), rdLoc(src), + genTypeInfo(p.module, dest.t, dest.lode.info)]) of tyString: if p.config.selectedGC == gcDestructors: genGenericAsgn(p, dest, src, flags) @@ -284,36 +284,36 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = 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) + 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) 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) + [dest.rdLoc, src.rdLoc, tmp.rdLoc]) + linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", [tmp.rdLoc]) else: linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n", - addrLoc(p.config, dest), rdLoc(src)) + [addrLoc(p.config, dest), rdLoc(src)]) of tyProc: 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) - linefmt(p, cpsStmts, "$1.ClP_0 = $2.ClP_0;$n", rdLoc(dest), rdLoc(src)) + 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)) + 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) else: genGenericAsgn(p, dest, src, flags) else: - linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) + linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) of tyObject: # XXX: check for subtyping? if ty.isImportedCppType: - linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) + linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) elif not isObjLackingTypeField(ty): genGenericAsgn(p, dest, src, flags) elif containsGarbageCollectedRef(ty): @@ -324,46 +324,46 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = else: genGenericAsgn(p, dest, src, flags) else: - linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) + linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) of tyArray: if containsGarbageCollectedRef(dest.t): genGenericAsgn(p, dest, src, flags) else: linefmt(p, cpsStmts, "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n", - rdLoc(dest), rdLoc(src), getTypeDesc(p.module, dest.t)) + [rdLoc(dest), rdLoc(src), getTypeDesc(p.module, dest.t)]) of tyOpenArray, tyVarargs: # open arrays are always on the stack - really? What if a sequence is # passed to an open array? 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), - genTypeInfo(p.module, dest.t, dest.lode.info)) + [addrLoc(p.config, dest), addrLoc(p.config, src), + genTypeInfo(p.module, dest.t, dest.lode.info)]) else: linefmt(p, cpsStmts, # bug #4799, keep the nimCopyMem for a while #"#nimCopyMem((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len_0);$n", "$1 = $2;$n", - rdLoc(dest), rdLoc(src)) + [rdLoc(dest), rdLoc(src)]) of tySet: if mapType(p.config, ty) == ctArray: linefmt(p, cpsStmts, "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, $3);$n", - rdLoc(dest), rdLoc(src), rope(getSize(p.config, dest.t))) + [rdLoc(dest), rdLoc(src), getSize(p.config, dest.t)]) else: - linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) + linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) of tyPtr, tyPointer, tyChar, tyBool, tyEnum, tyCString, tyInt..tyUInt64, tyRange, tyVar, tyLent: - linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) + linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) else: internalError(p.config, "genAssignment: " & $ty.kind) if optMemTracker in p.options and dest.storage in {OnHeap, OnUnknown}: #writeStackTrace() #echo p.currLineInfo, " requesting" linefmt(p, cpsStmts, "#memTrackerWrite((void*)$1, $2, $3, $4);$n", - addrLoc(p.config, dest), rope getSize(p.config, dest.t), + [addrLoc(p.config, dest), getSize(p.config, dest.t), makeCString(toFullPath(p.config, p.currLineInfo)), - rope p.currLineInfo.safeLineNm) + p.currLineInfo.safeLineNm]) proc genDeepCopy(p: BProc; dest, src: TLoc) = template addrLocOrTemp(a: TLoc): Rope = @@ -380,26 +380,26 @@ proc genDeepCopy(p: BProc; dest, src: TLoc) = of tyPtr, tyRef, tyProc, tyTuple, tyObject, tyArray: # XXX optimize this linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);$n", - addrLoc(p.config, dest), addrLocOrTemp(src), - genTypeInfo(p.module, dest.t, dest.lode.info)) + [addrLoc(p.config, dest), addrLocOrTemp(src), + genTypeInfo(p.module, dest.t, dest.lode.info)]) of tySequence, tyString: linefmt(p, cpsStmts, "#genericSeqDeepCopy($1, $2, $3);$n", - addrLoc(p.config, dest), rdLoc(src), - genTypeInfo(p.module, dest.t, dest.lode.info)) + [addrLoc(p.config, dest), rdLoc(src), + genTypeInfo(p.module, dest.t, dest.lode.info)]) of tyOpenArray, tyVarargs: linefmt(p, cpsStmts, "#genericDeepCopyOpenArray((void*)$1, (void*)$2, $1Len_0, $3);$n", - addrLoc(p.config, dest), addrLocOrTemp(src), - genTypeInfo(p.module, dest.t, dest.lode.info)) + [addrLoc(p.config, dest), addrLocOrTemp(src), + genTypeInfo(p.module, dest.t, dest.lode.info)]) of tySet: if mapType(p.config, ty) == ctArray: linefmt(p, cpsStmts, "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, $3);$n", - rdLoc(dest), rdLoc(src), rope(getSize(p.config, dest.t))) + [rdLoc(dest), rdLoc(src), getSize(p.config, dest.t)]) else: - linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) + linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) of tyPointer, tyChar, tyBool, tyEnum, tyCString, tyInt..tyUInt64, tyRange, tyVar, tyLent: - linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) + linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) else: internalError(p.config, "genDeepCopy: " & $ty.kind) proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc) = @@ -439,27 +439,27 @@ proc putIntoDest(p: BProc, d: var TLoc, n: PNode, r: Rope; s=OnUnknown) = d.lode = n d.r = r -proc binaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) = +proc binaryStmt(p: BProc, e: PNode, d: var TLoc, op: string) = var a, b: TLoc if d.k != locNone: internalError(p.config, e.info, "binaryStmt") initLocExpr(p, e.sons[1], a) initLocExpr(p, e.sons[2], b) - lineCg(p, cpsStmts, frmt, rdLoc(a), rdLoc(b)) + lineCg(p, cpsStmts, "$1 $2 $3;$n", [rdLoc(a), op, rdLoc(b)]) -proc binaryStmtAddr(p: BProc, e: PNode, d: var TLoc, frmt: string) = +proc binaryStmtAddr(p: BProc, e: PNode, d: var TLoc, cpname: string) = var a, b: TLoc if d.k != locNone: internalError(p.config, e.info, "binaryStmtAddr") initLocExpr(p, e.sons[1], a) initLocExpr(p, e.sons[2], b) - lineCg(p, cpsStmts, frmt, byRefLoc(p, a), rdLoc(b)) + lineCg(p, cpsStmts, "#$1($2, $3);$n", [cpname, byRefLoc(p, a), rdLoc(b)]) -proc unaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) = +template unaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) = var a: TLoc if d.k != locNone: internalError(p.config, e.info, "unaryStmt") initLocExpr(p, e.sons[1], a) lineCg(p, cpsStmts, frmt, [rdLoc(a)]) -proc binaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) = +template binaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) = var a, b: TLoc assert(e.sons[1].typ != nil) assert(e.sons[2].typ != nil) @@ -467,7 +467,7 @@ proc binaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) = initLocExpr(p, e.sons[2], b) putIntoDest(p, d, e, ropecg(p.module, frmt, [rdLoc(a), rdLoc(b)])) -proc binaryExprChar(p: BProc, e: PNode, d: var TLoc, frmt: string) = +template binaryExprChar(p: BProc, e: PNode, d: var TLoc, frmt: string) = var a, b: TLoc assert(e.sons[1].typ != nil) assert(e.sons[2].typ != nil) @@ -475,40 +475,41 @@ proc binaryExprChar(p: BProc, e: PNode, d: var TLoc, frmt: string) = initLocExpr(p, e.sons[2], b) putIntoDest(p, d, e, ropecg(p.module, frmt, [a.rdCharLoc, b.rdCharLoc])) -proc unaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) = +template unaryExpr(p: BProc, e: PNode, d: var TLoc, frmt: string) = var a: TLoc initLocExpr(p, e.sons[1], a) putIntoDest(p, d, e, ropecg(p.module, frmt, [rdLoc(a)])) -proc unaryExprChar(p: BProc, e: PNode, d: var TLoc, frmt: string) = +template unaryExprChar(p: BProc, e: PNode, d: var TLoc, frmt: string) = var a: TLoc initLocExpr(p, e.sons[1], a) putIntoDest(p, d, e, ropecg(p.module, frmt, [rdCharLoc(a)])) -proc binaryArithOverflowRaw(p: BProc, t: PType, a, b: TLoc; - frmt: string): Rope = +template binaryArithOverflowRaw(p: BProc, t: PType, a, b: TLoc; + cpname: string): Rope = var size = getSize(p.config, t) let storage = if size < p.config.target.intSize: rope("NI") else: getTypeDesc(p.module, t) - result = getTempName(p.module) - linefmt(p, cpsLocals, "$1 $2;$n", storage, result) - lineCg(p, cpsStmts, frmt, result, rdCharLoc(a), rdCharLoc(b)) + var result = getTempName(p.module) + linefmt(p, cpsLocals, "$1 $2;$n", [storage, result]) + lineCg(p, cpsStmts, "$1 = #$2($3, $4);$n", [result, cpname, rdCharLoc(a), rdCharLoc(b)]) if size < p.config.target.intSize or t.kind in {tyRange, tyEnum}: linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseOverflow();$n", - result, intLiteral(firstOrd(p.config, t)), intLiteral(lastOrd(p.config, t))) + [result, intLiteral(firstOrd(p.config, t)), intLiteral(lastOrd(p.config, t))]) + result proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) = const prc: array[mAddI..mPred, string] = [ - "$# = #addInt($#, $#);$n", "$# = #subInt($#, $#);$n", - "$# = #mulInt($#, $#);$n", "$# = #divInt($#, $#);$n", - "$# = #modInt($#, $#);$n", - "$# = #addInt($#, $#);$n", "$# = #subInt($#, $#);$n"] + "addInt", "subInt", + "mulInt", "divInt", "modInt", + "addInt", "subInt" + ] prc64: array[mAddI..mPred, string] = [ - "$# = #addInt64($#, $#);$n", "$# = #subInt64($#, $#);$n", - "$# = #mulInt64($#, $#);$n", "$# = #divInt64($#, $#);$n", - "$# = #modInt64($#, $#);$n", - "$# = #addInt64($#, $#);$n", "$# = #subInt64($#, $#);$n"] + "addInt64", "subInt64", + "mulInt64", "divInt64", "modInt64", + "addInt64", "subInt64" + ] opr: array[mAddI..mPred, string] = [ "($#)($# + $#)", "($#)($# - $#)", "($#)($# * $#)", "($#)($# / $#)", "($#)($# % $#)", @@ -526,7 +527,7 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) = putIntoDest(p, d, e, res) else: let res = binaryArithOverflowRaw(p, t, a, b, - if t.kind == tyInt64: prc64[m] else: prc[m]) + if t.kind == tyInt64: prc64[m] else: prc[m]) putIntoDest(p, d, e, "($#)($#)" % [getTypeDesc(p.module, e.typ), res]) proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) = @@ -543,7 +544,7 @@ proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) = t = skipTypes(e.typ, abstractRange) if optOverflowCheck in p.options: linefmt(p, cpsStmts, "if ($1 == $2) #raiseOverflow();$n", - rdLoc(a), intLiteral(firstOrd(p.config, t))) + [rdLoc(a), intLiteral(firstOrd(p.config, t))]) putIntoDest(p, d, e, opr[m] % [rdLoc(a), rope(getSize(p.config, t) * 8)]) proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) = @@ -814,11 +815,11 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) = if op.magic == mNot: linefmt(p, cpsStmts, "if ($1) #raiseFieldError($2);$n", - rdLoc(test), genStringLiteralFromData(p.module, strLit, e.info)) + [rdLoc(test), genStringLiteralFromData(p.module, strLit, e.info)]) else: linefmt(p, cpsStmts, "if (!($1)) #raiseFieldError($2);$n", - rdLoc(test), genStringLiteralFromData(p.module, strLit, e.info)) + [rdLoc(test), genStringLiteralFromData(p.module, strLit, e.info)]) proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) = if optFieldCheck in p.options: @@ -832,7 +833,7 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) = if field.loc.r == nil: internalError(p.config, e.info, "genCheckedRecordField") # generate the checks: genFieldCheck(p, e, r, field) - add(r, ropecg(p.module, ".$1", field.loc.r)) + add(r, ropecg(p.module, ".$1", [field.loc.r])) putIntoDest(p, d, e.sons[0], r, a.storage) else: genRecordField(p, e.sons[0], d) @@ -842,7 +843,7 @@ proc genUncheckedArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) = initLocExpr(p, x, a) initLocExpr(p, y, b) d.inheritLocation(a) - putIntoDest(p, d, n, ropecg(p.module, "$1[$2]", rdLoc(a), rdCharLoc(b)), + 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) = @@ -858,17 +859,17 @@ proc genArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) = if firstOrd(p.config, ty) == 0: if (firstOrd(p.config, b.t) < firstOrd(p.config, ty)) or (lastOrd(p.config, b.t) > lastOrd(p.config, ty)): linefmt(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError2($1, $2);$n", - rdCharLoc(b), intLiteral(lastOrd(p.config, ty))) + [rdCharLoc(b), intLiteral(lastOrd(p.config, ty))]) else: linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError3($1, $2, $3);$n", - rdCharLoc(b), first, intLiteral(lastOrd(p.config, ty))) + [rdCharLoc(b), first, intLiteral(lastOrd(p.config, ty))]) else: let idx = getOrdValue(y) if idx < firstOrd(p.config, ty) or idx > lastOrd(p.config, ty): localError(p.config, x.info, formatErrorIndexBound(idx, firstOrd(p.config, ty), lastOrd(p.config, ty))) d.inheritLocation(a) putIntoDest(p, d, n, - ropecg(p.module, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first), a.storage) + ropecg(p.module, "$1[($2)- $3]", [rdLoc(a), rdCharLoc(b), first]), a.storage) proc genCStringElem(p: BProc, n, x, y: PNode, d: var TLoc) = var a, b: TLoc @@ -876,7 +877,7 @@ proc genCStringElem(p: BProc, n, x, y: PNode, d: var TLoc) = initLocExpr(p, y, b) inheritLocation(d, a) putIntoDest(p, d, n, - ropecg(p.module, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.storage) + 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) @@ -885,18 +886,18 @@ proc genBoundsCheck(p: BProc; arr, a, b: TLoc) = linefmt(p, cpsStmts, "if ($2-$1 != -1 && " & "((NU)($1) >= (NU)($3Len_0) || (NU)($2) >= (NU)($3Len_0))) #raiseIndexError();$n", - rdLoc(a), rdLoc(b), rdLoc(arr)) + [rdLoc(a), rdLoc(b), rdLoc(arr)]) of tyArray: let first = intLiteral(firstOrd(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))) + [rdCharLoc(a), rdCharLoc(b), first, intLiteral(lastOrd(p.config, ty))]) of tySequence, tyString: linefmt(p, cpsStmts, "if ($2-$1 != -1 && " & "((NU)($1) >= (NU)$3 || (NU)($2) >= (NU)$3)) #raiseIndexError();$n", - rdLoc(a), rdLoc(b), lenExpr(p, arr)) + [rdLoc(a), rdLoc(b), lenExpr(p, arr)]) else: discard proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) = @@ -905,10 +906,10 @@ proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) = initLocExpr(p, y, b) # emit range check: if optBoundsCheck in p.options: linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len_0)) #raiseIndexError2($1,$2Len_0-1);$n", - rdLoc(b), rdLoc(a)) # BUGFIX: ``>=`` and not ``>``! + [rdLoc(b), rdLoc(a)]) # BUGFIX: ``>=`` and not ``>``! inheritLocation(d, a) putIntoDest(p, d, n, - ropecg(p.module, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.storage) + ropecg(p.module, "$1[$2]", [rdLoc(a), rdCharLoc(b)]), a.storage) proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) = var a, b: TLoc @@ -921,16 +922,16 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) = if ty.kind == tyString and (not defined(nimNoZeroTerminator) or optLaxStrings in p.options): linefmt(p, cpsStmts, "if ((NU)($1) > (NU)$2) #raiseIndexError2($1,$2);$n", - rdLoc(b), lenExpr(p, a)) + [rdLoc(b), lenExpr(p, a)]) else: linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)$2) #raiseIndexError2($1,$2-1);$n", - rdLoc(b), lenExpr(p, a)) + [rdLoc(b), lenExpr(p, a)]) 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.r = ropecg(p.module, "(*$1)", [a.r]) putIntoDest(p, d, n, - ropecg(p.module, "$1$3[$2]", rdLoc(a), rdCharLoc(b), dataField(p)), a.storage) + ropecg(p.module, "$1$3[$2]", [rdLoc(a), rdCharLoc(b), dataField(p)]), a.storage) proc genBracketExpr(p: BProc; n: PNode; d: var TLoc) = var ty = skipTypes(n.sons[0].typ, abstractVarRange + tyUserTypeClasses) @@ -1000,19 +1001,19 @@ proc genEcho(p: BProc, n: PNode) = add(args, ropecg(p.module, ", Genode::Cstring($1->data, $1->len)", [rdLoc(a)])) p.module.includeHeader("<base/log.h>") p.module.includeHeader("<util/string.h>") - linefmt(p, cpsStmts, """Genode::log(""$1);$n""", args) + linefmt(p, cpsStmts, """Genode::log(""$1);$n""", [args]) else: if n.len == 0: - linefmt(p, cpsStmts, "#echoBinSafe(NIM_NIL, $1);$n", n.len.rope) + linefmt(p, cpsStmts, "#echoBinSafe(NIM_NIL, $1);$n", [n.len]) else: var a: TLoc initLocExpr(p, n, a) - linefmt(p, cpsStmts, "#echoBinSafe($1, $2);$n", a.rdLoc, n.len.rope) + linefmt(p, cpsStmts, "#echoBinSafe($1, $2);$n", [a.rdLoc, n.len]) when false: p.module.includeHeader("<stdio.h>") linefmt(p, cpsStmts, "printf($1$2);$n", - makeCString(repeat("%s", n.len) & "\L"), args) - linefmt(p, cpsStmts, "fflush(stdout);$n") + makeCString(repeat("%s", n.len) & "\L"), [args]) + linefmt(p, cpsStmts, "fflush(stdout);$n", []) proc gcUsage(conf: ConfigRef; n: PNode) = if conf.selectedGC == gcNone: message(conf, n.info, warnGcMem, n.renderTree) @@ -1050,15 +1051,15 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) = initLocExpr(p, e.sons[i + 1], a) if skipTypes(e.sons[i + 1].typ, abstractVarRange).kind == tyChar: inc(L) - add(appends, ropecg(p.module, "#appendChar($1, $2);$n", strLoc(p, tmp), rdLoc(a))) + add(appends, ropecg(p.module, "#appendChar($1, $2);$n", [strLoc(p, tmp), rdLoc(a)])) else: if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}: inc(L, len(e.sons[i + 1].strVal)) else: add(lens, lenExpr(p, a)) add(lens, " + ") - add(appends, ropecg(p.module, "#appendString($1, $2);$n", strLoc(p, tmp), rdLoc(a))) - linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);$n", tmp.r, lens, rope(L)) + add(appends, ropecg(p.module, "#appendString($1, $2);$n", [strLoc(p, tmp), rdLoc(a)])) + linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);$n", [tmp.r, lens, L]) add(p.s(cpsStmts), appends) if d.k == locNone: d = tmp @@ -1090,7 +1091,7 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) = if skipTypes(e.sons[i + 2].typ, abstractVarRange).kind == tyChar: inc(L) add(appends, ropecg(p.module, "#appendChar($1, $2);$n", - strLoc(p, dest), rdLoc(a))) + [strLoc(p, dest), rdLoc(a)])) else: if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}: inc(L, len(e.sons[i + 2].strVal)) @@ -1098,13 +1099,13 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) = add(lens, lenExpr(p, a)) add(lens, " + ") add(appends, ropecg(p.module, "#appendString($1, $2);$n", - strLoc(p, dest), rdLoc(a))) + [strLoc(p, dest), rdLoc(a)])) if p.config.selectedGC == gcDestructors: linefmt(p, cpsStmts, "#prepareAdd($1, $2$3);$n", - byRefLoc(p, dest), lens, rope(L)) + [byRefLoc(p, dest), lens, L]) else: initLoc(call, locCall, e, OnHeap) - call.r = ropecg(p.module, "#resizeString($1, $2$3)", [rdLoc(dest), lens, rope(L)]) + call.r = ropecg(p.module, "#resizeString($1, $2$3)", [rdLoc(dest), lens, L]) genAssignment(p, dest, call, {}) gcUsage(p.config, e) add(p.s(cpsStmts), appends) @@ -1113,18 +1114,21 @@ 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; - let seqAppendPattern = if not p.module.compileToCpp: - "($2) #incrSeqV3((TGenericSeq*)($1), $3)" - else: - "($2) #incrSeqV3($1, $3)" var a, b, dest, tmpL, call: TLoc initLocExpr(p, e.sons[1], a) initLocExpr(p, e.sons[2], b) let seqType = skipTypes(e.sons[1].typ, {tyVar}) initLoc(call, locCall, e, OnHeap) - call.r = ropecg(p.module, seqAppendPattern, [rdLoc(a), - getTypeDesc(p.module, e.sons[1].typ), - genTypeInfo(p.module, seqType, e.info)]) + if not p.module.compileToCpp: + const seqAppendPattern = "($2) #incrSeqV3((TGenericSeq*)($1), $3)" + call.r = ropecg(p.module, seqAppendPattern, [rdLoc(a), + getTypeDesc(p.module, e.sons[1].typ), + genTypeInfo(p.module, seqType, e.info)]) + else: + const seqAppendPattern = "($2) #incrSeqV3($1, $3)" + call.r = ropecg(p.module, seqAppendPattern, [rdLoc(a), + getTypeDesc(p.module, e.sons[1].typ), + 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) @@ -1132,8 +1136,8 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) = # 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)) + 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}) gcUsage(p.config, e) @@ -1141,8 +1145,8 @@ proc genReset(p: BProc, n: PNode) = var a: TLoc initLocExpr(p, n.sons[1], a) linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n", - addrLoc(p.config, a), - genTypeInfo(p.module, skipTypes(a.t, {tyVar}), n.info)) + [addrLoc(p.config, a), + genTypeInfo(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) @@ -1177,23 +1181,23 @@ proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) = initLocExpr(p, newSymNode(bt.destructor), f) addf(p.module.s[cfsTypeInit3], "$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)]) - let args = [getTypeDesc(p.module, typ), ti, sizeExpr] if a.storage == OnHeap and usesWriteBarrier(p.config): if canFormAcycle(a.t): - linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", a.rdLoc) + 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) + linefmt(p, cpsStmts, "if ($1) { #nimGCunrefNoCycle($1); $1 = NIM_NIL; }$n", [a.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) + b.r = 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)", args) - linefmt(p, cpsStmts, "$1 = $2;$n", a.rdLoc, b.rdLoc) + b.r = 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)", args) + b.r = 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, false) @@ -1212,28 +1216,29 @@ proc genNew(p: BProc, e: PNode) = proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope; lenIsZero: bool) = let seqtype = skipTypes(dest.t, abstractVarRange) - let args = [getTypeDesc(p.module, seqtype), - genTypeInfo(p.module, seqtype, dest.lode.info), length] var call: TLoc initLoc(call, locExpr, dest.lode, OnHeap) if dest.storage == OnHeap and usesWriteBarrier(p.config): if canFormAcycle(dest.t): - linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", dest.rdLoc) + linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", [dest.rdLoc]) else: - linefmt(p, cpsStmts, "if ($1) { #nimGCunrefNoCycle($1); $1 = NIM_NIL; }$n", dest.rdLoc) + linefmt(p, cpsStmts, "if ($1) { #nimGCunrefNoCycle($1); $1 = NIM_NIL; }$n", [dest.rdLoc]) if not lenIsZero: 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) + call.r = ropecg(p.module, "($1) #newSeq($2, $3)", [getTypeDesc(p.module, seqtype), + genTypeInfo(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)", args) - linefmt(p, cpsStmts, "$1 = $2;$n", dest.rdLoc, call.rdLoc) + call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", [getTypeDesc(p.module, seqtype), + genTypeInfo(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" else: - call.r = ropecg(p.module, "($1) #newSeq($2, $3)", args) + call.r = ropecg(p.module, "($1) #newSeq($2, $3)", [getTypeDesc(p.module, seqtype), + genTypeInfo(p.module, seqtype, dest.lode.info), length]) genAssignment(p, dest, call, {}) proc genNewSeq(p: BProc, e: PNode) = @@ -1243,8 +1248,8 @@ proc genNewSeq(p: BProc, e: PNode) = if p.config.selectedGC == gcDestructors: let seqtype = skipTypes(e.sons[1].typ, abstractVarRange) linefmt(p, cpsStmts, "$1.len = $2; $1.p = ($4*) #newSeqPayload($2, sizeof($3));$n", - a.rdLoc, b.rdLoc, getTypeDesc(p.module, seqtype.lastSon), - getSeqPayloadType(p.module, seqtype)) + [a.rdLoc, b.rdLoc, getTypeDesc(p.module, seqtype.lastSon), + getSeqPayloadType(p.module, seqtype)]) else: let lenIsZero = optNilSeqs notin p.options and e[2].kind == nkIntLit and e[2].intVal == 0 @@ -1352,15 +1357,15 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) = 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)) + [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)) + arr.r = ropecg(p.module, "$1$3[$2]", [rdLoc(dest[]), intLiteral(i), dataField(p)]) arr.storage = OnHeap # we know that sequences are on the heap expr(p, n[i], arr) gcUsage(p.config, n) @@ -1383,8 +1388,8 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) = 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)) + [rdLoc d, 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) @@ -1392,20 +1397,20 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) = if L < 10: for i in countup(0, L - 1): initLoc(elem, locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), OnHeap) - elem.r = ropecg(p.module, "$1$3[$2]", rdLoc(d), intLiteral(i), dataField(p)) + elem.r = ropecg(p.module, "$1$3[$2]", [rdLoc(d), intLiteral(i), dataField(p)]) 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)) + arr.r = ropecg(p.module, "$1[$2]", [rdLoc(a), intLiteral(i)]) 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.rope) + linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n", [i.r, L]) initLoc(elem, locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), OnHeap) - elem.r = ropecg(p.module, "$1$3[$2]", rdLoc(d), rdLoc(i), dataField(p)) + elem.r = ropecg(p.module, "$1$3[$2]", [rdLoc(d), rdLoc(i), dataField(p)]) 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)) + arr.r = ropecg(p.module, "$1[$2]", [rdLoc(a), rdLoc(i)]) genAssignment(p, elem, arr, {needToCopy}) lineF(p, cpsStmts, "}$n", []) @@ -1432,7 +1437,7 @@ proc genNewFinalize(p: BProc, e: PNode) = proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo): Rope = if optNimV2 in p.config.globalOptions: result = ropecg(p.module, "#isObj($1.m_type, $2)", - a, genTypeInfo2Name(p.module, dest)) + [a, genTypeInfo2Name(p.module, dest)]) else: # unfortunately 'genTypeInfo' sets tfObjHasKids as a side effect, so we # have to call it here first: @@ -1445,11 +1450,11 @@ proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo): Rope = inc p.module.labels let cache = "Nim_OfCheck_CACHE" & p.module.labels.rope addf(p.module.s[cfsVars], "static TNimType* $#[2];$n", [cache]) - result = ropecg(p.module, "#isObjWithCache($#.m_type, $#, $#)", a, ti, cache) + result = ropecg(p.module, "#isObjWithCache($#.m_type, $#, $#)", [a, ti, cache]) when false: # former version: result = ropecg(p.module, "#isObj($1.m_type, $2)", - a, genTypeInfo(p.module, dest, info)) + [a, genTypeInfo(p.module, dest, info)]) proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) = var a: TLoc @@ -1461,7 +1466,7 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) = while t.kind in {tyVar, tyLent, tyPtr, tyRef}: 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) + r = ropecg(p.module, "(*$1)", [r]) t = skipTypes(t.lastSon, typedescInst) discard getTypeDesc(p.module, t) if not p.module.compileToCpp: @@ -1472,9 +1477,9 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) = globalError(p.config, x.info, "no 'of' operator available for pure objects") if nilCheck != nil: - r = ropecg(p.module, "(($1) && ($2))", nilCheck, genOfHelper(p, dest, r, x.info)) + r = ropecg(p.module, "(($1) && ($2))", [nilCheck, genOfHelper(p, dest, r, x.info)]) else: - r = ropecg(p.module, "($1)", genOfHelper(p, dest, r, x.info)) + r = ropecg(p.module, "($1)", [genOfHelper(p, dest, r, x.info)]) putIntoDest(p, d, x, r, a.storage) proc genOf(p: BProc, n: PNode, d: var TLoc) = @@ -1536,7 +1541,7 @@ proc genGetTypeInfo(p: BProc, e: PNode, d: var TLoc) = let t = e.sons[1].typ putIntoDest(p, d, e, genTypeInfo(p.module, t, e.info)) -proc genDollar(p: BProc, n: PNode, d: var TLoc, frmt: string) = +template genDollar(p: BProc, n: PNode, d: var TLoc, frmt: string) = var a: TLoc initLocExpr(p, n.sons[1], a) a.r = ropecg(p.module, frmt, [rdLoc(a)]) @@ -1580,7 +1585,7 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) = getIntTemp(p, tmp) var x = lenExpr(p, a) if op == mHigh: x = "($1-1)" % [x] - lineCg(p, cpsStmts, "$1 = $2;$n", tmp.r, x) + lineCg(p, cpsStmts, "$1 = $2;$n", [tmp.r, x]) putIntoDest(p, d, e, tmp.r) of tyArray: # YYY: length(sideeffect) is optimized away incorrectly? @@ -1608,21 +1613,26 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) = initLocExpr(p, x, a) initLocExpr(p, e.sons[2], b) let t = skipTypes(e.sons[1].typ, {tyVar}) - let setLenPattern = if not p.module.compileToCpp: - "($3) #setLengthSeqV2(&($1)->Sup, $4, $2)" - else: - "($3) #setLengthSeqV2($1, $4, $2)" initLoc(call, locCall, e, OnHeap) - call.r = ropecg(p.module, setLenPattern, [ + if not p.module.compileToCpp: + const setLenPattern = "($3) #setLengthSeqV2(&($1)->Sup, $4, $2)" + call.r = ropecg(p.module, setLenPattern, [ rdLoc(a), rdLoc(b), getTypeDesc(p.module, t), genTypeInfo(p.module, t.skipTypes(abstractInst), e.info)]) + + else: + const setLenPattern = "($3) #setLengthSeqV2($1, $4, $2)" + call.r = ropecg(p.module, setLenPattern, [ + rdLoc(a), rdLoc(b), getTypeDesc(p.module, t), + genTypeInfo(p.module, t.skipTypes(abstractInst), e.info)]) + genAssignment(p, a, call, {}) gcUsage(p.config, e) proc genSetLengthStr(p: BProc, e: PNode, d: var TLoc) = if p.config.selectedGc == gcDestructors: - binaryStmtAddr(p, e, d, "#setLengthStrV2($1, $2);$n") + binaryStmtAddr(p, e, d, "setLengthStrV2") else: var a, b, call: TLoc if d.k != locNone: internalError(p.config, e.info, "genSetLengthStr") @@ -1770,16 +1780,28 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) = case op of mIncl: binaryStmtInExcl(p, e, d, "$1[(NU)($2)>>3] |=(1U<<($2&7U));$n") of mExcl: binaryStmtInExcl(p, e, d, "$1[(NU)($2)>>3] &= ~(1U<<($2&7U));$n") - of mCard: unaryExprChar(p, e, d, "#cardSet($1, " & $size & ')') + of mCard: + var a: TLoc + initLocExpr(p, e.sons[1], a) + 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 initLocExpr(p, e.sons[1], a) initLocExpr(p, e.sons[2], b) if d.k == locNone: getTemp(p, getSysType(p.module.g.graph, unknownLineInfo(), tyBool), d) - linefmt(p, cpsStmts, lookupOpr[op], - [rdLoc(i), rope(size), rdLoc(d), rdLoc(a), rdLoc(b)]) + if op == mLtSet: + linefmt(p, cpsStmts, lookupOpr[mLtSet], + [rdLoc(i), size, rdLoc(d), rdLoc(a), rdLoc(b)]) + else: + linefmt(p, cpsStmts, lookupOpr[mLeSet], + [rdLoc(i), size, rdLoc(d), rdLoc(a), rdLoc(b)]) of mEqSet: - binaryExprChar(p, e, d, "(#nimCmpMem($1, $2, " & $(size) & ")==0)") + var a, b: TLoc + assert(e.sons[1].typ != nil) + assert(e.sons[2].typ != nil) + initLocExpr(p, e.sons[1], a) + initLocExpr(p, e.sons[2], b) + putIntoDest(p, d, e, ropecg(p.module, "(#nimCmpMem($1, $2, $3)==0)", [a.rdCharLoc, b.rdCharLoc, size])) of mMulSet, mPlusSet, mMinusSet, mSymDiffSet: # we inline the simple for loop for better code generation: getTemp(p, getSysType(p.module.g.graph, unknownLineInfo(), tyInt), i) # our counter @@ -1833,7 +1855,7 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) = var tmp: TLoc tmp.r = "LOC$1.source" % [lbl] linefmt(p, cpsLocals, "union { $1 source; $2 dest; } LOC$3;$n", - getTypeDesc(p.module, e.sons[1].typ), getTypeDesc(p.module, e.typ), lbl) + [getTypeDesc(p.module, e.sons[1].typ), getTypeDesc(p.module, e.typ), lbl]) tmp.k = locExpr tmp.lode = lodeTyp srct tmp.storage = OnStack @@ -1859,7 +1881,7 @@ proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) = putIntoDest(p, d, lodeTyp dest, ropecg(p.module, "(($1)#$5($2, $3, $4))", [ getTypeDesc(p.module, dest), rdCharLoc(a), genLiteral(p, n.sons[1], dest), genLiteral(p, n.sons[2], dest), - rope(magic)]), a.storage) + magic]), a.storage) proc genConv(p: BProc, e: PNode, d: var TLoc) = let destType = e.typ.skipTypes({tyVar, tyLent, tyGenericInst, tyAlias, tySink}) @@ -1891,11 +1913,11 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) = if a.kind in {nkStrLit..nkTripleStrLit} and a.strVal == "": initLocExpr(p, e.sons[2], x) putIntoDest(p, d, e, - ropecg(p.module, "($1 == 0)", lenExpr(p, x))) + ropecg(p.module, "($1 == 0)", [lenExpr(p, x)])) elif b.kind in {nkStrLit..nkTripleStrLit} and b.strVal == "": initLocExpr(p, e.sons[1], x) putIntoDest(p, d, e, - ropecg(p.module, "($1 == 0)", lenExpr(p, x))) + ropecg(p.module, "($1 == 0)", [lenExpr(p, x)])) else: binaryExpr(p, e, d, "#eqStrings($1, $2)") @@ -1908,12 +1930,12 @@ proc binaryFloatArith(p: BProc, e: PNode, d: var TLoc, m: TMagic) = initLocExpr(p, e.sons[1], a) initLocExpr(p, e.sons[2], b) putIntoDest(p, d, e, ropecg(p.module, "(($4)($2) $1 ($4)($3))", - rope(opr[m]), rdLoc(a), rdLoc(b), - getSimpleTypeDesc(p.module, e[1].typ))) + [opr[m], rdLoc(a), rdLoc(b), + getSimpleTypeDesc(p.module, e[1].typ)])) if optNaNCheck in p.options: - linefmt(p, cpsStmts, "#nanCheck($1);$n", rdLoc(d)) + linefmt(p, cpsStmts, "#nanCheck($1);$n", [rdLoc(d)]) if optInfCheck in p.options: - linefmt(p, cpsStmts, "#infCheck($1);$n", rdLoc(d)) + linefmt(p, cpsStmts, "#infCheck($1);$n", [rdLoc(d)]) else: binaryArith(p, e, d, m) @@ -1925,7 +1947,7 @@ proc genWasMoved(p: BProc; n: PNode) = initLocExpr(p, n[1].skipAddr, a) resetLoc(p, a) #linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));$n", - # addrLoc(p.config, a), getTypeDesc(p.module, a.t)) + # [addrLoc(p.config, a), getTypeDesc(p.module, a.t)]) proc genMove(p: BProc; n: PNode; d: var TLoc) = var a: TLoc @@ -1976,11 +1998,11 @@ proc genDispose(p: BProc; n: PNode) = if elemType.destructor != nil: var destroyCall = newNodeI(nkCall, n.info) genStmts(p, destroyCall) - lineCg(p, cpsStmts, "#nimRawDispose($#)", rdLoc(a)) + lineCg(p, cpsStmts, ["#nimRawDispose($#)", rdLoc(a)]) else: # ``nimRawDisposeVirtual`` calls the ``finalizer`` which is the same as the # destructor, but it uses the runtime type. Afterwards the memory is freed: - lineCg(p, cpsStmts, "#nimDestroyAndDispose($#)", rdLoc(a)) + lineCg(p, cpsStmts, ["#nimDestroyAndDispose($#)", rdLoc(a)]) proc genEnumToStr(p: BProc, e: PNode, d: var TLoc) = const ToStringProcSlot = -4 @@ -2013,11 +2035,11 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = if optOverflowCheck notin p.options: unaryExpr(p, e, d, "($1 - 1)") else: unaryExpr(p, e, d, "#subInt($1, 1)") of mInc, mDec: - const opr: array[mInc..mDec, string] = ["$1 += $2;$n", "$1 -= $2;$n"] - const fun64: array[mInc..mDec, string] = ["$# = #addInt64($#, $#);$n", - "$# = #subInt64($#, $#);$n"] - const fun: array[mInc..mDec, string] = ["$# = #addInt($#, $#);$n", - "$# = #subInt($#, $#);$n"] + const opr: array[mInc..mDec, string] = ["+=", "-="] + const fun64: array[mInc..mDec, string] = ["addInt64", + "subInt64"] + const fun: array[mInc..mDec, string] = ["addInt", + "subInt"] let underlying = skipTypes(e.sons[1].typ, {tyGenericInst, tyAlias, tySink, tyVar, tyLent, tyRange}) if optOverflowCheck notin p.options or underlying.kind in {tyUInt..tyUInt64}: binaryStmt(p, e, d, opr[op]) @@ -2031,13 +2053,14 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = let ranged = skipTypes(e.sons[1].typ, {tyGenericInst, tyAlias, tySink, tyVar, tyLent}) let res = binaryArithOverflowRaw(p, ranged, a, b, if underlying.kind == tyInt64: fun64[op] else: fun[op]) + putIntoDest(p, a, e.sons[1], "($#)($#)" % [ getTypeDesc(p.module, ranged), res]) of mConStrStr: genStrConcat(p, e, d) of mAppendStrCh: if p.config.selectedGC == gcDestructors: - binaryStmtAddr(p, e, d, "#nimAddCharV1($1, $2);$n") + binaryStmtAddr(p, e, d, "nimAddCharV1") else: var dest, b, call: TLoc initLoc(call, locCall, e, OnHeap) @@ -2095,12 +2118,10 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = var a, tmp: TLoc initLocExpr(p, e[1], a) getIntTemp(p, tmp) - var frmt: FormatStr if not p.module.compileToCpp: - frmt = "$1 = $2->Sup.len;$n" + lineCg(p, cpsStmts, "$1 = $2->Sup.len;$n", [tmp.r, rdLoc(a)]) else: - frmt = "$1 = $2->len;$n" - lineCg(p, cpsStmts, frmt, tmp.r, rdLoc(a)) + lineCg(p, cpsStmts, "$1 = $2->len;$n", [tmp.r, rdLoc(a)]) putIntoDest(p, d, e, tmp.r) of mGCref: unaryStmt(p, e, d, "if ($1) { #nimGCref($1); }$n") of mGCunref: unaryStmt(p, e, d, "if ($1) { #nimGCunref($1); }$n") @@ -2252,11 +2273,11 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) = when false: if d.k != locNone: linefmt(p, cpsStmts, "$1.ClP_0 = $2; $1.ClE_0 = $3;$n", - d.rdLoc, a.rdLoc, b.rdLoc) + [d.rdLoc, a.rdLoc, b.rdLoc]) else: getTemp(p, n.typ, tmp) linefmt(p, cpsStmts, "$1.ClP_0 = $2; $1.ClE_0 = $3;$n", - tmp.rdLoc, a.rdLoc, b.rdLoc) + [tmp.rdLoc, a.rdLoc, b.rdLoc]) putLocIntoDest(p, d, tmp) proc genArrayConstr(p: BProc, n: PNode, d: var TLoc) = @@ -2327,10 +2348,10 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) = genTypeInfo(p.module, dest, n.info) if nilCheck != nil: linefmt(p, cpsStmts, "if ($1) #chckObj($2.m_type, $3);$n", - nilCheck, r, checkFor) + [nilCheck, r, checkFor]) else: linefmt(p, cpsStmts, "#chckObj($1.m_type, $2);$n", - r, checkFor) + [r, checkFor]) if n.sons[0].typ.kind != tyObject: putIntoDest(p, d, n, "(($1) ($2))" % [getTypeDesc(p.module, n.typ), rdLoc(a)], a.storage) @@ -2367,7 +2388,7 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) = # this by ensuring the destination is also a pointer: if d.k == locNone and skipTypes(n.typ, abstractInst).kind in {tyRef, tyPtr, tyVar, tyLent}: getTemp(p, n.typ, d) - linefmt(p, cpsStmts, "$1 = &$2;$n", rdLoc(d), r) + linefmt(p, cpsStmts, "$1 = &$2;$n", [rdLoc(d), r]) else: r = "&" & r putIntoDest(p, d, n, r, a.storage) @@ -2709,7 +2730,7 @@ proc genConstSeq(p: BProc, n: PNode, t: PType): Rope = " #TGenericSeq Sup;$n" & " $1 data[$2];$n" & "} $3 = $4;$n", [ - getTypeDesc(p.module, base), n.len.rope, result, data]) + getTypeDesc(p.module, base), n.len, result, data]) result = "(($1)&$2)" % [getTypeDesc(p.module, t), result] @@ -2727,7 +2748,7 @@ proc genConstSeqV2(p: BProc, n: PNode, t: PType): Rope = "static const struct {$n" & " NI cap; void* allocator; $1 data[$2];$n" & "} $3 = {$2, NIM_NIL, $4};$n", [ - getTypeDesc(p.module, base), rope(len(n)), payload, data]) + getTypeDesc(p.module, base), len(n), payload, data]) result = "{$1, ($2*)&$3}" % [rope(len(n)), getSeqPayloadType(p.module, t), payload] proc genConstExpr(p: BProc, n: PNode): Rope = diff --git a/compiler/ccgliterals.nim b/compiler/ccgliterals.nim index efbae3cb8..f5372f050 100644 --- a/compiler/ccgliterals.nim +++ b/compiler/ccgliterals.nim @@ -47,7 +47,7 @@ proc genStringLiteralV1(m: BModule; n: PNode): Rope = [genStringLiteralDataOnlyV1(m, n.strVal)]) else: result = ropecg(m, "((#NimStringDesc*) &$1$2)", - [m.tmpBase, rope(id)]) + [m.tmpBase, id]) # ------ Version 2: destructor based strings and seqs ----------------------- diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 9dd70a703..386bedae9 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -44,8 +44,19 @@ proc inExceptBlockLen(p: BProc): int = for x in p.nestedTryStmts: if x.inExcept: result.inc -proc startBlock(p: BProc, start: FormatStr = "{$n", - args: varargs[Rope]): int {.discardable.} +proc startBlockInternal(p: BProc): int {.discardable.} = + inc(p.labels) + result = len(p.blocks) + setLen(p.blocks, result + 1) + p.blocks[result].id = p.labels + p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16 + p.blocks[result].nestedExceptStmts = p.inExceptBlockLen.int16 + +template startBlock(p: BProc, start: FormatStr = "{$n", + args: varargs[Rope]): int = + lineCg(p, cpsStmts, start, args) + startBlockInternal(p) + proc endBlock(p: BProc) proc genVarTuple(p: BProc, n: PNode) = @@ -70,7 +81,7 @@ proc genVarTuple(p: BProc, n: PNode) = if forHcr: # check with the boolean if the initializing code for the tuple should be ran - lineCg(p, cpsStmts, "if ($1)$n", hcrCond) + lineCg(p, cpsStmts, "if ($1)$n", [hcrCond]) startBlock(p) defer: if forHcr: @@ -80,10 +91,10 @@ proc genVarTuple(p: BProc, n: PNode) = # insert the registration of the globals for the different parts of the tuple at the # start of the current scope (after they have been iterated) and init a boolean to # check if any of them is newly introduced and the initializing code has to be ran - lineCg(p, cpsLocals, "NIM_BOOL $1 = NIM_FALSE;$n", hcrCond) + lineCg(p, cpsLocals, "NIM_BOOL $1 = NIM_FALSE;$n", [hcrCond]) for curr in hcrGlobals: lineCg(p, cpsLocals, "$1 |= hcrRegisterGlobal($4, \"$2\", sizeof($3), $5, (void**)&$2);$N", - hcrCond, curr.loc.r, rdLoc(curr.loc), getModuleDllPath(p.module, n.sons[0].sym), curr.tp) + [hcrCond, curr.loc.r, rdLoc(curr.loc), getModuleDllPath(p.module, n.sons[0].sym), curr.tp]) genLineDir(p, n) initLocExpr(p, n.sons[L-1], tup) @@ -130,16 +141,6 @@ proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} = else: expr(p, ri, a) -proc startBlock(p: BProc, start: FormatStr = "{$n", - args: varargs[Rope]): int {.discardable.} = - lineCg(p, cpsStmts, start, args) - inc(p.labels) - result = len(p.blocks) - setLen(p.blocks, result + 1) - p.blocks[result].id = p.labels - p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16 - p.blocks[result].nestedExceptStmts = p.inExceptBlockLen.int16 - proc assignLabel(b: var TBlock): Rope {.inline.} = b.label = "LA" & b.id.rope result = b.label @@ -192,9 +193,9 @@ proc genState(p: BProc, n: PNode) = let n0 = n[0] if n0.kind == nkIntLit: let idx = n.sons[0].intVal - linefmt(p, cpsStmts, "STATE$1: ;$n", idx.rope) + linefmt(p, cpsStmts, "STATE$1: ;$n", [idx]) elif n0.kind == nkStrLit: - linefmt(p, cpsStmts, "$1: ;$n", n0.strVal.rope) + linefmt(p, cpsStmts, "$1: ;$n", [n0.strVal]) proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) = # Called by return and break stmts. @@ -207,7 +208,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) = if not p.module.compileToCpp or optNoCppExceptions in p.config.globalOptions: # Pop safe points generated by try if not tryStmt.inExcept and not isDefined(p.config, "nimQuirky"): - linefmt(p, cpsStmts, "#popSafePoint();$n") + linefmt(p, cpsStmts, "#popSafePoint();$n", []) # Pop this try-stmt of the list of nested trys # so we don't infinite recurse on it in the next step. @@ -227,7 +228,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) = # Pop exceptions that was handled by the # except-blocks we are in for i in countdown(howManyExcepts-1, 0): - linefmt(p, cpsStmts, "#popCurrentException();$n") + linefmt(p, cpsStmts, "#popCurrentException();$n", []) proc genGotoState(p: BProc, n: PNode) = # we resist the temptation to translate it into duff's device as it later @@ -352,7 +353,7 @@ proc genSingleVar(p: BProc, a: PNode) = # put it in the locals section - mainly because of loops which # use the var in a call to resetLoc() in the statements section lineCg(targetProc, cpsLocals, "hcrRegisterGlobal($3, \"$1\", sizeof($2), $4, (void**)&$1);$n", - v.loc.r, rdLoc(v.loc), getModuleDllPath(p.module, v), traverseProc) + [v.loc.r, rdLoc(v.loc), getModuleDllPath(p.module, v), traverseProc]) # nothing special left to do later on - let's avoid closing and reopening blocks forHcr = false @@ -361,7 +362,7 @@ proc genSingleVar(p: BProc, a: PNode) = # be able to re-run it but without the top level code - just the init of globals if forHcr: lineCg(targetProc, cpsStmts, "if (hcrRegisterGlobal($3, \"$1\", sizeof($2), $4, (void**)&$1))$N", - v.loc.r, rdLoc(v.loc), getModuleDllPath(p.module, v), traverseProc) + [v.loc.r, rdLoc(v.loc), getModuleDllPath(p.module, v), traverseProc]) startBlock(targetProc) defer: if forHcr: @@ -452,7 +453,7 @@ proc genReturnStmt(p: BProc, t: PNode) = # If we're in a finally block, and we came here by exception # consume it before we return. var safePoint = p.finallySafePoints[p.finallySafePoints.len-1] - linefmt(p, cpsStmts, "if ($1.status != 0) #popCurrentException();$n", safePoint) + linefmt(p, cpsStmts, "if ($1.status != 0) #popCurrentException();$n", [safePoint]) lineF(p, cpsStmts, "goto BeforeRet_;$n", []) proc genGotoForCase(p: BProc; caseStmt: PNode) = @@ -589,7 +590,7 @@ proc genWhileStmt(p: BProc, t: PNode) = if optProfiler in p.options: # invoke at loop body exit: - linefmt(p, cpsStmts, "#nimProfile();$n") + linefmt(p, cpsStmts, "#nimProfile();$n", []) endBlock(p) dec(p.withinLoop) @@ -690,7 +691,7 @@ proc genRaiseStmt(p: BProc, t: PNode) = lineCg(p, cpsStmts, "#raiseExceptionEx((#Exception*)$1, $2, $3, $4, $5);$n", [e, makeCString(typ.sym.name.s), makeCString(if p.prc != nil: p.prc.name.s else: p.module.module.name.s), - makeCString(toFileName(p.config, t.info)), rope(toLinenumber(t.info))]) + makeCString(toFileName(p.config, t.info)), toLinenumber(t.info)]) if optNimV2 in p.config.globalOptions: lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [e]) else: @@ -699,9 +700,9 @@ proc genRaiseStmt(p: BProc, t: PNode) = if p.module.compileToCpp and optNoCppExceptions notin p.config.globalOptions: line(p, cpsStmts, ~"throw;$n") else: - linefmt(p, cpsStmts, "#reraiseException();$n") + linefmt(p, cpsStmts, "#reraiseException();$n", []) -proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc, +template genCaseGenericBranch(p: BProc, b: PNode, e: TLoc, rangeFormat, eqFormat: FormatStr, labl: TLabel) = var x, y: TLoc @@ -731,10 +732,11 @@ proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc, exprBlock(p, t.sons[i].sons[0], d) result = lend -proc genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc, +template genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc, rangeFormat, eqFormat: FormatStr, until: int, a: TLoc): TLabel = # generate a C-if statement for a Nim case statement + var res: TLabel var labId = p.labels for i in 1..until: inc(p.labels) @@ -747,12 +749,13 @@ proc genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc, inc(p.labels) var gotoTarget = p.labels lineF(p, cpsStmts, "goto LA$1_;$n", [rope(gotoTarget)]) - result = genCaseSecondPass(p, t, d, labId, until) + res = genCaseSecondPass(p, t, d, labId, until) lineF(p, cpsStmts, "LA$1_: ;$n", [rope(gotoTarget)]) else: - result = genCaseSecondPass(p, t, d, labId, until) + res = genCaseSecondPass(p, t, d, labId, until) + res -proc genCaseGeneric(p: BProc, t: PNode, d: var TLoc, +template genCaseGeneric(p: BProc, t: PNode, d: var TLoc, rangeFormat, eqFormat: FormatStr) = var a: TLoc initLocExpr(p, t.sons[0], a) @@ -793,7 +796,7 @@ proc genStringCase(p: BProc, t: PNode, d: var TLoc) = # but we reserved a label, which we use later discard linefmt(p, cpsStmts, "switch (#hashString($1) & $2) {$n", - rdLoc(a), rope(bitMask)) + [rdLoc(a), bitMask]) for j in countup(0, high(branches)): if branches[j] != nil: lineF(p, cpsStmts, "case $1: $n$2break;$n", @@ -895,7 +898,7 @@ proc genRestoreFrameAfterException(p: BProc) = p.hasCurFramePointer = true p.procSec(cpsLocals).add(ropecg(p.module, "\tTFrame* _nimCurFrame;$n", [])) p.procSec(cpsInit).add(ropecg(p.module, "\t_nimCurFrame = #getFrame();$n", [])) - linefmt(p, cpsStmts, "#setFrame(_nimCurFrame);$n") + linefmt(p, cpsStmts, "#setFrame(_nimCurFrame);$n", []) proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = # code to generate: @@ -1006,25 +1009,25 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) = var safePoint: Rope if not quirkyExceptions: safePoint = getTempName(p.module) - linefmt(p, cpsLocals, "#TSafePoint $1;$n", safePoint) - linefmt(p, cpsStmts, "#pushSafePoint(&$1);$n", safePoint) + linefmt(p, cpsLocals, "#TSafePoint $1;$n", [safePoint]) + linefmt(p, cpsStmts, "#pushSafePoint(&$1);$n", [safePoint]) if isDefined(p.config, "nimStdSetjmp"): - linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint) + linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint]) elif isDefined(p.config, "nimSigSetjmp"): - linefmt(p, cpsStmts, "$1.status = sigsetjmp($1.context, 0);$n", safePoint) + linefmt(p, cpsStmts, "$1.status = sigsetjmp($1.context, 0);$n", [safePoint]) elif isDefined(p.config, "nimRawSetjmp"): - linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", safePoint) + linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", [safePoint]) else: - linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint) + linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint]) startBlock(p, "if ($1.status == 0) {$n", [safePoint]) var length = sonsLen(t) add(p.nestedTryStmts, (t, false)) expr(p, t.sons[0], d) if not quirkyExceptions: - linefmt(p, cpsStmts, "#popSafePoint();$n") + linefmt(p, cpsStmts, "#popSafePoint();$n", []) endBlock(p) startBlock(p, "else {$n") - linefmt(p, cpsStmts, "#popSafePoint();$n") + linefmt(p, cpsStmts, "#popSafePoint();$n", []) genRestoreFrameAfterException(p) elif 1 < length and t.sons[1].kind == nkExceptBranch: startBlock(p, "if (#getCurrentException()) {$n") @@ -1041,30 +1044,28 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) = if i > 1: lineF(p, cpsStmts, "else", []) startBlock(p) if not quirkyExceptions: - linefmt(p, cpsStmts, "$1.status = 0;$n", safePoint) + linefmt(p, cpsStmts, "$1.status = 0;$n", [safePoint]) expr(p, t.sons[i].sons[0], d) - linefmt(p, cpsStmts, "#popCurrentException();$n") + linefmt(p, cpsStmts, "#popCurrentException();$n", []) endBlock(p) else: var orExpr: Rope = nil for j in countup(0, blen - 2): assert(t.sons[i].sons[j].kind == nkType) if orExpr != nil: add(orExpr, "||") - let isObjFormat = if not p.module.compileToCpp: - "#isObj(#getCurrentException()->Sup.m_type, $1)" - else: "#isObj(#getCurrentException()->m_type, $1)" - let checkFor = if optNimV2 in p.config.globalOptions: genTypeInfo2Name(p.module, t[i][j].typ) else: genTypeInfo(p.module, t[i][j].typ, t[i][j].info) - appcg(p.module, orExpr, isObjFormat, [checkFor]) + let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type" + appcg(p.module, orExpr, "#isObj(#getCurrentException()->$1, $2)", [memberName, checkFor]) + if i > 1: line(p, cpsStmts, "else ") startBlock(p, "if ($1) {$n", [orExpr]) if not quirkyExceptions: - linefmt(p, cpsStmts, "$1.status = 0;$n", safePoint) + linefmt(p, cpsStmts, "$1.status = 0;$n", [safePoint]) expr(p, t.sons[i].sons[blen-1], d) - linefmt(p, cpsStmts, "#popCurrentException();$n") + linefmt(p, cpsStmts, "#popCurrentException();$n", []) endBlock(p) inc(i) discard pop(p.nestedTryStmts) @@ -1074,7 +1075,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) = genSimpleBlock(p, t.sons[i].sons[0]) discard pop(p.finallySafePoints) if not quirkyExceptions: - linefmt(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", safePoint) + linefmt(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint]) proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): Rope = var res = "" @@ -1169,7 +1170,7 @@ proc genBreakPoint(p: BProc, t: PNode) = genLineDir(p, t) # BUGFIX appcg(p.module, p.module.g.breakpoints, "#dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [ - rope(toLinenumber(t.info)), makeCString(toFilename(p.config, t.info)), + toLinenumber(t.info), makeCString(toFilename(p.config, t.info)), makeCString(name)]) proc genWatchpoint(p: BProc, n: PNode) = @@ -1212,7 +1213,7 @@ proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType, var L = lengthOrd(p.config, field.typ) if not containsOrIncl(p.module.declaredThings, field.id): appcg(p.module, cfsVars, "extern $1", - discriminatorTableDecl(p.module, t, field)) + [discriminatorTableDecl(p.module, t, field)]) lineCg(p, cpsStmts, "#FieldDiscriminantCheck((NI)(NU)($1), (NI)(NU)($2), $3, $4);$n", [rdLoc(a), rdLoc(tmp), discriminatorTableName(p.module, t, field), diff --git a/compiler/ccgthreadvars.nim b/compiler/ccgthreadvars.nim index 3e8a87041..d2d4ada36 100644 --- a/compiler/ccgthreadvars.nim +++ b/compiler/ccgthreadvars.nim @@ -21,7 +21,7 @@ proc accessThreadLocalVar(p: BProc, s: PSym) = incl p.module.flags, usesThreadVars addf(p.procSec(cpsLocals), "\tNimThreadVars* NimTV_;$n", []) add(p.procSec(cpsInit), - ropecg(p.module, "\tNimTV_ = (NimThreadVars*) #GetThreadLocalVars();$n")) + ropecg(p.module, "\tNimTV_ = (NimThreadVars*) #GetThreadLocalVars();$n", [])) proc declareThreadVar(m: BModule, s: PSym, isExtern: bool) = if emulatedThreadVars(m.config): diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim index 87e7c9d48..bcc33be14 100644 --- a/compiler/ccgtrav.nim +++ b/compiler/ccgtrav.nim @@ -16,6 +16,9 @@ type p: BProc visitorFrmt: string +const + visitorFrmt = "#nimGCvisit((void*)$1, $2);$n" + proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) proc genCaseRange(p: BProc, branch: PNode) proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) @@ -75,9 +78,9 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) = getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo(), tyInt), i) let oldCode = p.s(cpsStmts) linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n", - i.r, arraySize.rope) + [i.r, arraySize]) let oldLen = p.s(cpsStmts).len - genTraverseProc(c, ropecg(c.p.module, "$1[$2]", accessor, i.r), typ.sons[1]) + genTraverseProc(c, ropecg(c.p.module, "$1[$2]", [accessor, i.r]), typ.sons[1]) if p.s(cpsStmts).len == oldLen: # do not emit dummy long loops for faster debug builds: p.s(cpsStmts) = oldCode @@ -92,22 +95,22 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) = of tyTuple: let typ = getUniqueType(typ) for i in countup(0, sonsLen(typ) - 1): - genTraverseProc(c, ropecg(c.p.module, "$1.Field$2", accessor, i.rope), typ.sons[i]) + genTraverseProc(c, ropecg(c.p.module, "$1.Field$2", [accessor, i]), typ.sons[i]) of tyRef: - lineCg(p, cpsStmts, c.visitorFrmt, accessor) + lineCg(p, cpsStmts, visitorFrmt, [accessor, c.visitorFrmt]) of tySequence: if tfHasAsgn notin typ.flags: - lineCg(p, cpsStmts, c.visitorFrmt, accessor) + lineCg(p, cpsStmts, visitorFrmt, [accessor, c.visitorFrmt]) elif containsGarbageCollectedRef(typ.lastSon): # destructor based seqs are themselves not traced but their data is, if # they contain a GC'ed type: genTraverseProcSeq(c, accessor, typ) of tyString: if tfHasAsgn notin typ.flags: - lineCg(p, cpsStmts, c.visitorFrmt, accessor) + lineCg(p, cpsStmts, visitorFrmt, [accessor, c.visitorFrmt]) of tyProc: if typ.callConv == ccClosure: - lineCg(p, cpsStmts, c.visitorFrmt, ropecg(c.p.module, "$1.ClE_0", accessor)) + lineCg(p, cpsStmts, visitorFrmt, [ropecg(c.p.module, "$1.ClE_0", [accessor]), c.visitorFrmt]) else: discard @@ -145,7 +148,7 @@ proc genTraverseProc(m: BModule, origTyp: PType; sig: SigHash): Rope = lineF(p, cpsInit, "a = ($1)p;$n", [t]) c.p = p - c.visitorFrmt = "#nimGCvisit((void*)$1, op);$n" + c.visitorFrmt = "op" # "#nimGCvisit((void*)$1, op);$n" assert typ.kind != tyTypeDesc if typ.kind == tySequence: @@ -180,7 +183,7 @@ proc genTraverseProcForGlobal(m: BModule, s: PSym; info: TLineInfo): Rope = accessThreadLocalVar(p, s) sLoc = "NimTV_->" & sLoc - c.visitorFrmt = "#nimGCvisit((void*)$1, 0);$n" + c.visitorFrmt = "0" # "#nimGCvisit((void*)$1, 0);$n" c.p = p let header = "static N_NIMCALL(void, $1)(void)" % [result] genTraverseProc(c, sLoc, s.loc.t) diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 41e04b612..bccb59b6d 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -559,7 +559,7 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope, appcg(m, result, " : public $1 {$n", [getTypeDescAux(m, typ.sons[0].skipTypes(skipPtrs), check)]) if typ.isException: - appcg(m, result, "virtual void raise() { throw *this; }$n") # required for polymorphic exceptions + appcg(m, result, "virtual void raise() { throw *this; }$n", []) # required for polymorphic exceptions if typ.sym.magic == mException: # Add cleanup destructor to Exception base class appcg(m, result, "~$1();$n", [name]) @@ -751,10 +751,14 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope = " NI len; $2_Content* p;$n" & "};$n", [getTypeDescAux(m, t.sons[0], check), result]) else: - appcg(m, m.s[cfsSeqTypes], - (if m.compileToCpp: cppSeq else: cSeq) & - " $1 data[SEQ_DECL_SIZE];$n" & - "};$n", [getTypeDescAux(m, t.sons[0], check), result]) + if m.compileToCpp: + appcg(m, m.s[cfsSeqTypes], + cppSeq & " $1 data[SEQ_DECL_SIZE];$n" & + "};$n", [getTypeDescAux(m, t.sons[0], check), result]) + else: + appcg(m, m.s[cfsSeqTypes], + cSeq & " $1 data[SEQ_DECL_SIZE];$n" & + "};$n", [getTypeDescAux(m, t.sons[0], check), result]) elif m.config.selectedGC == gcDestructors: internalError(m.config, "cannot map the empty seq type to a C type") else: diff --git a/compiler/cgen.nim b/compiler/cgen.nim index f3a6e5a26..92cc3819b 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -101,23 +101,54 @@ proc getModuleDllPath(m: BModule): Rope = proc getModuleDllPath(m: BModule, s: PSym): Rope = return getModuleDllPath(findPendingModule(m, s)) +import macros + +proc cgFormatValue(result: var string; value: Rope): void = + for str in leaves(value): + result.add str + +proc cgFormatValue(result: var string; value: string): void = + result.add value + +proc cgFormatValue(result: var string; value: BiggestInt): void = + result.add value + # TODO: please document -proc ropecg(m: BModule, frmt: FormatStr, args: varargs[Rope]): Rope = - assert m != nil +macro ropecg(m: BModule, frmt: static[FormatStr], args: untyped): Rope = + args.expectKind nnkBracket + # echo "ropecg ", newLit(frmt).repr, ", ", args.repr var i = 0 var length = len(frmt) - result = nil + result = nnkStmtListExpr.newTree() + + result.add quote do: + assert `m` != nil + + let resVar = genSym(nskVar, "res") + # during `koch boot` the median of all generates strings from this + # macro is around 40 bytes in length. + result.add newVarStmt(resVar, newCall(bindSym"newStringOfCap", newLit(80))) + let formatValue = bindSym"cgFormatValue" + var num = 0 + var strLit = "" + + template flushStrLit() = + if strLit != "": + result.add newCall(ident "add", resVar, newLit(strLit)) + strLit.setLen 0 + while i < length: if frmt[i] == '$': inc(i) # skip '$' case frmt[i] of '$': - add(result, "$") + strLit.add '$' inc(i) of '#': + flushStrLit() inc(i) - add(result, args[num]) + result.add newCall(formatValue, resVar, args[num]) inc(num) of '0'..'9': var j = 0 @@ -126,71 +157,83 @@ proc ropecg(m: BModule, frmt: FormatStr, args: varargs[Rope]): Rope = inc(i) if i >= length or not (frmt[i] in {'0'..'9'}): break num = j - if j > high(args) + 1: - internalError(m.config, "ropes: invalid format string $" & $j) - add(result, args[j-1]) + if j > len(args): + error("ropes: invalid format string " & newLit(frmt).repr & " args.len: " & $args.len) + + flushStrLit() + result.add newCall(formatValue, resVar, args[j-1]) of 'n': - if optLineDir notin m.config.options: add(result, "\L") + flushStrLit() + result.add quote do: + if optLineDir notin `m`.config.options: + add(`resVar`, "\L") inc(i) of 'N': - add(result, "\L") + strLit.add "\L" inc(i) - else: internalError(m.config, "ropes: invalid format string $" & frmt[i]) + else: + error("ropes: invalid format string $" & frmt[i]) elif frmt[i] == '#' and frmt[i+1] in IdentStartChars: inc(i) var j = i while frmt[j] in IdentChars: inc(j) - var ident = substr(frmt, i, j-1) + var ident = newLit(substr(frmt, i, j-1)) i = j - add(result, cgsym(m, ident)) + flushStrLit() + result.add newCall(formatValue, resVar, newCall(ident"cgsym", m, ident)) elif frmt[i] == '#' and frmt[i+1] == '$': inc(i, 2) var j = 0 while frmt[i] in Digits: j = (j * 10) + ord(frmt[i]) - ord('0') inc(i) - add(result, cgsym(m, $args[j-1])) + let ident = args[j-1] + flushStrLit() + result.add newCall(formatValue, resVar, newCall(ident"cgsym", m, ident)) var start = i while i < length: if frmt[i] != '$' and frmt[i] != '#': inc(i) else: break if i - 1 >= start: - add(result, substr(frmt, start, i - 1)) + add(strLit, substr(frmt, start, i - 1)) + + flushStrLit() + result.add newCall(ident"rope", resVar) proc indentLine(p: BProc, r: Rope): Rope = result = r for i in countup(0, p.blocks.len-1): prepend(result, "\t".rope) -proc appcg(m: BModule, c: var Rope, frmt: FormatStr, - args: varargs[Rope]) = +template appcg(m: BModule, c: var Rope, frmt: FormatStr, + args: varargs[untyped]) = add(c, ropecg(m, frmt, args)) -proc appcg(m: BModule, s: TCFileSection, frmt: FormatStr, - args: varargs[Rope]) = - add(m.s[s], ropecg(m, frmt, args)) +template appcg(m: BModule, sec: TCFileSection, frmt: FormatStr, + args: varargs[untyped]) = + add(m.s[sec], ropecg(m, frmt, args)) -proc appcg(p: BProc, s: TCProcSection, frmt: FormatStr, - args: varargs[Rope]) = - add(p.s(s), ropecg(p.module, frmt, args)) +template appcg(p: BProc, sec: TCProcSection, frmt: FormatStr, + args: varargs[untyped]) = + add(p.s(sec), ropecg(p.module, frmt, args)) -proc line(p: BProc, s: TCProcSection, r: Rope) = - add(p.s(s), indentLine(p, r)) +template line(p: BProc, sec: TCProcSection, r: Rope) = + add(p.s(sec), indentLine(p, r)) -proc line(p: BProc, s: TCProcSection, r: string) = - add(p.s(s), indentLine(p, r.rope)) +template line(p: BProc, sec: TCProcSection, r: string) = + add(p.s(sec), indentLine(p, r.rope)) -proc lineF(p: BProc, s: TCProcSection, frmt: FormatStr, +template lineF(p: BProc, sec: TCProcSection, frmt: FormatStr, args: openarray[Rope]) = - add(p.s(s), indentLine(p, frmt % args)) + add(p.s(sec), indentLine(p, frmt % args)) -proc lineCg(p: BProc, s: TCProcSection, frmt: FormatStr, - args: varargs[Rope]) = - add(p.s(s), indentLine(p, ropecg(p.module, frmt, args))) +template lineCg(p: BProc, sec: TCProcSection, frmt: FormatStr, + args: untyped) = + add(p.s(sec), indentLine(p, ropecg(p.module, frmt, args))) -proc linefmt(p: BProc, s: TCProcSection, frmt: FormatStr, - args: varargs[Rope]) = - add(p.s(s), indentLine(p, ropecg(p.module, frmt, args))) +template linefmt(p: BProc, sec: TCProcSection, frmt: FormatStr, + args: untyped) = + add(p.s(sec), indentLine(p, ropecg(p.module, frmt, args))) proc safeLineNm(info: TLineInfo): int = result = toLinenumber(info) @@ -222,13 +265,13 @@ proc genLineDir(p: BProc, t: PNode) = (p.prc == nil or sfPure notin p.prc.flags): if freshLineInfo(p, t.info): linefmt(p, cpsStmts, "#endb($1, $2);$N", - line.rope, makeCString(toFilename(p.config, t.info))) + [line, makeCString(toFilename(p.config, t.info))]) elif ({optLineTrace, optStackTrace} * p.options == {optLineTrace, optStackTrace}) and (p.prc == nil or sfPure notin p.prc.flags) and t.info.fileIndex != InvalidFileIDX: if freshLineInfo(p, t.info): linefmt(p, cpsStmts, "nimln_($1, $2);$n", - line.rope, quotedFilename(p.config, t.info)) + [line, quotedFilename(p.config, t.info)]) proc postStmtActions(p: BProc) {.inline.} = add(p.s(cpsStmts), p.module.injectStmt) @@ -291,7 +334,7 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc, if p.module.compileToCpp and t.isException and not isDefined(p.config, "noCppExceptions"): # init vtable in Exception object for polymorphic exceptions includeHeader(p.module, "<new>") - linefmt(p, section, "new ($1) $2;$n", rdLoc(a), getTypeDesc(p.module, t)) + linefmt(p, section, "new ($1) $2;$n", [rdLoc(a), getTypeDesc(p.module, t)]) #if optNimV2 in p.config.globalOptions: return case analyseObjectWithTypeField(t) @@ -305,14 +348,14 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc, while s.kind == tyObject and s.sons[0] != nil: add(r, ".Sup") s = skipTypes(s.sons[0], skipPtrs) - linefmt(p, section, "$1.m_type = $2;$n", r, genTypeInfo(p.module, t, a.lode.info)) + linefmt(p, section, "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t, a.lode.info)]) of frEmbedded: if optNimV2 in p.config.globalOptions: localError(p.config, p.prc.info, "complex object initialization is not supported with --newruntime") # worst case for performance: var r = if takeAddr: addrLoc(p.config, a) else: rdLoc(a) - linefmt(p, section, "#objectInit($1, $2);$n", r, genTypeInfo(p.module, t, a.lode.info)) + linefmt(p, section, "#objectInit($1, $2);$n", [r, genTypeInfo(p.module, t, a.lode.info)]) type TAssignmentFlag = enum @@ -332,7 +375,7 @@ proc resetLoc(p: BProc, loc: var TLoc) = if isImportedCppType(typ): return if p.config.selectedGc == gcDestructors and typ.kind in {tyString, tySequence}: assert rdLoc(loc) != nil - linefmt(p, cpsStmts, "$1.len = 0; $1.p = NIM_NIL;$n", rdLoc(loc)) + linefmt(p, cpsStmts, "$1.len = 0; $1.p = NIM_NIL;$n", [rdLoc(loc)]) elif not isComplexValueType(typ): if containsGcRef: var nilLoc: TLoc @@ -340,13 +383,13 @@ proc resetLoc(p: BProc, loc: var TLoc) = nilLoc.r = rope("NIM_NIL") genRefAssign(p, loc, nilLoc) else: - linefmt(p, cpsStmts, "$1 = 0;$n", rdLoc(loc)) + linefmt(p, cpsStmts, "$1 = 0;$n", [rdLoc(loc)]) else: if optNilCheck in p.options: - linefmt(p, cpsStmts, "#chckNil((void*)$1);$n", addrLoc(p.config, loc)) + linefmt(p, cpsStmts, "#chckNil((void*)$1);$n", [addrLoc(p.config, loc)]) if loc.storage != OnStack and containsGcRef: linefmt(p, cpsStmts, "#genericReset((void*)$1, $2);$n", - addrLoc(p.config, loc), genTypeInfo(p.module, loc.t, loc.lode.info)) + [addrLoc(p.config, loc), genTypeInfo(p.module, loc.t, loc.lode.info)]) # XXX: generated reset procs should not touch the m_type # field, so disabling this should be safe: genObjectInit(p, cpsStmts, loc.t, loc, true) @@ -354,7 +397,7 @@ proc resetLoc(p: BProc, loc: var TLoc) = # array passed as argument decayed into pointer, bug #7332 # so we use getTypeDesc here rather than rdLoc(loc) linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));$n", - addrLoc(p.config, loc), getTypeDesc(p.module, loc.t)) + [addrLoc(p.config, loc), getTypeDesc(p.module, loc.t)]) # XXX: We can be extra clever here and call memset only # on the bytes following the m_type field? genObjectInit(p, cpsStmts, loc.t, loc, true) @@ -362,17 +405,17 @@ proc resetLoc(p: BProc, loc: var TLoc) = proc constructLoc(p: BProc, loc: TLoc, isTemp = false) = let typ = loc.t if p.config.selectedGc == gcDestructors and skipTypes(typ, abstractInst).kind in {tyString, tySequence}: - linefmt(p, cpsStmts, "$1.len = 0; $1.p = NIM_NIL;$n", rdLoc(loc)) + linefmt(p, cpsStmts, "$1.len = 0; $1.p = NIM_NIL;$n", [rdLoc(loc)]) elif not isComplexValueType(typ): - linefmt(p, cpsStmts, "$1 = ($2)0;$n", rdLoc(loc), - getTypeDesc(p.module, typ)) + linefmt(p, cpsStmts, "$1 = ($2)0;$n", [rdLoc(loc), + getTypeDesc(p.module, typ)]) else: if not isTemp or containsGarbageCollectedRef(loc.t): # don't use nimZeroMem for temporary values for performance if we can # avoid it: if not isImportedCppType(typ): linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));$n", - addrLoc(p.config, loc), getTypeDesc(p.module, typ)) + [addrLoc(p.config, loc), getTypeDesc(p.module, typ)]) genObjectInit(p, cpsStmts, loc.t, loc, true) proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) = @@ -390,7 +433,7 @@ proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) = proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) = inc(p.labels) result.r = "T" & rope(p.labels) & "_" - linefmt(p, cpsLocals, "$1 $2;$n", getTypeDesc(p.module, t), result.r) + linefmt(p, cpsLocals, "$1 $2;$n", [getTypeDesc(p.module, t), result.r]) result.k = locTemp result.lode = lodeTyp t result.storage = OnStack @@ -400,7 +443,7 @@ proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) = proc getIntTemp(p: BProc, result: var TLoc) = inc(p.labels) result.r = "T" & rope(p.labels) & "_" - linefmt(p, cpsLocals, "NI $1;$n", result.r) + linefmt(p, cpsLocals, "NI $1;$n", [result.r]) result.k = locTemp result.storage = OnStack result.lode = lodeTyp getSysType(p.module.g.graph, unknownLineInfo(), tyInt) @@ -412,7 +455,7 @@ proc initGCFrame(p: BProc): Rope = proc deinitGCFrame(p: BProc): Rope = if p.gcFrameId > 0: result = ropecg(p.module, - "if (((NU)&GCFRAME_) < 4096) #nimGCFrame(&GCFRAME_);$n") + "if (((NU)&GCFRAME_) < 4096) #nimGCFrame(&GCFRAME_);$n", []) proc localDebugInfo(p: BProc, s: PSym, retType: PType) = if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return @@ -565,29 +608,29 @@ proc initFrame(p: BProc, procname, filename: Rope): Rope = FR_.line = n; FR_.filename = file; """ if p.module.s[cfsFrameDefines].len == 0: - appcg(p.module, p.module.s[cfsFrameDefines], frameDefines, [rope("#")]) + appcg(p.module, p.module.s[cfsFrameDefines], frameDefines, ["#"]) discard cgsym(p.module, "nimFrame") if p.maxFrameLen > 0: discard cgsym(p.module, "VarSlot") result = ropecg(p.module, "\tnimfrs_($1, $2, $3, $4);$n", - procname, filename, p.maxFrameLen.rope, - p.blocks[0].frameLen.rope) + [procname, filename, p.maxFrameLen, + p.blocks[0].frameLen]) else: - result = ropecg(p.module, "\tnimfr_($1, $2);$n", procname, filename) + result = ropecg(p.module, "\tnimfr_($1, $2);$n", [procname, filename]) proc initFrameNoDebug(p: BProc; frame, procname, filename: Rope; line: int): Rope = discard cgsym(p.module, "nimFrame") addf(p.blocks[0].sections[cpsLocals], "TFrame $1;$n", [frame]) result = ropecg(p.module, "\t$1.procname = $2; $1.filename = $3; " & " $1.line = $4; $1.len = -1; nimFrame(&$1);$n", - frame, procname, filename, rope(line)) + [frame, procname, filename, line]) proc deinitFrameNoDebug(p: BProc; frame: Rope): Rope = - result = ropecg(p.module, "\t#popFrameOfAddr(&$1);$n", frame) + result = ropecg(p.module, "\t#popFrameOfAddr(&$1);$n", [frame]) proc deinitFrame(p: BProc): Rope = - result = ropecg(p.module, "\t#popFrame();$n") + result = ropecg(p.module, "\t#popFrame();$n", []) include ccgexprs @@ -766,10 +809,10 @@ proc closureSetup(p: BProc, prc: PSym) = # generate cast assignment: if p.config.selectedGC == gcGo: linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, ($2) ClE_0);$n", - addrLoc(p.config, env.loc), getTypeDesc(p.module, env.typ)) + [addrLoc(p.config, env.loc), getTypeDesc(p.module, env.typ)]) else: linefmt(p, cpsStmts, "$1 = ($2) ClE_0;$n", - rdLoc(env.loc), getTypeDesc(p.module, env.typ)) + [rdLoc(env.loc), getTypeDesc(p.module, env.typ)]) proc containsResult(n: PNode): bool = if n.kind == nkSym and n.sym.kind == skResult: @@ -928,13 +971,13 @@ proc genProcAux(m: BModule, prc: PSym) = var decl = localVarDecl(p, resNode) var a: TLoc initLocExprSingleUse(p, val, a) - linefmt(p, cpsStmts, "$1 = $2;$n", decl, rdLoc(a)) + linefmt(p, cpsStmts, "$1 = $2;$n", [decl, rdLoc(a)]) else: # declare the result symbol: assignLocalVar(p, resNode) assert(res.loc.r != nil) initLocalVar(p, res, immediateAsgn=false) - returnStmt = ropecg(p.module, "\treturn $1;$n", rdLoc(res.loc)) + returnStmt = ropecg(p.module, "\treturn $1;$n", [rdLoc(res.loc)]) else: fillResult(p.config, resNode) assignParam(p, res, prc.typ[0]) @@ -966,9 +1009,9 @@ proc genProcAux(m: BModule, prc: PSym) = if hasDeclspec in extccomp.CC[p.config.cCompiler].props: header = "__declspec(naked) " & header generatedProc = ropecg(p.module, "$N$1 {$n$2$3$4}$N$N", - header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)) + [header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)]) else: - generatedProc = ropecg(p.module, "$N$1 {$N", header) + generatedProc = ropecg(p.module, "$N$1 {$N", [header]) add(generatedProc, initGCFrame(p)) if optStackTrace in prc.options: add(generatedProc, p.s(cpsLocals)) @@ -1007,8 +1050,8 @@ proc genProcPrototype(m: BModule, sym: PSym) = if getModule(sym).id != m.module.id and not containsOrIncl(m.declaredThings, sym.id): add(m.s[cfsVars], ropecg(m, "$1 $2 $3;$n", - rope(if isReloadable(m, sym): "static" else: "extern"), - getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym))) + [(if isReloadable(m, sym): "static" else: "extern"), + getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym)])) if isReloadable(m, sym): addf(m.s[cfsDynLibInit], "\t$1 = ($2) hcrGetProc($3, \"$1\");$n", [mangleDynLibProc(sym), getTypeDesc(m, sym.loc.t), getModuleDllPath(m, sym)]) @@ -1024,7 +1067,7 @@ proc genProcPrototype(m: BModule, sym: PSym) = header.add(" __attribute__((naked))") if sfNoReturn in sym.flags and hasAttribute in CC[m.config.cCompiler].props: header.add(" __attribute__((noreturn))") - add(m.s[cfsProcHeaders], ropecg(m, "$1;$N", header)) + add(m.s[cfsProcHeaders], ropecg(m, "$1;$N", [header])) # TODO: figure out how to rename this - it DOES generate a forward declaration proc genProcNoForward(m: BModule, prc: PSym) = @@ -1222,19 +1265,19 @@ proc genMainProc(m: BModule) = n.info = prc.annex.path.info appcg(m, result, "\tif (!($1 = #nimLoadLibrary($2)))$N" & "\t\t#nimLoadLibraryError($2);$N", - [handle.rope, genStringLiteral(m, n)]) + [handle, genStringLiteral(m, n)]) add(preMainCode, loadLib("hcr_handle", "hcrGetProc")) - add(preMainCode, "\tvoid* rtl_handle;$N") + add(preMainCode, "\tvoid* rtl_handle;\L") add(preMainCode, loadLib("rtl_handle", "nimGC_setStackBottom")) add(preMainCode, hcrGetProcLoadCode(m, "nimGC_setStackBottom", "nimrtl_", "rtl_handle", "nimGetProcAddr")) - add(preMainCode, "\tinner = PreMain;$N") - add(preMainCode, "\tinitStackBottomWith_actual((void *)&inner);$N") - add(preMainCode, "\t(*inner)();$N") + add(preMainCode, "\tinner = PreMain;\L") + add(preMainCode, "\tinitStackBottomWith_actual((void *)&inner);\L") + add(preMainCode, "\t(*inner)();\L") else: - add(preMainCode, "\tPreMain();$N") + add(preMainCode, "\tPreMain();\L") - let + const # not a big deal if we always compile these 3 global vars... makes the HCR code easier PosixCmdLine = "int cmdCount;$N" & @@ -1261,7 +1304,7 @@ proc genMainProc(m: BModule) = "\tNimMain();$N" MainProcsWithResult = - MainProcs & ("\treturn " & (if m.hcrOn: "*" else: "") & "nim_program_result;$N") + MainProcs & ("\treturn $1nim_program_result;$N") NimMainInner = "N_CDECL(void, NimMainInner)(void) {$N" & "$1" & @@ -1270,7 +1313,7 @@ proc genMainProc(m: BModule) = NimMainProc = "N_CDECL(void, NimMain)(void) {$N" & "\tvoid (*volatile inner)(void);$N" & - $preMainCode & + "$4" & "\tinner = NimMainInner;$N" & "$2" & "\t(*inner)();$N" & @@ -1331,29 +1374,12 @@ proc genMainProc(m: BModule) = "\t});$N" & "}$N$N" - var nimMain, otherMain: FormatStr if m.config.target.targetOS == osWindows and m.config.globalOptions * {optGenGuiApp, optGenDynLib} != {}: - if optGenGuiApp in m.config.globalOptions: - nimMain = WinNimMain - otherMain = WinCMain - else: - nimMain = WinNimDllMain - otherMain = WinCDllMain m.includeHeader("<windows.h>") elif m.config.target.targetOS == osGenode: - nimMain = GenodeNimMain - otherMain = ComponentConstruct m.includeHeader("<libc/component.h>") - elif optGenDynLib in m.config.globalOptions: - nimMain = PosixNimDllMain - otherMain = PosixCDllMain - elif m.config.target.targetOS == osStandalone: - nimMain = NimMainBody - otherMain = StandaloneCMain - else: - nimMain = NimMainBody - otherMain = PosixCMain + if optEndb in m.config.options: for i in 0..<m.config.m.fileInfos.len: m.g.breakpoints.addf("dbgRegisterFilename($1);$N", @@ -1361,18 +1387,65 @@ proc genMainProc(m: BModule) = let initStackBottomCall = if m.config.target.targetOS == osStandalone or m.config.selectedGC == gcNone: "".rope - else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N") + else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N", []) inc(m.labels) appcg(m, m.s[cfsProcs], PreMainBody, [ m.g.mainDatInit, m.g.breakpoints, m.g.otherModsInit]) - appcg(m, m.s[cfsProcs], nimMain, - [m.g.mainModInit, initStackBottomCall, rope(m.labels)]) + if m.config.target.targetOS == osWindows and + m.config.globalOptions * {optGenGuiApp, optGenDynLib} != {}: + if optGenGuiApp in m.config.globalOptions: + const nimMain = WinNimMain + appcg(m, m.s[cfsProcs], nimMain, + [m.g.mainModInit, initStackBottomCall, m.labels, preMainCode]) + else: + const nimMain = WinNimDllMain + appcg(m, m.s[cfsProcs], nimMain, + [m.g.mainModInit, initStackBottomCall, m.labels, preMainCode]) + elif m.config.target.targetOS == osGenode: + const nimMain = GenodeNimMain + appcg(m, m.s[cfsProcs], nimMain, + [m.g.mainModInit, initStackBottomCall, m.labels, preMainCode]) + elif optGenDynLib in m.config.globalOptions: + const nimMain = PosixNimDllMain + appcg(m, m.s[cfsProcs], nimMain, + [m.g.mainModInit, initStackBottomCall, m.labels, preMainCode]) + elif m.config.target.targetOS == osStandalone: + const nimMain = NimMainBody + appcg(m, m.s[cfsProcs], nimMain, + [m.g.mainModInit, initStackBottomCall, m.labels, preMainCode]) + else: + const nimMain = NimMainBody + appcg(m, m.s[cfsProcs], nimMain, + [m.g.mainModInit, initStackBottomCall, m.labels, preMainCode]) + + if optNoMain notin m.config.globalOptions: if m.config.cppCustomNamespace.len > 0: m.s[cfsProcs].add closeNamespaceNim() & "using namespace " & m.config.cppCustomNamespace & ";\L" - appcg(m, m.s[cfsProcs], otherMain, []) + if m.config.target.targetOS == osWindows and + m.config.globalOptions * {optGenGuiApp, optGenDynLib} != {}: + if optGenGuiApp in m.config.globalOptions: + const otherMain = WinCMain + appcg(m, m.s[cfsProcs], otherMain, [if m.hcrOn: "*" else: ""]) + else: + const otherMain = WinCDllMain + appcg(m, m.s[cfsProcs], otherMain, []) + elif m.config.target.targetOS == osGenode: + const otherMain = ComponentConstruct + appcg(m, m.s[cfsProcs], otherMain, []) + elif optGenDynLib in m.config.globalOptions: + const otherMain = PosixCDllMain + appcg(m, m.s[cfsProcs], otherMain, []) + elif m.config.target.targetOS == osStandalone: + const otherMain = StandaloneCMain + appcg(m, m.s[cfsProcs], otherMain, []) + else: + const otherMain = PosixCMain + appcg(m, m.s[cfsProcs], otherMain, [if m.hcrOn: "*" else: ""]) + + if m.config.cppCustomNamespace.len > 0: m.s[cfsProcs].add openNamespaceNim(m.config.cppCustomNamespace) @@ -1430,9 +1503,9 @@ proc registerModuleToMain(g: BModuleList; m: BModule) = # systemDatInit and systemInit calls if any if sfSystemModule in m.module.flags: if emulatedThreadVars(m.config) and m.config.target.targetOS != osStandalone: - add(g.mainDatInit, ropecg(m, "\t#initThreadVarsEmulation();$N")) + add(g.mainDatInit, ropecg(m, "\t#initThreadVarsEmulation();$N", [])) if m.config.target.targetOS != osStandalone and m.config.selectedGC != gcNone: - add(g.mainDatInit, ropecg(m, "\t#initStackBottomWith((void *)&inner);$N")) + add(g.mainDatInit, ropecg(m, "\t#initStackBottomWith((void *)&inner);$N", [])) if m.s[cfsInitProc].len > 0: addf(g.mainModProcs, "N_LIB_PRIVATE N_NIMCALL(void, $1)(void);$N", [init]) @@ -1503,13 +1576,13 @@ proc genInitCode(m: BModule) = if m.hcrOn: appcg(m, m.s[cfsTypeInit1], "\t#TNimNode* $1;$N", [m.typeNodesName]) appcg(m, m.s[cfsTypeInit1], "\thcrRegisterGlobal($3, \"$1_$2\", sizeof(TNimNode) * $2, NULL, (void**)&$1);$N", - [m.typeNodesName, rope(m.typeNodes), getModuleDllPath(m, m.module)]) + [m.typeNodesName, m.typeNodes, getModuleDllPath(m, m.module)]) else: appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n", - [m.typeNodesName, rope(m.typeNodes)]) + [m.typeNodesName, m.typeNodes]) if m.nimTypes > 0: appcg(m, m.s[cfsTypeInit1], "static #TNimType $1[$2];$n", - [m.nimTypesName, rope(m.nimTypes)]) + [m.nimTypesName, m.nimTypes]) if m.hcrOn: addf(prc, "\tint* nim_hcr_dummy_ = 0;$n" & |