no ropes WIP (#20433)
* refactorings in preparation for ropes elimination of the C code generator; mostly the usual ': Rope' -> 'result: var Rope' rewrite * rewrote ccgcalls.nim * refactored ccgexprs.nim * ccgliterals: refactoring * refactoring: code dealing with name mangling * refactoring: getRecordFieldsAux * ropes are strings (insert obscene joke here) * optimize JS code gen * optimizations and code improvements * more optimizations * final cleanups
This commit is contained in:
parent
805186809c
commit
ca1f3f36b9
24 changed files with 1058 additions and 1002 deletions
|
|
@ -745,7 +745,7 @@ const
|
||||||
mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet,
|
mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet,
|
||||||
mConStrStr, mAppendStrCh, mAppendStrStr, mAppendSeqElem,
|
mConStrStr, mAppendStrCh, mAppendStrStr, mAppendSeqElem,
|
||||||
mInSet, mRepr, mOpenArrayToSeq}
|
mInSet, mRepr, mOpenArrayToSeq}
|
||||||
|
|
||||||
generatedMagics* = {mNone, mIsolate, mFinished, mOpenArrayToSeq}
|
generatedMagics* = {mNone, mIsolate, mFinished, mOpenArrayToSeq}
|
||||||
## magics that are generated as normal procs in the backend
|
## magics that are generated as normal procs in the backend
|
||||||
|
|
||||||
|
|
@ -1504,7 +1504,7 @@ proc mergeLoc(a: var TLoc, b: TLoc) =
|
||||||
if a.storage == low(typeof(a.storage)): a.storage = b.storage
|
if a.storage == low(typeof(a.storage)): a.storage = b.storage
|
||||||
a.flags.incl b.flags
|
a.flags.incl b.flags
|
||||||
if a.lode == nil: a.lode = b.lode
|
if a.lode == nil: a.lode = b.lode
|
||||||
if a.r == nil: a.r = b.r
|
if a.r == "": a.r = b.r
|
||||||
|
|
||||||
proc newSons*(father: Indexable, length: int) =
|
proc newSons*(father: Indexable, length: int) =
|
||||||
setLen(father.sons, length)
|
setLen(father.sons, length)
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,11 @@
|
||||||
# the data structures here are used in various places of the compiler.
|
# the data structures here are used in various places of the compiler.
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, hashes, intsets, strutils, options, lineinfos, ropes, idents, rodutils,
|
ast, hashes, intsets, options, lineinfos, ropes, idents, rodutils,
|
||||||
msgs
|
msgs
|
||||||
|
|
||||||
|
import strutils except addf
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
import std/assertions
|
import std/assertions
|
||||||
|
|
||||||
|
|
@ -258,7 +260,7 @@ proc makeYamlString*(s: string): Rope =
|
||||||
# this could trigger InternalError(111). See the ropes module for
|
# this could trigger InternalError(111). See the ropes module for
|
||||||
# further information.
|
# further information.
|
||||||
const MaxLineLength = 64
|
const MaxLineLength = 64
|
||||||
result = nil
|
result = ""
|
||||||
var res = "\""
|
var res = "\""
|
||||||
for i in 0..<s.len:
|
for i in 0..<s.len:
|
||||||
if (i + 1) mod MaxLineLength == 0:
|
if (i + 1) mod MaxLineLength == 0:
|
||||||
|
|
@ -274,9 +276,9 @@ proc flagsToStr[T](flags: set[T]): Rope =
|
||||||
if flags == {}:
|
if flags == {}:
|
||||||
result = rope("[]")
|
result = rope("[]")
|
||||||
else:
|
else:
|
||||||
result = nil
|
result = ""
|
||||||
for x in items(flags):
|
for x in items(flags):
|
||||||
if result != nil: result.add(", ")
|
if result != "": result.add(", ")
|
||||||
result.add(makeYamlString($x))
|
result.add(makeYamlString($x))
|
||||||
result = "[" & result & "]"
|
result = "[" & result & "]"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,12 +77,12 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
|
||||||
callee, params: Rope) =
|
callee, params: Rope) =
|
||||||
let canRaise = p.config.exc == excGoto and canRaiseDisp(p, ri[0])
|
let canRaise = p.config.exc == excGoto and canRaiseDisp(p, ri[0])
|
||||||
genLineDir(p, ri)
|
genLineDir(p, ri)
|
||||||
var pl = callee & ~"(" & params
|
var pl = callee & "(" & params
|
||||||
# getUniqueType() is too expensive here:
|
# getUniqueType() is too expensive here:
|
||||||
var typ = skipTypes(ri[0].typ, abstractInst)
|
var typ = skipTypes(ri[0].typ, abstractInst)
|
||||||
if typ[0] != nil:
|
if typ[0] != nil:
|
||||||
if isInvalidReturnType(p.config, typ):
|
if isInvalidReturnType(p.config, typ):
|
||||||
if params != nil: pl.add(~", ")
|
if params.len != 0: pl.add(", ")
|
||||||
# beware of 'result = p(result)'. We may need to allocate a temporary:
|
# beware of 'result = p(result)'. We may need to allocate a temporary:
|
||||||
if d.k in {locTemp, locNone} or not preventNrvo(p, d.lode, le, ri):
|
if d.k in {locTemp, locNone} or not preventNrvo(p, d.lode, le, ri):
|
||||||
# Great, we can use 'd':
|
# Great, we can use 'd':
|
||||||
|
|
@ -91,18 +91,18 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
|
||||||
# reset before pass as 'result' var:
|
# reset before pass as 'result' var:
|
||||||
discard "resetLoc(p, d)"
|
discard "resetLoc(p, d)"
|
||||||
pl.add(addrLoc(p.config, d))
|
pl.add(addrLoc(p.config, d))
|
||||||
pl.add(~");$n")
|
pl.add(");\n")
|
||||||
line(p, cpsStmts, pl)
|
line(p, cpsStmts, pl)
|
||||||
else:
|
else:
|
||||||
var tmp: TLoc
|
var tmp: TLoc
|
||||||
getTemp(p, typ[0], tmp, needsInit=true)
|
getTemp(p, typ[0], tmp, needsInit=true)
|
||||||
pl.add(addrLoc(p.config, tmp))
|
pl.add(addrLoc(p.config, tmp))
|
||||||
pl.add(~");$n")
|
pl.add(");\n")
|
||||||
line(p, cpsStmts, pl)
|
line(p, cpsStmts, pl)
|
||||||
genAssignment(p, d, tmp, {}) # no need for deep copying
|
genAssignment(p, d, tmp, {}) # no need for deep copying
|
||||||
if canRaise: raiseExit(p)
|
if canRaise: raiseExit(p)
|
||||||
else:
|
else:
|
||||||
pl.add(~")")
|
pl.add(")")
|
||||||
if p.module.compileToCpp:
|
if p.module.compileToCpp:
|
||||||
if lfSingleUse in d.flags:
|
if lfSingleUse in d.flags:
|
||||||
# do not generate spurious temporaries for C++! For C we're better off
|
# do not generate spurious temporaries for C++! For C we're better off
|
||||||
|
|
@ -140,7 +140,7 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
|
||||||
if canRaise: raiseExit(p)
|
if canRaise: raiseExit(p)
|
||||||
genAssignment(p, d, tmp, {})
|
genAssignment(p, d, tmp, {})
|
||||||
else:
|
else:
|
||||||
pl.add(~");$n")
|
pl.add(");\n")
|
||||||
line(p, cpsStmts, pl)
|
line(p, cpsStmts, pl)
|
||||||
if canRaise: raiseExit(p)
|
if canRaise: raiseExit(p)
|
||||||
|
|
||||||
|
|
@ -173,8 +173,10 @@ proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType): (Rope,
|
||||||
result = ("($3*)(($1)+($2))" % [rdLoc(a), rdLoc(b), dest],
|
result = ("($3*)(($1)+($2))" % [rdLoc(a), rdLoc(b), dest],
|
||||||
lengthExpr)
|
lengthExpr)
|
||||||
else:
|
else:
|
||||||
|
var lit = newRopeAppender()
|
||||||
|
intLiteral(first, lit)
|
||||||
result = ("($4*)($1)+(($2)-($3))" %
|
result = ("($4*)($1)+(($2)-($3))" %
|
||||||
[rdLoc(a), rdLoc(b), intLiteral(first), dest],
|
[rdLoc(a), rdLoc(b), lit, dest],
|
||||||
lengthExpr)
|
lengthExpr)
|
||||||
of tyOpenArray, tyVarargs:
|
of tyOpenArray, tyVarargs:
|
||||||
if reifiedOpenArray(q[1]):
|
if reifiedOpenArray(q[1]):
|
||||||
|
|
@ -200,7 +202,7 @@ proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType): (Rope,
|
||||||
else:
|
else:
|
||||||
internalError(p.config, "openArrayLoc: " & typeToString(a.t))
|
internalError(p.config, "openArrayLoc: " & typeToString(a.t))
|
||||||
|
|
||||||
proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope =
|
proc openArrayLoc(p: BProc, formalType: PType, n: PNode; result: var Rope) =
|
||||||
var q = skipConv(n)
|
var q = skipConv(n)
|
||||||
var skipped = false
|
var skipped = false
|
||||||
while q.kind == nkStmtListExpr and q.len > 0:
|
while q.kind == nkStmtListExpr and q.len > 0:
|
||||||
|
|
@ -215,7 +217,7 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope =
|
||||||
genStmts(p, q[i])
|
genStmts(p, q[i])
|
||||||
q = q.lastSon
|
q = q.lastSon
|
||||||
let (x, y) = genOpenArraySlice(p, q, formalType, n.typ[0])
|
let (x, y) = genOpenArraySlice(p, q, formalType, n.typ[0])
|
||||||
result = x & ", " & y
|
result.add x & ", " & y
|
||||||
else:
|
else:
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
initLocExpr(p, if n.kind == nkHiddenStdConv: n[1] else: n, a)
|
initLocExpr(p, if n.kind == nkHiddenStdConv: n[1] else: n, a)
|
||||||
|
|
@ -223,11 +225,11 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope =
|
||||||
of tyOpenArray, tyVarargs:
|
of tyOpenArray, tyVarargs:
|
||||||
if reifiedOpenArray(n):
|
if reifiedOpenArray(n):
|
||||||
if a.t.kind in {tyVar, tyLent}:
|
if a.t.kind in {tyVar, tyLent}:
|
||||||
result = "$1->Field0, $1->Field1" % [rdLoc(a)]
|
result.add "$1->Field0, $1->Field1" % [rdLoc(a)]
|
||||||
else:
|
else:
|
||||||
result = "$1.Field0, $1.Field1" % [rdLoc(a)]
|
result.add "$1.Field0, $1.Field1" % [rdLoc(a)]
|
||||||
else:
|
else:
|
||||||
result = "$1, $1Len_0" % [rdLoc(a)]
|
result.add "$1, $1Len_0" % [rdLoc(a)]
|
||||||
of tyString, tySequence:
|
of tyString, tySequence:
|
||||||
let ntyp = skipTypes(n.typ, abstractInst)
|
let ntyp = skipTypes(n.typ, abstractInst)
|
||||||
if formalType.skipTypes(abstractInst).kind in {tyVar} and ntyp.kind == tyString and
|
if formalType.skipTypes(abstractInst).kind in {tyVar} and ntyp.kind == tyString and
|
||||||
|
|
@ -236,19 +238,19 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope =
|
||||||
if ntyp.kind in {tyVar} and not compileToCpp(p.module):
|
if ntyp.kind in {tyVar} and not compileToCpp(p.module):
|
||||||
var t: TLoc
|
var t: TLoc
|
||||||
t.r = "(*$1)" % [a.rdLoc]
|
t.r = "(*$1)" % [a.rdLoc]
|
||||||
result = "(*$1)$3, $2" % [a.rdLoc, lenExpr(p, t), dataField(p)]
|
result.add "(*$1)$3, $2" % [a.rdLoc, lenExpr(p, t), dataField(p)]
|
||||||
else:
|
else:
|
||||||
result = "$1$3, $2" % [a.rdLoc, lenExpr(p, a), dataField(p)]
|
result.add "$1$3, $2" % [a.rdLoc, lenExpr(p, a), dataField(p)]
|
||||||
of tyArray:
|
of tyArray:
|
||||||
result = "$1, $2" % [rdLoc(a), rope(lengthOrd(p.config, a.t))]
|
result.add "$1, $2" % [rdLoc(a), rope(lengthOrd(p.config, a.t))]
|
||||||
of tyPtr, tyRef:
|
of tyPtr, tyRef:
|
||||||
case lastSon(a.t).kind
|
case lastSon(a.t).kind
|
||||||
of tyString, tySequence:
|
of tyString, tySequence:
|
||||||
var t: TLoc
|
var t: TLoc
|
||||||
t.r = "(*$1)" % [a.rdLoc]
|
t.r = "(*$1)" % [a.rdLoc]
|
||||||
result = "(*$1)$3, $2" % [a.rdLoc, lenExpr(p, t), dataField(p)]
|
result.add "(*$1)$3, $2" % [a.rdLoc, lenExpr(p, t), dataField(p)]
|
||||||
of tyArray:
|
of tyArray:
|
||||||
result = "$1, $2" % [rdLoc(a), rope(lengthOrd(p.config, lastSon(a.t)))]
|
result.add "$1, $2" % [rdLoc(a), rope(lengthOrd(p.config, lastSon(a.t)))]
|
||||||
else:
|
else:
|
||||||
internalError(p.config, "openArrayLoc: " & typeToString(a.t))
|
internalError(p.config, "openArrayLoc: " & typeToString(a.t))
|
||||||
else: internalError(p.config, "openArrayLoc: " & typeToString(a.t))
|
else: internalError(p.config, "openArrayLoc: " & typeToString(a.t))
|
||||||
|
|
@ -268,24 +270,24 @@ proc literalsNeedsTmp(p: BProc, a: TLoc): TLoc =
|
||||||
getTemp(p, a.lode.typ, result, needsInit=false)
|
getTemp(p, a.lode.typ, result, needsInit=false)
|
||||||
genAssignment(p, result, a, {})
|
genAssignment(p, result, a, {})
|
||||||
|
|
||||||
proc genArgStringToCString(p: BProc, n: PNode, needsTmp: bool): Rope {.inline.} =
|
proc genArgStringToCString(p: BProc, n: PNode; result: var Rope; needsTmp: bool) {.inline.} =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
initLocExpr(p, n[0], a)
|
initLocExpr(p, n[0], a)
|
||||||
ropecg(p.module, "#nimToCStringConv($1)", [withTmpIfNeeded(p, a, needsTmp).rdLoc])
|
appcg(p.module, result, "#nimToCStringConv($1)", [withTmpIfNeeded(p, a, needsTmp).rdLoc])
|
||||||
|
|
||||||
proc genArg(p: BProc, n: PNode, param: PSym; call: PNode, needsTmp = false): Rope =
|
proc genArg(p: BProc, n: PNode, param: PSym; call: PNode; result: var Rope; needsTmp = false) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
if n.kind == nkStringToCString:
|
if n.kind == nkStringToCString:
|
||||||
result = genArgStringToCString(p, n, needsTmp)
|
genArgStringToCString(p, n, result, needsTmp)
|
||||||
elif skipTypes(param.typ, abstractVar).kind in {tyOpenArray, tyVarargs}:
|
elif skipTypes(param.typ, abstractVar).kind in {tyOpenArray, tyVarargs}:
|
||||||
var n = if n.kind != nkHiddenAddr: n else: n[0]
|
var n = if n.kind != nkHiddenAddr: n else: n[0]
|
||||||
result = openArrayLoc(p, param.typ, n)
|
openArrayLoc(p, param.typ, n, result)
|
||||||
elif ccgIntroducedPtr(p.config, param, call[0].typ[0]):
|
elif ccgIntroducedPtr(p.config, param, call[0].typ[0]):
|
||||||
initLocExpr(p, n, a)
|
initLocExpr(p, n, a)
|
||||||
if n.kind in {nkCharLit..nkNilLit}:
|
if n.kind in {nkCharLit..nkNilLit}:
|
||||||
result = addrLoc(p.config, literalsNeedsTmp(p, a))
|
addAddrLoc(p.config, literalsNeedsTmp(p, a), result)
|
||||||
else:
|
else:
|
||||||
result = addrLoc(p.config, withTmpIfNeeded(p, a, needsTmp))
|
addAddrLoc(p.config, withTmpIfNeeded(p, a, needsTmp), result)
|
||||||
elif p.module.compileToCpp and param.typ.kind in {tyVar} and
|
elif p.module.compileToCpp and param.typ.kind in {tyVar} and
|
||||||
n.kind == nkHiddenAddr:
|
n.kind == nkHiddenAddr:
|
||||||
initLocExprSingleUse(p, n[0], a)
|
initLocExprSingleUse(p, n[0], a)
|
||||||
|
|
@ -295,21 +297,21 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode, needsTmp = false): Rop
|
||||||
if callee.kind == nkSym and
|
if callee.kind == nkSym and
|
||||||
{sfImportc, sfInfixCall, sfCompilerProc} * callee.sym.flags == {sfImportc} and
|
{sfImportc, sfInfixCall, sfCompilerProc} * callee.sym.flags == {sfImportc} and
|
||||||
{lfHeader, lfNoDecl} * callee.sym.loc.flags != {}:
|
{lfHeader, lfNoDecl} * callee.sym.loc.flags != {}:
|
||||||
result = addrLoc(p.config, a)
|
addAddrLoc(p.config, a, result)
|
||||||
else:
|
else:
|
||||||
result = rdLoc(a)
|
addRdLoc(a, result)
|
||||||
else:
|
else:
|
||||||
initLocExprSingleUse(p, n, a)
|
initLocExprSingleUse(p, n, a)
|
||||||
result = rdLoc(withTmpIfNeeded(p, a, needsTmp))
|
addRdLoc(withTmpIfNeeded(p, a, needsTmp), result)
|
||||||
#assert result != nil
|
#assert result != nil
|
||||||
|
|
||||||
proc genArgNoParam(p: BProc, n: PNode, needsTmp = false): Rope =
|
proc genArgNoParam(p: BProc, n: PNode; result: var Rope; needsTmp = false) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
if n.kind == nkStringToCString:
|
if n.kind == nkStringToCString:
|
||||||
result = genArgStringToCString(p, n, needsTmp)
|
genArgStringToCString(p, n, result, needsTmp)
|
||||||
else:
|
else:
|
||||||
initLocExprSingleUse(p, n, a)
|
initLocExprSingleUse(p, n, a)
|
||||||
result = rdLoc(withTmpIfNeeded(p, a, needsTmp))
|
addRdLoc(withTmpIfNeeded(p, a, needsTmp), result)
|
||||||
|
|
||||||
from dfa import aliases, AliasKind
|
from dfa import aliases, AliasKind
|
||||||
|
|
||||||
|
|
@ -365,7 +367,7 @@ proc getPotentialReads(n: PNode; result: var seq[PNode]) =
|
||||||
for s in n:
|
for s in n:
|
||||||
getPotentialReads(s, result)
|
getPotentialReads(s, result)
|
||||||
|
|
||||||
proc genParams(p: BProc, ri: PNode, typ: PType): Rope =
|
proc genParams(p: BProc, ri: PNode, typ: PType; result: var Rope) =
|
||||||
# We must generate temporaries in cases like #14396
|
# We must generate temporaries in cases like #14396
|
||||||
# to keep the strict Left-To-Right evaluation
|
# to keep the strict Left-To-Right evaluation
|
||||||
var needTmp = newSeq[bool](ri.len - 1)
|
var needTmp = newSeq[bool](ri.len - 1)
|
||||||
|
|
@ -385,16 +387,21 @@ proc genParams(p: BProc, ri: PNode, typ: PType): Rope =
|
||||||
# Optimization: don't use a temp, if we would only take the address anyway
|
# Optimization: don't use a temp, if we would only take the address anyway
|
||||||
needTmp[i - 1] = false
|
needTmp[i - 1] = false
|
||||||
|
|
||||||
|
var oldLen = result.len
|
||||||
for i in 1..<ri.len:
|
for i in 1..<ri.len:
|
||||||
if i < typ.len:
|
if i < typ.len:
|
||||||
assert(typ.n[i].kind == nkSym)
|
assert(typ.n[i].kind == nkSym)
|
||||||
let paramType = typ.n[i]
|
let paramType = typ.n[i]
|
||||||
if not paramType.typ.isCompileTimeOnly:
|
if not paramType.typ.isCompileTimeOnly:
|
||||||
if result != nil: result.add(~", ")
|
if oldLen != result.len:
|
||||||
result.add(genArg(p, ri[i], paramType.sym, ri, needTmp[i-1]))
|
result.add(", ")
|
||||||
|
oldLen = result.len
|
||||||
|
genArg(p, ri[i], paramType.sym, ri, result, needTmp[i-1])
|
||||||
else:
|
else:
|
||||||
if result != nil: result.add(~", ")
|
if oldLen != result.len:
|
||||||
result.add(genArgNoParam(p, ri[i], needTmp[i-1]))
|
result.add(", ")
|
||||||
|
oldLen = result.len
|
||||||
|
genArgNoParam(p, ri[i], result, needTmp[i-1])
|
||||||
|
|
||||||
proc addActualSuffixForHCR(res: var Rope, module: PSym, sym: PSym) =
|
proc addActualSuffixForHCR(res: var Rope, module: PSym, sym: PSym) =
|
||||||
if sym.flags * {sfImportc, sfNonReloadable} == {} and sym.loc.k == locProc and
|
if sym.flags * {sfImportc, sfNonReloadable} == {} and sym.loc.k == locProc and
|
||||||
|
|
@ -410,7 +417,8 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
assert(typ.kind == tyProc)
|
assert(typ.kind == tyProc)
|
||||||
assert(typ.len == typ.n.len)
|
assert(typ.len == typ.n.len)
|
||||||
|
|
||||||
var params = genParams(p, ri, typ)
|
var params = newRopeAppender()
|
||||||
|
genParams(p, ri, typ, params)
|
||||||
|
|
||||||
var callee = rdLoc(op)
|
var callee = rdLoc(op)
|
||||||
if p.hcrOn and ri[0].kind == nkSym:
|
if p.hcrOn and ri[0].kind == nkSym:
|
||||||
|
|
@ -420,7 +428,7 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
|
|
||||||
proc addComma(r: Rope): Rope =
|
proc addComma(r: Rope): Rope =
|
||||||
if r == nil: r else: r & ~", "
|
if r.len == 0: r else: r & ", "
|
||||||
|
|
||||||
const PatProc = "$1.ClE_0? $1.ClP_0($3$1.ClE_0):(($4)($1.ClP_0))($2)"
|
const PatProc = "$1.ClE_0? $1.ClP_0($3$1.ClE_0):(($4)($1.ClP_0))($2)"
|
||||||
const PatIter = "$1.ClP_0($3$1.ClE_0)" # we know the env exists
|
const PatIter = "$1.ClP_0($3$1.ClE_0)" # we know the env exists
|
||||||
|
|
@ -433,7 +441,8 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
assert(typ.kind == tyProc)
|
assert(typ.kind == tyProc)
|
||||||
assert(typ.len == typ.n.len)
|
assert(typ.len == typ.n.len)
|
||||||
|
|
||||||
var pl = genParams(p, ri, typ)
|
var pl = newRopeAppender()
|
||||||
|
genParams(p, ri, typ, pl)
|
||||||
|
|
||||||
template genCallPattern {.dirty.} =
|
template genCallPattern {.dirty.} =
|
||||||
if tfIterator in typ.flags:
|
if tfIterator in typ.flags:
|
||||||
|
|
@ -445,7 +454,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
let canRaise = p.config.exc == excGoto and canRaiseDisp(p, ri[0])
|
let canRaise = p.config.exc == excGoto and canRaiseDisp(p, ri[0])
|
||||||
if typ[0] != nil:
|
if typ[0] != nil:
|
||||||
if isInvalidReturnType(p.config, typ):
|
if isInvalidReturnType(p.config, typ):
|
||||||
if ri.len > 1: pl.add(~", ")
|
if ri.len > 1: pl.add(", ")
|
||||||
# beware of 'result = p(result)'. We may need to allocate a temporary:
|
# beware of 'result = p(result)'. We may need to allocate a temporary:
|
||||||
if d.k in {locTemp, locNone} or not preventNrvo(p, d.lode, le, ri):
|
if d.k in {locTemp, locNone} or not preventNrvo(p, d.lode, le, ri):
|
||||||
# Great, we can use 'd':
|
# Great, we can use 'd':
|
||||||
|
|
@ -491,24 +500,30 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
genCallPattern()
|
genCallPattern()
|
||||||
if canRaise: raiseExit(p)
|
if canRaise: raiseExit(p)
|
||||||
|
|
||||||
proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType): Rope =
|
proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType; result: var Rope;
|
||||||
|
argsCounter: var int) =
|
||||||
if i < typ.len:
|
if i < typ.len:
|
||||||
# 'var T' is 'T&' in C++. This means we ignore the request of
|
# 'var T' is 'T&' in C++. This means we ignore the request of
|
||||||
# any nkHiddenAddr when it's a 'var T'.
|
# any nkHiddenAddr when it's a 'var T'.
|
||||||
let paramType = typ.n[i]
|
let paramType = typ.n[i]
|
||||||
assert(paramType.kind == nkSym)
|
assert(paramType.kind == nkSym)
|
||||||
if paramType.typ.isCompileTimeOnly:
|
if paramType.typ.isCompileTimeOnly:
|
||||||
result = nil
|
discard
|
||||||
elif typ[i].kind in {tyVar} and ri[i].kind == nkHiddenAddr:
|
elif typ[i].kind in {tyVar} and ri[i].kind == nkHiddenAddr:
|
||||||
result = genArgNoParam(p, ri[i][0])
|
if argsCounter > 0: result.add ", "
|
||||||
|
genArgNoParam(p, ri[i][0], result)
|
||||||
|
inc argsCounter
|
||||||
else:
|
else:
|
||||||
result = genArgNoParam(p, ri[i]) #, typ.n[i].sym)
|
if argsCounter > 0: result.add ", "
|
||||||
|
genArgNoParam(p, ri[i], result) #, typ.n[i].sym)
|
||||||
|
inc argsCounter
|
||||||
else:
|
else:
|
||||||
if tfVarargs notin typ.flags:
|
if tfVarargs notin typ.flags:
|
||||||
localError(p.config, ri.info, "wrong argument count")
|
localError(p.config, ri.info, "wrong argument count")
|
||||||
result = nil
|
|
||||||
else:
|
else:
|
||||||
result = genArgNoParam(p, ri[i])
|
if argsCounter > 0: result.add ", "
|
||||||
|
genArgNoParam(p, ri[i], result)
|
||||||
|
inc argsCounter
|
||||||
|
|
||||||
discard """
|
discard """
|
||||||
Dot call syntax in C++
|
Dot call syntax in C++
|
||||||
|
|
@ -565,7 +580,7 @@ proc skipAddrDeref(node: PNode): PNode =
|
||||||
else:
|
else:
|
||||||
result = node
|
result = node
|
||||||
|
|
||||||
proc genThisArg(p: BProc; ri: PNode; i: int; typ: PType): Rope =
|
proc genThisArg(p: BProc; ri: PNode; i: int; typ: PType; result: var Rope) =
|
||||||
# for better or worse c2nim translates the 'this' argument to a 'var T'.
|
# for better or worse c2nim translates the 'this' argument to a 'var T'.
|
||||||
# However manual wrappers may also use 'ptr T'. In any case we support both
|
# However manual wrappers may also use 'ptr T'. In any case we support both
|
||||||
# for convenience.
|
# for convenience.
|
||||||
|
|
@ -579,75 +594,72 @@ proc genThisArg(p: BProc; ri: PNode; i: int; typ: PType): Rope =
|
||||||
if t.kind in {tyVar}:
|
if t.kind in {tyVar}:
|
||||||
let x = if ri.kind == nkHiddenAddr: ri[0] else: ri
|
let x = if ri.kind == nkHiddenAddr: ri[0] else: ri
|
||||||
if x.typ.kind == tyPtr:
|
if x.typ.kind == tyPtr:
|
||||||
result = genArgNoParam(p, x)
|
genArgNoParam(p, x, result)
|
||||||
result.add("->")
|
result.add("->")
|
||||||
elif x.kind in {nkHiddenDeref, nkDerefExpr} and x[0].typ.kind == tyPtr:
|
elif x.kind in {nkHiddenDeref, nkDerefExpr} and x[0].typ.kind == tyPtr:
|
||||||
result = genArgNoParam(p, x[0])
|
genArgNoParam(p, x[0], result)
|
||||||
result.add("->")
|
result.add("->")
|
||||||
else:
|
else:
|
||||||
result = genArgNoParam(p, x)
|
genArgNoParam(p, x, result)
|
||||||
result.add(".")
|
result.add(".")
|
||||||
elif t.kind == tyPtr:
|
elif t.kind == tyPtr:
|
||||||
if ri.kind in {nkAddr, nkHiddenAddr}:
|
if ri.kind in {nkAddr, nkHiddenAddr}:
|
||||||
result = genArgNoParam(p, ri[0])
|
genArgNoParam(p, ri[0], result)
|
||||||
result.add(".")
|
result.add(".")
|
||||||
else:
|
else:
|
||||||
result = genArgNoParam(p, ri)
|
genArgNoParam(p, ri, result)
|
||||||
result.add("->")
|
result.add("->")
|
||||||
else:
|
else:
|
||||||
ri = skipAddrDeref(ri)
|
ri = skipAddrDeref(ri)
|
||||||
if ri.kind in {nkAddr, nkHiddenAddr}: ri = ri[0]
|
if ri.kind in {nkAddr, nkHiddenAddr}: ri = ri[0]
|
||||||
result = genArgNoParam(p, ri) #, typ.n[i].sym)
|
genArgNoParam(p, ri, result) #, typ.n[i].sym)
|
||||||
result.add(".")
|
result.add(".")
|
||||||
|
|
||||||
proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): Rope =
|
proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType; result: var Rope) =
|
||||||
var i = 0
|
var i = 0
|
||||||
var j = 1
|
var j = 1
|
||||||
while i < pat.len:
|
while i < pat.len:
|
||||||
case pat[i]
|
case pat[i]
|
||||||
of '@':
|
of '@':
|
||||||
var first = true
|
var argsCounter = 0
|
||||||
for k in j..<ri.len:
|
for k in j..<ri.len:
|
||||||
let arg = genOtherArg(p, ri, k, typ)
|
genOtherArg(p, ri, k, typ, result, argsCounter)
|
||||||
if arg.len > 0:
|
|
||||||
if not first:
|
|
||||||
result.add(~", ")
|
|
||||||
first = false
|
|
||||||
result.add arg
|
|
||||||
inc i
|
inc i
|
||||||
of '#':
|
of '#':
|
||||||
if i+1 < pat.len and pat[i+1] in {'+', '@'}:
|
if i+1 < pat.len and pat[i+1] in {'+', '@'}:
|
||||||
let ri = ri[j]
|
let ri = ri[j]
|
||||||
if ri.kind in nkCallKinds:
|
if ri.kind in nkCallKinds:
|
||||||
let typ = skipTypes(ri[0].typ, abstractInst)
|
let typ = skipTypes(ri[0].typ, abstractInst)
|
||||||
if pat[i+1] == '+': result.add genArgNoParam(p, ri[0])
|
if pat[i+1] == '+': genArgNoParam(p, ri[0], result)
|
||||||
result.add(~"(")
|
result.add("(")
|
||||||
if 1 < ri.len:
|
if 1 < ri.len:
|
||||||
result.add genOtherArg(p, ri, 1, typ)
|
var argsCounterB = 0
|
||||||
|
genOtherArg(p, ri, 1, typ, result, argsCounterB)
|
||||||
for k in j+1..<ri.len:
|
for k in j+1..<ri.len:
|
||||||
result.add(~", ")
|
var argsCounterB = 0
|
||||||
result.add genOtherArg(p, ri, k, typ)
|
genOtherArg(p, ri, k, typ, result, argsCounterB)
|
||||||
result.add(~")")
|
result.add(")")
|
||||||
else:
|
else:
|
||||||
localError(p.config, ri.info, "call expression expected for C++ pattern")
|
localError(p.config, ri.info, "call expression expected for C++ pattern")
|
||||||
inc i
|
inc i
|
||||||
elif i+1 < pat.len and pat[i+1] == '.':
|
elif i+1 < pat.len and pat[i+1] == '.':
|
||||||
result.add genThisArg(p, ri, j, typ)
|
genThisArg(p, ri, j, typ, result)
|
||||||
inc i
|
inc i
|
||||||
elif i+1 < pat.len and pat[i+1] == '[':
|
elif i+1 < pat.len and pat[i+1] == '[':
|
||||||
var arg = ri[j].skipAddrDeref
|
var arg = ri[j].skipAddrDeref
|
||||||
while arg.kind in {nkAddr, nkHiddenAddr, nkObjDownConv}: arg = arg[0]
|
while arg.kind in {nkAddr, nkHiddenAddr, nkObjDownConv}: arg = arg[0]
|
||||||
result.add genArgNoParam(p, arg)
|
genArgNoParam(p, arg, result)
|
||||||
#result.add debugTree(arg, 0, 10)
|
#result.add debugTree(arg, 0, 10)
|
||||||
else:
|
else:
|
||||||
result.add genOtherArg(p, ri, j, typ)
|
var argsCounter = 0
|
||||||
|
genOtherArg(p, ri, j, typ, result, argsCounter)
|
||||||
inc j
|
inc j
|
||||||
inc i
|
inc i
|
||||||
of '\'':
|
of '\'':
|
||||||
var idx, stars: int
|
var idx, stars: int
|
||||||
if scanCppGenericSlot(pat, i, idx, stars):
|
if scanCppGenericSlot(pat, i, idx, stars):
|
||||||
var t = resolveStarsInCppType(typ, idx, stars)
|
var t = resolveStarsInCppType(typ, idx, stars)
|
||||||
if t == nil: result.add(~"void")
|
if t == nil: result.add("void")
|
||||||
else: result.add(getTypeDesc(p.module, t))
|
else: result.add(getTypeDesc(p.module, t))
|
||||||
else:
|
else:
|
||||||
let start = i
|
let start = i
|
||||||
|
|
@ -665,10 +677,11 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
assert(typ.kind == tyProc)
|
assert(typ.kind == tyProc)
|
||||||
assert(typ.len == typ.n.len)
|
assert(typ.len == typ.n.len)
|
||||||
# don't call '$' here for efficiency:
|
# don't call '$' here for efficiency:
|
||||||
let pat = ri[0].sym.loc.r.data
|
let pat = $ri[0].sym.loc.r
|
||||||
internalAssert p.config, pat.len > 0
|
internalAssert p.config, pat.len > 0
|
||||||
if pat.contains({'#', '(', '@', '\''}):
|
if pat.contains({'#', '(', '@', '\''}):
|
||||||
var pl = genPatternCall(p, ri, pat, typ)
|
var pl = newRopeAppender()
|
||||||
|
genPatternCall(p, ri, pat, typ, pl)
|
||||||
# simpler version of 'fixupCall' that works with the pl+params combination:
|
# simpler version of 'fixupCall' that works with the pl+params combination:
|
||||||
var typ = skipTypes(ri[0].typ, abstractInst)
|
var typ = skipTypes(ri[0].typ, abstractInst)
|
||||||
if typ[0] != nil:
|
if typ[0] != nil:
|
||||||
|
|
@ -687,80 +700,79 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
list.r = pl
|
list.r = pl
|
||||||
genAssignment(p, d, list, {}) # no need for deep copying
|
genAssignment(p, d, list, {}) # no need for deep copying
|
||||||
else:
|
else:
|
||||||
pl.add(~";$n")
|
pl.add(";\n")
|
||||||
line(p, cpsStmts, pl)
|
line(p, cpsStmts, pl)
|
||||||
else:
|
else:
|
||||||
var pl: Rope = nil
|
var pl = newRopeAppender()
|
||||||
#var param = typ.n[1].sym
|
var argsCounter = 0
|
||||||
if 1 < ri.len:
|
if 1 < ri.len:
|
||||||
pl.add(genThisArg(p, ri, 1, typ))
|
genThisArg(p, ri, 1, typ, pl)
|
||||||
pl.add(op.r)
|
pl.add(op.r)
|
||||||
var params: Rope
|
var params = newRopeAppender()
|
||||||
for i in 2..<ri.len:
|
for i in 2..<ri.len:
|
||||||
if params != nil: params.add(~", ")
|
|
||||||
assert(typ.len == typ.n.len)
|
assert(typ.len == typ.n.len)
|
||||||
params.add(genOtherArg(p, ri, i, typ))
|
genOtherArg(p, ri, i, typ, params, argsCounter)
|
||||||
fixupCall(p, le, ri, d, pl, params)
|
fixupCall(p, le, ri, d, pl, params)
|
||||||
|
|
||||||
proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
|
proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
|
||||||
# generates a crappy ObjC call
|
# generates a crappy ObjC call
|
||||||
var op: TLoc
|
var op: TLoc
|
||||||
initLocExpr(p, ri[0], op)
|
initLocExpr(p, ri[0], op)
|
||||||
var pl = ~"["
|
var pl = "["
|
||||||
# getUniqueType() is too expensive here:
|
# getUniqueType() is too expensive here:
|
||||||
var typ = skipTypes(ri[0].typ, abstractInst)
|
var typ = skipTypes(ri[0].typ, abstractInst)
|
||||||
assert(typ.kind == tyProc)
|
assert(typ.kind == tyProc)
|
||||||
assert(typ.len == typ.n.len)
|
assert(typ.len == typ.n.len)
|
||||||
|
|
||||||
# don't call '$' here for efficiency:
|
# don't call '$' here for efficiency:
|
||||||
let pat = ri[0].sym.loc.r.data
|
let pat = $ri[0].sym.loc.r
|
||||||
internalAssert p.config, pat.len > 0
|
internalAssert p.config, pat.len > 0
|
||||||
var start = 3
|
var start = 3
|
||||||
if ' ' in pat:
|
if ' ' in pat:
|
||||||
start = 1
|
start = 1
|
||||||
pl.add(op.r)
|
pl.add(op.r)
|
||||||
if ri.len > 1:
|
if ri.len > 1:
|
||||||
pl.add(~": ")
|
pl.add(": ")
|
||||||
pl.add(genArg(p, ri[1], typ.n[1].sym, ri))
|
genArg(p, ri[1], typ.n[1].sym, ri, pl)
|
||||||
start = 2
|
start = 2
|
||||||
else:
|
else:
|
||||||
if ri.len > 1:
|
if ri.len > 1:
|
||||||
pl.add(genArg(p, ri[1], typ.n[1].sym, ri))
|
genArg(p, ri[1], typ.n[1].sym, ri, pl)
|
||||||
pl.add(~" ")
|
pl.add(" ")
|
||||||
pl.add(op.r)
|
pl.add(op.r)
|
||||||
if ri.len > 2:
|
if ri.len > 2:
|
||||||
pl.add(~": ")
|
pl.add(": ")
|
||||||
pl.add(genArg(p, ri[2], typ.n[2].sym, ri))
|
genArg(p, ri[2], typ.n[2].sym, ri, pl)
|
||||||
for i in start..<ri.len:
|
for i in start..<ri.len:
|
||||||
assert(typ.len == typ.n.len)
|
assert(typ.len == typ.n.len)
|
||||||
if i >= typ.len:
|
if i >= typ.len:
|
||||||
internalError(p.config, ri.info, "varargs for objective C method?")
|
internalError(p.config, ri.info, "varargs for objective C method?")
|
||||||
assert(typ.n[i].kind == nkSym)
|
assert(typ.n[i].kind == nkSym)
|
||||||
var param = typ.n[i].sym
|
var param = typ.n[i].sym
|
||||||
pl.add(~" ")
|
pl.add(" ")
|
||||||
pl.add(param.name.s)
|
pl.add(param.name.s)
|
||||||
pl.add(~": ")
|
pl.add(": ")
|
||||||
pl.add(genArg(p, ri[i], param, ri))
|
genArg(p, ri[i], param, ri, pl)
|
||||||
if typ[0] != nil:
|
if typ[0] != nil:
|
||||||
if isInvalidReturnType(p.config, typ):
|
if isInvalidReturnType(p.config, typ):
|
||||||
if ri.len > 1: pl.add(~" ")
|
if ri.len > 1: pl.add(" ")
|
||||||
# beware of 'result = p(result)'. We always allocate a temporary:
|
# beware of 'result = p(result)'. We always allocate a temporary:
|
||||||
if d.k in {locTemp, locNone}:
|
if d.k in {locTemp, locNone}:
|
||||||
# We already got a temp. Great, special case it:
|
# We already got a temp. Great, special case it:
|
||||||
if d.k == locNone: getTemp(p, typ[0], d, needsInit=true)
|
if d.k == locNone: getTemp(p, typ[0], d, needsInit=true)
|
||||||
pl.add(~"Result: ")
|
pl.add("Result: ")
|
||||||
pl.add(addrLoc(p.config, d))
|
pl.add(addrLoc(p.config, d))
|
||||||
pl.add(~"];$n")
|
pl.add("];\n")
|
||||||
line(p, cpsStmts, pl)
|
line(p, cpsStmts, pl)
|
||||||
else:
|
else:
|
||||||
var tmp: TLoc
|
var tmp: TLoc
|
||||||
getTemp(p, typ[0], tmp, needsInit=true)
|
getTemp(p, typ[0], tmp, needsInit=true)
|
||||||
pl.add(addrLoc(p.config, tmp))
|
pl.add(addrLoc(p.config, tmp))
|
||||||
pl.add(~"];$n")
|
pl.add("];\n")
|
||||||
line(p, cpsStmts, pl)
|
line(p, cpsStmts, pl)
|
||||||
genAssignment(p, d, tmp, {}) # no need for deep copying
|
genAssignment(p, d, tmp, {}) # no need for deep copying
|
||||||
else:
|
else:
|
||||||
pl.add(~"]")
|
pl.add("]")
|
||||||
if d.k == locNone: getTemp(p, typ[0], d)
|
if d.k == locNone: getTemp(p, typ[0], d)
|
||||||
assert(d.t != nil) # generate an assignment to d:
|
assert(d.t != nil) # generate an assignment to d:
|
||||||
var list: TLoc
|
var list: TLoc
|
||||||
|
|
@ -768,7 +780,7 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
|
||||||
list.r = pl
|
list.r = pl
|
||||||
genAssignment(p, d, list, {}) # no need for deep copying
|
genAssignment(p, d, list, {}) # no need for deep copying
|
||||||
else:
|
else:
|
||||||
pl.add(~"];$n")
|
pl.add("];\n")
|
||||||
line(p, cpsStmts, pl)
|
line(p, cpsStmts, pl)
|
||||||
|
|
||||||
proc notYetAlive(n: PNode): bool {.inline.} =
|
proc notYetAlive(n: PNode): bool {.inline.} =
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -32,82 +32,87 @@ proc detectSeqVersion(m: BModule): int =
|
||||||
|
|
||||||
# ----- Version 1: GC'ed strings and seqs --------------------------------
|
# ----- Version 1: GC'ed strings and seqs --------------------------------
|
||||||
|
|
||||||
proc genStringLiteralDataOnlyV1(m: BModule, s: string): Rope =
|
proc genStringLiteralDataOnlyV1(m: BModule, s: string; result: var Rope) =
|
||||||
discard cgsym(m, "TGenericSeq")
|
cgsym(m, "TGenericSeq")
|
||||||
result = getTempName(m)
|
let tmp = getTempName(m)
|
||||||
m.s[cfsData].addf("STRING_LITERAL($1, $2, $3);$n",
|
result.add tmp
|
||||||
[result, makeCString(s), rope(s.len)])
|
m.s[cfsStrData].addf("STRING_LITERAL($1, $2, $3);$n",
|
||||||
|
[tmp, makeCString(s), rope(s.len)])
|
||||||
|
|
||||||
proc genStringLiteralV1(m: BModule; n: PNode): Rope =
|
proc genStringLiteralV1(m: BModule; n: PNode; result: var Rope) =
|
||||||
if s.isNil:
|
if s.isNil:
|
||||||
result = ropecg(m, "((#NimStringDesc*) NIM_NIL)", [])
|
appcg(m, result, "((#NimStringDesc*) NIM_NIL)", [])
|
||||||
else:
|
else:
|
||||||
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
|
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
|
||||||
if id == m.labels:
|
if id == m.labels:
|
||||||
# string literal not found in the cache:
|
# string literal not found in the cache:
|
||||||
result = ropecg(m, "((#NimStringDesc*) &$1)",
|
appcg(m, result, "((#NimStringDesc*) &", [])
|
||||||
[genStringLiteralDataOnlyV1(m, n.strVal)])
|
genStringLiteralDataOnlyV1(m, n.strVal, result)
|
||||||
|
result.add ")"
|
||||||
else:
|
else:
|
||||||
result = ropecg(m, "((#NimStringDesc*) &$1$2)",
|
appcg(m, result, "((#NimStringDesc*) &$1$2)",
|
||||||
[m.tmpBase, id])
|
[m.tmpBase, id])
|
||||||
|
|
||||||
# ------ Version 2: destructor based strings and seqs -----------------------
|
# ------ Version 2: destructor based strings and seqs -----------------------
|
||||||
|
|
||||||
proc genStringLiteralDataOnlyV2(m: BModule, s: string; result: Rope; isConst: bool) =
|
proc genStringLiteralDataOnlyV2(m: BModule, s: string; result: Rope; isConst: bool) =
|
||||||
m.s[cfsData].addf("static $4 struct {$n" &
|
m.s[cfsStrData].addf("static $4 struct {$n" &
|
||||||
" NI cap; NIM_CHAR data[$2+1];$n" &
|
" NI cap; NIM_CHAR data[$2+1];$n" &
|
||||||
"} $1 = { $2 | NIM_STRLIT_FLAG, $3 };$n",
|
"} $1 = { $2 | NIM_STRLIT_FLAG, $3 };$n",
|
||||||
[result, rope(s.len), makeCString(s),
|
[result, rope(s.len), makeCString(s),
|
||||||
rope(if isConst: "const" else: "")])
|
rope(if isConst: "const" else: "")])
|
||||||
|
|
||||||
proc genStringLiteralV2(m: BModule; n: PNode; isConst: bool): Rope =
|
proc genStringLiteralV2(m: BModule; n: PNode; isConst: bool; result: var Rope) =
|
||||||
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
|
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
|
||||||
if id == m.labels:
|
if id == m.labels:
|
||||||
let pureLit = getTempName(m)
|
let pureLit = getTempName(m)
|
||||||
genStringLiteralDataOnlyV2(m, n.strVal, pureLit, isConst)
|
genStringLiteralDataOnlyV2(m, n.strVal, pureLit, isConst)
|
||||||
result = getTempName(m)
|
let tmp = getTempName(m)
|
||||||
discard cgsym(m, "NimStrPayload")
|
result.add tmp
|
||||||
discard cgsym(m, "NimStringV2")
|
cgsym(m, "NimStrPayload")
|
||||||
|
cgsym(m, "NimStringV2")
|
||||||
# string literal not found in the cache:
|
# string literal not found in the cache:
|
||||||
m.s[cfsData].addf("static $4 NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
|
m.s[cfsStrData].addf("static $4 NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
|
||||||
[result, rope(n.strVal.len), pureLit, rope(if isConst: "const" else: "")])
|
[tmp, rope(n.strVal.len), pureLit, rope(if isConst: "const" else: "")])
|
||||||
else:
|
else:
|
||||||
result = getTempName(m)
|
let tmp = getTempName(m)
|
||||||
m.s[cfsData].addf("static $4 NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
|
result.add tmp
|
||||||
[result, rope(n.strVal.len), m.tmpBase & rope(id),
|
m.s[cfsStrData].addf("static $4 NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
|
||||||
|
[tmp, rope(n.strVal.len), m.tmpBase & rope(id),
|
||||||
rope(if isConst: "const" else: "")])
|
rope(if isConst: "const" else: "")])
|
||||||
|
|
||||||
proc genStringLiteralV2Const(m: BModule; n: PNode; isConst: bool): Rope =
|
proc genStringLiteralV2Const(m: BModule; n: PNode; isConst: bool; result: var Rope) =
|
||||||
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
|
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
|
||||||
var pureLit: Rope
|
var pureLit: Rope
|
||||||
if id == m.labels:
|
if id == m.labels:
|
||||||
pureLit = getTempName(m)
|
pureLit = getTempName(m)
|
||||||
discard cgsym(m, "NimStrPayload")
|
cgsym(m, "NimStrPayload")
|
||||||
discard cgsym(m, "NimStringV2")
|
cgsym(m, "NimStringV2")
|
||||||
# string literal not found in the cache:
|
# string literal not found in the cache:
|
||||||
genStringLiteralDataOnlyV2(m, n.strVal, pureLit, isConst)
|
genStringLiteralDataOnlyV2(m, n.strVal, pureLit, isConst)
|
||||||
else:
|
else:
|
||||||
pureLit = m.tmpBase & rope(id)
|
pureLit = m.tmpBase & rope(id)
|
||||||
result = "{$1, (NimStrPayload*)&$2}" % [rope(n.strVal.len), pureLit]
|
result.addf "{$1, (NimStrPayload*)&$2}", [rope(n.strVal.len), pureLit]
|
||||||
|
|
||||||
# ------ Version selector ---------------------------------------------------
|
# ------ Version selector ---------------------------------------------------
|
||||||
|
|
||||||
proc genStringLiteralDataOnly(m: BModule; s: string; info: TLineInfo;
|
proc genStringLiteralDataOnly(m: BModule; s: string; info: TLineInfo;
|
||||||
isConst: bool): Rope =
|
isConst: bool; result: var Rope) =
|
||||||
case detectStrVersion(m)
|
case detectStrVersion(m)
|
||||||
of 0, 1: result = genStringLiteralDataOnlyV1(m, s)
|
of 0, 1: genStringLiteralDataOnlyV1(m, s, result)
|
||||||
of 2:
|
of 2:
|
||||||
result = getTempName(m)
|
let tmp = getTempName(m)
|
||||||
genStringLiteralDataOnlyV2(m, s, result, isConst)
|
genStringLiteralDataOnlyV2(m, s, tmp, isConst)
|
||||||
|
result.add tmp
|
||||||
else:
|
else:
|
||||||
localError(m.config, info, "cannot determine how to produce code for string literal")
|
localError(m.config, info, "cannot determine how to produce code for string literal")
|
||||||
|
|
||||||
proc genNilStringLiteral(m: BModule; info: TLineInfo): Rope =
|
proc genNilStringLiteral(m: BModule; info: TLineInfo; result: var Rope) =
|
||||||
result = ropecg(m, "((#NimStringDesc*) NIM_NIL)", [])
|
appcg(m, result, "((#NimStringDesc*) NIM_NIL)", [])
|
||||||
|
|
||||||
proc genStringLiteral(m: BModule; n: PNode): Rope =
|
proc genStringLiteral(m: BModule; n: PNode; result: var Rope) =
|
||||||
case detectStrVersion(m)
|
case detectStrVersion(m)
|
||||||
of 0, 1: result = genStringLiteralV1(m, n)
|
of 0, 1: genStringLiteralV1(m, n, result)
|
||||||
of 2: result = genStringLiteralV2(m, n, isConst = true)
|
of 2: genStringLiteralV2(m, n, isConst = true, result)
|
||||||
else:
|
else:
|
||||||
localError(m.config, n.info, "cannot determine how to produce code for string literal")
|
localError(m.config, n.info, "cannot determine how to produce code for string literal")
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ proc specializeResetN(p: BProc, accessor: Rope, n: PNode;
|
||||||
of nkRecCase:
|
of nkRecCase:
|
||||||
if (n[0].kind != nkSym): internalError(p.config, n.info, "specializeResetN")
|
if (n[0].kind != nkSym): internalError(p.config, n.info, "specializeResetN")
|
||||||
let disc = n[0].sym
|
let disc = n[0].sym
|
||||||
if disc.loc.r == nil: fillObjectFields(p.module, typ)
|
if disc.loc.r == "": fillObjectFields(p.module, typ)
|
||||||
if disc.loc.t == nil:
|
if disc.loc.t == nil:
|
||||||
internalError(p.config, n.info, "specializeResetN()")
|
internalError(p.config, n.info, "specializeResetN()")
|
||||||
lineF(p, cpsStmts, "switch ($1.$2) {$n", [accessor, disc.loc.r])
|
lineF(p, cpsStmts, "switch ($1.$2) {$n", [accessor, disc.loc.r])
|
||||||
|
|
@ -42,7 +42,7 @@ proc specializeResetN(p: BProc, accessor: Rope, n: PNode;
|
||||||
of nkSym:
|
of nkSym:
|
||||||
let field = n.sym
|
let field = n.sym
|
||||||
if field.typ.kind == tyVoid: return
|
if field.typ.kind == tyVoid: return
|
||||||
if field.loc.r == nil: fillObjectFields(p.module, typ)
|
if field.loc.r == "": fillObjectFields(p.module, typ)
|
||||||
if field.loc.t == nil:
|
if field.loc.t == nil:
|
||||||
internalError(p.config, n.info, "specializeResetN()")
|
internalError(p.config, n.info, "specializeResetN()")
|
||||||
specializeResetT(p, "$1.$2" % [accessor, field.loc.r], field.loc.t)
|
specializeResetT(p, "$1.$2" % [accessor, field.loc.r], field.loc.t)
|
||||||
|
|
|
||||||
|
|
@ -15,21 +15,22 @@ const
|
||||||
stringCaseThreshold = 8
|
stringCaseThreshold = 8
|
||||||
# above X strings a hash-switch for strings is generated
|
# above X strings a hash-switch for strings is generated
|
||||||
|
|
||||||
proc getTraverseProc(p: BProc, v: PSym): Rope =
|
proc registerTraverseProc(p: BProc, v: PSym) =
|
||||||
|
var traverseProc = ""
|
||||||
if p.config.selectedGC in {gcMarkAndSweep, gcHooks, gcRefc} and
|
if p.config.selectedGC in {gcMarkAndSweep, gcHooks, gcRefc} and
|
||||||
optOwnedRefs notin p.config.globalOptions and
|
optOwnedRefs notin p.config.globalOptions and
|
||||||
containsGarbageCollectedRef(v.loc.t):
|
containsGarbageCollectedRef(v.loc.t):
|
||||||
# we register a specialized marked proc here; this has the advantage
|
# we register a specialized marked proc here; this has the advantage
|
||||||
# that it works out of the box for thread local storage then :-)
|
# that it works out of the box for thread local storage then :-)
|
||||||
result = genTraverseProcForGlobal(p.module, v, v.info)
|
traverseProc = genTraverseProcForGlobal(p.module, v, v.info)
|
||||||
|
|
||||||
proc registerTraverseProc(p: BProc, v: PSym, traverseProc: Rope) =
|
if traverseProc.len != 0 and not p.hcrOn:
|
||||||
if sfThread in v.flags:
|
if sfThread in v.flags:
|
||||||
appcg(p.module, p.module.preInitProc.procSec(cpsInit),
|
appcg(p.module, p.module.preInitProc.procSec(cpsInit),
|
||||||
"$n\t#nimRegisterThreadLocalMarker($1);$n$n", [traverseProc])
|
"$n\t#nimRegisterThreadLocalMarker($1);$n$n", [traverseProc])
|
||||||
else:
|
else:
|
||||||
appcg(p.module, p.module.preInitProc.procSec(cpsInit),
|
appcg(p.module, p.module.preInitProc.procSec(cpsInit),
|
||||||
"$n\t#nimRegisterGlobalMarker($1);$n$n", [traverseProc])
|
"$n\t#nimRegisterGlobalMarker($1);$n$n", [traverseProc])
|
||||||
|
|
||||||
proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} =
|
proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} =
|
||||||
if n.kind == nkEmpty:
|
if n.kind == nkEmpty:
|
||||||
|
|
@ -54,7 +55,9 @@ proc inExceptBlockLen(p: BProc): int =
|
||||||
proc startBlockInternal(p: BProc): int {.discardable.} =
|
proc startBlockInternal(p: BProc): int {.discardable.} =
|
||||||
inc(p.labels)
|
inc(p.labels)
|
||||||
result = p.blocks.len
|
result = p.blocks.len
|
||||||
setLen(p.blocks, result + 1)
|
|
||||||
|
p.blocks.add initBlock()
|
||||||
|
|
||||||
p.blocks[result].id = p.labels
|
p.blocks[result].id = p.labels
|
||||||
p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16
|
p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16
|
||||||
p.blocks[result].nestedExceptStmts = p.inExceptBlockLen.int16
|
p.blocks[result].nestedExceptStmts = p.inExceptBlockLen.int16
|
||||||
|
|
@ -78,7 +81,7 @@ proc genVarTuple(p: BProc, n: PNode) =
|
||||||
|
|
||||||
# check only the first son
|
# check only the first son
|
||||||
var forHcr = treatGlobalDifferentlyForHCR(p.module, n[0].sym)
|
var forHcr = treatGlobalDifferentlyForHCR(p.module, n[0].sym)
|
||||||
let hcrCond = if forHcr: getTempName(p.module) else: nil
|
let hcrCond = if forHcr: getTempName(p.module) else: ""
|
||||||
var hcrGlobals: seq[tuple[loc: TLoc, tp: Rope]]
|
var hcrGlobals: seq[tuple[loc: TLoc, tp: Rope]]
|
||||||
# determine if the tuple is constructed at top-level scope or inside of a block (if/while/block)
|
# determine if the tuple is constructed at top-level scope or inside of a block (if/while/block)
|
||||||
let isGlobalInBlock = forHcr and p.blocks.len > 2
|
let isGlobalInBlock = forHcr and p.blocks.len > 2
|
||||||
|
|
@ -97,13 +100,10 @@ proc genVarTuple(p: BProc, n: PNode) =
|
||||||
let vn = n[i]
|
let vn = n[i]
|
||||||
let v = vn.sym
|
let v = vn.sym
|
||||||
if sfCompileTime in v.flags: continue
|
if sfCompileTime in v.flags: continue
|
||||||
var traverseProc: Rope
|
|
||||||
if sfGlobal in v.flags:
|
if sfGlobal in v.flags:
|
||||||
assignGlobalVar(p, vn, nil)
|
assignGlobalVar(p, vn, "")
|
||||||
genObjectInit(p, cpsInit, v.typ, v.loc, constructObj)
|
genObjectInit(p, cpsInit, v.typ, v.loc, constructObj)
|
||||||
traverseProc = getTraverseProc(p, v)
|
registerTraverseProc(p, v)
|
||||||
if traverseProc != nil and not p.hcrOn:
|
|
||||||
registerTraverseProc(p, v, traverseProc)
|
|
||||||
else:
|
else:
|
||||||
assignLocalVar(p, vn)
|
assignLocalVar(p, vn)
|
||||||
initLocalVar(p, v, immediateAsgn=isAssignedImmediately(p.config, n[^1]))
|
initLocalVar(p, v, immediateAsgn=isAssignedImmediately(p.config, n[^1]))
|
||||||
|
|
@ -115,7 +115,7 @@ proc genVarTuple(p: BProc, n: PNode) =
|
||||||
field.r = "$1.$2" % [rdLoc(tup), mangleRecFieldName(p.module, t.n[i].sym)]
|
field.r = "$1.$2" % [rdLoc(tup), mangleRecFieldName(p.module, t.n[i].sym)]
|
||||||
putLocIntoDest(p, v.loc, field)
|
putLocIntoDest(p, v.loc, field)
|
||||||
if forHcr or isGlobalInBlock:
|
if forHcr or isGlobalInBlock:
|
||||||
hcrGlobals.add((loc: v.loc, tp: if traverseProc == nil: ~"NULL" else: traverseProc))
|
hcrGlobals.add((loc: v.loc, tp: "NULL"))
|
||||||
|
|
||||||
if forHcr:
|
if forHcr:
|
||||||
# end the block where the tuple gets initialized
|
# end the block where the tuple gets initialized
|
||||||
|
|
@ -145,12 +145,12 @@ proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} =
|
||||||
a.flags.incl(lfEnforceDeref)
|
a.flags.incl(lfEnforceDeref)
|
||||||
expr(p, ri, a)
|
expr(p, ri, a)
|
||||||
|
|
||||||
proc assignLabel(b: var TBlock): Rope {.inline.} =
|
proc assignLabel(b: var TBlock; result: var Rope) {.inline.} =
|
||||||
b.label = "LA" & b.id.rope
|
b.label = "LA" & b.id.rope
|
||||||
result = b.label
|
result.add b.label
|
||||||
|
|
||||||
proc blockBody(b: var TBlock): Rope =
|
proc blockBody(b: var TBlock; result: var Rope) =
|
||||||
result = b.sections[cpsLocals]
|
result.add b.sections[cpsLocals]
|
||||||
if b.frameLen > 0:
|
if b.frameLen > 0:
|
||||||
result.addf("FR_.len+=$1;$n", [b.frameLen.rope])
|
result.addf("FR_.len+=$1;$n", [b.frameLen.rope])
|
||||||
result.add(b.sections[cpsInit])
|
result.add(b.sections[cpsInit])
|
||||||
|
|
@ -159,7 +159,7 @@ proc blockBody(b: var TBlock): Rope =
|
||||||
proc endBlock(p: BProc, blockEnd: Rope) =
|
proc endBlock(p: BProc, blockEnd: Rope) =
|
||||||
let topBlock = p.blocks.len-1
|
let topBlock = p.blocks.len-1
|
||||||
# the block is merged into the parent block
|
# the block is merged into the parent block
|
||||||
p.blocks[topBlock-1].sections[cpsStmts].add(p.blocks[topBlock].blockBody)
|
p.blocks[topBlock].blockBody(p.blocks[topBlock-1].sections[cpsStmts])
|
||||||
setLen(p.blocks, topBlock)
|
setLen(p.blocks, topBlock)
|
||||||
# this is done after the block is popped so $n is
|
# this is done after the block is popped so $n is
|
||||||
# properly indented when pretty printing is enabled
|
# properly indented when pretty printing is enabled
|
||||||
|
|
@ -171,7 +171,7 @@ proc endBlock(p: BProc) =
|
||||||
var blockEnd: Rope
|
var blockEnd: Rope
|
||||||
if frameLen > 0:
|
if frameLen > 0:
|
||||||
blockEnd.addf("FR_.len-=$1;$n", [frameLen.rope])
|
blockEnd.addf("FR_.len-=$1;$n", [frameLen.rope])
|
||||||
if p.blocks[topBlock].label != nil:
|
if p.blocks[topBlock].label.len != 0:
|
||||||
blockEnd.addf("} $1: ;$n", [p.blocks[topBlock].label])
|
blockEnd.addf("} $1: ;$n", [p.blocks[topBlock].label])
|
||||||
else:
|
else:
|
||||||
blockEnd.addf("}$n", [])
|
blockEnd.addf("}$n", [])
|
||||||
|
|
@ -279,17 +279,15 @@ proc genGotoVar(p: BProc; value: PNode) =
|
||||||
else:
|
else:
|
||||||
lineF(p, cpsStmts, "goto NIMSTATE_$#;$n", [value.intVal.rope])
|
lineF(p, cpsStmts, "goto NIMSTATE_$#;$n", [value.intVal.rope])
|
||||||
|
|
||||||
proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType): Rope
|
proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType; result: var Rope)
|
||||||
|
|
||||||
proc potentialValueInit(p: BProc; v: PSym; value: PNode): Rope =
|
proc potentialValueInit(p: BProc; v: PSym; value: PNode; result: var Rope) =
|
||||||
if lfDynamicLib in v.loc.flags or sfThread in v.flags or p.hcrOn:
|
if lfDynamicLib in v.loc.flags or sfThread in v.flags or p.hcrOn:
|
||||||
result = nil
|
discard "nothing to do"
|
||||||
elif sfGlobal in v.flags and value != nil and isDeepConstExpr(value, p.module.compileToCpp) and
|
elif sfGlobal in v.flags and value != nil and isDeepConstExpr(value, p.module.compileToCpp) and
|
||||||
p.withinLoop == 0 and not containsGarbageCollectedRef(v.typ):
|
p.withinLoop == 0 and not containsGarbageCollectedRef(v.typ):
|
||||||
#echo "New code produced for ", v.name.s, " ", p.config $ value.info
|
#echo "New code produced for ", v.name.s, " ", p.config $ value.info
|
||||||
result = genBracedInit(p, value, isConst = false, v.typ)
|
genBracedInit(p, value, isConst = false, v.typ, result)
|
||||||
else:
|
|
||||||
result = nil
|
|
||||||
|
|
||||||
proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
||||||
if sfGoto in v.flags:
|
if sfGoto in v.flags:
|
||||||
|
|
@ -297,8 +295,8 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
||||||
genGotoVar(p, value)
|
genGotoVar(p, value)
|
||||||
return
|
return
|
||||||
var targetProc = p
|
var targetProc = p
|
||||||
var traverseProc: Rope
|
var valueAsRope = ""
|
||||||
let valueAsRope = potentialValueInit(p, v, value)
|
potentialValueInit(p, v, value, valueAsRope)
|
||||||
if sfGlobal in v.flags:
|
if sfGlobal in v.flags:
|
||||||
if v.flags * {sfImportc, sfExportc} == {sfImportc} and
|
if v.flags * {sfImportc, sfExportc} == {sfImportc} and
|
||||||
value.kind == nkEmpty and
|
value.kind == nkEmpty and
|
||||||
|
|
@ -314,7 +312,7 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
||||||
# That's why we are doing the construction inside the preInitProc.
|
# That's why we are doing the construction inside the preInitProc.
|
||||||
# genObjectInit relies on the C runtime's guarantees that
|
# genObjectInit relies on the C runtime's guarantees that
|
||||||
# global variables will be initialized to zero.
|
# global variables will be initialized to zero.
|
||||||
if valueAsRope == nil:
|
if valueAsRope.len == 0:
|
||||||
var loc = v.loc
|
var loc = v.loc
|
||||||
|
|
||||||
# When the native TLS is unavailable, a global thread-local variable needs
|
# When the native TLS is unavailable, a global thread-local variable needs
|
||||||
|
|
@ -328,9 +326,7 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
||||||
# if sfImportc notin v.flags: constructLoc(p.module.preInitProc, v.loc)
|
# if sfImportc notin v.flags: constructLoc(p.module.preInitProc, v.loc)
|
||||||
if sfExportc in v.flags and p.module.g.generatedHeader != nil:
|
if sfExportc in v.flags and p.module.g.generatedHeader != nil:
|
||||||
genVarPrototype(p.module.g.generatedHeader, vn)
|
genVarPrototype(p.module.g.generatedHeader, vn)
|
||||||
traverseProc = getTraverseProc(p, v)
|
registerTraverseProc(p, v)
|
||||||
if traverseProc != nil and not p.hcrOn:
|
|
||||||
registerTraverseProc(p, v, traverseProc)
|
|
||||||
else:
|
else:
|
||||||
let imm = isAssignedImmediately(p.config, value)
|
let imm = isAssignedImmediately(p.config, value)
|
||||||
if imm and p.module.compileToCpp and p.splitDecls == 0 and
|
if imm and p.module.compileToCpp and p.splitDecls == 0 and
|
||||||
|
|
@ -343,14 +339,14 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
||||||
var tmp: TLoc
|
var tmp: TLoc
|
||||||
if value.kind in nkCallKinds and value[0].kind == nkSym and
|
if value.kind in nkCallKinds and value[0].kind == nkSym and
|
||||||
sfConstructor in value[0].sym.flags:
|
sfConstructor in value[0].sym.flags:
|
||||||
var params: Rope
|
var params = newRopeAppender()
|
||||||
|
var argsCounter = 0
|
||||||
let typ = skipTypes(value[0].typ, abstractInst)
|
let typ = skipTypes(value[0].typ, abstractInst)
|
||||||
assert(typ.kind == tyProc)
|
assert(typ.kind == tyProc)
|
||||||
for i in 1..<value.len:
|
for i in 1..<value.len:
|
||||||
if params != nil: params.add(~", ")
|
|
||||||
assert(typ.len == typ.n.len)
|
assert(typ.len == typ.n.len)
|
||||||
params.add(genOtherArg(p, value, i, typ))
|
genOtherArg(p, value, i, typ, params, argsCounter)
|
||||||
if params == nil:
|
if params.len == 0:
|
||||||
lineF(p, cpsStmts, "$#;$n", [decl])
|
lineF(p, cpsStmts, "$#;$n", [decl])
|
||||||
else:
|
else:
|
||||||
lineF(p, cpsStmts, "$#($#);$n", [decl, params])
|
lineF(p, cpsStmts, "$#($#);$n", [decl, params])
|
||||||
|
|
@ -361,7 +357,7 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
||||||
assignLocalVar(p, vn)
|
assignLocalVar(p, vn)
|
||||||
initLocalVar(p, v, imm)
|
initLocalVar(p, v, imm)
|
||||||
|
|
||||||
if traverseProc == nil: traverseProc = ~"NULL"
|
let traverseProc = "NULL"
|
||||||
# If the var is in a block (control flow like if/while or a block) in global scope just
|
# If the var is in a block (control flow like if/while or a block) in global scope just
|
||||||
# register the so called "global" so it can be used later on. There is no need to close
|
# register the so called "global" so it can be used later on. There is no need to close
|
||||||
# and reopen of if (nim_hcr_do_init_) blocks because we are in one already anyway.
|
# and reopen of if (nim_hcr_do_init_) blocks because we are in one already anyway.
|
||||||
|
|
@ -381,7 +377,7 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
||||||
lineCg(targetProc, cpsStmts, "if (hcrRegisterGlobal($3, \"$1\", sizeof($2), $4, (void**)&$1))$N",
|
lineCg(targetProc, cpsStmts, "if (hcrRegisterGlobal($3, \"$1\", sizeof($2), $4, (void**)&$1))$N",
|
||||||
[v.loc.r, rdLoc(v.loc), getModuleDllPath(p.module, v), traverseProc])
|
[v.loc.r, rdLoc(v.loc), getModuleDllPath(p.module, v), traverseProc])
|
||||||
startBlock(targetProc)
|
startBlock(targetProc)
|
||||||
if value.kind != nkEmpty and valueAsRope == nil:
|
if value.kind != nkEmpty and valueAsRope.len == 0:
|
||||||
genLineDir(targetProc, vn)
|
genLineDir(targetProc, vn)
|
||||||
loadInto(targetProc, vn, value, v.loc)
|
loadInto(targetProc, vn, value, v.loc)
|
||||||
if forHcr:
|
if forHcr:
|
||||||
|
|
@ -560,7 +556,9 @@ proc genComputedGoto(p: BProc; n: PNode) =
|
||||||
return
|
return
|
||||||
|
|
||||||
let val = getOrdValue(it[j])
|
let val = getOrdValue(it[j])
|
||||||
lineF(p, cpsStmts, "TMP$#_:$n", [intLiteral(toInt64(val)+id+1)])
|
var lit = newRopeAppender()
|
||||||
|
intLiteral(toInt64(val)+id+1, lit)
|
||||||
|
lineF(p, cpsStmts, "TMP$#_:$n", [lit])
|
||||||
|
|
||||||
genStmts(p, it.lastSon)
|
genStmts(p, it.lastSon)
|
||||||
|
|
||||||
|
|
@ -614,8 +612,9 @@ proc genWhileStmt(p: BProc, t: PNode) =
|
||||||
p.blocks[p.breakIdx].isLoop = true
|
p.blocks[p.breakIdx].isLoop = true
|
||||||
initLocExpr(p, t[0], a)
|
initLocExpr(p, t[0], a)
|
||||||
if (t[0].kind != nkIntLit) or (t[0].intVal == 0):
|
if (t[0].kind != nkIntLit) or (t[0].intVal == 0):
|
||||||
let label = assignLabel(p.blocks[p.breakIdx])
|
lineF(p, cpsStmts, "if (!$1) goto ", [rdLoc(a)])
|
||||||
lineF(p, cpsStmts, "if (!$1) goto $2;$n", [rdLoc(a), label])
|
assignLabel(p.blocks[p.breakIdx], p.s(cpsStmts))
|
||||||
|
lineF(p, cpsStmts, ";$n", [])
|
||||||
genStmts(p, loopBody)
|
genStmts(p, loopBody)
|
||||||
|
|
||||||
if optProfiler in p.options:
|
if optProfiler in p.options:
|
||||||
|
|
@ -702,12 +701,12 @@ proc genBreakStmt(p: BProc, t: PNode) =
|
||||||
while idx >= 0 and not p.blocks[idx].isLoop: dec idx
|
while idx >= 0 and not p.blocks[idx].isLoop: dec idx
|
||||||
if idx < 0 or not p.blocks[idx].isLoop:
|
if idx < 0 or not p.blocks[idx].isLoop:
|
||||||
internalError(p.config, t.info, "no loop to break")
|
internalError(p.config, t.info, "no loop to break")
|
||||||
let label = assignLabel(p.blocks[idx])
|
p.blocks[idx].label = "LA" & p.blocks[idx].id.rope
|
||||||
blockLeaveActions(p,
|
blockLeaveActions(p,
|
||||||
p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts,
|
p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts,
|
||||||
p.inExceptBlockLen - p.blocks[idx].nestedExceptStmts)
|
p.inExceptBlockLen - p.blocks[idx].nestedExceptStmts)
|
||||||
genLineDir(p, t)
|
genLineDir(p, t)
|
||||||
lineF(p, cpsStmts, "goto $1;$n", [label])
|
lineF(p, cpsStmts, "goto $1;$n", [p.blocks[idx].label])
|
||||||
|
|
||||||
proc raiseExit(p: BProc) =
|
proc raiseExit(p: BProc) =
|
||||||
assert p.config.exc == excGoto
|
assert p.config.exc == excGoto
|
||||||
|
|
@ -729,21 +728,19 @@ proc finallyActions(p: BProc) =
|
||||||
if finallyBlock != nil:
|
if finallyBlock != nil:
|
||||||
genSimpleBlock(p, finallyBlock[0])
|
genSimpleBlock(p, finallyBlock[0])
|
||||||
|
|
||||||
proc raiseInstr(p: BProc): Rope =
|
proc raiseInstr(p: BProc; result: var Rope) =
|
||||||
if p.config.exc == excGoto:
|
if p.config.exc == excGoto:
|
||||||
let L = p.nestedTryStmts.len
|
let L = p.nestedTryStmts.len
|
||||||
if L == 0:
|
if L == 0:
|
||||||
p.flags.incl beforeRetNeeded
|
p.flags.incl beforeRetNeeded
|
||||||
# easy case, simply goto 'ret':
|
# easy case, simply goto 'ret':
|
||||||
result = ropecg(p.module, "goto BeforeRet_;$n", [])
|
result.add ropecg(p.module, "goto BeforeRet_;$n", [])
|
||||||
else:
|
else:
|
||||||
# raise inside an 'except' must go to the finally block,
|
# raise inside an 'except' must go to the finally block,
|
||||||
# raise outside an 'except' block must go to the 'except' list.
|
# raise outside an 'except' block must go to the 'except' list.
|
||||||
result = ropecg(p.module, "goto LA$1_;$n",
|
result.add ropecg(p.module, "goto LA$1_;$n",
|
||||||
[p.nestedTryStmts[L-1].label])
|
[p.nestedTryStmts[L-1].label])
|
||||||
# + ord(p.nestedTryStmts[L-1].inExcept)])
|
# + ord(p.nestedTryStmts[L-1].inExcept)])
|
||||||
else:
|
|
||||||
result = nil
|
|
||||||
|
|
||||||
proc genRaiseStmt(p: BProc, t: PNode) =
|
proc genRaiseStmt(p: BProc, t: PNode) =
|
||||||
if t[0].kind != nkEmpty:
|
if t[0].kind != nkEmpty:
|
||||||
|
|
@ -772,12 +769,10 @@ proc genRaiseStmt(p: BProc, t: PNode) =
|
||||||
genLineDir(p, t)
|
genLineDir(p, t)
|
||||||
# reraise the last exception:
|
# reraise the last exception:
|
||||||
if p.config.exc == excCpp:
|
if p.config.exc == excCpp:
|
||||||
line(p, cpsStmts, ~"throw;$n")
|
line(p, cpsStmts, "throw;\n")
|
||||||
else:
|
else:
|
||||||
linefmt(p, cpsStmts, "#reraiseException();$n", [])
|
linefmt(p, cpsStmts, "#reraiseException();$n", [])
|
||||||
let gotoInstr = raiseInstr(p)
|
raiseInstr(p, p.s(cpsStmts))
|
||||||
if gotoInstr != nil:
|
|
||||||
line(p, cpsStmts, gotoInstr)
|
|
||||||
|
|
||||||
template genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
|
template genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
|
||||||
rangeFormat, eqFormat: FormatStr, labl: TLabel) =
|
rangeFormat, eqFormat: FormatStr, labl: TLabel) =
|
||||||
|
|
@ -885,9 +880,11 @@ proc genStringCase(p: BProc, t: PNode, stringKind: TTypeKind, d: var TLoc) =
|
||||||
linefmt(p, cpsStmts, "switch (#hashString($1) & $2) {$n",
|
linefmt(p, cpsStmts, "switch (#hashString($1) & $2) {$n",
|
||||||
[rdLoc(a), bitMask])
|
[rdLoc(a), bitMask])
|
||||||
for j in 0..high(branches):
|
for j in 0..high(branches):
|
||||||
if branches[j] != nil:
|
if branches[j] != "":
|
||||||
|
var lit = newRopeAppender()
|
||||||
|
intLiteral(j, lit)
|
||||||
lineF(p, cpsStmts, "case $1: $n$2break;$n",
|
lineF(p, cpsStmts, "case $1: $n$2break;$n",
|
||||||
[intLiteral(j), branches[j]])
|
[lit, branches[j]])
|
||||||
lineF(p, cpsStmts, "}$n", []) # else statement:
|
lineF(p, cpsStmts, "}$n", []) # else statement:
|
||||||
if t[^1].kind != nkOfBranch:
|
if t[^1].kind != nkOfBranch:
|
||||||
lineF(p, cpsStmts, "goto LA$1_;$n", [rope(p.labels)])
|
lineF(p, cpsStmts, "goto LA$1_;$n", [rope(p.labels)])
|
||||||
|
|
@ -921,16 +918,22 @@ proc genCaseRange(p: BProc, branch: PNode) =
|
||||||
for j in 0..<branch.len-1:
|
for j in 0..<branch.len-1:
|
||||||
if branch[j].kind == nkRange:
|
if branch[j].kind == nkRange:
|
||||||
if hasSwitchRange in CC[p.config.cCompiler].props:
|
if hasSwitchRange in CC[p.config.cCompiler].props:
|
||||||
lineF(p, cpsStmts, "case $1 ... $2:$n", [
|
var litA = newRopeAppender()
|
||||||
genLiteral(p, branch[j][0]),
|
var litB = newRopeAppender()
|
||||||
genLiteral(p, branch[j][1])])
|
genLiteral(p, branch[j][0], litA)
|
||||||
|
genLiteral(p, branch[j][1], litB)
|
||||||
|
lineF(p, cpsStmts, "case $1 ... $2:$n", [litA, litB])
|
||||||
else:
|
else:
|
||||||
var v = copyNode(branch[j][0])
|
var v = copyNode(branch[j][0])
|
||||||
while v.intVal <= branch[j][1].intVal:
|
while v.intVal <= branch[j][1].intVal:
|
||||||
lineF(p, cpsStmts, "case $1:$n", [genLiteral(p, v)])
|
var litA = newRopeAppender()
|
||||||
|
genLiteral(p, v, litA)
|
||||||
|
lineF(p, cpsStmts, "case $1:$n", [litA])
|
||||||
inc(v.intVal)
|
inc(v.intVal)
|
||||||
else:
|
else:
|
||||||
lineF(p, cpsStmts, "case $1:$n", [genLiteral(p, branch[j])])
|
var litA = newRopeAppender()
|
||||||
|
genLiteral(p, branch[j], litA)
|
||||||
|
lineF(p, cpsStmts, "case $1:$n", [litA])
|
||||||
|
|
||||||
proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =
|
proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =
|
||||||
# analyse 'case' statement:
|
# analyse 'case' statement:
|
||||||
|
|
@ -942,7 +945,7 @@ proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =
|
||||||
var lend = if splitPoint > 0: genIfForCaseUntil(p, n, d,
|
var lend = if splitPoint > 0: genIfForCaseUntil(p, n, d,
|
||||||
rangeFormat = "if ($1 >= $2 && $1 <= $3) goto $4;$n",
|
rangeFormat = "if ($1 >= $2 && $1 <= $3) goto $4;$n",
|
||||||
eqFormat = "if ($1 == $2) goto $3;$n",
|
eqFormat = "if ($1 == $2) goto $3;$n",
|
||||||
splitPoint, a) else: nil
|
splitPoint, a) else: ""
|
||||||
|
|
||||||
# generate switch part (might be empty):
|
# generate switch part (might be empty):
|
||||||
if splitPoint+1 < n.len:
|
if splitPoint+1 < n.len:
|
||||||
|
|
@ -963,7 +966,7 @@ proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =
|
||||||
if (hasAssume in CC[p.config.cCompiler].props) and not hasDefault:
|
if (hasAssume in CC[p.config.cCompiler].props) and not hasDefault:
|
||||||
lineF(p, cpsStmts, "default: __assume(0);$n", [])
|
lineF(p, cpsStmts, "default: __assume(0);$n", [])
|
||||||
lineF(p, cpsStmts, "}$n", [])
|
lineF(p, cpsStmts, "}$n", [])
|
||||||
if lend != nil: fixLabel(p, lend)
|
if lend != "": fixLabel(p, lend)
|
||||||
|
|
||||||
proc genCase(p: BProc, t: PNode, d: var TLoc) =
|
proc genCase(p: BProc, t: PNode, d: var TLoc) =
|
||||||
genLineDir(p, t)
|
genLineDir(p, t)
|
||||||
|
|
@ -1064,7 +1067,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||||
linefmt(p, cpsStmts, "#popCurrentException();$n", [])
|
linefmt(p, cpsStmts, "#popCurrentException();$n", [])
|
||||||
endBlock(p)
|
endBlock(p)
|
||||||
else:
|
else:
|
||||||
var orExpr = Rope(nil)
|
var orExpr = newRopeAppender()
|
||||||
var exvar = PNode(nil)
|
var exvar = PNode(nil)
|
||||||
for j in 0..<t[i].len - 1:
|
for j in 0..<t[i].len - 1:
|
||||||
var typeNode = t[i][j]
|
var typeNode = t[i][j]
|
||||||
|
|
@ -1075,7 +1078,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||||
if isImportedException(typeNode.typ, p.config):
|
if isImportedException(typeNode.typ, p.config):
|
||||||
hasImportedCppExceptions = true
|
hasImportedCppExceptions = true
|
||||||
else:
|
else:
|
||||||
if orExpr != nil: orExpr.add("||")
|
if orExpr.len != 0: orExpr.add("||")
|
||||||
let checkFor = if optTinyRtti in p.config.globalOptions:
|
let checkFor = if optTinyRtti in p.config.globalOptions:
|
||||||
genTypeInfo2Name(p.module, typeNode.typ)
|
genTypeInfo2Name(p.module, typeNode.typ)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1083,14 +1086,15 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||||
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
|
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
|
||||||
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor])
|
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor])
|
||||||
|
|
||||||
if orExpr != nil:
|
if orExpr.len != 0:
|
||||||
if hasIf:
|
if hasIf:
|
||||||
startBlock(p, "else if ($1) {$n", [orExpr])
|
startBlock(p, "else if ($1) {$n", [orExpr])
|
||||||
else:
|
else:
|
||||||
startBlock(p, "if ($1) {$n", [orExpr])
|
startBlock(p, "if ($1) {$n", [orExpr])
|
||||||
hasIf = true
|
hasIf = true
|
||||||
if exvar != nil:
|
if exvar != nil:
|
||||||
fillLoc(exvar.sym.loc, locTemp, exvar, mangleLocalName(p, exvar.sym), OnStack)
|
fillLocalName(p, exvar.sym)
|
||||||
|
fillLoc(exvar.sym.loc, locTemp, exvar, OnStack)
|
||||||
linefmt(p, cpsStmts, "$1 $2 = T$3_;$n", [getTypeDesc(p.module, exvar.sym.typ),
|
linefmt(p, cpsStmts, "$1 $2 = T$3_;$n", [getTypeDesc(p.module, exvar.sym.typ),
|
||||||
rdLoc(exvar.sym.loc), rope(etmp+1)])
|
rdLoc(exvar.sym.loc), rope(etmp+1)])
|
||||||
# we handled the error:
|
# we handled the error:
|
||||||
|
|
@ -1131,7 +1135,8 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||||
typeNode = t[i][j][1]
|
typeNode = t[i][j][1]
|
||||||
if isImportedException(typeNode.typ, p.config):
|
if isImportedException(typeNode.typ, p.config):
|
||||||
let exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:`
|
let exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:`
|
||||||
fillLoc(exvar.sym.loc, locTemp, exvar, mangleLocalName(p, exvar.sym), OnStack)
|
fillLocalName(p, exvar.sym)
|
||||||
|
fillLoc(exvar.sym.loc, locTemp, exvar, OnStack)
|
||||||
startBlock(p, "catch ($1& $2) {$n", getTypeDesc(p.module, typeNode.typ), rdLoc(exvar.sym.loc))
|
startBlock(p, "catch ($1& $2) {$n", getTypeDesc(p.module, typeNode.typ), rdLoc(exvar.sym.loc))
|
||||||
genExceptBranchBody(t[i][^1]) # exception handler body will duplicated for every type
|
genExceptBranchBody(t[i][^1]) # exception handler body will duplicated for every type
|
||||||
endBlock(p)
|
endBlock(p)
|
||||||
|
|
@ -1184,7 +1189,7 @@ proc genTryCppOld(p: BProc, t: PNode, d: var TLoc) =
|
||||||
if not isEmptyType(t.typ) and d.k == locNone:
|
if not isEmptyType(t.typ) and d.k == locNone:
|
||||||
getTemp(p, t.typ, d)
|
getTemp(p, t.typ, d)
|
||||||
genLineDir(p, t)
|
genLineDir(p, t)
|
||||||
discard cgsym(p.module, "popCurrentExceptionEx")
|
cgsym(p.module, "popCurrentExceptionEx")
|
||||||
let fin = if t[^1].kind == nkFinally: t[^1] else: nil
|
let fin = if t[^1].kind == nkFinally: t[^1] else: nil
|
||||||
p.nestedTryStmts.add((fin, false, 0.Natural))
|
p.nestedTryStmts.add((fin, false, 0.Natural))
|
||||||
startBlock(p, "try {$n")
|
startBlock(p, "try {$n")
|
||||||
|
|
@ -1210,7 +1215,8 @@ proc genTryCppOld(p: BProc, t: PNode, d: var TLoc) =
|
||||||
for j in 0..<t[i].len-1:
|
for j in 0..<t[i].len-1:
|
||||||
if t[i][j].isInfixAs():
|
if t[i][j].isInfixAs():
|
||||||
let exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:`
|
let exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:`
|
||||||
fillLoc(exvar.sym.loc, locTemp, exvar, mangleLocalName(p, exvar.sym), OnUnknown)
|
fillLocalName(p, exvar.sym)
|
||||||
|
fillLoc(exvar.sym.loc, locTemp, exvar, OnUnknown)
|
||||||
startBlock(p, "catch ($1& $2) {$n", getTypeDesc(p.module, t[i][j][1].typ), rdLoc(exvar.sym.loc))
|
startBlock(p, "catch ($1& $2) {$n", getTypeDesc(p.module, t[i][j][1].typ), rdLoc(exvar.sym.loc))
|
||||||
else:
|
else:
|
||||||
startBlock(p, "catch ($1&) {$n", getTypeDesc(p.module, t[i][j].typ))
|
startBlock(p, "catch ($1&) {$n", getTypeDesc(p.module, t[i][j].typ))
|
||||||
|
|
@ -1225,7 +1231,7 @@ proc genTryCppOld(p: BProc, t: PNode, d: var TLoc) =
|
||||||
# finally requires catch all presence
|
# finally requires catch all presence
|
||||||
startBlock(p, "catch (...) {$n")
|
startBlock(p, "catch (...) {$n")
|
||||||
genStmts(p, t[^1][0])
|
genStmts(p, t[^1][0])
|
||||||
line(p, cpsStmts, ~"throw;$n")
|
line(p, cpsStmts, "throw;\n")
|
||||||
endBlock(p)
|
endBlock(p)
|
||||||
|
|
||||||
genSimpleBlock(p, t[^1][0])
|
genSimpleBlock(p, t[^1][0])
|
||||||
|
|
@ -1287,10 +1293,10 @@ proc genTryGoto(p: BProc; t: PNode; d: var TLoc) =
|
||||||
linefmt(p, cpsStmts, "*nimErr_ = NIM_FALSE;$n", [])
|
linefmt(p, cpsStmts, "*nimErr_ = NIM_FALSE;$n", [])
|
||||||
expr(p, t[i][0], d)
|
expr(p, t[i][0], d)
|
||||||
else:
|
else:
|
||||||
var orExpr: Rope = nil
|
var orExpr = newRopeAppender()
|
||||||
for j in 0..<t[i].len - 1:
|
for j in 0..<t[i].len - 1:
|
||||||
assert(t[i][j].kind == nkType)
|
assert(t[i][j].kind == nkType)
|
||||||
if orExpr != nil: orExpr.add("||")
|
if orExpr.len != 0: orExpr.add("||")
|
||||||
let checkFor = if optTinyRtti in p.config.globalOptions:
|
let checkFor = if optTinyRtti in p.config.globalOptions:
|
||||||
genTypeInfo2Name(p.module, t[i][j].typ)
|
genTypeInfo2Name(p.module, t[i][j].typ)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1372,7 +1378,7 @@ proc genTrySetjmp(p: BProc, t: PNode, d: var TLoc) =
|
||||||
else:
|
else:
|
||||||
p.flags.incl noSafePoints
|
p.flags.incl noSafePoints
|
||||||
genLineDir(p, t)
|
genLineDir(p, t)
|
||||||
discard cgsym(p.module, "Exception")
|
cgsym(p.module, "Exception")
|
||||||
var safePoint: Rope
|
var safePoint: Rope
|
||||||
if not quirkyExceptions:
|
if not quirkyExceptions:
|
||||||
safePoint = getTempName(p.module)
|
safePoint = getTempName(p.module)
|
||||||
|
|
@ -1389,7 +1395,7 @@ proc genTrySetjmp(p: BProc, t: PNode, d: var TLoc) =
|
||||||
if isDefined(p.config, "vcc") or isDefined(p.config, "clangcl"):
|
if isDefined(p.config, "vcc") or isDefined(p.config, "clangcl"):
|
||||||
# For the vcc compiler, use `setjmp()` with one argument.
|
# For the vcc compiler, use `setjmp()` with one argument.
|
||||||
# See https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setjmp?view=msvc-170
|
# See https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setjmp?view=msvc-170
|
||||||
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint])
|
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint])
|
||||||
else:
|
else:
|
||||||
# The Windows `_setjmp()` takes two arguments, with the second being an
|
# The Windows `_setjmp()` takes two arguments, with the second being an
|
||||||
# undocumented buffer used by the SEH mechanism for stack unwinding.
|
# undocumented buffer used by the SEH mechanism for stack unwinding.
|
||||||
|
|
@ -1431,10 +1437,10 @@ proc genTrySetjmp(p: BProc, t: PNode, d: var TLoc) =
|
||||||
linefmt(p, cpsStmts, "#popCurrentException();$n", [])
|
linefmt(p, cpsStmts, "#popCurrentException();$n", [])
|
||||||
endBlock(p)
|
endBlock(p)
|
||||||
else:
|
else:
|
||||||
var orExpr: Rope = nil
|
var orExpr = newRopeAppender()
|
||||||
for j in 0..<t[i].len - 1:
|
for j in 0..<t[i].len - 1:
|
||||||
assert(t[i][j].kind == nkType)
|
assert(t[i][j].kind == nkType)
|
||||||
if orExpr != nil: orExpr.add("||")
|
if orExpr.len != 0: orExpr.add("||")
|
||||||
let checkFor = if optTinyRtti in p.config.globalOptions:
|
let checkFor = if optTinyRtti in p.config.globalOptions:
|
||||||
genTypeInfo2Name(p.module, t[i][j].typ)
|
genTypeInfo2Name(p.module, t[i][j].typ)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1466,7 +1472,7 @@ proc genTrySetjmp(p: BProc, t: PNode, d: var TLoc) =
|
||||||
if not quirkyExceptions:
|
if not quirkyExceptions:
|
||||||
linefmt(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint])
|
linefmt(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint])
|
||||||
|
|
||||||
proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): Rope =
|
proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false; result: var Rope) =
|
||||||
var res = ""
|
var res = ""
|
||||||
for it in t.sons:
|
for it in t.sons:
|
||||||
case it.kind
|
case it.kind
|
||||||
|
|
@ -1482,13 +1488,8 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): Rope =
|
||||||
res.add($getTypeDesc(p.module, sym.typ))
|
res.add($getTypeDesc(p.module, sym.typ))
|
||||||
else:
|
else:
|
||||||
discard getTypeDesc(p.module, skipTypes(sym.typ, abstractPtrs))
|
discard getTypeDesc(p.module, skipTypes(sym.typ, abstractPtrs))
|
||||||
var r = sym.loc.r
|
fillBackendName(p.module, sym)
|
||||||
if r == nil:
|
res.add($sym.loc.r)
|
||||||
# if no name has already been given,
|
|
||||||
# it doesn't matter much:
|
|
||||||
r = mangleName(p.module, sym)
|
|
||||||
sym.loc.r = r # but be consequent!
|
|
||||||
res.add($r)
|
|
||||||
of nkTypeOfExpr:
|
of nkTypeOfExpr:
|
||||||
res.add($getTypeDesc(p.module, it.typ))
|
res.add($getTypeDesc(p.module, it.typ))
|
||||||
else:
|
else:
|
||||||
|
|
@ -1513,12 +1514,13 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): Rope =
|
||||||
result.add("\\n\"\n")
|
result.add("\\n\"\n")
|
||||||
else:
|
else:
|
||||||
res.add("\L")
|
res.add("\L")
|
||||||
result = res.rope
|
result.add res.rope
|
||||||
|
|
||||||
proc genAsmStmt(p: BProc, t: PNode) =
|
proc genAsmStmt(p: BProc, t: PNode) =
|
||||||
assert(t.kind == nkAsmStmt)
|
assert(t.kind == nkAsmStmt)
|
||||||
genLineDir(p, t)
|
genLineDir(p, t)
|
||||||
var s = genAsmOrEmitStmt(p, t, isAsmStmt=true)
|
var s = newRopeAppender()
|
||||||
|
genAsmOrEmitStmt(p, t, isAsmStmt=true, s)
|
||||||
# see bug #2362, "top level asm statements" seem to be a mis-feature
|
# see bug #2362, "top level asm statements" seem to be a mis-feature
|
||||||
# but even if we don't do this, the example in #2362 cannot possibly
|
# but even if we don't do this, the example in #2362 cannot possibly
|
||||||
# work:
|
# work:
|
||||||
|
|
@ -1526,7 +1528,8 @@ proc genAsmStmt(p: BProc, t: PNode) =
|
||||||
# top level asm statement?
|
# top level asm statement?
|
||||||
p.module.s[cfsProcHeaders].add runtimeFormat(CC[p.config.cCompiler].asmStmtFrmt, [s])
|
p.module.s[cfsProcHeaders].add runtimeFormat(CC[p.config.cCompiler].asmStmtFrmt, [s])
|
||||||
else:
|
else:
|
||||||
p.s(cpsStmts).add indentLine(p, runtimeFormat(CC[p.config.cCompiler].asmStmtFrmt, [s]))
|
addIndent p, p.s(cpsStmts)
|
||||||
|
p.s(cpsStmts).add runtimeFormat(CC[p.config.cCompiler].asmStmtFrmt, [s])
|
||||||
|
|
||||||
proc determineSection(n: PNode): TCFileSection =
|
proc determineSection(n: PNode): TCFileSection =
|
||||||
result = cfsProcHeaders
|
result = cfsProcHeaders
|
||||||
|
|
@ -1537,7 +1540,8 @@ proc determineSection(n: PNode): TCFileSection =
|
||||||
elif sec.startsWith("/*INCLUDESECTION*/"): result = cfsHeaders
|
elif sec.startsWith("/*INCLUDESECTION*/"): result = cfsHeaders
|
||||||
|
|
||||||
proc genEmit(p: BProc, t: PNode) =
|
proc genEmit(p: BProc, t: PNode) =
|
||||||
var s = genAsmOrEmitStmt(p, t[1])
|
var s = newRopeAppender()
|
||||||
|
genAsmOrEmitStmt(p, t[1], false, s)
|
||||||
if p.prc == nil:
|
if p.prc == nil:
|
||||||
# top level emit pragma?
|
# top level emit pragma?
|
||||||
let section = determineSection(t[1])
|
let section = determineSection(t[1])
|
||||||
|
|
@ -1562,10 +1566,12 @@ proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
|
||||||
if not containsOrIncl(p.module.declaredThings, field.id):
|
if not containsOrIncl(p.module.declaredThings, field.id):
|
||||||
appcg(p.module, cfsVars, "extern $1",
|
appcg(p.module, cfsVars, "extern $1",
|
||||||
[discriminatorTableDecl(p.module, t, field)])
|
[discriminatorTableDecl(p.module, t, field)])
|
||||||
|
var lit = newRopeAppender()
|
||||||
|
intLiteral(toInt64(lengthOrd(p.config, field.typ))+1, lit)
|
||||||
lineCg(p, cpsStmts,
|
lineCg(p, cpsStmts,
|
||||||
"#FieldDiscriminantCheck((NI)(NU)($1), (NI)(NU)($2), $3, $4);$n",
|
"#FieldDiscriminantCheck((NI)(NU)($1), (NI)(NU)($2), $3, $4);$n",
|
||||||
[rdLoc(a), rdLoc(tmp), discriminatorTableName(p.module, t, field),
|
[rdLoc(a), rdLoc(tmp), discriminatorTableName(p.module, t, field),
|
||||||
intLiteral(toInt64(lengthOrd(p.config, field.typ))+1)])
|
lit])
|
||||||
|
|
||||||
when false:
|
when false:
|
||||||
proc genCaseObjDiscMapping(p: BProc, e: PNode, t: PType, field: PSym; d: var TLoc) =
|
proc genCaseObjDiscMapping(p: BProc, e: PNode, t: PType, field: PSym; d: var TLoc) =
|
||||||
|
|
|
||||||
|
|
@ -44,13 +44,13 @@ proc declareThreadVar(m: BModule, s: PSym, isExtern: bool) =
|
||||||
m.s[cfsVars].addf(" $1;$n", [s.loc.r])
|
m.s[cfsVars].addf(" $1;$n", [s.loc.r])
|
||||||
|
|
||||||
proc generateThreadLocalStorage(m: BModule) =
|
proc generateThreadLocalStorage(m: BModule) =
|
||||||
if m.g.nimtv != nil and (usesThreadVars in m.flags or sfMainModule in m.module.flags):
|
if m.g.nimtv != "" and (usesThreadVars in m.flags or sfMainModule in m.module.flags):
|
||||||
for t in items(m.g.nimtvDeps): discard getTypeDesc(m, t)
|
for t in items(m.g.nimtvDeps): discard getTypeDesc(m, t)
|
||||||
finishTypeDescriptions(m)
|
finishTypeDescriptions(m)
|
||||||
m.s[cfsSeqTypes].addf("typedef struct {$1} NimThreadVars;$n", [m.g.nimtv])
|
m.s[cfsSeqTypes].addf("typedef struct {$1} NimThreadVars;$n", [m.g.nimtv])
|
||||||
|
|
||||||
proc generateThreadVarsSize(m: BModule) =
|
proc generateThreadVarsSize(m: BModule) =
|
||||||
if m.g.nimtv != nil:
|
if m.g.nimtv != "":
|
||||||
let externc = if m.config.backend == backendCpp or
|
let externc = if m.config.backend == backendCpp or
|
||||||
sfCompileToCpp in m.module.flags: "extern \"C\" "
|
sfCompileToCpp in m.module.flags: "extern \"C\" "
|
||||||
else: ""
|
else: ""
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, n: PNode;
|
||||||
if (n[0].kind != nkSym): internalError(c.p.config, n.info, "genTraverseProc")
|
if (n[0].kind != nkSym): internalError(c.p.config, n.info, "genTraverseProc")
|
||||||
var p = c.p
|
var p = c.p
|
||||||
let disc = n[0].sym
|
let disc = n[0].sym
|
||||||
if disc.loc.r == nil: fillObjectFields(c.p.module, typ)
|
if disc.loc.r == "": fillObjectFields(c.p.module, typ)
|
||||||
if disc.loc.t == nil:
|
if disc.loc.t == nil:
|
||||||
internalError(c.p.config, n.info, "genTraverseProc()")
|
internalError(c.p.config, n.info, "genTraverseProc()")
|
||||||
lineF(p, cpsStmts, "switch ($1.$2) {$n", [accessor, disc.loc.r])
|
lineF(p, cpsStmts, "switch ($1.$2) {$n", [accessor, disc.loc.r])
|
||||||
|
|
@ -51,7 +51,7 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, n: PNode;
|
||||||
of nkSym:
|
of nkSym:
|
||||||
let field = n.sym
|
let field = n.sym
|
||||||
if field.typ.kind == tyVoid: return
|
if field.typ.kind == tyVoid: return
|
||||||
if field.loc.r == nil: fillObjectFields(c.p.module, typ)
|
if field.loc.r == "": fillObjectFields(c.p.module, typ)
|
||||||
if field.loc.t == nil:
|
if field.loc.t == nil:
|
||||||
internalError(c.p.config, n.info, "genTraverseProc()")
|
internalError(c.p.config, n.info, "genTraverseProc()")
|
||||||
genTraverseProc(c, "$1.$2" % [accessor, field.loc.r], field.loc.t)
|
genTraverseProc(c, "$1.$2" % [accessor, field.loc.r], field.loc.t)
|
||||||
|
|
@ -76,7 +76,8 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) =
|
||||||
let arraySize = lengthOrd(c.p.config, typ[0])
|
let arraySize = lengthOrd(c.p.config, typ[0])
|
||||||
var i: TLoc
|
var i: TLoc
|
||||||
getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo, tyInt), i)
|
getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo, tyInt), i)
|
||||||
let oldCode = p.s(cpsStmts)
|
var oldCode = p.s(cpsStmts)
|
||||||
|
freeze oldCode
|
||||||
linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
|
linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
|
||||||
[i.r, arraySize])
|
[i.r, arraySize])
|
||||||
let oldLen = p.s(cpsStmts).len
|
let oldLen = p.s(cpsStmts).len
|
||||||
|
|
@ -120,7 +121,8 @@ proc genTraverseProcSeq(c: TTraversalClosure, accessor: Rope, typ: PType) =
|
||||||
assert typ.kind == tySequence
|
assert typ.kind == tySequence
|
||||||
var i: TLoc
|
var i: TLoc
|
||||||
getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo, tyInt), i)
|
getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo, tyInt), i)
|
||||||
let oldCode = p.s(cpsStmts)
|
var oldCode = p.s(cpsStmts)
|
||||||
|
freeze oldCode
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
a.r = accessor
|
a.r = accessor
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,6 @@
|
||||||
|
|
||||||
import sighashes, modulegraphs
|
import sighashes, modulegraphs
|
||||||
|
|
||||||
proc genProcHeader(m: BModule, prc: PSym, asPtr: bool = false): Rope
|
|
||||||
|
|
||||||
proc isKeyword(w: PIdent): bool =
|
proc isKeyword(w: PIdent): bool =
|
||||||
# Nim and C++ share some keywords
|
# Nim and C++ share some keywords
|
||||||
# it's more efficient to test the whole Nim keywords range
|
# it's more efficient to test the whole Nim keywords range
|
||||||
|
|
@ -35,10 +33,9 @@ proc mangleField(m: BModule; name: PIdent): string =
|
||||||
if isKeyword(name):
|
if isKeyword(name):
|
||||||
result.add "_0"
|
result.add "_0"
|
||||||
|
|
||||||
proc mangleName(m: BModule; s: PSym): Rope =
|
proc fillBackendName(m: BModule; s: PSym) =
|
||||||
result = s.loc.r
|
if s.loc.r == "":
|
||||||
if result == nil:
|
var result = s.name.s.mangle.rope
|
||||||
result = s.name.s.mangle.rope
|
|
||||||
result.add "__"
|
result.add "__"
|
||||||
result.add m.g.graph.ifaces[s.itemId.module].uniqueName
|
result.add m.g.graph.ifaces[s.itemId.module].uniqueName
|
||||||
result.add "_"
|
result.add "_"
|
||||||
|
|
@ -49,12 +46,11 @@ proc mangleName(m: BModule; s: PSym): Rope =
|
||||||
s.loc.r = result
|
s.loc.r = result
|
||||||
writeMangledName(m.ndi, s, m.config)
|
writeMangledName(m.ndi, s, m.config)
|
||||||
|
|
||||||
proc mangleParamName(m: BModule; s: PSym): Rope =
|
proc fillParamName(m: BModule; s: PSym) =
|
||||||
## we cannot use 'sigConflicts' here since we have a BModule, not a BProc.
|
## we cannot use 'sigConflicts' here since we have a BModule, not a BProc.
|
||||||
## Fortunately C's scoping rules are sane enough so that that doesn't
|
## Fortunately C's scoping rules are sane enough so that that doesn't
|
||||||
## cause any trouble.
|
## cause any trouble.
|
||||||
result = s.loc.r
|
if s.loc.r == "":
|
||||||
if result == nil:
|
|
||||||
var res = s.name.s.mangle
|
var res = s.name.s.mangle
|
||||||
# Take into account if HCR is on because of the following scenario:
|
# Take into account if HCR is on because of the following scenario:
|
||||||
# if a module gets imported and it has some more importc symbols in it,
|
# if a module gets imported and it has some more importc symbols in it,
|
||||||
|
|
@ -74,20 +70,16 @@ proc mangleParamName(m: BModule; s: PSym): Rope =
|
||||||
# executable file for the main module, which is running (or both!) -> error.
|
# executable file for the main module, which is running (or both!) -> error.
|
||||||
if m.hcrOn or isKeyword(s.name) or m.g.config.cppDefines.contains(res):
|
if m.hcrOn or isKeyword(s.name) or m.g.config.cppDefines.contains(res):
|
||||||
res.add "_0"
|
res.add "_0"
|
||||||
result = res.rope
|
s.loc.r = res.rope
|
||||||
s.loc.r = result
|
|
||||||
writeMangledName(m.ndi, s, m.config)
|
writeMangledName(m.ndi, s, m.config)
|
||||||
|
|
||||||
proc mangleLocalName(p: BProc; s: PSym): Rope =
|
proc fillLocalName(p: BProc; s: PSym) =
|
||||||
assert s.kind in skLocalVars+{skTemp}
|
assert s.kind in skLocalVars+{skTemp}
|
||||||
#assert sfGlobal notin s.flags
|
#assert sfGlobal notin s.flags
|
||||||
result = s.loc.r
|
if s.loc.r == "":
|
||||||
if result == nil:
|
|
||||||
var key = s.name.s.mangle
|
var key = s.name.s.mangle
|
||||||
when not defined(nimSeqsV2):
|
|
||||||
shallow(key)
|
|
||||||
let counter = p.sigConflicts.getOrDefault(key)
|
let counter = p.sigConflicts.getOrDefault(key)
|
||||||
result = key.rope
|
var result = key.rope
|
||||||
if s.kind == skTemp:
|
if s.kind == skTemp:
|
||||||
# speed up conflict search for temps (these are quite common):
|
# speed up conflict search for temps (these are quite common):
|
||||||
if counter != 0: result.add "_" & rope(counter+1)
|
if counter != 0: result.add "_" & rope(counter+1)
|
||||||
|
|
@ -103,8 +95,6 @@ proc scopeMangledParam(p: BProc; param: PSym) =
|
||||||
## generate unique identifiers reliably (consider that ``var a = a`` is
|
## generate unique identifiers reliably (consider that ``var a = a`` is
|
||||||
## even an idiom in Nim).
|
## even an idiom in Nim).
|
||||||
var key = param.name.s.mangle
|
var key = param.name.s.mangle
|
||||||
when not defined(nimSeqsV2):
|
|
||||||
shallow(key)
|
|
||||||
p.sigConflicts.inc(key)
|
p.sigConflicts.inc(key)
|
||||||
|
|
||||||
const
|
const
|
||||||
|
|
@ -112,13 +102,12 @@ const
|
||||||
tyDistinct, tyRange, tyStatic, tyAlias, tySink,
|
tyDistinct, tyRange, tyStatic, tyAlias, tySink,
|
||||||
tyInferred, tyOwned}
|
tyInferred, tyOwned}
|
||||||
|
|
||||||
proc typeName(typ: PType): Rope =
|
proc typeName(typ: PType; result: var Rope) =
|
||||||
let typ = typ.skipTypes(irrelevantForBackend)
|
let typ = typ.skipTypes(irrelevantForBackend)
|
||||||
result =
|
result.add $typ.kind
|
||||||
if typ.sym != nil and typ.kind in {tyObject, tyEnum}:
|
if typ.sym != nil and typ.kind in {tyObject, tyEnum}:
|
||||||
rope($typ.kind & '_' & typ.sym.name.s.mangle)
|
result.add "_"
|
||||||
else:
|
result.add typ.sym.name.s.mangle
|
||||||
rope($typ.kind)
|
|
||||||
|
|
||||||
proc getTypeName(m: BModule; typ: PType; sig: SigHash): Rope =
|
proc getTypeName(m: BModule; typ: PType; sig: SigHash): Rope =
|
||||||
var t = typ
|
var t = typ
|
||||||
|
|
@ -131,14 +120,17 @@ proc getTypeName(m: BModule; typ: PType; sig: SigHash): Rope =
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
let typ = if typ.kind in {tyAlias, tySink, tyOwned}: typ.lastSon else: typ
|
let typ = if typ.kind in {tyAlias, tySink, tyOwned}: typ.lastSon else: typ
|
||||||
if typ.loc.r == nil:
|
if typ.loc.r == "":
|
||||||
typ.loc.r = typ.typeName & $sig
|
typ.typeName(typ.loc.r)
|
||||||
|
typ.loc.r.add $sig
|
||||||
else:
|
else:
|
||||||
when defined(debugSigHashes):
|
when defined(debugSigHashes):
|
||||||
# check consistency:
|
# check consistency:
|
||||||
assert($typ.loc.r == $(typ.typeName & $sig))
|
var tn = newRopeAppender()
|
||||||
|
typ.typeName(tn)
|
||||||
|
assert($typ.loc.r == $(tn & $sig))
|
||||||
result = typ.loc.r
|
result = typ.loc.r
|
||||||
if result == nil: internalError(m.config, "getTypeName: " & $typ.kind)
|
if result == "": internalError(m.config, "getTypeName: " & $typ.kind)
|
||||||
|
|
||||||
proc mapSetType(conf: ConfigRef; typ: PType): TCTypeKind =
|
proc mapSetType(conf: ConfigRef; typ: PType): TCTypeKind =
|
||||||
case int(getSize(conf, typ))
|
case int(getSize(conf, typ))
|
||||||
|
|
@ -266,7 +258,7 @@ proc addAbiCheck(m: BModule, t: PType, name: Rope) =
|
||||||
|
|
||||||
|
|
||||||
proc fillResult(conf: ConfigRef; param: PNode, proctype: PType) =
|
proc fillResult(conf: ConfigRef; param: PNode, proctype: PType) =
|
||||||
fillLoc(param.sym.loc, locParam, param, ~"Result",
|
fillLoc(param.sym.loc, locParam, param, "Result",
|
||||||
OnStack)
|
OnStack)
|
||||||
let t = param.sym.typ
|
let t = param.sym.typ
|
||||||
if mapReturnType(conf, t) != ctArray and isInvalidReturnType(conf, proctype):
|
if mapReturnType(conf, t) != ctArray and isInvalidReturnType(conf, proctype):
|
||||||
|
|
@ -292,11 +284,11 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope =
|
||||||
of tyString:
|
of tyString:
|
||||||
case detectStrVersion(m)
|
case detectStrVersion(m)
|
||||||
of 2:
|
of 2:
|
||||||
discard cgsym(m, "NimStrPayload")
|
cgsym(m, "NimStrPayload")
|
||||||
discard cgsym(m, "NimStringV2")
|
cgsym(m, "NimStringV2")
|
||||||
result = typeNameOrLiteral(m, typ, "NimStringV2")
|
result = typeNameOrLiteral(m, typ, "NimStringV2")
|
||||||
else:
|
else:
|
||||||
discard cgsym(m, "NimStringDesc")
|
cgsym(m, "NimStringDesc")
|
||||||
result = typeNameOrLiteral(m, typ, "NimStringDesc*")
|
result = typeNameOrLiteral(m, typ, "NimStringDesc*")
|
||||||
of tyCstring: result = typeNameOrLiteral(m, typ, "NCSTRING")
|
of tyCstring: result = typeNameOrLiteral(m, typ, "NCSTRING")
|
||||||
of tyBool: result = typeNameOrLiteral(m, typ, "NIM_BOOL")
|
of tyBool: result = typeNameOrLiteral(m, typ, "NIM_BOOL")
|
||||||
|
|
@ -310,11 +302,11 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope =
|
||||||
else: internalError(m.config, "tyStatic for getSimpleTypeDesc")
|
else: internalError(m.config, "tyStatic for getSimpleTypeDesc")
|
||||||
of tyGenericInst, tyAlias, tySink, tyOwned:
|
of tyGenericInst, tyAlias, tySink, tyOwned:
|
||||||
result = getSimpleTypeDesc(m, lastSon typ)
|
result = getSimpleTypeDesc(m, lastSon typ)
|
||||||
else: result = nil
|
else: result = ""
|
||||||
|
|
||||||
if result != nil and typ.isImportedType():
|
if result != "" and typ.isImportedType():
|
||||||
let sig = hashType typ
|
let sig = hashType typ
|
||||||
if cacheGetType(m.typeCache, sig) == nil:
|
if cacheGetType(m.typeCache, sig) == "":
|
||||||
m.typeCache[sig] = result
|
m.typeCache[sig] = result
|
||||||
|
|
||||||
proc pushType(m: BModule, typ: PType) =
|
proc pushType(m: BModule, typ: PType) =
|
||||||
|
|
@ -327,7 +319,7 @@ proc getTypePre(m: BModule, typ: PType; sig: SigHash): Rope =
|
||||||
if typ == nil: result = rope("void")
|
if typ == nil: result = rope("void")
|
||||||
else:
|
else:
|
||||||
result = getSimpleTypeDesc(m, typ)
|
result = getSimpleTypeDesc(m, typ)
|
||||||
if result == nil: result = cacheGetType(m.typeCache, sig)
|
if result == "": result = cacheGetType(m.typeCache, sig)
|
||||||
|
|
||||||
proc structOrUnion(t: PType): Rope =
|
proc structOrUnion(t: PType): Rope =
|
||||||
let cachedUnion = rope("union")
|
let cachedUnion = rope("union")
|
||||||
|
|
@ -348,9 +340,9 @@ proc seqStar(m: BModule): string =
|
||||||
|
|
||||||
proc getTypeForward(m: BModule, typ: PType; sig: SigHash): Rope =
|
proc getTypeForward(m: BModule, typ: PType; sig: SigHash): Rope =
|
||||||
result = cacheGetType(m.forwTypeCache, sig)
|
result = cacheGetType(m.forwTypeCache, sig)
|
||||||
if result != nil: return
|
if result != "": return
|
||||||
result = getTypePre(m, typ, sig)
|
result = getTypePre(m, typ, sig)
|
||||||
if result != nil: return
|
if result != "": return
|
||||||
let concrete = typ.skipTypes(abstractInst)
|
let concrete = typ.skipTypes(abstractInst)
|
||||||
case concrete.kind
|
case concrete.kind
|
||||||
of tySequence, tyTuple, tyObject:
|
of tySequence, tyTuple, tyObject:
|
||||||
|
|
@ -382,7 +374,7 @@ proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet; kind: TSymKind): R
|
||||||
internalError(m.config, "cannot map the empty seq type to a C type")
|
internalError(m.config, "cannot map the empty seq type to a C type")
|
||||||
|
|
||||||
result = cacheGetType(m.forwTypeCache, sig)
|
result = cacheGetType(m.forwTypeCache, sig)
|
||||||
if result == nil:
|
if result == "":
|
||||||
result = getTypeName(m, t, sig)
|
result = getTypeName(m, t, sig)
|
||||||
if not isImportedType(t):
|
if not isImportedType(t):
|
||||||
m.forwTypeCache[sig] = result
|
m.forwTypeCache[sig] = result
|
||||||
|
|
@ -390,7 +382,7 @@ proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet; kind: TSymKind): R
|
||||||
let payload = result & "_Content"
|
let payload = result & "_Content"
|
||||||
addForwardStructFormat(m, rope"struct", payload)
|
addForwardStructFormat(m, rope"struct", payload)
|
||||||
|
|
||||||
if cacheGetType(m.typeCache, sig) == nil:
|
if cacheGetType(m.typeCache, sig) == "":
|
||||||
m.typeCache[sig] = result
|
m.typeCache[sig] = result
|
||||||
#echo "adding ", sig, " ", typeToString(t), " ", m.module.name.s
|
#echo "adding ", sig, " ", typeToString(t), " ", m.module.name.s
|
||||||
appcg(m, m.s[cfsTypes],
|
appcg(m, m.s[cfsTypes],
|
||||||
|
|
@ -411,7 +403,7 @@ proc getSeqPayloadType(m: BModule; t: PType): Rope =
|
||||||
proc seqV2ContentType(m: BModule; t: PType; check: var IntSet) =
|
proc seqV2ContentType(m: BModule; t: PType; check: var IntSet) =
|
||||||
let sig = hashType(t)
|
let sig = hashType(t)
|
||||||
let result = cacheGetType(m.typeCache, sig)
|
let result = cacheGetType(m.typeCache, sig)
|
||||||
if result == nil:
|
if result == "":
|
||||||
discard getTypeDescAux(m, t, check, skVar)
|
discard getTypeDescAux(m, t, check, skVar)
|
||||||
else:
|
else:
|
||||||
# little hack for now to prevent multiple definitions of the same
|
# little hack for now to prevent multiple definitions of the same
|
||||||
|
|
@ -433,30 +425,31 @@ proc paramStorageLoc(param: PSym): TStorageLoc =
|
||||||
proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
|
proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
|
||||||
check: var IntSet, declareEnvironment=true;
|
check: var IntSet, declareEnvironment=true;
|
||||||
weakDep=false) =
|
weakDep=false) =
|
||||||
params = nil
|
params = ""
|
||||||
if t[0] == nil or isInvalidReturnType(m.config, t):
|
if t[0] == nil or isInvalidReturnType(m.config, t):
|
||||||
rettype = ~"void"
|
rettype = "void"
|
||||||
else:
|
else:
|
||||||
rettype = getTypeDescAux(m, t[0], check, skResult)
|
rettype = getTypeDescAux(m, t[0], check, skResult)
|
||||||
for i in 1..<t.n.len:
|
for i in 1..<t.n.len:
|
||||||
if t.n[i].kind != nkSym: internalError(m.config, t.n.info, "genProcParams")
|
if t.n[i].kind != nkSym: internalError(m.config, t.n.info, "genProcParams")
|
||||||
var param = t.n[i].sym
|
var param = t.n[i].sym
|
||||||
if isCompileTimeOnly(param.typ): continue
|
if isCompileTimeOnly(param.typ): continue
|
||||||
if params != nil: params.add(~", ")
|
if params != "": params.add(", ")
|
||||||
fillLoc(param.loc, locParam, t.n[i], mangleParamName(m, param),
|
fillParamName(m, param)
|
||||||
|
fillLoc(param.loc, locParam, t.n[i],
|
||||||
param.paramStorageLoc)
|
param.paramStorageLoc)
|
||||||
if ccgIntroducedPtr(m.config, param, t[0]):
|
if ccgIntroducedPtr(m.config, param, t[0]):
|
||||||
params.add(getTypeDescWeak(m, param.typ, check, skParam))
|
params.add(getTypeDescWeak(m, param.typ, check, skParam))
|
||||||
params.add(~"*")
|
params.add("*")
|
||||||
incl(param.loc.flags, lfIndirect)
|
incl(param.loc.flags, lfIndirect)
|
||||||
param.loc.storage = OnUnknown
|
param.loc.storage = OnUnknown
|
||||||
elif weakDep:
|
elif weakDep:
|
||||||
params.add(getTypeDescWeak(m, param.typ, check, skParam))
|
params.add(getTypeDescWeak(m, param.typ, check, skParam))
|
||||||
else:
|
else:
|
||||||
params.add(getTypeDescAux(m, param.typ, check, skParam))
|
params.add(getTypeDescAux(m, param.typ, check, skParam))
|
||||||
params.add(~" ")
|
params.add(" ")
|
||||||
if sfNoalias in param.flags:
|
if sfNoalias in param.flags:
|
||||||
params.add(~"NIM_NOALIAS ")
|
params.add("NIM_NOALIAS ")
|
||||||
params.add(param.loc.r)
|
params.add(param.loc.r)
|
||||||
# declare the len field for open arrays:
|
# declare the len field for open arrays:
|
||||||
var arr = param.typ.skipTypes({tyGenericInst})
|
var arr = param.typ.skipTypes({tyGenericInst})
|
||||||
|
|
@ -471,7 +464,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
|
||||||
arr = arr[0].skipTypes({tySink})
|
arr = arr[0].skipTypes({tySink})
|
||||||
if t[0] != nil and isInvalidReturnType(m.config, t):
|
if t[0] != nil and isInvalidReturnType(m.config, t):
|
||||||
var arr = t[0]
|
var arr = t[0]
|
||||||
if params != nil: params.add(", ")
|
if params != "": params.add(", ")
|
||||||
if mapReturnType(m.config, t[0]) != ctArray:
|
if mapReturnType(m.config, t[0]) != ctArray:
|
||||||
if isHeaderFile in m.flags:
|
if isHeaderFile in m.flags:
|
||||||
# still generates types for `--header`
|
# still generates types for `--header`
|
||||||
|
|
@ -484,12 +477,12 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
|
||||||
params.add(getTypeDescAux(m, arr, check, skResult))
|
params.add(getTypeDescAux(m, arr, check, skResult))
|
||||||
params.addf(" Result", [])
|
params.addf(" Result", [])
|
||||||
if t.callConv == ccClosure and declareEnvironment:
|
if t.callConv == ccClosure and declareEnvironment:
|
||||||
if params != nil: params.add(", ")
|
if params != "": params.add(", ")
|
||||||
params.add("void* ClE_0")
|
params.add("void* ClE_0")
|
||||||
if tfVarargs in t.flags:
|
if tfVarargs in t.flags:
|
||||||
if params != nil: params.add(", ")
|
if params != "": params.add(", ")
|
||||||
params.add("...")
|
params.add("...")
|
||||||
if params == nil: params.add("void)")
|
if params == "": params.add("void)")
|
||||||
else: params.add(")")
|
else: params.add(")")
|
||||||
params = "(" & params
|
params = "(" & params
|
||||||
|
|
||||||
|
|
@ -498,30 +491,30 @@ proc mangleRecFieldName(m: BModule; field: PSym): Rope =
|
||||||
result = field.loc.r
|
result = field.loc.r
|
||||||
else:
|
else:
|
||||||
result = rope(mangleField(m, field.name))
|
result = rope(mangleField(m, field.name))
|
||||||
if result == nil: internalError(m.config, field.info, "mangleRecFieldName")
|
if result == "": internalError(m.config, field.info, "mangleRecFieldName")
|
||||||
|
|
||||||
proc genRecordFieldsAux(m: BModule, n: PNode,
|
proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||||
rectype: PType,
|
rectype: PType,
|
||||||
check: var IntSet, unionPrefix = ""): Rope =
|
check: var IntSet; result: var Rope; unionPrefix = "") =
|
||||||
result = nil
|
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
for i in 0..<n.len:
|
for i in 0..<n.len:
|
||||||
result.add(genRecordFieldsAux(m, n[i], rectype, check, unionPrefix))
|
genRecordFieldsAux(m, n[i], rectype, check, result, unionPrefix)
|
||||||
of nkRecCase:
|
of nkRecCase:
|
||||||
if n[0].kind != nkSym: internalError(m.config, n.info, "genRecordFieldsAux")
|
if n[0].kind != nkSym: internalError(m.config, n.info, "genRecordFieldsAux")
|
||||||
result.add(genRecordFieldsAux(m, n[0], rectype, check, unionPrefix))
|
genRecordFieldsAux(m, n[0], rectype, check, result, unionPrefix)
|
||||||
# prefix mangled name with "_U" to avoid clashes with other field names,
|
# prefix mangled name with "_U" to avoid clashes with other field names,
|
||||||
# since identifiers are not allowed to start with '_'
|
# since identifiers are not allowed to start with '_'
|
||||||
var unionBody: Rope = nil
|
var unionBody: Rope = ""
|
||||||
for i in 1..<n.len:
|
for i in 1..<n.len:
|
||||||
case n[i].kind
|
case n[i].kind
|
||||||
of nkOfBranch, nkElse:
|
of nkOfBranch, nkElse:
|
||||||
let k = lastSon(n[i])
|
let k = lastSon(n[i])
|
||||||
if k.kind != nkSym:
|
if k.kind != nkSym:
|
||||||
let structName = "_" & mangleRecFieldName(m, n[0].sym) & "_" & $i
|
let structName = "_" & mangleRecFieldName(m, n[0].sym) & "_" & $i
|
||||||
let a = genRecordFieldsAux(m, k, rectype, check, unionPrefix & $structName & ".")
|
var a = newRopeAppender()
|
||||||
if a != nil:
|
genRecordFieldsAux(m, k, rectype, check, a, unionPrefix & $structName & ".")
|
||||||
|
if a != "":
|
||||||
if tfPacked notin rectype.flags:
|
if tfPacked notin rectype.flags:
|
||||||
unionBody.add("struct {")
|
unionBody.add("struct {")
|
||||||
else:
|
else:
|
||||||
|
|
@ -534,9 +527,9 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||||
if tfPacked in rectype.flags and hasAttribute notin CC[m.config.cCompiler].props:
|
if tfPacked in rectype.flags and hasAttribute notin CC[m.config.cCompiler].props:
|
||||||
unionBody.addf("#pragma pack(pop)$n", [])
|
unionBody.addf("#pragma pack(pop)$n", [])
|
||||||
else:
|
else:
|
||||||
unionBody.add(genRecordFieldsAux(m, k, rectype, check, unionPrefix))
|
genRecordFieldsAux(m, k, rectype, check, unionBody, unionPrefix)
|
||||||
else: internalError(m.config, "genRecordFieldsAux(record case branch)")
|
else: internalError(m.config, "genRecordFieldsAux(record case branch)")
|
||||||
if unionBody != nil:
|
if unionBody != "":
|
||||||
result.addf("union{$n$1};$n", [unionBody])
|
result.addf("union{$n$1};$n", [unionBody])
|
||||||
of nkSym:
|
of nkSym:
|
||||||
let field = n.sym
|
let field = n.sym
|
||||||
|
|
@ -550,7 +543,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||||
# have to recurse via 'getTypeDescAux'. And not doing so prevents problems
|
# have to recurse via 'getTypeDescAux'. And not doing so prevents problems
|
||||||
# with heavily templatized C++ code:
|
# with heavily templatized C++ code:
|
||||||
if not isImportedCppType(rectype):
|
if not isImportedCppType(rectype):
|
||||||
let noAlias = if sfNoalias in field.flags: ~" NIM_NOALIAS" else: nil
|
let noAlias = if sfNoalias in field.flags: " NIM_NOALIAS" else: ""
|
||||||
|
|
||||||
let fieldType = field.loc.lode.typ.skipTypes(abstractInst)
|
let fieldType = field.loc.lode.typ.skipTypes(abstractInst)
|
||||||
if fieldType.kind == tyUncheckedArray:
|
if fieldType.kind == tyUncheckedArray:
|
||||||
|
|
@ -568,7 +561,8 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||||
else: internalError(m.config, n.info, "genRecordFieldsAux()")
|
else: internalError(m.config, n.info, "genRecordFieldsAux()")
|
||||||
|
|
||||||
proc getRecordFields(m: BModule, typ: PType, check: var IntSet): Rope =
|
proc getRecordFields(m: BModule, typ: PType, check: var IntSet): Rope =
|
||||||
result = genRecordFieldsAux(m, typ.n, typ, check)
|
result = newRopeAppender()
|
||||||
|
genRecordFieldsAux(m, typ.n, typ, check, result)
|
||||||
|
|
||||||
proc fillObjectFields*(m: BModule; typ: PType) =
|
proc fillObjectFields*(m: BModule; typ: PType) =
|
||||||
# sometimes generic objects are not consistently merged. We patch over
|
# sometimes generic objects are not consistently merged. We patch over
|
||||||
|
|
@ -625,7 +619,7 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,
|
||||||
result.addf(" {$n", [name])
|
result.addf(" {$n", [name])
|
||||||
|
|
||||||
let desc = getRecordFields(m, typ, check)
|
let desc = getRecordFields(m, typ, check)
|
||||||
if desc == nil and not hasField:
|
if desc == "" and not hasField:
|
||||||
result.addf("char dummy;$n", [])
|
result.addf("char dummy;$n", [])
|
||||||
else:
|
else:
|
||||||
result.add(desc)
|
result.add(desc)
|
||||||
|
|
@ -636,11 +630,11 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,
|
||||||
proc getTupleDesc(m: BModule, typ: PType, name: Rope,
|
proc getTupleDesc(m: BModule, typ: PType, name: Rope,
|
||||||
check: var IntSet): Rope =
|
check: var IntSet): Rope =
|
||||||
result = "$1 $2 {$n" % [structOrUnion(typ), name]
|
result = "$1 $2 {$n" % [structOrUnion(typ), name]
|
||||||
var desc: Rope = nil
|
var desc: Rope = ""
|
||||||
for i in 0..<typ.len:
|
for i in 0..<typ.len:
|
||||||
desc.addf("$1 Field$2;$n",
|
desc.addf("$1 Field$2;$n",
|
||||||
[getTypeDescAux(m, typ[i], check, skField), rope(i)])
|
[getTypeDescAux(m, typ[i], check, skField), rope(i)])
|
||||||
if desc == nil: result.add("char dummy;\L")
|
if desc == "": result.add("char dummy;\L")
|
||||||
else: result.add(desc)
|
else: result.add(desc)
|
||||||
result.add("};\L")
|
result.add("};\L")
|
||||||
|
|
||||||
|
|
@ -679,7 +673,7 @@ proc getOpenArrayDesc(m: BModule, t: PType, check: var IntSet; kind: TSymKind):
|
||||||
result = getTypeDescWeak(m, t[0], check, kind) & "*"
|
result = getTypeDescWeak(m, t[0], check, kind) & "*"
|
||||||
else:
|
else:
|
||||||
result = cacheGetType(m.typeCache, sig)
|
result = cacheGetType(m.typeCache, sig)
|
||||||
if result == nil:
|
if result == "":
|
||||||
result = getTypeName(m, t, sig)
|
result = getTypeName(m, t, sig)
|
||||||
m.typeCache[sig] = result
|
m.typeCache[sig] = result
|
||||||
let elemType = getTypeDescWeak(m, t[0], check, kind)
|
let elemType = getTypeDescWeak(m, t[0], check, kind)
|
||||||
|
|
@ -705,7 +699,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKin
|
||||||
addAbiCheck(m, t, result)
|
addAbiCheck(m, t, result)
|
||||||
|
|
||||||
result = getTypePre(m, t, sig)
|
result = getTypePre(m, t, sig)
|
||||||
if result != nil and t.kind != tyOpenArray:
|
if result != "" and t.kind != tyOpenArray:
|
||||||
excl(check, t.id)
|
excl(check, t.id)
|
||||||
return
|
return
|
||||||
case t.kind
|
case t.kind
|
||||||
|
|
@ -748,7 +742,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKin
|
||||||
result = getOpenArrayDesc(m, t, check, kind)
|
result = getOpenArrayDesc(m, t, check, kind)
|
||||||
of tyEnum:
|
of tyEnum:
|
||||||
result = cacheGetType(m.typeCache, sig)
|
result = cacheGetType(m.typeCache, sig)
|
||||||
if result == nil:
|
if result == "":
|
||||||
result = getTypeName(m, origTyp, sig)
|
result = getTypeName(m, origTyp, sig)
|
||||||
if not (isImportedCppType(t) or
|
if not (isImportedCppType(t) or
|
||||||
(sfImportc in t.sym.flags and t.sym.magic == mNone)):
|
(sfImportc in t.sym.flags and t.sym.magic == mNone)):
|
||||||
|
|
@ -796,12 +790,12 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKin
|
||||||
# we cannot use getTypeForward here because then t would be associated
|
# we cannot use getTypeForward here because then t would be associated
|
||||||
# with the name of the struct, not with the pointer to the struct:
|
# with the name of the struct, not with the pointer to the struct:
|
||||||
result = cacheGetType(m.forwTypeCache, sig)
|
result = cacheGetType(m.forwTypeCache, sig)
|
||||||
if result == nil:
|
if result == "":
|
||||||
result = getTypeName(m, origTyp, sig)
|
result = getTypeName(m, origTyp, sig)
|
||||||
if not isImportedType(t):
|
if not isImportedType(t):
|
||||||
addForwardStructFormat(m, structOrUnion(t), result)
|
addForwardStructFormat(m, structOrUnion(t), result)
|
||||||
m.forwTypeCache[sig] = result
|
m.forwTypeCache[sig] = result
|
||||||
assert(cacheGetType(m.typeCache, sig) == nil)
|
assert(cacheGetType(m.typeCache, sig) == "")
|
||||||
m.typeCache[sig] = result & seqStar(m)
|
m.typeCache[sig] = result & seqStar(m)
|
||||||
if not isImportedType(t):
|
if not isImportedType(t):
|
||||||
if skipTypes(t[0], typedescInst).kind != tyEmpty:
|
if skipTypes(t[0], typedescInst).kind != tyEmpty:
|
||||||
|
|
@ -837,25 +831,26 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKin
|
||||||
[foo, result, rope(n)])
|
[foo, result, rope(n)])
|
||||||
of tyObject, tyTuple:
|
of tyObject, tyTuple:
|
||||||
if isImportedCppType(t) and origTyp.kind == tyGenericInst:
|
if isImportedCppType(t) and origTyp.kind == tyGenericInst:
|
||||||
let cppName = getTypeName(m, t, sig)
|
let cppNameAsRope = getTypeName(m, t, sig)
|
||||||
|
let cppName = $cppNameAsRope
|
||||||
var i = 0
|
var i = 0
|
||||||
var chunkStart = 0
|
var chunkStart = 0
|
||||||
|
|
||||||
template addResultType(ty: untyped) =
|
template addResultType(ty: untyped) =
|
||||||
if ty == nil or ty.kind == tyVoid:
|
if ty == nil or ty.kind == tyVoid:
|
||||||
result.add(~"void")
|
result.add("void")
|
||||||
elif ty.kind == tyStatic:
|
elif ty.kind == tyStatic:
|
||||||
internalAssert m.config, ty.n != nil
|
internalAssert m.config, ty.n != nil
|
||||||
result.add ty.n.renderTree
|
result.add ty.n.renderTree
|
||||||
else:
|
else:
|
||||||
result.add getTypeDescAux(m, ty, check, kind)
|
result.add getTypeDescAux(m, ty, check, kind)
|
||||||
|
|
||||||
while i < cppName.data.len:
|
while i < cppName.len:
|
||||||
if cppName.data[i] == '\'':
|
if cppName[i] == '\'':
|
||||||
var chunkEnd = i-1
|
var chunkEnd = i-1
|
||||||
var idx, stars: int
|
var idx, stars: int
|
||||||
if scanCppGenericSlot(cppName.data, i, idx, stars):
|
if scanCppGenericSlot(cppName, i, idx, stars):
|
||||||
result.add cppName.data.substr(chunkStart, chunkEnd)
|
result.add cppName.substr(chunkStart, chunkEnd)
|
||||||
chunkStart = i
|
chunkStart = i
|
||||||
|
|
||||||
let typeInSlot = resolveStarsInCppType(origTyp, idx + 1, stars)
|
let typeInSlot = resolveStarsInCppType(origTyp, idx + 1, stars)
|
||||||
|
|
@ -864,9 +859,9 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKin
|
||||||
inc i
|
inc i
|
||||||
|
|
||||||
if chunkStart != 0:
|
if chunkStart != 0:
|
||||||
result.add cppName.data.substr(chunkStart)
|
result.add cppName.substr(chunkStart)
|
||||||
else:
|
else:
|
||||||
result = cppName & "<"
|
result = cppNameAsRope & "<"
|
||||||
for i in 1..<origTyp.len-1:
|
for i in 1..<origTyp.len-1:
|
||||||
if i > 1: result.add(" COMMA ")
|
if i > 1: result.add(" COMMA ")
|
||||||
addResultType(origTyp[i])
|
addResultType(origTyp[i])
|
||||||
|
|
@ -877,13 +872,13 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKin
|
||||||
# The resulting type will include commas and these won't play well
|
# The resulting type will include commas and these won't play well
|
||||||
# with the C macros for defining procs such as N_NIMCALL. We must
|
# with the C macros for defining procs such as N_NIMCALL. We must
|
||||||
# create a typedef for the type and use it in the proc signature:
|
# create a typedef for the type and use it in the proc signature:
|
||||||
let typedefName = ~"TY" & $sig
|
let typedefName = "TY" & $sig
|
||||||
m.s[cfsTypes].addf("typedef $1 $2;$n", [result, typedefName])
|
m.s[cfsTypes].addf("typedef $1 $2;$n", [result, typedefName])
|
||||||
m.typeCache[sig] = typedefName
|
m.typeCache[sig] = typedefName
|
||||||
result = typedefName
|
result = typedefName
|
||||||
else:
|
else:
|
||||||
result = cacheGetType(m.forwTypeCache, sig)
|
result = cacheGetType(m.forwTypeCache, sig)
|
||||||
if result == nil:
|
if result == "":
|
||||||
result = getTypeName(m, origTyp, sig)
|
result = getTypeName(m, origTyp, sig)
|
||||||
m.forwTypeCache[sig] = result
|
m.forwTypeCache[sig] = result
|
||||||
if not isImportedType(t):
|
if not isImportedType(t):
|
||||||
|
|
@ -899,7 +894,9 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKin
|
||||||
discard # addAbiCheck(m, t, result) # already handled elsewhere
|
discard # addAbiCheck(m, t, result) # already handled elsewhere
|
||||||
of tySet:
|
of tySet:
|
||||||
# Don't use the imported name as it may be scoped: 'Foo::SomeKind'
|
# Don't use the imported name as it may be scoped: 'Foo::SomeKind'
|
||||||
result = $t.kind & '_' & t.lastSon.typeName & $t.lastSon.hashType
|
result = rope("tySet_")
|
||||||
|
t.lastSon.typeName(result)
|
||||||
|
result.add $t.lastSon.hashType
|
||||||
m.typeCache[sig] = result
|
m.typeCache[sig] = result
|
||||||
if not isImportedType(t):
|
if not isImportedType(t):
|
||||||
let s = int(getSize(m.config, t))
|
let s = int(getSize(m.config, t))
|
||||||
|
|
@ -912,7 +909,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKin
|
||||||
result = getTypeDescAux(m, lastSon(t), check, kind)
|
result = getTypeDescAux(m, lastSon(t), check, kind)
|
||||||
else:
|
else:
|
||||||
internalError(m.config, "getTypeDescAux(" & $t.kind & ')')
|
internalError(m.config, "getTypeDescAux(" & $t.kind & ')')
|
||||||
result = nil
|
result = ""
|
||||||
# fixes bug #145:
|
# fixes bug #145:
|
||||||
excl(check, t.id)
|
excl(check, t.id)
|
||||||
|
|
||||||
|
|
@ -963,21 +960,12 @@ proc isReloadable(m: BModule, prc: PSym): bool =
|
||||||
proc isNonReloadable(m: BModule, prc: PSym): bool =
|
proc isNonReloadable(m: BModule, prc: PSym): bool =
|
||||||
return m.hcrOn and sfNonReloadable in prc.flags
|
return m.hcrOn and sfNonReloadable in prc.flags
|
||||||
|
|
||||||
proc genProcHeader(m: BModule, prc: PSym, asPtr: bool = false): Rope =
|
proc genProcHeader(m: BModule, prc: PSym; result: var Rope; asPtr: bool = false) =
|
||||||
var
|
|
||||||
rettype, params: Rope
|
|
||||||
# using static is needed for inline procs
|
# using static is needed for inline procs
|
||||||
if lfExportLib in prc.loc.flags:
|
|
||||||
if isHeaderFile in m.flags:
|
|
||||||
result.add "N_LIB_IMPORT "
|
|
||||||
else:
|
|
||||||
result.add "N_LIB_EXPORT "
|
|
||||||
elif prc.typ.callConv == ccInline or asPtr or isNonReloadable(m, prc):
|
|
||||||
result.add "static "
|
|
||||||
elif sfImportc notin prc.flags:
|
|
||||||
result.add "N_LIB_PRIVATE "
|
|
||||||
var check = initIntSet()
|
var check = initIntSet()
|
||||||
fillLoc(prc.loc, locProc, prc.ast[namePos], mangleName(m, prc), OnUnknown)
|
fillBackendName(m, prc)
|
||||||
|
fillLoc(prc.loc, locProc, prc.ast[namePos], OnUnknown)
|
||||||
|
var rettype, params: Rope
|
||||||
genProcParams(m, prc.typ, rettype, params, check)
|
genProcParams(m, prc.typ, rettype, params, check)
|
||||||
# handle the 2 options for hotcodereloading codegen - function pointer
|
# handle the 2 options for hotcodereloading codegen - function pointer
|
||||||
# (instead of forward declaration) or header for function body with "_actual" postfix
|
# (instead of forward declaration) or header for function body with "_actual" postfix
|
||||||
|
|
@ -988,12 +976,21 @@ proc genProcHeader(m: BModule, prc: PSym, asPtr: bool = false): Rope =
|
||||||
# careful here! don't access ``prc.ast`` as that could reload large parts of
|
# careful here! don't access ``prc.ast`` as that could reload large parts of
|
||||||
# the object graph!
|
# the object graph!
|
||||||
if prc.constraint.isNil:
|
if prc.constraint.isNil:
|
||||||
|
if lfExportLib in prc.loc.flags:
|
||||||
|
if isHeaderFile in m.flags:
|
||||||
|
result.add "N_LIB_IMPORT "
|
||||||
|
else:
|
||||||
|
result.add "N_LIB_EXPORT "
|
||||||
|
elif prc.typ.callConv == ccInline or asPtr or isNonReloadable(m, prc):
|
||||||
|
result.add "static "
|
||||||
|
elif sfImportc notin prc.flags:
|
||||||
|
result.add "N_LIB_PRIVATE "
|
||||||
result.addf("$1$2($3, $4)$5",
|
result.addf("$1$2($3, $4)$5",
|
||||||
[rope(CallingConvToStr[prc.typ.callConv]), asPtrStr, rettype, name,
|
[rope(CallingConvToStr[prc.typ.callConv]), asPtrStr, rettype, name,
|
||||||
params])
|
params])
|
||||||
else:
|
else:
|
||||||
let asPtrStr = if asPtr: (rope("(*") & name & ")") else: name
|
let asPtrStr = if asPtr: (rope("(*") & name & ")") else: name
|
||||||
result = runtimeFormat(prc.cgDeclFrmt, [rettype, asPtrStr, params])
|
result.add runtimeFormat(prc.cgDeclFrmt, [rettype, asPtrStr, params])
|
||||||
|
|
||||||
# ------------------ type info generation -------------------------------------
|
# ------------------ type info generation -------------------------------------
|
||||||
|
|
||||||
|
|
@ -1032,7 +1029,7 @@ proc genTypeInfoAuxBase(m: BModule; typ, origType: PType;
|
||||||
#else echo("can contain a cycle: " & typeToString(typ))
|
#else echo("can contain a cycle: " & typeToString(typ))
|
||||||
if flags != 0:
|
if flags != 0:
|
||||||
m.s[cfsTypeInit3].addf("$1.flags = $2;$n", [nameHcr, rope(flags)])
|
m.s[cfsTypeInit3].addf("$1.flags = $2;$n", [nameHcr, rope(flags)])
|
||||||
discard cgsym(m, "TNimType")
|
cgsym(m, "TNimType")
|
||||||
if isDefined(m.config, "nimTypeNames"):
|
if isDefined(m.config, "nimTypeNames"):
|
||||||
var typename = typeToString(if origType.typeInst != nil: origType.typeInst
|
var typename = typeToString(if origType.typeInst != nil: origType.typeInst
|
||||||
else: origType, preferName)
|
else: origType, preferName)
|
||||||
|
|
@ -1040,16 +1037,16 @@ proc genTypeInfoAuxBase(m: BModule; typ, origType: PType;
|
||||||
typename = "anon ref object from " & m.config$origType.skipTypes(skipPtrs).sym.info
|
typename = "anon ref object from " & m.config$origType.skipTypes(skipPtrs).sym.info
|
||||||
m.s[cfsTypeInit3].addf("$1.name = $2;$n",
|
m.s[cfsTypeInit3].addf("$1.name = $2;$n",
|
||||||
[nameHcr, makeCString typename])
|
[nameHcr, makeCString typename])
|
||||||
discard cgsym(m, "nimTypeRoot")
|
cgsym(m, "nimTypeRoot")
|
||||||
m.s[cfsTypeInit3].addf("$1.nextType = nimTypeRoot; nimTypeRoot=&$1;$n",
|
m.s[cfsTypeInit3].addf("$1.nextType = nimTypeRoot; nimTypeRoot=&$1;$n",
|
||||||
[nameHcr])
|
[nameHcr])
|
||||||
|
|
||||||
if m.hcrOn:
|
if m.hcrOn:
|
||||||
m.s[cfsData].addf("static TNimType* $1;$n", [name])
|
m.s[cfsStrData].addf("static TNimType* $1;$n", [name])
|
||||||
m.hcrCreateTypeInfosProc.addf("\thcrRegisterGlobal($2, \"$1\", sizeof(TNimType), NULL, (void**)&$1);$n",
|
m.hcrCreateTypeInfosProc.addf("\thcrRegisterGlobal($2, \"$1\", sizeof(TNimType), NULL, (void**)&$1);$n",
|
||||||
[name, getModuleDllPath(m, m.module)])
|
[name, getModuleDllPath(m, m.module)])
|
||||||
else:
|
else:
|
||||||
m.s[cfsData].addf("N_LIB_PRIVATE TNimType $1;$n", [name])
|
m.s[cfsStrData].addf("N_LIB_PRIVATE TNimType $1;$n", [name])
|
||||||
|
|
||||||
proc genTypeInfoAux(m: BModule, typ, origType: PType, name: Rope;
|
proc genTypeInfoAux(m: BModule, typ, origType: PType, name: Rope;
|
||||||
info: TLineInfo) =
|
info: TLineInfo) =
|
||||||
|
|
@ -1077,7 +1074,7 @@ proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): Rope =
|
||||||
proc rope(arg: Int128): Rope = rope($arg)
|
proc rope(arg: Int128): Rope = rope($arg)
|
||||||
|
|
||||||
proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): Rope =
|
proc discriminatorTableDecl(m: BModule, objtype: PType, d: PSym): Rope =
|
||||||
discard cgsym(m, "TNimNode")
|
cgsym(m, "TNimNode")
|
||||||
var tmp = discriminatorTableName(m, objtype, d)
|
var tmp = discriminatorTableName(m, objtype, d)
|
||||||
result = "TNimNode* $1[$2];$n" % [tmp, rope(lengthOrd(m.config, d.typ)+1)]
|
result = "TNimNode* $1[$2];$n" % [tmp, rope(lengthOrd(m.config, d.typ)+1)]
|
||||||
|
|
||||||
|
|
@ -1112,7 +1109,7 @@ proc genObjectFields(m: BModule, typ, origType: PType, n: PNode, expr: Rope;
|
||||||
var tmp = discriminatorTableName(m, typ, field)
|
var tmp = discriminatorTableName(m, typ, field)
|
||||||
var L = lengthOrd(m.config, field.typ)
|
var L = lengthOrd(m.config, field.typ)
|
||||||
assert L > 0
|
assert L > 0
|
||||||
if field.loc.r == nil: fillObjectFields(m, typ)
|
if field.loc.r == "": fillObjectFields(m, typ)
|
||||||
if field.loc.t == nil:
|
if field.loc.t == nil:
|
||||||
internalError(m.config, n.info, "genObjectFields")
|
internalError(m.config, n.info, "genObjectFields")
|
||||||
m.s[cfsTypeInit3].addf("$1.kind = 3;$n" &
|
m.s[cfsTypeInit3].addf("$1.kind = 3;$n" &
|
||||||
|
|
@ -1150,7 +1147,7 @@ proc genObjectFields(m: BModule, typ, origType: PType, n: PNode, expr: Rope;
|
||||||
# Do not produce code for void types
|
# Do not produce code for void types
|
||||||
if isEmptyType(field.typ): return
|
if isEmptyType(field.typ): return
|
||||||
if field.bitsize == 0:
|
if field.bitsize == 0:
|
||||||
if field.loc.r == nil: fillObjectFields(m, typ)
|
if field.loc.r == "": fillObjectFields(m, typ)
|
||||||
if field.loc.t == nil:
|
if field.loc.t == nil:
|
||||||
internalError(m.config, n.info, "genObjectFields")
|
internalError(m.config, n.info, "genObjectFields")
|
||||||
m.s[cfsTypeInit3].addf("$1.kind = 1;$n" &
|
m.s[cfsTypeInit3].addf("$1.kind = 1;$n" &
|
||||||
|
|
@ -1244,7 +1241,7 @@ proc genSetInfo(m: BModule, typ: PType, name: Rope; info: TLineInfo) =
|
||||||
assert(typ[0] != nil)
|
assert(typ[0] != nil)
|
||||||
genTypeInfoAux(m, typ, typ, name, info)
|
genTypeInfoAux(m, typ, typ, name, info)
|
||||||
var tmp = getNimNode(m)
|
var tmp = getNimNode(m)
|
||||||
m.s[cfsTypeInit3].addf("$1.len = $2; $1.kind = 0;$n" & "$3.node = &$1;$n",
|
m.s[cfsTypeInit3].addf("$1.len = $2; $1.kind = 0;$n$3.node = &$1;$n",
|
||||||
[tmp, rope(firstOrd(m.config, typ)), tiNameForHcr(m, name)])
|
[tmp, rope(firstOrd(m.config, typ)), tiNameForHcr(m, name)])
|
||||||
|
|
||||||
proc genArrayInfo(m: BModule, typ: PType, name: Rope; info: TLineInfo) =
|
proc genArrayInfo(m: BModule, typ: PType, name: Rope; info: TLineInfo) =
|
||||||
|
|
@ -1269,11 +1266,11 @@ proc genDeepCopyProc(m: BModule; s: PSym; result: Rope) =
|
||||||
proc declareNimType(m: BModule, name: string; str: Rope, module: int) =
|
proc declareNimType(m: BModule, name: string; str: Rope, module: int) =
|
||||||
let nr = rope(name)
|
let nr = rope(name)
|
||||||
if m.hcrOn:
|
if m.hcrOn:
|
||||||
m.s[cfsData].addf("static $2* $1;$n", [str, nr])
|
m.s[cfsStrData].addf("static $2* $1;$n", [str, nr])
|
||||||
m.s[cfsTypeInit1].addf("\t$1 = ($3*)hcrGetGlobal($2, \"$1\");$n",
|
m.s[cfsTypeInit1].addf("\t$1 = ($3*)hcrGetGlobal($2, \"$1\");$n",
|
||||||
[str, getModuleDllPath(m, module), nr])
|
[str, getModuleDllPath(m, module), nr])
|
||||||
else:
|
else:
|
||||||
m.s[cfsData].addf("extern $2 $1;$n", [str, nr])
|
m.s[cfsStrData].addf("extern $2 $1;$n", [str, nr])
|
||||||
|
|
||||||
proc genTypeInfo2Name(m: BModule; t: PType): Rope =
|
proc genTypeInfo2Name(m: BModule; t: PType): Rope =
|
||||||
var res = "|"
|
var res = "|"
|
||||||
|
|
@ -1300,7 +1297,7 @@ proc genTypeInfo2Name(m: BModule; t: PType): Rope =
|
||||||
|
|
||||||
proc isTrivialProc(g: ModuleGraph; s: PSym): bool {.inline.} = getBody(g, s).len == 0
|
proc isTrivialProc(g: ModuleGraph; s: PSym): bool {.inline.} = getBody(g, s).len == 0
|
||||||
|
|
||||||
proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp): Rope =
|
proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp; result: var Rope) =
|
||||||
let theProc = getAttachedOp(m.g.graph, t, op)
|
let theProc = getAttachedOp(m.g.graph, t, op)
|
||||||
if theProc != nil and not isTrivialProc(m.g.graph, theProc):
|
if theProc != nil and not isTrivialProc(m.g.graph, theProc):
|
||||||
# the prototype of a destructor is ``=destroy(x: var T)`` and that of a
|
# the prototype of a destructor is ``=destroy(x: var T)`` and that of a
|
||||||
|
|
@ -1311,7 +1308,7 @@ proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp): Rope =
|
||||||
theProc.name.s & " needs to have the 'nimcall' calling convention")
|
theProc.name.s & " needs to have the 'nimcall' calling convention")
|
||||||
|
|
||||||
genProc(m, theProc)
|
genProc(m, theProc)
|
||||||
result = theProc.loc.r
|
result.add theProc.loc.r
|
||||||
|
|
||||||
when false:
|
when false:
|
||||||
if not canFormAcycle(t) and op == attachedTrace:
|
if not canFormAcycle(t) and op == attachedTrace:
|
||||||
|
|
@ -1323,7 +1320,7 @@ proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp): Rope =
|
||||||
# unfortunately this check is wrong for an object type that only contains
|
# unfortunately this check is wrong for an object type that only contains
|
||||||
# .cursor fields like 'Node' inside 'cycleleak'.
|
# .cursor fields like 'Node' inside 'cycleleak'.
|
||||||
internalError(m.config, info, "no attached trace proc found")
|
internalError(m.config, info, "no attached trace proc found")
|
||||||
result = rope("NIM_NIL")
|
result.add rope("NIM_NIL")
|
||||||
|
|
||||||
proc genTypeInfoV2Impl(m: BModule, t, origType: PType, name: Rope; info: TLineInfo) =
|
proc genTypeInfoV2Impl(m: BModule, t, origType: PType, name: Rope; info: TLineInfo) =
|
||||||
var typeName: Rope
|
var typeName: Rope
|
||||||
|
|
@ -1335,17 +1332,23 @@ proc genTypeInfoV2Impl(m: BModule, t, origType: PType, name: Rope; info: TLineIn
|
||||||
else:
|
else:
|
||||||
typeName = rope("NIM_NIL")
|
typeName = rope("NIM_NIL")
|
||||||
|
|
||||||
discard cgsym(m, "TNimTypeV2")
|
cgsym(m, "TNimTypeV2")
|
||||||
m.s[cfsData].addf("N_LIB_PRIVATE TNimTypeV2 $1;$n", [name])
|
m.s[cfsStrData].addf("N_LIB_PRIVATE TNimTypeV2 $1;$n", [name])
|
||||||
let destroyImpl = genHook(m, t, info, attachedDestructor)
|
|
||||||
let traceImpl = genHook(m, t, info, attachedTrace)
|
|
||||||
|
|
||||||
var flags = 0
|
var flags = 0
|
||||||
if not canFormAcycle(t): flags = flags or 1
|
if not canFormAcycle(t): flags = flags or 1
|
||||||
|
|
||||||
addf(m.s[cfsTypeInit3], "$1.destructor = (void*)$2; $1.size = sizeof($3); $1.align = NIM_ALIGNOF($3); $1.name = $4;$n; $1.traceImpl = (void*)$5; $1.flags = $6;", [
|
var typeEntry = newRopeAppender()
|
||||||
name, destroyImpl, getTypeDesc(m, t), typeName,
|
addf(typeEntry, "$1.destructor = (void*)", [name])
|
||||||
traceImpl, rope(flags)])
|
genHook(m, t, info, attachedDestructor, typeEntry)
|
||||||
|
|
||||||
|
addf(typeEntry, "; $1.traceImpl = (void*)", [name])
|
||||||
|
genHook(m, t, info, attachedTrace, typeEntry)
|
||||||
|
|
||||||
|
addf(typeEntry, "; $1.name = $2;$n; $1.size = sizeof($3); $1.align = NIM_ALIGNOF($3); $1.flags = $4;",
|
||||||
|
[name, typeName, getTypeDesc(m, t), rope(flags)])
|
||||||
|
|
||||||
|
m.s[cfsTypeInit3].add typeEntry
|
||||||
|
|
||||||
if t.kind == tyObject and t.len > 0 and t[0] != nil and optEnableDeepCopy in m.config.globalOptions:
|
if t.kind == tyObject and t.len > 0 and t[0] != nil and optEnableDeepCopy in m.config.globalOptions:
|
||||||
discard genTypeInfoV1(m, t, info)
|
discard genTypeInfoV1(m, t, info)
|
||||||
|
|
@ -1359,12 +1362,12 @@ proc genTypeInfoV2(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||||
|
|
||||||
let sig = hashType(origType)
|
let sig = hashType(origType)
|
||||||
result = m.typeInfoMarkerV2.getOrDefault(sig)
|
result = m.typeInfoMarkerV2.getOrDefault(sig)
|
||||||
if result != nil:
|
if result != "":
|
||||||
return prefixTI.rope & result & ")".rope
|
return prefixTI.rope & result & ")".rope
|
||||||
|
|
||||||
let marker = m.g.typeInfoMarkerV2.getOrDefault(sig)
|
let marker = m.g.typeInfoMarkerV2.getOrDefault(sig)
|
||||||
if marker.str != nil:
|
if marker.str != "":
|
||||||
discard cgsym(m, "TNimTypeV2")
|
cgsym(m, "TNimTypeV2")
|
||||||
declareNimType(m, "TNimTypeV2", marker.str, marker.owner)
|
declareNimType(m, "TNimTypeV2", marker.str, marker.owner)
|
||||||
# also store in local type section:
|
# also store in local type section:
|
||||||
m.typeInfoMarkerV2[sig] = marker.str
|
m.typeInfoMarkerV2[sig] = marker.str
|
||||||
|
|
@ -1378,7 +1381,7 @@ proc genTypeInfoV2(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||||
# make sure the type info is created in the owner module
|
# make sure the type info is created in the owner module
|
||||||
discard genTypeInfoV2(m.g.modules[owner], origType, info)
|
discard genTypeInfoV2(m.g.modules[owner], origType, info)
|
||||||
# reference the type info as extern here
|
# reference the type info as extern here
|
||||||
discard cgsym(m, "TNimTypeV2")
|
cgsym(m, "TNimTypeV2")
|
||||||
declareNimType(m, "TNimTypeV2", result, owner)
|
declareNimType(m, "TNimTypeV2", result, owner)
|
||||||
return prefixTI.rope & result & ")".rope
|
return prefixTI.rope & result & ")".rope
|
||||||
|
|
||||||
|
|
@ -1430,13 +1433,13 @@ proc genTypeInfoV1(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||||
|
|
||||||
let sig = hashType(origType)
|
let sig = hashType(origType)
|
||||||
result = m.typeInfoMarker.getOrDefault(sig)
|
result = m.typeInfoMarker.getOrDefault(sig)
|
||||||
if result != nil:
|
if result != "":
|
||||||
return prefixTI.rope & result & ")".rope
|
return prefixTI.rope & result & ")".rope
|
||||||
|
|
||||||
let marker = m.g.typeInfoMarker.getOrDefault(sig)
|
let marker = m.g.typeInfoMarker.getOrDefault(sig)
|
||||||
if marker.str != nil:
|
if marker.str != "":
|
||||||
discard cgsym(m, "TNimType")
|
cgsym(m, "TNimType")
|
||||||
discard cgsym(m, "TNimNode")
|
cgsym(m, "TNimNode")
|
||||||
declareNimType(m, "TNimType", marker.str, marker.owner)
|
declareNimType(m, "TNimType", marker.str, marker.owner)
|
||||||
# also store in local type section:
|
# also store in local type section:
|
||||||
m.typeInfoMarker[sig] = marker.str
|
m.typeInfoMarker[sig] = marker.str
|
||||||
|
|
@ -1447,8 +1450,8 @@ proc genTypeInfoV1(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||||
|
|
||||||
let old = m.g.graph.emittedTypeInfo.getOrDefault($result)
|
let old = m.g.graph.emittedTypeInfo.getOrDefault($result)
|
||||||
if old != FileIndex(0):
|
if old != FileIndex(0):
|
||||||
discard cgsym(m, "TNimType")
|
cgsym(m, "TNimType")
|
||||||
discard cgsym(m, "TNimNode")
|
cgsym(m, "TNimNode")
|
||||||
declareNimType(m, "TNimType", result, old.int)
|
declareNimType(m, "TNimType", result, old.int)
|
||||||
return prefixTI.rope & result & ")".rope
|
return prefixTI.rope & result & ")".rope
|
||||||
|
|
||||||
|
|
@ -1457,8 +1460,8 @@ proc genTypeInfoV1(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||||
# make sure the type info is created in the owner module
|
# make sure the type info is created in the owner module
|
||||||
discard genTypeInfoV1(m.g.modules[owner], origType, info)
|
discard genTypeInfoV1(m.g.modules[owner], origType, info)
|
||||||
# reference the type info as extern here
|
# reference the type info as extern here
|
||||||
discard cgsym(m, "TNimType")
|
cgsym(m, "TNimType")
|
||||||
discard cgsym(m, "TNimNode")
|
cgsym(m, "TNimNode")
|
||||||
declareNimType(m, "TNimType", result, owner)
|
declareNimType(m, "TNimType", result, owner)
|
||||||
return prefixTI.rope & result & ")".rope
|
return prefixTI.rope & result & ")".rope
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ when defined(nimPreviewSlimSystem):
|
||||||
when not defined(leanCompiler):
|
when not defined(leanCompiler):
|
||||||
import spawn, semparallel
|
import spawn, semparallel
|
||||||
|
|
||||||
import strutils except `%` # collides with ropes.`%`
|
import strutils except `%`, addf # collides with ropes.`%`
|
||||||
|
|
||||||
from ic / ic import ModuleBackendFlag
|
from ic / ic import ModuleBackendFlag
|
||||||
import dynlib
|
import dynlib
|
||||||
|
|
@ -63,16 +63,23 @@ proc initLoc(result: var TLoc, k: TLocKind, lode: PNode, s: TStorageLoc) =
|
||||||
result.k = k
|
result.k = k
|
||||||
result.storage = s
|
result.storage = s
|
||||||
result.lode = lode
|
result.lode = lode
|
||||||
result.r = nil
|
result.r = ""
|
||||||
result.flags = {}
|
result.flags = {}
|
||||||
|
|
||||||
proc fillLoc(a: var TLoc, k: TLocKind, lode: PNode, r: Rope, s: TStorageLoc) =
|
proc fillLoc(a: var TLoc, k: TLocKind, lode: PNode, r: Rope, s: TStorageLoc) {.inline.} =
|
||||||
|
# fills the loc if it is not already initialized
|
||||||
|
if a.k == locNone:
|
||||||
|
a.k = k
|
||||||
|
a.lode = lode
|
||||||
|
a.storage = s
|
||||||
|
if a.r == "": a.r = r
|
||||||
|
|
||||||
|
proc fillLoc(a: var TLoc, k: TLocKind, lode: PNode, s: TStorageLoc) {.inline.} =
|
||||||
# fills the loc if it is not already initialized
|
# fills the loc if it is not already initialized
|
||||||
if a.k == locNone:
|
if a.k == locNone:
|
||||||
a.k = k
|
a.k = k
|
||||||
a.lode = lode
|
a.lode = lode
|
||||||
a.storage = s
|
a.storage = s
|
||||||
if a.r == nil: a.r = r
|
|
||||||
|
|
||||||
proc t(a: TLoc): PType {.inline.} =
|
proc t(a: TLoc): PType {.inline.} =
|
||||||
if a.lode.kind == nkSym:
|
if a.lode.kind == nkSym:
|
||||||
|
|
@ -96,7 +103,8 @@ proc useHeader(m: BModule, sym: PSym) =
|
||||||
let str = getStr(sym.annex.path)
|
let str = getStr(sym.annex.path)
|
||||||
m.includeHeader(str)
|
m.includeHeader(str)
|
||||||
|
|
||||||
proc cgsym(m: BModule, name: string): Rope
|
proc cgsym(m: BModule, name: string)
|
||||||
|
proc cgsymValue(m: BModule, name: string): Rope
|
||||||
|
|
||||||
proc getCFile(m: BModule): AbsoluteFile
|
proc getCFile(m: BModule): AbsoluteFile
|
||||||
|
|
||||||
|
|
@ -113,10 +121,6 @@ proc getModuleDllPath(m: BModule, s: PSym): Rope =
|
||||||
|
|
||||||
import macros
|
import macros
|
||||||
|
|
||||||
proc cgFormatValue(result: var string; value: Rope) =
|
|
||||||
for str in leaves(value):
|
|
||||||
result.add str
|
|
||||||
|
|
||||||
proc cgFormatValue(result: var string; value: string) =
|
proc cgFormatValue(result: var string; value: string) =
|
||||||
result.add value
|
result.add value
|
||||||
|
|
||||||
|
|
@ -197,7 +201,7 @@ macro ropecg(m: BModule, frmt: static[FormatStr], args: untyped): Rope =
|
||||||
var ident = newLit(substr(frmt, i, j-1))
|
var ident = newLit(substr(frmt, i, j-1))
|
||||||
i = j
|
i = j
|
||||||
flushStrLit()
|
flushStrLit()
|
||||||
result.add newCall(formatValue, resVar, newCall(ident"cgsym", m, ident))
|
result.add newCall(formatValue, resVar, newCall(ident"cgsymValue", m, ident))
|
||||||
elif frmt[i] == '#' and frmt[i+1] == '$':
|
elif frmt[i] == '#' and frmt[i+1] == '$':
|
||||||
inc(i, 2)
|
inc(i, 2)
|
||||||
var j = 0
|
var j = 0
|
||||||
|
|
@ -206,7 +210,7 @@ macro ropecg(m: BModule, frmt: static[FormatStr], args: untyped): Rope =
|
||||||
inc(i)
|
inc(i)
|
||||||
let ident = args[j-1]
|
let ident = args[j-1]
|
||||||
flushStrLit()
|
flushStrLit()
|
||||||
result.add newCall(formatValue, resVar, newCall(ident"cgsym", m, ident))
|
result.add newCall(formatValue, resVar, newCall(ident"cgsymValue", m, ident))
|
||||||
var start = i
|
var start = i
|
||||||
while i < frmt.len:
|
while i < frmt.len:
|
||||||
if frmt[i] != '$' and frmt[i] != '#': inc(i)
|
if frmt[i] != '$' and frmt[i] != '#': inc(i)
|
||||||
|
|
@ -217,10 +221,9 @@ macro ropecg(m: BModule, frmt: static[FormatStr], args: untyped): Rope =
|
||||||
flushStrLit()
|
flushStrLit()
|
||||||
result.add newCall(ident"rope", resVar)
|
result.add newCall(ident"rope", resVar)
|
||||||
|
|
||||||
proc indentLine(p: BProc, r: Rope): Rope =
|
proc addIndent(p: BProc; result: var Rope) =
|
||||||
result = r
|
|
||||||
for i in 0..<p.blocks.len:
|
for i in 0..<p.blocks.len:
|
||||||
prepend(result, "\t".rope)
|
result.add "\t".rope
|
||||||
|
|
||||||
template appcg(m: BModule, c: var Rope, frmt: FormatStr,
|
template appcg(m: BModule, c: var Rope, frmt: FormatStr,
|
||||||
args: untyped) =
|
args: untyped) =
|
||||||
|
|
@ -234,23 +237,24 @@ template appcg(p: BProc, sec: TCProcSection, frmt: FormatStr,
|
||||||
args: untyped) =
|
args: untyped) =
|
||||||
p.s(sec).add(ropecg(p.module, frmt, args))
|
p.s(sec).add(ropecg(p.module, frmt, args))
|
||||||
|
|
||||||
template line(p: BProc, sec: TCProcSection, r: Rope) =
|
|
||||||
p.s(sec).add(indentLine(p, r))
|
|
||||||
|
|
||||||
template line(p: BProc, sec: TCProcSection, r: string) =
|
template line(p: BProc, sec: TCProcSection, r: string) =
|
||||||
p.s(sec).add(indentLine(p, r.rope))
|
addIndent p, p.s(sec)
|
||||||
|
p.s(sec).add(r)
|
||||||
|
|
||||||
template lineF(p: BProc, sec: TCProcSection, frmt: FormatStr,
|
template lineF(p: BProc, sec: TCProcSection, frmt: FormatStr,
|
||||||
args: untyped) =
|
args: untyped) =
|
||||||
p.s(sec).add(indentLine(p, frmt % args))
|
addIndent p, p.s(sec)
|
||||||
|
p.s(sec).add(frmt % args)
|
||||||
|
|
||||||
template lineCg(p: BProc, sec: TCProcSection, frmt: FormatStr,
|
template lineCg(p: BProc, sec: TCProcSection, frmt: FormatStr,
|
||||||
args: untyped) =
|
args: untyped) =
|
||||||
p.s(sec).add(indentLine(p, ropecg(p.module, frmt, args)))
|
addIndent p, p.s(sec)
|
||||||
|
p.s(sec).add(ropecg(p.module, frmt, args))
|
||||||
|
|
||||||
template linefmt(p: BProc, sec: TCProcSection, frmt: FormatStr,
|
template linefmt(p: BProc, sec: TCProcSection, frmt: FormatStr,
|
||||||
args: untyped) =
|
args: untyped) =
|
||||||
p.s(sec).add(indentLine(p, ropecg(p.module, frmt, args)))
|
addIndent p, p.s(sec)
|
||||||
|
p.s(sec).add(ropecg(p.module, frmt, args))
|
||||||
|
|
||||||
proc safeLineNm(info: TLineInfo): int =
|
proc safeLineNm(info: TLineInfo): int =
|
||||||
result = toLinenumber(info)
|
result = toLinenumber(info)
|
||||||
|
|
@ -276,7 +280,7 @@ proc genLineDir(p: BProc, t: PNode) =
|
||||||
let line = t.info.safeLineNm
|
let line = t.info.safeLineNm
|
||||||
|
|
||||||
if optEmbedOrigSrc in p.config.globalOptions:
|
if optEmbedOrigSrc in p.config.globalOptions:
|
||||||
p.s(cpsStmts).add(~"//" & sourceLine(p.config, t.info) & "\L")
|
p.s(cpsStmts).add("//" & sourceLine(p.config, t.info) & "\L")
|
||||||
genCLineDir(p.s(cpsStmts), toFullPath(p.config, t.info), line, p.config)
|
genCLineDir(p.s(cpsStmts), toFullPath(p.config, t.info), line, p.config)
|
||||||
if ({optLineTrace, optStackTrace} * p.options == {optLineTrace, optStackTrace}) and
|
if ({optLineTrace, optStackTrace} * p.options == {optLineTrace, optStackTrace}) and
|
||||||
(p.prc == nil or sfPure notin p.prc.flags) and t.info.fileIndex != InvalidFileIdx:
|
(p.prc == nil or sfPure notin p.prc.flags) and t.info.fileIndex != InvalidFileIdx:
|
||||||
|
|
@ -287,7 +291,7 @@ proc genLineDir(p: BProc, t: PNode) =
|
||||||
proc accessThreadLocalVar(p: BProc, s: PSym)
|
proc accessThreadLocalVar(p: BProc, s: PSym)
|
||||||
proc emulatedThreadVars(conf: ConfigRef): bool {.inline.}
|
proc emulatedThreadVars(conf: ConfigRef): bool {.inline.}
|
||||||
proc genProc(m: BModule, prc: PSym)
|
proc genProc(m: BModule, prc: PSym)
|
||||||
proc raiseInstr(p: BProc): Rope
|
proc raiseInstr(p: BProc; result: var Rope)
|
||||||
|
|
||||||
template compileToCpp(m: BModule): untyped =
|
template compileToCpp(m: BModule): untyped =
|
||||||
m.config.backend == backendCpp or sfCompileToCpp in m.module.flags
|
m.config.backend == backendCpp or sfCompileToCpp in m.module.flags
|
||||||
|
|
@ -298,10 +302,18 @@ proc getTempName(m: BModule): Rope =
|
||||||
|
|
||||||
proc rdLoc(a: TLoc): Rope =
|
proc rdLoc(a: TLoc): Rope =
|
||||||
# 'read' location (deref if indirect)
|
# 'read' location (deref if indirect)
|
||||||
result = a.r
|
if lfIndirect in a.flags:
|
||||||
if lfIndirect in a.flags: result = "(*$1)" % [result]
|
result = "(*" & a.r & ")"
|
||||||
|
else:
|
||||||
|
result = a.r
|
||||||
|
|
||||||
proc lenField(p: BProc): Rope =
|
proc addRdLoc(a: TLoc; result: var Rope) =
|
||||||
|
if lfIndirect in a.flags:
|
||||||
|
result.add "(*" & a.r & ")"
|
||||||
|
else:
|
||||||
|
result.add a.r
|
||||||
|
|
||||||
|
proc lenField(p: BProc): Rope {.inline.} =
|
||||||
result = rope(if p.module.compileToCpp: "len" else: "Sup.len")
|
result = rope(if p.module.compileToCpp: "len" else: "Sup.len")
|
||||||
|
|
||||||
proc lenExpr(p: BProc; a: TLoc): Rope =
|
proc lenExpr(p: BProc; a: TLoc): Rope =
|
||||||
|
|
@ -326,16 +338,24 @@ template mapTypeChooser(n: PNode): TSymKind =
|
||||||
|
|
||||||
template mapTypeChooser(a: TLoc): TSymKind = mapTypeChooser(a.lode)
|
template mapTypeChooser(a: TLoc): TSymKind = mapTypeChooser(a.lode)
|
||||||
|
|
||||||
proc addrLoc(conf: ConfigRef; a: TLoc): Rope =
|
proc addAddrLoc(conf: ConfigRef; a: TLoc; result: var Rope) =
|
||||||
result = a.r
|
|
||||||
if lfIndirect notin a.flags and mapType(conf, a.t, mapTypeChooser(a)) != ctArray:
|
if lfIndirect notin a.flags and mapType(conf, a.t, mapTypeChooser(a)) != ctArray:
|
||||||
result = "(&" & result & ")"
|
result.add "(&" & a.r & ")"
|
||||||
|
else:
|
||||||
|
result.add a.r
|
||||||
|
|
||||||
|
proc addrLoc(conf: ConfigRef; a: TLoc): Rope =
|
||||||
|
if lfIndirect notin a.flags and mapType(conf, a.t, mapTypeChooser(a)) != ctArray:
|
||||||
|
result = "(&" & a.r & ")"
|
||||||
|
else:
|
||||||
|
result = a.r
|
||||||
|
|
||||||
proc byRefLoc(p: BProc; a: TLoc): Rope =
|
proc byRefLoc(p: BProc; a: TLoc): Rope =
|
||||||
result = a.r
|
|
||||||
if lfIndirect notin a.flags and mapType(p.config, a.t, mapTypeChooser(a)) != ctArray and not
|
if lfIndirect notin a.flags and mapType(p.config, a.t, mapTypeChooser(a)) != ctArray and not
|
||||||
p.module.compileToCpp:
|
p.module.compileToCpp:
|
||||||
result = "(&" & result & ")"
|
result = "(&" & a.r & ")"
|
||||||
|
else:
|
||||||
|
result = a.r
|
||||||
|
|
||||||
proc rdCharLoc(a: TLoc): Rope =
|
proc rdCharLoc(a: TLoc): Rope =
|
||||||
# read a location that may need a char-cast:
|
# read a location that may need a char-cast:
|
||||||
|
|
@ -416,7 +436,7 @@ proc resetLoc(p: BProc, loc: var TLoc) =
|
||||||
let typ = skipTypes(loc.t, abstractVarRange)
|
let typ = skipTypes(loc.t, abstractVarRange)
|
||||||
if isImportedCppType(typ): return
|
if isImportedCppType(typ): return
|
||||||
if optSeqDestructors in p.config.globalOptions and typ.kind in {tyString, tySequence}:
|
if optSeqDestructors in p.config.globalOptions and typ.kind in {tyString, tySequence}:
|
||||||
assert rdLoc(loc) != nil
|
assert loc.r != ""
|
||||||
|
|
||||||
let atyp = skipTypes(loc.t, abstractInst)
|
let atyp = skipTypes(loc.t, abstractInst)
|
||||||
if atyp.kind in {tyVar, tyLent}:
|
if atyp.kind in {tyVar, tyLent}:
|
||||||
|
|
@ -523,7 +543,8 @@ proc getIntTemp(p: BProc, result: var TLoc) =
|
||||||
proc localVarDecl(p: BProc; n: PNode): Rope =
|
proc localVarDecl(p: BProc; n: PNode): Rope =
|
||||||
let s = n.sym
|
let s = n.sym
|
||||||
if s.loc.k == locNone:
|
if s.loc.k == locNone:
|
||||||
fillLoc(s.loc, locLocalVar, n, mangleLocalName(p, s), OnStack)
|
fillLocalName(p, s)
|
||||||
|
fillLoc(s.loc, locLocalVar, n, OnStack)
|
||||||
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
|
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
|
||||||
if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0:
|
if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0:
|
||||||
result.addf("NIM_ALIGN($1) ", [rope(s.alignment)])
|
result.addf("NIM_ALIGN($1) ", [rope(s.alignment)])
|
||||||
|
|
@ -560,7 +581,8 @@ proc treatGlobalDifferentlyForHCR(m: BModule, s: PSym): bool =
|
||||||
proc assignGlobalVar(p: BProc, n: PNode; value: Rope) =
|
proc assignGlobalVar(p: BProc, n: PNode; value: Rope) =
|
||||||
let s = n.sym
|
let s = n.sym
|
||||||
if s.loc.k == locNone:
|
if s.loc.k == locNone:
|
||||||
fillLoc(s.loc, locGlobalVar, n, mangleName(p.module, s), OnHeap)
|
fillBackendName(p.module, s)
|
||||||
|
fillLoc(s.loc, locGlobalVar, n, OnHeap)
|
||||||
if treatGlobalDifferentlyForHCR(p.module, s): incl(s.loc.flags, lfIndirect)
|
if treatGlobalDifferentlyForHCR(p.module, s): incl(s.loc.flags, lfIndirect)
|
||||||
|
|
||||||
if lfDynamicLib in s.loc.flags:
|
if lfDynamicLib in s.loc.flags:
|
||||||
|
|
@ -569,7 +591,7 @@ proc assignGlobalVar(p: BProc, n: PNode; value: Rope) =
|
||||||
varInDynamicLib(q, s)
|
varInDynamicLib(q, s)
|
||||||
else:
|
else:
|
||||||
s.loc.r = mangleDynLibProc(s)
|
s.loc.r = mangleDynLibProc(s)
|
||||||
if value != nil:
|
if value != "":
|
||||||
internalError(p.config, n.info, ".dynlib variables cannot have a value")
|
internalError(p.config, n.info, ".dynlib variables cannot have a value")
|
||||||
return
|
return
|
||||||
useHeader(p.module, s)
|
useHeader(p.module, s)
|
||||||
|
|
@ -577,10 +599,10 @@ proc assignGlobalVar(p: BProc, n: PNode; value: Rope) =
|
||||||
if not containsOrIncl(p.module.declaredThings, s.id):
|
if not containsOrIncl(p.module.declaredThings, s.id):
|
||||||
if sfThread in s.flags:
|
if sfThread in s.flags:
|
||||||
declareThreadVar(p.module, s, sfImportc in s.flags)
|
declareThreadVar(p.module, s, sfImportc in s.flags)
|
||||||
if value != nil:
|
if value != "":
|
||||||
internalError(p.config, n.info, ".threadvar variables cannot have a value")
|
internalError(p.config, n.info, ".threadvar variables cannot have a value")
|
||||||
else:
|
else:
|
||||||
var decl: Rope = nil
|
var decl: Rope = ""
|
||||||
var td = getTypeDesc(p.module, s.loc.t, skVar)
|
var td = getTypeDesc(p.module, s.loc.t, skVar)
|
||||||
if s.constraint.isNil:
|
if s.constraint.isNil:
|
||||||
if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0:
|
if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0:
|
||||||
|
|
@ -589,34 +611,35 @@ proc assignGlobalVar(p: BProc, n: PNode; value: Rope) =
|
||||||
elif sfImportc in s.flags: decl.add("extern ")
|
elif sfImportc in s.flags: decl.add("extern ")
|
||||||
elif lfExportLib in s.loc.flags: decl.add("N_LIB_EXPORT_VAR ")
|
elif lfExportLib in s.loc.flags: decl.add("N_LIB_EXPORT_VAR ")
|
||||||
else: decl.add("N_LIB_PRIVATE ")
|
else: decl.add("N_LIB_PRIVATE ")
|
||||||
if s.kind == skLet and value != nil: decl.add("NIM_CONST ")
|
if s.kind == skLet and value != "": decl.add("NIM_CONST ")
|
||||||
decl.add(td)
|
decl.add(td)
|
||||||
if p.hcrOn: decl.add("*")
|
if p.hcrOn: decl.add("*")
|
||||||
if sfRegister in s.flags: decl.add(" register")
|
if sfRegister in s.flags: decl.add(" register")
|
||||||
if sfVolatile in s.flags: decl.add(" volatile")
|
if sfVolatile in s.flags: decl.add(" volatile")
|
||||||
if sfNoalias in s.flags: decl.add(" NIM_NOALIAS")
|
if sfNoalias in s.flags: decl.add(" NIM_NOALIAS")
|
||||||
if value != nil:
|
if value != "":
|
||||||
decl.addf(" $1 = $2;$n", [s.loc.r, value])
|
decl.addf(" $1 = $2;$n", [s.loc.r, value])
|
||||||
else:
|
else:
|
||||||
decl.addf(" $1;$n", [s.loc.r])
|
decl.addf(" $1;$n", [s.loc.r])
|
||||||
else:
|
else:
|
||||||
if value != nil:
|
if value != "":
|
||||||
decl = runtimeFormat(s.cgDeclFrmt & " = $#;$n", [td, s.loc.r, value])
|
decl = runtimeFormat(s.cgDeclFrmt & " = $#;$n", [td, s.loc.r, value])
|
||||||
else:
|
else:
|
||||||
decl = runtimeFormat(s.cgDeclFrmt & ";$n", [td, s.loc.r])
|
decl = runtimeFormat(s.cgDeclFrmt & ";$n", [td, s.loc.r])
|
||||||
p.module.s[cfsVars].add(decl)
|
p.module.s[cfsVars].add(decl)
|
||||||
if p.withinLoop > 0 and value == nil:
|
if p.withinLoop > 0 and value == "":
|
||||||
# fixes tests/run/tzeroarray:
|
# fixes tests/run/tzeroarray:
|
||||||
resetLoc(p, s.loc)
|
resetLoc(p, s.loc)
|
||||||
|
|
||||||
proc assignParam(p: BProc, s: PSym, retType: PType) =
|
proc assignParam(p: BProc, s: PSym, retType: PType) =
|
||||||
assert(s.loc.r != nil)
|
assert(s.loc.r != "")
|
||||||
scopeMangledParam(p, s)
|
scopeMangledParam(p, s)
|
||||||
|
|
||||||
proc fillProcLoc(m: BModule; n: PNode) =
|
proc fillProcLoc(m: BModule; n: PNode) =
|
||||||
let sym = n.sym
|
let sym = n.sym
|
||||||
if sym.loc.k == locNone:
|
if sym.loc.k == locNone:
|
||||||
fillLoc(sym.loc, locProc, n, mangleName(m, sym), OnStack)
|
fillBackendName(m, sym)
|
||||||
|
fillLoc(sym.loc, locProc, n, OnStack)
|
||||||
|
|
||||||
proc getLabel(p: BProc): TLabel =
|
proc getLabel(p: BProc): TLabel =
|
||||||
inc(p.labels)
|
inc(p.labels)
|
||||||
|
|
@ -631,9 +654,9 @@ proc genStmts(p: BProc, t: PNode)
|
||||||
proc expr(p: BProc, n: PNode, d: var TLoc)
|
proc expr(p: BProc, n: PNode, d: var TLoc)
|
||||||
proc genProcPrototype(m: BModule, sym: PSym)
|
proc genProcPrototype(m: BModule, sym: PSym)
|
||||||
proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc)
|
proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc)
|
||||||
proc intLiteral(i: BiggestInt): Rope
|
proc intLiteral(i: BiggestInt; result: var Rope)
|
||||||
proc genLiteral(p: BProc, n: PNode): Rope
|
proc genLiteral(p: BProc, n: PNode; result: var Rope)
|
||||||
proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType): Rope
|
proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType; result: var Rope; argsCounter: var int)
|
||||||
proc raiseExit(p: BProc)
|
proc raiseExit(p: BProc)
|
||||||
|
|
||||||
proc initLocExpr(p: BProc, e: PNode, result: var TLoc) =
|
proc initLocExpr(p: BProc, e: PNode, result: var TLoc) =
|
||||||
|
|
@ -671,11 +694,11 @@ proc initFrame(p: BProc, procname, filename: Rope): Rope =
|
||||||
if p.module.s[cfsFrameDefines].len == 0:
|
if p.module.s[cfsFrameDefines].len == 0:
|
||||||
appcg(p.module, p.module.s[cfsFrameDefines], frameDefines, ["#"])
|
appcg(p.module, p.module.s[cfsFrameDefines], frameDefines, ["#"])
|
||||||
|
|
||||||
discard cgsym(p.module, "nimFrame")
|
cgsym(p.module, "nimFrame")
|
||||||
result = ropecg(p.module, "\tnimfr_($1, $2);$n", [procname, filename])
|
result = ropecg(p.module, "\tnimfr_($1, $2);$n", [procname, filename])
|
||||||
|
|
||||||
proc initFrameNoDebug(p: BProc; frame, procname, filename: Rope; line: int): Rope =
|
proc initFrameNoDebug(p: BProc; frame, procname, filename: Rope; line: int): Rope =
|
||||||
discard cgsym(p.module, "nimFrame")
|
cgsym(p.module, "nimFrame")
|
||||||
p.blocks[0].sections[cpsLocals].addf("TFrame $1;$n", [frame])
|
p.blocks[0].sections[cpsLocals].addf("TFrame $1;$n", [frame])
|
||||||
result = ropecg(p.module, "\t$1.procname = $2; $1.filename = $3; " &
|
result = ropecg(p.module, "\t$1.procname = $2; $1.filename = $3; " &
|
||||||
" $1.line = $4; $1.len = -1; nimFrame(&$1);$n",
|
" $1.line = $4; $1.len = -1; nimFrame(&$1);$n",
|
||||||
|
|
@ -702,24 +725,28 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
|
||||||
if not lib.generated:
|
if not lib.generated:
|
||||||
lib.generated = true
|
lib.generated = true
|
||||||
var tmp = getTempName(m)
|
var tmp = getTempName(m)
|
||||||
assert(lib.name == nil)
|
assert(lib.name == "")
|
||||||
lib.name = tmp # BUGFIX: cgsym has awful side-effects
|
lib.name = tmp # BUGFIX: cgsym has awful side-effects
|
||||||
m.s[cfsVars].addf("static void* $1;$n", [tmp])
|
m.s[cfsVars].addf("static void* $1;$n", [tmp])
|
||||||
if lib.path.kind in {nkStrLit..nkTripleStrLit}:
|
if lib.path.kind in {nkStrLit..nkTripleStrLit}:
|
||||||
var s: TStringSeq = @[]
|
var s: TStringSeq = @[]
|
||||||
libCandidates(lib.path.strVal, s)
|
libCandidates(lib.path.strVal, s)
|
||||||
rawMessage(m.config, hintDependency, lib.path.strVal)
|
rawMessage(m.config, hintDependency, lib.path.strVal)
|
||||||
var loadlib: Rope = nil
|
var loadlib: Rope = ""
|
||||||
for i in 0..high(s):
|
for i in 0..high(s):
|
||||||
inc(m.labels)
|
inc(m.labels)
|
||||||
if i > 0: loadlib.add("||")
|
if i > 0: loadlib.add("||")
|
||||||
let n = newStrNode(nkStrLit, s[i])
|
let n = newStrNode(nkStrLit, s[i])
|
||||||
n.info = lib.path.info
|
n.info = lib.path.info
|
||||||
appcg(m, loadlib, "($1 = #nimLoadLibrary($2))$n",
|
appcg(m, loadlib, "($1 = #nimLoadLibrary(", [tmp])
|
||||||
[tmp, genStringLiteral(m, n)])
|
genStringLiteral(m, n, loadlib)
|
||||||
|
loadlib.addf "))$n", []
|
||||||
appcg(m, m.s[cfsDynLibInit],
|
appcg(m, m.s[cfsDynLibInit],
|
||||||
"if (!($1)) #nimLoadLibraryError($2);$n",
|
"if (!($1)) #nimLoadLibraryError(",
|
||||||
[loadlib, genStringLiteral(m, lib.path)])
|
[loadlib])
|
||||||
|
genStringLiteral(m, lib.path, m.s[cfsDynLibInit])
|
||||||
|
m.s[cfsDynLibInit].addf ");$n", []
|
||||||
|
|
||||||
else:
|
else:
|
||||||
var p = newProc(nil, m)
|
var p = newProc(nil, m)
|
||||||
p.options.excl optStackTrace
|
p.options.excl optStackTrace
|
||||||
|
|
@ -738,7 +765,7 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
|
||||||
"if (!($1 = #nimLoadLibrary($2))) #nimLoadLibraryError($2);$n",
|
"if (!($1 = #nimLoadLibrary($2))) #nimLoadLibraryError($2);$n",
|
||||||
[tmp, rdLoc(dest)])
|
[tmp, rdLoc(dest)])
|
||||||
|
|
||||||
if lib.name == nil: internalError(m.config, "loadDynamicLib")
|
if lib.name == "": internalError(m.config, "loadDynamicLib")
|
||||||
|
|
||||||
proc mangleDynLibProc(sym: PSym): Rope =
|
proc mangleDynLibProc(sym: PSym): Rope =
|
||||||
# we have to build this as a single rope in order not to trip the
|
# we have to build this as a single rope in order not to trip the
|
||||||
|
|
@ -803,18 +830,25 @@ proc symInDynamicLibPartial(m: BModule, sym: PSym) =
|
||||||
sym.loc.r = mangleDynLibProc(sym)
|
sym.loc.r = mangleDynLibProc(sym)
|
||||||
sym.typ.sym = nil # generate a new name
|
sym.typ.sym = nil # generate a new name
|
||||||
|
|
||||||
proc cgsym(m: BModule, name: string): Rope =
|
proc cgsymImpl(m: BModule; sym: PSym) {.inline.} =
|
||||||
|
case sym.kind
|
||||||
|
of skProc, skFunc, skMethod, skConverter, skIterator: genProc(m, sym)
|
||||||
|
of skVar, skResult, skLet: genVarPrototype(m, newSymNode sym)
|
||||||
|
of skType: discard getTypeDesc(m, sym.typ)
|
||||||
|
else: internalError(m.config, "cgsym: " & $sym.kind)
|
||||||
|
|
||||||
|
proc cgsym(m: BModule, name: string) =
|
||||||
let sym = magicsys.getCompilerProc(m.g.graph, name)
|
let sym = magicsys.getCompilerProc(m.g.graph, name)
|
||||||
if sym != nil:
|
if sym != nil:
|
||||||
case sym.kind
|
cgsymImpl m, sym
|
||||||
of skProc, skFunc, skMethod, skConverter, skIterator: genProc(m, sym)
|
else:
|
||||||
of skVar, skResult, skLet: genVarPrototype(m, newSymNode sym)
|
rawMessage(m.config, errGenerated, "system module needs: " & name)
|
||||||
of skType: discard getTypeDesc(m, sym.typ)
|
|
||||||
else: internalError(m.config, "cgsym: " & name & ": " & $sym.kind)
|
proc cgsymValue(m: BModule, name: string): Rope =
|
||||||
|
let sym = magicsys.getCompilerProc(m.g.graph, name)
|
||||||
|
if sym != nil:
|
||||||
|
cgsymImpl m, sym
|
||||||
else:
|
else:
|
||||||
# we used to exclude the system module from this check, but for DLL
|
|
||||||
# generation support this sloppyness leads to hard to detect bugs, so
|
|
||||||
# we're picky here for the system module too:
|
|
||||||
rawMessage(m.config, errGenerated, "system module needs: " & name)
|
rawMessage(m.config, errGenerated, "system module needs: " & name)
|
||||||
result = sym.loc.r
|
result = sym.loc.r
|
||||||
if m.hcrOn and sym != nil and sym.kind in {skProc..skIterator}:
|
if m.hcrOn and sym != nil and sym.kind in {skProc..skIterator}:
|
||||||
|
|
@ -845,12 +879,12 @@ proc generateHeaders(m: BModule) =
|
||||||
#undef unix
|
#undef unix
|
||||||
""")
|
""")
|
||||||
|
|
||||||
proc openNamespaceNim(namespace: string): Rope =
|
proc openNamespaceNim(namespace: string; result: var Rope) =
|
||||||
result.add("namespace ")
|
result.add("namespace ")
|
||||||
result.add(namespace)
|
result.add(namespace)
|
||||||
result.add(" {\L")
|
result.add(" {\L")
|
||||||
|
|
||||||
proc closeNamespaceNim(): Rope =
|
proc closeNamespaceNim(result: var Rope) =
|
||||||
result.add("}\L")
|
result.add("}\L")
|
||||||
|
|
||||||
proc closureSetup(p: BProc, prc: PSym) =
|
proc closureSetup(p: BProc, prc: PSym) =
|
||||||
|
|
@ -1028,8 +1062,9 @@ proc isNoReturn(m: BModule; s: PSym): bool {.inline.} =
|
||||||
|
|
||||||
proc genProcAux(m: BModule, prc: PSym) =
|
proc genProcAux(m: BModule, prc: PSym) =
|
||||||
var p = newProc(prc, m)
|
var p = newProc(prc, m)
|
||||||
var header = genProcHeader(m, prc)
|
var header = newRopeAppender()
|
||||||
var returnStmt: Rope = nil
|
genProcHeader(m, prc, header)
|
||||||
|
var returnStmt: Rope = ""
|
||||||
assert(prc.ast != nil)
|
assert(prc.ast != nil)
|
||||||
|
|
||||||
var procBody = transformBody(m.g.graph, m.idgen, prc, cache = false)
|
var procBody = transformBody(m.g.graph, m.idgen, prc, cache = false)
|
||||||
|
|
@ -1051,7 +1086,7 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||||
else:
|
else:
|
||||||
# declare the result symbol:
|
# declare the result symbol:
|
||||||
assignLocalVar(p, resNode)
|
assignLocalVar(p, resNode)
|
||||||
assert(res.loc.r != nil)
|
assert(res.loc.r != "")
|
||||||
initLocalVar(p, res, immediateAsgn=false)
|
initLocalVar(p, res, immediateAsgn=false)
|
||||||
returnStmt = ropecg(p.module, "\treturn $1;$n", [rdLoc(res.loc)])
|
returnStmt = ropecg(p.module, "\treturn $1;$n", [rdLoc(res.loc)])
|
||||||
else:
|
else:
|
||||||
|
|
@ -1109,10 +1144,10 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||||
if beforeRetNeeded in p.flags: generatedProc.add("{")
|
if beforeRetNeeded in p.flags: generatedProc.add("{")
|
||||||
generatedProc.add(p.s(cpsInit))
|
generatedProc.add(p.s(cpsInit))
|
||||||
generatedProc.add(p.s(cpsStmts))
|
generatedProc.add(p.s(cpsStmts))
|
||||||
if beforeRetNeeded in p.flags: generatedProc.add(~"\t}BeforeRet_: ;$n")
|
if beforeRetNeeded in p.flags: generatedProc.add("\t}BeforeRet_: ;\n")
|
||||||
if optStackTrace in prc.options: generatedProc.add(deinitFrame(p))
|
if optStackTrace in prc.options: generatedProc.add(deinitFrame(p))
|
||||||
generatedProc.add(returnStmt)
|
generatedProc.add(returnStmt)
|
||||||
generatedProc.add(~"}$N")
|
generatedProc.add("}\n")
|
||||||
m.s[cfsProcs].add(generatedProc)
|
m.s[cfsProcs].add(generatedProc)
|
||||||
if isReloadable(m, prc):
|
if isReloadable(m, prc):
|
||||||
m.s[cfsDynLibInit].addf("\t$1 = ($3) hcrRegisterProc($4, \"$1\", (void*)$2);$n",
|
m.s[cfsDynLibInit].addf("\t$1 = ($3) hcrRegisterProc($4, \"$1\", (void*)$2);$n",
|
||||||
|
|
@ -1141,7 +1176,8 @@ proc genProcPrototype(m: BModule, sym: PSym) =
|
||||||
[mangleDynLibProc(sym), getTypeDesc(m, sym.loc.t), getModuleDllPath(m, sym)])
|
[mangleDynLibProc(sym), getTypeDesc(m, sym.loc.t), getModuleDllPath(m, sym)])
|
||||||
elif not containsOrIncl(m.declaredProtos, sym.id):
|
elif not containsOrIncl(m.declaredProtos, sym.id):
|
||||||
let asPtr = isReloadable(m, sym)
|
let asPtr = isReloadable(m, sym)
|
||||||
var header = genProcHeader(m, sym, asPtr)
|
var header = newRopeAppender()
|
||||||
|
genProcHeader(m, sym, header, asPtr)
|
||||||
if not asPtr:
|
if not asPtr:
|
||||||
if isNoReturn(m, sym) and hasDeclspec in extccomp.CC[m.config.cCompiler].props:
|
if isNoReturn(m, sym) and hasDeclspec in extccomp.CC[m.config.cCompiler].props:
|
||||||
header = "__declspec(noreturn) " & header
|
header = "__declspec(noreturn) " & header
|
||||||
|
|
@ -1159,7 +1195,7 @@ proc genProcNoForward(m: BModule, prc: PSym) =
|
||||||
fillProcLoc(m, prc.ast[namePos])
|
fillProcLoc(m, prc.ast[namePos])
|
||||||
useHeader(m, prc)
|
useHeader(m, prc)
|
||||||
# dependency to a compilerproc:
|
# dependency to a compilerproc:
|
||||||
discard cgsym(m, prc.name.s)
|
cgsym(m, prc.name.s)
|
||||||
return
|
return
|
||||||
if lfNoDecl in prc.loc.flags:
|
if lfNoDecl in prc.loc.flags:
|
||||||
fillProcLoc(m, prc.ast[namePos])
|
fillProcLoc(m, prc.ast[namePos])
|
||||||
|
|
@ -1250,14 +1286,15 @@ proc genVarPrototype(m: BModule, n: PNode) =
|
||||||
#assert(sfGlobal in sym.flags)
|
#assert(sfGlobal in sym.flags)
|
||||||
let sym = n.sym
|
let sym = n.sym
|
||||||
useHeader(m, sym)
|
useHeader(m, sym)
|
||||||
fillLoc(sym.loc, locGlobalVar, n, mangleName(m, sym), OnHeap)
|
fillBackendName(m, sym)
|
||||||
|
fillLoc(sym.loc, locGlobalVar, n, OnHeap)
|
||||||
if treatGlobalDifferentlyForHCR(m, sym): incl(sym.loc.flags, lfIndirect)
|
if treatGlobalDifferentlyForHCR(m, sym): incl(sym.loc.flags, lfIndirect)
|
||||||
|
|
||||||
if (lfNoDecl in sym.loc.flags) or contains(m.declaredThings, sym.id):
|
if (lfNoDecl in sym.loc.flags) or contains(m.declaredThings, sym.id):
|
||||||
return
|
return
|
||||||
if sym.owner.id != m.module.id:
|
if sym.owner.id != m.module.id:
|
||||||
# else we already have the symbol generated!
|
# else we already have the symbol generated!
|
||||||
assert(sym.loc.r != nil)
|
assert(sym.loc.r != "")
|
||||||
if sfThread in sym.flags:
|
if sfThread in sym.flags:
|
||||||
declareThreadVar(m, sym, true)
|
declareThreadVar(m, sym, true)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1343,9 +1380,11 @@ proc genMainProc(m: BModule) =
|
||||||
assert prc != nil
|
assert prc != nil
|
||||||
let n = newStrNode(nkStrLit, prc.annex.path.strVal)
|
let n = newStrNode(nkStrLit, prc.annex.path.strVal)
|
||||||
n.info = prc.annex.path.info
|
n.info = prc.annex.path.info
|
||||||
|
var strLit = newRopeAppender()
|
||||||
|
genStringLiteral(m, n, strLit)
|
||||||
appcg(m, result, "\tif (!($1 = #nimLoadLibrary($2)))$N" &
|
appcg(m, result, "\tif (!($1 = #nimLoadLibrary($2)))$N" &
|
||||||
"\t\t#nimLoadLibraryError($2);$N",
|
"\t\t#nimLoadLibraryError($2);$N",
|
||||||
[handle, genStringLiteral(m, n)])
|
[handle, strLit])
|
||||||
|
|
||||||
preMainCode.add(loadLib("hcr_handle", "hcrGetProc"))
|
preMainCode.add(loadLib("hcr_handle", "hcrGetProc"))
|
||||||
preMainCode.add("\tvoid* rtl_handle;\L")
|
preMainCode.add("\tvoid* rtl_handle;\L")
|
||||||
|
|
@ -1526,7 +1565,8 @@ proc genMainProc(m: BModule) =
|
||||||
|
|
||||||
if optNoMain notin m.config.globalOptions:
|
if optNoMain notin m.config.globalOptions:
|
||||||
if m.config.cppCustomNamespace.len > 0:
|
if m.config.cppCustomNamespace.len > 0:
|
||||||
m.s[cfsProcs].add closeNamespaceNim() & "using namespace " & m.config.cppCustomNamespace & ";\L"
|
closeNamespaceNim(m.s[cfsProcs])
|
||||||
|
m.s[cfsProcs].add "using namespace " & m.config.cppCustomNamespace & ";\L"
|
||||||
|
|
||||||
if m.config.target.targetOS == osWindows and
|
if m.config.target.targetOS == osWindows and
|
||||||
m.config.globalOptions * {optGenGuiApp, optGenDynLib} != {}:
|
m.config.globalOptions * {optGenGuiApp, optGenDynLib} != {}:
|
||||||
|
|
@ -1550,7 +1590,7 @@ proc genMainProc(m: BModule) =
|
||||||
appcg(m, m.s[cfsProcs], otherMain, [if m.hcrOn: "*" else: "", m.config.nimMainPrefix])
|
appcg(m, m.s[cfsProcs], otherMain, [if m.hcrOn: "*" else: "", m.config.nimMainPrefix])
|
||||||
|
|
||||||
if m.config.cppCustomNamespace.len > 0:
|
if m.config.cppCustomNamespace.len > 0:
|
||||||
m.s[cfsProcs].add openNamespaceNim(m.config.cppCustomNamespace)
|
openNamespaceNim(m.config.cppCustomNamespace, m.s[cfsProcs])
|
||||||
|
|
||||||
proc registerInitProcs*(g: BModuleList; m: PSym; flags: set[ModuleBackendFlag]) =
|
proc registerInitProcs*(g: BModuleList; m: PSym; flags: set[ModuleBackendFlag]) =
|
||||||
## Called from the IC backend.
|
## Called from the IC backend.
|
||||||
|
|
@ -1733,7 +1773,7 @@ proc genInitCode(m: BModule) =
|
||||||
# Give this small function its own scope
|
# Give this small function its own scope
|
||||||
prc.addf("{$N", [])
|
prc.addf("{$N", [])
|
||||||
# Keep a bogus frame in case the code needs one
|
# Keep a bogus frame in case the code needs one
|
||||||
prc.add(~"\tTFrame FR_; FR_.len = 0;$N")
|
prc.add("\tTFrame FR_; FR_.len = 0;\n")
|
||||||
|
|
||||||
writeSection(preInitProc, cpsLocals)
|
writeSection(preInitProc, cpsLocals)
|
||||||
writeSection(preInitProc, cpsInit, m.hcrOn)
|
writeSection(preInitProc, cpsInit, m.hcrOn)
|
||||||
|
|
@ -1759,13 +1799,13 @@ proc genInitCode(m: BModule) =
|
||||||
var procname = makeCString(m.module.name.s)
|
var procname = makeCString(m.module.name.s)
|
||||||
prc.add(initFrame(m.initProc, procname, quotedFilename(m.config, m.module.info)))
|
prc.add(initFrame(m.initProc, procname, quotedFilename(m.config, m.module.info)))
|
||||||
else:
|
else:
|
||||||
prc.add(~"\tTFrame FR_; FR_.len = 0;$N")
|
prc.add("\tTFrame FR_; FR_.len = 0;\n")
|
||||||
|
|
||||||
writeSection(initProc, cpsInit, m.hcrOn)
|
writeSection(initProc, cpsInit, m.hcrOn)
|
||||||
writeSection(initProc, cpsStmts)
|
writeSection(initProc, cpsStmts)
|
||||||
|
|
||||||
if beforeRetNeeded in m.initProc.flags:
|
if beforeRetNeeded in m.initProc.flags:
|
||||||
prc.add(~"\tBeforeRet_: ;$n")
|
prc.add("\tBeforeRet_: ;\n")
|
||||||
|
|
||||||
if sfMainModule in m.module.flags and m.config.exc == excGoto:
|
if sfMainModule in m.module.flags and m.config.exc == excGoto:
|
||||||
if getCompilerProc(m.g.graph, "nimTestErrorFlag") != nil:
|
if getCompilerProc(m.g.graph, "nimTestErrorFlag") != nil:
|
||||||
|
|
@ -1796,7 +1836,7 @@ proc genInitCode(m: BModule) =
|
||||||
m.s[cfsInitProc].addf("}$N$N", [])
|
m.s[cfsInitProc].addf("}$N$N", [])
|
||||||
|
|
||||||
for i, el in pairs(m.extensionLoaders):
|
for i, el in pairs(m.extensionLoaders):
|
||||||
if el != nil:
|
if el != "":
|
||||||
let ex = "NIM_EXTERNC N_NIMCALL(void, nimLoadProcs$1)(void) {$2}$N$N" %
|
let ex = "NIM_EXTERNC N_NIMCALL(void, nimLoadProcs$1)(void) {$2}$N$N" %
|
||||||
[(i.ord - '0'.ord).rope, el]
|
[(i.ord - '0'.ord).rope, el]
|
||||||
moduleInitRequired = true
|
moduleInitRequired = true
|
||||||
|
|
@ -1824,7 +1864,7 @@ proc genModule(m: BModule, cfile: Cfile): Rope =
|
||||||
generateHeaders(m)
|
generateHeaders(m)
|
||||||
result.add(m.s[cfsHeaders])
|
result.add(m.s[cfsHeaders])
|
||||||
if m.config.cppCustomNamespace.len > 0:
|
if m.config.cppCustomNamespace.len > 0:
|
||||||
result.add openNamespaceNim(m.config.cppCustomNamespace)
|
openNamespaceNim(m.config.cppCustomNamespace, result)
|
||||||
if m.s[cfsFrameDefines].len > 0:
|
if m.s[cfsFrameDefines].len > 0:
|
||||||
result.add(m.s[cfsFrameDefines])
|
result.add(m.s[cfsFrameDefines])
|
||||||
else:
|
else:
|
||||||
|
|
@ -1843,10 +1883,10 @@ proc genModule(m: BModule, cfile: Cfile): Rope =
|
||||||
result.add(m.s[cfsDatInitProc])
|
result.add(m.s[cfsDatInitProc])
|
||||||
|
|
||||||
if m.config.cppCustomNamespace.len > 0:
|
if m.config.cppCustomNamespace.len > 0:
|
||||||
result.add closeNamespaceNim()
|
closeNamespaceNim(result)
|
||||||
|
|
||||||
if moduleIsEmpty:
|
if moduleIsEmpty:
|
||||||
result = nil
|
result = ""
|
||||||
|
|
||||||
proc initProcOptions(m: BModule): TOptions =
|
proc initProcOptions(m: BModule): TOptions =
|
||||||
let opts = m.config.options
|
let opts = m.config.options
|
||||||
|
|
@ -1867,6 +1907,7 @@ proc rawNewModule(g: BModuleList; module: PSym, filename: AbsoluteFile): BModule
|
||||||
result.typeInfoMarker = initTable[SigHash, Rope]()
|
result.typeInfoMarker = initTable[SigHash, Rope]()
|
||||||
result.sigConflicts = initCountTable[SigHash]()
|
result.sigConflicts = initCountTable[SigHash]()
|
||||||
result.initProc = newProc(nil, result)
|
result.initProc = newProc(nil, result)
|
||||||
|
for i in low(result.s)..high(result.s): result.s[i] = newRopeAppender()
|
||||||
result.initProc.options = initProcOptions(result)
|
result.initProc.options = initProcOptions(result)
|
||||||
result.preInitProc = newProc(nil, result)
|
result.preInitProc = newProc(nil, result)
|
||||||
result.preInitProc.flags.incl nimErrorFlagDisabled
|
result.preInitProc.flags.incl nimErrorFlagDisabled
|
||||||
|
|
@ -1924,13 +1965,14 @@ proc writeHeader(m: BModule) =
|
||||||
generateThreadLocalStorage(m)
|
generateThreadLocalStorage(m)
|
||||||
for i in cfsHeaders..cfsProcs:
|
for i in cfsHeaders..cfsProcs:
|
||||||
result.add(m.s[i])
|
result.add(m.s[i])
|
||||||
if m.config.cppCustomNamespace.len > 0 and i == cfsHeaders: result.add openNamespaceNim(m.config.cppCustomNamespace)
|
if m.config.cppCustomNamespace.len > 0 and i == cfsHeaders:
|
||||||
|
openNamespaceNim(m.config.cppCustomNamespace, result)
|
||||||
result.add(m.s[cfsInitProc])
|
result.add(m.s[cfsInitProc])
|
||||||
|
|
||||||
if optGenDynLib in m.config.globalOptions:
|
if optGenDynLib in m.config.globalOptions:
|
||||||
result.add("N_LIB_IMPORT ")
|
result.add("N_LIB_IMPORT ")
|
||||||
result.addf("N_CDECL(void, $1NimMain)(void);$n", [rope m.config.nimMainPrefix])
|
result.addf("N_CDECL(void, $1NimMain)(void);$n", [rope m.config.nimMainPrefix])
|
||||||
if m.config.cppCustomNamespace.len > 0: result.add closeNamespaceNim()
|
if m.config.cppCustomNamespace.len > 0: closeNamespaceNim(result)
|
||||||
result.addf("#endif /* $1 */$n", [guard])
|
result.addf("#endif /* $1 */$n", [guard])
|
||||||
if not writeRope(result, m.filename):
|
if not writeRope(result, m.filename):
|
||||||
rawMessage(m.config, errCannotOpenFile, m.filename.string)
|
rawMessage(m.config, errCannotOpenFile, m.filename.string)
|
||||||
|
|
@ -2034,7 +2076,7 @@ proc writeModule(m: BModule, pending: bool) =
|
||||||
var cf = Cfile(nimname: m.module.name.s, cname: cfile,
|
var cf = Cfile(nimname: m.module.name.s, cname: cfile,
|
||||||
obj: completeCfilePath(m.config, toObjFile(m.config, cfile)), flags: {})
|
obj: completeCfilePath(m.config, toObjFile(m.config, cfile)), flags: {})
|
||||||
var code = genModule(m, cf)
|
var code = genModule(m, cf)
|
||||||
if code != nil or m.config.symbolFiles != disabledSf:
|
if code != "" or m.config.symbolFiles != disabledSf:
|
||||||
when hasTinyCBackend:
|
when hasTinyCBackend:
|
||||||
if m.config.cmd == cmdTcc:
|
if m.config.cmd == cmdTcc:
|
||||||
tccgen.compileCCode($code, m.config)
|
tccgen.compileCCode($code, m.config)
|
||||||
|
|
@ -2060,7 +2102,7 @@ proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode) =
|
||||||
# phase ordering problem here: We need to announce this
|
# phase ordering problem here: We need to announce this
|
||||||
# dependency to 'nimTestErrorFlag' before system.c has been written to disk.
|
# dependency to 'nimTestErrorFlag' before system.c has been written to disk.
|
||||||
if m.config.exc == excGoto and getCompilerProc(graph, "nimTestErrorFlag") != nil:
|
if m.config.exc == excGoto and getCompilerProc(graph, "nimTestErrorFlag") != nil:
|
||||||
discard cgsym(m, "nimTestErrorFlag")
|
cgsym(m, "nimTestErrorFlag")
|
||||||
|
|
||||||
if {optGenStaticLib, optGenDynLib, optNoMain} * m.config.globalOptions == {}:
|
if {optGenStaticLib, optGenDynLib, optNoMain} * m.config.globalOptions == {}:
|
||||||
for i in countdown(high(graph.globalDestructors), 0):
|
for i in countdown(high(graph.globalDestructors), 0):
|
||||||
|
|
@ -2076,7 +2118,7 @@ proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode) =
|
||||||
|
|
||||||
if m.hcrOn:
|
if m.hcrOn:
|
||||||
# make sure this is pulled in (meaning hcrGetGlobal() is called for it during init)
|
# make sure this is pulled in (meaning hcrGetGlobal() is called for it during init)
|
||||||
discard cgsym(m, "programResult")
|
cgsym(m, "programResult")
|
||||||
if m.inHcrInitGuard:
|
if m.inHcrInitGuard:
|
||||||
endBlock(m.initProc)
|
endBlock(m.initProc)
|
||||||
|
|
||||||
|
|
@ -2086,17 +2128,17 @@ proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode) =
|
||||||
# so it can load the HCR runtime and later pass the library handle to the HCR runtime which
|
# so it can load the HCR runtime and later pass the library handle to the HCR runtime which
|
||||||
# will in turn pass it to the other modules it initializes so they can initialize the
|
# will in turn pass it to the other modules it initializes so they can initialize the
|
||||||
# register/get procs so they don't have to have the definitions of these functions as well
|
# register/get procs so they don't have to have the definitions of these functions as well
|
||||||
discard cgsym(m, "nimLoadLibrary")
|
cgsym(m, "nimLoadLibrary")
|
||||||
discard cgsym(m, "nimLoadLibraryError")
|
cgsym(m, "nimLoadLibraryError")
|
||||||
discard cgsym(m, "nimGetProcAddr")
|
cgsym(m, "nimGetProcAddr")
|
||||||
discard cgsym(m, "procAddrError")
|
cgsym(m, "procAddrError")
|
||||||
discard cgsym(m, "rawWrite")
|
cgsym(m, "rawWrite")
|
||||||
|
|
||||||
# raise dependencies on behalf of genMainProc
|
# raise dependencies on behalf of genMainProc
|
||||||
if m.config.target.targetOS != osStandalone and m.config.selectedGC notin {gcNone, gcArc, gcOrc}:
|
if m.config.target.targetOS != osStandalone and m.config.selectedGC notin {gcNone, gcArc, gcOrc}:
|
||||||
discard cgsym(m, "initStackBottomWith")
|
cgsym(m, "initStackBottomWith")
|
||||||
if emulatedThreadVars(m.config) and m.config.target.targetOS != osStandalone:
|
if emulatedThreadVars(m.config) and m.config.target.targetOS != osStandalone:
|
||||||
discard cgsym(m, "initThreadVarsEmulation")
|
cgsym(m, "initThreadVarsEmulation")
|
||||||
|
|
||||||
if m.g.forwardedProcs.len == 0:
|
if m.g.forwardedProcs.len == 0:
|
||||||
incl m.flags, objHasKidsValid
|
incl m.flags, objHasKidsValid
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ type
|
||||||
cfsFieldInfo, # section for field information
|
cfsFieldInfo, # section for field information
|
||||||
cfsTypeInfo, # section for type information (ag ABI checks)
|
cfsTypeInfo, # section for type information (ag ABI checks)
|
||||||
cfsProcHeaders, # section for C procs prototypes
|
cfsProcHeaders, # section for C procs prototypes
|
||||||
|
cfsStrData, # section for constant string literals
|
||||||
cfsData, # section for C constant data
|
cfsData, # section for C constant data
|
||||||
cfsVars, # section for C variable declarations
|
cfsVars, # section for C variable declarations
|
||||||
cfsProcs, # section for C procs that are not inline
|
cfsProcs, # section for C procs that are not inline
|
||||||
|
|
@ -190,13 +191,18 @@ proc procSec*(p: BProc, s: TCProcSection): var Rope {.inline.} =
|
||||||
# top level proc sections
|
# top level proc sections
|
||||||
result = p.blocks[0].sections[s]
|
result = p.blocks[0].sections[s]
|
||||||
|
|
||||||
|
proc initBlock*(): TBlock =
|
||||||
|
result = TBlock()
|
||||||
|
for i in low(result.sections)..high(result.sections):
|
||||||
|
result.sections[i] = newRopeAppender()
|
||||||
|
|
||||||
proc newProc*(prc: PSym, module: BModule): BProc =
|
proc newProc*(prc: PSym, module: BModule): BProc =
|
||||||
new(result)
|
new(result)
|
||||||
result.prc = prc
|
result.prc = prc
|
||||||
result.module = module
|
result.module = module
|
||||||
result.options = if prc != nil: prc.options
|
result.options = if prc != nil: prc.options
|
||||||
else: module.config.options
|
else: module.config.options
|
||||||
newSeq(result.blocks, 1)
|
result.blocks = @[initBlock()]
|
||||||
result.nestedTryStmts = @[]
|
result.nestedTryStmts = @[]
|
||||||
result.finallySafePoints = @[]
|
result.finallySafePoints = @[]
|
||||||
result.sigConflicts = initCountTable[string]()
|
result.sigConflicts = initCountTable[string]()
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ proc createDispatcher(s: PSym; g: ModuleGraph; idgen: IdGenerator): PSym =
|
||||||
if disp.typ.callConv == ccInline: disp.typ.callConv = ccNimCall
|
if disp.typ.callConv == ccInline: disp.typ.callConv = ccNimCall
|
||||||
disp.ast = copyTree(s.ast)
|
disp.ast = copyTree(s.ast)
|
||||||
disp.ast[bodyPos] = newNodeI(nkEmpty, s.info)
|
disp.ast[bodyPos] = newNodeI(nkEmpty, s.info)
|
||||||
disp.loc.r = nil
|
disp.loc.r = ""
|
||||||
if s.typ[0] != nil:
|
if s.typ[0] != nil:
|
||||||
if disp.ast.len > resultPos:
|
if disp.ast.len > resultPos:
|
||||||
disp.ast[resultPos].sym = copySym(s.ast[resultPos].sym, nextSymId(idgen))
|
disp.ast[resultPos].sym = copySym(s.ast[resultPos].sym, nextSymId(idgen))
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,8 @@ import options, ast, ropes, passes, pathutils, msgs, lineinfos
|
||||||
|
|
||||||
import modulegraphs
|
import modulegraphs
|
||||||
|
|
||||||
import std/[os, strutils, parseutils]
|
import std/[os, parseutils]
|
||||||
|
import strutils except addf
|
||||||
import std/private/globs
|
import std/private/globs
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
|
|
@ -109,7 +110,7 @@ proc myOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext
|
||||||
g.config = graph.config
|
g.config = graph.config
|
||||||
g.graph = graph
|
g.graph = graph
|
||||||
if graph.backend == nil:
|
if graph.backend == nil:
|
||||||
graph.backend = Backend(dotGraph: nil)
|
graph.backend = Backend(dotGraph: "")
|
||||||
result = g
|
result = g
|
||||||
|
|
||||||
const gendependPass* = makePass(open = myOpen, process = addDotDependency)
|
const gendependPass* = makePass(open = myOpen, process = addDotDependency)
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,9 @@
|
||||||
|
|
||||||
import ropes, platform, condsyms, options, msgs, lineinfos, pathutils, modulepaths
|
import ropes, platform, condsyms, options, msgs, lineinfos, pathutils, modulepaths
|
||||||
|
|
||||||
import std/[os, strutils, osproc, sha1, streams, sequtils, times, strtabs, json, jsonutils, sugar, parseutils]
|
import std/[os, osproc, sha1, streams, sequtils, times, strtabs, json, jsonutils, sugar, parseutils]
|
||||||
|
|
||||||
|
import std / strutils except addf
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
import std/syncio
|
import std/syncio
|
||||||
|
|
@ -616,7 +618,7 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile,
|
||||||
"for the selected C compiler: " & CC[conf.cCompiler].name)
|
"for the selected C compiler: " & CC[conf.cCompiler].name)
|
||||||
|
|
||||||
result.add(' ')
|
result.add(' ')
|
||||||
result.addf(CC[c].compileTmpl, [
|
strutils.addf(result, CC[c].compileTmpl, [
|
||||||
"dfile", dfile,
|
"dfile", dfile,
|
||||||
"file", cfsh, "objfile", quoteShell(objfile),
|
"file", cfsh, "objfile", quoteShell(objfile),
|
||||||
"options", options, "include", includeCmd,
|
"options", options, "include", includeCmd,
|
||||||
|
|
@ -707,7 +709,7 @@ proc getLinkCmd(conf: ConfigRef; output: AbsoluteFile,
|
||||||
"buildgui", buildgui, "options", linkOptions, "objfiles", objfiles,
|
"buildgui", buildgui, "options", linkOptions, "objfiles", objfiles,
|
||||||
"exefile", exefile, "nim", getPrefixDir(conf).string, "lib", conf.libpath.string])
|
"exefile", exefile, "nim", getPrefixDir(conf).string, "lib", conf.libpath.string])
|
||||||
result.add ' '
|
result.add ' '
|
||||||
result.addf(linkTmpl, ["builddll", builddll,
|
strutils.addf(result, linkTmpl, ["builddll", builddll,
|
||||||
"mapfile", mapfile,
|
"mapfile", mapfile,
|
||||||
"buildgui", buildgui, "options", linkOptions,
|
"buildgui", buildgui, "options", linkOptions,
|
||||||
"objfiles", objfiles, "exefile", exefile,
|
"objfiles", objfiles, "exefile", exefile,
|
||||||
|
|
@ -856,7 +858,7 @@ proc callCCompiler*(conf: ConfigRef) =
|
||||||
return # speed up that call if only compiling and no script shall be
|
return # speed up that call if only compiling and no script shall be
|
||||||
# generated
|
# generated
|
||||||
#var c = cCompiler
|
#var c = cCompiler
|
||||||
var script: Rope = nil
|
var script: Rope = ""
|
||||||
var cmds: TStringSeq
|
var cmds: TStringSeq
|
||||||
var prettyCmds: TStringSeq
|
var prettyCmds: TStringSeq
|
||||||
let prettyCb = proc (idx: int) = writePrettyCmdsStderr(prettyCmds[idx])
|
let prettyCb = proc (idx: int) = writePrettyCmdsStderr(prettyCmds[idx])
|
||||||
|
|
|
||||||
|
|
@ -403,7 +403,7 @@ proc storeSym*(s: PSym; c: var PackedEncoder; m: var PackedModule): PackedItemId
|
||||||
p.bitsize = s.bitsize
|
p.bitsize = s.bitsize
|
||||||
p.alignment = s.alignment
|
p.alignment = s.alignment
|
||||||
|
|
||||||
p.externalName = toLitId(if s.loc.r.isNil: "" else: $s.loc.r, m)
|
p.externalName = toLitId(s.loc.r, m)
|
||||||
p.locFlags = s.loc.flags
|
p.locFlags = s.loc.flags
|
||||||
c.addMissing s.typ
|
c.addMissing s.typ
|
||||||
p.typ = s.typ.storeType(c, m)
|
p.typ = s.typ.storeType(c, m)
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,8 @@ import
|
||||||
cgmeth, lowerings, sighashes, modulegraphs, lineinfos, rodutils,
|
cgmeth, lowerings, sighashes, modulegraphs, lineinfos, rodutils,
|
||||||
transf, injectdestructors, sourcemap, astmsgs
|
transf, injectdestructors, sourcemap, astmsgs
|
||||||
|
|
||||||
import json, sets, math, tables, intsets, strutils
|
import json, sets, math, tables, intsets
|
||||||
|
import strutils except addf
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
import std/[assertions, syncio]
|
import std/[assertions, syncio]
|
||||||
|
|
@ -110,21 +111,18 @@ type
|
||||||
template config*(p: PProc): ConfigRef = p.module.config
|
template config*(p: PProc): ConfigRef = p.module.config
|
||||||
|
|
||||||
proc indentLine(p: PProc, r: Rope): Rope =
|
proc indentLine(p: PProc, r: Rope): Rope =
|
||||||
result = r
|
|
||||||
var p = p
|
var p = p
|
||||||
|
var ind = 0
|
||||||
while true:
|
while true:
|
||||||
for i in 0..<p.blocks.len + p.extraIndent:
|
inc ind, p.blocks.len + p.extraIndent
|
||||||
prepend(result, rope" ")
|
|
||||||
if p.up == nil or p.up.prc != p.prc.owner:
|
if p.up == nil or p.up.prc != p.prc.owner:
|
||||||
break
|
break
|
||||||
p = p.up
|
p = p.up
|
||||||
|
result = repeat(' ', ind*2) & r
|
||||||
|
|
||||||
template line(p: PProc, added: string) =
|
template line(p: PProc, added: string) =
|
||||||
p.body.add(indentLine(p, rope(added)))
|
p.body.add(indentLine(p, rope(added)))
|
||||||
|
|
||||||
template line(p: PProc, added: Rope) =
|
|
||||||
p.body.add(indentLine(p, added))
|
|
||||||
|
|
||||||
template lineF(p: PProc, frmt: FormatStr, args: varargs[Rope]) =
|
template lineF(p: PProc, frmt: FormatStr, args: varargs[Rope]) =
|
||||||
p.body.add(indentLine(p, ropes.`%`(frmt, args)))
|
p.body.add(indentLine(p, ropes.`%`(frmt, args)))
|
||||||
|
|
||||||
|
|
@ -140,9 +138,9 @@ proc newGlobals(): PGlobals =
|
||||||
result.typeInfoGenerated = initIntSet()
|
result.typeInfoGenerated = initIntSet()
|
||||||
|
|
||||||
proc initCompRes(r: var TCompRes) =
|
proc initCompRes(r: var TCompRes) =
|
||||||
r.address = nil
|
r.address = ""
|
||||||
r.res = nil
|
r.res = ""
|
||||||
r.tmpLoc = nil
|
r.tmpLoc = ""
|
||||||
r.typ = etyNone
|
r.typ = etyNone
|
||||||
r.kind = resNone
|
r.kind = resNone
|
||||||
|
|
||||||
|
|
@ -241,7 +239,7 @@ proc mangleName(m: BModule, s: PSym): Rope =
|
||||||
if chr notin {'A'..'Z','a'..'z','_','$','0'..'9'}:
|
if chr notin {'A'..'Z','a'..'z','_','$','0'..'9'}:
|
||||||
return false
|
return false
|
||||||
result = s.loc.r
|
result = s.loc.r
|
||||||
if result == nil:
|
if result == "":
|
||||||
if s.kind == skField and s.name.s.validJsName:
|
if s.kind == skField and s.name.s.validJsName:
|
||||||
result = rope(s.name.s)
|
result = rope(s.name.s)
|
||||||
elif s.kind == skTemp:
|
elif s.kind == skTemp:
|
||||||
|
|
@ -464,7 +462,7 @@ proc maybeMakeTemp(p: PProc, n: PNode; x: TCompRes): tuple[a, tmp: Rope] =
|
||||||
b = a
|
b = a
|
||||||
if needsTemp(p, n):
|
if needsTemp(p, n):
|
||||||
# if we have tmp just use it
|
# if we have tmp just use it
|
||||||
if x.tmpLoc != nil and (mapType(n.typ) == etyBaseIndex or n.kind in {nkHiddenDeref, nkDerefExpr}):
|
if x.tmpLoc != "" and (mapType(n.typ) == etyBaseIndex or n.kind in {nkHiddenDeref, nkDerefExpr}):
|
||||||
b = "$1[0][$1[1]]" % [x.tmpLoc]
|
b = "$1[0][$1[1]]" % [x.tmpLoc]
|
||||||
(a: a, tmp: b)
|
(a: a, tmp: b)
|
||||||
else:
|
else:
|
||||||
|
|
@ -481,10 +479,10 @@ proc maybeMakeTempAssignable(p: PProc, n: PNode; x: TCompRes): tuple[a, tmp: Rop
|
||||||
b = a
|
b = a
|
||||||
if needsTemp(p, n):
|
if needsTemp(p, n):
|
||||||
# if we have tmp just use it
|
# if we have tmp just use it
|
||||||
if x.tmpLoc != nil and (mapType(n.typ) == etyBaseIndex or n.kind in {nkHiddenDeref, nkDerefExpr}):
|
if x.tmpLoc != "" and (mapType(n.typ) == etyBaseIndex or n.kind in {nkHiddenDeref, nkDerefExpr}):
|
||||||
b = "$1[0][$1[1]]" % [x.tmpLoc]
|
b = "$1[0][$1[1]]" % [x.tmpLoc]
|
||||||
result = (a: a, tmp: b)
|
result = (a: a, tmp: b)
|
||||||
elif x.tmpLoc != nil and n.kind == nkBracketExpr:
|
elif x.tmpLoc != "" and n.kind == nkBracketExpr:
|
||||||
# genArrayAddr
|
# genArrayAddr
|
||||||
var
|
var
|
||||||
address, index: TCompRes
|
address, index: TCompRes
|
||||||
|
|
@ -745,7 +743,7 @@ proc moveInto(p: PProc, src: var TCompRes, dest: TCompRes) =
|
||||||
else:
|
else:
|
||||||
lineF(p, "$1;$n", [src.rdLoc])
|
lineF(p, "$1;$n", [src.rdLoc])
|
||||||
src.kind = resNone
|
src.kind = resNone
|
||||||
src.res = nil
|
src.res = ""
|
||||||
|
|
||||||
proc genTry(p: PProc, n: PNode, r: var TCompRes) =
|
proc genTry(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
# code to generate:
|
# code to generate:
|
||||||
|
|
@ -800,7 +798,7 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
moveInto(p, a, r)
|
moveInto(p, a, r)
|
||||||
if i > 1: lineF(p, "}$n", [])
|
if i > 1: lineF(p, "}$n", [])
|
||||||
else:
|
else:
|
||||||
var orExpr: Rope = nil
|
var orExpr: Rope = ""
|
||||||
var excAlias: PNode = nil
|
var excAlias: PNode = nil
|
||||||
|
|
||||||
useMagic(p, "isObj")
|
useMagic(p, "isObj")
|
||||||
|
|
@ -813,13 +811,13 @@ proc genTry(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
excAlias = it[2]
|
excAlias = it[2]
|
||||||
# If this is a ``except exc as sym`` branch there must be no following
|
# If this is a ``except exc as sym`` branch there must be no following
|
||||||
# nodes
|
# nodes
|
||||||
doAssert orExpr == nil
|
doAssert orExpr == ""
|
||||||
elif it.kind == nkType:
|
elif it.kind == nkType:
|
||||||
throwObj = it
|
throwObj = it
|
||||||
else:
|
else:
|
||||||
internalError(p.config, n.info, "genTryStmt")
|
internalError(p.config, n.info, "genTryStmt")
|
||||||
|
|
||||||
if orExpr != nil: orExpr.add("||")
|
if orExpr != "": orExpr.add("||")
|
||||||
# Generate the correct type checking code depending on whether this is a
|
# Generate the correct type checking code depending on whether this is a
|
||||||
# NIM-native or a JS-native exception
|
# NIM-native or a JS-native exception
|
||||||
# if isJsObject(throwObj.typ):
|
# if isJsObject(throwObj.typ):
|
||||||
|
|
@ -907,7 +905,7 @@ proc genCaseJS(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
gen(p, e[1], b)
|
gen(p, e[1], b)
|
||||||
if j != itLen - 2:
|
if j != itLen - 2:
|
||||||
lineF(p, "$1 >= $2 && $1 <= $3 || $n", [cond.rdLoc, a.rdLoc, b.rdLoc])
|
lineF(p, "$1 >= $2 && $1 <= $3 || $n", [cond.rdLoc, a.rdLoc, b.rdLoc])
|
||||||
else:
|
else:
|
||||||
lineF(p, "$1 >= $2 && $1 <= $3", [cond.rdLoc, a.rdLoc, b.rdLoc])
|
lineF(p, "$1 >= $2 && $1 <= $3", [cond.rdLoc, a.rdLoc, b.rdLoc])
|
||||||
else:
|
else:
|
||||||
var v = copyNode(e[0])
|
var v = copyNode(e[0])
|
||||||
|
|
@ -998,7 +996,7 @@ proc genBreakStmt(p: PProc, n: PNode) =
|
||||||
|
|
||||||
proc genAsmOrEmitStmt(p: PProc, n: PNode) =
|
proc genAsmOrEmitStmt(p: PProc, n: PNode) =
|
||||||
genLineDir(p, n)
|
genLineDir(p, n)
|
||||||
p.body.add p.indentLine(nil)
|
p.body.add p.indentLine("")
|
||||||
for i in 0..<n.len:
|
for i in 0..<n.len:
|
||||||
let it = n[i]
|
let it = n[i]
|
||||||
case it.kind
|
case it.kind
|
||||||
|
|
@ -1016,12 +1014,12 @@ proc genAsmOrEmitStmt(p: PProc, n: PNode) =
|
||||||
if it.typ.kind == tyPointer:
|
if it.typ.kind == tyPointer:
|
||||||
# A fat pointer is disguised as an array
|
# A fat pointer is disguised as an array
|
||||||
r.res = r.address
|
r.res = r.address
|
||||||
r.address = nil
|
r.address = ""
|
||||||
r.typ = etyNone
|
r.typ = etyNone
|
||||||
elif r.typ == etyBaseIndex:
|
elif r.typ == etyBaseIndex:
|
||||||
# Deference first
|
# Deference first
|
||||||
r.res = "$1[$2]" % [r.address, r.res]
|
r.res = "$1[$2]" % [r.address, r.res]
|
||||||
r.address = nil
|
r.address = ""
|
||||||
r.typ = etyNone
|
r.typ = etyNone
|
||||||
|
|
||||||
p.body.add(r.rdLoc)
|
p.body.add(r.rdLoc)
|
||||||
|
|
@ -1055,12 +1053,12 @@ proc genIf(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
line(p, repeat('}', toClose) & "\L")
|
line(p, repeat('}', toClose) & "\L")
|
||||||
|
|
||||||
proc generateHeader(p: PProc, typ: PType): Rope =
|
proc generateHeader(p: PProc, typ: PType): Rope =
|
||||||
result = nil
|
result = ""
|
||||||
for i in 1..<typ.n.len:
|
for i in 1..<typ.n.len:
|
||||||
assert(typ.n[i].kind == nkSym)
|
assert(typ.n[i].kind == nkSym)
|
||||||
var param = typ.n[i].sym
|
var param = typ.n[i].sym
|
||||||
if isCompileTimeOnly(param.typ): continue
|
if isCompileTimeOnly(param.typ): continue
|
||||||
if result != nil: result.add(", ")
|
if result != "": result.add(", ")
|
||||||
var name = mangleName(p.module, param)
|
var name = mangleName(p.module, param)
|
||||||
result.add(name)
|
result.add(name)
|
||||||
if mapType(param.typ) == etyBaseIndex:
|
if mapType(param.typ) == etyBaseIndex:
|
||||||
|
|
@ -1135,7 +1133,7 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
|
||||||
elif b.typ == etyBaseIndex:
|
elif b.typ == etyBaseIndex:
|
||||||
lineF(p, "$# = [$#, $#];$n", [a.res, b.address, b.res])
|
lineF(p, "$# = [$#, $#];$n", [a.res, b.address, b.res])
|
||||||
elif b.typ == etyNone:
|
elif b.typ == etyNone:
|
||||||
internalAssert p.config, b.address == nil
|
internalAssert p.config, b.address == ""
|
||||||
lineF(p, "$# = [$#, 0];$n", [a.address, b.res])
|
lineF(p, "$# = [$#, 0];$n", [a.address, b.res])
|
||||||
elif x.typ.kind == tyVar and y.typ.kind == tyPtr:
|
elif x.typ.kind == tyVar and y.typ.kind == tyPtr:
|
||||||
lineF(p, "$# = [$#, $#];$n", [a.res, b.address, b.res])
|
lineF(p, "$# = [$#, $#];$n", [a.res, b.address, b.res])
|
||||||
|
|
@ -1143,13 +1141,13 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
|
||||||
lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
|
lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
|
||||||
elif a.typ == etyBaseIndex:
|
elif a.typ == etyBaseIndex:
|
||||||
# array indexing may not map to var type
|
# array indexing may not map to var type
|
||||||
if b.address != nil:
|
if b.address != "":
|
||||||
lineF(p, "$1 = $2; $3 = $4;$n", [a.address, b.address, a.res, b.res])
|
lineF(p, "$1 = $2; $3 = $4;$n", [a.address, b.address, a.res, b.res])
|
||||||
else:
|
else:
|
||||||
lineF(p, "$1 = $2;$n", [a.address, b.res])
|
lineF(p, "$1 = $2;$n", [a.address, b.res])
|
||||||
else:
|
else:
|
||||||
internalError(p.config, x.info, $("genAsgn", b.typ, a.typ))
|
internalError(p.config, x.info, $("genAsgn", b.typ, a.typ))
|
||||||
elif b.address != nil:
|
elif b.address != "":
|
||||||
lineF(p, "$1 = $2; $3 = $4;$n", [a.address, b.address, a.res, b.res])
|
lineF(p, "$1 = $2; $3 = $4;$n", [a.address, b.address, a.res, b.res])
|
||||||
else:
|
else:
|
||||||
lineF(p, "$1 = $2;$n", [a.address, b.res])
|
lineF(p, "$1 = $2;$n", [a.address, b.res])
|
||||||
|
|
@ -1201,7 +1199,7 @@ proc genFieldAddr(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
else:
|
else:
|
||||||
if b[1].kind != nkSym: internalError(p.config, b[1].info, "genFieldAddr")
|
if b[1].kind != nkSym: internalError(p.config, b[1].info, "genFieldAddr")
|
||||||
var f = b[1].sym
|
var f = b[1].sym
|
||||||
if f.loc.r == nil: f.loc.r = mangleName(p.module, f)
|
if f.loc.r == "": f.loc.r = mangleName(p.module, f)
|
||||||
r.res = makeJSString($f.loc.r)
|
r.res = makeJSString($f.loc.r)
|
||||||
internalAssert p.config, a.typ != etyBaseIndex
|
internalAssert p.config, a.typ != etyBaseIndex
|
||||||
r.address = a.res
|
r.address = a.res
|
||||||
|
|
@ -1229,7 +1227,7 @@ proc genFieldAccess(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
else:
|
else:
|
||||||
if n[1].kind != nkSym: internalError(p.config, n[1].info, "genFieldAccess")
|
if n[1].kind != nkSym: internalError(p.config, n[1].info, "genFieldAccess")
|
||||||
var f = n[1].sym
|
var f = n[1].sym
|
||||||
if f.loc.r == nil: f.loc.r = mangleName(p.module, f)
|
if f.loc.r == "": f.loc.r = mangleName(p.module, f)
|
||||||
r.res = "$1.$2" % [r.res, f.loc.r]
|
r.res = "$1.$2" % [r.res, f.loc.r]
|
||||||
mkTemp(1)
|
mkTemp(1)
|
||||||
r.kind = resExpr
|
r.kind = resExpr
|
||||||
|
|
@ -1250,11 +1248,11 @@ proc genCheckedFieldOp(p: PProc, n: PNode, addrTyp: PType, r: var TCompRes) =
|
||||||
# Field symbol
|
# Field symbol
|
||||||
var field = accessExpr[1].sym
|
var field = accessExpr[1].sym
|
||||||
internalAssert p.config, field.kind == skField
|
internalAssert p.config, field.kind == skField
|
||||||
if field.loc.r == nil: field.loc.r = mangleName(p.module, field)
|
if field.loc.r == "": field.loc.r = mangleName(p.module, field)
|
||||||
# Discriminant symbol
|
# Discriminant symbol
|
||||||
let disc = checkExpr[2].sym
|
let disc = checkExpr[2].sym
|
||||||
internalAssert p.config, disc.kind == skField
|
internalAssert p.config, disc.kind == skField
|
||||||
if disc.loc.r == nil: disc.loc.r = mangleName(p.module, disc)
|
if disc.loc.r == "": disc.loc.r = mangleName(p.module, disc)
|
||||||
|
|
||||||
var setx: TCompRes
|
var setx: TCompRes
|
||||||
gen(p, checkExpr[1], setx)
|
gen(p, checkExpr[1], setx)
|
||||||
|
|
@ -1271,7 +1269,7 @@ proc genCheckedFieldOp(p: PProc, n: PNode, addrTyp: PType, r: var TCompRes) =
|
||||||
useMagic(p, "reprDiscriminant") # no need to offset by firstOrd unlike for cgen
|
useMagic(p, "reprDiscriminant") # no need to offset by firstOrd unlike for cgen
|
||||||
let msg = genFieldDefect(p.config, field.name.s, disc)
|
let msg = genFieldDefect(p.config, field.name.s, disc)
|
||||||
lineF(p, "if ($1[$2.$3]$4undefined) { raiseFieldError2(makeNimstrLit($5), reprDiscriminant($2.$3, $6)); }$n",
|
lineF(p, "if ($1[$2.$3]$4undefined) { raiseFieldError2(makeNimstrLit($5), reprDiscriminant($2.$3, $6)); }$n",
|
||||||
setx.res, tmp, disc.loc.r, if negCheck: ~"!==" else: ~"===",
|
setx.res, tmp, disc.loc.r, if negCheck: "!==" else: "===",
|
||||||
makeJSString(msg), genTypeInfo(p, disc.typ))
|
makeJSString(msg), genTypeInfo(p, disc.typ))
|
||||||
|
|
||||||
if addrTyp != nil and mapType(p, addrTyp) == etyBaseIndex:
|
if addrTyp != nil and mapType(p, addrTyp) == etyBaseIndex:
|
||||||
|
|
@ -1320,7 +1318,7 @@ proc genArrayAccess(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
genFieldAddr(p, n, r)
|
genFieldAddr(p, n, r)
|
||||||
else: internalError(p.config, n.info, "expr(nkBracketExpr, " & $ty.kind & ')')
|
else: internalError(p.config, n.info, "expr(nkBracketExpr, " & $ty.kind & ')')
|
||||||
r.typ = mapType(n.typ)
|
r.typ = mapType(n.typ)
|
||||||
if r.res == nil: internalError(p.config, n.info, "genArrayAccess")
|
if r.res == "": internalError(p.config, n.info, "genArrayAccess")
|
||||||
if ty.kind == tyCstring:
|
if ty.kind == tyCstring:
|
||||||
r.res = "$1.charCodeAt($2)" % [r.address, r.res]
|
r.res = "$1.charCodeAt($2)" % [r.address, r.res]
|
||||||
elif r.typ == etyBaseIndex:
|
elif r.typ == etyBaseIndex:
|
||||||
|
|
@ -1347,11 +1345,11 @@ template isIndirect(x: PSym): bool =
|
||||||
|
|
||||||
proc genSymAddr(p: PProc, n: PNode, typ: PType, r: var TCompRes) =
|
proc genSymAddr(p: PProc, n: PNode, typ: PType, r: var TCompRes) =
|
||||||
let s = n.sym
|
let s = n.sym
|
||||||
if s.loc.r == nil: internalError(p.config, n.info, "genAddr: 3")
|
if s.loc.r == "": internalError(p.config, n.info, "genAddr: 3")
|
||||||
case s.kind
|
case s.kind
|
||||||
of skParam:
|
of skParam:
|
||||||
r.res = s.loc.r
|
r.res = s.loc.r
|
||||||
r.address = nil
|
r.address = ""
|
||||||
r.typ = etyNone
|
r.typ = etyNone
|
||||||
of skVar, skLet, skResult:
|
of skVar, skLet, skResult:
|
||||||
r.kind = resExpr
|
r.kind = resExpr
|
||||||
|
|
@ -1367,7 +1365,7 @@ proc genSymAddr(p: PProc, n: PNode, typ: PType, r: var TCompRes) =
|
||||||
r.res = s.loc.r & "[0]"
|
r.res = s.loc.r & "[0]"
|
||||||
else:
|
else:
|
||||||
r.res = s.loc.r
|
r.res = s.loc.r
|
||||||
r.address = nil
|
r.address = ""
|
||||||
elif {sfGlobal, sfAddrTaken} * s.flags != {} or jsType == etyBaseIndex:
|
elif {sfGlobal, sfAddrTaken} * s.flags != {} or jsType == etyBaseIndex:
|
||||||
# for ease of code generation, we do not distinguish between
|
# for ease of code generation, we do not distinguish between
|
||||||
# sfAddrTaken and sfGlobal.
|
# sfAddrTaken and sfGlobal.
|
||||||
|
|
@ -1466,7 +1464,7 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
var s = n.sym
|
var s = n.sym
|
||||||
case s.kind
|
case s.kind
|
||||||
of skVar, skLet, skParam, skTemp, skResult, skForVar:
|
of skVar, skLet, skParam, skTemp, skResult, skForVar:
|
||||||
if s.loc.r == nil:
|
if s.loc.r == "":
|
||||||
internalError(p.config, n.info, "symbol has no generated name: " & s.name.s)
|
internalError(p.config, n.info, "symbol has no generated name: " & s.name.s)
|
||||||
if sfCompileTime in s.flags:
|
if sfCompileTime in s.flags:
|
||||||
genVarInit(p, s, if s.ast != nil: s.ast else: newNodeI(nkEmpty, s.info))
|
genVarInit(p, s, if s.ast != nil: s.ast else: newNodeI(nkEmpty, s.info))
|
||||||
|
|
@ -1491,7 +1489,7 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
r.res = s.loc.r
|
r.res = s.loc.r
|
||||||
of skConst:
|
of skConst:
|
||||||
genConstant(p, s)
|
genConstant(p, s)
|
||||||
if s.loc.r == nil:
|
if s.loc.r == "":
|
||||||
internalError(p.config, n.info, "symbol has no generated name: " & s.name.s)
|
internalError(p.config, n.info, "symbol has no generated name: " & s.name.s)
|
||||||
r.res = s.loc.r
|
r.res = s.loc.r
|
||||||
of skProc, skFunc, skConverter, skMethod:
|
of skProc, skFunc, skConverter, skMethod:
|
||||||
|
|
@ -1511,7 +1509,7 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
else:
|
else:
|
||||||
genProcForSymIfNeeded(p, s)
|
genProcForSymIfNeeded(p, s)
|
||||||
else:
|
else:
|
||||||
if s.loc.r == nil:
|
if s.loc.r == "":
|
||||||
internalError(p.config, n.info, "symbol has no generated name: " & s.name.s)
|
internalError(p.config, n.info, "symbol has no generated name: " & s.name.s)
|
||||||
if mapType(p, s.typ) == etyBaseIndex:
|
if mapType(p, s.typ) == etyBaseIndex:
|
||||||
r.address = s.loc.r
|
r.address = s.loc.r
|
||||||
|
|
@ -1536,7 +1534,7 @@ proc genDeref(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
r.res = "$1[1]" % [tmp]
|
r.res = "$1[1]" % [tmp]
|
||||||
r.tmpLoc = tmp
|
r.tmpLoc = tmp
|
||||||
elif a.typ == etyBaseIndex:
|
elif a.typ == etyBaseIndex:
|
||||||
if a.tmpLoc != nil:
|
if a.tmpLoc != "":
|
||||||
r.tmpLoc = a.tmpLoc
|
r.tmpLoc = a.tmpLoc
|
||||||
r.res = a.rdLoc
|
r.res = a.rdLoc
|
||||||
else:
|
else:
|
||||||
|
|
@ -1659,9 +1657,9 @@ proc genPatternCall(p: PProc; n: PNode; pat: string; typ: PType;
|
||||||
proc genInfixCall(p: PProc, n: PNode, r: var TCompRes) =
|
proc genInfixCall(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
# don't call '$' here for efficiency:
|
# don't call '$' here for efficiency:
|
||||||
let f = n[0].sym
|
let f = n[0].sym
|
||||||
if f.loc.r == nil: f.loc.r = mangleName(p.module, f)
|
if f.loc.r == "": f.loc.r = mangleName(p.module, f)
|
||||||
if sfInfixCall in f.flags:
|
if sfInfixCall in f.flags:
|
||||||
let pat = n[0].sym.loc.r.data
|
let pat = $n[0].sym.loc.r
|
||||||
internalAssert p.config, pat.len > 0
|
internalAssert p.config, pat.len > 0
|
||||||
if pat.contains({'#', '(', '@'}):
|
if pat.contains({'#', '(', '@'}):
|
||||||
var typ = skipTypes(n[0].typ, abstractInst)
|
var typ = skipTypes(n[0].typ, abstractInst)
|
||||||
|
|
@ -1671,10 +1669,10 @@ proc genInfixCall(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
if n.len != 1:
|
if n.len != 1:
|
||||||
gen(p, n[1], r)
|
gen(p, n[1], r)
|
||||||
if r.typ == etyBaseIndex:
|
if r.typ == etyBaseIndex:
|
||||||
if r.address == nil:
|
if r.address == "":
|
||||||
globalError(p.config, n.info, "cannot invoke with infix syntax")
|
globalError(p.config, n.info, "cannot invoke with infix syntax")
|
||||||
r.res = "$1[$2]" % [r.address, r.res]
|
r.res = "$1[$2]" % [r.address, r.res]
|
||||||
r.address = nil
|
r.address = ""
|
||||||
r.typ = etyNone
|
r.typ = etyNone
|
||||||
r.res.add(".")
|
r.res.add(".")
|
||||||
var op: TCompRes
|
var op: TCompRes
|
||||||
|
|
@ -1826,12 +1824,12 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
|
||||||
result = createVar(p, lastSon t, indirect)
|
result = createVar(p, lastSon t, indirect)
|
||||||
else:
|
else:
|
||||||
internalError(p.config, "createVar: " & $t.kind)
|
internalError(p.config, "createVar: " & $t.kind)
|
||||||
result = nil
|
result = ""
|
||||||
else:
|
else:
|
||||||
internalError(p.config, "createVar: " & $t.kind)
|
internalError(p.config, "createVar: " & $t.kind)
|
||||||
result = nil
|
result = ""
|
||||||
|
|
||||||
template returnType: untyped = ~""
|
template returnType: untyped = ""
|
||||||
|
|
||||||
proc genVarInit(p: PProc, v: PSym, n: PNode) =
|
proc genVarInit(p: PProc, v: PSym, n: PNode) =
|
||||||
var
|
var
|
||||||
|
|
@ -1929,8 +1927,7 @@ proc genVarStmt(p: PProc, n: PNode) =
|
||||||
|
|
||||||
proc genConstant(p: PProc, c: PSym) =
|
proc genConstant(p: PProc, c: PSym) =
|
||||||
if lfNoDecl notin c.loc.flags and not p.g.generatedSyms.containsOrIncl(c.id):
|
if lfNoDecl notin c.loc.flags and not p.g.generatedSyms.containsOrIncl(c.id):
|
||||||
let oldBody = p.body
|
let oldBody = move p.body
|
||||||
p.body = nil
|
|
||||||
#genLineDir(p, c.ast)
|
#genLineDir(p, c.ast)
|
||||||
genVarInit(p, c, c.ast)
|
genVarInit(p, c, c.ast)
|
||||||
p.g.constants.add(p.body)
|
p.g.constants.add(p.body)
|
||||||
|
|
@ -1984,7 +1981,7 @@ proc genConStrStr(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
else:
|
else:
|
||||||
r.res.add("$1 || [])" % [a.res])
|
r.res.add("$1 || [])" % [a.res])
|
||||||
|
|
||||||
proc genReprAux(p: PProc, n: PNode, r: var TCompRes, magic: string, typ: Rope = nil) =
|
proc genReprAux(p: PProc, n: PNode, r: var TCompRes, magic: string, typ: Rope = "") =
|
||||||
useMagic(p, magic)
|
useMagic(p, magic)
|
||||||
r.res.add(magic & "(")
|
r.res.add(magic & "(")
|
||||||
var a: TCompRes
|
var a: TCompRes
|
||||||
|
|
@ -1993,7 +1990,7 @@ proc genReprAux(p: PProc, n: PNode, r: var TCompRes, magic: string, typ: Rope =
|
||||||
if magic == "reprAny":
|
if magic == "reprAny":
|
||||||
# the pointer argument in reprAny is expandend to
|
# the pointer argument in reprAny is expandend to
|
||||||
# (pointedto, pointer), so we need to fill it
|
# (pointedto, pointer), so we need to fill it
|
||||||
if a.address.isNil:
|
if a.address.len == 0:
|
||||||
r.res.add(a.res)
|
r.res.add(a.res)
|
||||||
r.res.add(", null")
|
r.res.add(", null")
|
||||||
else:
|
else:
|
||||||
|
|
@ -2001,14 +1998,14 @@ proc genReprAux(p: PProc, n: PNode, r: var TCompRes, magic: string, typ: Rope =
|
||||||
else:
|
else:
|
||||||
r.res.add(a.res)
|
r.res.add(a.res)
|
||||||
|
|
||||||
if not typ.isNil:
|
if typ != "":
|
||||||
r.res.add(", ")
|
r.res.add(", ")
|
||||||
r.res.add(typ)
|
r.res.add(typ)
|
||||||
r.res.add(")")
|
r.res.add(")")
|
||||||
|
|
||||||
proc genRepr(p: PProc, n: PNode, r: var TCompRes) =
|
proc genRepr(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
let t = skipTypes(n[1].typ, abstractVarRange)
|
let t = skipTypes(n[1].typ, abstractVarRange)
|
||||||
case t.kind:
|
case t.kind
|
||||||
of tyInt..tyInt64, tyUInt..tyUInt64:
|
of tyInt..tyInt64, tyUInt..tyUInt64:
|
||||||
genReprAux(p, n, r, "reprInt")
|
genReprAux(p, n, r, "reprInt")
|
||||||
of tyChar:
|
of tyChar:
|
||||||
|
|
@ -2327,7 +2324,7 @@ proc genObjConstr(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
let val = it[1]
|
let val = it[1]
|
||||||
gen(p, val, a)
|
gen(p, val, a)
|
||||||
var f = it[0].sym
|
var f = it[0].sym
|
||||||
if f.loc.r == nil: f.loc.r = mangleName(p.module, f)
|
if f.loc.r == "": f.loc.r = mangleName(p.module, f)
|
||||||
fieldIDs.incl(lookupFieldAgain(nTyp, f).id)
|
fieldIDs.incl(lookupFieldAgain(nTyp, f).id)
|
||||||
|
|
||||||
let typ = val.typ.skipTypes(abstractInst)
|
let typ = val.typ.skipTypes(abstractInst)
|
||||||
|
|
@ -2388,7 +2385,7 @@ proc convStrToCStr(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
gen(p, n[0][0], r)
|
gen(p, n[0][0], r)
|
||||||
else:
|
else:
|
||||||
gen(p, n[0], r)
|
gen(p, n[0], r)
|
||||||
if r.res == nil: internalError(p.config, n.info, "convStrToCStr")
|
if r.res == "": internalError(p.config, n.info, "convStrToCStr")
|
||||||
useMagic(p, "toJSStr")
|
useMagic(p, "toJSStr")
|
||||||
r.res = "toJSStr($1)" % [r.res]
|
r.res = "toJSStr($1)" % [r.res]
|
||||||
r.kind = resExpr
|
r.kind = resExpr
|
||||||
|
|
@ -2400,7 +2397,7 @@ proc convCStrToStr(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
gen(p, n[0][0], r)
|
gen(p, n[0][0], r)
|
||||||
else:
|
else:
|
||||||
gen(p, n[0], r)
|
gen(p, n[0], r)
|
||||||
if r.res == nil: internalError(p.config, n.info, "convCStrToStr")
|
if r.res == "": internalError(p.config, n.info, "convCStrToStr")
|
||||||
useMagic(p, "cstrToNimstr")
|
useMagic(p, "cstrToNimstr")
|
||||||
r.res = "cstrToNimstr($1)" % [r.res]
|
r.res = "cstrToNimstr($1)" % [r.res]
|
||||||
r.kind = resExpr
|
r.kind = resExpr
|
||||||
|
|
@ -2430,11 +2427,11 @@ proc genProcBody(p: PProc, prc: PSym): Rope =
|
||||||
makeJSString(prc.owner.name.s & '.' & prc.name.s),
|
makeJSString(prc.owner.name.s & '.' & prc.name.s),
|
||||||
makeJSString(toFilenameOption(p.config, prc.info.fileIndex, foStacktrace)))
|
makeJSString(toFilenameOption(p.config, prc.info.fileIndex, foStacktrace)))
|
||||||
else:
|
else:
|
||||||
result = nil
|
result = ""
|
||||||
if p.beforeRetNeeded:
|
if p.beforeRetNeeded:
|
||||||
result.add p.indentLine(~"BeforeRet: {$n")
|
result.add p.indentLine("BeforeRet: {\n")
|
||||||
result.add p.body
|
result.add p.body
|
||||||
result.add p.indentLine(~"};$n")
|
result.add p.indentLine("};\n")
|
||||||
else:
|
else:
|
||||||
result.add(p.body)
|
result.add(p.body)
|
||||||
if prc.typ.callConv == ccSysCall:
|
if prc.typ.callConv == ccSysCall:
|
||||||
|
|
@ -2444,8 +2441,8 @@ proc genProcBody(p: PProc, prc: PSym): Rope =
|
||||||
result.add(frameDestroy(p))
|
result.add(frameDestroy(p))
|
||||||
|
|
||||||
proc optionalLine(p: Rope): Rope =
|
proc optionalLine(p: Rope): Rope =
|
||||||
if p == nil:
|
if p == "":
|
||||||
return nil
|
return ""
|
||||||
else:
|
else:
|
||||||
return p & "\L"
|
return p & "\L"
|
||||||
|
|
||||||
|
|
@ -2458,8 +2455,8 @@ proc genProc(oldProc: PProc, prc: PSym): Rope =
|
||||||
# echo "BEGIN generating code for: " & prc.name.s
|
# echo "BEGIN generating code for: " & prc.name.s
|
||||||
var p = newProc(oldProc.g, oldProc.module, prc.ast, prc.options)
|
var p = newProc(oldProc.g, oldProc.module, prc.ast, prc.options)
|
||||||
p.up = oldProc
|
p.up = oldProc
|
||||||
var returnStmt: Rope = nil
|
var returnStmt: Rope = ""
|
||||||
var resultAsgn: Rope = nil
|
var resultAsgn: Rope = ""
|
||||||
var name = mangleName(p.module, prc)
|
var name = mangleName(p.module, prc)
|
||||||
let header = generateHeader(p, prc.typ)
|
let header = generateHeader(p, prc.typ)
|
||||||
if prc.typ[0] != nil and sfPure notin prc.flags:
|
if prc.typ[0] != nil and sfPure notin prc.flags:
|
||||||
|
|
@ -2503,7 +2500,7 @@ proc genProc(oldProc: PProc, prc: PSym): Rope =
|
||||||
optionalLine(p.indentLine(returnStmt))])
|
optionalLine(p.indentLine(returnStmt))])
|
||||||
else:
|
else:
|
||||||
# if optLineDir in p.config.options:
|
# if optLineDir in p.config.options:
|
||||||
# result.add(~"\L")
|
# result.add("\L")
|
||||||
|
|
||||||
if p.config.hcrOn:
|
if p.config.hcrOn:
|
||||||
# Here, we introduce thunks that create the equivalent of a jump table
|
# Here, we introduce thunks that create the equivalent of a jump table
|
||||||
|
|
@ -2526,7 +2523,7 @@ proc genProc(oldProc: PProc, prc: PSym): Rope =
|
||||||
|
|
||||||
dec p.extraIndent
|
dec p.extraIndent
|
||||||
result.add p.indentLine(def)
|
result.add p.indentLine(def)
|
||||||
result.add p.indentLine(~"}$n")
|
result.add p.indentLine("}\n")
|
||||||
|
|
||||||
#if gVerbosity >= 3:
|
#if gVerbosity >= 3:
|
||||||
# echo "END generated code for: " & prc.name.s
|
# echo "END generated code for: " & prc.name.s
|
||||||
|
|
@ -2534,7 +2531,7 @@ proc genProc(oldProc: PProc, prc: PSym): Rope =
|
||||||
proc genStmt(p: PProc, n: PNode) =
|
proc genStmt(p: PProc, n: PNode) =
|
||||||
var r: TCompRes
|
var r: TCompRes
|
||||||
gen(p, n, r)
|
gen(p, n, r)
|
||||||
if r.res != nil: lineF(p, "$#;$n", [r.res])
|
if r.res != "": lineF(p, "$#;$n", [r.res])
|
||||||
|
|
||||||
proc genPragma(p: PProc, n: PNode) =
|
proc genPragma(p: PProc, n: PNode) =
|
||||||
for it in n.sons:
|
for it in n.sons:
|
||||||
|
|
@ -2574,7 +2571,7 @@ proc genCast(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
r.res = "($1 - ($2 $3))" % [rope minuend, r.res, trimmer]
|
r.res = "($1 - ($2 $3))" % [rope minuend, r.res, trimmer]
|
||||||
elif (src.kind == tyPtr and mapType(p, src) == etyObject) and dest.kind == tyPointer:
|
elif (src.kind == tyPtr and mapType(p, src) == etyObject) and dest.kind == tyPointer:
|
||||||
r.address = r.res
|
r.address = r.res
|
||||||
r.res = ~"null"
|
r.res = "null"
|
||||||
r.typ = etyBaseIndex
|
r.typ = etyBaseIndex
|
||||||
elif (dest.kind == tyPtr and mapType(p, dest) == etyObject) and src.kind == tyPointer:
|
elif (dest.kind == tyPtr and mapType(p, dest) == etyObject) and src.kind == tyPointer:
|
||||||
r.res = r.address
|
r.res = r.address
|
||||||
|
|
@ -2583,8 +2580,8 @@ proc genCast(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
r.typ = etyNone
|
r.typ = etyNone
|
||||||
if r.kind != resCallee: r.kind = resNone
|
if r.kind != resCallee: r.kind = resNone
|
||||||
#r.address = nil
|
#r.address = ""
|
||||||
r.res = nil
|
r.res = ""
|
||||||
|
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkSym:
|
of nkSym:
|
||||||
|
|
@ -2723,7 +2720,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
var s = n[namePos].sym
|
var s = n[namePos].sym
|
||||||
if {sfExportc, sfCompilerProc} * s.flags == {sfExportc}:
|
if {sfExportc, sfCompilerProc} * s.flags == {sfExportc}:
|
||||||
genSym(p, n[namePos], r)
|
genSym(p, n[namePos], r)
|
||||||
r.res = nil
|
r.res = ""
|
||||||
of nkGotoState, nkState:
|
of nkGotoState, nkState:
|
||||||
globalError(p.config, n.info, "First class iterators not implemented")
|
globalError(p.config, n.info, "First class iterators not implemented")
|
||||||
of nkPragmaBlock: gen(p, n.lastSon, r)
|
of nkPragmaBlock: gen(p, n.lastSon, r)
|
||||||
|
|
@ -2840,7 +2837,7 @@ proc getClassName(t: PType): Rope =
|
||||||
s = skipTypes(t, abstractPtrs).sym
|
s = skipTypes(t, abstractPtrs).sym
|
||||||
if s.isNil or sfAnon in s.flags:
|
if s.isNil or sfAnon in s.flags:
|
||||||
doAssert(false, "cannot retrieve class name")
|
doAssert(false, "cannot retrieve class name")
|
||||||
if s.loc.r != nil: result = s.loc.r
|
if s.loc.r != "": result = s.loc.r
|
||||||
else: result = rope(s.name.s)
|
else: result = rope(s.name.s)
|
||||||
|
|
||||||
proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
|
proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,13 @@ proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
|
||||||
s, u: Rope
|
s, u: Rope
|
||||||
field: PSym
|
field: PSym
|
||||||
b: PNode
|
b: PNode
|
||||||
result = nil
|
result = ""
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
if n.len == 1:
|
if n.len == 1:
|
||||||
result = genObjectFields(p, typ, n[0])
|
result = genObjectFields(p, typ, n[0])
|
||||||
else:
|
else:
|
||||||
s = nil
|
s = ""
|
||||||
for i in 0..<n.len:
|
for i in 0..<n.len:
|
||||||
if i > 0: s.add(", \L")
|
if i > 0: s.add(", \L")
|
||||||
s.add(genObjectFields(p, typ, n[i]))
|
s.add(genObjectFields(p, typ, n[i]))
|
||||||
|
|
@ -44,13 +44,13 @@ proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
|
||||||
s = genTypeInfo(p, field.typ)
|
s = genTypeInfo(p, field.typ)
|
||||||
for i in 1..<n.len:
|
for i in 1..<n.len:
|
||||||
b = n[i] # branch
|
b = n[i] # branch
|
||||||
u = nil
|
u = ""
|
||||||
case b.kind
|
case b.kind
|
||||||
of nkOfBranch:
|
of nkOfBranch:
|
||||||
if b.len < 2:
|
if b.len < 2:
|
||||||
internalError(p.config, b.info, "genObjectFields; nkOfBranch broken")
|
internalError(p.config, b.info, "genObjectFields; nkOfBranch broken")
|
||||||
for j in 0..<b.len - 1:
|
for j in 0..<b.len - 1:
|
||||||
if u != nil: u.add(", ")
|
if u != "": u.add(", ")
|
||||||
if b[j].kind == nkRange:
|
if b[j].kind == nkRange:
|
||||||
u.addf("[$1, $2]", [rope(getOrdValue(b[j][0])),
|
u.addf("[$1, $2]", [rope(getOrdValue(b[j][0])),
|
||||||
rope(getOrdValue(b[j][1]))])
|
rope(getOrdValue(b[j][1]))])
|
||||||
|
|
@ -59,7 +59,7 @@ proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
|
||||||
of nkElse:
|
of nkElse:
|
||||||
u = rope(lengthOrd(p.config, field.typ))
|
u = rope(lengthOrd(p.config, field.typ))
|
||||||
else: internalError(p.config, n.info, "genObjectFields(nkRecCase)")
|
else: internalError(p.config, n.info, "genObjectFields(nkRecCase)")
|
||||||
if result != nil: result.add(", \L")
|
if result != "": result.add(", \L")
|
||||||
result.addf("[setConstr($1), $2]",
|
result.addf("[setConstr($1), $2]",
|
||||||
[u, genObjectFields(p, typ, lastSon(b))])
|
[u, genObjectFields(p, typ, lastSon(b))])
|
||||||
result = ("{kind: 3, offset: \"$1\", len: $3, " &
|
result = ("{kind: 3, offset: \"$1\", len: $3, " &
|
||||||
|
|
@ -84,7 +84,7 @@ proc genObjectInfo(p: PProc, typ: PType, name: Rope) =
|
||||||
[name, genTypeInfo(p, typ[0].skipTypes(skipPtrs))])
|
[name, genTypeInfo(p, typ[0].skipTypes(skipPtrs))])
|
||||||
|
|
||||||
proc genTupleFields(p: PProc, typ: PType): Rope =
|
proc genTupleFields(p: PProc, typ: PType): Rope =
|
||||||
var s: Rope = nil
|
var s: Rope = ""
|
||||||
for i in 0..<typ.len:
|
for i in 0..<typ.len:
|
||||||
if i > 0: s.add(", \L")
|
if i > 0: s.add(", \L")
|
||||||
s.addf("{kind: 1, offset: \"Field$1\", len: 0, " &
|
s.addf("{kind: 1, offset: \"Field$1\", len: 0, " &
|
||||||
|
|
@ -102,7 +102,7 @@ proc genTupleInfo(p: PProc, typ: PType, name: Rope) =
|
||||||
p.g.typeInfo.addf("$1.node = NNI$2;$n", [name, rope(typ.id)])
|
p.g.typeInfo.addf("$1.node = NNI$2;$n", [name, rope(typ.id)])
|
||||||
|
|
||||||
proc genEnumInfo(p: PProc, typ: PType, name: Rope) =
|
proc genEnumInfo(p: PProc, typ: PType, name: Rope) =
|
||||||
var s: Rope = nil
|
var s: Rope = ""
|
||||||
for i in 0..<typ.n.len:
|
for i in 0..<typ.n.len:
|
||||||
if (typ.n[i].kind != nkSym): internalError(p.config, typ.n.info, "genEnumInfo")
|
if (typ.n[i].kind != nkSym): internalError(p.config, typ.n.info, "genEnumInfo")
|
||||||
let field = typ.n[i].sym
|
let field = typ.n[i].sym
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,9 @@
|
||||||
import
|
import
|
||||||
std/[strutils, os, tables, terminal, macros, times],
|
std/[strutils, os, tables, terminal, macros, times],
|
||||||
std/private/miscdollars,
|
std/private/miscdollars,
|
||||||
options, ropes, lineinfos, pathutils, strutils2
|
options, lineinfos, pathutils, strutils2
|
||||||
|
|
||||||
|
import ropes except `%`
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
import std/[syncio, assertions]
|
import std/[syncio, assertions]
|
||||||
|
|
@ -43,18 +45,16 @@ proc toCChar*(c: char; result: var string) {.inline.} =
|
||||||
result.add c
|
result.add c
|
||||||
|
|
||||||
proc makeCString*(s: string): Rope =
|
proc makeCString*(s: string): Rope =
|
||||||
result = nil
|
result = newStringOfCap(int(s.len.toFloat * 1.1) + 1)
|
||||||
var res = newStringOfCap(int(s.len.toFloat * 1.1) + 1)
|
result.add("\"")
|
||||||
res.add("\"")
|
|
||||||
for i in 0..<s.len:
|
for i in 0..<s.len:
|
||||||
# line wrapping of string litterals in cgen'd code was a bad idea, e.g. causes: bug #16265
|
# line wrapping of string litterals in cgen'd code was a bad idea, e.g. causes: bug #16265
|
||||||
# It also makes reading c sources or grepping harder, for zero benefit.
|
# It also makes reading c sources or grepping harder, for zero benefit.
|
||||||
# const MaxLineLength = 64
|
# const MaxLineLength = 64
|
||||||
# if (i + 1) mod MaxLineLength == 0:
|
# if (i + 1) mod MaxLineLength == 0:
|
||||||
# res.add("\"\L\"")
|
# res.add("\"\L\"")
|
||||||
toCChar(s[i], res)
|
toCChar(s[i], result)
|
||||||
res.add('\"')
|
result.add('\"')
|
||||||
result.add(rope(res))
|
|
||||||
|
|
||||||
proc newFileInfo(fullPath: AbsoluteFile, projPath: RelativeFile): TFileInfo =
|
proc newFileInfo(fullPath: AbsoluteFile, projPath: RelativeFile): TFileInfo =
|
||||||
result.fullPath = fullPath
|
result.fullPath = fullPath
|
||||||
|
|
|
||||||
|
|
@ -960,7 +960,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
|
||||||
incl(sym.loc.flags, lfHeader)
|
incl(sym.loc.flags, lfHeader)
|
||||||
incl(sym.loc.flags, lfNoDecl)
|
incl(sym.loc.flags, lfNoDecl)
|
||||||
# implies nodecl, because otherwise header would not make sense
|
# implies nodecl, because otherwise header would not make sense
|
||||||
if sym.loc.r == nil: sym.loc.r = rope(sym.name.s)
|
if sym.loc.r == "": sym.loc.r = rope(sym.name.s)
|
||||||
of wNoSideEffect:
|
of wNoSideEffect:
|
||||||
noVal(c, it)
|
noVal(c, it)
|
||||||
if sym != nil:
|
if sym != nil:
|
||||||
|
|
@ -1290,7 +1290,7 @@ proc implicitPragmas*(c: PContext, sym: PSym, info: TLineInfo,
|
||||||
sfImportc in sym.flags and lib != nil:
|
sfImportc in sym.flags and lib != nil:
|
||||||
incl(sym.loc.flags, lfDynamicLib)
|
incl(sym.loc.flags, lfDynamicLib)
|
||||||
addToLib(lib, sym)
|
addToLib(lib, sym)
|
||||||
if sym.loc.r == nil: sym.loc.r = rope(sym.name.s)
|
if sym.loc.r == "": sym.loc.r = rope(sym.name.s)
|
||||||
|
|
||||||
proc hasPragma*(n: PNode, pragma: TSpecialWord): bool =
|
proc hasPragma*(n: PNode, pragma: TSpecialWord): bool =
|
||||||
if n == nil: return false
|
if n == nil: return false
|
||||||
|
|
|
||||||
|
|
@ -7,217 +7,57 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
# Ropes for the C code generator
|
# Ropes for the C code generator. Ropes are mapped to `string` directly nowadays.
|
||||||
#
|
|
||||||
# Ropes are a data structure that represents a very long string
|
|
||||||
# efficiently; especially concatenation is done in O(1) instead of O(N).
|
|
||||||
# Ropes make use a lazy evaluation: They are essentially concatenation
|
|
||||||
# trees that are only flattened when converting to a native Nim
|
|
||||||
# string or when written to disk. The empty string is represented by a
|
|
||||||
# nil pointer.
|
|
||||||
# A little picture makes everything clear:
|
|
||||||
#
|
|
||||||
# "this string" & " is internally " & "represented as"
|
|
||||||
#
|
|
||||||
# con -- inner nodes do not contain raw data
|
|
||||||
# / \
|
|
||||||
# / \
|
|
||||||
# / \
|
|
||||||
# con "represented as"
|
|
||||||
# / \
|
|
||||||
# / \
|
|
||||||
# / \
|
|
||||||
# / \
|
|
||||||
# / \
|
|
||||||
#"this string" " is internally "
|
|
||||||
#
|
|
||||||
# Note that this is the same as:
|
|
||||||
# "this string" & (" is internally " & "represented as")
|
|
||||||
#
|
|
||||||
# con
|
|
||||||
# / \
|
|
||||||
# / \
|
|
||||||
# / \
|
|
||||||
# "this string" con
|
|
||||||
# / \
|
|
||||||
# / \
|
|
||||||
# / \
|
|
||||||
# / \
|
|
||||||
# / \
|
|
||||||
#" is internally " "represented as"
|
|
||||||
#
|
|
||||||
# The 'con' operator is associative! This does not matter however for
|
|
||||||
# the algorithms we use for ropes.
|
|
||||||
#
|
|
||||||
# Note that the left and right pointers are not needed for leaves.
|
|
||||||
# Leaves have relatively high memory overhead (~30 bytes on a 32
|
|
||||||
# bit machines) and we produce many of them. This is why we cache and
|
|
||||||
# share leaves across different rope trees.
|
|
||||||
# To cache them they are inserted in a `cache` array.
|
|
||||||
|
|
||||||
import
|
import hashes
|
||||||
hashes
|
|
||||||
|
|
||||||
from pathutils import AbsoluteFile
|
from pathutils import AbsoluteFile
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
import std/[assertions, syncio, formatfloat]
|
import std/[assertions, syncio, formatfloat]
|
||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
FormatStr* = string # later we may change it to CString for better
|
FormatStr* = string # later we may change it to CString for better
|
||||||
# performance of the code generator (assignments
|
# performance of the code generator (assignments
|
||||||
# copy the format strings
|
# copy the format strings
|
||||||
# though it is not necessary)
|
# though it is not necessary)
|
||||||
Rope* = ref RopeObj
|
Rope* = string
|
||||||
RopeObj*{.acyclic.} = object of RootObj # the empty rope is represented
|
|
||||||
# by nil to safe space
|
|
||||||
left, right: Rope
|
|
||||||
L: int # <= 0 if a leaf
|
|
||||||
data*: string
|
|
||||||
|
|
||||||
proc len*(a: Rope): int =
|
proc newRopeAppender*(): string {.inline.} =
|
||||||
## the rope's length
|
result = newString(0)
|
||||||
if a == nil: result = 0
|
|
||||||
else: result = abs a.L
|
|
||||||
|
|
||||||
proc newRope(data: string = ""): Rope =
|
proc freeze*(r: Rope) {.inline.} = discard
|
||||||
new(result)
|
|
||||||
result.L = -data.len
|
|
||||||
result.data = data
|
|
||||||
|
|
||||||
when compileOption("tlsEmulation"): # fixme: be careful if you want to make ropes support multiple threads
|
proc resetRopeCache* = discard
|
||||||
var
|
|
||||||
cache: array[0..2048*2 - 1, Rope]
|
|
||||||
else:
|
|
||||||
var
|
|
||||||
cache {.threadvar.} : array[0..2048*2 - 1, Rope]
|
|
||||||
|
|
||||||
proc resetRopeCache* =
|
template rope*(s: string): string = s
|
||||||
for i in low(cache)..high(cache):
|
|
||||||
cache[i] = nil
|
|
||||||
|
|
||||||
proc ropeInvariant(r: Rope): bool =
|
|
||||||
if r == nil:
|
|
||||||
result = true
|
|
||||||
else:
|
|
||||||
result = true #
|
|
||||||
# if r.data <> snil then
|
|
||||||
# result := true
|
|
||||||
# else begin
|
|
||||||
# result := (r.left <> nil) and (r.right <> nil);
|
|
||||||
# if result then result := ropeInvariant(r.left);
|
|
||||||
# if result then result := ropeInvariant(r.right);
|
|
||||||
# end
|
|
||||||
|
|
||||||
var gCacheTries* = 0
|
|
||||||
var gCacheMisses* = 0
|
|
||||||
var gCacheIntTries* = 0
|
|
||||||
|
|
||||||
proc insertInCache(s: string): Rope =
|
|
||||||
inc gCacheTries
|
|
||||||
var h = hash(s) and high(cache)
|
|
||||||
result = cache[h]
|
|
||||||
if isNil(result) or result.data != s:
|
|
||||||
inc gCacheMisses
|
|
||||||
result = newRope(s)
|
|
||||||
cache[h] = result
|
|
||||||
|
|
||||||
proc rope*(s: string): Rope =
|
|
||||||
## Converts a string to a rope.
|
|
||||||
if s.len == 0:
|
|
||||||
result = nil
|
|
||||||
else:
|
|
||||||
result = insertInCache(s)
|
|
||||||
assert(ropeInvariant(result))
|
|
||||||
|
|
||||||
proc rope*(i: BiggestInt): Rope =
|
proc rope*(i: BiggestInt): Rope =
|
||||||
## Converts an int to a rope.
|
## Converts an int to a rope.
|
||||||
inc gCacheIntTries
|
|
||||||
result = rope($i)
|
result = rope($i)
|
||||||
|
|
||||||
proc rope*(f: BiggestFloat): Rope =
|
proc rope*(f: BiggestFloat): Rope =
|
||||||
## Converts a float to a rope.
|
## Converts a float to a rope.
|
||||||
result = rope($f)
|
result = rope($f)
|
||||||
|
|
||||||
proc `&`*(a, b: Rope): Rope =
|
|
||||||
if a == nil:
|
|
||||||
result = b
|
|
||||||
elif b == nil:
|
|
||||||
result = a
|
|
||||||
else:
|
|
||||||
result = newRope()
|
|
||||||
result.L = abs(a.L) + abs(b.L)
|
|
||||||
result.left = a
|
|
||||||
result.right = b
|
|
||||||
|
|
||||||
proc `&`*(a: Rope, b: string): Rope =
|
|
||||||
## the concatenation operator for ropes.
|
|
||||||
result = a & rope(b)
|
|
||||||
|
|
||||||
proc `&`*(a: string, b: Rope): Rope =
|
|
||||||
## the concatenation operator for ropes.
|
|
||||||
result = rope(a) & b
|
|
||||||
|
|
||||||
proc `&`*(a: openArray[Rope]): Rope =
|
|
||||||
## the concatenation operator for an openarray of ropes.
|
|
||||||
for i in 0..high(a): result = result & a[i]
|
|
||||||
|
|
||||||
proc add*(a: var Rope, b: Rope) =
|
|
||||||
## adds `b` to the rope `a`.
|
|
||||||
a = a & b
|
|
||||||
|
|
||||||
proc add*(a: var Rope, b: string) =
|
|
||||||
## adds `b` to the rope `a`.
|
|
||||||
a = a & b
|
|
||||||
|
|
||||||
iterator leaves*(r: Rope): string =
|
|
||||||
## iterates over any leaf string in the rope `r`.
|
|
||||||
if r != nil:
|
|
||||||
var stack = @[r]
|
|
||||||
while stack.len > 0:
|
|
||||||
var it = stack.pop
|
|
||||||
while it.left != nil:
|
|
||||||
assert it.right != nil
|
|
||||||
stack.add(it.right)
|
|
||||||
it = it.left
|
|
||||||
assert(it != nil)
|
|
||||||
yield it.data
|
|
||||||
|
|
||||||
iterator items*(r: Rope): char =
|
|
||||||
## iterates over any character in the rope `r`.
|
|
||||||
for s in leaves(r):
|
|
||||||
for c in items(s): yield c
|
|
||||||
|
|
||||||
proc writeRope*(f: File, r: Rope) =
|
proc writeRope*(f: File, r: Rope) =
|
||||||
## writes a rope to a file.
|
## writes a rope to a file.
|
||||||
for s in leaves(r): write(f, s)
|
write(f, r)
|
||||||
|
|
||||||
proc writeRope*(head: Rope, filename: AbsoluteFile): bool =
|
proc writeRope*(head: Rope, filename: AbsoluteFile): bool =
|
||||||
var f: File
|
var f: File
|
||||||
if open(f, filename.string, fmWrite):
|
if open(f, filename.string, fmWrite):
|
||||||
if head != nil: writeRope(f, head)
|
writeRope(f, head)
|
||||||
close(f)
|
close(f)
|
||||||
result = true
|
result = true
|
||||||
else:
|
else:
|
||||||
result = false
|
result = false
|
||||||
|
|
||||||
proc `$`*(r: Rope): string =
|
|
||||||
## converts a rope back to a string.
|
|
||||||
result = newString(r.len)
|
|
||||||
setLen(result, 0)
|
|
||||||
for s in leaves(r): result.add(s)
|
|
||||||
|
|
||||||
proc ropeConcat*(a: varargs[Rope]): Rope =
|
|
||||||
# not overloaded version of concat to speed-up `rfmt` a little bit
|
|
||||||
for i in 0..high(a): result = result & a[i]
|
|
||||||
|
|
||||||
proc prepend*(a: var Rope, b: Rope) = a = b & a
|
|
||||||
proc prepend*(a: var Rope, b: string) = a = b & a
|
proc prepend*(a: var Rope, b: string) = a = b & a
|
||||||
|
|
||||||
proc runtimeFormat*(frmt: FormatStr, args: openArray[Rope]): Rope =
|
proc runtimeFormat*(frmt: FormatStr, args: openArray[Rope]): Rope =
|
||||||
var i = 0
|
var i = 0
|
||||||
result = nil
|
result = newRopeAppender()
|
||||||
var num = 0
|
var num = 0
|
||||||
while i < frmt.len:
|
while i < frmt.len:
|
||||||
if frmt[i] == '$':
|
if frmt[i] == '$':
|
||||||
|
|
@ -270,7 +110,6 @@ proc runtimeFormat*(frmt: FormatStr, args: openArray[Rope]): Rope =
|
||||||
else: break
|
else: break
|
||||||
if i - 1 >= start:
|
if i - 1 >= start:
|
||||||
result.add(substr(frmt, start, i - 1))
|
result.add(substr(frmt, start, i - 1))
|
||||||
assert(ropeInvariant(result))
|
|
||||||
|
|
||||||
proc `%`*(frmt: static[FormatStr], args: openArray[Rope]): Rope =
|
proc `%`*(frmt: static[FormatStr], args: openArray[Rope]): Rope =
|
||||||
runtimeFormat(frmt, args)
|
runtimeFormat(frmt, args)
|
||||||
|
|
@ -279,21 +118,10 @@ template addf*(c: var Rope, frmt: FormatStr, args: openArray[Rope]) =
|
||||||
## shortcut for ``add(c, frmt % args)``.
|
## shortcut for ``add(c, frmt % args)``.
|
||||||
c.add(frmt % args)
|
c.add(frmt % args)
|
||||||
|
|
||||||
when true:
|
|
||||||
template `~`*(r: string): Rope = r % []
|
|
||||||
else:
|
|
||||||
{.push stack_trace: off, line_trace: off.}
|
|
||||||
proc `~`*(r: static[string]): Rope =
|
|
||||||
# this is the new optimized "to rope" operator
|
|
||||||
# the mnemonic is that `~` looks a bit like a rope :)
|
|
||||||
var r {.global.} = r % []
|
|
||||||
return r
|
|
||||||
{.pop.}
|
|
||||||
|
|
||||||
const
|
const
|
||||||
bufSize = 1024 # 1 KB is reasonable
|
bufSize = 1024 # 1 KB is reasonable
|
||||||
|
|
||||||
proc equalsFile*(r: Rope, f: File): bool =
|
proc equalsFile*(s: Rope, f: File): bool =
|
||||||
## returns true if the contents of the file `f` equal `r`.
|
## returns true if the contents of the file `f` equal `r`.
|
||||||
var
|
var
|
||||||
buf: array[bufSize, char]
|
buf: array[bufSize, char]
|
||||||
|
|
@ -302,7 +130,7 @@ proc equalsFile*(r: Rope, f: File): bool =
|
||||||
btotal = 0
|
btotal = 0
|
||||||
rtotal = 0
|
rtotal = 0
|
||||||
|
|
||||||
for s in leaves(r):
|
when true:
|
||||||
var spos = 0
|
var spos = 0
|
||||||
rtotal += s.len
|
rtotal += s.len
|
||||||
while spos < s.len:
|
while spos < s.len:
|
||||||
|
|
|
||||||
|
|
@ -2259,7 +2259,7 @@ proc instantiateCreateFlowVarCall(c: PContext; t: PType;
|
||||||
# codegen would fail:
|
# codegen would fail:
|
||||||
if sfCompilerProc in result.flags:
|
if sfCompilerProc in result.flags:
|
||||||
result.flags.excl {sfCompilerProc, sfExportc, sfImportc}
|
result.flags.excl {sfCompilerProc, sfExportc, sfImportc}
|
||||||
result.loc.r = nil
|
result.loc.r = ""
|
||||||
|
|
||||||
proc setMs(n: PNode, s: PSym): PNode =
|
proc setMs(n: PNode, s: PSym): PNode =
|
||||||
result = n
|
result = n
|
||||||
|
|
@ -2836,7 +2836,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
|
||||||
defer:
|
defer:
|
||||||
if isCompilerDebug():
|
if isCompilerDebug():
|
||||||
echo ("<", c.config$n.info, n, ?.result.typ)
|
echo ("<", c.config$n.info, n, ?.result.typ)
|
||||||
|
|
||||||
template directLiteral(typeKind: TTypeKind) =
|
template directLiteral(typeKind: TTypeKind) =
|
||||||
if result.typ == nil:
|
if result.typ == nil:
|
||||||
if expectedType != nil and (
|
if expectedType != nil and (
|
||||||
|
|
|
||||||
|
|
@ -824,7 +824,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||||
f.options = c.config.options
|
f.options = c.config.options
|
||||||
if fieldOwner != nil and
|
if fieldOwner != nil and
|
||||||
{sfImportc, sfExportc} * fieldOwner.flags != {} and
|
{sfImportc, sfExportc} * fieldOwner.flags != {} and
|
||||||
not hasCaseFields and f.loc.r == nil:
|
not hasCaseFields and f.loc.r == "":
|
||||||
f.loc.r = rope(f.name.s)
|
f.loc.r = rope(f.name.s)
|
||||||
f.flags.incl {sfImportc, sfExportc} * fieldOwner.flags
|
f.flags.incl {sfImportc, sfExportc} * fieldOwner.flags
|
||||||
inc(pos)
|
inc(pos)
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,7 @@ proc `&=`(c: var MD5Context, s: string) = md5Update(c, s, s.len)
|
||||||
proc `&=`(c: var MD5Context, ch: char) =
|
proc `&=`(c: var MD5Context, ch: char) =
|
||||||
# XXX suspicious code here; relies on ch being zero terminated?
|
# XXX suspicious code here; relies on ch being zero terminated?
|
||||||
md5Update(c, unsafeAddr ch, 1)
|
md5Update(c, unsafeAddr ch, 1)
|
||||||
proc `&=`(c: var MD5Context, r: Rope) =
|
|
||||||
for l in leaves(r): md5Update(c, l.cstring, l.len)
|
|
||||||
proc `&=`(c: var MD5Context, i: BiggestInt) =
|
proc `&=`(c: var MD5Context, i: BiggestInt) =
|
||||||
md5Update(c, cast[cstring](unsafeAddr i), sizeof(i))
|
md5Update(c, cast[cstring](unsafeAddr i), sizeof(i))
|
||||||
proc `&=`(c: var MD5Context, f: BiggestFloat) =
|
proc `&=`(c: var MD5Context, f: BiggestFloat) =
|
||||||
|
|
@ -150,7 +149,7 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
|
||||||
# is actually safe without an infinite recursion check:
|
# is actually safe without an infinite recursion check:
|
||||||
if t.sym != nil:
|
if t.sym != nil:
|
||||||
if {sfCompilerProc} * t.sym.flags != {}:
|
if {sfCompilerProc} * t.sym.flags != {}:
|
||||||
doAssert t.sym.loc.r != nil
|
doAssert t.sym.loc.r != ""
|
||||||
# The user has set a specific name for this type
|
# The user has set a specific name for this type
|
||||||
c &= t.sym.loc.r
|
c &= t.sym.loc.r
|
||||||
elif CoOwnerSig in flags:
|
elif CoOwnerSig in flags:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue