mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-19 01:18:32 +00:00
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:
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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("}")
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user