cbuilder: ccgexprs sweep part 1, basic if stmts (#24381)

Most of what ccgexprs uses is now ported to cbuilder, so this PR makes
around ~25% of ccgexprs use it, along with adding `if` stmts (no
`while`/`switch` and `for` which is only used as `for (tmp = a; tmp < b;
tmp++)`). The `if` builder does not add indents for blocks since we
can't make `Builder` an object yet rather than an alias to `string`,
this will likely be one of the last refactors.

Somewhat unrelated but `ccgtypes` is not ready yet because proc
signatures are not implemented.
This commit is contained in:
metagn
2024-10-31 09:50:05 +03:00
committed by GitHub
parent 5e56f0a356
commit 658c9da33e
6 changed files with 475 additions and 314 deletions

View File

@@ -27,6 +27,50 @@ import std/formatfloat
proc addFloatValue(builder: var Builder, val: float) =
builder.addFloat(val)
proc cFloatValue(val: float): Snippet =
result = ""
result.addFloat(val)
template cFloatValue(val: float): Snippet = $val
proc int64Literal(i: BiggestInt; result: var Builder) =
if i > low(int64):
result.add "IL64($1)" % [rope(i)]
else:
result.add "(IL64(-9223372036854775807) - IL64(1))"
proc uint64Literal(i: uint64; result: var Builder) =
result.add rope($i & "ULL")
proc intLiteral(i: BiggestInt; result: var Builder) =
if i > low(int32) and i <= high(int32):
result.addIntValue(i)
elif i == low(int32):
# Nim has the same bug for the same reasons :-)
result.add "(-2147483647 -1)"
elif i > low(int64):
result.add "IL64($1)" % [rope(i)]
else:
result.add "(IL64(-9223372036854775807) - IL64(1))"
proc intLiteral(i: Int128; result: var Builder) =
intLiteral(toInt64(i), result)
proc cInt64Literal(i: BiggestInt): Snippet =
if i > low(int64):
result = "IL64($1)" % [rope(i)]
else:
result = "(IL64(-9223372036854775807) - IL64(1))"
proc cUint64Literal(i: uint64): Snippet =
result = $i & "ULL"
proc cIntLiteral(i: BiggestInt): Snippet =
if i > low(int32) and i <= high(int32):
result = rope(i)
elif i == low(int32):
# Nim has the same bug for the same reasons :-)
result = "(-2147483647 -1)"
elif i > low(int64):
result = "IL64($1)" % [rope(i)]
else:
result = "(IL64(-9223372036854775807) - IL64(1))"
proc cIntLiteral(i: Int128): Snippet =
result = cIntLiteral(toInt64(i))

View File

@@ -2,8 +2,15 @@
# XXX add stuff like NI, NIM_NIL as constants
proc constType(t: Snippet): Snippet =
# needs manipulation of `t` in nifc
"NIM_CONST " & t
proc constPtrType(t: Snippet): Snippet =
t & "* NIM_CONST"
proc ptrConstType(t: Snippet): Snippet =
"NIM_CONST " & t & "*"
proc ptrType(t: Snippet): Snippet =
t & "*"
@@ -26,6 +33,11 @@ proc wrapPar(value: Snippet): Snippet =
# used for expression group, no-op on sexp
"(" & value & ")"
proc removeSinglePar(value: Snippet): Snippet =
# removes a single paren layer expected to exist, to silence Wparentheses-equality
assert value[0] == '(' and value[^1] == ')'
value[1..^2]
template addCast(builder: var Builder, typ: Snippet, valueBody: typed) =
## adds a cast to `typ` with value built by `valueBody`
builder.add "(("
@@ -75,16 +87,26 @@ template addCall(builder: var Builder, call: out CallBuilder, callee: Snippet, b
body
finishCallBuilder(builder, call)
proc addNullaryCall(builder: var Builder, callee: Snippet) =
builder.add(callee)
builder.add("()")
proc addUnaryCall(builder: var Builder, callee: Snippet, arg: Snippet) =
proc addCall(builder: var Builder, callee: Snippet, args: varargs[Snippet]) =
builder.add(callee)
builder.add("(")
builder.add(arg)
if args.len != 0:
builder.add(args[0])
for i in 1 ..< args.len:
builder.add(", ")
builder.add(args[i])
builder.add(")")
proc cCall(callee: Snippet, args: varargs[Snippet]): Snippet =
result = callee
result.add("(")
if args.len != 0:
result.add(args[0])
for i in 1 ..< args.len:
result.add(", ")
result.add(args[i])
result.add(")")
proc addSizeof(builder: var Builder, val: Snippet) =
builder.add("sizeof(")
builder.add(val)

View File

@@ -1,28 +1,94 @@
template addAssignment(builder: var Builder, lhs: Snippet, valueBody: typed) =
template addAssignmentWithValue(builder: var Builder, lhs: Snippet, valueBody: typed) =
builder.add(lhs)
builder.add(" = ")
valueBody
builder.add(";\n")
template addFieldAssignment(builder: var Builder, lhs: Snippet, name: string, valueBody: typed) =
template addFieldAssignmentWithValue(builder: var Builder, lhs: Snippet, name: string, valueBody: typed) =
builder.add(lhs)
builder.add("." & name & " = ")
valueBody
builder.add(";\n")
template addDerefFieldAssignment(builder: var Builder, lhs: Snippet, name: string, valueBody: typed) =
template addAssignment(builder: var Builder, lhs, rhs: Snippet) =
builder.addAssignmentWithValue(lhs):
builder.add(rhs)
template addFieldAssignment(builder: var Builder, lhs: Snippet, name: string, rhs: Snippet) =
builder.addFieldAssignmentWithValue(lhs, name):
builder.add(rhs)
template addMutualFieldAssignment(builder: var Builder, lhs, rhs: Snippet, name: string) =
builder.addFieldAssignmentWithValue(lhs, name):
builder.add(rhs)
builder.add("." & name)
template addAssignment(builder: var Builder, lhs: Snippet, rhs: int | int64 | uint64 | Int128) =
builder.addAssignmentWithValue(lhs):
builder.addIntValue(rhs)
template addFieldAssignment(builder: var Builder, lhs: Snippet, name: string, rhs: int | int64 | uint64 | Int128) =
builder.addFieldAssignmentWithValue(lhs, name):
builder.addIntValue(rhs)
template addDerefFieldAssignment(builder: var Builder, lhs: Snippet, name: string, rhs: Snippet) =
builder.add(lhs)
builder.add("->" & name & " = ")
valueBody
builder.add(rhs)
builder.add(";\n")
template addSubscriptAssignment(builder: var Builder, lhs: Snippet, index: Snippet, valueBody: typed) =
template addSubscriptAssignment(builder: var Builder, lhs: Snippet, index: Snippet, rhs: Snippet) =
builder.add(lhs)
builder.add("[" & index & "] = ")
valueBody
builder.add(rhs)
builder.add(";\n")
template addStmt(builder: var Builder, stmtBody: typed) =
## makes an expression built by `stmtBody` into a statement
stmtBody
builder.add(";\n")
proc addCallStmt(builder: var Builder, callee: Snippet, args: varargs[Snippet]) =
builder.addStmt():
builder.addCall(callee, args)
# XXX blocks need indent tracker in `Builder` object
template addSingleIfStmt(builder: var Builder, cond: Snippet, body: typed) =
builder.add("if (")
builder.add(cond)
builder.add(") {\n")
body
builder.add("}\n")
template addSingleIfStmtWithCond(builder: var Builder, condBody: typed, body: typed) =
builder.add("if (")
condBody
builder.add(") {\n")
body
builder.add("}\n")
type IfStmt = object
needsElse: bool
template addIfStmt(builder: var Builder, stmt: out IfStmt, body: typed) =
stmt = IfStmt(needsElse: false)
body
builder.add("\n")
template addElifBranch(builder: var Builder, stmt: var IfStmt, cond: Snippet, body: typed) =
if stmt.needsElse:
builder.add(" else ")
else:
stmt.needsElse = true
builder.add("if (")
builder.add(cond)
builder.add(") {\n")
body
builder.add("}")
template addElseBranch(builder: var Builder, stmt: var IfStmt, body: typed) =
assert stmt.needsElse
builder.add(" else {\n")
body
builder.add("}")

View File

@@ -20,29 +20,6 @@ proc getNullValueAuxT(p: BProc; orig, t: PType; obj, constOrNil: PNode,
proc rdSetElemLoc(conf: ConfigRef; a: TLoc, typ: PType; result: var Rope)
proc int64Literal(i: BiggestInt; result: var Builder) =
if i > low(int64):
result.add "IL64($1)" % [rope(i)]
else:
result.add "(IL64(-9223372036854775807) - IL64(1))"
proc uint64Literal(i: uint64; result: var Builder) =
result.add rope($i & "ULL")
proc intLiteral(i: BiggestInt; result: var Builder) =
if i > low(int32) and i <= high(int32):
result.add rope(i)
elif i == low(int32):
# Nim has the same bug for the same reasons :-)
result.add "(-2147483647 -1)"
elif i > low(int64):
result.add "IL64($1)" % [rope(i)]
else:
result.add "(IL64(-9223372036854775807) - IL64(1))"
proc intLiteral(i: Int128; result: var Builder) =
intLiteral(toInt64(i), result)
proc genLiteral(p: BProc, n: PNode, ty: PType; result: var Builder) =
case n.kind
of nkCharLit..nkUInt64Lit:
@@ -196,15 +173,21 @@ proc canMove(p: BProc, n: PNode; dest: TLoc): bool =
# echo n.info, " optimized ", n
# result = false
template simpleAsgn(builder: var Builder, dest, src: TLoc) =
let rd = rdLoc(dest)
let rs = rdLoc(src)
builder.addAssignment(rd, rs)
proc genRefAssign(p: BProc, dest, src: TLoc) =
if (dest.storage == OnStack and p.config.selectedGC != gcGo) or not usesWriteBarrier(p.config):
linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
elif dest.storage == OnHeap:
linefmt(p, cpsStmts, "#asgnRef((void**) $1, $2);$n",
[addrLoc(p.config, dest), rdLoc(src)])
simpleAsgn(p.s(cpsStmts), dest, src)
else:
linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);$n",
[addrLoc(p.config, dest), rdLoc(src)])
let fnName =
if dest.storage == OnHeap: cgsymValue(p.module, "asgnRef")
else: cgsymValue(p.module, "unsureAsgnRef")
let rad = addrLoc(p.config, dest)
let rs = rdLoc(src)
p.s(cpsStmts).addCallStmt(fnName, cCast("void**", rad), rs)
proc asgnComplexity(n: PNode): int =
if n != nil:
@@ -271,21 +254,31 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
# here for this flag, where it is reasonably safe to do so
# (for objects, etc.):
if optSeqDestructors in p.config.globalOptions:
linefmt(p, cpsStmts,
"$1 = $2;$n",
[rdLoc(dest), rdLoc(src)])
simpleAsgn(p.s(cpsStmts), dest, 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)])
let rad = addrLoc(p.config, dest)
let ras = addrLoc(p.config, src)
let rd = rdLoc(dest)
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "nimCopyMem"),
cCast("void*", rad),
cCast(ptrConstType("void"), ras),
cSizeof(rd))
else:
linefmt(p, cpsStmts, "#genericShallowAssign((void*)$1, (void*)$2, $3);$n",
[addrLoc(p.config, dest), addrLoc(p.config, src), genTypeInfoV1(p.module, dest.t, dest.lode.info)])
let rad = addrLoc(p.config, dest)
let ras = addrLoc(p.config, src)
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "genericShallowAssign"),
cCast("void*", rad),
cCast("void*", ras),
genTypeInfoV1(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), genTypeInfoV1(p.module, dest.t, dest.lode.info)])
let rad = addrLoc(p.config, dest)
let ras = addrLoc(p.config, src)
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "genericAssign"),
cCast("void*", rad),
cCast("void*", ras),
genTypeInfoV1(p.module, dest.t, dest.lode.info))
proc genOpenArrayConv(p: BProc; d: TLoc; a: TLoc; flags: TAssignmentFlags) =
assert d.k != locNone
@@ -296,29 +289,48 @@ proc genOpenArrayConv(p: BProc; d: TLoc; a: TLoc; flags: TAssignmentFlags) =
if reifiedOpenArray(a.lode):
if needTempForOpenArray in flags:
var tmp: TLoc = getTemp(p, a.t)
linefmt(p, cpsStmts, "$2 = $1; $n",
[a.rdLoc, tmp.rdLoc])
linefmt(p, cpsStmts, "$1.Field0 = $2.Field0; $1.Field1 = $2.Field1;$n",
[rdLoc(d), tmp.rdLoc])
let rtmp = tmp.rdLoc
let ra = a.rdLoc
p.s(cpsStmts).addAssignment(rtmp, ra)
let rd = d.rdLoc
p.s(cpsStmts).addMutualFieldAssignment(rd, rtmp, "Field0")
p.s(cpsStmts).addMutualFieldAssignment(rd, rtmp, "Field1")
else:
linefmt(p, cpsStmts, "$1.Field0 = $2.Field0; $1.Field1 = $2.Field1;$n",
[rdLoc(d), a.rdLoc])
let rd = d.rdLoc
let ra = a.rdLoc
p.s(cpsStmts).addMutualFieldAssignment(rd, ra, "Field0")
p.s(cpsStmts).addMutualFieldAssignment(rd, ra, "Field1")
else:
linefmt(p, cpsStmts, "$1.Field0 = $2; $1.Field1 = $2Len_0;$n",
[rdLoc(d), a.rdLoc])
let rd = d.rdLoc
let ra = a.rdLoc
p.s(cpsStmts).addFieldAssignment(rd, "Field0", ra)
p.s(cpsStmts).addFieldAssignment(rd, "Field1", ra & "Len_0")
of tySequence:
linefmt(p, cpsStmts, "$1.Field0 = ($5) ? ($2$3) : NIM_NIL; $1.Field1 = $4;$n",
[rdLoc(d), a.rdLoc, dataField(p), lenExpr(p, a), dataFieldAccessor(p, a.rdLoc)])
let rd = d.rdLoc
let ra = a.rdLoc
let la = lenExpr(p, a)
p.s(cpsStmts).addFieldAssignment(rd, "Field0",
cIfExpr(dataFieldAccessor(p, ra), dataField(p, ra), "NIM_NIL"))
p.s(cpsStmts).addFieldAssignment(rd, "Field1", la)
of tyArray:
linefmt(p, cpsStmts, "$1.Field0 = $2; $1.Field1 = $3;$n",
[rdLoc(d), rdLoc(a), rope(lengthOrd(p.config, a.t))])
let rd = d.rdLoc
let ra = a.rdLoc
p.s(cpsStmts).addFieldAssignment(rd, "Field0", ra)
p.s(cpsStmts).addFieldAssignment(rd, "Field1", lengthOrd(p.config, a.t))
of tyString:
let etyp = skipTypes(a.t, abstractInst)
if etyp.kind in {tyVar} and optSeqDestructors in p.config.globalOptions:
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
let bra = byRefLoc(p, a)
p.s(cpsStmts).addCallStmt(
cgsymValue(p.module, "nimPrepareStrMutationV2"),
bra)
linefmt(p, cpsStmts, "$1.Field0 = ($5) ? ($2$3) : NIM_NIL; $1.Field1 = $4;$n",
[rdLoc(d), a.rdLoc, dataField(p), lenExpr(p, a), dataFieldAccessor(p, a.rdLoc)])
let rd = d.rdLoc
let ra = a.rdLoc
p.s(cpsStmts).addFieldAssignment(rd, "Field0",
cIfExpr(dataFieldAccessor(p, ra), dataField(p, ra), "NIM_NIL"))
let la = lenExpr(p, a)
p.s(cpsStmts).addFieldAssignment(rd, "Field1", la)
else:
internalError(p.config, a.lode.info, "cannot handle " & $a.t.kind)
@@ -327,7 +339,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
# 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)])
simpleAsgn(p.s(cpsStmts), dest, src)
return
let ty = skipTypes(dest.t, abstractRange + tyUserTypeClasses + {tyStatic})
case ty.kind
@@ -339,9 +351,12 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
elif (needToCopy notin flags and src.storage != OnStatic) or canMove(p, src.lode, dest):
genRefAssign(p, dest, src)
else:
linefmt(p, cpsStmts, "#genericSeqAssign($1, $2, $3);$n",
[addrLoc(p.config, dest), rdLoc(src),
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
let rad = addrLoc(p.config, dest)
let rs = rdLoc(src)
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "genericSeqAssign"),
rad,
rs,
genTypeInfoV1(p.module, dest.t, dest.lode.info))
of tyString:
if optSeqDestructors in p.config.globalOptions:
genGenericAsgn(p, dest, src, flags)
@@ -349,35 +364,48 @@ 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])
let rd = rdLoc(dest)
let rs = rdLoc(src)
p.s(cpsStmts).addAssignmentWithValue(rd):
p.s(cpsStmts).addCall(cgsymValue(p.module, "copyString"), rs)
elif dest.storage == OnHeap:
let rd = rdLoc(dest)
let rs = rdLoc(src)
# we use a temporary to care for the dreaded self assignment:
var tmp: TLoc = getTemp(p, ty)
linefmt(p, cpsStmts, "$3 = $1; $1 = #copyStringRC1($2);$n",
[dest.rdLoc, src.rdLoc, tmp.rdLoc])
linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", [tmp.rdLoc])
let rtmp = rdLoc(tmp)
p.s(cpsStmts).addAssignment(rtmp, rd)
p.s(cpsStmts).addAssignmentWithValue(rd):
p.s(cpsStmts).addCall(cgsymValue(p.module, "copyStringRC1"), rs)
p.s(cpsStmts).addSingleIfStmt(rtmp):
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "nimGCunrefNoCycle"), rtmp)
else:
linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
[addrLoc(p.config, dest), rdLoc(src)])
let rad = addrLoc(p.config, dest)
let rs = rdLoc(src)
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "unsureAsgnRef"),
cCast("void**", rad),
cCall(cgsymValue(p.module, "copyString"), rs))
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)])
let rd = rdLoc(dest)
let rs = rdLoc(src)
p.s(cpsStmts).addMutualFieldAssignment(rd, rs, "ClP_0")
else:
linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
simpleAsgn(p.s(cpsStmts), dest, src)
of tyTuple:
if containsGarbageCollectedRef(dest.t):
if dest.t.kidsLen <= 4: genOptAsgnTuple(p, dest, src, flags)
else: genGenericAsgn(p, dest, src, flags)
else:
linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
simpleAsgn(p.s(cpsStmts), dest, src)
of tyObject:
# XXX: check for subtyping?
if ty.isImportedCppType:
linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
simpleAsgn(p.s(cpsStmts), dest, src)
elif not isObjLackingTypeField(ty):
genGenericAsgn(p, dest, src, flags)
elif containsGarbageCollectedRef(ty):
@@ -389,48 +417,60 @@ 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)])
simpleAsgn(p.s(cpsStmts), dest, src)
of tyArray:
if containsGarbageCollectedRef(dest.t) and p.config.selectedGC notin {gcArc, gcAtomicArc, gcOrc, gcHooks}:
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)])
let rd = rdLoc(dest)
let rs = rdLoc(src)
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "nimCopyMem"),
cCast("void*", rd),
cCast(ptrConstType("void"), rs),
cSizeof(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 reifiedOpenArray(dest.lode):
genOpenArrayConv(p, dest, src, flags)
elif containsGarbageCollectedRef(dest.t):
linefmt(p, cpsStmts, # XXX: is this correct for arrays?
"#genericAssignOpenArray((void*)$1, (void*)$2, $1Len_0, $3);$n",
[addrLoc(p.config, dest), addrLoc(p.config, src),
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
let rad = addrLoc(p.config, dest)
let ras = addrLoc(p.config, src)
# XXX: is this correct for arrays?
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "genericAssignOpenArray"),
cCast("void*", rad),
cCast("void*", ras),
rad & "Len_0",
genTypeInfoV1(p.module, dest.t, dest.lode.info))
else:
linefmt(p, cpsStmts,
simpleAsgn(p.s(cpsStmts), dest, src)
#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)])
#"#nimCopyMem((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len_0);\n")
of tySet:
if mapSetType(p.config, ty) == ctArray:
linefmt(p, cpsStmts, "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, $3);$n",
[rdLoc(dest), rdLoc(src), getSize(p.config, dest.t)])
let rd = rdLoc(dest)
let rs = rdLoc(src)
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "nimCopyMem"),
cCast("void*", rd),
cCast(ptrConstType("void"), rs),
cIntValue(getSize(p.config, dest.t)))
else:
linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
simpleAsgn(p.s(cpsStmts), dest, src)
of tyPtr, tyPointer, tyChar, tyBool, tyEnum, tyCstring,
tyInt..tyUInt64, tyRange, tyVar, tyLent, tyNil:
linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
simpleAsgn(p.s(cpsStmts), dest, 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), getSize(p.config, dest.t),
makeCString(toFullPath(p.config, p.currLineInfo)),
p.currLineInfo.safeLineNm])
let rad = addrLoc(p.config, dest)
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "memTrackerWrite"),
cCast("void*", rad),
cIntValue(getSize(p.config, dest.t)),
makeCString(toFullPath(p.config, p.currLineInfo)),
cIntValue(p.currLineInfo.safeLineNm))
proc genDeepCopy(p: BProc; dest, src: TLoc) =
template addrLocOrTemp(a: TLoc): Rope =
@@ -445,33 +485,48 @@ proc genDeepCopy(p: BProc; dest, src: TLoc) =
case ty.kind
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),
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
let rad = addrLoc(p.config, dest)
let rats = addrLocOrTemp(src)
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "genericDeepCopy"),
cCast("void*", rad),
cCast("void*", rats),
genTypeInfoV1(p.module, dest.t, dest.lode.info))
of tySequence, tyString:
if optTinyRtti in p.config.globalOptions:
linefmt(p, cpsStmts, "#genericDeepCopy((void*)$1, (void*)$2, $3);$n",
[addrLoc(p.config, dest), addrLocOrTemp(src),
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
let rad = addrLoc(p.config, dest)
let rats = addrLocOrTemp(src)
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "genericDeepCopy"),
cCast("void*", rad),
cCast("void*", rats),
genTypeInfoV1(p.module, dest.t, dest.lode.info))
else:
linefmt(p, cpsStmts, "#genericSeqDeepCopy($1, $2, $3);$n",
[addrLoc(p.config, dest), rdLoc(src),
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
let rad = addrLoc(p.config, dest)
let rs = rdLoc(src)
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "genericSeqDeepCopy"),
rad,
rs,
genTypeInfoV1(p.module, dest.t, dest.lode.info))
of tyOpenArray, tyVarargs:
let source = addrLocOrTemp(src)
linefmt(p, cpsStmts,
"#genericDeepCopyOpenArray((void*)$1, (void*)$2, $2->Field1, $3);$n",
[addrLoc(p.config, dest), source,
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
let rad = addrLoc(p.config, dest)
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "genericDeepCopyOpenArray"),
cCast("void*", rad),
cCast("void*", source),
derefField(source, "Field1"),
genTypeInfoV1(p.module, dest.t, dest.lode.info))
of tySet:
if mapSetType(p.config, ty) == ctArray:
linefmt(p, cpsStmts, "#nimCopyMem((void*)$1, (NIM_CONST void*)$2, $3);$n",
[rdLoc(dest), rdLoc(src), getSize(p.config, dest.t)])
let rd = rdLoc(dest)
let rs = rdLoc(src)
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "nimCopyMem"),
cCast("void*", rd),
cCast(ptrConstType("void"), rs),
cIntValue(getSize(p.config, dest.t)))
else:
linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
simpleAsgn(p.s(cpsStmts), dest, src)
of tyPointer, tyChar, tyBool, tyEnum, tyCstring,
tyInt..tyUInt64, tyRange, tyVar, tyLent:
linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
simpleAsgn(p.s(cpsStmts), dest, src)
else: internalError(p.config, "genDeepCopy: " & $ty.kind)
proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc) =
@@ -519,7 +574,9 @@ proc binaryStmtAddr(p: BProc, e: PNode, d: var TLoc, cpname: string) =
if d.k != locNone: internalError(p.config, e.info, "binaryStmtAddr")
var a = initLocExpr(p, e[1])
var b = initLocExpr(p, e[2])
lineCg(p, cpsStmts, "#$1($2, $3);$n", [cpname, byRefLoc(p, a), rdLoc(b)])
let bra = byRefLoc(p, a)
let rb = rdLoc(b)
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, cpname), bra, rb)
template unaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
if d.k != locNone: internalError(p.config, e.info, "unaryStmt")
@@ -554,21 +611,28 @@ template binaryArithOverflowRaw(p: BProc, t: PType, a, b: TLoc;
let storage = if size < p.config.target.intSize: rope("NI")
else: getTypeDesc(p.module, t)
var result = getTempName(p.module)
linefmt(p, cpsLocals, "$1 $2;$n", [storage, result])
lineCg(p, cpsStmts, "if (#$2($3, $4, &$1)) { #raiseOverflow(); ",
[result, cpname, rdCharLoc(a), rdCharLoc(b)])
raiseInstr(p, p.s(cpsStmts))
linefmt p, cpsStmts, "};$n", []
p.s(cpsLocals).addVar(kind = Local, name = result, typ = storage)
let rca = rdCharLoc(a)
let rcb = rdCharLoc(b)
p.s(cpsStmts).addSingleIfStmtWithCond():
p.s(cpsStmts).addCall(cgsymValue(p.module, cpname),
rca,
rcb,
cAddr(result))
do:
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "raiseOverflow"))
raiseInstr(p, p.s(cpsStmts))
if size < p.config.target.intSize or t.kind in {tyRange, tyEnum}:
var first = newRopeAppender()
intLiteral(firstOrd(p.config, t), first)
var last = newRopeAppender()
intLiteral(lastOrd(p.config, t), last)
linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3){ #raiseOverflow(); ",
[result, first, last])
raiseInstr(p, p.s(cpsStmts))
linefmt p, cpsStmts, "}$n", []
let first = cIntLiteral(firstOrd(p.config, t))
let last = cIntLiteral(lastOrd(p.config, t))
p.s(cpsStmts).addSingleIfStmtWithCond():
p.s(cpsStmts).addOp(Or,
cOp(LessThan, result, first),
cOp(GreaterThan, result, last))
do:
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "raiseOverflow"))
raiseInstr(p, p.s(cpsStmts))
result
@@ -584,7 +648,7 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
"nimMulInt64", "nimDivInt64", "nimModInt64",
"nimAddInt64", "nimSubInt64"
]
opr: array[mAddI..mPred, string] = ["+", "-", "*", "/", "%", "+", "-"]
opr: array[mAddI..mPred, TypedBinaryOp] = [Add, Sub, Mul, Div, Mod, Add, Sub]
assert(e[1].typ != nil)
assert(e[2].typ != nil)
var a = initLocExpr(p, e[1])
@@ -593,7 +657,8 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
# later via 'chckRange'
let t = e.typ.skipTypes(abstractRange)
if optOverflowCheck notin p.options or (m in {mSucc, mPred} and t.kind in {tyUInt..tyUInt64}):
let res = "($1)($2 $3 $4)" % [getTypeDesc(p.module, e.typ), rdLoc(a), rope(opr[m]), rdLoc(b)]
let typ = getTypeDesc(p.module, e.typ)
let res = cCast(typ, cOp(opr[m], typ, rdLoc(a), rdLoc(b)))
putIntoDest(p, d, e, res)
else:
# we handle div by zero here so that we know that the compilerproc's
@@ -606,15 +671,17 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
if e[2].kind in {nkIntLit..nkInt64Lit}:
needsOverflowCheck = e[2].intVal == -1
if canBeZero:
linefmt(p, cpsStmts, "if ($1 == 0){ #raiseDivByZero(); ", [rdLoc(b)])
raiseInstr(p, p.s(cpsStmts))
linefmt(p, cpsStmts, "}$n", [])
# remove extra paren from `==` op here to avoid Wparentheses-equality:
p.s(cpsStmts).addSingleIfStmt(removeSinglePar(cOp(Equal, rdLoc(b), cIntValue(0)))):
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "raiseDivByZero"))
raiseInstr(p, p.s(cpsStmts))
if needsOverflowCheck:
let res = binaryArithOverflowRaw(p, t, a, b,
if t.kind == tyInt64: prc64[m] else: prc[m])
putIntoDest(p, d, e, "($#)($#)" % [getTypeDesc(p.module, e.typ), res])
putIntoDest(p, d, e, cCast(getTypeDesc(p.module, e.typ), res))
else:
let res = "($1)(($2) $3 ($4))" % [getTypeDesc(p.module, e.typ), rdLoc(a), rope(opr[m]), rdLoc(b)]
let typ = getTypeDesc(p.module, e.typ)
let res = cCast(typ, cOp(opr[m], typ, wrapPar(rdLoc(a)), wrapPar(rdLoc(b))))
putIntoDest(p, d, e, res)
proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
@@ -622,21 +689,25 @@ proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
assert(e[1].typ != nil)
var a: TLoc = initLocExpr(p, e[1])
t = skipTypes(e.typ, abstractRange)
let ra = rdLoc(a)
if optOverflowCheck in p.options:
var first = newRopeAppender()
intLiteral(firstOrd(p.config, t), first)
linefmt(p, cpsStmts, "if ($1 == $2){ #raiseOverflow(); ",
[rdLoc(a), first])
raiseInstr(p, p.s(cpsStmts))
linefmt p, cpsStmts, "}$n", []
let first = cIntLiteral(firstOrd(p.config, t))
# remove extra paren from `==` op here to avoid Wparentheses-equality:
p.s(cpsStmts).addSingleIfStmt(removeSinglePar(cOp(Equal, ra, first))):
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "raiseOverflow"))
raiseInstr(p, p.s(cpsStmts))
case m
of mUnaryMinusI:
putIntoDest(p, d, e, "((NI$2)-($1))" % [rdLoc(a), rope(getSize(p.config, t) * 8)])
let typ = "NI" & rope(getSize(p.config, t) * 8)
putIntoDest(p, d, e, cCast(typ, cOp(Neg, typ, ra)))
of mUnaryMinusI64:
putIntoDest(p, d, e, "-($1)" % [rdLoc(a)])
putIntoDest(p, d, e, cOp(Neg, getTypeDesc(p.module, t), ra))
of mAbsI:
putIntoDest(p, d, e, "($1 > 0? ($1) : -($1))" % [rdLoc(a)])
putIntoDest(p, d, e,
cIfExpr(cOp(GreaterThan, ra, cIntValue(0)),
wrapPar(ra),
cOp(Neg, getTypeDesc(p.module, t), ra)))
else:
assert(false, $m)
@@ -770,18 +841,25 @@ proc genEqProc(p: BProc, e: PNode, d: var TLoc) =
assert(e[2].typ != nil)
var a = initLocExpr(p, e[1])
var b = initLocExpr(p, e[2])
let ra = rdLoc(a)
let rb = rdLoc(b)
if a.t.skipTypes(abstractInstOwned).callConv == ccClosure:
putIntoDest(p, d, e,
"($1.ClP_0 == $2.ClP_0 && $1.ClE_0 == $2.ClE_0)" % [rdLoc(a), rdLoc(b)])
putIntoDest(p, d, e, cOp(And,
cOp(Equal, dotField(ra, "ClP_0"), dotField(rb, "ClP_0")),
cOp(Equal, dotField(ra, "ClE_0"), dotField(rb, "ClE_0"))))
else:
putIntoDest(p, d, e, "($1 == $2)" % [rdLoc(a), rdLoc(b)])
putIntoDest(p, d, e, cOp(Equal, ra, rb))
proc genIsNil(p: BProc, e: PNode, d: var TLoc) =
let t = skipTypes(e[1].typ, abstractRange)
var a: TLoc = initLocExpr(p, e[1])
let ra = rdLoc(a)
var res = ""
if t.kind == tyProc and t.callConv == ccClosure:
unaryExpr(p, e, d, "($1.ClP_0 == 0)")
res = cOp(Equal, dotField(ra, "ClP_0"), cIntValue(0))
else:
unaryExpr(p, e, d, "($1 == 0)")
res = cOp(Equal, ra, cIntValue(0))
putIntoDest(p, d, e, res)
proc unaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
var
@@ -867,7 +945,7 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc) =
# so the '&' and '*' cancel out:
putIntoDest(p, d, e, rdLoc(a), a.storage)
else:
putIntoDest(p, d, e, "(*$1)" % [rdLoc(a)], a.storage)
putIntoDest(p, d, e, cDeref(rdLoc(a)), a.storage)
proc cowBracket(p: BProc; n: PNode) =
if n.kind == nkBracketExpr and optSeqDestructors in p.config.globalOptions:
@@ -1749,8 +1827,7 @@ proc genNewFinalize(p: BProc, e: PNode) =
var f = initLocExpr(p, e[2])
b = initLoc(locExpr, a.lode, OnHeap)
ti = genTypeInfo(p.config, p.module, refType, e.info)
p.module.s[cfsTypeInit3].addDerefFieldAssignment(ti, "finalizer"):
p.module.s[cfsTypeInit3].add(cCast("void*", rdLoc(f)))
p.module.s[cfsTypeInit3].addDerefFieldAssignment(ti, "finalizer", cCast("void*", rdLoc(f)))
b.snippet = ropecg(p.module, "($1) #newObj($2, sizeof($3))", [
getTypeDesc(p.module, refType),
ti, getTypeDesc(p.module, skipTypes(refType.elementType, abstractRange))])
@@ -1973,8 +2050,7 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
var a = initLocExpr(p, e[1])
var x = lenExpr(p, a)
if op == mHigh: x = "($1-1)" % [x]
p.s(cpsStmts).addAssignment(tmp.snippet):
p.s(cpsStmts).add(x)
p.s(cpsStmts).addAssignment(tmp.snippet, x)
putIntoDest(p, d, e, tmp.snippet)
of tyArray:
# YYY: length(sideeffect) is optimized away incorrectly?
@@ -2421,15 +2497,15 @@ proc genMove(p: BProc; n: PNode; d: var TLoc) =
if n.len == 4:
# generated by liftdestructors:
var src: TLoc = initLocExpr(p, n[2])
linefmt(p, cpsStmts, "if ($1.p != $2.p) {", [rdLoc(a), rdLoc(src)])
genStmts(p, n[3])
linefmt(p, cpsStmts, "}$n", [])
let destVal = rdLoc(a)
let srcVal = rdLoc(src)
p.s(cpsStmts).addFieldAssignment(destVal, "len"):
p.s(cpsStmts).add(dotField(srcVal, "len"))
p.s(cpsStmts).addFieldAssignment(destVal, "p"):
p.s(cpsStmts).add(dotField(srcVal, "p"))
p.s(cpsStmts).addSingleIfStmt(
cOp(NotEqual,
dotField(destVal, "p"),
dotField(srcVal, "p"))):
genStmts(p, n[3])
p.s(cpsStmts).addFieldAssignment(destVal, "len", dotField(srcVal, "len"))
p.s(cpsStmts).addFieldAssignment(destVal, "p", dotField(srcVal, "p"))
else:
if d.k == locNone: d = getTemp(p, n.typ)
if p.config.selectedGC in {gcArc, gcAtomicArc, gcOrc}:
@@ -2518,10 +2594,8 @@ proc genSlice(p: BProc; e: PNode; d: var TLoc) =
p.config.selectedGC in {gcArc, gcAtomicArc, gcOrc})
if d.k == locNone: d = getTemp(p, e.typ)
let dest = rdLoc(d)
p.s(cpsStmts).addFieldAssignment(dest, "Field0"):
p.s(cpsStmts).add(x)
p.s(cpsStmts).addFieldAssignment(dest, "Field1"):
p.s(cpsStmts).add(y)
p.s(cpsStmts).addFieldAssignment(dest, "Field0", x)
p.s(cpsStmts).addFieldAssignment(dest, "Field1", y)
when false:
localError(p.config, e.info, "invalid context for 'toOpenArray'; " &
"'toOpenArray' is only valid within a call expression")
@@ -2764,8 +2838,7 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
else:
# small set
var ts = "NU" & $(getSize(p.config, e.typ) * 8)
p.s(cpsStmts).addAssignment(rdLoc(d)):
p.s(cpsStmts).addIntValue(0)
p.s(cpsStmts).addAssignment(rdLoc(d), cIntValue(0))
for it in e.sons:
if it.kind == nkRange:
idx = getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt)) # our counter
@@ -2843,17 +2916,13 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) =
when false:
if d.k != locNone:
let dest = d.rdLoc
p.s(cpsStmts).addFieldAssignment(dest, "ClP_0"):
p.s(cpsStmts).add(a.rdLoc)
p.s(cpsStmts).addFieldAssignment(dest, "ClE_0"):
p.s(cpsStmts).add(b.rdLoc)
p.s(cpsStmts).addFieldAssignment(dest, "ClP_0", a.rdLoc)
p.s(cpsStmts).addFieldAssignment(dest, "ClE_0", b.rdLoc)
else:
tmp = getTemp(p, n.typ)
let dest = tmp.rdLoc
p.s(cpsStmts).addFieldAssignment(dest, "ClP_0"):
p.s(cpsStmts).add(a.rdLoc)
p.s(cpsStmts).addFieldAssignment(dest, "ClE_0"):
p.s(cpsStmts).add(b.rdLoc)
p.s(cpsStmts).addFieldAssignment(dest, "ClP_0", a.rdLoc)
p.s(cpsStmts).addFieldAssignment(dest, "ClE_0", b.rdLoc)
putLocIntoDest(p, d, tmp)
proc genArrayConstr(p: BProc, n: PNode, d: var TLoc) =
@@ -3034,14 +3103,12 @@ proc genConstHeader(m, q: BModule; p: BProc, sym: PSym) =
m.s[cfsVars].addVar(kind = Global, name = sym.loc.snippet,
typ = ptrType(getTypeDesc(m, sym.loc.t, dkVar)))
m.initProc.procSec(cpsLocals).add('\t')
m.initProc.procSec(cpsLocals).addAssignment(sym.loc.snippet):
m.initProc.procSec(cpsLocals).addAssignmentWithValue(sym.loc.snippet):
m.initProc.procSec(cpsLocals).addCast(ptrType(getTypeDesc(m, sym.loc.t, dkVar))):
var getGlobalCall: CallBuilder
m.initProc.procSec(cpsLocals).addCall(getGlobalCall, "hcrGetGlobal"):
m.initProc.procSec(cpsLocals).addArgument(getGlobalCall):
m.initProc.procSec(cpsLocals).add(getModuleDllPath(q, sym))
m.initProc.procSec(cpsLocals).addArgument(getGlobalCall):
m.initProc.procSec(cpsLocals).add('"' & sym.loc.snippet & '"')
m.initProc.procSec(cpsLocals).addCall("hcrGetGlobal",
getModuleDllPath(q, sym),
'"' & sym.loc.snippet & '"')
else:
var headerDecl = newBuilder("")
headerDecl.addDeclWithVisibility(Extern):
@@ -3090,7 +3157,7 @@ proc genConstDefinition(q: BModule; p: BProc; sym: PSym) =
q.initProc.procSec(cpsLocals).addArgument(copyCall):
q.initProc.procSec(cpsLocals).add(cCast("void*", sym.loc.snippet))
q.initProc.procSec(cpsLocals).addArgument(copyCall):
q.initProc.procSec(cpsLocals).add(cCast(constType("void*"), cAddr(actualConstName)))
q.initProc.procSec(cpsLocals).add(cCast(ptrConstType("void"), cAddr(actualConstName)))
q.initProc.procSec(cpsLocals).addArgument(copyCall):
q.initProc.procSec(cpsLocals).addSizeof(rdLoc(sym.loc))

View File

@@ -1287,35 +1287,29 @@ proc genTypeInfoAuxBase(m: BModule; typ, origType: PType;
size = rope"void*"
else:
size = getTypeDesc(m, origType, dkVar)
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "size"):
m.s[cfsTypeInit3].addFieldAssignmentWithValue(nameHcr, "size"):
m.s[cfsTypeInit3].addSizeof(size)
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "align"):
m.s[cfsTypeInit3].addFieldAssignmentWithValue(nameHcr, "align"):
m.s[cfsTypeInit3].addAlignof(size)
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "kind"):
m.s[cfsTypeInit3].addIntValue(nimtypeKind)
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "base"):
m.s[cfsTypeInit3].add(base)
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "kind", nimtypeKind)
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "base", base)
# compute type flags for GC optimization
var flags = 0
if not containsGarbageCollectedRef(typ): flags = flags or 1
if not canFormAcycle(m.g.graph, typ): flags = flags or 2
#else echo("can contain a cycle: " & typeToString(typ))
if flags != 0:
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "flags"):
m.s[cfsTypeInit3].addIntValue(flags)
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "flags", cIntValue(flags))
cgsym(m, "TNimType")
if isDefined(m.config, "nimTypeNames"):
var typename = typeToString(if origType.typeInst != nil: origType.typeInst
else: origType, preferName)
if typename == "ref object" and origType.skipTypes(skipPtrs).sym != nil:
typename = "anon ref object from " & m.config$origType.skipTypes(skipPtrs).sym.info
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "name"):
m.s[cfsTypeInit3].add(makeCString typename)
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "name", makeCString typename)
cgsym(m, "nimTypeRoot")
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "nextType"):
m.s[cfsTypeInit3].add("nimTypeRoot")
m.s[cfsTypeInit3].addAssignment("nimTypeRoot"):
m.s[cfsTypeInit3].add(cAddr(nameHcr))
m.s[cfsTypeInit3].addFieldAssignment(nameHcr, "nextType", "nimTypeRoot")
m.s[cfsTypeInit3].addAssignment("nimTypeRoot", cAddr(nameHcr))
if m.hcrOn:
m.s[cfsStrData].addVar(kind = Global, name = name, typ = ptrType("TNimType"))
@@ -1400,20 +1394,15 @@ proc genObjectFields(m: BModule; typ, origType: PType, n: PNode, expr: Rope;
genTNimNodeArray(m, tmp, n.len)
for i in 0..<n.len:
var tmp2 = getNimNode(m)
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, cIntValue(i)):
m.s[cfsTypeInit3].add(cAddr(tmp2))
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, cIntValue(i), cAddr(tmp2))
genObjectFields(m, typ, origType, n[i], tmp2, info)
m.s[cfsTypeInit3].addFieldAssignment(expr, "len"):
m.s[cfsTypeInit3].addIntValue(n.len)
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind"):
m.s[cfsTypeInit3].addIntValue(2)
m.s[cfsTypeInit3].addFieldAssignment(expr, "sons"):
m.s[cfsTypeInit3].add(cAddr(subscript(tmp, cIntValue(0))))
m.s[cfsTypeInit3].addFieldAssignment(expr, "len", n.len)
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind", 2)
m.s[cfsTypeInit3].addFieldAssignment(expr, "sons",
cAddr(subscript(tmp, cIntValue(0))))
else:
m.s[cfsTypeInit3].addFieldAssignment(expr, "len"):
m.s[cfsTypeInit3].addIntValue(n.len)
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind"):
m.s[cfsTypeInit3].addIntValue(2)
m.s[cfsTypeInit3].addFieldAssignment(expr, "len", n.len)
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind", 2)
of nkRecCase:
assert(n[0].kind == nkSym)
var field = n[0].sym
@@ -1424,18 +1413,13 @@ proc genObjectFields(m: BModule; typ, origType: PType, n: PNode, expr: Rope;
if field.loc.t == nil:
internalError(m.config, n.info, "genObjectFields")
let fieldTypInfo = genTypeInfoV1(m, field.typ, info)
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind"):
m.s[cfsTypeInit3].addIntValue(3)
m.s[cfsTypeInit3].addFieldAssignment(expr, "offset"):
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind", 3)
m.s[cfsTypeInit3].addFieldAssignmentWithValue(expr, "offset"):
m.s[cfsTypeInit3].addOffsetof(getTypeDesc(m, origType, dkVar), field.loc.snippet)
m.s[cfsTypeInit3].addFieldAssignment(expr, "typ"):
m.s[cfsTypeInit3].add(fieldTypInfo)
m.s[cfsTypeInit3].addFieldAssignment(expr, "name"):
m.s[cfsTypeInit3].add(makeCString(field.name.s))
m.s[cfsTypeInit3].addFieldAssignment(expr, "sons"):
m.s[cfsTypeInit3].add(cAddr(subscript(tmp, "0")))
m.s[cfsTypeInit3].addFieldAssignment(expr, "len"):
m.s[cfsTypeInit3].addIntValue(L)
m.s[cfsTypeInit3].addFieldAssignment(expr, "typ", fieldTypInfo)
m.s[cfsTypeInit3].addFieldAssignment(expr, "name", makeCString(field.name.s))
m.s[cfsTypeInit3].addFieldAssignment(expr, "sons", cAddr(subscript(tmp, "0")))
m.s[cfsTypeInit3].addFieldAssignment(expr, "len", L)
m.s[cfsData].addArrayVar(kind = Local, name = tmp,
elementType = ptrType("TNimNode"), len = toInt(L)+1)
for i in 1..<n.len:
@@ -1451,15 +1435,12 @@ proc genObjectFields(m: BModule; typ, origType: PType, n: PNode, expr: Rope;
var x = toInt(getOrdValue(b[j][0]))
var y = toInt(getOrdValue(b[j][1]))
while x <= y:
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, cIntValue(x)):
m.s[cfsTypeInit3].add(cAddr(tmp2))
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, cIntValue(x), cAddr(tmp2))
inc(x)
else:
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, cIntValue(getOrdValue(b[j]))):
m.s[cfsTypeInit3].add(cAddr(tmp2))
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, cIntValue(getOrdValue(b[j])), cAddr(tmp2))
of nkElse:
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, cIntValue(L)):
m.s[cfsTypeInit3].add(cAddr(tmp2))
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, cIntValue(L), cAddr(tmp2))
else: internalError(m.config, n.info, "genObjectFields(nkRecCase)")
of nkSym:
var field = n.sym
@@ -1470,14 +1451,11 @@ proc genObjectFields(m: BModule; typ, origType: PType, n: PNode, expr: Rope;
if field.loc.t == nil:
internalError(m.config, n.info, "genObjectFields")
let fieldTypInfo = genTypeInfoV1(m, field.typ, info)
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind"):
m.s[cfsTypeInit3].addIntValue(1)
m.s[cfsTypeInit3].addFieldAssignment(expr, "offset"):
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind", 1)
m.s[cfsTypeInit3].addFieldAssignmentWithValue(expr, "offset"):
m.s[cfsTypeInit3].addOffsetof(getTypeDesc(m, origType, dkVar), field.loc.snippet)
m.s[cfsTypeInit3].addFieldAssignment(expr, "typ"):
m.s[cfsTypeInit3].add(fieldTypInfo)
m.s[cfsTypeInit3].addFieldAssignment(expr, "name"):
m.s[cfsTypeInit3].add(makeCString(field.name.s))
m.s[cfsTypeInit3].addFieldAssignment(expr, "typ", fieldTypInfo)
m.s[cfsTypeInit3].addFieldAssignment(expr, "name", makeCString(field.name.s))
else: internalError(m.config, n.info, "genObjectFields")
proc genObjectInfo(m: BModule; typ, origType: PType, name: Rope; info: TLineInfo) =
@@ -1489,8 +1467,7 @@ proc genObjectInfo(m: BModule; typ, origType: PType, name: Rope; info: TLineInfo
var tmp = getNimNode(m)
if (not isImportedType(typ)) or tfCompleteStruct in typ.flags:
genObjectFields(m, typ, origType, typ.n, tmp, info)
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, name), "node"):
m.s[cfsTypeInit3].add(cAddr(tmp))
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, name), "node", cAddr(tmp))
var t = typ.baseClass
while t != nil:
t = t.skipTypes(skipPtrs)
@@ -1506,29 +1483,20 @@ proc genTupleInfo(m: BModule; typ, origType: PType, name: Rope; info: TLineInfo)
for i, a in typ.ikids:
var tmp2 = getNimNode(m)
let fieldTypInfo = genTypeInfoV1(m, a, info)
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, cIntValue(i)):
m.s[cfsTypeInit3].add(cAddr(tmp2))
m.s[cfsTypeInit3].addFieldAssignment(tmp2, "kind"):
m.s[cfsTypeInit3].addIntValue(1)
m.s[cfsTypeInit3].addFieldAssignment(tmp2, "offset"):
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, cIntValue(i), cAddr(tmp2))
m.s[cfsTypeInit3].addFieldAssignment(tmp2, "kind", 1)
m.s[cfsTypeInit3].addFieldAssignmentWithValue(tmp2, "offset"):
m.s[cfsTypeInit3].addOffsetof(getTypeDesc(m, origType, dkVar), "Field" & $i)
m.s[cfsTypeInit3].addFieldAssignment(tmp2, "typ"):
m.s[cfsTypeInit3].add(fieldTypInfo)
m.s[cfsTypeInit3].addFieldAssignment(tmp2, "name"):
m.s[cfsTypeInit3].add("\"Field" & $i & "\"")
m.s[cfsTypeInit3].addFieldAssignment(expr, "len"):
m.s[cfsTypeInit3].addIntValue(typ.kidsLen)
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind"):
m.s[cfsTypeInit3].addIntValue(2)
m.s[cfsTypeInit3].addFieldAssignment(expr, "sons"):
m.s[cfsTypeInit3].add(cAddr(subscript(tmp, cIntValue(0))))
m.s[cfsTypeInit3].addFieldAssignment(tmp2, "typ", fieldTypInfo)
m.s[cfsTypeInit3].addFieldAssignment(tmp2, "name", "\"Field" & $i & "\"")
m.s[cfsTypeInit3].addFieldAssignment(expr, "len", typ.kidsLen)
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind", 2)
m.s[cfsTypeInit3].addFieldAssignment(expr, "sons",
cAddr(subscript(tmp, cIntValue(0))))
else:
m.s[cfsTypeInit3].addFieldAssignment(expr, "len"):
m.s[cfsTypeInit3].addIntValue(typ.kidsLen)
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind"):
m.s[cfsTypeInit3].addIntValue(2)
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, name), "node"):
m.s[cfsTypeInit3].add(cAddr(expr))
m.s[cfsTypeInit3].addFieldAssignment(expr, "len", typ.kidsLen)
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind", 2)
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, name), "node", cAddr(expr))
proc genEnumInfo(m: BModule; typ: PType, name: Rope; info: TLineInfo) =
# Type information for enumerations is quite heavy, so we do some
@@ -1555,8 +1523,7 @@ proc genEnumInfo(m: BModule; typ: PType, name: Rope; info: TLineInfo) =
else:
enumNames.add(makeCString(field.ast.strVal))
if field.position != i or tfEnumHasHoles in typ.flags:
specialCases.addFieldAssignment(elemNode, "offset"):
specialCases.addIntValue(field.position)
specialCases.addFieldAssignment(elemNode, "offset", field.position)
hasHoles = true
var enumArray = getTempName(m)
var counter = getTempName(m)
@@ -1573,14 +1540,11 @@ proc genEnumInfo(m: BModule; typ: PType, name: Rope; info: TLineInfo) =
rope(typ.n.len), m.typeNodesName, rope(firstNimNode), enumArray, nodePtrs])
m.s[cfsTypeInit3].add(specialCases)
let n = getNimNode(m)
m.s[cfsTypeInit3].addFieldAssignment(n, "len"):
m.s[cfsTypeInit3].addIntValue(typ.n.len)
m.s[cfsTypeInit3].addFieldAssignment(n, "kind"):
m.s[cfsTypeInit3].addIntValue(0)
m.s[cfsTypeInit3].addFieldAssignment(n, "sons"):
m.s[cfsTypeInit3].add(cAddr(subscript(nodePtrs, cIntValue(0))))
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, name), "node"):
m.s[cfsTypeInit3].add(cAddr(n))
m.s[cfsTypeInit3].addFieldAssignment(n, "len", typ.n.len)
m.s[cfsTypeInit3].addFieldAssignment(n, "kind", 0)
m.s[cfsTypeInit3].addFieldAssignment(n, "sons",
cAddr(subscript(nodePtrs, cIntValue(0))))
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, name), "node", cAddr(n))
if hasHoles:
# 1 << 2 is {ntfEnumHole}
m.s[cfsTypeInit3].addf("$1.flags = 1<<2;$n", [tiNameForHcr(m, name)])
@@ -1589,12 +1553,9 @@ proc genSetInfo(m: BModule; typ: PType, name: Rope; info: TLineInfo) =
assert(typ.elementType != nil)
genTypeInfoAux(m, typ, typ, name, info)
var tmp = getNimNode(m)
m.s[cfsTypeInit3].addFieldAssignment(tmp, "len"):
m.s[cfsTypeInit3].addIntValue(firstOrd(m.config, typ))
m.s[cfsTypeInit3].addFieldAssignment(tmp, "kind"):
m.s[cfsTypeInit3].addIntValue(0)
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, name), "node"):
m.s[cfsTypeInit3].add(cAddr(tmp))
m.s[cfsTypeInit3].addFieldAssignment(tmp, "len", firstOrd(m.config, typ))
m.s[cfsTypeInit3].addFieldAssignment(tmp, "kind", 0)
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, name), "node", cAddr(tmp))
proc genArrayInfo(m: BModule; typ: PType, name: Rope; info: TLineInfo) =
genTypeInfoAuxBase(m, typ, typ, name, genTypeInfoV1(m, typ.elementType, info), info)
@@ -1620,7 +1581,7 @@ proc declareNimType(m: BModule; name: string; str: Rope, module: int) =
if m.hcrOn:
m.s[cfsStrData].addVar(kind = Global, name = str, typ = ptrType(nr))
m.s[cfsTypeInit1].add('\t')
m.s[cfsTypeInit1].addAssignment(str):
m.s[cfsTypeInit1].addAssignmentWithValue(str):
m.s[cfsTypeInit1].addCast(typ = ptrType(nr)):
var hcrGlobal: CallBuilder
m.s[cfsTypeInit1].addCall(hcrGlobal, "hcrGetGlobal"):
@@ -1771,10 +1732,10 @@ proc genTypeInfoV2OldImpl(m: BModule; t, origType: PType, name: Rope; info: TLin
if not canFormAcycle(m.g.graph, t): flags = flags or 1
var typeEntry = newRopeAppender()
typeEntry.addFieldAssignment(name, "destructor"):
typeEntry.addFieldAssignmentWithValue(name, "destructor"):
typeEntry.addCast("void*"):
genHook(m, t, info, attachedDestructor, typeEntry)
typeEntry.addFieldAssignment(name, "traceImpl"):
typeEntry.addFieldAssignmentWithValue(name, "traceImpl"):
typeEntry.addCast("void*"):
genHook(m, t, info, attachedTrace, typeEntry)
@@ -1790,18 +1751,15 @@ proc genTypeInfoV2OldImpl(m: BModule; t, origType: PType, name: Rope; info: TLin
typeName = genTypeInfo2Name(m, t)
else:
typeName = rope("NIM_NIL")
typeEntry.addFieldAssignment(name, "name"):
typeEntry.add(typeName)
typeEntry.addFieldAssignment(name, "name", typeName)
let sizeTyp = getTypeDesc(m, t)
typeEntry.addFieldAssignment(name, "size"):
typeEntry.addFieldAssignmentWithValue(name, "size"):
typeEntry.addSizeof(sizeTyp)
typeEntry.addFieldAssignment(name, "align"):
typeEntry.addFieldAssignmentWithValue(name, "align"):
typeEntry.addCast(typ = "NI16"):
typeEntry.addAlignof(sizeTyp)
typeEntry.addFieldAssignment(name, "depth"):
typeEntry.addIntValue(objDepth)
typeEntry.addFieldAssignment(name, "flags"):
typeEntry.addIntValue(flags)
typeEntry.addFieldAssignment(name, "depth", objDepth)
typeEntry.addFieldAssignment(name, "flags", flags)
if objDepth >= 0:
let objDisplay = genDisplay(m, t, objDepth)
@@ -1811,8 +1769,7 @@ proc genTypeInfoV2OldImpl(m: BModule; t, origType: PType, name: Rope; info: TLin
elementType = getTypeDesc(m, getSysType(m.g.graph, unknownLineInfo, tyUInt32), dkVar),
len = objDepth + 1,
initializer = objDisplay)
typeEntry.addFieldAssignment(name, "display"):
typeEntry.add(objDisplayStore)
typeEntry.addFieldAssignment(name, "display", objDisplayStore)
let dispatchMethods = toSeq(getMethodsPerType(m.g.graph, t))
if dispatchMethods.len > 0:
@@ -1824,8 +1781,7 @@ proc genTypeInfoV2OldImpl(m: BModule; t, origType: PType, name: Rope; info: TLin
initializer = genVTable(dispatchMethods))
for i in dispatchMethods:
genProcPrototype(m, i)
typeEntry.addFieldAssignment(name, "vTable"):
typeEntry.add(vTablePointerName)
typeEntry.addFieldAssignment(name, "vTable", vTablePointerName)
m.s[cfsTypeInit3].add typeEntry
@@ -2043,14 +1999,12 @@ proc genTypeInfoV1(m: BModule; t: PType; info: TLineInfo): Rope =
genTypeInfoAux(m, t, t, result, info)
if m.config.selectedGC in {gcMarkAndSweep, gcRefc, gcGo}:
let markerProc = genTraverseProc(m, origType, sig)
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, result), "marker"):
m.s[cfsTypeInit3].add(markerProc)
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, result), "marker", markerProc)
of tyRef:
genTypeInfoAux(m, t, t, result, info)
if m.config.selectedGC in {gcMarkAndSweep, gcRefc, gcGo}:
let markerProc = genTraverseProc(m, origType, sig)
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, result), "marker"):
m.s[cfsTypeInit3].add(markerProc)
m.s[cfsTypeInit3].addFieldAssignment(tiNameForHcr(m, result), "marker", markerProc)
of tyPtr, tyRange, tyUncheckedArray: genTypeInfoAux(m, t, t, result, info)
of tyArray: genArrayInfo(m, t, result, info)
of tySet: genSetInfo(m, t, result, info)
@@ -2076,10 +2030,8 @@ proc genTypeInfoV1(m: BModule; t: PType; info: TLineInfo): Rope =
if optTinyRtti in m.config.globalOptions and t.kind == tyObject and sfImportc notin t.sym.flags:
let v2info = genTypeInfoV2(m, origType, info)
m.s[cfsTypeInit3].addDerefFieldAssignment(v2info, "typeInfoV1"):
m.s[cfsTypeInit3].add(cCast("void*", cAddr(result)))
m.s[cfsTypeInit3].addFieldAssignment(result, "typeInfoV2"):
m.s[cfsTypeInit3].add(cCast("void*", v2info))
m.s[cfsTypeInit3].addDerefFieldAssignment(v2info, "typeInfoV1", cCast("void*", cAddr(result)))
m.s[cfsTypeInit3].addFieldAssignment(result, "typeInfoV2", cCast("void*", v2info))
result = prefixTI.rope & result & ")".rope

View File

@@ -337,31 +337,43 @@ proc getTempName(m: BModule): Rope =
result = m.tmpBase & rope(m.labels)
inc m.labels
include cbuilderbase
include cbuilderexprs
include cbuilderdecls
include cbuilderstmts
proc rdLoc(a: TLoc): Rope =
# 'read' location (deref if indirect)
if lfIndirect in a.flags:
result = "(*" & a.snippet & ")"
result = cDeref(a.snippet)
else:
result = a.snippet
proc addRdLoc(a: TLoc; result: var Rope) =
if lfIndirect in a.flags:
result.add "(*" & a.snippet & ")"
result.add cDeref(a.snippet)
else:
result.add a.snippet
proc lenField(p: BProc): Rope {.inline.} =
result = rope(if p.module.compileToCpp: "len" else: "Sup.len")
proc lenField(p: BProc, val: Rope): Rope {.inline.} =
if p.module.compileToCpp:
result = derefField(val, "len")
else:
result = dotField(derefField(val, "Sup"), "len")
proc lenExpr(p: BProc; a: TLoc): Rope =
if optSeqDestructors in p.config.globalOptions:
result = rdLoc(a) & ".len"
result = dotField(rdLoc(a), "len")
else:
result = "($1 ? $1->$2 : 0)" % [rdLoc(a), lenField(p)]
let ra = rdLoc(a)
result = cIfExpr(ra, lenField(p, ra), cIntValue(0))
proc dataFieldAccessor(p: BProc, sym: Rope): Rope =
if optSeqDestructors in p.config.globalOptions:
result = "(" & sym & ").p"
result = dotField(wrapPar(sym), "p")
else:
result = sym
@@ -371,12 +383,11 @@ proc dataField(p: BProc): Rope =
else:
result = rope"->data"
proc dataField(p: BProc, val: Rope): Rope {.inline.} =
result = derefField(dataFieldAccessor(p, val), "data")
proc genProcPrototype(m: BModule, sym: PSym)
include cbuilderbase
include cbuilderexprs
include cbuilderdecls
include cbuilderstmts
include ccgliterals
include ccgtypes
@@ -389,20 +400,20 @@ template mapTypeChooser(a: TLoc): TSymKind = mapTypeChooser(a.lode)
proc addAddrLoc(conf: ConfigRef; a: TLoc; result: var Rope) =
if lfIndirect notin a.flags and mapType(conf, a.t, mapTypeChooser(a) == skParam) != ctArray:
result.add "(&" & a.snippet & ")"
result.add wrapPar(cAddr(a.snippet))
else:
result.add a.snippet
proc addrLoc(conf: ConfigRef; a: TLoc): Rope =
if lfIndirect notin a.flags and mapType(conf, a.t, mapTypeChooser(a) == skParam) != ctArray:
result = "(&" & a.snippet & ")"
result = wrapPar(cAddr(a.snippet))
else:
result = a.snippet
proc byRefLoc(p: BProc; a: TLoc): Rope =
if lfIndirect notin a.flags and mapType(p.config, a.t, mapTypeChooser(a) == skParam) != ctArray and not
p.module.compileToCpp:
result = "(&" & a.snippet & ")"
result = wrapPar(cAddr(a.snippet))
else:
result = a.snippet
@@ -410,7 +421,7 @@ proc rdCharLoc(a: TLoc): Rope =
# read a location that may need a char-cast:
result = rdLoc(a)
if skipTypes(a.t, abstractRange).kind == tyChar:
result = "((NU8)($1))" % [result]
result = cCast("NU8", result)
type
TAssignmentFlag = enum
@@ -756,7 +767,6 @@ proc genStmts(p: BProc, t: PNode)
proc expr(p: BProc, n: PNode, d: var TLoc)
proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc)
proc intLiteral(i: BiggestInt; result: var Rope)
proc genLiteral(p: BProc, n: PNode; result: var Rope)
proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType; result: var Rope; argsCounter: var int)
proc raiseExit(p: BProc)