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