mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-03 02:18:00 +00:00
don't generate memset calls for C++ objects
This commit is contained in:
@@ -33,7 +33,7 @@ proc isAssignedImmediately(n: PNode): bool {.inline.} =
|
||||
return false
|
||||
result = true
|
||||
|
||||
proc genVarTuple(p: BProc, n: PNode) =
|
||||
proc genVarTuple(p: BProc, n: PNode) =
|
||||
var tup, field: TLoc
|
||||
if n.kind != nkVarTuple: internalError(n.info, "genVarTuple")
|
||||
var L = sonsLen(n)
|
||||
@@ -49,7 +49,7 @@ proc genVarTuple(p: BProc, n: PNode) =
|
||||
genLineDir(p, n)
|
||||
initLocExpr(p, n.sons[L-1], tup)
|
||||
var t = tup.t.getUniqueType
|
||||
for i in countup(0, L-3):
|
||||
for i in countup(0, L-3):
|
||||
var v = n.sons[i].sym
|
||||
if sfCompileTime in v.flags: continue
|
||||
if sfGlobal in v.flags:
|
||||
@@ -60,11 +60,11 @@ proc genVarTuple(p: BProc, n: PNode) =
|
||||
assignLocalVar(p, v)
|
||||
initLocalVar(p, v, immediateAsgn=isAssignedImmediately(n[L-1]))
|
||||
initLoc(field, locExpr, t.sons[i], tup.s)
|
||||
if t.kind == tyTuple:
|
||||
if t.kind == tyTuple:
|
||||
field.r = ropef("$1.Field$2", [rdLoc(tup), toRope(i)])
|
||||
else:
|
||||
else:
|
||||
if t.n.sons[i].kind != nkSym: internalError(n.info, "genVarTuple")
|
||||
field.r = ropef("$1.$2",
|
||||
field.r = ropef("$1.$2",
|
||||
[rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)])
|
||||
putLocIntoDest(p, v.loc, field)
|
||||
|
||||
@@ -117,7 +117,7 @@ proc endBlock(p: BProc, blockEnd: PRope) =
|
||||
line(p, cpsStmts, blockEnd)
|
||||
|
||||
proc endBlock(p: BProc) =
|
||||
let topBlock = p.blocks.len - 1
|
||||
let topBlock = p.blocks.len - 1
|
||||
var blockEnd = if p.blocks[topBlock].label != nil:
|
||||
rfmt(nil, "} $1: ;$n", p.blocks[topBlock].label)
|
||||
else:
|
||||
@@ -190,10 +190,10 @@ proc genSingleVar(p: BProc, a: PNode) =
|
||||
targetProc = p.module.preInitProc
|
||||
assignGlobalVar(targetProc, v)
|
||||
# XXX: be careful here.
|
||||
# Global variables should not be zeromem-ed within loops
|
||||
# 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
|
||||
# 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):
|
||||
@@ -229,10 +229,10 @@ proc genClosureVar(p: BProc, a: PNode) =
|
||||
genLineDir(p, a)
|
||||
loadInto(p, a.sons[0], a.sons[2], v)
|
||||
|
||||
proc genVarStmt(p: BProc, n: PNode) =
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
proc genVarStmt(p: BProc, n: PNode) =
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
var a = n.sons[i]
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if a.kind == nkCommentStmt: continue
|
||||
if a.kind == nkIdentDefs:
|
||||
# can be a lifted var nowadays ...
|
||||
if a.sons[0].kind == nkSym:
|
||||
@@ -242,12 +242,12 @@ proc genVarStmt(p: BProc, n: PNode) =
|
||||
else:
|
||||
genVarTuple(p, a)
|
||||
|
||||
proc genConstStmt(p: BProc, t: PNode) =
|
||||
for i in countup(0, sonsLen(t) - 1):
|
||||
proc genConstStmt(p: BProc, t: PNode) =
|
||||
for i in countup(0, sonsLen(t) - 1):
|
||||
var it = t.sons[i]
|
||||
if it.kind == nkCommentStmt: continue
|
||||
if it.kind == nkCommentStmt: continue
|
||||
if it.kind != nkConstDef: internalError(t.info, "genConstStmt")
|
||||
var c = it.sons[0].sym
|
||||
var c = it.sons[0].sym
|
||||
if c.typ.containsCompileTimeOnly: continue
|
||||
if sfFakeConst in c.flags:
|
||||
genSingleVar(p, it)
|
||||
@@ -274,9 +274,9 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) =
|
||||
getTemp(p, n.typ, d)
|
||||
genLineDir(p, n)
|
||||
let lend = getLabel(p)
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
let it = n.sons[i]
|
||||
if it.len == 2:
|
||||
if it.len == 2:
|
||||
when newScopeForIf: startBlock(p)
|
||||
initLocExprSingleUse(p, it.sons[0], a)
|
||||
lelse = getLabel(p)
|
||||
@@ -303,13 +303,13 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) =
|
||||
if sonsLen(n) > 1: fixLabel(p, lend)
|
||||
|
||||
|
||||
proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
|
||||
proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
|
||||
# Called by return and break stmts.
|
||||
# Deals with issues faced when jumping out of try/except/finally stmts,
|
||||
|
||||
var stack: seq[PNode]
|
||||
newSeq(stack, 0)
|
||||
|
||||
|
||||
var alreadyPoppedCnt = p.inExceptBlock
|
||||
for i in countup(1, howManyTrys):
|
||||
if not p.module.compileToCpp:
|
||||
@@ -327,11 +327,11 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
|
||||
# Find finally-stmt for this try-stmt
|
||||
# and generate a copy of its sons
|
||||
var finallyStmt = lastSon(tryStmt)
|
||||
if finallyStmt.kind == nkFinally:
|
||||
if finallyStmt.kind == nkFinally:
|
||||
genStmts(p, finallyStmt.sons[0])
|
||||
|
||||
# push old elements again:
|
||||
for i in countdown(howManyTrys-1, 0):
|
||||
for i in countdown(howManyTrys-1, 0):
|
||||
p.nestedTryStmts.add(stack[i])
|
||||
|
||||
if not p.module.compileToCpp:
|
||||
@@ -344,14 +344,14 @@ proc genReturnStmt(p: BProc, t: PNode) =
|
||||
p.beforeRetNeeded = true
|
||||
genLineDir(p, t)
|
||||
if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0])
|
||||
blockLeaveActions(p,
|
||||
blockLeaveActions(p,
|
||||
howManyTrys = p.nestedTryStmts.len,
|
||||
howManyExcepts = p.inExceptBlock)
|
||||
if (p.finallySafePoints.len > 0):
|
||||
# If we're in a finally block, and we came here by exception
|
||||
# consume it before we return.
|
||||
var safePoint = p.finallySafePoints[p.finallySafePoints.len-1]
|
||||
linefmt(p, cpsStmts, "if ($1.status != 0) #popCurrentException();$n", safePoint)
|
||||
linefmt(p, cpsStmts, "if ($1.status != 0) #popCurrentException();$n", safePoint)
|
||||
lineF(p, cpsStmts, "goto BeforeRet;$n", [])
|
||||
|
||||
proc genComputedGoto(p: BProc; n: PNode) =
|
||||
@@ -387,7 +387,7 @@ proc genComputedGoto(p: BProc; n: PNode) =
|
||||
let topBlock = p.blocks.len-1
|
||||
let oldBody = p.blocks[topBlock].sections[cpsStmts]
|
||||
p.blocks[topBlock].sections[cpsStmts] = nil
|
||||
|
||||
|
||||
for j in casePos+1 .. <n.len: genStmts(p, n.sons[j])
|
||||
let tailB = p.blocks[topBlock].sections[cpsStmts]
|
||||
|
||||
@@ -402,7 +402,7 @@ proc genComputedGoto(p: BProc; n: PNode) =
|
||||
initLocExpr(p, caseStmt.sons[0], a)
|
||||
# first goto:
|
||||
lineF(p, cpsStmts, "goto *$#[$#];$n", tmp, a.rdLoc)
|
||||
|
||||
|
||||
for i in 1 .. <caseStmt.len:
|
||||
startBlock(p)
|
||||
let it = caseStmt.sons[i]
|
||||
@@ -426,7 +426,7 @@ proc genComputedGoto(p: BProc; n: PNode) =
|
||||
proc genWhileStmt(p: BProc, t: PNode) =
|
||||
# we don't generate labels here as for example GCC would produce
|
||||
# significantly worse code
|
||||
var
|
||||
var
|
||||
a: TLoc
|
||||
labl: TLabel
|
||||
assert(sonsLen(t) == 2)
|
||||
@@ -437,7 +437,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
|
||||
p.breakIdx = startBlock(p, "while (1) {$n")
|
||||
p.blocks[p.breakIdx].isLoop = true
|
||||
initLocExpr(p, t.sons[0], a)
|
||||
if (t.sons[0].kind != nkIntLit) or (t.sons[0].intVal == 0):
|
||||
if (t.sons[0].kind != nkIntLit) or (t.sons[0].intVal == 0):
|
||||
let label = assignLabel(p.blocks[p.breakIdx])
|
||||
lineF(p, cpsStmts, "if (!$1) goto $2;$n", [rdLoc(a), label])
|
||||
var loopBody = t.sons[1]
|
||||
@@ -483,23 +483,23 @@ proc genParForStmt(p: BProc, t: PNode) =
|
||||
let call = t.sons[1]
|
||||
initLocExpr(p, call.sons[1], rangeA)
|
||||
initLocExpr(p, call.sons[2], rangeB)
|
||||
|
||||
|
||||
lineF(p, cpsStmts, "#pragma omp parallel for $4$n" &
|
||||
"for ($1 = $2; $1 <= $3; ++$1)",
|
||||
"for ($1 = $2; $1 <= $3; ++$1)",
|
||||
forLoopVar.loc.rdLoc,
|
||||
rangeA.rdLoc, rangeB.rdLoc,
|
||||
call.sons[3].getStr.toRope)
|
||||
|
||||
|
||||
p.breakIdx = startBlock(p)
|
||||
p.blocks[p.breakIdx].isLoop = true
|
||||
genStmts(p, t.sons[2])
|
||||
endBlock(p)
|
||||
|
||||
dec(p.withinLoop)
|
||||
|
||||
proc genBreakStmt(p: BProc, t: PNode) =
|
||||
|
||||
proc genBreakStmt(p: BProc, t: PNode) =
|
||||
var idx = p.breakIdx
|
||||
if t.sons[0].kind != nkEmpty:
|
||||
if t.sons[0].kind != nkEmpty:
|
||||
# named break?
|
||||
assert(t.sons[0].kind == nkSym)
|
||||
var sym = t.sons[0].sym
|
||||
@@ -511,13 +511,13 @@ proc genBreakStmt(p: BProc, t: PNode) =
|
||||
if idx < 0 or not p.blocks[idx].isLoop:
|
||||
internalError(t.info, "no loop to break")
|
||||
let label = assignLabel(p.blocks[idx])
|
||||
blockLeaveActions(p,
|
||||
blockLeaveActions(p,
|
||||
p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts,
|
||||
p.inExceptBlock - p.blocks[idx].nestedExceptStmts)
|
||||
genLineDir(p, t)
|
||||
lineF(p, cpsStmts, "goto $1;$n", [label])
|
||||
|
||||
proc getRaiseFrmt(p: BProc): string =
|
||||
proc getRaiseFrmt(p: BProc): string =
|
||||
if p.module.compileToCpp:
|
||||
result = "throw NimException($1, $2);$n"
|
||||
elif getCompilerProc("Exception") != nil:
|
||||
@@ -532,7 +532,7 @@ proc genRaiseStmt(p: BProc, t: PNode) =
|
||||
var finallyBlock = p.nestedTryStmts[p.nestedTryStmts.len - 1].lastSon
|
||||
if finallyBlock.kind == nkFinally:
|
||||
genSimpleBlock(p, finallyBlock.sons[0])
|
||||
if t.sons[0].kind != nkEmpty:
|
||||
if t.sons[0].kind != nkEmpty:
|
||||
var a: TLoc
|
||||
initLocExpr(p, t.sons[0], a)
|
||||
var e = rdLoc(a)
|
||||
@@ -547,23 +547,23 @@ proc genRaiseStmt(p: BProc, t: PNode) =
|
||||
else:
|
||||
linefmt(p, cpsStmts, "#reraiseException();$n")
|
||||
|
||||
proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
|
||||
rangeFormat, eqFormat: TFormatStr, labl: TLabel) =
|
||||
var
|
||||
proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
|
||||
rangeFormat, eqFormat: TFormatStr, labl: TLabel) =
|
||||
var
|
||||
x, y: TLoc
|
||||
var length = sonsLen(b)
|
||||
for i in countup(0, length - 2):
|
||||
if b.sons[i].kind == nkRange:
|
||||
for i in countup(0, length - 2):
|
||||
if b.sons[i].kind == nkRange:
|
||||
initLocExpr(p, b.sons[i].sons[0], x)
|
||||
initLocExpr(p, b.sons[i].sons[1], y)
|
||||
lineCg(p, cpsStmts, rangeFormat,
|
||||
lineCg(p, cpsStmts, rangeFormat,
|
||||
[rdCharLoc(e), rdCharLoc(x), rdCharLoc(y), labl])
|
||||
else:
|
||||
else:
|
||||
initLocExpr(p, b.sons[i], x)
|
||||
lineCg(p, cpsStmts, eqFormat, [rdCharLoc(e), rdCharLoc(x), labl])
|
||||
|
||||
proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc,
|
||||
labId, until: int): TLabel =
|
||||
proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc,
|
||||
labId, until: int): TLabel =
|
||||
var lend = getLabel(p)
|
||||
for i in 1..until:
|
||||
lineF(p, cpsStmts, "LA$1: ;$n", [toRope(labId + i)])
|
||||
@@ -596,23 +596,23 @@ proc genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc,
|
||||
else:
|
||||
result = genCaseSecondPass(p, t, d, labId, until)
|
||||
|
||||
proc genCaseGeneric(p: BProc, t: PNode, d: var TLoc,
|
||||
rangeFormat, eqFormat: TFormatStr) =
|
||||
proc genCaseGeneric(p: BProc, t: PNode, d: var TLoc,
|
||||
rangeFormat, eqFormat: TFormatStr) =
|
||||
var a: TLoc
|
||||
initLocExpr(p, t.sons[0], a)
|
||||
var lend = genIfForCaseUntil(p, t, d, rangeFormat, eqFormat, sonsLen(t)-1, a)
|
||||
fixLabel(p, lend)
|
||||
|
||||
proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel,
|
||||
branches: var openArray[PRope]) =
|
||||
proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel,
|
||||
branches: var openArray[PRope]) =
|
||||
var x: TLoc
|
||||
var length = sonsLen(b)
|
||||
for i in countup(0, length - 2):
|
||||
for i in countup(0, length - 2):
|
||||
assert(b.sons[i].kind != nkRange)
|
||||
initLocExpr(p, b.sons[i], x)
|
||||
assert(b.sons[i].kind in {nkStrLit..nkTripleStrLit})
|
||||
var j = int(hashString(b.sons[i].strVal) and high(branches))
|
||||
appcg(p.module, branches[j], "if (#eqStrings($1, $2)) goto $3;$n",
|
||||
appcg(p.module, branches[j], "if (#eqStrings($1, $2)) goto $3;$n",
|
||||
[rdLoc(e), rdLoc(x), labl])
|
||||
|
||||
proc genStringCase(p: BProc, t: PNode, d: var TLoc) =
|
||||
@@ -627,35 +627,35 @@ proc genStringCase(p: BProc, t: PNode, d: var TLoc) =
|
||||
var a: TLoc
|
||||
initLocExpr(p, t.sons[0], a) # fist pass: gnerate ifs+goto:
|
||||
var labId = p.labels
|
||||
for i in countup(1, sonsLen(t) - 1):
|
||||
for i in countup(1, sonsLen(t) - 1):
|
||||
inc(p.labels)
|
||||
if t.sons[i].kind == nkOfBranch:
|
||||
genCaseStringBranch(p, t.sons[i], a, con("LA", toRope(p.labels)),
|
||||
if t.sons[i].kind == nkOfBranch:
|
||||
genCaseStringBranch(p, t.sons[i], a, con("LA", toRope(p.labels)),
|
||||
branches)
|
||||
else:
|
||||
else:
|
||||
# else statement: nothing to do yet
|
||||
# but we reserved a label, which we use later
|
||||
discard
|
||||
linefmt(p, cpsStmts, "switch (#hashString($1) & $2) {$n",
|
||||
linefmt(p, cpsStmts, "switch (#hashString($1) & $2) {$n",
|
||||
rdLoc(a), toRope(bitMask))
|
||||
for j in countup(0, high(branches)):
|
||||
if branches[j] != nil:
|
||||
lineF(p, cpsStmts, "case $1: $n$2break;$n",
|
||||
lineF(p, cpsStmts, "case $1: $n$2break;$n",
|
||||
[intLiteral(j), branches[j]])
|
||||
lineF(p, cpsStmts, "}$n") # else statement:
|
||||
if t.sons[sonsLen(t)-1].kind != nkOfBranch:
|
||||
lineF(p, cpsStmts, "goto LA$1;$n", [toRope(p.labels)])
|
||||
if t.sons[sonsLen(t)-1].kind != nkOfBranch:
|
||||
lineF(p, cpsStmts, "goto LA$1;$n", [toRope(p.labels)])
|
||||
# third pass: generate statements
|
||||
var lend = genCaseSecondPass(p, t, d, labId, sonsLen(t)-1)
|
||||
fixLabel(p, lend)
|
||||
else:
|
||||
genCaseGeneric(p, t, d, "", "if (#eqStrings($1, $2)) goto $3;$n")
|
||||
|
||||
proc branchHasTooBigRange(b: PNode): bool =
|
||||
for i in countup(0, sonsLen(b)-2):
|
||||
|
||||
proc branchHasTooBigRange(b: PNode): bool =
|
||||
for i in countup(0, sonsLen(b)-2):
|
||||
# last son is block
|
||||
if (b.sons[i].kind == nkRange) and
|
||||
b.sons[i].sons[1].intVal - b.sons[i].sons[0].intVal > RangeExpandLimit:
|
||||
b.sons[i].sons[1].intVal - b.sons[i].sons[0].intVal > RangeExpandLimit:
|
||||
return true
|
||||
|
||||
proc ifSwitchSplitPoint(p: BProc, n: PNode): int =
|
||||
@@ -664,21 +664,21 @@ proc ifSwitchSplitPoint(p: BProc, n: PNode): int =
|
||||
var stmtBlock = lastSon(branch)
|
||||
if stmtBlock.stmtsContainPragma(wLinearScanEnd):
|
||||
result = i
|
||||
elif hasSwitchRange notin CC[cCompiler].props:
|
||||
if branch.kind == nkOfBranch and branchHasTooBigRange(branch):
|
||||
elif hasSwitchRange notin CC[cCompiler].props:
|
||||
if branch.kind == nkOfBranch and branchHasTooBigRange(branch):
|
||||
result = i
|
||||
|
||||
proc genCaseRange(p: BProc, branch: PNode) =
|
||||
var length = branch.len
|
||||
for j in 0 .. length-2:
|
||||
if branch[j].kind == nkRange:
|
||||
if hasSwitchRange in CC[cCompiler].props:
|
||||
for j in 0 .. length-2:
|
||||
if branch[j].kind == nkRange:
|
||||
if hasSwitchRange in CC[cCompiler].props:
|
||||
lineF(p, cpsStmts, "case $1 ... $2:$n", [
|
||||
genLiteral(p, branch[j][0]),
|
||||
genLiteral(p, branch[j][0]),
|
||||
genLiteral(p, branch[j][1])])
|
||||
else:
|
||||
else:
|
||||
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)])
|
||||
inc(v.intVal)
|
||||
else:
|
||||
@@ -687,53 +687,53 @@ proc genCaseRange(p: BProc, branch: PNode) =
|
||||
proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =
|
||||
# analyse 'case' statement:
|
||||
var splitPoint = ifSwitchSplitPoint(p, n)
|
||||
|
||||
|
||||
# generate if part (might be empty):
|
||||
var a: TLoc
|
||||
initLocExpr(p, n.sons[0], a)
|
||||
var lend = if splitPoint > 0: genIfForCaseUntil(p, n, d,
|
||||
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
|
||||
|
||||
|
||||
# generate switch part (might be empty):
|
||||
if splitPoint+1 < n.len:
|
||||
lineF(p, cpsStmts, "switch ($1) {$n", [rdCharLoc(a)])
|
||||
var hasDefault = false
|
||||
for i in splitPoint+1 .. < n.len:
|
||||
for i in splitPoint+1 .. < n.len:
|
||||
var branch = n[i]
|
||||
if branch.kind == nkOfBranch:
|
||||
if branch.kind == nkOfBranch:
|
||||
genCaseRange(p, branch)
|
||||
else:
|
||||
else:
|
||||
# else part of case statement:
|
||||
lineF(p, cpsStmts, "default:$n")
|
||||
hasDefault = true
|
||||
exprBlock(p, branch.lastSon, d)
|
||||
lineF(p, cpsStmts, "break;$n")
|
||||
if (hasAssume in CC[cCompiler].props) and not hasDefault:
|
||||
if (hasAssume in CC[cCompiler].props) and not hasDefault:
|
||||
lineF(p, cpsStmts, "default: __assume(0);$n")
|
||||
lineF(p, cpsStmts, "}$n")
|
||||
if lend != nil: fixLabel(p, lend)
|
||||
|
||||
proc genCase(p: BProc, t: PNode, d: var TLoc) =
|
||||
|
||||
proc genCase(p: BProc, t: PNode, d: var TLoc) =
|
||||
genLineDir(p, t)
|
||||
if not isEmptyType(t.typ) and d.k == locNone:
|
||||
getTemp(p, t.typ, d)
|
||||
case skipTypes(t.sons[0].typ, abstractVarRange).kind
|
||||
of tyString:
|
||||
genStringCase(p, t, d)
|
||||
of tyFloat..tyFloat128:
|
||||
genCaseGeneric(p, t, d, "if ($1 >= $2 && $1 <= $3) goto $4;$n",
|
||||
of tyFloat..tyFloat128:
|
||||
genCaseGeneric(p, t, d, "if ($1 >= $2 && $1 <= $3) goto $4;$n",
|
||||
"if ($1 == $2) goto $3;$n")
|
||||
else:
|
||||
genOrdinalCase(p, t, d)
|
||||
|
||||
proc hasGeneralExceptSection(t: PNode): bool =
|
||||
|
||||
proc hasGeneralExceptSection(t: PNode): bool =
|
||||
var length = sonsLen(t)
|
||||
var i = 1
|
||||
while (i < length) and (t.sons[i].kind == nkExceptBranch):
|
||||
while (i < length) and (t.sons[i].kind == nkExceptBranch):
|
||||
var blen = sonsLen(t.sons[i])
|
||||
if blen == 1:
|
||||
if blen == 1:
|
||||
return true
|
||||
inc(i)
|
||||
result = false
|
||||
@@ -798,7 +798,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||
lineF(p, cpsStmts, "if ($1) ", [orExpr])
|
||||
exprBlock(p, t.sons[i].sons[blen-1], d)
|
||||
inc(i)
|
||||
|
||||
|
||||
# reraise the exception if there was no catch all
|
||||
# and none of the handlers matched
|
||||
if not catchAllPresent:
|
||||
@@ -811,15 +811,15 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||
|
||||
line(p, cpsStmts, ~"throw;$n")
|
||||
endBlock(p)
|
||||
|
||||
|
||||
lineF(p, cpsStmts, "}$n") # end of catch block
|
||||
dec p.inExceptBlock
|
||||
|
||||
|
||||
discard pop(p.nestedTryStmts)
|
||||
if (i < length) and (t.sons[i].kind == nkFinally):
|
||||
genSimpleBlock(p, t.sons[i].sons[0])
|
||||
|
||||
proc genTry(p: BProc, t: PNode, d: var TLoc) =
|
||||
|
||||
proc genTry(p: BProc, t: PNode, d: var TLoc) =
|
||||
# code to generate:
|
||||
#
|
||||
# XXX: There should be a standard dispatch algorithm
|
||||
@@ -841,7 +841,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
|
||||
# clearException();
|
||||
# }
|
||||
# }
|
||||
# {
|
||||
# {
|
||||
# /* finally: */
|
||||
# printf('fin!\n');
|
||||
# }
|
||||
@@ -927,14 +927,14 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): PRope =
|
||||
res.add(rdLoc(a).ropeToStr)
|
||||
else:
|
||||
var r = sym.loc.r
|
||||
if r == nil:
|
||||
if r == nil:
|
||||
# if no name has already been given,
|
||||
# it doesn't matter much:
|
||||
r = mangleName(sym)
|
||||
sym.loc.r = r # but be consequent!
|
||||
res.add(r.ropeToStr)
|
||||
else: internalError(t.sons[i].info, "genAsmOrEmitStmt()")
|
||||
|
||||
|
||||
if isAsmStmt and hasGnuAsm in CC[cCompiler].props:
|
||||
for x in splitLines(res):
|
||||
var j = 0
|
||||
@@ -952,40 +952,43 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): PRope =
|
||||
res.add(tnl)
|
||||
result = res.toRope
|
||||
|
||||
proc genAsmStmt(p: BProc, t: PNode) =
|
||||
proc genAsmStmt(p: BProc, t: PNode) =
|
||||
assert(t.kind == nkAsmStmt)
|
||||
genLineDir(p, t)
|
||||
var s = genAsmOrEmitStmt(p, t, isAsmStmt=true)
|
||||
# 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
|
||||
# work:
|
||||
if p.prc == nil:
|
||||
# top level asm statement?
|
||||
appf(p.module.s[cfsProcHeaders], CC[cCompiler].asmStmtFrmt, [s])
|
||||
else:
|
||||
lineF(p, cpsStmts, CC[cCompiler].asmStmtFrmt, [s])
|
||||
|
||||
proc genEmit(p: BProc, t: PNode) =
|
||||
proc genEmit(p: BProc, t: PNode) =
|
||||
genLineDir(p, t)
|
||||
var s = genAsmOrEmitStmt(p, t.sons[1])
|
||||
if p.prc == nil:
|
||||
if p.prc == nil:
|
||||
# top level emit pragma?
|
||||
app(p.module.s[cfsProcHeaders], s)
|
||||
else:
|
||||
line(p, cpsStmts, s)
|
||||
|
||||
var
|
||||
var
|
||||
breakPointId: int = 0
|
||||
gBreakpoints: PRope # later the breakpoints are inserted into the main proc
|
||||
|
||||
proc genBreakPoint(p: BProc, t: PNode) =
|
||||
proc genBreakPoint(p: BProc, t: PNode) =
|
||||
var name: string
|
||||
if optEndb in p.options:
|
||||
if t.kind == nkExprColonExpr:
|
||||
if t.kind == nkExprColonExpr:
|
||||
assert(t.sons[1].kind in {nkStrLit..nkTripleStrLit})
|
||||
name = normalize(t.sons[1].strVal)
|
||||
else:
|
||||
else:
|
||||
inc(breakPointId)
|
||||
name = "bp" & $breakPointId
|
||||
genLineDir(p, t) # BUGFIX
|
||||
appcg(p.module, gBreakpoints,
|
||||
appcg(p.module, gBreakpoints,
|
||||
"#dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [
|
||||
toRope(toLinenumber(t.info)), makeCString(toFilename(t.info)),
|
||||
makeCString(name)])
|
||||
@@ -1006,14 +1009,14 @@ proc genPragma(p: BProc, n: PNode) =
|
||||
of wEmit: genEmit(p, it)
|
||||
of wBreakpoint: genBreakPoint(p, it)
|
||||
of wWatchPoint: genWatchpoint(p, it)
|
||||
of wInjectStmt:
|
||||
of wInjectStmt:
|
||||
var p = newProc(nil, p.module)
|
||||
p.options = p.options - {optLineTrace, optStackTrace}
|
||||
genStmts(p, it.sons[1])
|
||||
p.module.injectStmt = p.s(cpsStmts)
|
||||
else: discard
|
||||
|
||||
proc fieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool =
|
||||
proc fieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool =
|
||||
if optFieldCheck in p.options:
|
||||
var le = asgn.sons[0]
|
||||
if le.kind == nkCheckedFieldExpr:
|
||||
@@ -1021,23 +1024,23 @@ proc fieldDiscriminantCheckNeeded(p: BProc, asgn: PNode): bool =
|
||||
result = sfDiscriminant in field.flags
|
||||
elif le.kind == nkDotExpr:
|
||||
var field = le.sons[1].sym
|
||||
result = sfDiscriminant in field.flags
|
||||
result = sfDiscriminant in field.flags
|
||||
|
||||
proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
|
||||
field: PSym) =
|
||||
proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
|
||||
field: PSym) =
|
||||
var t = skipTypes(objtype, abstractVar)
|
||||
assert t.kind == tyObject
|
||||
discard genTypeInfo(p.module, t)
|
||||
var L = lengthOrd(field.typ)
|
||||
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))
|
||||
lineCg(p, cpsStmts,
|
||||
"#FieldDiscriminantCheck((NI)(NU)($1), (NI)(NU)($2), $3, $4);$n",
|
||||
[rdLoc(a), rdLoc(tmp), discriminatorTableName(p.module, t, field),
|
||||
intLiteral(L+1)])
|
||||
|
||||
proc asgnFieldDiscriminant(p: BProc, e: PNode) =
|
||||
proc asgnFieldDiscriminant(p: BProc, e: PNode) =
|
||||
var a, tmp: TLoc
|
||||
var dotExpr = e.sons[0]
|
||||
var d: PSym
|
||||
@@ -1047,8 +1050,8 @@ proc asgnFieldDiscriminant(p: BProc, e: PNode) =
|
||||
expr(p, e.sons[1], tmp)
|
||||
genDiscriminantCheck(p, a, tmp, dotExpr.sons[0].typ, dotExpr.sons[1].sym)
|
||||
genAssignment(p, a, tmp, {})
|
||||
|
||||
proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
|
||||
|
||||
proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
|
||||
genLineDir(p, e)
|
||||
if not fieldDiscriminantCheckNeeded(p, e):
|
||||
var a: TLoc
|
||||
@@ -1059,7 +1062,7 @@ proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
|
||||
else:
|
||||
asgnFieldDiscriminant(p, e)
|
||||
|
||||
proc genStmts(p: BProc, t: PNode) =
|
||||
proc genStmts(p: BProc, t: PNode) =
|
||||
var a: TLoc
|
||||
expr(p, t, a)
|
||||
internalAssert a.k in {locNone, locTemp, locLocalVar}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
## This module implements the C code generator.
|
||||
|
||||
import
|
||||
import
|
||||
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp,
|
||||
options, intsets,
|
||||
nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os,
|
||||
@@ -25,7 +25,7 @@ when options.hasTinyCBackend:
|
||||
var
|
||||
generatedHeader: BModule
|
||||
|
||||
proc addForwardedProc(m: BModule, prc: PSym) =
|
||||
proc addForwardedProc(m: BModule, prc: PSym) =
|
||||
m.forwardedProcs.add(prc)
|
||||
inc(gForwardedProcsCounter)
|
||||
|
||||
@@ -33,7 +33,7 @@ proc getCgenModule(s: PSym): BModule =
|
||||
result = if s.position >= 0 and s.position < gModules.len: gModules[s.position]
|
||||
else: nil
|
||||
|
||||
proc findPendingModule(m: BModule, s: PSym): BModule =
|
||||
proc findPendingModule(m: BModule, s: PSym): BModule =
|
||||
var ms = getModule(s)
|
||||
result = gModules[ms.position]
|
||||
|
||||
@@ -41,21 +41,21 @@ proc emitLazily(s: PSym): bool {.inline.} =
|
||||
result = optDeadCodeElim in gGlobalOptions or
|
||||
sfDeadCodeElim in getModule(s).flags
|
||||
|
||||
proc initLoc(result: var TLoc, k: TLocKind, typ: PType, s: TStorageLoc) =
|
||||
proc initLoc(result: var TLoc, k: TLocKind, typ: PType, s: TStorageLoc) =
|
||||
result.k = k
|
||||
result.s = s
|
||||
result.t = typ
|
||||
result.r = nil
|
||||
result.flags = {}
|
||||
|
||||
proc fillLoc(a: var TLoc, k: TLocKind, typ: PType, r: PRope, s: TStorageLoc) =
|
||||
proc fillLoc(a: var TLoc, k: TLocKind, typ: PType, r: PRope, s: TStorageLoc) =
|
||||
# fills the loc if it is not already initialized
|
||||
if a.k == locNone:
|
||||
if a.k == locNone:
|
||||
a.k = k
|
||||
a.t = typ
|
||||
a.s = s
|
||||
if a.r == nil: a.r = r
|
||||
|
||||
|
||||
proc isSimpleConst(typ: PType): bool =
|
||||
let t = skipTypes(typ, abstractVar)
|
||||
result = t.kind notin
|
||||
@@ -67,43 +67,43 @@ proc useStringh(m: BModule) =
|
||||
m.includesStringh = true
|
||||
discard lists.includeStr(m.headerFiles, "<string.h>")
|
||||
|
||||
proc useHeader(m: BModule, sym: PSym) =
|
||||
if lfHeader in sym.loc.flags:
|
||||
proc useHeader(m: BModule, sym: PSym) =
|
||||
if lfHeader in sym.loc.flags:
|
||||
assert(sym.annex != nil)
|
||||
discard lists.includeStr(m.headerFiles, getStr(sym.annex.path))
|
||||
|
||||
proc cgsym(m: BModule, name: string): PRope
|
||||
|
||||
proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope =
|
||||
proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope =
|
||||
var i = 0
|
||||
var length = len(frmt)
|
||||
result = nil
|
||||
var num = 0
|
||||
while i < length:
|
||||
if frmt[i] == '$':
|
||||
while i < length:
|
||||
if frmt[i] == '$':
|
||||
inc(i) # skip '$'
|
||||
case frmt[i]
|
||||
of '$':
|
||||
of '$':
|
||||
app(result, "$")
|
||||
inc(i)
|
||||
of '#':
|
||||
of '#':
|
||||
inc(i)
|
||||
app(result, args[num])
|
||||
inc(num)
|
||||
of '0'..'9':
|
||||
of '0'..'9':
|
||||
var j = 0
|
||||
while true:
|
||||
while true:
|
||||
j = (j * 10) + ord(frmt[i]) - ord('0')
|
||||
inc(i)
|
||||
if i >= length or not (frmt[i] in {'0'..'9'}): break
|
||||
if i >= length or not (frmt[i] in {'0'..'9'}): break
|
||||
num = j
|
||||
if j > high(args) + 1:
|
||||
if j > high(args) + 1:
|
||||
internalError("ropes: invalid format string $" & $j)
|
||||
app(result, args[j-1])
|
||||
of 'n':
|
||||
if optLineDir notin gOptions: app(result, rnl)
|
||||
inc(i)
|
||||
of 'N':
|
||||
of 'N':
|
||||
app(result, rnl)
|
||||
inc(i)
|
||||
else: internalError("ropes: invalid format string $" & frmt[i])
|
||||
@@ -117,37 +117,37 @@ proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope =
|
||||
elif frmt[i] == '#' and frmt[i+1] == '$':
|
||||
inc(i, 2)
|
||||
var j = 0
|
||||
while frmt[i] in Digits:
|
||||
while frmt[i] in Digits:
|
||||
j = (j * 10) + ord(frmt[i]) - ord('0')
|
||||
inc(i)
|
||||
app(result, cgsym(m, args[j-1].ropeToStr))
|
||||
var start = i
|
||||
while i < length:
|
||||
while i < length:
|
||||
if frmt[i] != '$' and frmt[i] != '#': inc(i)
|
||||
else: break
|
||||
if i - 1 >= start:
|
||||
else: break
|
||||
if i - 1 >= start:
|
||||
app(result, substr(frmt, start, i - 1))
|
||||
|
||||
template rfmt(m: BModule, fmt: string, args: varargs[PRope]): expr =
|
||||
ropecg(m, fmt, args)
|
||||
|
||||
proc appcg(m: BModule, c: var PRope, frmt: TFormatStr,
|
||||
args: varargs[PRope]) =
|
||||
proc appcg(m: BModule, c: var PRope, frmt: TFormatStr,
|
||||
args: varargs[PRope]) =
|
||||
app(c, ropecg(m, frmt, args))
|
||||
|
||||
proc appcg(m: BModule, s: TCFileSection, frmt: TFormatStr,
|
||||
args: varargs[PRope]) =
|
||||
proc appcg(m: BModule, s: TCFileSection, frmt: TFormatStr,
|
||||
args: varargs[PRope]) =
|
||||
app(m.s[s], ropecg(m, frmt, args))
|
||||
|
||||
proc appcg(p: BProc, s: TCProcSection, frmt: TFormatStr,
|
||||
args: varargs[PRope]) =
|
||||
proc appcg(p: BProc, s: TCProcSection, frmt: TFormatStr,
|
||||
args: varargs[PRope]) =
|
||||
app(p.s(s), ropecg(p.module, frmt, args))
|
||||
|
||||
var indent = "\t".toRope
|
||||
proc indentLine(p: BProc, r: PRope): PRope =
|
||||
result = r
|
||||
for i in countup(0, p.blocks.len-1): prepend(result, indent)
|
||||
|
||||
|
||||
proc line(p: BProc, s: TCProcSection, r: PRope) =
|
||||
app(p.s(s), indentLine(p, r))
|
||||
|
||||
@@ -180,7 +180,7 @@ proc genCLineDir(r: var PRope, filename: string, line: int) =
|
||||
appf(r, "$N#line $2 $1$N",
|
||||
[toRope(makeSingleLineCString(filename)), toRope(line)])
|
||||
|
||||
proc genCLineDir(r: var PRope, info: TLineInfo) =
|
||||
proc genCLineDir(r: var PRope, info: TLineInfo) =
|
||||
genCLineDir(r, info.toFullPath, info.safeLineNm)
|
||||
|
||||
proc genLineDir(p: BProc, t: PNode) =
|
||||
@@ -261,7 +261,9 @@ proc isComplexValueType(t: PType): bool {.inline.} =
|
||||
|
||||
proc resetLoc(p: BProc, loc: var TLoc) =
|
||||
let containsGcRef = containsGarbageCollectedRef(loc.t)
|
||||
if not isComplexValueType(skipTypes(loc.t, abstractVarRange)):
|
||||
let typ = skipTypes(loc.t, abstractVarRange)
|
||||
if isImportedCppType(typ): return
|
||||
if not isComplexValueType(typ):
|
||||
if containsGcRef:
|
||||
var nilLoc: TLoc
|
||||
initLoc(nilLoc, locTemp, loc.t, OnStack)
|
||||
@@ -282,35 +284,37 @@ proc resetLoc(p: BProc, loc: var TLoc) =
|
||||
useStringh(p.module)
|
||||
linefmt(p, cpsStmts, "memset((void*)$1, 0, sizeof($2));$n",
|
||||
addrLoc(loc), rdLoc(loc))
|
||||
# XXX: We can be extra clever here and call memset only
|
||||
# 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 constructLoc(p: BProc, loc: TLoc, isTemp = false) =
|
||||
if not isComplexValueType(skipTypes(loc.t, abstractRange)):
|
||||
let typ = skipTypes(loc.t, abstractRange)
|
||||
if not isComplexValueType(typ):
|
||||
linefmt(p, cpsStmts, "$1 = 0;$n", rdLoc(loc))
|
||||
else:
|
||||
if not isTemp or containsGarbageCollectedRef(loc.t):
|
||||
# don't use memset for temporary values for performance if we can
|
||||
# avoid it:
|
||||
useStringh(p.module)
|
||||
linefmt(p, cpsStmts, "memset((void*)$1, 0, sizeof($2));$n",
|
||||
addrLoc(loc), rdLoc(loc))
|
||||
if not isImportedCppType(typ):
|
||||
useStringh(p.module)
|
||||
linefmt(p, cpsStmts, "memset((void*)$1, 0, sizeof($2));$n",
|
||||
addrLoc(loc), rdLoc(loc))
|
||||
genObjectInit(p, cpsStmts, loc.t, loc, true)
|
||||
|
||||
proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
|
||||
if sfNoInit notin v.flags:
|
||||
# we know it is a local variable and thus on the stack!
|
||||
# If ``not immediateAsgn`` it is not initialized in a binding like
|
||||
# ``var v = X`` and thus we need to init it.
|
||||
# ``var v = X`` and thus we need to init it.
|
||||
# If ``v`` contains a GC-ref we may pass it to ``unsureAsgnRef`` somehow
|
||||
# which requires initialization. However this can really only happen if
|
||||
# ``var v = X()`` gets transformed into ``X(&v)``.
|
||||
# ``var v = X()`` gets transformed into ``X(&v)``.
|
||||
# Nowadays the logic in ccgcalls deals with this case however.
|
||||
if not immediateAsgn:
|
||||
constructLoc(p, v.loc)
|
||||
|
||||
proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) =
|
||||
proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) =
|
||||
inc(p.labels)
|
||||
result.r = con("LOC", toRope(p.labels))
|
||||
linefmt(p, cpsLocals, "$1 $2;$n", getTypeDesc(p.module, t), result.r)
|
||||
@@ -353,10 +357,10 @@ proc deinitGCFrame(p: BProc): PRope =
|
||||
if p.gcFrameId > 0:
|
||||
result = ropecg(p.module,
|
||||
"if (((NU)&GCFRAME) < 4096) #nimGCFrame(&GCFRAME);$n")
|
||||
|
||||
proc allocParam(p: BProc, s: PSym) =
|
||||
|
||||
proc allocParam(p: BProc, s: PSym) =
|
||||
assert(s.kind == skParam)
|
||||
if lfParamCopy notin s.loc.flags:
|
||||
if lfParamCopy notin s.loc.flags:
|
||||
inc(p.labels)
|
||||
var tmp = con("%LOC", toRope(p.labels))
|
||||
incl(s.loc.flags, lfParamCopy)
|
||||
@@ -365,8 +369,8 @@ proc allocParam(p: BProc, s: PSym) =
|
||||
[tmp, s.loc.r, getTypeDesc(p.module, s.loc.t)])
|
||||
s.loc.r = tmp
|
||||
|
||||
proc localDebugInfo(p: BProc, s: PSym) =
|
||||
if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return
|
||||
proc localDebugInfo(p: BProc, s: PSym) =
|
||||
if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return
|
||||
# XXX work around a bug: No type information for open arrays possible:
|
||||
if skipTypes(s.typ, abstractVar).kind in {tyOpenArray, tyVarargs}: return
|
||||
var a = con("&", s.loc.r)
|
||||
@@ -379,7 +383,7 @@ proc localDebugInfo(p: BProc, s: PSym) =
|
||||
inc p.blocks[p.blocks.len-1].frameLen
|
||||
|
||||
proc localVarDecl(p: BProc; s: PSym): PRope =
|
||||
if s.loc.k == locNone:
|
||||
if s.loc.k == locNone:
|
||||
fillLoc(s.loc, locLocalVar, s.typ, mangleName(s), OnStack)
|
||||
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
|
||||
result = getTypeDesc(p.module, s.loc.t)
|
||||
@@ -406,22 +410,22 @@ include ccgthreadvars
|
||||
proc varInDynamicLib(m: BModule, sym: PSym)
|
||||
proc mangleDynLibProc(sym: PSym): PRope
|
||||
|
||||
proc assignGlobalVar(p: BProc, s: PSym) =
|
||||
if s.loc.k == locNone:
|
||||
proc assignGlobalVar(p: BProc, s: PSym) =
|
||||
if s.loc.k == locNone:
|
||||
fillLoc(s.loc, locGlobalVar, s.typ, mangleName(s), OnHeap)
|
||||
|
||||
|
||||
if lfDynamicLib in s.loc.flags:
|
||||
var q = findPendingModule(p.module, s)
|
||||
if q != nil and not containsOrIncl(q.declaredThings, s.id):
|
||||
if q != nil and not containsOrIncl(q.declaredThings, s.id):
|
||||
varInDynamicLib(q, s)
|
||||
else:
|
||||
s.loc.r = mangleDynLibProc(s)
|
||||
return
|
||||
useHeader(p.module, s)
|
||||
if lfNoDecl in s.loc.flags: return
|
||||
if sfThread in s.flags:
|
||||
if sfThread in s.flags:
|
||||
declareThreadVar(p.module, s, sfImportc in s.flags)
|
||||
else:
|
||||
else:
|
||||
var decl: PRope = nil
|
||||
var td = getTypeDesc(p.module, s.loc.t)
|
||||
if s.constraint.isNil:
|
||||
@@ -437,25 +441,25 @@ proc assignGlobalVar(p: BProc, s: PSym) =
|
||||
# fixes tests/run/tzeroarray:
|
||||
resetLoc(p, s.loc)
|
||||
if p.module.module.options * {optStackTrace, optEndb} ==
|
||||
{optStackTrace, optEndb}:
|
||||
appcg(p.module, p.module.s[cfsDebugInit],
|
||||
"#dbgRegisterGlobal($1, &$2, $3);$n",
|
||||
[makeCString(normalize(s.owner.name.s & '.' & s.name.s)),
|
||||
{optStackTrace, optEndb}:
|
||||
appcg(p.module, p.module.s[cfsDebugInit],
|
||||
"#dbgRegisterGlobal($1, &$2, $3);$n",
|
||||
[makeCString(normalize(s.owner.name.s & '.' & s.name.s)),
|
||||
s.loc.r, genTypeInfo(p.module, s.typ)])
|
||||
|
||||
proc assignParam(p: BProc, s: PSym) =
|
||||
|
||||
proc assignParam(p: BProc, s: PSym) =
|
||||
assert(s.loc.r != nil)
|
||||
localDebugInfo(p, s)
|
||||
|
||||
proc fillProcLoc(sym: PSym) =
|
||||
if sym.loc.k == locNone:
|
||||
proc fillProcLoc(sym: PSym) =
|
||||
if sym.loc.k == locNone:
|
||||
fillLoc(sym.loc, locProc, sym.typ, mangleName(sym), OnStack)
|
||||
|
||||
proc getLabel(p: BProc): TLabel =
|
||||
|
||||
proc getLabel(p: BProc): TLabel =
|
||||
inc(p.labels)
|
||||
result = con("LA", toRope(p.labels))
|
||||
|
||||
proc fixLabel(p: BProc, labl: TLabel) =
|
||||
proc fixLabel(p: BProc, labl: TLabel) =
|
||||
lineF(p, cpsStmts, "$1: ;$n", [labl])
|
||||
|
||||
proc genVarPrototype(m: BModule, sym: PSym)
|
||||
@@ -487,12 +491,12 @@ include ccgcalls, "ccgstmts.nim", "ccgexprs.nim"
|
||||
|
||||
proc isGetProcAddr(lib: PLib): bool =
|
||||
let n = lib.path
|
||||
result = n.kind in nkCallKinds and n.typ != nil and
|
||||
result = n.kind in nkCallKinds and n.typ != nil and
|
||||
n.typ.kind in {tyPointer, tyProc}
|
||||
|
||||
proc loadDynamicLib(m: BModule, lib: PLib) =
|
||||
proc loadDynamicLib(m: BModule, lib: PLib) =
|
||||
assert(lib != nil)
|
||||
if not lib.generated:
|
||||
if not lib.generated:
|
||||
lib.generated = true
|
||||
var tmp = getGlobalTempName()
|
||||
assert(lib.name == nil)
|
||||
@@ -504,14 +508,14 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
|
||||
if gVerbosity >= 2:
|
||||
msgWriteln("Dependency: " & lib.path.strVal)
|
||||
var loadlib: PRope = nil
|
||||
for i in countup(0, high(s)):
|
||||
for i in countup(0, high(s)):
|
||||
inc(m.labels)
|
||||
if i > 0: app(loadlib, "||")
|
||||
appcg(m, loadlib, "($1 = #nimLoadLibrary((#NimStringDesc*) &$2))$n",
|
||||
appcg(m, loadlib, "($1 = #nimLoadLibrary((#NimStringDesc*) &$2))$n",
|
||||
[tmp, getStrLit(m, s[i])])
|
||||
appcg(m, m.s[cfsDynLibInit],
|
||||
"if (!($1)) #nimLoadLibraryError((#NimStringDesc*) &$2);$n",
|
||||
[loadlib, getStrLit(m, lib.path.strVal)])
|
||||
appcg(m, m.s[cfsDynLibInit],
|
||||
"if (!($1)) #nimLoadLibraryError((#NimStringDesc*) &$2);$n",
|
||||
[loadlib, getStrLit(m, lib.path.strVal)])
|
||||
else:
|
||||
var p = newProc(nil, m)
|
||||
p.options = p.options - {optStackTrace, optEndb}
|
||||
@@ -520,20 +524,20 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
|
||||
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",
|
||||
appcg(m, m.s[cfsDynLibInit],
|
||||
"if (!($1 = #nimLoadLibrary($2))) #nimLoadLibraryError($2);$n",
|
||||
[tmp, rdLoc(dest)])
|
||||
|
||||
|
||||
if lib.name == nil: internalError("loadDynamicLib")
|
||||
|
||||
|
||||
proc mangleDynLibProc(sym: PSym): PRope =
|
||||
if sfCompilerProc in sym.flags:
|
||||
if sfCompilerProc in sym.flags:
|
||||
# NOTE: sym.loc.r is the external name!
|
||||
result = toRope(sym.name.s)
|
||||
else:
|
||||
result = ropef("Dl_$1", [toRope(sym.id)])
|
||||
|
||||
proc symInDynamicLib(m: BModule, sym: PSym) =
|
||||
|
||||
proc symInDynamicLib(m: BModule, sym: PSym) =
|
||||
var lib = sym.annex
|
||||
let isCall = isGetProcAddr(lib)
|
||||
var extname = sym.loc.r
|
||||
@@ -565,13 +569,13 @@ proc symInDynamicLib(m: BModule, sym: PSym) =
|
||||
else:
|
||||
internalError(sym.info, "wrong index: " & idx)
|
||||
else:
|
||||
appcg(m, m.s[cfsDynLibInit],
|
||||
"\t$1 = ($2) #nimGetProcAddr($3, $4);$n",
|
||||
[tmp, getTypeDesc(m, sym.typ),
|
||||
appcg(m, m.s[cfsDynLibInit],
|
||||
"\t$1 = ($2) #nimGetProcAddr($3, $4);$n",
|
||||
[tmp, getTypeDesc(m, sym.typ),
|
||||
lib.name, makeCString(ropeToStr(extname))])
|
||||
appf(m.s[cfsVars], "$2 $1;$n", [sym.loc.r, getTypeDesc(m, sym.loc.t)])
|
||||
|
||||
proc varInDynamicLib(m: BModule, sym: PSym) =
|
||||
proc varInDynamicLib(m: BModule, sym: PSym) =
|
||||
var lib = sym.annex
|
||||
var extname = sym.loc.r
|
||||
loadDynamicLib(m, lib)
|
||||
@@ -579,9 +583,9 @@ proc varInDynamicLib(m: BModule, sym: PSym) =
|
||||
var tmp = mangleDynLibProc(sym)
|
||||
sym.loc.r = tmp # from now on we only need the internal name
|
||||
inc(m.labels, 2)
|
||||
appcg(m, m.s[cfsDynLibInit],
|
||||
"$1 = ($2*) #nimGetProcAddr($3, $4);$n",
|
||||
[tmp, getTypeDesc(m, sym.typ),
|
||||
appcg(m, m.s[cfsDynLibInit],
|
||||
"$1 = ($2*) #nimGetProcAddr($3, $4);$n",
|
||||
[tmp, getTypeDesc(m, sym.typ),
|
||||
lib.name, makeCString(ropeToStr(extname))])
|
||||
appf(m.s[cfsVars], "$2* $1;$n",
|
||||
[sym.loc.r, getTypeDesc(m, sym.loc.t)])
|
||||
@@ -590,9 +594,9 @@ proc symInDynamicLibPartial(m: BModule, sym: PSym) =
|
||||
sym.loc.r = mangleDynLibProc(sym)
|
||||
sym.typ.sym = nil # generate a new name
|
||||
|
||||
proc cgsym(m: BModule, name: string): PRope =
|
||||
proc cgsym(m: BModule, name: string): PRope =
|
||||
var sym = magicsys.getCompilerProc(name)
|
||||
if sym != nil:
|
||||
if sym != nil:
|
||||
case sym.kind
|
||||
of skProc, skMethod, skConverter, skIterators: genProc(m, sym)
|
||||
of skVar, skResult, skLet: genVarPrototype(m, sym)
|
||||
@@ -604,18 +608,18 @@ proc cgsym(m: BModule, name: string): PRope =
|
||||
# we're picky here for the system module too:
|
||||
rawMessage(errSystemNeeds, name)
|
||||
result = sym.loc.r
|
||||
|
||||
|
||||
proc generateHeaders(m: BModule) =
|
||||
app(m.s[cfsHeaders], tnl & "#include \"nimbase.h\"" & tnl)
|
||||
var it = PStrEntry(m.headerFiles.head)
|
||||
while it != nil:
|
||||
if it.data[0] notin {'\"', '<'}:
|
||||
if it.data[0] notin {'\"', '<'}:
|
||||
appf(m.s[cfsHeaders], "$N#include \"$1\"$N", [toRope(it.data)])
|
||||
else:
|
||||
appf(m.s[cfsHeaders], "$N#include $1$N", [toRope(it.data)])
|
||||
it = PStrEntry(it.next)
|
||||
|
||||
proc retIsNotVoid(s: PSym): bool =
|
||||
proc retIsNotVoid(s: PSym): bool =
|
||||
result = (s.typ.sons[0] != nil) and not isInvalidReturnType(s.typ.sons[0])
|
||||
|
||||
proc initFrame(p: BProc, procname, filename: PRope): PRope =
|
||||
@@ -663,11 +667,11 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||
else:
|
||||
fillResult(res)
|
||||
assignParam(p, res)
|
||||
if skipTypes(res.typ, abstractInst).kind == tyArray:
|
||||
if skipTypes(res.typ, abstractInst).kind == tyArray:
|
||||
incl(res.loc.flags, lfIndirect)
|
||||
res.loc.s = OnUnknown
|
||||
|
||||
for i in countup(1, sonsLen(prc.typ.n) - 1):
|
||||
|
||||
for i in countup(1, sonsLen(prc.typ.n) - 1):
|
||||
var param = prc.typ.n.sons[i].sym
|
||||
if param.typ.isCompileTimeOnly: continue
|
||||
assignParam(p, param)
|
||||
@@ -682,11 +686,11 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||
else:
|
||||
generatedProc = rfmt(nil, "$N$1 {$N", header)
|
||||
app(generatedProc, initGCFrame(p))
|
||||
if optStackTrace in prc.options:
|
||||
if optStackTrace in prc.options:
|
||||
app(generatedProc, p.s(cpsLocals))
|
||||
var procname = makeCString(prc.name.s)
|
||||
app(generatedProc, initFrame(p, procname, prc.info.quotedFilename))
|
||||
else:
|
||||
else:
|
||||
app(generatedProc, p.s(cpsLocals))
|
||||
if optProfiler in prc.options:
|
||||
# invoke at proc entry for recursion:
|
||||
@@ -706,12 +710,12 @@ proc crossesCppBoundary(m: BModule; sym: PSym): bool {.inline.} =
|
||||
sfCompileToCpp notin sym.getModule().flags and
|
||||
gCmd != cmdCompileToCpp
|
||||
|
||||
proc genProcPrototype(m: BModule, sym: PSym) =
|
||||
proc genProcPrototype(m: BModule, sym: PSym) =
|
||||
useHeader(m, sym)
|
||||
if lfNoDecl in sym.loc.flags: return
|
||||
if lfNoDecl in sym.loc.flags: return
|
||||
if lfDynamicLib in sym.loc.flags:
|
||||
if getModule(sym).id != m.module.id and
|
||||
not containsOrIncl(m.declaredThings, sym.id):
|
||||
not containsOrIncl(m.declaredThings, sym.id):
|
||||
app(m.s[cfsVars], rfmt(nil, "extern $1 $2;$n",
|
||||
getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym)))
|
||||
elif not containsOrIncl(m.declaredProtos, sym.id):
|
||||
@@ -722,13 +726,13 @@ proc genProcPrototype(m: BModule, sym: PSym) =
|
||||
header.app(" __attribute__((naked))")
|
||||
app(m.s[cfsProcHeaders], rfmt(nil, "$1;$n", header))
|
||||
|
||||
proc genProcNoForward(m: BModule, prc: PSym) =
|
||||
proc genProcNoForward(m: BModule, prc: PSym) =
|
||||
fillProcLoc(prc)
|
||||
useHeader(m, prc)
|
||||
if lfImportCompilerProc in prc.loc.flags:
|
||||
# dependency to a compilerproc:
|
||||
discard cgsym(m, prc.name.s)
|
||||
return
|
||||
return
|
||||
genProcPrototype(m, prc)
|
||||
if lfNoDecl in prc.loc.flags: discard
|
||||
elif prc.typ.callConv == ccInline:
|
||||
@@ -738,13 +742,13 @@ proc genProcNoForward(m: BModule, prc: PSym) =
|
||||
if not containsOrIncl(m.declaredThings, prc.id): genProcAux(m, prc)
|
||||
elif lfDynamicLib in prc.loc.flags:
|
||||
var q = findPendingModule(m, prc)
|
||||
if q != nil and not containsOrIncl(q.declaredThings, prc.id):
|
||||
if q != nil and not containsOrIncl(q.declaredThings, prc.id):
|
||||
symInDynamicLib(q, prc)
|
||||
else:
|
||||
symInDynamicLibPartial(m, prc)
|
||||
elif sfImportc notin prc.flags:
|
||||
var q = findPendingModule(m, prc)
|
||||
if q != nil and not containsOrIncl(q.declaredThings, prc.id):
|
||||
if q != nil and not containsOrIncl(q.declaredThings, prc.id):
|
||||
genProcAux(q, prc)
|
||||
|
||||
proc requestConstImpl(p: BProc, sym: PSym) =
|
||||
@@ -770,7 +774,7 @@ proc requestConstImpl(p: BProc, sym: PSym) =
|
||||
|
||||
proc isActivated(prc: PSym): bool = prc.typ != nil
|
||||
|
||||
proc genProc(m: BModule, prc: PSym) =
|
||||
proc genProc(m: BModule, prc: PSym) =
|
||||
if sfBorrow in prc.flags or not isActivated(prc): return
|
||||
fillProcLoc(prc)
|
||||
if sfForward in prc.flags: addForwardedProc(m, prc)
|
||||
@@ -780,19 +784,19 @@ proc genProc(m: BModule, prc: PSym) =
|
||||
generatedHeader != nil and lfNoDecl notin prc.loc.flags:
|
||||
genProcPrototype(generatedHeader, prc)
|
||||
if prc.typ.callConv == ccInline:
|
||||
if not containsOrIncl(generatedHeader.declaredThings, prc.id):
|
||||
if not containsOrIncl(generatedHeader.declaredThings, prc.id):
|
||||
genProcAux(generatedHeader, prc)
|
||||
|
||||
proc genVarPrototypeAux(m: BModule, sym: PSym) =
|
||||
proc genVarPrototypeAux(m: BModule, sym: PSym) =
|
||||
assert(sfGlobal in sym.flags)
|
||||
useHeader(m, sym)
|
||||
fillLoc(sym.loc, locGlobalVar, sym.typ, mangleName(sym), OnHeap)
|
||||
if (lfNoDecl in sym.loc.flags) or containsOrIncl(m.declaredThings, sym.id):
|
||||
return
|
||||
if sym.owner.id != m.module.id:
|
||||
if (lfNoDecl in sym.loc.flags) or containsOrIncl(m.declaredThings, sym.id):
|
||||
return
|
||||
if sym.owner.id != m.module.id:
|
||||
# else we already have the symbol generated!
|
||||
assert(sym.loc.r != nil)
|
||||
if sfThread in sym.flags:
|
||||
if sfThread in sym.flags:
|
||||
declareThreadVar(m, sym, true)
|
||||
else:
|
||||
app(m.s[cfsVars], "extern ")
|
||||
@@ -838,7 +842,7 @@ proc genFilenames(m: BModule): PRope =
|
||||
result.appf("dbgRegisterFilename($1);$N", fileInfos[i].projPath.makeCString)
|
||||
|
||||
proc genMainProc(m: BModule) =
|
||||
const
|
||||
const
|
||||
# The use of a volatile function pointer to call Pre/NimMainInner
|
||||
# prevents inlining of the NimMainInner function and dependent
|
||||
# functions, which might otherwise merge their stack frames.
|
||||
@@ -859,7 +863,7 @@ proc genMainProc(m: BModule) =
|
||||
|
||||
MainProcs =
|
||||
"\tNimMain();$N"
|
||||
|
||||
|
||||
MainProcsWithResult =
|
||||
MainProcs & "\treturn nim_program_result;$N"
|
||||
|
||||
@@ -880,7 +884,7 @@ proc genMainProc(m: BModule) =
|
||||
"char** cmdLine;$N" &
|
||||
"char** gEnv;$N" &
|
||||
NimMainBody
|
||||
|
||||
|
||||
PosixCMain =
|
||||
"int main(int argc, char** args, char** env) {$N" &
|
||||
"\tcmdLine = args;$N" &
|
||||
@@ -888,20 +892,20 @@ proc genMainProc(m: BModule) =
|
||||
"\tgEnv = env;$N" &
|
||||
MainProcsWithResult &
|
||||
"}$N$N"
|
||||
|
||||
|
||||
StandaloneCMain =
|
||||
"int main(void) {$N" &
|
||||
MainProcs &
|
||||
"\treturn 0;$N" &
|
||||
"}$N$N"
|
||||
|
||||
|
||||
WinNimMain = NimMainBody
|
||||
|
||||
|
||||
WinCMain = "N_STDCALL(int, WinMain)(HINSTANCE hCurInstance, $N" &
|
||||
" HINSTANCE hPrevInstance, $N" &
|
||||
" LPSTR lpCmdLine, int nCmdShow) {$N" &
|
||||
MainProcsWithResult & "}$N$N"
|
||||
|
||||
|
||||
WinNimDllMain = "N_LIB_EXPORT " & NimMainBody
|
||||
|
||||
WinCDllMain =
|
||||
@@ -911,7 +915,7 @@ proc genMainProc(m: BModule) =
|
||||
"\treturn 1;$N}$N$N"
|
||||
|
||||
PosixNimDllMain = WinNimDllMain
|
||||
|
||||
|
||||
PosixCDllMain =
|
||||
"void NIM_POSIX_INIT NimMainInit(void) {$N" &
|
||||
MainProcs &
|
||||
@@ -919,11 +923,11 @@ proc genMainProc(m: BModule) =
|
||||
|
||||
var nimMain, otherMain: TFormatStr
|
||||
if platform.targetOS == osWindows and
|
||||
gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}:
|
||||
if optGenGuiApp in gGlobalOptions:
|
||||
gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}:
|
||||
if optGenGuiApp in gGlobalOptions:
|
||||
nimMain = WinNimMain
|
||||
otherMain = WinCMain
|
||||
else:
|
||||
else:
|
||||
nimMain = WinNimDllMain
|
||||
otherMain = WinCDllMain
|
||||
discard lists.includeStr(m.headerFiles, "<windows.h>")
|
||||
@@ -939,7 +943,7 @@ proc genMainProc(m: BModule) =
|
||||
if gBreakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint")
|
||||
if optEndb in gOptions:
|
||||
gBreakpoints.app(m.genFilenames)
|
||||
|
||||
|
||||
let initStackBottomCall =
|
||||
if platform.targetOS == osStandalone: "".toRope
|
||||
else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N")
|
||||
@@ -964,11 +968,11 @@ proc getSomeInitName(m: PSym, suffix: string): PRope =
|
||||
result.app "_"
|
||||
result.app m.name.s
|
||||
result.app suffix
|
||||
|
||||
|
||||
proc getInitName(m: PSym): PRope = getSomeInitName(m, "Init")
|
||||
proc getDatInitName(m: PSym): PRope = getSomeInitName(m, "DatInit")
|
||||
|
||||
proc registerModuleToMain(m: PSym) =
|
||||
proc registerModuleToMain(m: PSym) =
|
||||
var
|
||||
init = m.getInitName
|
||||
datInit = m.getDatInitName
|
||||
@@ -981,19 +985,19 @@ proc registerModuleToMain(m: PSym) =
|
||||
app(mainModInit, initCall)
|
||||
else:
|
||||
app(otherModsInit, initCall)
|
||||
|
||||
proc genInitCode(m: BModule) =
|
||||
|
||||
proc genInitCode(m: BModule) =
|
||||
var initname = getInitName(m.module)
|
||||
var prc = ropef("NIM_EXTERNC N_NOINLINE(void, $1)(void) {$N", [initname])
|
||||
if m.typeNodes > 0:
|
||||
appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n",
|
||||
if m.typeNodes > 0:
|
||||
appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n",
|
||||
[m.typeNodesName, toRope(m.typeNodes)])
|
||||
if m.nimTypes > 0:
|
||||
appcg(m, m.s[cfsTypeInit1], "static #TNimType $1[$2];$n",
|
||||
if m.nimTypes > 0:
|
||||
appcg(m, m.s[cfsTypeInit1], "static #TNimType $1[$2];$n",
|
||||
[m.nimTypesName, toRope(m.nimTypes)])
|
||||
|
||||
|
||||
app(prc, initGCFrame(m.initProc))
|
||||
|
||||
|
||||
app(prc, genSectionStart(cpsLocals))
|
||||
app(prc, m.preInitProc.s(cpsLocals))
|
||||
app(prc, m.initProc.s(cpsLocals))
|
||||
@@ -1009,7 +1013,7 @@ proc genInitCode(m: BModule) =
|
||||
app(prc, initFrame(m.initProc, procname, m.module.info.quotedFilename))
|
||||
else:
|
||||
app(prc, ~"\tTFrame F; F.len = 0;$N")
|
||||
|
||||
|
||||
app(prc, genSectionStart(cpsInit))
|
||||
app(prc, m.preInitProc.s(cpsInit))
|
||||
app(prc, m.initProc.s(cpsInit))
|
||||
@@ -1033,27 +1037,27 @@ proc genInitCode(m: BModule) =
|
||||
app(prc, genSectionStart(i))
|
||||
app(prc, m.s[i])
|
||||
app(prc, genSectionEnd(i))
|
||||
|
||||
|
||||
appf(prc, "}$N$N")
|
||||
# we cannot simply add the init proc to ``m.s[cfsProcs]`` anymore because
|
||||
# that would lead to a *nesting* of merge sections which the merger does
|
||||
# not support. So we add it to another special section: ``cfsInitProc``
|
||||
app(m.s[cfsInitProc], prc)
|
||||
|
||||
|
||||
for i, el in pairs(m.extensionLoaders):
|
||||
if el != nil:
|
||||
let ex = ropef("N_NIMCALL(void, nimLoadProcs$1)(void) {$2}$N$N",
|
||||
(i.ord - '0'.ord).toRope, el)
|
||||
app(m.s[cfsInitProc], ex)
|
||||
|
||||
proc genModule(m: BModule, cfile: string): PRope =
|
||||
proc genModule(m: BModule, cfile: string): PRope =
|
||||
result = getFileHeader(cfile)
|
||||
result.app(genMergeInfo(m))
|
||||
|
||||
|
||||
generateHeaders(m)
|
||||
|
||||
generateThreadLocalStorage(m)
|
||||
for i in countup(cfsHeaders, cfsProcs):
|
||||
for i in countup(cfsHeaders, cfsProcs):
|
||||
app(result, genSectionStart(i))
|
||||
app(result, m.s[i])
|
||||
app(result, genSectionEnd(i))
|
||||
@@ -1069,7 +1073,7 @@ proc newPostInitProc(m: BModule): BProc =
|
||||
# little hack so that unique temporaries are generated:
|
||||
result.labels = 200_000
|
||||
|
||||
proc initProcOptions(m: BModule): TOptions =
|
||||
proc initProcOptions(m: BModule): TOptions =
|
||||
if sfSystemModule in m.module.flags: gOptions-{optStackTrace} else: gOptions
|
||||
|
||||
proc rawNewModule(module: PSym, filename: string): BModule =
|
||||
@@ -1124,11 +1128,11 @@ proc resetModule*(m: BModule) =
|
||||
m.typeNodes = 0
|
||||
m.nimTypes = 0
|
||||
nullify m.extensionLoaders
|
||||
|
||||
|
||||
# indicate that this is now cached module
|
||||
# the cache will be invalidated by nullifying gModules
|
||||
m.fromCache = true
|
||||
|
||||
|
||||
# we keep only the "merge info" information for the module
|
||||
# and the properties that can't change:
|
||||
# m.filename
|
||||
@@ -1155,11 +1159,11 @@ proc newModule(module: PSym): BModule =
|
||||
growCache gModules, module.position
|
||||
gModules[module.position] = result
|
||||
|
||||
if (optDeadCodeElim in gGlobalOptions):
|
||||
if (sfDeadCodeElim in module.flags):
|
||||
if (optDeadCodeElim in gGlobalOptions):
|
||||
if (sfDeadCodeElim in module.flags):
|
||||
internalError("added pending module twice: " & module.filename)
|
||||
|
||||
proc myOpen(module: PSym): PPassContext =
|
||||
proc myOpen(module: PSym): PPassContext =
|
||||
result = newModule(module)
|
||||
if optGenIndex in gGlobalOptions and generatedHeader == nil:
|
||||
let f = if headerFile.len > 0: headerFile else: gProjectFull
|
||||
@@ -1175,12 +1179,12 @@ proc writeHeader(m: BModule) =
|
||||
generateHeaders(m)
|
||||
|
||||
generateThreadLocalStorage(m)
|
||||
for i in countup(cfsHeaders, cfsProcs):
|
||||
for i in countup(cfsHeaders, cfsProcs):
|
||||
app(result, genSectionStart(i))
|
||||
app(result, m.s[i])
|
||||
app(result, genSectionEnd(i))
|
||||
app(result, m.s[cfsInitProc])
|
||||
|
||||
|
||||
if optGenDynLib in gGlobalOptions:
|
||||
result.app("N_LIB_IMPORT ")
|
||||
result.appf("N_CDECL(void, NimMain)(void);$n")
|
||||
@@ -1200,20 +1204,20 @@ proc myOpenCached(module: PSym, rd: PRodReader): PPassContext =
|
||||
readMergeInfo(getCFile(m), m)
|
||||
result = m
|
||||
|
||||
proc myProcess(b: PPassContext, n: PNode): PNode =
|
||||
proc myProcess(b: PPassContext, n: PNode): PNode =
|
||||
result = n
|
||||
if b == nil or passes.skipCodegen(n): return
|
||||
var m = BModule(b)
|
||||
m.initProc.options = initProcOptions(m)
|
||||
genStmts(m.initProc, n)
|
||||
|
||||
proc finishModule(m: BModule) =
|
||||
proc finishModule(m: BModule) =
|
||||
var i = 0
|
||||
while i <= high(m.forwardedProcs):
|
||||
while i <= high(m.forwardedProcs):
|
||||
# Note: ``genProc`` may add to ``m.forwardedProcs``, so we cannot use
|
||||
# a ``for`` loop here
|
||||
var prc = m.forwardedProcs[i]
|
||||
if sfForward in prc.flags:
|
||||
if sfForward in prc.flags:
|
||||
internalError(prc.info, "still forwarded: " & prc.name.s)
|
||||
genProcNoForward(m, prc)
|
||||
inc(i)
|
||||
@@ -1221,13 +1225,13 @@ proc finishModule(m: BModule) =
|
||||
dec(gForwardedProcsCounter, i)
|
||||
setLen(m.forwardedProcs, 0)
|
||||
|
||||
proc shouldRecompile(code: PRope, cfile: string): bool =
|
||||
proc shouldRecompile(code: PRope, cfile: string): bool =
|
||||
result = true
|
||||
if optForceFullMake notin gGlobalOptions:
|
||||
var objFile = toObjFile(cfile)
|
||||
if writeRopeIfNotEqual(code, cfile): return
|
||||
if writeRopeIfNotEqual(code, cfile): return
|
||||
if existsFile(objFile) and os.fileNewer(objFile, cfile): result = false
|
||||
else:
|
||||
else:
|
||||
writeRope(code, cfile)
|
||||
|
||||
# We need 2 different logics here: pending modules (including
|
||||
@@ -1240,15 +1244,15 @@ proc writeModule(m: BModule, pending: bool) =
|
||||
# generate code for the init statements of the module:
|
||||
var cfile = getCFile(m)
|
||||
var cfilenoext = changeFileExt(cfile, "")
|
||||
|
||||
|
||||
if not m.fromCache or optForceFullMake in gGlobalOptions:
|
||||
genInitCode(m)
|
||||
finishTypeDescriptions(m)
|
||||
if sfMainModule in m.module.flags:
|
||||
if sfMainModule in m.module.flags:
|
||||
# generate main file:
|
||||
app(m.s[cfsProcHeaders], mainModProcs)
|
||||
generateThreadVarsSize(m)
|
||||
|
||||
|
||||
var code = genModule(m, cfile)
|
||||
when hasTinyCBackend:
|
||||
if gCmd == cmdRun:
|
||||
@@ -1269,13 +1273,13 @@ proc writeModule(m: BModule, pending: bool) =
|
||||
# ``system.c`` but then compilation fails due to an error. This means
|
||||
# that ``system.o`` is missing, so we need to call the C compiler for it:
|
||||
addFileToCompile(cfile)
|
||||
|
||||
|
||||
addFileToLink(cfilenoext)
|
||||
|
||||
proc updateCachedModule(m: BModule) =
|
||||
let cfile = getCFile(m)
|
||||
let cfilenoext = changeFileExt(cfile, "")
|
||||
|
||||
|
||||
if mergeRequired(m) and sfMainModule notin m.module.flags:
|
||||
mergeFiles(cfile, m)
|
||||
genInitCode(m)
|
||||
@@ -1286,17 +1290,17 @@ proc updateCachedModule(m: BModule) =
|
||||
|
||||
addFileToLink(cfilenoext)
|
||||
|
||||
proc myClose(b: PPassContext, n: PNode): PNode =
|
||||
proc myClose(b: PPassContext, n: PNode): PNode =
|
||||
result = n
|
||||
if b == nil or passes.skipCodegen(n): return
|
||||
if b == nil or passes.skipCodegen(n): return
|
||||
var m = BModule(b)
|
||||
if n != nil:
|
||||
if n != nil:
|
||||
m.initProc.options = initProcOptions(m)
|
||||
genStmts(m.initProc, n)
|
||||
# cached modules need to registered too:
|
||||
# cached modules need to registered too:
|
||||
registerModuleToMain(m.module)
|
||||
|
||||
if sfMainModule in m.module.flags:
|
||||
if sfMainModule in m.module.flags:
|
||||
m.objHasKidsValid = true
|
||||
var disp = generateMethodDispatchers()
|
||||
for i in 0..sonsLen(disp)-1: genProcAux(m, disp.sons[i].sym)
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
|
||||
# This module implements lookup helpers.
|
||||
|
||||
import
|
||||
intsets, ast, astalgo, idents, semdata, types, msgs, options, rodread,
|
||||
import
|
||||
intsets, ast, astalgo, idents, semdata, types, msgs, options, rodread,
|
||||
renderer, wordrecg, idgen, nimfix.prettybase
|
||||
|
||||
proc ensureNoMissingOrUnusedSymbols(scope: PScope)
|
||||
@@ -87,14 +87,14 @@ proc searchInScopes*(c: PContext, s: PIdent): PSym =
|
||||
if result != nil: return
|
||||
result = nil
|
||||
|
||||
proc debugScopes*(c: PContext) {.deprecated.} =
|
||||
proc debugScopes*(c: PContext; limit=0) {.deprecated.} =
|
||||
var i = 0
|
||||
for scope in walkScopes(c.currentScope):
|
||||
echo "scope ", i
|
||||
for h in 0 .. high(scope.symbols.data):
|
||||
if scope.symbols.data[h] != nil:
|
||||
echo scope.symbols.data[h].name.s
|
||||
if i == 2: break
|
||||
if i == limit: break
|
||||
inc i
|
||||
|
||||
proc searchInScopes*(c: PContext, s: PIdent, filter: TSymKinds): PSym =
|
||||
@@ -108,7 +108,7 @@ proc errorSym*(c: PContext, n: PNode): PSym =
|
||||
var m = n
|
||||
# ensure that 'considerQuotedIdent' can't fail:
|
||||
if m.kind == nkDotExpr: m = m.sons[1]
|
||||
let ident = if m.kind in {nkIdent, nkSym, nkAccQuoted}:
|
||||
let ident = if m.kind in {nkIdent, nkSym, nkAccQuoted}:
|
||||
considerQuotedIdent(m)
|
||||
else:
|
||||
getIdent("err:" & renderTree(m))
|
||||
@@ -119,11 +119,11 @@ proc errorSym*(c: PContext, n: PNode): PSym =
|
||||
if gCmd != cmdInteractive and c.inCompilesContext == 0:
|
||||
c.importTable.addSym(result)
|
||||
|
||||
type
|
||||
TOverloadIterMode* = enum
|
||||
type
|
||||
TOverloadIterMode* = enum
|
||||
oimDone, oimNoQualifier, oimSelfModule, oimOtherModule, oimSymChoice,
|
||||
oimSymChoiceLocalLookup
|
||||
TOverloadIter*{.final.} = object
|
||||
TOverloadIter*{.final.} = object
|
||||
it*: TIdentIter
|
||||
m*: PSym
|
||||
mode*: TOverloadIterMode
|
||||
@@ -131,7 +131,7 @@ type
|
||||
scope*: PScope
|
||||
inSymChoice: IntSet
|
||||
|
||||
proc getSymRepr*(s: PSym): string =
|
||||
proc getSymRepr*(s: PSym): string =
|
||||
case s.kind
|
||||
of skProc, skMethod, skConverter, skIterators: result = getProcHeader(s)
|
||||
else: result = s.name.s
|
||||
@@ -148,7 +148,7 @@ proc ensureNoMissingOrUnusedSymbols(scope: PScope) =
|
||||
if missingImpls == 0:
|
||||
localError(s.info, errImplOfXexpected, getSymRepr(s))
|
||||
inc missingImpls
|
||||
elif {sfUsed, sfExported} * s.flags == {} and optHints in s.options:
|
||||
elif {sfUsed, sfExported} * s.flags == {} and optHints in s.options:
|
||||
# BUGFIX: check options in s!
|
||||
if s.kind notin {skForVar, skParam, skMethod, skUnknown, skGenericParam}:
|
||||
# XXX: implicit type params are currently skTypes
|
||||
@@ -156,11 +156,11 @@ proc ensureNoMissingOrUnusedSymbols(scope: PScope) =
|
||||
if s.typ != nil and tfImplicitTypeParam notin s.typ.flags:
|
||||
message(s.info, hintXDeclaredButNotUsed, getSymRepr(s))
|
||||
s = nextIter(it, scope.symbols)
|
||||
|
||||
|
||||
proc wrongRedefinition*(info: TLineInfo, s: string) =
|
||||
if gCmd != cmdInteractive:
|
||||
localError(info, errAttemptToRedefine, s)
|
||||
|
||||
|
||||
proc addDecl*(c: PContext, sym: PSym) =
|
||||
if not c.currentScope.addUniqueSym(sym):
|
||||
wrongRedefinition(sym.info, sym.name.s)
|
||||
@@ -172,7 +172,7 @@ proc addDeclAt*(scope: PScope, sym: PSym) =
|
||||
if not scope.addUniqueSym(sym):
|
||||
wrongRedefinition(sym.info, sym.name.s)
|
||||
|
||||
proc addInterfaceDeclAux(c: PContext, sym: PSym) =
|
||||
proc addInterfaceDeclAux(c: PContext, sym: PSym) =
|
||||
if sfExported in sym.flags:
|
||||
# add to interface:
|
||||
if c.module != nil: strTableAdd(c.module.tab, sym)
|
||||
@@ -183,16 +183,16 @@ proc addInterfaceDeclAt*(c: PContext, scope: PScope, sym: PSym) =
|
||||
addInterfaceDeclAux(c, sym)
|
||||
|
||||
proc addOverloadableSymAt*(scope: PScope, fn: PSym) =
|
||||
if fn.kind notin OverloadableSyms:
|
||||
if fn.kind notin OverloadableSyms:
|
||||
internalError(fn.info, "addOverloadableSymAt")
|
||||
return
|
||||
let check = strTableGet(scope.symbols, fn.name)
|
||||
if check != nil and check.kind notin OverloadableSyms:
|
||||
if check != nil and check.kind notin OverloadableSyms:
|
||||
wrongRedefinition(fn.info, fn.name.s)
|
||||
else:
|
||||
scope.addSym(fn)
|
||||
|
||||
proc addInterfaceDecl*(c: PContext, sym: PSym) =
|
||||
|
||||
proc addInterfaceDecl*(c: PContext, sym: PSym) =
|
||||
# it adds the symbol to the interface if appropriate
|
||||
addDecl(c, sym)
|
||||
addInterfaceDeclAux(c, sym)
|
||||
@@ -221,7 +221,7 @@ when defined(nimfix):
|
||||
else:
|
||||
template fixSpelling(n: PNode; ident: PIdent; op: expr) = discard
|
||||
|
||||
proc lookUp*(c: PContext, n: PNode): PSym =
|
||||
proc lookUp*(c: PContext, n: PNode): PSym =
|
||||
# Looks up a symbol. Generates an error in case of nil.
|
||||
case n.kind
|
||||
of nkIdent:
|
||||
@@ -242,12 +242,12 @@ proc lookUp*(c: PContext, n: PNode): PSym =
|
||||
else:
|
||||
internalError(n.info, "lookUp")
|
||||
return
|
||||
if contains(c.ambiguousSymbols, result.id):
|
||||
if contains(c.ambiguousSymbols, result.id):
|
||||
localError(n.info, errUseQualifier, result.name.s)
|
||||
if result.kind == skStub: loadStub(result)
|
||||
|
||||
type
|
||||
TLookupFlag* = enum
|
||||
|
||||
type
|
||||
TLookupFlag* = enum
|
||||
checkAmbiguity, checkUndeclared
|
||||
|
||||
proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
|
||||
@@ -294,7 +294,7 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
|
||||
else:
|
||||
result = nil
|
||||
if result != nil and result.kind == skStub: loadStub(result)
|
||||
|
||||
|
||||
proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||
case n.kind
|
||||
of nkIdent, nkAccQuoted:
|
||||
@@ -311,17 +311,17 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||
of nkSym:
|
||||
result = n.sym
|
||||
o.mode = oimDone
|
||||
of nkDotExpr:
|
||||
of nkDotExpr:
|
||||
o.mode = oimOtherModule
|
||||
o.m = qualifiedLookUp(c, n.sons[0])
|
||||
if o.m != nil and o.m.kind == skModule:
|
||||
var ident: PIdent = nil
|
||||
if n.sons[1].kind == nkIdent:
|
||||
if n.sons[1].kind == nkIdent:
|
||||
ident = n.sons[1].ident
|
||||
elif n.sons[1].kind == nkAccQuoted:
|
||||
ident = considerQuotedIdent(n.sons[1])
|
||||
if ident != nil:
|
||||
if o.m == c.module:
|
||||
if ident != nil:
|
||||
if o.m == c.module:
|
||||
# a module may access its private members:
|
||||
result = initIdentIter(o.it, c.topLevelScope.symbols,
|
||||
ident).skipAlias(n)
|
||||
@@ -329,7 +329,7 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||
else:
|
||||
result = initIdentIter(o.it, o.m.tab, ident).skipAlias(n)
|
||||
else:
|
||||
localError(n.sons[1].info, errIdentifierExpected,
|
||||
localError(n.sons[1].info, errIdentifierExpected,
|
||||
renderTree(n.sons[1]))
|
||||
result = errorSym(c, n.sons[1])
|
||||
of nkClosedSymChoice, nkOpenSymChoice:
|
||||
@@ -347,12 +347,12 @@ proc lastOverloadScope*(o: TOverloadIter): int =
|
||||
of oimSelfModule: result = 1
|
||||
of oimOtherModule: result = 0
|
||||
else: result = -1
|
||||
|
||||
proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||
|
||||
proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||
case o.mode
|
||||
of oimDone:
|
||||
of oimDone:
|
||||
result = nil
|
||||
of oimNoQualifier:
|
||||
of oimNoQualifier:
|
||||
if o.scope != nil:
|
||||
result = nextIdentIter(o.it, o.scope.symbols).skipAlias(n)
|
||||
while result == nil:
|
||||
@@ -360,13 +360,13 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||
if o.scope == nil: break
|
||||
result = initIdentIter(o.it, o.scope.symbols, o.it.name).skipAlias(n)
|
||||
# BUGFIX: o.it.name <-> n.ident
|
||||
else:
|
||||
else:
|
||||
result = nil
|
||||
of oimSelfModule:
|
||||
of oimSelfModule:
|
||||
result = nextIdentIter(o.it, c.topLevelScope.symbols).skipAlias(n)
|
||||
of oimOtherModule:
|
||||
of oimOtherModule:
|
||||
result = nextIdentIter(o.it, o.m.tab).skipAlias(n)
|
||||
of oimSymChoice:
|
||||
of oimSymChoice:
|
||||
if o.symChoiceIndex < sonsLen(n):
|
||||
result = n.sons[o.symChoiceIndex].sym
|
||||
incl(o.inSymChoice, result.id)
|
||||
@@ -389,7 +389,7 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||
if o.scope == nil: break
|
||||
result = firstIdentExcluding(o.it, o.scope.symbols,
|
||||
n.sons[0].sym.name, o.inSymChoice).skipAlias(n)
|
||||
|
||||
|
||||
if result != nil and result.kind == skStub: loadStub(result)
|
||||
|
||||
proc pickSym*(c: PContext, n: PNode; kind: TSymKind;
|
||||
|
||||
@@ -9,19 +9,19 @@
|
||||
|
||||
# This module implements semantic checking for pragmas
|
||||
|
||||
import
|
||||
os, platform, condsyms, ast, astalgo, idents, semdata, msgs, renderer,
|
||||
import
|
||||
os, platform, condsyms, ast, astalgo, idents, semdata, msgs, renderer,
|
||||
wordrecg, ropes, options, strutils, lists, extccomp, math, magicsys, trees,
|
||||
rodread, types, lookups
|
||||
|
||||
const
|
||||
const
|
||||
FirstCallConv* = wNimcall
|
||||
LastCallConv* = wNoconv
|
||||
|
||||
const
|
||||
procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
||||
wMagic, wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader,
|
||||
wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
|
||||
procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
||||
wMagic, wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader,
|
||||
wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
|
||||
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
|
||||
wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
|
||||
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
|
||||
@@ -33,7 +33,7 @@ const
|
||||
macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc,
|
||||
wNodecl, wMagic, wNosideeffect, wCompilerproc, wDeprecated, wExtern,
|
||||
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator}
|
||||
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect,
|
||||
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect,
|
||||
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
|
||||
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
|
||||
wTags, wLocks, wGcSafe}
|
||||
@@ -46,18 +46,18 @@ const
|
||||
wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
|
||||
wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto,
|
||||
wInjectStmt, wDeprecated, wExperimental}
|
||||
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
||||
wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader,
|
||||
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
||||
wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader,
|
||||
wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame,
|
||||
wRaises, wLocks, wTags, wGcSafe}
|
||||
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
|
||||
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
|
||||
wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow,
|
||||
wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
|
||||
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
|
||||
wBorrow, wGcSafe}
|
||||
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
|
||||
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
|
||||
wImportCpp, wImportObjC, wError, wGuard}
|
||||
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
|
||||
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
|
||||
wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern,
|
||||
wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
|
||||
wGensym, wInject, wCodegenDecl, wGuard}
|
||||
@@ -74,18 +74,18 @@ proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords)
|
||||
proc invalidPragma(n: PNode) =
|
||||
localError(n.info, errInvalidPragmaX, renderTree(n, {renderNoComments}))
|
||||
|
||||
proc pragmaAsm*(c: PContext, n: PNode): char =
|
||||
proc pragmaAsm*(c: PContext, n: PNode): char =
|
||||
result = '\0'
|
||||
if n != nil:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
if n != nil:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
let it = n.sons[i]
|
||||
if it.kind == nkExprColonExpr and it.sons[0].kind == nkIdent:
|
||||
case whichKeyword(it.sons[0].ident)
|
||||
of wSubsChar:
|
||||
of wSubsChar:
|
||||
if it.sons[1].kind == nkCharLit: result = chr(int(it.sons[1].intVal))
|
||||
else: invalidPragma(it)
|
||||
else: invalidPragma(it)
|
||||
else:
|
||||
else:
|
||||
invalidPragma(it)
|
||||
|
||||
proc setExternName(s: PSym, extname: string) =
|
||||
@@ -94,7 +94,7 @@ proc setExternName(s: PSym, extname: string) =
|
||||
# note that '{.importc.}' is transformed into '{.importc: "$1".}'
|
||||
s.loc.flags.incl(lfFullExternalName)
|
||||
|
||||
proc makeExternImport(s: PSym, extname: string) =
|
||||
proc makeExternImport(s: PSym, extname: string) =
|
||||
setExternName(s, extname)
|
||||
incl(s.flags, sfImportc)
|
||||
excl(s.flags, sfForward)
|
||||
@@ -145,7 +145,7 @@ proc newEmptyStrNode(n: PNode): PNode {.noinline.} =
|
||||
result.strVal = ""
|
||||
|
||||
proc getStrLitNode(c: PContext, n: PNode): PNode =
|
||||
if n.kind != nkExprColonExpr:
|
||||
if n.kind != nkExprColonExpr:
|
||||
localError(n.info, errStringLiteralExpected)
|
||||
# error correction:
|
||||
result = newEmptyStrNode(n)
|
||||
@@ -153,62 +153,62 @@ proc getStrLitNode(c: PContext, n: PNode): PNode =
|
||||
n.sons[1] = c.semConstExpr(c, n.sons[1])
|
||||
case n.sons[1].kind
|
||||
of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.sons[1]
|
||||
else:
|
||||
else:
|
||||
localError(n.info, errStringLiteralExpected)
|
||||
# error correction:
|
||||
result = newEmptyStrNode(n)
|
||||
|
||||
proc expectStrLit(c: PContext, n: PNode): string =
|
||||
proc expectStrLit(c: PContext, n: PNode): string =
|
||||
result = getStrLitNode(c, n).strVal
|
||||
|
||||
proc expectIntLit(c: PContext, n: PNode): int =
|
||||
if n.kind != nkExprColonExpr:
|
||||
proc expectIntLit(c: PContext, n: PNode): int =
|
||||
if n.kind != nkExprColonExpr:
|
||||
localError(n.info, errIntLiteralExpected)
|
||||
else:
|
||||
else:
|
||||
n.sons[1] = c.semConstExpr(c, n.sons[1])
|
||||
case n.sons[1].kind
|
||||
of nkIntLit..nkInt64Lit: result = int(n.sons[1].intVal)
|
||||
else: localError(n.info, errIntLiteralExpected)
|
||||
|
||||
proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string =
|
||||
proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string =
|
||||
if n.kind == nkExprColonExpr: result = expectStrLit(c, n)
|
||||
else: result = defaultStr
|
||||
|
||||
proc processCodegenDecl(c: PContext, n: PNode, sym: PSym) =
|
||||
sym.constraint = getStrLitNode(c, n)
|
||||
|
||||
proc processMagic(c: PContext, n: PNode, s: PSym) =
|
||||
proc processMagic(c: PContext, n: PNode, s: PSym) =
|
||||
#if sfSystemModule notin c.module.flags:
|
||||
# liMessage(n.info, errMagicOnlyInSystem)
|
||||
if n.kind != nkExprColonExpr:
|
||||
if n.kind != nkExprColonExpr:
|
||||
localError(n.info, errStringLiteralExpected)
|
||||
return
|
||||
var v: string
|
||||
if n.sons[1].kind == nkIdent: v = n.sons[1].ident.s
|
||||
else: v = expectStrLit(c, n)
|
||||
for m in countup(low(TMagic), high(TMagic)):
|
||||
if substr($m, 1) == v:
|
||||
for m in countup(low(TMagic), high(TMagic)):
|
||||
if substr($m, 1) == v:
|
||||
s.magic = m
|
||||
break
|
||||
if s.magic == mNone: message(n.info, warnUnknownMagic, v)
|
||||
|
||||
proc wordToCallConv(sw: TSpecialWord): TCallingConvention =
|
||||
proc wordToCallConv(sw: TSpecialWord): TCallingConvention =
|
||||
# this assumes that the order of special words and calling conventions is
|
||||
# the same
|
||||
result = TCallingConvention(ord(ccDefault) + ord(sw) - ord(wNimcall))
|
||||
|
||||
proc isTurnedOn(c: PContext, n: PNode): bool =
|
||||
proc isTurnedOn(c: PContext, n: PNode): bool =
|
||||
if n.kind == nkExprColonExpr:
|
||||
let x = c.semConstBoolExpr(c, n.sons[1])
|
||||
n.sons[1] = x
|
||||
if x.kind == nkIntLit: return x.intVal != 0
|
||||
localError(n.info, errOnOrOffExpected)
|
||||
|
||||
proc onOff(c: PContext, n: PNode, op: TOptions) =
|
||||
proc onOff(c: PContext, n: PNode, op: TOptions) =
|
||||
if isTurnedOn(c, n): gOptions = gOptions + op
|
||||
else: gOptions = gOptions - op
|
||||
|
||||
proc pragmaDeadCodeElim(c: PContext, n: PNode) =
|
||||
|
||||
proc pragmaDeadCodeElim(c: PContext, n: PNode) =
|
||||
if isTurnedOn(c, n): incl(c.module.flags, sfDeadCodeElim)
|
||||
else: excl(c.module.flags, sfDeadCodeElim)
|
||||
|
||||
@@ -216,20 +216,20 @@ proc pragmaNoForward(c: PContext, n: PNode) =
|
||||
if isTurnedOn(c, n): incl(c.module.flags, sfNoForward)
|
||||
else: excl(c.module.flags, sfNoForward)
|
||||
|
||||
proc processCallConv(c: PContext, n: PNode) =
|
||||
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
|
||||
proc processCallConv(c: PContext, n: PNode) =
|
||||
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
|
||||
var sw = whichKeyword(n.sons[1].ident)
|
||||
case sw
|
||||
of FirstCallConv..LastCallConv:
|
||||
of FirstCallConv..LastCallConv:
|
||||
POptionEntry(c.optionStack.tail).defaultCC = wordToCallConv(sw)
|
||||
else: localError(n.info, errCallConvExpected)
|
||||
else:
|
||||
else:
|
||||
localError(n.info, errCallConvExpected)
|
||||
|
||||
proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib =
|
||||
|
||||
proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib =
|
||||
var it = PLib(c.libs.head)
|
||||
while it != nil:
|
||||
if it.kind == kind:
|
||||
while it != nil:
|
||||
if it.kind == kind:
|
||||
if trees.exprStructuralEquivalent(it.path, path): return it
|
||||
it = PLib(it.next)
|
||||
result = newLib(kind)
|
||||
@@ -252,10 +252,10 @@ proc expectDynlibNode(c: PContext, n: PNode): PNode =
|
||||
if result.typ == nil or result.typ.kind notin {tyPointer, tyString, tyProc}:
|
||||
localError(n.info, errStringLiteralExpected)
|
||||
result = newEmptyStrNode(n)
|
||||
|
||||
proc processDynLib(c: PContext, n: PNode, sym: PSym) =
|
||||
|
||||
proc processDynLib(c: PContext, n: PNode, sym: PSym) =
|
||||
if (sym == nil) or (sym.kind == skModule):
|
||||
POptionEntry(c.optionStack.tail).dynlib = getLib(c, libDynamic,
|
||||
POptionEntry(c.optionStack.tail).dynlib = getLib(c, libDynamic,
|
||||
expectDynlibNode(c, n))
|
||||
else:
|
||||
if n.kind == nkExprColonExpr:
|
||||
@@ -268,7 +268,7 @@ proc processDynLib(c: PContext, n: PNode, sym: PSym) =
|
||||
# since we'll be loading the dynlib symbols dynamically, we must use
|
||||
# a calling convention that doesn't introduce custom name mangling
|
||||
# cdecl is the default - the user can override this explicitly
|
||||
if sym.kind in routineKinds and sym.typ != nil and
|
||||
if sym.kind in routineKinds and sym.typ != nil and
|
||||
sym.typ.callConv == ccDefault:
|
||||
sym.typ.callConv = ccCDecl
|
||||
|
||||
@@ -295,10 +295,10 @@ proc processNote(c: PContext, n: PNode) =
|
||||
n.sons[1] = x
|
||||
if x.kind == nkIntLit and x.intVal != 0: incl(gNotes, nk)
|
||||
else: excl(gNotes, nk)
|
||||
else:
|
||||
else:
|
||||
invalidPragma(n)
|
||||
|
||||
proc processOption(c: PContext, n: PNode): bool =
|
||||
|
||||
proc processOption(c: PContext, n: PNode): bool =
|
||||
if n.kind != nkExprColonExpr: result = true
|
||||
elif n.sons[0].kind == nkBracketExpr: processNote(c, n)
|
||||
elif n.sons[0].kind != nkIdent: result = true
|
||||
@@ -318,34 +318,34 @@ proc processOption(c: PContext, n: PNode): bool =
|
||||
of wAssertions: onOff(c, n, {optAssert})
|
||||
of wWarnings: onOff(c, n, {optWarns})
|
||||
of wHints: onOff(c, n, {optHints})
|
||||
of wCallconv: processCallConv(c, n)
|
||||
of wCallconv: processCallConv(c, n)
|
||||
of wLinedir: onOff(c, n, {optLineDir})
|
||||
of wStacktrace: onOff(c, n, {optStackTrace})
|
||||
of wLinetrace: onOff(c, n, {optLineTrace})
|
||||
of wDebugger: onOff(c, n, {optEndb})
|
||||
of wProfiler: onOff(c, n, {optProfiler})
|
||||
of wByRef: onOff(c, n, {optByRef})
|
||||
of wDynlib: processDynLib(c, n, nil)
|
||||
of wOptimization:
|
||||
if n.sons[1].kind != nkIdent:
|
||||
of wDynlib: processDynLib(c, n, nil)
|
||||
of wOptimization:
|
||||
if n.sons[1].kind != nkIdent:
|
||||
invalidPragma(n)
|
||||
else:
|
||||
else:
|
||||
case n.sons[1].ident.s.normalize
|
||||
of "speed":
|
||||
of "speed":
|
||||
incl(gOptions, optOptimizeSpeed)
|
||||
excl(gOptions, optOptimizeSize)
|
||||
of "size":
|
||||
excl(gOptions, optOptimizeSpeed)
|
||||
incl(gOptions, optOptimizeSize)
|
||||
of "none":
|
||||
of "none":
|
||||
excl(gOptions, optOptimizeSpeed)
|
||||
excl(gOptions, optOptimizeSize)
|
||||
else: localError(n.info, errNoneSpeedOrSizeExpected)
|
||||
of wImplicitStatic: onOff(c, n, {optImplicitStatic})
|
||||
of wPatterns: onOff(c, n, {optPatterns})
|
||||
else: result = true
|
||||
|
||||
proc processPush(c: PContext, n: PNode, start: int) =
|
||||
|
||||
proc processPush(c: PContext, n: PNode, start: int) =
|
||||
if n.sons[start-1].kind == nkExprColonExpr:
|
||||
localError(n.info, errGenerated, "':' after 'push' not supported")
|
||||
var x = newOptionEntry()
|
||||
@@ -355,41 +355,41 @@ proc processPush(c: PContext, n: PNode, start: int) =
|
||||
x.dynlib = y.dynlib
|
||||
x.notes = gNotes
|
||||
append(c.optionStack, x)
|
||||
for i in countup(start, sonsLen(n) - 1):
|
||||
for i in countup(start, sonsLen(n) - 1):
|
||||
if processOption(c, n.sons[i]):
|
||||
# simply store it somewhere:
|
||||
if x.otherPragmas.isNil:
|
||||
x.otherPragmas = newNodeI(nkPragma, n.info)
|
||||
x.otherPragmas.add n.sons[i]
|
||||
#localError(n.info, errOptionExpected)
|
||||
|
||||
proc processPop(c: PContext, n: PNode) =
|
||||
if c.optionStack.counter <= 1:
|
||||
|
||||
proc processPop(c: PContext, n: PNode) =
|
||||
if c.optionStack.counter <= 1:
|
||||
localError(n.info, errAtPopWithoutPush)
|
||||
else:
|
||||
gOptions = POptionEntry(c.optionStack.tail).options
|
||||
else:
|
||||
gOptions = POptionEntry(c.optionStack.tail).options
|
||||
gNotes = POptionEntry(c.optionStack.tail).notes
|
||||
remove(c.optionStack, c.optionStack.tail)
|
||||
|
||||
proc processDefine(c: PContext, n: PNode) =
|
||||
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
|
||||
proc processDefine(c: PContext, n: PNode) =
|
||||
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
|
||||
defineSymbol(n.sons[1].ident.s)
|
||||
message(n.info, warnDeprecated, "define")
|
||||
else:
|
||||
else:
|
||||
invalidPragma(n)
|
||||
|
||||
proc processUndef(c: PContext, n: PNode) =
|
||||
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
|
||||
|
||||
proc processUndef(c: PContext, n: PNode) =
|
||||
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
|
||||
undefSymbol(n.sons[1].ident.s)
|
||||
message(n.info, warnDeprecated, "undef")
|
||||
else:
|
||||
else:
|
||||
invalidPragma(n)
|
||||
|
||||
type
|
||||
TLinkFeature = enum
|
||||
|
||||
type
|
||||
TLinkFeature = enum
|
||||
linkNormal, linkSys
|
||||
|
||||
proc processCompile(c: PContext, n: PNode) =
|
||||
proc processCompile(c: PContext, n: PNode) =
|
||||
var s = expectStrLit(c, n)
|
||||
var found = findFile(s)
|
||||
if found == "": found = s
|
||||
@@ -397,7 +397,7 @@ proc processCompile(c: PContext, n: PNode) =
|
||||
extccomp.addExternalFileToCompile(found)
|
||||
extccomp.addFileToLink(completeCFilePath(trunc, false))
|
||||
|
||||
proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) =
|
||||
proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) =
|
||||
var f = expectStrLit(c, n)
|
||||
if splitFile(f).ext == "": f = addFileExt(f, CC[cCompiler].objExt)
|
||||
var found = findFile(f)
|
||||
@@ -407,8 +407,8 @@ proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) =
|
||||
of linkSys:
|
||||
extccomp.addFileToLink(libpath / completeCFilePath(found, false))
|
||||
else: internalError(n.info, "processCommonLink")
|
||||
|
||||
proc pragmaBreakpoint(c: PContext, n: PNode) =
|
||||
|
||||
proc pragmaBreakpoint(c: PContext, n: PNode) =
|
||||
discard getOptionalStr(c, n, "")
|
||||
|
||||
proc pragmaWatchpoint(c: PContext, n: PNode) =
|
||||
@@ -427,59 +427,59 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
|
||||
return
|
||||
# now parse the string literal and substitute symbols:
|
||||
var a = 0
|
||||
while true:
|
||||
while true:
|
||||
var b = strutils.find(str, marker, a)
|
||||
var sub = if b < 0: substr(str, a) else: substr(str, a, b - 1)
|
||||
if sub != "": addSon(result, newStrNode(nkStrLit, sub))
|
||||
if b < 0: break
|
||||
if b < 0: break
|
||||
var c = strutils.find(str, marker, b + 1)
|
||||
if c < 0: sub = substr(str, b + 1)
|
||||
else: sub = substr(str, b + 1, c - 1)
|
||||
if sub != "":
|
||||
if sub != "":
|
||||
var e = searchInScopes(con, getIdent(sub))
|
||||
if e != nil:
|
||||
if e != nil:
|
||||
if e.kind == skStub: loadStub(e)
|
||||
addSon(result, newSymNode(e))
|
||||
else:
|
||||
else:
|
||||
addSon(result, newStrNode(nkStrLit, sub))
|
||||
else:
|
||||
# an empty '``' produces a single '`'
|
||||
addSon(result, newStrNode(nkStrLit, $marker))
|
||||
if c < 0: break
|
||||
if c < 0: break
|
||||
a = c + 1
|
||||
else:
|
||||
illFormedAstLocal(n)
|
||||
result = newNode(nkAsmStmt, n.info)
|
||||
|
||||
proc pragmaEmit(c: PContext, n: PNode) =
|
||||
|
||||
proc pragmaEmit(c: PContext, n: PNode) =
|
||||
discard getStrLitNode(c, n)
|
||||
n.sons[1] = semAsmOrEmit(c, n, '`')
|
||||
|
||||
proc noVal(n: PNode) =
|
||||
proc noVal(n: PNode) =
|
||||
if n.kind == nkExprColonExpr: invalidPragma(n)
|
||||
|
||||
proc pragmaUnroll(c: PContext, n: PNode) =
|
||||
if c.p.nestedLoopCounter <= 0:
|
||||
proc pragmaUnroll(c: PContext, n: PNode) =
|
||||
if c.p.nestedLoopCounter <= 0:
|
||||
invalidPragma(n)
|
||||
elif n.kind == nkExprColonExpr:
|
||||
var unrollFactor = expectIntLit(c, n)
|
||||
if unrollFactor <% 32:
|
||||
if unrollFactor <% 32:
|
||||
n.sons[1] = newIntNode(nkIntLit, unrollFactor)
|
||||
else:
|
||||
else:
|
||||
invalidPragma(n)
|
||||
|
||||
proc pragmaLine(c: PContext, n: PNode) =
|
||||
if n.kind == nkExprColonExpr:
|
||||
n.sons[1] = c.semConstExpr(c, n.sons[1])
|
||||
let a = n.sons[1]
|
||||
if a.kind == nkPar:
|
||||
if a.kind == nkPar:
|
||||
var x = a.sons[0]
|
||||
var y = a.sons[1]
|
||||
if x.kind == nkExprColonExpr: x = x.sons[1]
|
||||
if y.kind == nkExprColonExpr: y = y.sons[1]
|
||||
if x.kind != nkStrLit:
|
||||
if x.kind != nkStrLit:
|
||||
localError(n.info, errStringLiteralExpected)
|
||||
elif y.kind != nkIntLit:
|
||||
elif y.kind != nkIntLit:
|
||||
localError(n.info, errIntLiteralExpected)
|
||||
else:
|
||||
n.info.fileIndex = msgs.fileInfoIdx(x.strVal)
|
||||
@@ -490,12 +490,12 @@ proc pragmaLine(c: PContext, n: PNode) =
|
||||
# sensible default:
|
||||
n.info = getInfoContext(-1)
|
||||
|
||||
proc processPragma(c: PContext, n: PNode, i: int) =
|
||||
proc processPragma(c: PContext, n: PNode, i: int) =
|
||||
var it = n.sons[i]
|
||||
if it.kind != nkExprColonExpr: invalidPragma(n)
|
||||
elif it.sons[0].kind != nkIdent: invalidPragma(n)
|
||||
elif it.sons[1].kind != nkIdent: invalidPragma(n)
|
||||
|
||||
|
||||
var userPragma = newSym(skTemplate, it.sons[1].ident, nil, it.info)
|
||||
var body = newNodeI(nkPragma, n.info)
|
||||
for j in i+1 .. sonsLen(n)-1: addSon(body, n.sons[j])
|
||||
@@ -508,7 +508,7 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) =
|
||||
if t.kind != tyObject:
|
||||
localError(x.info, errGenerated, "invalid type for raises/tags list")
|
||||
x.typ = t
|
||||
|
||||
|
||||
if n.kind == nkExprColonExpr:
|
||||
let it = n.sons[1]
|
||||
if it.kind notin {nkCurly, nkBracket}:
|
||||
@@ -569,7 +569,7 @@ proc deprecatedStmt(c: PContext; pragma: PNode) =
|
||||
localError(n.info, "key:value pair expected")
|
||||
|
||||
proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym =
|
||||
if it.kind != nkExprColonExpr:
|
||||
if it.kind != nkExprColonExpr:
|
||||
invalidPragma(it); return
|
||||
let n = it[1]
|
||||
if n.kind == nkSym:
|
||||
@@ -592,9 +592,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||
var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
|
||||
if key.kind == nkIdent:
|
||||
var userPragma = strTableGet(c.userPragmas, key.ident)
|
||||
if userPragma != nil:
|
||||
if userPragma != nil:
|
||||
inc c.instCounter
|
||||
if c.instCounter > 100:
|
||||
if c.instCounter > 100:
|
||||
globalError(it.info, errRecursiveDependencyX, userPragma.name.s)
|
||||
pragma(c, sym, userPragma.ast, validPragmas)
|
||||
# ensure the pragma is also remember for generic instantiations in other
|
||||
@@ -603,9 +603,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||
dec c.instCounter
|
||||
else:
|
||||
var k = whichKeyword(key.ident)
|
||||
if k in validPragmas:
|
||||
if k in validPragmas:
|
||||
case k
|
||||
of wExportc:
|
||||
of wExportc:
|
||||
makeExternExport(sym, getOptionalStr(c, it, "$1"), it.info)
|
||||
incl(sym.flags, sfUsed) # avoid wrong hints
|
||||
of wImportc: makeExternImport(sym, getOptionalStr(c, it, "$1"))
|
||||
@@ -627,16 +627,16 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||
var align = expectIntLit(c, it)
|
||||
if (not isPowerOfTwo(align) and align != 0) or align >% high(int16):
|
||||
localError(it.info, errPowerOfTwoExpected)
|
||||
else:
|
||||
else:
|
||||
sym.typ.align = align.int16
|
||||
of wSize:
|
||||
if sym.typ == nil: invalidPragma(it)
|
||||
var size = expectIntLit(c, it)
|
||||
if not isPowerOfTwo(size) or size <= 0 or size > 8:
|
||||
if not isPowerOfTwo(size) or size <= 0 or size > 8:
|
||||
localError(it.info, errPowerOfTwoExpected)
|
||||
else:
|
||||
sym.typ.size = size
|
||||
of wNodecl:
|
||||
of wNodecl:
|
||||
noVal(it)
|
||||
incl(sym.loc.flags, lfNoDecl)
|
||||
of wPure, wAsmNoStackFrame:
|
||||
@@ -644,19 +644,19 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||
if sym != nil:
|
||||
if k == wPure and sym.kind in routineKinds: invalidPragma(it)
|
||||
else: incl(sym.flags, sfPure)
|
||||
of wVolatile:
|
||||
of wVolatile:
|
||||
noVal(it)
|
||||
incl(sym.flags, sfVolatile)
|
||||
of wRegister:
|
||||
of wRegister:
|
||||
noVal(it)
|
||||
incl(sym.flags, sfRegister)
|
||||
of wThreadVar:
|
||||
of wThreadVar:
|
||||
noVal(it)
|
||||
incl(sym.flags, sfThread)
|
||||
of wDeadCodeElim: pragmaDeadCodeElim(c, it)
|
||||
of wNoForward: pragmaNoForward(c, it)
|
||||
of wMagic: processMagic(c, it, sym)
|
||||
of wCompileTime:
|
||||
of wCompileTime:
|
||||
noVal(it)
|
||||
incl(sym.flags, sfCompileTime)
|
||||
incl(sym.loc.flags, lfNoDecl)
|
||||
@@ -664,15 +664,15 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||
noVal(it)
|
||||
incl(sym.flags, sfGlobal)
|
||||
incl(sym.flags, sfPure)
|
||||
of wMerge:
|
||||
of wMerge:
|
||||
noVal(it)
|
||||
incl(sym.flags, sfMerge)
|
||||
of wHeader:
|
||||
of wHeader:
|
||||
var lib = getLib(c, libHeader, getStrLitNode(c, it))
|
||||
addToLib(lib, sym)
|
||||
incl(sym.flags, sfImportc)
|
||||
incl(sym.loc.flags, lfHeader)
|
||||
incl(sym.loc.flags, lfNoDecl)
|
||||
incl(sym.loc.flags, lfNoDecl)
|
||||
# implies nodecl, because otherwise header would not make sense
|
||||
if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s)
|
||||
of wDestructor:
|
||||
@@ -685,13 +685,13 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||
noVal(it)
|
||||
incl(sym.flags, sfNoSideEffect)
|
||||
if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect)
|
||||
of wSideeffect:
|
||||
of wSideeffect:
|
||||
noVal(it)
|
||||
incl(sym.flags, sfSideEffect)
|
||||
of wNoreturn:
|
||||
of wNoreturn:
|
||||
noVal(it)
|
||||
incl(sym.flags, sfNoReturn)
|
||||
of wDynlib:
|
||||
of wDynlib:
|
||||
processDynLib(c, it, sym)
|
||||
of wCompilerproc:
|
||||
noVal(it) # compilerproc may not get a string!
|
||||
@@ -703,7 +703,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||
if it.kind == nkExprColonExpr: deprecatedStmt(c, it)
|
||||
elif sym != nil: incl(sym.flags, sfDeprecated)
|
||||
else: incl(c.module.flags, sfDeprecated)
|
||||
of wVarargs:
|
||||
of wVarargs:
|
||||
noVal(it)
|
||||
if sym.typ == nil: invalidPragma(it)
|
||||
else: incl(sym.typ.flags, tfVarargs)
|
||||
@@ -713,7 +713,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||
else:
|
||||
noVal(it)
|
||||
incl(sym.flags, sfBorrow)
|
||||
of wFinal:
|
||||
of wFinal:
|
||||
noVal(it)
|
||||
if sym.typ == nil: invalidPragma(it)
|
||||
else: incl(sym.typ.flags, tfFinal)
|
||||
@@ -745,10 +745,10 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||
else: incl(sym.typ.flags, tfPacked)
|
||||
of wHint: message(it.info, hintUser, expectStrLit(c, it))
|
||||
of wWarning: message(it.info, warnUser, expectStrLit(c, it))
|
||||
of wError:
|
||||
of wError:
|
||||
if sym != nil and sym.isRoutine:
|
||||
# This is subtle but correct: the error *statement* is only
|
||||
# allowed for top level statements. Seems to be easier than
|
||||
# allowed for top level statements. Seems to be easier than
|
||||
# distinguishing properly between
|
||||
# ``proc p() {.error}`` and ``proc p() = {.error: "msg".}``
|
||||
noVal(it)
|
||||
@@ -765,11 +765,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||
of wPassc: extccomp.addCompileOption(expectStrLit(c, it))
|
||||
of wBreakpoint: pragmaBreakpoint(c, it)
|
||||
of wWatchPoint: pragmaWatchpoint(c, it)
|
||||
of wPush:
|
||||
of wPush:
|
||||
processPush(c, n, i + 1)
|
||||
result = true
|
||||
result = true
|
||||
of wPop: processPop(c, it)
|
||||
of wPragma:
|
||||
of wPragma:
|
||||
processPragma(c, n, i)
|
||||
result = true
|
||||
of wDiscardable:
|
||||
@@ -779,16 +779,16 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||
noVal(it)
|
||||
if sym != nil: incl(sym.flags, sfNoInit)
|
||||
of wCodegenDecl: processCodegenDecl(c, it, sym)
|
||||
of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks,
|
||||
wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
|
||||
of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks,
|
||||
wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
|
||||
wLinedir, wStacktrace, wLinetrace, wOptimization,
|
||||
wCallconv,
|
||||
wCallconv,
|
||||
wDebugger, wProfiler, wFloatchecks, wNanChecks, wInfChecks,
|
||||
wPatterns:
|
||||
if processOption(c, it):
|
||||
# calling conventions (boring...):
|
||||
localError(it.info, errOptionExpected)
|
||||
of FirstCallConv..LastCallConv:
|
||||
of FirstCallConv..LastCallConv:
|
||||
assert(sym != nil)
|
||||
if sym.typ == nil: invalidPragma(it)
|
||||
else: sym.typ.callConv = wordToCallConv(k)
|
||||
@@ -843,14 +843,14 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||
of wInjectStmt:
|
||||
if it.kind != nkExprColonExpr:
|
||||
localError(it.info, errExprExpected)
|
||||
else:
|
||||
else:
|
||||
it.sons[1] = c.semExpr(c, it.sons[1])
|
||||
of wExperimental:
|
||||
noVal(it)
|
||||
if isTopLevel(c):
|
||||
c.module.flags.incl sfExperimental
|
||||
else:
|
||||
localError(it.info, "'experimental' pragma only valid as toplevel statement")
|
||||
localError(it.info, "'experimental' pragma only valid as toplevel statement")
|
||||
else: invalidPragma(it)
|
||||
else: invalidPragma(it)
|
||||
else: processNote(c, it)
|
||||
@@ -884,7 +884,7 @@ proc hasPragma*(n: PNode, pragma: TSpecialWord): bool =
|
||||
var key = if p.kind == nkExprColonExpr: p[0] else: p
|
||||
if key.kind == nkIdent and whichKeyword(key.ident) == pragma:
|
||||
return true
|
||||
|
||||
|
||||
return false
|
||||
|
||||
proc pragmaRec(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
||||
|
||||
Reference in New Issue
Block a user