diff --git a/compiler/cbuilderstmts.nim b/compiler/cbuilderstmts.nim
index aa29951391..a96571d1b8 100644
--- a/compiler/cbuilderstmts.nim
+++ b/compiler/cbuilderstmts.nim
@@ -109,3 +109,16 @@ proc addReturn(builder: var Builder, value: string) =
builder.add("return ")
builder.add(value)
builder.add(";\n")
+
+template addGoto(builder: var Builder, label: TLabel) =
+ builder.add("goto ")
+ builder.add(label)
+ builder.add(";\n")
+
+template addIncr(builder: var Builder, val: Snippet) =
+ builder.add(val)
+ builder.add("++;\n")
+
+template addDecr(builder: var Builder, val: Snippet) =
+ builder.add(val)
+ builder.add("--;\n")
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 4b81f9af72..78e9e5e280 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -952,7 +952,8 @@ proc cowBracket(p: BProc; n: PNode) =
let strCandidate = n[0]
if strCandidate.typ.skipTypes(abstractInst).kind == tyString:
var a: TLoc = initLocExpr(p, strCandidate)
- linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
+ let raa = byRefLoc(p, a)
+ p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "nimPrepareStrMutationV2"), raa)
proc cow(p: BProc; n: PNode) {.inline.} =
if n.kind == nkHiddenAddr: cowBracket(p, n[0])
@@ -992,7 +993,7 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
case e[1].kind
of nkIntLit..nkUInt64Lit: i = int(e[1].intVal)
else: internalError(p.config, e.info, "genTupleElem")
- r.addf(".Field$1", [rope(i)])
+ r = dotField(r, "Field" & $i)
putIntoDest(p, d, e, r, a.storage)
proc lookupFieldAgain(p: BProc, ty: PType; field: PSym; r: var Rope;
@@ -1007,7 +1008,8 @@ proc lookupFieldAgain(p: BProc, ty: PType; field: PSym; r: var Rope;
if result != nil:
if resTyp != nil: resTyp[] = ty
break
- if not p.module.compileToCpp: r.add(".Sup")
+ if not p.module.compileToCpp:
+ r = dotField(r, "Sup")
ty = ty[0]
if result == nil: internalError(p.config, field.info, "genCheckedRecordField")
@@ -1026,16 +1028,14 @@ proc genRecordField(p: BProc, e: PNode, d: var TLoc) =
if ty.kind == tyTuple:
# we found a unique tuple type which lacks field information
# so we use Field$i
- r.add ".Field"
- r.add rope(f.position)
+ r = dotField(r, "Field" & $f.position)
putIntoDest(p, d, e, r, a.storage)
else:
var rtyp: PType = nil
let field = lookupFieldAgain(p, ty, f, r, addr rtyp)
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.snippet
+ r = dotField(r, field.loc.snippet)
putIntoDest(p, d, e, r, a.storage)
r.freeze
@@ -1054,10 +1054,7 @@ 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.snippet = newRopeAppender()
- v.snippet.add obj
- v.snippet.add(".")
- v.snippet.add(disc.sym.loc.snippet)
+ v.snippet = dotField(obj, disc.sym.loc.snippet)
genInExprAux(p, it, u, v, test)
var msg = ""
if optDeclaredLocs in p.config.globalOptions:
@@ -1072,39 +1069,51 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
genStringLiteral(p.module, newStrNode(nkStrLit, msg), strLit)
## discriminant check
- template fun(code) = linefmt(p, cpsStmts, code, [rdLoc(test)])
- if op.magic == mNot: fun("if ($1) ") else: fun("if (!($1)) ")
+ let rt = rdLoc(test)
+ let cond = if op.magic == mNot: rt else: cOp(Not, rt)
+ p.s(cpsStmts).addSingleIfStmt(cond):
+ ## call raiseFieldError2 on failure
+ var discIndex = newRopeAppender()
+ rdSetElemLoc(p.config, v, u.t, discIndex)
+ if optTinyRtti in p.config.globalOptions:
+ let base = disc.typ.skipTypes(abstractInst+{tyRange})
+ case base.kind
+ of tyEnum:
+ let toStrProc = getToStringProc(p.module.g.graph, base)
+ # XXX need to modify this logic for IC.
+ # need to analyze nkFieldCheckedExpr and marks procs "used" like range checks in dce
+ var toStr: TLoc = default(TLoc)
+ expr(p, newSymNode(toStrProc), toStr)
+ let rToStr = rdLoc(toStr)
+ let rv = rdLoc(v)
+ var raiseCall: CallBuilder
+ p.s(cpsStmts).addStmt():
+ p.s(cpsStmts).addCall(raiseCall, cgsymValue(p.module, "raiseFieldErrorStr")):
+ p.s(cpsStmts).addArgument(raiseCall):
+ p.s(cpsStmts).add(strLit)
+ p.s(cpsStmts).addArgument(raiseCall):
+ p.s(cpsStmts).addCall(rToStr, rv)
+ else:
+ p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "raiseFieldError2"),
+ strLit,
+ cCast("NI", discIndex))
- ## call raiseFieldError2 on failure
- var discIndex = newRopeAppender()
- rdSetElemLoc(p.config, v, u.t, discIndex)
- if optTinyRtti in p.config.globalOptions:
- let base = disc.typ.skipTypes(abstractInst+{tyRange})
- case base.kind
- of tyEnum:
- const code = "{ #raiseFieldErrorStr($1, $2); "
- let toStrProc = getToStringProc(p.module.g.graph, base)
- # XXX need to modify this logic for IC.
- # need to analyze nkFieldCheckedExpr and marks procs "used" like range checks in dce
- var toStr: TLoc = default(TLoc)
- expr(p, newSymNode(toStrProc), toStr)
- let enumStr = "$1($2)" % [rdLoc(toStr), rdLoc(v)]
- linefmt(p, cpsStmts, code, [strLit, enumStr])
else:
- const code = "{ #raiseFieldError2($1, (NI)$2); "
- linefmt(p, cpsStmts, code, [strLit, discIndex])
+ # complication needed for signed types
+ let first = p.config.firstOrd(disc.sym.typ)
+ let firstLit = cInt64Literal(cast[int](first))
+ let discName = genTypeInfo(p.config, p.module, disc.sym.typ, e.info)
+ var raiseCall: CallBuilder
+ p.s(cpsStmts).addStmt():
+ p.s(cpsStmts).addCall(raiseCall, cgsymValue(p.module, "raiseFieldError2")):
+ p.s(cpsStmts).addArgument(raiseCall):
+ p.s(cpsStmts).add(strLit)
+ p.s(cpsStmts).addArgument(raiseCall):
+ p.s(cpsStmts).addCall(cgsymValue(p.module, "reprDiscriminant"),
+ cOp(Add, "NI", cCast("NI", discIndex), cCast("NI", firstLit)),
+ discName)
- else:
- # complication needed for signed types
- let first = p.config.firstOrd(disc.sym.typ)
- var firstLit = newRopeAppender()
- int64Literal(cast[int](first), firstLit)
- let discName = genTypeInfo(p.config, p.module, disc.sym.typ, e.info)
- const code = "{ #raiseFieldError2($1, #reprDiscriminant(((NI)$2) + (NI)$3, $4)); "
- linefmt(p, cpsStmts, code, [strLit, discIndex, firstLit, discName])
-
- raiseInstr(p, p.s(cpsStmts))
- linefmt p, cpsStmts, "}$n", []
+ raiseInstr(p, p.s(cpsStmts))
proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
assert e[0].kind == nkDotExpr
@@ -1119,8 +1128,7 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
if field.loc.snippet == "":
internalError(p.config, e.info, "genCheckedRecordField") # generate the checks:
genFieldCheck(p, e, r, field)
- r.add(".")
- r.add field.loc.snippet
+ r = dotField(r, field.loc.snippet)
putIntoDest(p, d, e[0], r, a.storage)
r.freeze
else:
@@ -1130,114 +1138,132 @@ proc genUncheckedArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
var a = initLocExpr(p, x)
var b = initLocExpr(p, y)
d.inheritLocation(a)
- putIntoDest(p, d, n, ropecg(p.module, "$1[$2]", [rdLoc(a), rdCharLoc(b)]),
+ putIntoDest(p, d, n, subscript(rdLoc(a), rdCharLoc(b)),
a.storage)
proc genArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
var a = initLocExpr(p, x)
var b = initLocExpr(p, y)
var ty = skipTypes(a.t, abstractVarRange + abstractPtrs + tyUserTypeClasses)
- var first = newRopeAppender()
- intLiteral(firstOrd(p.config, ty), first)
+ let first = cIntLiteral(firstOrd(p.config, ty))
# emit range check:
if optBoundsCheck in p.options and ty.kind != tyUncheckedArray:
if not isConstExpr(y):
# semantic pass has already checked for const index expressions
if firstOrd(p.config, ty) == 0 and lastOrd(p.config, ty) >= 0:
if (firstOrd(p.config, b.t) < firstOrd(p.config, ty)) or (lastOrd(p.config, b.t) > lastOrd(p.config, ty)):
- var last = newRopeAppender()
- intLiteral(lastOrd(p.config, ty), last)
- linefmt(p, cpsStmts, "if ((NU)($1) > (NU)($2)){ #raiseIndexError2($1, $2); ",
- [rdCharLoc(b), last])
- raiseInstr(p, p.s(cpsStmts))
- linefmt p, cpsStmts, "}$n", []
+ let last = cIntLiteral(lastOrd(p.config, ty))
+ let rcb = rdCharLoc(b)
+ p.s(cpsStmts).addSingleIfStmt(
+ cOp(GreaterThan, cCast("NU", rcb), cCast("NU", last))):
+ p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "raiseIndexError2"),
+ rcb,
+ last)
+ raiseInstr(p, p.s(cpsStmts))
else:
- var last = newRopeAppender()
- intLiteral(lastOrd(p.config, ty), last)
- linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3){ #raiseIndexError3($1, $2, $3); ",
- [rdCharLoc(b), first, last])
- raiseInstr(p, p.s(cpsStmts))
- linefmt p, cpsStmts, "}$n", []
+ let last = cIntLiteral(lastOrd(p.config, ty))
+ let rcb = rdCharLoc(b)
+ p.s(cpsStmts).addSingleIfStmt(
+ cOp(Or, cOp(LessThan, rcb, first), cOp(GreaterThan, rcb, last))):
+ p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "raiseIndexError3"),
+ rcb,
+ first,
+ last)
+ raiseInstr(p, p.s(cpsStmts))
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)
+ let ra = rdLoc(a)
+ let rcb = rdCharLoc(b)
+ putIntoDest(p, d, n, subscript(ra, cOp(Sub, "NI", rcb, first)), a.storage)
proc genCStringElem(p: BProc, n, x, y: PNode, d: var TLoc) =
var a = initLocExpr(p, x)
var b = initLocExpr(p, y)
inheritLocation(d, a)
- putIntoDest(p, d, n,
- ropecg(p.module, "$1[$2]", [rdLoc(a), rdCharLoc(b)]), a.storage)
+ let ra = rdLoc(a)
+ let rcb = rdLoc(b)
+ putIntoDest(p, d, n, subscript(ra, rcb), a.storage)
proc genBoundsCheck(p: BProc; arr, a, b: TLoc; arrTyp: PType) =
let ty = arrTyp
case ty.kind
of tyOpenArray, tyVarargs:
- if reifiedOpenArray(arr.lode):
- linefmt(p, cpsStmts,
- "if ($2-$1 != -1 && " &
- "($1 < 0 || $1 >= $3.Field1 || $2 < 0 || $2 >= $3.Field1)){ #raiseIndexError4($1, $2, $3.Field1); ",
- [rdLoc(a), rdLoc(b), rdLoc(arr)])
- else:
- linefmt(p, cpsStmts,
- "if ($2-$1 != -1 && ($1 < 0 || $1 >= $3Len_0 || $2 < 0 || $2 >= $3Len_0))" &
- "{ #raiseIndexError4($1, $2, $3Len_0); ",
- [rdLoc(a), rdLoc(b), rdLoc(arr)])
- raiseInstr(p, p.s(cpsStmts))
- linefmt p, cpsStmts, "}$n", []
+ let ra = rdLoc(a)
+ let rb = rdLoc(b)
+ let rarr = rdLoc(arr)
+ let arrlen =
+ if reifiedOpenArray(arr.lode):
+ dotField(rarr, "Field1")
+ else:
+ rarr & "Len_0"
+ p.s(cpsStmts).addSingleIfStmt(cOp(And,
+ cOp(NotEqual, cOp(Sub, "NI", rb, ra), cIntValue(-1)),
+ cOp(Or,
+ cOp(Or, cOp(LessThan, ra, cIntValue(0)), cOp(GreaterEqual, ra, arrlen)),
+ cOp(Or, cOp(LessThan, rb, cIntValue(0)), cOp(GreaterEqual, rb, arrlen))))):
+ p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "raiseIndexError4"),
+ ra, rb, arrlen)
+ raiseInstr(p, p.s(cpsStmts))
of tyArray:
- var first = newRopeAppender()
- intLiteral(firstOrd(p.config, ty), first)
- var last = newRopeAppender()
- intLiteral(lastOrd(p.config, ty), last)
- linefmt(p, cpsStmts,
- "if ($2-$1 != -1 && " &
- "($2-$1 < -1 || $1 < $3 || $1 > $4 || $2 < $3 || $2 > $4)){ #raiseIndexError(); ",
- [rdCharLoc(a), rdCharLoc(b), first, last])
-
- raiseInstr(p, p.s(cpsStmts))
- linefmt p, cpsStmts, "}$n", []
+ let first = cIntLiteral(firstOrd(p.config, ty))
+ let last = cIntLiteral(lastOrd(p.config, ty))
+ let rca = rdCharLoc(a)
+ let rcb = rdCharLoc(b)
+ p.s(cpsStmts).addSingleIfStmt(cOp(And,
+ cOp(NotEqual, cOp(Sub, "NI", rcb, rca), cIntValue(-1)),
+ cOp(Or,
+ cOp(LessThan, cOp(Sub, "NI", rcb, rca), cIntValue(-1)),
+ cOp(Or,
+ cOp(Or, cOp(LessThan, rca, first), cOp(GreaterThan, rca, last)),
+ cOp(Or, cOp(LessThan, rcb, first), cOp(GreaterThan, rcb, last)))))):
+ p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "raiseIndexError"))
+ raiseInstr(p, p.s(cpsStmts))
of tySequence, tyString:
- linefmt(p, cpsStmts,
- "if ($2-$1 != -1 && " &
- "($1 < 0 || $1 >= $3 || $2 < 0 || $2 >= $3)){ #raiseIndexError4($1, $2, $3); ",
- [rdLoc(a), rdLoc(b), lenExpr(p, arr)])
- raiseInstr(p, p.s(cpsStmts))
- linefmt p, cpsStmts, "}$n", []
+ let ra = rdLoc(a)
+ let rb = rdLoc(b)
+ let arrlen = lenExpr(p, arr)
+ p.s(cpsStmts).addSingleIfStmt(cOp(And,
+ cOp(NotEqual, cOp(Sub, "NI", rb, ra), cIntValue(-1)),
+ cOp(Or,
+ cOp(Or, cOp(LessThan, ra, cIntValue(0)), cOp(GreaterEqual, ra, arrlen)),
+ cOp(Or, cOp(LessThan, rb, cIntValue(0)), cOp(GreaterEqual, rb, arrlen))))):
+ p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "raiseIndexError4"),
+ ra, rb, arrlen)
+ raiseInstr(p, p.s(cpsStmts))
else: discard
proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
var a = initLocExpr(p, x)
var b = initLocExpr(p, y)
+ let ra = rdLoc(a)
+ let rcb = rdCharLoc(b)
+ var arrData, arrLen: Snippet
if not reifiedOpenArray(x):
- # emit range check:
- if optBoundsCheck in p.options:
- linefmt(p, cpsStmts, "if ($1 < 0 || $1 >= $2Len_0){ #raiseIndexError2($1,$2Len_0-1); ",
- [rdCharLoc(b), rdLoc(a)]) # BUGFIX: ``>=`` and not ``>``!
- raiseInstr(p, p.s(cpsStmts))
- linefmt p, cpsStmts, "}$n", []
-
- inheritLocation(d, a)
- putIntoDest(p, d, n,
- ropecg(p.module, "$1[$2]", [rdLoc(a), rdCharLoc(b)]), a.storage)
+ arrData = ra
+ arrLen = ra & "Len_0"
else:
- if optBoundsCheck in p.options:
- linefmt(p, cpsStmts, "if ($1 < 0 || $1 >= $2.Field1){ #raiseIndexError2($1,$2.Field1-1); ",
- [rdCharLoc(b), rdLoc(a)]) # BUGFIX: ``>=`` and not ``>``!
- raiseInstr(p, p.s(cpsStmts))
- linefmt p, cpsStmts, "}$n", []
+ arrData = dotField(ra, "Field0")
+ arrLen = dotField(ra, "Field1")
- inheritLocation(d, a)
- putIntoDest(p, d, n,
- ropecg(p.module, "$1.Field0[$2]", [rdLoc(a), rdCharLoc(b)]), a.storage)
+ # emit range check:
+ if optBoundsCheck in p.options:
+ p.s(cpsStmts).addSingleIfStmt(cOp(Or,
+ cOp(LessThan, rcb, cIntValue(0)),
+ cOp(GreaterEqual, rcb, arrLen))): # BUGFIX: ``>=`` and not ``>``!
+ p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "raiseIndexError2"),
+ rcb,
+ cOp(Sub, "NI", arrLen, cIntValue(1)))
+ raiseInstr(p, p.s(cpsStmts))
+
+ inheritLocation(d, a)
+ putIntoDest(p, d, n, subscript(arrData, rcb), a.storage)
proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) =
var a = initLocExpr(p, x)
@@ -1245,23 +1271,29 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) =
var ty = skipTypes(a.t, abstractVarRange)
if ty.kind in {tyRef, tyPtr}:
ty = skipTypes(ty.elementType, abstractVarRange)
+ let rcb = rdCharLoc(b)
# emit range check:
if optBoundsCheck in p.options:
- linefmt(p, cpsStmts,
- "if ($1 < 0 || $1 >= $2){ #raiseIndexError2($1,$2-1); ",
- [rdCharLoc(b), lenExpr(p, a)])
- raiseInstr(p, p.s(cpsStmts))
- linefmt p, cpsStmts, "}$n", []
+ let arrLen = lenExpr(p, a)
+ p.s(cpsStmts).addSingleIfStmt(cOp(Or,
+ cOp(LessThan, rcb, cIntValue(0)),
+ cOp(GreaterEqual, rcb, arrLen))):
+ p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "raiseIndexError2"),
+ rcb,
+ cOp(Sub, "NI", arrLen, cIntValue(1)))
+ raiseInstr(p, p.s(cpsStmts))
if d.k == locNone: d.storage = OnHeap
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
- a.snippet = ropecg(p.module, "(*$1)", [a.snippet])
+ a.snippet = cDeref(a.snippet)
if lfPrepareForMutation in d.flags and ty.kind == tyString and
optSeqDestructors in p.config.globalOptions:
- linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
- putIntoDest(p, d, n,
- ropecg(p.module, "$1$3[$2]", [rdLoc(a), rdCharLoc(b), dataField(p)]), a.storage)
+ let bra = byRefLoc(p, a)
+ p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "nimPrepareStrMutationV2"),
+ bra)
+ let ra = rdLoc(a)
+ putIntoDest(p, d, n, subscript(dataField(p, ra), rcb), a.storage)
proc genBracketExpr(p: BProc; n: PNode; d: var TLoc) =
var ty = skipTypes(n[0].typ, abstractVarRange + tyUserTypeClasses)
@@ -1321,9 +1353,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.snippet = "((" & rdLoc(tmpA) & ")||(" & rdLoc(tmpB) & "))"
+ tmpB.snippet = cOp(Or, rdLoc(tmpA), rdLoc(tmpB))
else:
- tmpB.snippet = "((" & rdLoc(tmpA) & ")&&(" & rdLoc(tmpB) & "))"
+ tmpB.snippet = cOp(And, rdLoc(tmpA), rdLoc(tmpB))
if d.k == locNone:
d = tmpB
else:
@@ -1335,10 +1367,10 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
inc p.splitDecls
expr(p, e[1], tmp)
L = getLabel(p)
- if m == mOr:
- lineF(p, cpsStmts, "if ($1) goto $2;$n", [rdLoc(tmp), L])
- else:
- lineF(p, cpsStmts, "if (!($1)) goto $2;$n", [rdLoc(tmp), L])
+ let rtmp = rdLoc(tmp)
+ let cond = if m == mOr: rtmp else: cOp(Not, rtmp)
+ p.s(cpsStmts).addSingleIfStmt(cond):
+ p.s(cpsStmts).addGoto(L)
expr(p, e[2], tmp)
fixLabel(p, L)
if d.k == locNone:
@@ -1353,29 +1385,42 @@ proc genEcho(p: BProc, n: PNode) =
internalAssert p.config, n.kind == nkBracket
if p.config.target.targetOS == osGenode:
# echo directly to the Genode LOG session
- var args: Rope = ""
- var a: TLoc
- for i, it in n.sons:
- if it.skipConv.kind == nkNilLit:
- args.add(", \"\"")
- elif n.len != 0:
- a = initLocExpr(p, it)
- if i > 0:
- args.add(", ")
- case detectStrVersion(p.module)
- of 2:
- args.add(ropecg(p.module, "Genode::Cstring($1.p->data, $1.len)", [a.rdLoc]))
- else:
- args.add(ropecg(p.module, "Genode::Cstring($1->data, $1->len)", [a.rdLoc]))
p.module.includeHeader("")
p.module.includeHeader("")
- linefmt(p, cpsStmts, """Genode::log($1);$n""", [args])
+ var a: TLoc
+ let logName = "Genode::log"
+ var logCall: CallBuilder
+ p.s(cpsStmts).addStmt():
+ p.s(cpsStmts).addCall(logCall, logName):
+ for it in n.sons:
+ if it.skipConv.kind == nkNilLit:
+ p.s(cpsStmts).addArgument(logCall):
+ p.s(cpsStmts).add("\"\"")
+ elif n.len != 0:
+ a = initLocExpr(p, it)
+ let ra = a.rdLoc
+ let fnName = "Genode::Cstring"
+ p.s(cpsStmts).addArgument(logCall):
+ case detectStrVersion(p.module)
+ of 2:
+ p.s(cpsStmts).addCall(fnName,
+ dotField(derefField(ra, "p"), "data"),
+ dotField(ra, "len"))
+ else:
+ p.s(cpsStmts).addCall(fnName,
+ derefField(ra, "data"),
+ derefField(ra, "len"))
else:
if n.len == 0:
- linefmt(p, cpsStmts, "#echoBinSafe(NIM_NIL, $1);$n", [n.len])
+ p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "echoBinSafe"),
+ "NIM_NIL",
+ cIntValue(n.len))
else:
var a: TLoc = initLocExpr(p, n)
- linefmt(p, cpsStmts, "#echoBinSafe($1, $2);$n", [a.rdLoc, n.len])
+ let ra = a.rdLoc
+ p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "echoBinSafe"),
+ ra,
+ cIntValue(n.len))
when false:
p.module.includeHeader("")
linefmt(p, cpsStmts, "printf($1$2);$n",
@@ -1411,22 +1456,31 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
var a: TLoc
var tmp: TLoc = getTemp(p, e.typ)
var L = 0
- var appends: Rope = ""
- var lens: Rope = ""
+ var appends = newBuilder("")
+ var lens: seq[Snippet] = @[]
for i in 0..$3++;$n", [tmpL.snippet, rdLoc(a), lenField(p)])
- dest.snippet = ropecg(p.module, "$1$3[$2]", [rdLoc(a), tmpL.snippet, dataField(p)])
+ p.s(cpsStmts).addAssignment(tmpL.snippet, lenField(p, ra))
+ p.s(cpsStmts).addIncr(lenField(p, ra))
+ dest.snippet = subscript(dataField(p, ra), tmpL.snippet)
genAssignment(p, dest, b, {needToCopy})
gcUsage(p.config, e)
@@ -1519,15 +1585,16 @@ proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope; needsInit: bool) =
assert refType.kind == tyRef
let bt = refType.elementType
if sizeExpr == "":
- sizeExpr = "sizeof($1)" % [getTypeDesc(p.module, bt)]
+ sizeExpr = cSizeof(getTypeDesc(p.module, bt))
if optTinyRtti in p.config.globalOptions:
- if needsInit:
- b.snippet = ropecg(p.module, "($1) #nimNewObj($2, NIM_ALIGNOF($3))",
- [getTypeDesc(p.module, typ), sizeExpr, getTypeDesc(p.module, bt)])
- else:
- b.snippet = ropecg(p.module, "($1) #nimNewObjUninit($2, NIM_ALIGNOF($3))",
- [getTypeDesc(p.module, typ), sizeExpr, getTypeDesc(p.module, bt)])
+ let fnName = cgsymValue(p.module, if needsInit: "nimNewObj" else: "nimNewObjUninit")
+ var bres = newBuilder("")
+ bres.addCast(getTypeDesc(p.module, typ)):
+ bres.addCall(fnName,
+ sizeExpr,
+ cAlignof(getTypeDesc(p.module, bt)))
+ b.snippet = bres
genAssignment(p, a, b, {})
else:
let ti = genTypeInfoV1(p.module, typ, a.lode.info)
@@ -1541,25 +1608,52 @@ proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope; needsInit: bool) =
"the destructor that is turned into a finalizer needs " &
"to have the 'nimcall' calling convention")
var f: TLoc = initLocExpr(p, newSymNode(op))
- p.module.s[cfsTypeInit3].addf("$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
+ let rf = rdLoc(f)
+ p.module.s[cfsTypeInit3].addDerefFieldAssignment(ti, "finalizer",
+ cCast("void*", rf))
if a.storage == OnHeap and usesWriteBarrier(p.config):
- if canFormAcycle(p.module.g.graph, a.t):
- linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", [a.rdLoc])
- else:
- linefmt(p, cpsStmts, "if ($1) { #nimGCunrefNoCycle($1); $1 = NIM_NIL; }$n", [a.rdLoc])
+ let unrefFnName = cgsymValue(p.module,
+ if canFormAcycle(p.module.g.graph, a.t):
+ "nimGCunrefRC1"
+ else:
+ "nimGCunrefNoCycle")
+ let ra = a.rdLoc
+ p.s(cpsStmts).addSingleIfStmt(ra):
+ p.s(cpsStmts).addCallStmt(unrefFnName, ra)
+ p.s(cpsStmts).addAssignment(ra, "NIM_NIL")
if p.config.selectedGC == gcGo:
# newObjRC1() would clash with unsureAsgnRef() - which is used by gcGo to
# implement the write barrier
- 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])
+ var bres = newBuilder("")
+ bres.addCast(getTypeDesc(p.module, typ)):
+ bres.addCall(cgsymValue(p.module, "newObj"),
+ ti,
+ sizeExpr)
+ b.snippet = bres
+ let raa = addrLoc(p.config, a)
+ let rb = b.rdLoc
+ p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "unsureAsgnRef"),
+ cCast("void**", raa),
+ rb)
else:
# use newObjRC1 as an optimization
- 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])
+ var bres = newBuilder("")
+ bres.addCast(getTypeDesc(p.module, typ)):
+ bres.addCall(cgsymValue(p.module, "newObjRC1"),
+ ti,
+ sizeExpr)
+ b.snippet = bres
+ let ra = a.rdLoc
+ let rb = b.rdLoc
+ p.s(cpsStmts).addAssignment(ra, rb)
else:
- b.snippet = ropecg(p.module, "($1) #newObj($2, $3)", [getTypeDesc(p.module, typ), ti, sizeExpr])
+ var bres = newBuilder("")
+ bres.addCast(getTypeDesc(p.module, typ)):
+ bres.addCall(cgsymValue(p.module, "newObj"),
+ ti,
+ sizeExpr)
+ b.snippet = bres
genAssignment(p, a, b, {})
# set the object type:
genObjectInit(p, cpsStmts, bt, a, constructRefObj)
@@ -1578,26 +1672,47 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope; lenIsZero: bool) =
let seqtype = skipTypes(dest.t, abstractVarRange)
var call: TLoc = initLoc(locExpr, dest.lode, OnHeap)
if dest.storage == OnHeap and usesWriteBarrier(p.config):
- if canFormAcycle(p.module.g.graph, dest.t):
- 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])
+ let unrefFnName = cgsymValue(p.module,
+ if canFormAcycle(p.module.g.graph, dest.t):
+ "nimGCunrefRC1"
+ else:
+ "nimGCunrefNoCycle")
+ let rd = dest.rdLoc
+ p.s(cpsStmts).addSingleIfStmt(rd):
+ p.s(cpsStmts).addCallStmt(unrefFnName, rd)
+ p.s(cpsStmts).addAssignment(rd, "NIM_NIL")
if not lenIsZero:
+ let st = getTypeDesc(p.module, seqtype)
+ let typinfo = genTypeInfoV1(p.module, seqtype, dest.lode.info)
if p.config.selectedGC == gcGo:
# we need the write barrier
- 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])
+ var callRes = newBuilder("")
+ callRes.addCast(st):
+ callRes.addCall(cgsymValue(p.module, "newSeq"), typinfo, length)
+ call.snippet = callRes
+ let rad = addrLoc(p.config, dest)
+ let rc = call.rdLoc
+ p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "unsureAsgnRef"),
+ cCast("void**", rad),
+ rc)
else:
- 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])
+ var callRes = newBuilder("")
+ callRes.addCast(st):
+ callRes.addCall(cgsymValue(p.module, "newSeqRC1"), typinfo, length)
+ call.snippet = callRes
+ let rd = dest.rdLoc
+ let rc = call.rdLoc
+ p.s(cpsStmts).addAssignment(rd, rc)
else:
if lenIsZero:
call.snippet = rope"NIM_NIL"
else:
- call.snippet = ropecg(p.module, "($1) #newSeq($2, $3)", [getTypeDesc(p.module, seqtype),
- genTypeInfoV1(p.module, seqtype, dest.lode.info), length])
+ let st = getTypeDesc(p.module, seqtype)
+ let typinfo = genTypeInfoV1(p.module, seqtype, dest.lode.info)
+ var callRes = newBuilder("")
+ callRes.addCast(st):
+ callRes.addCall(cgsymValue(p.module, "newSeq"), typinfo, length)
+ call.snippet = callRes
genAssignment(p, dest, call, {})
proc genNewSeq(p: BProc, e: PNode) =
@@ -1605,10 +1720,17 @@ proc genNewSeq(p: BProc, e: PNode) =
var b = initLocExpr(p, e[2])
if optSeqDestructors in p.config.globalOptions:
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.elementType),
- getSeqPayloadType(p.module, seqtype)])
+ let ra = a.rdLoc
+ let rb = b.rdLoc
+ let et = getTypeDesc(p.module, seqtype.elementType)
+ let pt = getSeqPayloadType(p.module, seqtype)
+ p.s(cpsStmts).addFieldAssignment(ra, "len", rb)
+ p.s(cpsStmts).addFieldAssignmentWithValue(ra, "p"):
+ p.s(cpsStmts).addCast(ptrType(pt)):
+ p.s(cpsStmts).addCall(cgsymValue(p.module, "newSeqPayload"),
+ rb,
+ cSizeof(et),
+ cAlignof(et))
else:
let lenIsZero = e[2].kind == nkIntLit and e[2].intVal == 0
genNewSeqAux(p, a, b.rdLoc, lenIsZero)
@@ -1619,16 +1741,26 @@ proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) =
var a: TLoc = initLocExpr(p, e[1])
if optSeqDestructors in p.config.globalOptions:
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),
- ])
+ let rd = d.rdLoc
+ let ra = a.rdLoc
+ let et = getTypeDesc(p.module, seqtype.elementType)
+ let pt = getSeqPayloadType(p.module, seqtype)
+ p.s(cpsStmts).addFieldAssignment(rd, "len", cIntValue(0))
+ p.s(cpsStmts).addFieldAssignmentWithValue(rd, "p"):
+ p.s(cpsStmts).addCast(ptrType(pt)):
+ p.s(cpsStmts).addCall(cgsymValue(p.module, "newSeqPayloadUninit"),
+ ra,
+ cSizeof(et),
+ cAlignof(et))
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),
- genTypeInfoV1(p.module, seqtype, e.info), a.rdLoc]))
+ let ra = a.rdLoc
+ var dres = newBuilder("")
+ dres.addCast(getTypeDesc(p.module, seqtype)):
+ dres.addCall(cgsymValue(p.module, "nimNewSeqOfCap"),
+ genTypeInfoV1(p.module, seqtype, e.info),
+ ra)
+ putIntoDest(p, d, e, dres)
gcUsage(p.config, e)
proc rawConstExpr(p: BProc, n: PNode; d: var TLoc) =
@@ -1664,8 +1796,7 @@ proc genFieldObjConstr(p: BProc; ty: PType; useTemp, isRef: bool; nField, val, c
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)
+ tmp2.snippet = dotField(tmp2.snippet, field.loc.snippet)
if useTemp:
tmp2.k = locTemp
tmp2.storage = if isRef: OnHeap else: OnStack
@@ -1710,7 +1841,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
if isRef:
rawGenNew(p, tmp, "", needsInit = nfAllFieldsSet notin e.flags)
t = t.elementType.skipTypes(abstractInstOwned)
- r = "(*$1)" % [r]
+ r = cDeref(r)
gcUsage(p.config, e)
elif needsZeroMem:
constructLoc(p, tmp)
@@ -1750,21 +1881,27 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) =
elif d.k == locNone:
d = getTemp(p, n.typ)
- var lit = newRopeAppender()
- intLiteral(n.len, lit)
+ let lit = cIntLiteral(n.len)
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.elementType),
- getSeqPayloadType(p.module, seqtype)])
+ let rd = rdLoc dest[]
+ let et = getTypeDesc(p.module, seqtype.elementType)
+ let pt = getSeqPayloadType(p.module, seqtype)
+ p.s(cpsStmts).addFieldAssignment(rd, "len", lit)
+ p.s(cpsStmts).addFieldAssignmentWithValue(rd, "p"):
+ p.s(cpsStmts).addCast(ptrType(pt)):
+ p.s(cpsStmts).addCall(cgsymValue(p.module, "newSeqPayload"),
+ lit,
+ cSizeof(et),
+ cAlignof(et))
else:
# generate call to newSeq before adding the elements per hand:
genNewSeqAux(p, dest[], lit, n.len == 0)
for i in 0..