Merge branch 'master' of github.com:Araq/Nimrod

This commit is contained in:
Araq
2012-04-15 10:02:35 +02:00
20 changed files with 440 additions and 264 deletions

View File

@@ -244,12 +244,17 @@ const
sfDispatcher* = sfDeadCodeElim # copied method symbol is the dispatcher
sfNoInit* = sfMainModule # don't generate code to init the variable
sfImmediate* = sfDeadCodeElim # macro or template is immediately expanded
# without considering any possible overloads
sfImmediate* = sfDeadCodeElim
# macro or template is immediately expanded
# without considering any possible overloads
sfAnon* = sfCompilerProc # symbol name that was generated by the compiler
# the compiler will avoid printing such names
# in user messages.
sfAnon* = sfDiscardable
# symbol name that was generated by the compiler
# the compiler will avoid printing such names
# in user messages.
sfShadowed* = sfInnerProc
# a variable that was shadowed in some inner scope
const
# getting ready for the future expr/stmt merge
@@ -647,6 +652,14 @@ const
resultPos* = 5
dispatcherPos* = 6 # caution: if method has no 'result' it can be position 5!
nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix,
nkCommand, nkCallStrLit}
nkLambdaKinds* = {nkLambda, nkDo}
skLocalVars* = {skVar, skLet, skForVar, skParam}
# creator procs:
proc NewSym*(symKind: TSymKind, Name: PIdent, owner: PSym): PSym
proc NewType*(kind: TTypeKind, owner: PSym): PType
@@ -691,11 +704,6 @@ proc copyNode*(src: PNode): PNode
proc copyTree*(src: PNode): PNode
# does copy its sons!
const nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand,
nkCallStrLit}
const nkLambdaKinds* = {nkLambda, nkDo}
proc isCallExpr*(n: PNode): bool =
result = n.kind in nkCallKinds

View File

@@ -6,6 +6,8 @@
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
#
# included from cgen.nim
proc leftAppearsOnRightSide(le, ri: PNode): bool =
if le != nil:
@@ -16,9 +18,6 @@ proc leftAppearsOnRightSide(le, ri: PNode): bool =
proc hasNoInit(call: PNode): bool {.inline.} =
result = call.sons[0].kind == nkSym and sfNoInit in call.sons[0].sym.flags
proc resetLoc(p: BProc, d: var TLoc) =
zeroVar(p, d, containsGarbageCollectedRef(d.t))
proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, pl: PRope) =
var pl = pl
var typ = ri.sons[0].typ # getUniqueType() is too expensive here!
@@ -34,15 +33,15 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, pl: PRope) =
resetLoc(p, d)
app(pl, addrLoc(d))
app(pl, ")")
app(p.s[cpsStmts], pl)
appf(p.s[cpsStmts], ";$n")
app(p.s(cpsStmts), pl)
appf(p.s(cpsStmts), ";$n")
else:
var tmp: TLoc
getTemp(p, typ.sons[0], tmp)
app(pl, addrLoc(tmp))
app(pl, ")")
app(p.s[cpsStmts], pl)
appf(p.s[cpsStmts], ";$n")
app(p.s(cpsStmts), pl)
appf(p.s(cpsStmts), ";$n")
genAssignment(p, d, tmp, {}) # no need for deep copying
else:
app(pl, ")")
@@ -54,8 +53,8 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, pl: PRope) =
genAssignment(p, d, list, {}) # no need for deep copying
else:
app(pl, ")")
app(p.s[cpsStmts], pl)
appf(p.s[cpsStmts], ";$n")
app(p.s(cpsStmts), pl)
appf(p.s(cpsStmts), ";$n")
proc isInCurrentFrame(p: BProc, n: PNode): bool =
# checks if `n` is an expression that refers to the current frame;
@@ -164,7 +163,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
if i < length - 1: app(pl, ", ")
template genCallPattern =
appf(p.s[cpsStmts], CallPattern, op.r, pl, pl.addComma, rawProc)
appf(p.s(cpsStmts), CallPattern, op.r, pl, pl.addComma, rawProc)
let rawProc = getRawProcType(p, typ)
if typ.sons[0] != nil:
@@ -179,13 +178,13 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
resetLoc(p, d)
app(pl, addrLoc(d))
genCallPattern()
appf(p.s[cpsStmts], ";$n")
appf(p.s(cpsStmts), ";$n")
else:
var tmp: TLoc
getTemp(p, typ.sons[0], tmp)
app(pl, addrLoc(tmp))
genCallPattern()
appf(p.s[cpsStmts], ";$n")
appf(p.s(cpsStmts), ";$n")
genAssignment(p, d, tmp, {}) # no need for deep copying
else:
if d.k == locNone: getTemp(p, typ.sons[0], d)
@@ -196,7 +195,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
genAssignment(p, d, list, {}) # no need for deep copying
else:
genCallPattern()
appf(p.s[cpsStmts], ";$n")
appf(p.s(cpsStmts), ";$n")
proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
var op, a: TLoc
@@ -261,15 +260,15 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
app(pl, "Result: ")
app(pl, addrLoc(d))
app(pl, "]")
app(p.s[cpsStmts], pl)
appf(p.s[cpsStmts], ";$n")
app(p.s(cpsStmts), pl)
appf(p.s(cpsStmts), ";$n")
else:
var tmp: TLoc
getTemp(p, typ.sons[0], tmp)
app(pl, addrLoc(tmp))
app(pl, "]")
app(p.s[cpsStmts], pl)
appf(p.s[cpsStmts], ";$n")
app(p.s(cpsStmts), pl)
appf(p.s(cpsStmts), ";$n")
genAssignment(p, d, tmp, {}) # no need for deep copying
else:
app(pl, "]")
@@ -281,8 +280,8 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
genAssignment(p, d, list, {}) # no need for deep copying
else:
app(pl, "]")
app(p.s[cpsStmts], pl)
appf(p.s[cpsStmts], ";$n")
app(p.s(cpsStmts), pl)
appf(p.s(cpsStmts), ";$n")
proc genCall(p: BProc, e: PNode, d: var TLoc) =
if e.sons[0].typ.callConv == ccClosure:

View File

@@ -160,7 +160,7 @@ proc getStorageLoc(n: PNode): TStorageLoc =
proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
if dest.s == OnStack or optRefcGC notin gGlobalOptions:
appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
appf(p.s(cpsStmts), "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
if needToKeepAlive in flags: keepAlive(p, dest)
elif dest.s == OnHeap:
# location is on heap
@@ -180,13 +180,13 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
# appf(p.s[cpsStmts], 'if ($1) nimGCunref($1);$n', [rdLoc(dest)])
# appf(p.s[cpsStmts], '$1 = $2;$n', [rdLoc(dest), rdLoc(src)])
if canFormAcycle(dest.t):
appcg(p.module, p.s[cpsStmts], "#asgnRef((void**) $1, $2);$n",
appcg(p.module, p.s(cpsStmts), "#asgnRef((void**) $1, $2);$n",
[addrLoc(dest), rdLoc(src)])
else:
appcg(p.module, p.s[cpsStmts], "#asgnRefNoCycle((void**) $1, $2);$n",
appcg(p.module, p.s(cpsStmts), "#asgnRefNoCycle((void**) $1, $2);$n",
[addrLoc(dest), rdLoc(src)])
else:
appcg(p.module, p.s[cpsStmts], "#unsureAsgnRef((void**) $1, $2);$n",
appcg(p.module, p.s(cpsStmts), "#unsureAsgnRef((void**) $1, $2);$n",
[addrLoc(dest), rdLoc(src)])
if needToKeepAlive in flags: keepAlive(p, dest)
@@ -736,9 +736,9 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
expr(p, e.sons[1], tmp)
L = getLabel(p)
if m == mOr:
appf(p.s[cpsStmts], "if ($1) goto $2;$n", [rdLoc(tmp), L])
appf(p.s(cpsStmts), "if ($1) goto $2;$n", [rdLoc(tmp), L])
else:
appf(p.s[cpsStmts], "if (!($1)) goto $2;$n", [rdLoc(tmp), L])
appf(p.s(cpsStmts), "if (!($1)) goto $2;$n", [rdLoc(tmp), L])
expr(p, e.sons[2], tmp)
fixLabel(p, L)
if d.k == locNone:
@@ -771,9 +771,9 @@ proc genIfExpr(p: BProc, n: PNode, d: var TLoc) =
of nkElifExpr:
initLocExpr(p, it.sons[0], a)
Lelse = getLabel(p)
appf(p.s[cpsStmts], "if (!$1) goto $2;$n", [rdLoc(a), Lelse])
appf(p.s(cpsStmts), "if (!$1) goto $2;$n", [rdLoc(a), Lelse])
expr(p, it.sons[1], tmp)
appf(p.s[cpsStmts], "goto $1;$n", [Lend])
appf(p.s(cpsStmts), "goto $1;$n", [Lend])
fixLabel(p, Lelse)
of nkElseExpr:
expr(p, it.sons[0], tmp)
@@ -832,7 +832,7 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
appf(lens, "$1->$2 + ", [rdLoc(a), lenField()])
appcg(p.module, appends, "#appendString($1, $2);$n", [tmp.r, rdLoc(a)])
appcg(p, cpsStmts, "$1 = #rawNewString($2$3);$n", [tmp.r, lens, toRope(L)])
app(p.s[cpsStmts], appends)
app(p.s(cpsStmts), appends)
if d.k == locNone:
d = tmp
keepAlive(p, tmp)
@@ -874,7 +874,7 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
appcg(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n",
[rdLoc(dest), lens, toRope(L)])
keepAlive(p, dest)
app(p.s[cpsStmts], appends)
app(p.s(cpsStmts), appends)
proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
# seq &= x -->
@@ -1171,7 +1171,7 @@ proc binaryStmtInExcl(p: BProc, e: PNode, d: var TLoc, frmt: string) =
assert(d.k == locNone)
InitLocExpr(p, e.sons[1], a)
InitLocExpr(p, e.sons[2], b)
appf(p.s[cpsStmts], frmt, [rdLoc(a), rdSetElemLoc(b, a.t)])
appf(p.s(cpsStmts), frmt, [rdLoc(a), rdSetElemLoc(b, a.t)])
proc genInOp(p: BProc, e: PNode, d: var TLoc) =
var a, b, x, y: TLoc
@@ -1247,7 +1247,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
initLocExpr(p, e.sons[1], a)
initLocExpr(p, e.sons[2], b)
if d.k == locNone: getTemp(p, a.t, d)
appf(p.s[cpsStmts], lookupOpr[op],
appf(p.s(cpsStmts), lookupOpr[op],
[rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b)])
of mEqSet:
binaryExprChar(p, e, d, "(memcmp($1, $2, " & $(size) & ")==0)")
@@ -1257,7 +1257,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
initLocExpr(p, e.sons[1], a)
initLocExpr(p, e.sons[2], b)
if d.k == locNone: getTemp(p, a.t, d)
appf(p.s[cpsStmts],
appf(p.s(cpsStmts),
"for ($1 = 0; $1 < $2; $1++) $n" &
" $3[$1] = $4[$1] $6 $5[$1];$n", [
rdLoc(i), toRope(size), rdLoc(d), rdLoc(a), rdLoc(b),
@@ -1467,35 +1467,35 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
if d.k == locNone: getTemp(p, e.typ, d)
if getSize(e.typ) > 8:
# big set:
appf(p.s[cpsStmts], "memset($1, 0, sizeof($1));$n", [rdLoc(d)])
appf(p.s(cpsStmts), "memset($1, 0, sizeof($1));$n", [rdLoc(d)])
for i in countup(0, sonsLen(e) - 1):
if e.sons[i].kind == nkRange:
getTemp(p, getSysType(tyInt), idx) # our counter
initLocExpr(p, e.sons[i].sons[0], a)
initLocExpr(p, e.sons[i].sons[1], b)
appf(p.s[cpsStmts], "for ($1 = $3; $1 <= $4; $1++) $n" &
appf(p.s(cpsStmts), "for ($1 = $3; $1 <= $4; $1++) $n" &
"$2[$1/8] |=(1<<($1%8));$n", [rdLoc(idx), rdLoc(d),
rdSetElemLoc(a, e.typ), rdSetElemLoc(b, e.typ)])
else:
initLocExpr(p, e.sons[i], a)
appf(p.s[cpsStmts], "$1[$2/8] |=(1<<($2%8));$n",
appf(p.s(cpsStmts), "$1[$2/8] |=(1<<($2%8));$n",
[rdLoc(d), rdSetElemLoc(a, e.typ)])
else:
# small set
var ts = "NI" & $(getSize(e.typ) * 8)
appf(p.s[cpsStmts], "$1 = 0;$n", [rdLoc(d)])
appf(p.s(cpsStmts), "$1 = 0;$n", [rdLoc(d)])
for i in countup(0, sonsLen(e) - 1):
if e.sons[i].kind == nkRange:
getTemp(p, getSysType(tyInt), idx) # our counter
initLocExpr(p, e.sons[i].sons[0], a)
initLocExpr(p, e.sons[i].sons[1], b)
appf(p.s[cpsStmts], "for ($1 = $3; $1 <= $4; $1++) $n" &
appf(p.s(cpsStmts), "for ($1 = $3; $1 <= $4; $1++) $n" &
"$2 |=(1<<((" & ts & ")($1)%(sizeof(" & ts & ")*8)));$n", [
rdLoc(idx), rdLoc(d), rdSetElemLoc(a, e.typ),
rdSetElemLoc(b, e.typ)])
else:
initLocExpr(p, e.sons[i], a)
appf(p.s[cpsStmts],
appf(p.s(cpsStmts),
"$1 |=(1<<((" & ts & ")($2)%(sizeof(" & ts & ")*8)));$n",
[rdLoc(d), rdSetElemLoc(a, e.typ)])

View File

@@ -280,7 +280,7 @@ proc mergeRequired*(m: BModule): bool =
#echo "not empty: ", i, " ", ropeToStr(m.s[i])
return true
for i in low(TCProcSection)..high(TCProcSection):
if m.initProc.s[i] != nil:
if m.initProc.s(i) != nil:
#echo "not empty: ", i, " ", ropeToStr(m.initProc.s[i])
return true
@@ -292,5 +292,5 @@ proc mergeFiles*(cfilename: string, m: BModule) =
for i in low(TCFileSection)..high(TCFileSection):
m.s[i] = con(old.f[i], m.s[i])
for i in low(TCProcSection)..high(TCProcSection):
m.initProc.s[i] = con(old.p[i], m.initProc.s[i])
m.initProc.s(i) = con(old.p[i], m.initProc.s(i))

View File

@@ -47,6 +47,51 @@ proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} =
else:
expr(p, ri, a)
proc startBlock(p: BProc, start: TFormatStr = "{$n",
args: openarray[PRope]): int {.discardable.} =
inc(p.labels)
result = len(p.blocks)
setlen(p.blocks, result + 1)
p.blocks[result].id = p.labels
p.blocks[result].nestedTryStmts = p.nestedTryStmts.len
appcg(p, cpsLocals, start, args)
proc assignLabel(b: var TBlock): PRope {.inline.} =
b.label = con("LA", b.id.toRope)
result = b.label
proc blockBody(b: var TBlock): PRope {.inline.} =
return b.sections[cpsLocals].con(b.sections[cpsInit]).con(b.sections[cpsStmts])
proc endBlock(p: BProc, blockEnd: PRope) =
let topBlock = p.blocks.len - 1
# the block is merged into the parent block
app(p.blocks[topBlock - 1].sections[cpsStmts], p.blocks[topBlock].blockBody)
setlen(p.blocks, topBlock)
# this is done after the block is popped so $n is
# properly indented when pretty printing is enabled
app(p.s(cpsStmts), blockEnd)
var gBlockEndBracket = ropef("}$n")
proc endBlock(p: BProc) =
let topBlock = p.blocks.len - 1
let blockEnd = if p.blocks[topBlock].label != nil:
ropef("} $1: ;$n", [p.blocks[topBlock].label])
else:
gBlockEndBracket
endBlock(p, blockEnd)
proc genSimpleBlock(p: BProc, stmts: PNode) {.inline.} =
startBlock(p)
genStmts(p, stmts)
endBlock(p)
template preserveBreakIdx(body: stmt): stmt =
var oldBreakIdx = p.breakIdx
body
p.breakIdx = oldBreakIdx
proc genSingleVar(p: BProc, a: PNode) =
var v = a.sons[0].sym
if sfCompileTime in v.flags: return
@@ -56,7 +101,15 @@ proc genSingleVar(p: BProc, a: PNode) =
if v.owner.kind != skModule:
targetProc = p.module.preInitProc
assignGlobalVar(targetProc, v)
genObjectInit(targetProc, cpsInit, v.typ, v.loc, true)
# XXX: be careful here.
# Global variables should not be zeromem-ed within loops
# (see bug #20).
# That's why we are doing the construction inside the preInitProc.
# genObjectInit relies on the C runtime's guarantees that
# global variables will be initialized to zero.
genObjectInit(p.module.preInitProc, cpsInit, v.typ, v.loc, true)
# Alternative construction using default constructor (which may zeromem):
# if sfImportc notin v.flags: constructLoc(p.module.preInitProc, v.loc)
else:
assignLocalVar(p, v)
initLocalVar(p, v, immediateAsgn)
@@ -110,16 +163,15 @@ proc genConstStmt(p: BProc, t: PNode) =
proc genIfStmt(p: BProc, n: PNode) =
#
# if (!expr1) goto L1;
# thenPart
# { thenPart }
# goto LEnd
# L1:
# if (!expr2) goto L2;
# thenPart2
# { thenPart2 }
# goto LEnd
# L2:
# elsePart
# { elsePart }
# Lend:
#
var
a: TLoc
Lelse: TLabel
@@ -132,15 +184,15 @@ proc genIfStmt(p: BProc, n: PNode) =
initLocExpr(p, it.sons[0], a)
Lelse = getLabel(p)
inc(p.labels)
appff(p.s[cpsStmts], "if (!$1) goto $2;$n",
appff(p.s(cpsStmts), "if (!$1) goto $2;$n",
"br i1 $1, label %LOC$3, label %$2$n" & "LOC$3: $n",
[rdLoc(a), Lelse, toRope(p.labels)])
genStmts(p, it.sons[1])
genSimpleBlock(p, it.sons[1])
if sonsLen(n) > 1:
appff(p.s[cpsStmts], "goto $1;$n", "br label %$1$n", [Lend])
appff(p.s(cpsStmts), "goto $1;$n", "br label %$1$n", [Lend])
fixLabel(p, Lelse)
of nkElse:
genStmts(p, it.sons[0])
of nkElse:
genSimpleBlock(p, it.sons[0])
else: internalError(n.info, "genIfStmt()")
if sonsLen(n) > 1: fixLabel(p, Lend)
@@ -169,65 +221,54 @@ proc genReturnStmt(p: BProc, t: PNode) =
genLineDir(p, t)
if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0])
blockLeaveActions(p, min(1, p.nestedTryStmts.len))
appff(p.s[cpsStmts], "goto BeforeRet;$n", "br label %BeforeRet$n", [])
proc genWhileStmt(p: BProc, t: PNode) =
appff(p.s(cpsStmts), "goto BeforeRet;$n", "br label %BeforeRet$n", [])
proc genWhileStmt(p: BProc, t: PNode) =
# we don't generate labels here as for example GCC would produce
# significantly worse code
var
a: TLoc
Labl: TLabel
length: int
assert(sonsLen(t) == 2)
inc(p.withinLoop)
genLineDir(p, t)
assert(sonsLen(t) == 2)
inc(p.labels)
Labl = con("LA", toRope(p.labels))
length = len(p.blocks)
setlen(p.blocks, length + 1)
p.blocks[length].id = - p.labels # negative because it isn't used yet
p.blocks[length].nestedTryStmts = p.nestedTryStmts.len
appf(p.s[cpsStmts], "while (1) {$n")
initLocExpr(p, t.sons[0], a)
if (t.sons[0].kind != nkIntLit) or (t.sons[0].intVal == 0):
p.blocks[length].id = abs(p.blocks[length].id)
appf(p.s[cpsStmts], "if (!$1) goto $2;$n", [rdLoc(a), Labl])
genStmts(p, t.sons[1])
if p.blocks[length].id > 0: appf(p.s[cpsStmts], "} $1: ;$n", [Labl])
else: appf(p.s[cpsStmts], "}$n")
setlen(p.blocks, len(p.blocks) - 1)
preserveBreakIdx:
p.breakIdx = startBlock(p, "while (1) {$n")
initLocExpr(p, t.sons[0], a)
if (t.sons[0].kind != nkIntLit) or (t.sons[0].intVal == 0):
let label = assignLabel(p.blocks[p.breakIdx])
appf(p.s(cpsStmts), "if (!$1) goto $2;$n", [rdLoc(a), label])
genStmts(p, t.sons[1])
endBlock(p)
dec(p.withinLoop)
proc genBlock(p: BProc, t: PNode, d: var TLoc) =
inc(p.labels)
var idx = len(p.blocks)
if t.sons[0].kind != nkEmpty:
# named block?
assert(t.sons[0].kind == nkSym)
var sym = t.sons[0].sym
sym.loc.k = locOther
sym.loc.a = idx
setlen(p.blocks, idx + 1)
p.blocks[idx].id = -p.labels # negative because it isn't used yet
p.blocks[idx].nestedTryStmts = p.nestedTryStmts.len
if t.kind == nkBlockExpr: genStmtListExpr(p, t.sons[1], d)
else: genStmts(p, t.sons[1])
if p.blocks[idx].id > 0:
appf(p.s[cpsStmts], "LA$1: ;$n", [toRope(p.blocks[idx].id)])
setlen(p.blocks, idx)
proc genBlock(p: BProc, t: PNode, d: var TLoc) =
preserveBreakIdx:
p.breakIdx = startBlock(p)
if t.sons[0].kind != nkEmpty:
# named block?
assert(t.sons[0].kind == nkSym)
var sym = t.sons[0].sym
sym.loc.k = locOther
sym.loc.a = p.breakIdx
if t.kind == nkBlockExpr: genStmtListExpr(p, t.sons[1], d)
else: genStmts(p, t.sons[1])
endBlock(p)
proc genBreakStmt(p: BProc, t: PNode) =
var idx = len(p.blocks) - 1
var idx = p.breakIdx
if t.sons[0].kind != nkEmpty:
# named break?
assert(t.sons[0].kind == nkSym)
var sym = t.sons[0].sym
assert(sym.loc.k == locOther)
idx = sym.loc.a
p.blocks[idx].id = abs(p.blocks[idx].id) # label is used
let label = assignLabel(p.blocks[idx])
blockLeaveActions(p, p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts)
genLineDir(p, t)
appf(p.s[cpsStmts], "goto LA$1;$n", [toRope(p.blocks[idx].id)])
appf(p.s(cpsStmts), "goto $1;$n", [label])
proc getRaiseFrmt(p: BProc): string =
#if gCmd == cmdCompileToCpp:
@@ -269,13 +310,13 @@ proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
proc genCaseSecondPass(p: BProc, t: PNode, labId, until: int): TLabel =
var Lend = getLabel(p)
for i in 1..until:
appf(p.s[cpsStmts], "LA$1: ;$n", [toRope(labId + i)])
appf(p.s(cpsStmts), "LA$1: ;$n", [toRope(labId + i)])
if t.sons[i].kind == nkOfBranch:
var length = sonsLen(t.sons[i])
genStmts(p, t.sons[i].sons[length - 1])
appf(p.s[cpsStmts], "goto $1;$n", [Lend])
genSimpleBlock(p, t.sons[i].sons[length - 1])
appf(p.s(cpsStmts), "goto $1;$n", [Lend])
else:
genStmts(p, t.sons[i].sons[0])
genSimpleBlock(p, t.sons[i].sons[0])
result = Lend
proc genIfForCaseUntil(p: BProc, t: PNode, rangeFormat, eqFormat: TFormatStr,
@@ -288,13 +329,13 @@ proc genIfForCaseUntil(p: BProc, t: PNode, rangeFormat, eqFormat: TFormatStr,
genCaseGenericBranch(p, t.sons[i], a, rangeFormat, eqFormat,
con("LA", toRope(p.labels)))
else:
appf(p.s[cpsStmts], "goto LA$1;$n", [toRope(p.labels)])
appf(p.s(cpsStmts), "goto LA$1;$n", [toRope(p.labels)])
if until < t.len-1:
inc(p.labels)
var gotoTarget = p.labels
appf(p.s[cpsStmts], "goto LA$1;$n", [toRope(gotoTarget)])
appf(p.s(cpsStmts), "goto LA$1;$n", [toRope(gotoTarget)])
result = genCaseSecondPass(p, t, labId, until)
appf(p.s[cpsStmts], "LA$1: ;$n", [toRope(gotoTarget)])
appf(p.s(cpsStmts), "LA$1: ;$n", [toRope(gotoTarget)])
else:
result = genCaseSecondPass(p, t, labId, until)
@@ -346,11 +387,11 @@ proc genStringCase(p: BProc, t: PNode) =
if interior != brn:
echo "BUG! ", interior, "-", brn
if branches[j] != nil:
appf(p.s[cpsStmts], "case $1: $n$2break;$n",
appf(p.s(cpsStmts), "case $1: $n$2break;$n",
[intLiteral(j), branches[j]])
appf(p.s[cpsStmts], "}$n") # else statement:
appf(p.s(cpsStmts), "}$n") # else statement:
if t.sons[sonsLen(t) - 1].kind != nkOfBranch:
appf(p.s[cpsStmts], "goto LA$1;$n", [toRope(p.labels)])
appf(p.s(cpsStmts), "goto LA$1;$n", [toRope(p.labels)])
# third pass: generate statements
var Lend = genCaseSecondPass(p, t, labId, sonsLen(t)-1)
fixLabel(p, Lend)
@@ -379,16 +420,16 @@ proc genCaseRange(p: BProc, branch: PNode) =
for j in 0 .. length-2:
if branch[j].kind == nkRange:
if hasSwitchRange in CC[ccompiler].props:
appf(p.s[cpsStmts], "case $1 ... $2:$n", [
appf(p.s(cpsStmts), "case $1 ... $2:$n", [
genLiteral(p, branch[j][0]),
genLiteral(p, branch[j][1])])
else:
var v = copyNode(branch[j][0])
while v.intVal <= branch[j][1].intVal:
appf(p.s[cpsStmts], "case $1:$n", [genLiteral(p, v)])
appf(p.s(cpsStmts), "case $1:$n", [genLiteral(p, v)])
Inc(v.intVal)
else:
appf(p.s[cpsStmts], "case $1:$n", [genLiteral(p, branch[j])])
appf(p.s(cpsStmts), "case $1:$n", [genLiteral(p, branch[j])])
proc genOrdinalCase(p: BProc, n: PNode) =
# analyse 'case' statement:
@@ -404,22 +445,22 @@ proc genOrdinalCase(p: BProc, n: PNode) =
# generate switch part (might be empty):
if splitPoint+1 < n.len:
appf(p.s[cpsStmts], "switch ($1) {$n", [rdCharLoc(a)])
appf(p.s(cpsStmts), "switch ($1) {$n", [rdCharLoc(a)])
var hasDefault = false
for i in splitPoint+1 .. < n.len:
var branch = n[i]
if branch.kind == nkOfBranch:
genCaseRange(p, branch)
genStmts(p, branch.lastSon)
genSimpleBlock(p, branch.lastSon)
else:
# else part of case statement:
appf(p.s[cpsStmts], "default:$n")
genStmts(p, branch[0])
appf(p.s(cpsStmts), "default:$n")
genSimpleBlock(p, branch[0])
hasDefault = true
appf(p.s[cpsStmts], "break;$n")
appf(p.s(cpsStmts), "break;$n")
if (hasAssume in CC[ccompiler].props) and not hasDefault:
appf(p.s[cpsStmts], "default: __assume(0);$n")
appf(p.s[cpsStmts], "}$n")
appf(p.s(cpsStmts), "default: __assume(0);$n")
appf(p.s(cpsStmts), "}$n")
if Lend != nil: fixLabel(p, Lend)
proc genCaseStmt(p: BProc, t: PNode) =
@@ -466,6 +507,8 @@ proc genTryStmtCpp(p: BProc, t: PNode) =
# excHandler = excHandler->prev; // we handled the exception
# finallyPart();
# if (tmpRethrow) throw;
#
# XXX: push blocks
var
rethrowFlag: PRope
exc: PRope
@@ -475,43 +518,43 @@ proc genTryStmtCpp(p: BProc, t: PNode) =
exc = getTempName()
if not hasGeneralExceptSection(t):
rethrowFlag = getTempName()
appf(p.s[cpsLocals], "volatile NIM_BOOL $1 = NIM_FALSE;$n", [rethrowFlag])
appf(p.s(cpsLocals), "volatile NIM_BOOL $1 = NIM_FALSE;$n", [rethrowFlag])
if optStackTrace in p.Options:
appcg(p, cpsStmts, "#setFrame((TFrame*)&F);$n")
appf(p.s[cpsStmts], "try {$n")
appf(p.s(cpsStmts), "try {$n")
add(p.nestedTryStmts, t)
genStmts(p, t.sons[0])
length = sonsLen(t)
if t.sons[1].kind == nkExceptBranch:
appf(p.s[cpsStmts], "} catch (NimException& $1) {$n", [exc])
appf(p.s(cpsStmts), "} catch (NimException& $1) {$n", [exc])
if rethrowFlag != nil:
appf(p.s[cpsStmts], "$1 = NIM_TRUE;$n", [rethrowFlag])
appf(p.s[cpsStmts], "if ($1.sp.exc) {$n", [exc])
appf(p.s(cpsStmts), "$1 = NIM_TRUE;$n", [rethrowFlag])
appf(p.s(cpsStmts), "if ($1.sp.exc) {$n", [exc])
i = 1
while (i < length) and (t.sons[i].kind == nkExceptBranch):
blen = sonsLen(t.sons[i])
if blen == 1:
# general except section:
appf(p.s[cpsStmts], "default:$n")
appf(p.s(cpsStmts), "default:$n")
genStmts(p, t.sons[i].sons[0])
else:
for j in countup(0, blen - 2):
assert(t.sons[i].sons[j].kind == nkType)
appf(p.s[cpsStmts], "case $1:$n", [toRope(t.sons[i].sons[j].typ.id)])
appf(p.s(cpsStmts), "case $1:$n", [toRope(t.sons[i].sons[j].typ.id)])
genStmts(p, t.sons[i].sons[blen - 1])
if rethrowFlag != nil:
appf(p.s[cpsStmts], "$1 = NIM_FALSE; ", [rethrowFlag])
appf(p.s[cpsStmts], "break;$n")
appf(p.s(cpsStmts), "$1 = NIM_FALSE; ", [rethrowFlag])
appf(p.s(cpsStmts), "break;$n")
inc(i)
if t.sons[1].kind == nkExceptBranch:
appf(p.s[cpsStmts], "}}$n") # end of catch-switch statement
appf(p.s(cpsStmts), "}}$n") # end of catch-switch statement
appcg(p, cpsStmts, "#popSafePoint();")
discard pop(p.nestedTryStmts)
if (i < length) and (t.sons[i].kind == nkFinally):
genStmts(p, t.sons[i].sons[0])
if rethrowFlag != nil:
appf(p.s[cpsStmts], "if ($1) { throw; }$n", [rethrowFlag])
appf(p.s(cpsStmts), "if ($1) { throw; }$n", [rethrowFlag])
proc genTryStmt(p: BProc, t: PNode) =
# code to generate:
#
@@ -531,10 +574,13 @@ proc genTryStmt(p: BProc, t: PNode) =
# clearException();
# }
# }
# /* finally: */
# printf('fin!\n');
# {
# /* finally: */
# printf('fin!\n');
# }
# if (exception not cleared)
# propagateCurrentException();
#
genLineDir(p, t)
var safePoint = getTempName()
discard cgsym(p.module, "E_Base")
@@ -543,24 +589,25 @@ proc genTryStmt(p: BProc, t: PNode) =
"$1.status = setjmp($1.context);$n", [safePoint])
if optStackTrace in p.Options:
appcg(p, cpsStmts, "#setFrame((TFrame*)&F);$n")
appf(p.s[cpsStmts], "if ($1.status == 0) {$n", [safePoint])
startBlock(p, "if ($1.status == 0) {$n", [safePoint])
var length = sonsLen(t)
add(p.nestedTryStmts, t)
genStmts(p, t.sons[0])
appcg(p, cpsStmts, "#popSafePoint();$n} else {$n#popSafePoint();$n")
endBlock(p, ropecg(p.module, "#popSafePoint();$n } else {$n#popSafePoint();$n"))
discard pop(p.nestedTryStmts)
var i = 1
while (i < length) and (t.sons[i].kind == nkExceptBranch):
var blen = sonsLen(t.sons[i])
if blen == 1:
# general except section:
if i > 1: appf(p.s[cpsStmts], "else {$n")
if i > 1: appf(p.s(cpsStmts), "else")
startBlock(p)
appcg(p, cpsStmts, "$1.status = 0;$n", [safePoint])
inc p.popCurrExc
genStmts(p, t.sons[i].sons[0])
dec p.popCurrExc
appcg(p, cpsStmts, "#popCurrentException();$n", [])
if i > 1: appf(p.s[cpsStmts], "}$n")
endBlock(p)
else:
inc p.popCurrExc
var orExpr: PRope = nil
@@ -570,17 +617,16 @@ proc genTryStmt(p: BProc, t: PNode) =
appcg(p.module, orExpr,
"#isObj(#getCurrentException()->Sup.m_type, $1)",
[genTypeInfo(p.module, t.sons[i].sons[j].typ)])
if i > 1: app(p.s[cpsStmts], "else ")
appf(p.s[cpsStmts], "if ($1) {$n", [orExpr])
if i > 1: app(p.s(cpsStmts), "else ")
startBlock(p, "if ($1) {$n", [orExpr])
appcg(p, cpsStmts, "$1.status = 0;$n", [safePoint])
genStmts(p, t.sons[i].sons[blen-1])
dec p.popCurrExc
# code to clear the exception:
appcg(p, cpsStmts, "#popCurrentException();}$n", [])
endBlock(p, ropecg(p.module, "#popCurrentException();}$n"))
inc(i)
appf(p.s[cpsStmts], "}$n") # end of if statement
if i < length and t.sons[i].kind == nkFinally:
genStmts(p, t.sons[i].sons[0])
appf(p.s(cpsStmts), "}$n") # end of else block
if i < length and t.sons[i].kind == nkFinally:
genSimpleBlock(p, t.sons[i].sons[0])
appcg(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint])
proc genAsmOrEmitStmt(p: BProc, t: PNode): PRope =
@@ -608,7 +654,7 @@ proc genAsmStmt(p: BProc, t: PNode) =
assert(t.kind == nkAsmStmt)
genLineDir(p, t)
var s = genAsmOrEmitStmt(p, t)
appf(p.s[cpsStmts], CC[ccompiler].asmStmtFrmt, [s])
appf(p.s(cpsStmts), CC[ccompiler].asmStmtFrmt, [s])
proc genEmit(p: BProc, t: PNode) =
genLineDir(p, t)
@@ -617,7 +663,7 @@ proc genEmit(p: BProc, t: PNode) =
# top level emit pragma?
app(p.module.s[cfsProcHeaders], s)
else:
app(p.s[cpsStmts], s)
app(p.s(cpsStmts), s)
var
breakPointId: int = 0

View File

@@ -10,6 +10,8 @@
## Thread var support for crappy architectures that lack native support for
## thread local storage. (**Thank you Mac OS X!**)
# included from cgen.nim
proc emulatedThreadVars(): bool {.inline.} =
result = {optThreads, optTlsEmulation} <= gGlobalOptions
@@ -17,8 +19,9 @@ proc AccessThreadLocalVar(p: BProc, s: PSym) =
if emulatedThreadVars() and not p.ThreadVarAccessed:
p.ThreadVarAccessed = true
p.module.usesThreadVars = true
appf(p.s[cpsLocals], "NimThreadVars* NimTV;$n")
appcg(p, cpsInit, "NimTV=(NimThreadVars*)#GetThreadLocalVars();$n")
appf(p.procSec(cpsLocals), "NimThreadVars* NimTV;$n")
app(p.procSec(cpsInit),
ropecg(p.module, "NimTV=(NimThreadVars*)#GetThreadLocalVars();$n"))
var
nimtv: PRope # nimrod thread vars; the struct body

View File

@@ -10,6 +10,8 @@
## Generates traversal procs for the C backend. Traversal procs are only an
## optimization; the GC works without them too.
# included from cgen.nim
type
TTraversalClosure {.pure, final.} = object
p: BProc
@@ -29,17 +31,17 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, n: PNode) =
if (n.sons[0].kind != nkSym): InternalError(n.info, "genTraverseProc")
var p = c.p
let disc = n.sons[0].sym
p.s[cpsStmts].appf("switch ($1.$2) {$n", accessor, disc.loc.r)
p.s(cpsStmts).appf("switch ($1.$2) {$n", accessor, disc.loc.r)
for i in countup(1, sonsLen(n) - 1):
let branch = n.sons[i]
assert branch.kind in {nkOfBranch, nkElse}
if branch.kind == nkOfBranch:
genCaseRange(c.p, branch)
else:
p.s[cpsStmts].appf("default:$n")
p.s(cpsStmts).appf("default:$n")
genTraverseProc(c, accessor, lastSon(branch))
p.s[cpsStmts].appf("break;$n")
p.s[cpsStmts].appf("} $n")
p.s(cpsStmts).appf("break;$n")
p.s(cpsStmts).appf("} $n")
of nkSym:
let field = n.sym
genTraverseProc(c, ropef("$1.$2", accessor, field.loc.r), field.loc.t)
@@ -61,10 +63,10 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) =
let arraySize = lengthOrd(typ.sons[0])
var i: TLoc
getTemp(p, getSysType(tyInt), i)
appf(p.s[cpsStmts], "for ($1 = 0; $1 < $2; $1++) {$n",
appf(p.s(cpsStmts), "for ($1 = 0; $1 < $2; $1++) {$n",
i.r, arraySize.toRope)
genTraverseProc(c, ropef("$1[$2]", accessor, i.r), typ.sons[1])
appf(p.s[cpsStmts], "}$n")
appf(p.s(cpsStmts), "}$n")
of tyObject:
for i in countup(0, sonsLen(typ) - 1):
genTraverseProc(c, accessor.parentObj, typ.sons[i])
@@ -87,10 +89,10 @@ proc genTraverseProcSeq(c: var TTraversalClosure, accessor: PRope, typ: PType) =
assert typ.kind == tySequence
var i: TLoc
getTemp(p, getSysType(tyInt), i)
appf(p.s[cpsStmts], "for ($1 = 0; $1 < $2->$3; $1++) {$n",
appf(p.s(cpsStmts), "for ($1 = 0; $1 < $2->$3; $1++) {$n",
i.r, accessor, toRope(if gCmd != cmdCompileToCpp: "Sup.len" else: "len"))
genTraverseProc(c, ropef("$1->data[$2]", accessor, i.r), typ.sons[0])
appf(p.s[cpsStmts], "}$n")
appf(p.s(cpsStmts), "}$n")
proc genTraverseProc(m: BModule, typ: PType, reason: TTypeInfoReason): PRope =
var c: TTraversalClosure
@@ -104,8 +106,8 @@ proc genTraverseProc(m: BModule, typ: PType, reason: TTypeInfoReason): PRope =
let header = ropef("N_NIMCALL(void, $1)(void* p, NI op)", result)
let t = getTypeDesc(m, typ)
p.s[cpsLocals].appf("$1 a;$n", t)
p.s[cpsInit].appf("a = ($1)p;$n", t)
p.s(cpsLocals).appf("$1 a;$n", t)
p.s(cpsInit).appf("a = ($1)p;$n", t)
c.p = p
if typ.kind == tySequence:
@@ -118,7 +120,7 @@ proc genTraverseProc(m: BModule, typ: PType, reason: TTypeInfoReason): PRope =
genTraverseProc(c, "(*a)".toRope, typ.sons[0])
let generatedProc = ropef("$1 {$n$2$3$4}$n",
[header, p.s[cpsLocals], p.s[cpsInit], p.s[cpsStmts]])
[header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)])
m.s[cfsProcHeaders].appf("$1;$n", header)
m.s[cfsProcs].app(generatedProc)

View File

@@ -32,6 +32,15 @@ proc mangle(name: string): string =
add(result, "HEX")
add(result, toHex(ord(name[i]), 2))
proc isCKeyword(w: PIdent): bool =
# nimrod and C++ share some keywords
# it's more efficient to test the whole nimrod keywords range
case w.id
of cppKeywordsLow..cppKeywordsHigh,
nimKeywordsLow..nimKeywordsHigh,
ord(wInline): return true
else: return false
proc mangleName(s: PSym): PRope =
result = s.loc.r
if result == nil:
@@ -45,9 +54,64 @@ proc mangleName(s: PSym): PRope =
of skTemp, skParam, skType, skEnumField, skModule:
result = toRope("%")
else: InternalError(s.info, "mangleName")
app(result, toRope(mangle(s.name.s)))
app(result, "_")
app(result, toRope(s.id))
when oKeepVariableNames:
let keepOrigName = s.kind in skLocalVars - {skForVar} and
{sfFromGeneric, sfGlobal, sfShadowed} * s.flags == {} and
not isCKeyword(s.name)
# XXX: This is still very experimental
#
# Even with all these inefficient checks, the bootstrap
# time is actually improved. This is probably because so many
# rope concatenations and are now eliminated.
#
# Future notes:
# sfFromGeneric seems to be needed in order to avoid multiple
# definitions of certain varialbes generated in transf with
# names such as:
# `r`, `res`
# I need to study where these come from.
#
# about sfShadowed:
# consider the following nimrod code:
# var x = 10
# block:
# var x = something(x)
# The generated C code will be:
# NI x;
# x = 10;
# {
# NI x;
# x = something(x); // Oops, x is already shadowed here
# }
# Right now, we work-around by not keeping the original name
# of the shadowed variable, but we can do better - we can
# create an alternative reference to it in the outer scope and
# use that in the inner scope.
#
# about isCKeyword:
# nimrod variable names can be C keywords.
# We need to avoid such names in the generated code.
# XXX: Study whether mangleName is called just once per variable.
# Otherwise, there might be better place to do this.
#
# about sfGlobal:
# This seems to be harder - a top level extern variable from
# another modules can have the same name as a local one.
# Maybe we should just implement sfShadowed for them too.
#
# about skForVar:
# These are not properly scoped now - we need to add blocks
# around for loops in transf
if keepOrigName:
result = s.name.s.toRope
else:
app(result, toRope(mangle(s.name.s)))
app(result, "_")
app(result, toRope(s.id))
else:
app(result, toRope(mangle(s.name.s)))
app(result, "_")
app(result, toRope(s.id))
s.loc.r = result
proc isCompileTimeOnly(t: PType): bool =

View File

@@ -151,7 +151,7 @@ proc appcg(m: BModule, s: TCFileSection, frmt: TFormatStr,
proc appcg(p: BProc, s: TCProcSection, frmt: TFormatStr,
args: openarray[PRope]) =
app(p.s[s], ropecg(p.module, frmt, args))
app(p.s(s), ropecg(p.module, frmt, args))
proc safeLineNm(info: TLineInfo): int =
result = toLinenumber(info)
@@ -168,14 +168,14 @@ proc genCLineDir(r: var PRope, info: TLineInfo) =
proc genLineDir(p: BProc, t: PNode) =
var line = t.info.safeLineNm
genCLineDir(p.s[cpsStmts], t.info.toFullPath, line)
genCLineDir(p.s(cpsStmts), t.info.toFullPath, line)
if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and
(p.prc == nil or sfPure notin p.prc.flags):
appcg(p, cpsStmts, "#endb($1);$n", [toRope(line)])
elif ({optLineTrace, optStackTrace} * p.Options ==
{optLineTrace, optStackTrace}) and
(p.prc == nil or sfPure notin p.prc.flags):
appf(p.s[cpsStmts], "F.line = $1;F.filename = $2;$n",
appf(p.s(cpsStmts), "F.line = $1;F.filename = $2;$n",
[toRope(line), makeCString(toFilename(t.info).extractFilename)])
include "ccgtypes.nim"
@@ -229,45 +229,37 @@ proc isComplexValueType(t: PType): bool {.inline.} =
result = t.kind in {tyArray, tyArrayConstr, tySet, tyTuple, tyObject} or
(t.kind == tyProc and t.callConv == ccClosure)
proc zeroVar(p: BProc, loc: TLoc, containsGCref: bool) =
proc resetLoc(p: BProc, loc: var TLoc) =
let containsGcRef = containsGarbageCollectedRef(loc.t)
if not isComplexValueType(skipTypes(loc.t, abstractVarRange)):
if containsGcref and p.WithInLoop > 0:
appf(p.s[cpsInit], "$1 = 0;$n", [rdLoc(loc)])
if containsGcRef:
var nilLoc: TLoc
initLoc(nilLoc, locTemp, loc.t, onStack)
nilLoc.r = toRope("NIM_NIL")
# puts ``unsureAsgnRef`` etc to ``p.s[cpsStmts]``:
genRefAssign(p, loc, nilLoc, {afSrcIsNil})
else:
appf(p.s[cpsStmts], "$1 = 0;$n", [rdLoc(loc)])
appf(p.s(cpsStmts), "$1 = 0;$n", [rdLoc(loc)])
else:
if containsGcref and p.WithInLoop > 0:
appf(p.s[cpsInit], "memset((void*)$1, 0, sizeof($2));$n",
[addrLoc(loc), rdLoc(loc)])
genObjectInit(p, cpsInit, loc.t, loc, true)
appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
[addrLoc(loc), genTypeInfo(p.module, loc.t)])
if loc.s != OnStack:
appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
[addrLoc(loc), genTypeInfo(p.module, loc.t)])
# XXX: generated reset procs should not touch the m_type
# field, so disabling this should be safe:
genObjectInit(p, cpsStmts, loc.t, loc, true)
else:
appf(p.s[cpsStmts], "memset((void*)$1, 0, sizeof($2));$n",
[addrLoc(loc), rdLoc(loc)])
appf(p.s(cpsStmts), "memset((void*)$1, 0, sizeof($2));$n",
[addrLoc(loc), rdLoc(loc)])
# XXX: We can be extra clever here and call memset only
# on the bytes following the m_type field?
genObjectInit(p, cpsStmts, loc.t, loc, true)
proc zeroTemp(p: BProc, loc: TLoc) =
proc constructLoc(p: BProc, loc: TLoc, section = cpsStmts) =
if not isComplexValueType(skipTypes(loc.t, abstractVarRange)):
appf(p.s[cpsStmts], "$1 = 0;$n", [rdLoc(loc)])
when false:
var nilLoc: TLoc
initLoc(nilLoc, locTemp, loc.t, onStack)
nilLoc.r = toRope("NIM_NIL")
# puts ``unsureAsgnRef`` etc to ``p.s[cpsStmts]``:
genRefAssign(p, loc, nilLoc, {afSrcIsNil})
appf(p.s(section), "$1 = 0;$n", [rdLoc(loc)])
else:
appf(p.s[cpsStmts], "memset((void*)$1, 0, sizeof($2));$n",
[addrLoc(loc), rdLoc(loc)])
# XXX no object init necessary for temporaries?
when false:
appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n",
[addrLoc(loc), genTypeInfo(p.module, loc.t)])
appf(p.s(section), "memset((void*)$1, 0, sizeof($2));$n",
[addrLoc(loc), rdLoc(loc)])
genObjectInit(p, section, loc.t, loc, true)
proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
if sfNoInit notin v.flags:
@@ -279,11 +271,13 @@ proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
# ``var v = X()`` gets transformed into ``X(&v)``.
# Nowadays the logic in ccgcalls deals with this case however.
if not immediateAsgn:
zeroVar(p, v.loc, containsGarbageCollectedRef(v.typ))
proc initTemp(p: BProc, tmp: var TLoc) =
constructLoc(p, v.loc)
proc initTemp(p: BProc, tmp: var TLoc) =
# XXX: This is still suspicious.
# Objects should always be constructed?
if containsGarbageCollectedRef(tmp.t) or isInvalidReturnType(tmp.t):
zeroTemp(p, tmp)
constructLoc(p, tmp)
proc getTemp(p: BProc, t: PType, result: var TLoc) =
inc(p.labels)
@@ -291,7 +285,7 @@ proc getTemp(p: BProc, t: PType, result: var TLoc) =
result.r = con("%LOC", toRope(p.labels))
else:
result.r = con("LOC", toRope(p.labels))
appf(p.s[cpsLocals], "$1 $2;$n", [getTypeDesc(p.module, t), result.r])
appf(p.s(cpsLocals), "$1 $2;$n", [getTypeDesc(p.module, t), result.r])
result.k = locTemp
result.a = - 1
result.t = getUniqueType(t)
@@ -361,7 +355,7 @@ proc allocParam(p: BProc, s: PSym) =
var tmp = con("%LOC", toRope(p.labels))
incl(s.loc.flags, lfParamCopy)
incl(s.loc.flags, lfIndirect)
appf(p.s[cpsInit], "$1 = alloca $3$n" & "store $3 $2, $3* $1$n",
appf(p.s(cpsInit), "$1 = alloca $3$n" & "store $3 $2, $3* $1$n",
[tmp, s.loc.r, getTypeDesc(p.module, s.loc.t)])
s.loc.r = tmp
@@ -371,7 +365,7 @@ proc localDebugInfo(p: BProc, s: PSym) =
if skipTypes(s.typ, abstractVar).kind == tyOpenArray: return
var a = con("&", s.loc.r)
if (s.kind == skParam) and ccgIntroducedPtr(s): a = s.loc.r
appf(p.s[cpsInit],
appf(p.s(cpsInit),
"F.s[$1].address = (void*)$3; F.s[$1].typ = $4; F.s[$1].name = $2;$n",
[toRope(p.frameLen), makeCString(normalize(s.name.s)), a,
genTypeInfo(p.module, s.loc.t)])
@@ -384,13 +378,13 @@ proc assignLocalVar(p: BProc, s: PSym) =
if s.loc.k == locNone:
fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), OnStack)
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
app(p.s[cpsLocals], getTypeDesc(p.module, s.loc.t))
if sfRegister in s.flags: app(p.s[cpsLocals], " register")
app(p.s(cpsLocals), getTypeDesc(p.module, s.loc.t))
if sfRegister in s.flags: app(p.s(cpsLocals), " register")
#elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
# app(p.s[cpsLocals], " GC_GUARD")
if (sfVolatile in s.flags) or (p.nestedTryStmts.len > 0):
app(p.s[cpsLocals], " volatile")
appf(p.s[cpsLocals], " $1;$n", [s.loc.r])
app(p.s(cpsLocals), " volatile")
appf(p.s(cpsLocals), " $1;$n", [s.loc.r])
localDebugInfo(p, s)
include ccgthreadvars
@@ -410,7 +404,7 @@ proc assignGlobalVar(p: BProc, s: PSym) =
appf(p.module.s[cfsVars], " $1;$n", [s.loc.r])
if p.withinLoop > 0:
# fixes tests/run/tzeroarray:
initLocalVar(p, s, false)
resetLoc(p, s.loc)
if p.module.module.options * {optStackTrace, optEndb} ==
{optStackTrace, optEndb}:
appcg(p.module, p.module.s[cfsDebugInit],
@@ -433,7 +427,7 @@ proc getLabel(p: BProc): TLabel =
result = con("LA", toRope(p.labels))
proc fixLabel(p: BProc, labl: TLabel) =
appf(p.s[cpsStmts], "$1: ;$n", [labl])
appf(p.s(cpsStmts), "$1: ;$n", [labl])
proc genVarPrototype(m: BModule, sym: PSym)
proc requestConstImpl(p: BProc, sym: PSym)
@@ -481,9 +475,9 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
var p = newProc(nil, m)
var dest: TLoc
initLocExpr(p, lib.path, dest)
app(m.s[cfsVars], p.s[cpsLocals])
app(m.s[cfsDynLibInit], p.s[cpsInit])
app(m.s[cfsDynLibInit], p.s[cpsStmts])
app(m.s[cfsVars], p.s(cpsLocals))
app(m.s[cfsDynLibInit], p.s(cpsInit))
app(m.s[cfsDynLibInit], p.s(cpsStmts))
appcg(m, m.s[cfsDynLibInit],
"if (!($1 = #nimLoadLibrary($2))) #nimLoadLibraryError($2);$n",
[tmp, rdLoc(dest)])
@@ -551,13 +545,13 @@ proc getFrameDecl(p: BProc) =
[toRope(p.frameLen)])
else:
slots = nil
appff(p.s[cpsLocals], "volatile struct {TFrame* prev;" &
appff(p.s(cpsLocals), "volatile struct {TFrame* prev;" &
"NCSTRING procname;NI line;NCSTRING filename;" &
"NI len;$n$1} F;$n",
"%TF = type {%TFrame*, i8*, %NI, %NI$1}$n" &
"%F = alloca %TF$n", [slots])
inc(p.labels)
prepend(p.s[cpsInit], ropeff("F.len = $1;$n",
prepend(p.s(cpsInit), ropeff("F.len = $1;$n",
"%LOC$2 = getelementptr %TF %F, %NI 4$n" &
"store %NI $1, %NI* %LOC$2$n", [toRope(p.frameLen), toRope(p.labels)]))
@@ -613,32 +607,32 @@ proc genProcAux(m: BModule, prc: PSym) =
var generatedProc: PRope
if sfPure in prc.flags:
generatedProc = ropeff("$1 {$n$2$3$4}$n", "define $1 {$n$2$3$4}$n",
[header, p.s[cpsLocals], p.s[cpsInit], p.s[cpsStmts]])
[header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)])
else:
generatedProc = ropeff("$1 {$n", "define $1 {$n", [header])
app(generatedProc, initGCFrame(p))
if optStackTrace in prc.options:
getFrameDecl(p)
app(generatedProc, p.s[cpsLocals])
app(generatedProc, p.s(cpsLocals))
var procname = CStringLit(p, generatedProc, prc.name.s)
var filename = CStringLit(p, generatedProc, toFilename(prc.info))
app(generatedProc, initFrame(p, procname, filename))
else:
app(generatedProc, p.s[cpsLocals])
app(generatedProc, p.s(cpsLocals))
if (optProfiler in prc.options) and (gCmd != cmdCompileToLLVM):
if gProcProfile >= 64 * 1024:
InternalError(prc.info, "too many procedures for profiling")
discard cgsym(m, "profileData")
appf(p.s[cpsLocals], "ticks NIM_profilingStart;$n")
appf(p.s(cpsLocals), "ticks NIM_profilingStart;$n")
if prc.loc.a < 0:
appf(m.s[cfsDebugInit], "profileData[$1].procname = $2;$n", [
toRope(gProcProfile),
makeCString(prc.name.s)])
prc.loc.a = gProcProfile
inc(gProcProfile)
prepend(p.s[cpsInit], ropef("NIM_profilingStart = getticks();$n"))
app(generatedProc, p.s[cpsInit])
app(generatedProc, p.s[cpsStmts])
prepend(p.s(cpsInit), ropef("NIM_profilingStart = getticks();$n"))
app(generatedProc, p.s(cpsInit))
app(generatedProc, p.s(cpsStmts))
if p.beforeRetNeeded: appf(generatedProc, "BeforeRet: $n;")
app(generatedProc, deinitGCFrame(p))
if optStackTrace in prc.options: app(generatedProc, deinitFrame(p))
@@ -858,8 +852,8 @@ proc genInitCode(m: BModule) =
app(prc, initGCFrame(m.initProc))
app(prc, genSectionStart(cpsLocals))
app(prc, m.initProc.s[cpsLocals])
app(prc, m.preInitProc.s[cpsLocals])
app(prc, m.initProc.s(cpsLocals))
app(prc, m.preInitProc.s(cpsLocals))
app(prc, genSectionEnd(cpsLocals))
app(prc, genSectionStart(cfsTypeInit1))
@@ -876,13 +870,13 @@ proc genInitCode(m: BModule) =
app(prc, genSectionEnd(i))
app(prc, genSectionStart(cpsInit))
app(prc, m.preInitProc.s[cpsInit])
app(prc, m.initProc.s[cpsInit])
app(prc, m.preInitProc.s(cpsInit))
app(prc, m.initProc.s(cpsInit))
app(prc, genSectionEnd(cpsInit))
app(prc, genSectionStart(cpsStmts))
app(prc, m.preInitProc.s[cpsStmts])
app(prc, m.initProc.s[cpsStmts])
app(prc, m.preInitProc.s(cpsStmts))
app(prc, m.initProc.s(cpsStmts))
if optStackTrace in m.initProc.options and not m.PreventStackTrace:
app(prc, deinitFrame(m.initProc))
app(prc, genSectionEnd(cpsStmts))

View File

@@ -48,13 +48,14 @@ type
TCProcSections* = array[TCProcSection, PRope] # represents a generated C proc
BModule* = ref TCGen
BProc* = ref TCProc
TBlock{.final.} = object
TBlock*{.final.} = object
id*: int # the ID of the label; positive means that it
# has been used (i.e. the label should be emitted)
label*: PRope # generated text for the label
# nil if label is not used
nestedTryStmts*: int # how many try statements is it nested into
sections*: TCProcSections # the code beloging
TCProc{.final.} = object # represents C proc that is currently generated
s*: TCProcSections # the procs sections; short name for readability
prc*: PSym # the Nimrod proc that this C proc belongs to
BeforeRetNeeded*: bool # true iff 'BeforeRet' label for proc is needed
ThreadVarAccessed*: bool # true if the proc already accessed some threadvar
@@ -64,6 +65,8 @@ type
# before 'break'|'return'
labels*: Natural # for generating unique labels in the C proc
blocks*: seq[TBlock] # nested blocks
breakIdx*: int # the block that will be exited
# with a regular break
options*: TOptions # options that should be used for code
# generation; this is the same as prc.options
# unless prc == nil
@@ -113,6 +116,13 @@ var
gForwardedProcsCounter*: int = 0
gNimDat*: BModule # generated global data
proc s*(p: BProc, s: TCProcSection): var PRope {.inline.} =
# section in the current block
result = p.blocks[p.blocks.len - 1].sections[s]
proc procSec*(p: BProc, s: TCProcSection): var PRope {.inline.} =
# top level proc sections
result = p.blocks[0].sections[s]
proc newProc*(prc: PSym, module: BModule): BProc =
new(result)
@@ -120,6 +130,6 @@ proc newProc*(prc: PSym, module: BModule): BProc =
result.module = module
if prc != nil: result.options = prc.options
else: result.options = gOptions
result.blocks = @[]
newSeq(result.blocks, 1)
result.nestedTryStmts = @[]

View File

@@ -113,7 +113,9 @@ var
gKeepComments*: bool = true # whether the parser needs to keep comments
implicitImports*: seq[string] = @[] # modules that are to be implicitly imported
implicitIncludes*: seq[string] = @[] # modules that are to be implicitly included
const oKeepVariableNames* = true
proc mainCommandArg*: string =
## This is intended for commands like check or parse
## which will work on the main project file unless

View File

@@ -62,6 +62,7 @@ type
AmbiguousSymbols*: TIntSet # ids of all ambiguous symbols (cannot
# store this info in the syms themselves!)
InGenericContext*: int # > 0 if we are in a generic
InUnrolledContext*: int # > 0 if we are unrolling a loop
converters*: TSymSeq # sequence of converters
optionStack*: TLinkedList
libs*: TLinkedList # all libs used by this module

View File

@@ -15,6 +15,8 @@
# So we have to eval templates/macros right here so that symbol
# lookup can be accurate.
# included from sem.nim
type
TSemGenericFlag = enum
withinBind, withinTypeDesc

View File

@@ -50,8 +50,8 @@ proc semIf(c: PContext, n: PNode): PNode =
case it.kind
of nkElifBranch:
checkSonsLen(it, 2)
openScope(c.tab)
it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0]))
openScope(c.tab)
it.sons[1] = semStmt(c, it.sons[1])
closeScope(c.tab)
of nkElse:
@@ -216,7 +216,13 @@ proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode =
result = result.sons[1]
elif not sameType(result.typ, typ):
changeType(result, typ)
proc findShadowedVar(c: PContext, v: PSym): PSym =
for i in countdown(c.tab.tos - 2, 0):
let shadowed = StrTableGet(c.tab.stack[i], v.name)
if shadowed != nil and shadowed.kind in skLocalVars:
return shadowed
proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
if isTopLevel(c):
result = semIdentWithPragma(c, kind, n, {sfExported})
@@ -267,6 +273,11 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
for j in countup(0, length-3):
var v = semIdentDef(c, a.sons[j], symkind)
addInterfaceDecl(c, v)
when oKeepVariableNames:
if c.InUnrolledContext > 0: v.flags.incl(sfShadowed)
else:
let shadowed = findShadowedVar(c, v)
if shadowed != nil: shadowed.flags.incl(sfShadowed)
if def != nil and def.kind != nkEmpty:
# this is only needed for the evaluation pass:
v.ast = def
@@ -392,7 +403,9 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
openScope(c.tab)
var body = transfFieldLoopBody(loopBody, n, tupleTypeA, i,
ord(m==mFieldPairs))
inc c.InUnrolledContext
stmts.add(SemStmt(c, body))
dec c.InUnrolledContext
closeScope(c.tab)
Dec(c.p.nestedLoopCounter)
var b = newNodeI(nkBreakStmt, n.info)

View File

@@ -38,8 +38,8 @@ type
wMagic, wThread, wFinal, wProfiler, wObjChecks,
wImmediate, wImportCpp, wImportObjC,
wImportCompilerProc,
wImportc, wExportc, wExtern, wIncompleteStruct,
wAlign, wNodecl, wPure, wVolatile, wRegister, wSideeffect, wHeader,
wImportc, wExportc, wIncompleteStruct,
wAlign, wNodecl, wPure, wSideeffect, wHeader,
wNosideeffect, wNoreturn, wMerge, wLib, wDynlib, wCompilerproc, wProcVar,
wFatal, wError, wWarning, wHint, wLine, wPush, wPop, wDefine, wUndef,
wLinedir, wStacktrace, wLinetrace, wLink, wCompile,
@@ -58,13 +58,36 @@ type
wWatchPoint, wSubsChar,
wAcyclic, wShallow, wUnroll, wLinearScanEnd,
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar, wEmit, wNoStackFrame,
wImplicitStatic, wGlobal
wImplicitStatic, wGlobal,
wAuto, wBool, wCatch, wChar, wClass,
wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast,
wExplicit, wExtern, wFalse, wFloat, wFriend,
wGoto, wInt, wLong, wMutable, wNamespace, wNew, wOperator,
wPrivate, wProtected, wPublic, wRegister, wReinterpret_cast,
wShort, wSigned, wSizeof, wStatic_cast, wStruct, wSwitch,
wThis, wThrow, wTrue, wTypedef, wTypeid, wTypename,
wUnion, wUnsigned, wUsing, wVirtual, wVoid, wVolatile, wWchar_t,
wAlignas, wAlignof, wConstexpr, wDecltype, wNullptr, wNoexcept,
wThread_local, wStatic_assert, wChar16_t, wChar32_t,
TSpecialWords* = set[TSpecialWord]
const
oprLow* = ord(wColon)
oprHigh* = ord(wDotDot)
nimKeywordsLow* = ord(wAsm)
nimKeywordsHigh* = ord(wYield)
cppKeywordsLow* = ord(wAuto)
cppKeywordsHigh* = ord(wChar32_t)
cppNimSharedKeywords* = {
wAsm, wBreak, wCase, wConst, wContinue, wDo, wElse, wEnum, wExport,
wFor, wIf, wReturn, wStatic, wTemplate, wTry, wWhile }
specialWords*: array[low(TSpecialWord)..high(TSpecialWord), string] = ["",
"addr", "and", "as", "asm", "atomic",
@@ -86,14 +109,14 @@ const
"magic", "thread", "final", "profiler", "objchecks",
"immediate", "importcpp", "importobjc",
"importcompilerproc", "importc", "exportc", "extern", "incompletestruct",
"align", "nodecl", "pure", "volatile", "register", "sideeffect",
"importcompilerproc", "importc", "exportc", "incompletestruct",
"align", "nodecl", "pure", "sideeffect",
"header", "nosideeffect", "noreturn", "merge", "lib", "dynlib",
"compilerproc", "procvar", "fatal", "error", "warning", "hint", "line",
"push", "pop", "define", "undef", "linedir", "stacktrace", "linetrace",
"link", "compile", "linksys", "deprecated", "varargs",
"byref", "callconv", "breakpoint", "debugger", "nimcall", "stdcall",
"cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "closure",
"cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "closure",
"noconv", "on", "off", "checks", "rangechecks", "boundchecks",
"overflowchecks", "nilchecks",
"floatchecks", "nanchecks", "infchecks",
@@ -107,7 +130,22 @@ const
"watchpoint",
"subschar", "acyclic", "shallow", "unroll", "linearscanend",
"write", "putenv", "prependenv", "appendenv", "threadvar", "emit",
"nostackframe", "implicitstatic", "global"]
"nostackframe", "implicitstatic", "global",
"auto", "bool", "catch", "char", "class",
"const_cast", "default", "delete", "double",
"dynamic_cast", "explicit", "extern", "false",
"float", "friend", "goto", "int", "long", "mutable",
"namespace", "new", "operator",
"private", "protected", "public", "register", "reinterpret_cast",
"short", "signed", "sizeof", "static_cast", "struct", "switch",
"this", "throw", "true", "typedef", "typeid",
"typename", "union", "unsigned", "using", "virtual", "void", "volatile",
"wchar_t",
"alignas", "alignof", "constexpr", "decltype", "nullptr", "noexcept",
"thread_local", "static_assert", "char16_t", "char32_t",
]
proc findStr*(a: openarray[string], s: string): int =
for i in countup(low(a), high(a)):

View File

@@ -29,19 +29,14 @@ template colorOp(op: expr) {.immediate.} =
extract(a, ar, ag, ab)
extract(b, br, bg, bb)
result = rawRGB(op(ar, br), op(ag, bg), op(ab, bb))
template satPlus(a, b: expr): expr =
# saturated plus:
block:
var result = a +% b
if result > 255: result = 255
result
template satMinus(a, b: expr): expr =
block:
var result = a -% b
if result < 0: result = 0
result
proc satPlus(a, b: int): int {.inline.} =
result = a +% b
if result > 255: result = 255
proc satMinus(a, b: int): int {.inline.} =
result = a -% b
if result < 0: result = 0
proc `+`*(a, b: TColor): TColor =
## adds two colors: This uses saturated artithmetic, so that each color

View File

@@ -1738,7 +1738,6 @@ when isMainModule:
else:
assert false
var matches: array[0..5, string]
if match("abcdefg", peg"c {d} ef {g}", matches, 2):
assert matches[0] == "d"
assert matches[1] == "g"

View File

@@ -1593,12 +1593,12 @@ proc echo*[Ty](x: openarray[Ty]) {.magic: "Echo", noSideEffect.}
template newException*(exceptn: typeDesc, message: string): expr =
## creates an exception object of type ``exceptn`` and sets its ``msg`` field
## to `message`. Returns the new exception object.
block: # open a new scope
var
e: ref exceptn
new(e)
e.msg = message
e
# block: # open a new scope
var
e: ref exceptn
new(e)
e.msg = message
e
when not defined(EcmaScript) and not defined(NimrodVM):
{.push stack_trace: off.}

View File

@@ -1734,7 +1734,6 @@ when isMainModule:
else:
doAssert false
var matches: array[0..5, string]
if match("abcdefg", peg"c {d} ef {g}", matches, 2):
doAssert matches[0] == "d"
doAssert matches[1] == "g"

View File

@@ -10,20 +10,21 @@
## Include for the tester that contains test suites that test special features
## of the compiler.
# included from tester.nim
# ---------------- ROD file tests ---------------------------------------------
const
rodfilesDir = "tests/rodfiles"
nimcacheDir = rodfilesDir / "nimcache"
proc delNimCache() =
let dir = rodfilesDir / "nimcache"
proc delNimCache() =
try:
removeDir(dir)
removeDir(nimcacheDir)
except EOS:
echo "[Warning] could not delete: ", dir
echo "[Warning] could not delete: ", nimcacheDir
proc plusCache(options: string): string = return options &
" --symbolFiles:on --nimcache:./nimcache"
" --symbolFiles:on --nimcache:" & nimcacheDir
proc runRodFiles(r: var TResults, options: string) =
template test(filename: expr): stmt =