further steps for thread support; bootstrapping should require unzip C sources and ./build.sh
This commit is contained in:
parent
c7b3d828be
commit
67a30d8371
21 changed files with 372 additions and 421 deletions
|
|
@ -154,29 +154,25 @@ proc getStorageLoc(n: PNode): TStorageLoc =
|
||||||
else: result = OnUnknown
|
else: result = OnUnknown
|
||||||
|
|
||||||
proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
if (dest.s == OnStack) or not (optRefcGC in gGlobalOptions):
|
if dest.s == OnStack or optRefcGC notin gGlobalOptions:
|
||||||
appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
appf(p.s[cpsStmts], "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
|
||||||
elif dest.s == OnHeap:
|
elif dest.s == OnHeap:
|
||||||
# location is on heap
|
# location is on heap
|
||||||
# now the writer barrier is inlined for performance:
|
# now the writer barrier is inlined for performance:
|
||||||
#
|
#
|
||||||
# if afSrcIsNotNil in flags then begin
|
# if afSrcIsNotNil in flags:
|
||||||
# UseMagic(p.module, 'nimGCref');
|
# UseMagic(p.module, 'nimGCref')
|
||||||
# appf(p.s[cpsStmts], 'nimGCref($1);$n', [rdLoc(src)]);
|
# appf(p.s[cpsStmts], 'nimGCref($1);$n', [rdLoc(src)])
|
||||||
# end
|
# elif afSrcIsNil notin flags:
|
||||||
# else if not (afSrcIsNil in flags) then begin
|
# UseMagic(p.module, 'nimGCref')
|
||||||
# UseMagic(p.module, 'nimGCref');
|
# appf(p.s[cpsStmts], 'if ($1) nimGCref($1);$n', [rdLoc(src)])
|
||||||
# appf(p.s[cpsStmts], 'if ($1) nimGCref($1);$n', [rdLoc(src)]);
|
# if afDestIsNotNil in flags:
|
||||||
# end;
|
# UseMagic(p.module, 'nimGCunref')
|
||||||
# if afDestIsNotNil in flags then begin
|
# appf(p.s[cpsStmts], 'nimGCunref($1);$n', [rdLoc(dest)])
|
||||||
# UseMagic(p.module, 'nimGCunref');
|
# elif afDestIsNil notin flags:
|
||||||
# appf(p.s[cpsStmts], 'nimGCunref($1);$n', [rdLoc(dest)]);
|
# UseMagic(p.module, 'nimGCunref')
|
||||||
# end
|
# appf(p.s[cpsStmts], 'if ($1) nimGCunref($1);$n', [rdLoc(dest)])
|
||||||
# else if not (afDestIsNil in flags) then begin
|
# appf(p.s[cpsStmts], '$1 = $2;$n', [rdLoc(dest), rdLoc(src)])
|
||||||
# UseMagic(p.module, 'nimGCunref');
|
|
||||||
# appf(p.s[cpsStmts], 'if ($1) nimGCunref($1);$n', [rdLoc(dest)]);
|
|
||||||
# end;
|
|
||||||
# appf(p.s[cpsStmts], '$1 = $2;$n', [rdLoc(dest), rdLoc(src)]);
|
|
||||||
if canFormAcycle(dest.t):
|
if canFormAcycle(dest.t):
|
||||||
appcg(p.module, p.s[cpsStmts], "#asgnRef((void**) $1, $2);$n",
|
appcg(p.module, p.s[cpsStmts], "#asgnRef((void**) $1, $2);$n",
|
||||||
[addrLoc(dest), rdLoc(src)])
|
[addrLoc(dest), rdLoc(src)])
|
||||||
|
|
@ -196,7 +192,7 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
# (for objects, etc.):
|
# (for objects, etc.):
|
||||||
if needToCopy notin flags or
|
if needToCopy notin flags or
|
||||||
tfShallow in skipTypes(dest.t, abstractVarRange).flags:
|
tfShallow in skipTypes(dest.t, abstractVarRange).flags:
|
||||||
if (dest.s == OnStack) or not (optRefcGC in gGlobalOptions):
|
if dest.s == OnStack or optRefcGC notin gGlobalOptions:
|
||||||
appcg(p, cpsStmts,
|
appcg(p, cpsStmts,
|
||||||
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
|
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($3));$n",
|
||||||
[addrLoc(dest), addrLoc(src), rdLoc(dest)])
|
[addrLoc(dest), addrLoc(src), rdLoc(dest)])
|
||||||
|
|
@ -224,7 +220,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
if needToCopy notin flags:
|
if needToCopy notin flags:
|
||||||
genRefAssign(p, dest, src, flags)
|
genRefAssign(p, dest, src, flags)
|
||||||
else:
|
else:
|
||||||
if (dest.s == OnStack) or not (optRefcGC in gGlobalOptions):
|
if dest.s == OnStack or optRefcGC notin gGlobalOptions:
|
||||||
appcg(p, cpsStmts, "$1 = #copyString($2);$n", [rdLoc(dest), rdLoc(src)])
|
appcg(p, cpsStmts, "$1 = #copyString($2);$n", [rdLoc(dest), rdLoc(src)])
|
||||||
elif dest.s == OnHeap:
|
elif dest.s == OnHeap:
|
||||||
appcg(p, cpsStmts, "#asgnRefNoCycle((void**) $1, #copyString($2));$n",
|
appcg(p, cpsStmts, "#asgnRefNoCycle((void**) $1, #copyString($2));$n",
|
||||||
|
|
@ -827,18 +823,6 @@ proc genCall(p: BProc, t: PNode, d: var TLoc) =
|
||||||
app(p.s[cpsStmts], pl)
|
app(p.s[cpsStmts], pl)
|
||||||
app(p.s[cpsStmts], ';' & tnl)
|
app(p.s[cpsStmts], ';' & tnl)
|
||||||
|
|
||||||
when false:
|
|
||||||
app(pl, ")")
|
|
||||||
if (typ.sons[0] != nil) and not invalidRetType:
|
|
||||||
if d.k == locNone: getTemp(p, typ.sons[0], d)
|
|
||||||
assert(d.t != nil) # generate an assignment to d:
|
|
||||||
initLoc(list, locCall, nil, OnUnknown)
|
|
||||||
list.r = pl
|
|
||||||
genAssignment(p, d, list, {}) # no need for deep copying
|
|
||||||
else:
|
|
||||||
app(p.s[cpsStmts], pl)
|
|
||||||
app(p.s[cpsStmts], ';' & tnl)
|
|
||||||
|
|
||||||
proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
|
proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
|
||||||
# <Nimrod code>
|
# <Nimrod code>
|
||||||
# s = 'Hello ' & name & ', how do you feel?' & 'z'
|
# s = 'Hello ' & name & ', how do you feel?' & 'z'
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,6 @@ const
|
||||||
# over 'RangeExpandLimit' elements
|
# over 'RangeExpandLimit' elements
|
||||||
stringCaseThreshold = 8
|
stringCaseThreshold = 8
|
||||||
# above X strings a hash-switch for strings is generated
|
# above X strings a hash-switch for strings is generated
|
||||||
# this version sets it too high to avoid hashing, because this has not
|
|
||||||
# been tested for a long time
|
|
||||||
|
|
||||||
proc genLineDir(p: BProc, t: PNode) =
|
proc genLineDir(p: BProc, t: PNode) =
|
||||||
var line = toLinenumber(t.info) # BUGFIX
|
var line = toLinenumber(t.info) # BUGFIX
|
||||||
|
|
@ -23,11 +21,11 @@ proc genLineDir(p: BProc, t: PNode) =
|
||||||
appff(p.s[cpsStmts], "#line $2 \"$1\"$n", "; line $2 \"$1\"$n",
|
appff(p.s[cpsStmts], "#line $2 \"$1\"$n", "; line $2 \"$1\"$n",
|
||||||
[toRope(toFilename(t.info)), toRope(line)])
|
[toRope(toFilename(t.info)), toRope(line)])
|
||||||
if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and
|
if ({optStackTrace, optEndb} * p.Options == {optStackTrace, optEndb}) and
|
||||||
((p.prc == nil) or not (sfPure in p.prc.flags)):
|
(p.prc == nil or sfPure notin p.prc.flags):
|
||||||
appcg(p, cpsStmts, "#endb($1);$n", [toRope(line)])
|
appcg(p, cpsStmts, "#endb($1);$n", [toRope(line)])
|
||||||
elif ({optLineTrace, optStackTrace} * p.Options ==
|
elif ({optLineTrace, optStackTrace} * p.Options ==
|
||||||
{optLineTrace, optStackTrace}) and
|
{optLineTrace, optStackTrace}) and
|
||||||
((p.prc == nil) or not (sfPure in p.prc.flags)):
|
(p.prc == nil or sfPure notin p.prc.flags):
|
||||||
appf(p.s[cpsStmts], "F.line = $1;F.filename = $2;$n",
|
appf(p.s[cpsStmts], "F.line = $1;F.filename = $2;$n",
|
||||||
[toRope(line), makeCString(toFilename(t.info).extractFilename)])
|
[toRope(line), makeCString(toFilename(t.info).extractFilename)])
|
||||||
|
|
||||||
|
|
@ -458,7 +456,7 @@ proc genTryStmtCpp(p: BProc, t: PNode) =
|
||||||
rethrowFlag = getTempName()
|
rethrowFlag = getTempName()
|
||||||
appf(p.s[cpsLocals], "volatile NIM_BOOL $1 = NIM_FALSE;$n", [rethrowFlag])
|
appf(p.s[cpsLocals], "volatile NIM_BOOL $1 = NIM_FALSE;$n", [rethrowFlag])
|
||||||
if optStackTrace in p.Options:
|
if optStackTrace in p.Options:
|
||||||
appcg(p, cpsStmts, "#framePtr = (TFrame*)&F;" & tnl)
|
appcg(p, cpsStmts, "#setFrame((TFrame*)&F);$n")
|
||||||
app(p.s[cpsStmts], "try {" & tnl)
|
app(p.s[cpsStmts], "try {" & tnl)
|
||||||
add(p.nestedTryStmts, t)
|
add(p.nestedTryStmts, t)
|
||||||
genStmts(p, t.sons[0])
|
genStmts(p, t.sons[0])
|
||||||
|
|
@ -493,6 +491,72 @@ proc genTryStmtCpp(p: BProc, t: PNode) =
|
||||||
if rethrowFlag != nil:
|
if rethrowFlag != nil:
|
||||||
appf(p.s[cpsStmts], "if ($1) { throw; }$n", [rethrowFlag])
|
appf(p.s[cpsStmts], "if ($1) { throw; }$n", [rethrowFlag])
|
||||||
|
|
||||||
|
proc genTryStmtCpp2(p: BProc, t: PNode) =
|
||||||
|
# code to generate:
|
||||||
|
#
|
||||||
|
# TSafePoint sp;
|
||||||
|
# pushSafePoint(&sp);
|
||||||
|
# sp.status = setjmp(sp.context);
|
||||||
|
# if (sp.status == 0) {
|
||||||
|
# myDiv(4, 9);
|
||||||
|
# popSafePoint();
|
||||||
|
# } else {
|
||||||
|
# popSafePoint();
|
||||||
|
# /* except DivisionByZero: */
|
||||||
|
# if (sp.status == DivisionByZero) {
|
||||||
|
# printf('Division by Zero\n');
|
||||||
|
# clearException();
|
||||||
|
# } else {
|
||||||
|
# clearException();
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
# /* finally: */
|
||||||
|
# printf('fin!\n');
|
||||||
|
# if (exception not cleared)
|
||||||
|
# propagateCurrentException();
|
||||||
|
genLineDir(p, t)
|
||||||
|
var safePoint = getTempName()
|
||||||
|
discard cgsym(p.module, "E_Base")
|
||||||
|
appcg(p, cpsLocals, "#TSafePoint $1;$n", [safePoint])
|
||||||
|
appcg(p, cpsStmts, "#pushSafePoint(&$1);$n" &
|
||||||
|
"$1.status = setjmp($1.context);$n", [safePoint])
|
||||||
|
if optStackTrace in p.Options:
|
||||||
|
appcg(p, cpsStmts, "#setFrame((TFrame*)&F);$n")
|
||||||
|
appf(p.s[cpsStmts], "if ($1.status == 0) {$n", [safePoint])
|
||||||
|
var length = sonsLen(t)
|
||||||
|
add(p.nestedTryStmts, t)
|
||||||
|
genStmts(p, t.sons[0])
|
||||||
|
appcg(p, cpsStmts, "#popSafePoint();$n} else {$n#popSafePoint();$n")
|
||||||
|
var i = 1
|
||||||
|
while (i < length) and (t.sons[i].kind == nkExceptBranch):
|
||||||
|
var blen = sonsLen(t.sons[i])
|
||||||
|
if blen == 1:
|
||||||
|
# general except section:
|
||||||
|
if i > 1: app(p.s[cpsStmts], "else {" & tnl)
|
||||||
|
genStmts(p, t.sons[i].sons[0])
|
||||||
|
appcg(p, cpsStmts, "$1.status = 0;#popCurrentException();$n", [safePoint])
|
||||||
|
if i > 1: app(p.s[cpsStmts], '}' & tnl)
|
||||||
|
else:
|
||||||
|
var orExpr: PRope = nil
|
||||||
|
for j in countup(0, blen - 2):
|
||||||
|
assert(t.sons[i].sons[j].kind == nkType)
|
||||||
|
if orExpr != nil: app(orExpr, "||")
|
||||||
|
appcg(p.module, orExpr,
|
||||||
|
"#isObj(#getCurrentException()->Sup.m_type, $1)",
|
||||||
|
[genTypeInfo(p.module, t.sons[i].sons[j].typ)])
|
||||||
|
if i > 1: app(p.s[cpsStmts], "else ")
|
||||||
|
appf(p.s[cpsStmts], "if ($1) {$n", [orExpr])
|
||||||
|
genStmts(p, t.sons[i].sons[blen-1])
|
||||||
|
# code to clear the exception:
|
||||||
|
appcg(p, cpsStmts, "$1.status = 0;#popCurrentException();}$n",
|
||||||
|
[safePoint])
|
||||||
|
inc(i)
|
||||||
|
app(p.s[cpsStmts], '}' & tnl) # end of if statement
|
||||||
|
discard pop(p.nestedTryStmts)
|
||||||
|
if i < length and t.sons[i].kind == nkFinally:
|
||||||
|
genStmts(p, t.sons[i].sons[0])
|
||||||
|
appcg(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint])
|
||||||
|
|
||||||
proc genTryStmt(p: BProc, t: PNode) =
|
proc genTryStmt(p: BProc, t: PNode) =
|
||||||
# code to generate:
|
# code to generate:
|
||||||
#
|
#
|
||||||
|
|
@ -523,7 +587,7 @@ proc genTryStmt(p: BProc, t: PNode) =
|
||||||
appcg(p, cpsStmts, "#pushSafePoint(&$1);$n" &
|
appcg(p, cpsStmts, "#pushSafePoint(&$1);$n" &
|
||||||
"$1.status = setjmp($1.context);$n", [safePoint])
|
"$1.status = setjmp($1.context);$n", [safePoint])
|
||||||
if optStackTrace in p.Options:
|
if optStackTrace in p.Options:
|
||||||
appcg(p, cpsStmts, "#framePtr = (TFrame*)&F;" & tnl)
|
appcg(p, cpsStmts, "#setFrame((TFrame*)&F);$n")
|
||||||
appf(p.s[cpsStmts], "if ($1.status == 0) {$n", [safePoint])
|
appf(p.s[cpsStmts], "if ($1.status == 0) {$n", [safePoint])
|
||||||
var length = sonsLen(t)
|
var length = sonsLen(t)
|
||||||
add(p.nestedTryStmts, t)
|
add(p.nestedTryStmts, t)
|
||||||
|
|
@ -543,8 +607,9 @@ proc genTryStmt(p: BProc, t: PNode) =
|
||||||
for j in countup(0, blen - 2):
|
for j in countup(0, blen - 2):
|
||||||
assert(t.sons[i].sons[j].kind == nkType)
|
assert(t.sons[i].sons[j].kind == nkType)
|
||||||
if orExpr != nil: app(orExpr, "||")
|
if orExpr != nil: app(orExpr, "||")
|
||||||
appcg(p.module, orExpr, "#getCurrentException()->Sup.m_type == $1",
|
appcg(p.module, orExpr,
|
||||||
[genTypeInfo(p.module, t.sons[i].sons[j].typ)])
|
"#isObj(#getCurrentException()->Sup.m_type, $1)",
|
||||||
|
[genTypeInfo(p.module, t.sons[i].sons[j].typ)])
|
||||||
if i > 1: app(p.s[cpsStmts], "else ")
|
if i > 1: app(p.s[cpsStmts], "else ")
|
||||||
appf(p.s[cpsStmts], "if ($1) {$n", [orExpr])
|
appf(p.s[cpsStmts], "if ($1) {$n", [orExpr])
|
||||||
genStmts(p, t.sons[i].sons[blen-1])
|
genStmts(p, t.sons[i].sons[blen-1])
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,7 @@ type
|
||||||
module*: PSym
|
module*: PSym
|
||||||
filename*: string
|
filename*: string
|
||||||
s*: TCFileSections # sections of the C file
|
s*: TCFileSections # sections of the C file
|
||||||
|
PreventStackTrace: bool # true if stack traces need to be prevented
|
||||||
cfilename*: string # filename of the module (including path,
|
cfilename*: string # filename of the module (including path,
|
||||||
# without extension)
|
# without extension)
|
||||||
typeCache*: TIdTable # cache the generated types
|
typeCache*: TIdTable # cache the generated types
|
||||||
|
|
@ -100,7 +101,6 @@ type
|
||||||
typeNodesName*, nimTypesName*: PRope # used for type info generation
|
typeNodesName*, nimTypesName*: PRope # used for type info generation
|
||||||
labels*: natural # for generating unique module-scope names
|
labels*: natural # for generating unique module-scope names
|
||||||
|
|
||||||
|
|
||||||
var
|
var
|
||||||
mainModProcs, mainModInit: PRope # parts of the main module
|
mainModProcs, mainModInit: PRope # parts of the main module
|
||||||
gMapping: PRope # the generated mapping file (if requested)
|
gMapping: PRope # the generated mapping file (if requested)
|
||||||
|
|
@ -603,19 +603,12 @@ proc retIsNotVoid(s: PSym): bool =
|
||||||
proc initFrame(p: BProc, procname, filename: PRope): PRope =
|
proc initFrame(p: BProc, procname, filename: PRope): PRope =
|
||||||
result = ropecg(p.module,
|
result = ropecg(p.module,
|
||||||
"F.procname = $1;$n" &
|
"F.procname = $1;$n" &
|
||||||
"F.prev = #framePtr;$n" &
|
|
||||||
"F.filename = $2;$n" &
|
"F.filename = $2;$n" &
|
||||||
"F.line = 0;$n" &
|
"F.line = 0;$n" &
|
||||||
"framePtr = (TFrame*)&F;$n", [procname, filename])
|
"#pushFrame((TFrame*)&F);$n", [procname, filename])
|
||||||
|
|
||||||
proc deinitFrame(p: BProc): PRope =
|
proc deinitFrame(p: BProc): PRope =
|
||||||
inc(p.labels, 3)
|
result = ropecg(p.module, "#popFrame();$n")
|
||||||
result = ropeff("framePtr = framePtr->prev;$n",
|
|
||||||
"%LOC$1 = load %TFrame* @framePtr$n" &
|
|
||||||
"%LOC$2 = getelementptr %TFrame* %LOC$1, %NI 0$n" &
|
|
||||||
"%LOC$3 = load %TFrame** %LOC$2$n" &
|
|
||||||
"store %TFrame* $LOC$3, %TFrame** @framePtr", [toRope(p.labels),
|
|
||||||
toRope(p.labels - 1), toRope(p.labels - 2)])
|
|
||||||
|
|
||||||
proc genProcAux(m: BModule, prc: PSym) =
|
proc genProcAux(m: BModule, prc: PSym) =
|
||||||
var
|
var
|
||||||
|
|
@ -628,7 +621,7 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||||
header = con("N_LIB_EXPORT ", header)
|
header = con("N_LIB_EXPORT ", header)
|
||||||
returnStmt = nil
|
returnStmt = nil
|
||||||
assert(prc.ast != nil)
|
assert(prc.ast != nil)
|
||||||
if not (sfPure in prc.flags) and (prc.typ.sons[0] != nil):
|
if sfPure notin prc.flags and prc.typ.sons[0] != nil:
|
||||||
res = prc.ast.sons[resultPos].sym # get result symbol
|
res = prc.ast.sons[resultPos].sym # get result symbol
|
||||||
if not isInvalidReturnType(prc.typ.sons[0]):
|
if not isInvalidReturnType(prc.typ.sons[0]):
|
||||||
# declare the result symbol:
|
# declare the result symbol:
|
||||||
|
|
@ -869,7 +862,10 @@ proc genInitCode(m: BModule) =
|
||||||
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)])
|
||||||
if optStackTrace in m.initProc.options:
|
if optStackTrace in m.initProc.options:
|
||||||
|
# BUT: the generated init code might depend on a current frame, so
|
||||||
|
# declare it nevertheless:
|
||||||
getFrameDecl(m.initProc)
|
getFrameDecl(m.initProc)
|
||||||
|
if optStackTrace in m.initProc.options and not m.PreventStackTrace:
|
||||||
app(prc, m.initProc.s[cpsLocals])
|
app(prc, m.initProc.s[cpsLocals])
|
||||||
app(prc, m.s[cfsTypeInit1])
|
app(prc, m.s[cfsTypeInit1])
|
||||||
procname = CStringLit(m.initProc, prc, m.module.name.s)
|
procname = CStringLit(m.initProc, prc, m.module.name.s)
|
||||||
|
|
@ -884,7 +880,8 @@ proc genInitCode(m: BModule) =
|
||||||
app(prc, m.s[cfsDynLibInit])
|
app(prc, m.s[cfsDynLibInit])
|
||||||
app(prc, m.initProc.s[cpsInit])
|
app(prc, m.initProc.s[cpsInit])
|
||||||
app(prc, m.initProc.s[cpsStmts])
|
app(prc, m.initProc.s[cpsStmts])
|
||||||
if optStackTrace in m.initProc.options: app(prc, deinitFrame(m.initProc))
|
if optStackTrace in m.initProc.options and not m.PreventStackTrace:
|
||||||
|
app(prc, deinitFrame(m.initProc))
|
||||||
app(prc, '}' & tnl & tnl)
|
app(prc, '}' & tnl & tnl)
|
||||||
app(m.s[cfsProcs], prc)
|
app(m.s[cfsProcs], prc)
|
||||||
|
|
||||||
|
|
@ -911,6 +908,7 @@ proc rawNewModule(module: PSym, filename: string): BModule =
|
||||||
result.forwardedProcs = @[]
|
result.forwardedProcs = @[]
|
||||||
result.typeNodesName = getTempName()
|
result.typeNodesName = getTempName()
|
||||||
result.nimTypesName = getTempName()
|
result.nimTypesName = getTempName()
|
||||||
|
result.PreventStackTrace = sfSystemModule in module.flags
|
||||||
|
|
||||||
proc newModule(module: PSym, filename: string): BModule =
|
proc newModule(module: PSym, filename: string): BModule =
|
||||||
result = rawNewModule(module, filename)
|
result = rawNewModule(module, filename)
|
||||||
|
|
@ -923,6 +921,7 @@ proc registerTypeInfoModule() =
|
||||||
const moduleName = "nim__dat"
|
const moduleName = "nim__dat"
|
||||||
var s = NewSym(skModule, getIdent(moduleName), nil)
|
var s = NewSym(skModule, getIdent(moduleName), nil)
|
||||||
gNimDat = rawNewModule(s, joinPath(options.projectPath, moduleName) & ".nim")
|
gNimDat = rawNewModule(s, joinPath(options.projectPath, moduleName) & ".nim")
|
||||||
|
gNimDat.PreventStackTrace = true
|
||||||
addPendingModule(gNimDat)
|
addPendingModule(gNimDat)
|
||||||
appff(mainModProcs, "N_NOINLINE(void, $1)(void);$n",
|
appff(mainModProcs, "N_NOINLINE(void, $1)(void);$n",
|
||||||
"declare void $1() noinline$n", [getInitName(s)])
|
"declare void $1() noinline$n", [getInitName(s)])
|
||||||
|
|
@ -935,7 +934,6 @@ proc myOpenCached(module: PSym, filename: string,
|
||||||
rd: PRodReader): PPassContext =
|
rd: PRodReader): PPassContext =
|
||||||
if gNimDat == nil:
|
if gNimDat == nil:
|
||||||
registerTypeInfoModule()
|
registerTypeInfoModule()
|
||||||
#MessageOut('cgen.myOpenCached has been called ' + filename)
|
|
||||||
var cfile = changeFileExt(completeCFilePath(filename), cExt)
|
var cfile = changeFileExt(completeCFilePath(filename), cExt)
|
||||||
var cfilenoext = changeFileExt(cfile, "")
|
var cfilenoext = changeFileExt(cfile, "")
|
||||||
addFileToLink(cfilenoext)
|
addFileToLink(cfilenoext)
|
||||||
|
|
|
||||||
141
install.sh
141
install.sh
|
|
@ -63,15 +63,6 @@ if [ $# -eq 1 ] ; then
|
||||||
mkdir -p $libdir/wrappers/sdl || exit 1
|
mkdir -p $libdir/wrappers/sdl || exit 1
|
||||||
mkdir -p $libdir/wrappers/x11 || exit 1
|
mkdir -p $libdir/wrappers/x11 || exit 1
|
||||||
mkdir -p $libdir/wrappers/zip || exit 1
|
mkdir -p $libdir/wrappers/zip || exit 1
|
||||||
mkdir -p $libdir/oldwrappers || exit 1
|
|
||||||
mkdir -p $libdir/oldwrappers/cairo || exit 1
|
|
||||||
mkdir -p $libdir/oldwrappers/gtk || exit 1
|
|
||||||
mkdir -p $libdir/oldwrappers/lua || exit 1
|
|
||||||
mkdir -p $libdir/oldwrappers/opengl || exit 1
|
|
||||||
mkdir -p $libdir/oldwrappers/pcre || exit 1
|
|
||||||
mkdir -p $libdir/oldwrappers/sdl || exit 1
|
|
||||||
mkdir -p $libdir/oldwrappers/x11 || exit 1
|
|
||||||
mkdir -p $libdir/oldwrappers/zip || exit 1
|
|
||||||
mkdir -p $libdir/windows || exit 1
|
mkdir -p $libdir/windows || exit 1
|
||||||
mkdir -p $libdir/posix || exit 1
|
mkdir -p $libdir/posix || exit 1
|
||||||
mkdir -p $libdir/ecmas || exit 1
|
mkdir -p $libdir/ecmas || exit 1
|
||||||
|
|
@ -140,8 +131,6 @@ if [ $# -eq 1 ] ; then
|
||||||
chmod 644 $docdir/tut1.txt
|
chmod 644 $docdir/tut1.txt
|
||||||
cp doc/tut2.txt $docdir/tut2.txt || exit 1
|
cp doc/tut2.txt $docdir/tut2.txt || exit 1
|
||||||
chmod 644 $docdir/tut2.txt
|
chmod 644 $docdir/tut2.txt
|
||||||
cp doc/manual.html $docdir/manual.html || exit 1
|
|
||||||
chmod 644 $docdir/manual.html
|
|
||||||
cp doc/mytest.cfg $docdir/mytest.cfg || exit 1
|
cp doc/mytest.cfg $docdir/mytest.cfg || exit 1
|
||||||
chmod 644 $docdir/mytest.cfg
|
chmod 644 $docdir/mytest.cfg
|
||||||
cp doc/c2nim.pdf $docdir/c2nim.pdf || exit 1
|
cp doc/c2nim.pdf $docdir/c2nim.pdf || exit 1
|
||||||
|
|
@ -470,136 +459,6 @@ if [ $# -eq 1 ] ; then
|
||||||
chmod 644 $libdir/wrappers/zip/zzip.nim
|
chmod 644 $libdir/wrappers/zip/zzip.nim
|
||||||
cp lib/wrappers/zip/libzip_all.c $libdir/wrappers/zip/libzip_all.c || exit 1
|
cp lib/wrappers/zip/libzip_all.c $libdir/wrappers/zip/libzip_all.c || exit 1
|
||||||
chmod 644 $libdir/wrappers/zip/libzip_all.c
|
chmod 644 $libdir/wrappers/zip/libzip_all.c
|
||||||
cp lib/oldwrappers/iup.nim $libdir/oldwrappers/iup.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/iup.nim
|
|
||||||
cp lib/oldwrappers/libcurl.nim $libdir/oldwrappers/libcurl.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/libcurl.nim
|
|
||||||
cp lib/oldwrappers/mysql.nim $libdir/oldwrappers/mysql.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/mysql.nim
|
|
||||||
cp lib/oldwrappers/odbcsql.nim $libdir/oldwrappers/odbcsql.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/odbcsql.nim
|
|
||||||
cp lib/oldwrappers/postgres.nim $libdir/oldwrappers/postgres.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/postgres.nim
|
|
||||||
cp lib/oldwrappers/python.nim $libdir/oldwrappers/python.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/python.nim
|
|
||||||
cp lib/oldwrappers/sqlite3.nim $libdir/oldwrappers/sqlite3.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/sqlite3.nim
|
|
||||||
cp lib/oldwrappers/tcl.nim $libdir/oldwrappers/tcl.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/tcl.nim
|
|
||||||
cp lib/oldwrappers/cairo/cairo.nim $libdir/oldwrappers/cairo/cairo.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/cairo/cairo.nim
|
|
||||||
cp lib/oldwrappers/cairo/cairoft.nim $libdir/oldwrappers/cairo/cairoft.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/cairo/cairoft.nim
|
|
||||||
cp lib/oldwrappers/cairo/cairowin32.nim $libdir/oldwrappers/cairo/cairowin32.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/cairo/cairowin32.nim
|
|
||||||
cp lib/oldwrappers/cairo/cairoxlib.nim $libdir/oldwrappers/cairo/cairoxlib.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/cairo/cairoxlib.nim
|
|
||||||
cp lib/oldwrappers/gtk/atk.nim $libdir/oldwrappers/gtk/atk.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/gtk/atk.nim
|
|
||||||
cp lib/oldwrappers/gtk/gdk2.nim $libdir/oldwrappers/gtk/gdk2.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/gtk/gdk2.nim
|
|
||||||
cp lib/oldwrappers/gtk/gdk2pixbuf.nim $libdir/oldwrappers/gtk/gdk2pixbuf.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/gtk/gdk2pixbuf.nim
|
|
||||||
cp lib/oldwrappers/gtk/gdkglext.nim $libdir/oldwrappers/gtk/gdkglext.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/gtk/gdkglext.nim
|
|
||||||
cp lib/oldwrappers/gtk/glib2.nim $libdir/oldwrappers/gtk/glib2.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/gtk/glib2.nim
|
|
||||||
cp lib/oldwrappers/gtk/gtk2.nim $libdir/oldwrappers/gtk/gtk2.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/gtk/gtk2.nim
|
|
||||||
cp lib/oldwrappers/gtk/gtkglext.nim $libdir/oldwrappers/gtk/gtkglext.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/gtk/gtkglext.nim
|
|
||||||
cp lib/oldwrappers/gtk/gtkhtml.nim $libdir/oldwrappers/gtk/gtkhtml.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/gtk/gtkhtml.nim
|
|
||||||
cp lib/oldwrappers/gtk/libglade2.nim $libdir/oldwrappers/gtk/libglade2.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/gtk/libglade2.nim
|
|
||||||
cp lib/oldwrappers/gtk/pango.nim $libdir/oldwrappers/gtk/pango.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/gtk/pango.nim
|
|
||||||
cp lib/oldwrappers/gtk/pangoutils.nim $libdir/oldwrappers/gtk/pangoutils.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/gtk/pangoutils.nim
|
|
||||||
cp lib/oldwrappers/lua/lauxlib.nim $libdir/oldwrappers/lua/lauxlib.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/lua/lauxlib.nim
|
|
||||||
cp lib/oldwrappers/lua/lua.nim $libdir/oldwrappers/lua/lua.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/lua/lua.nim
|
|
||||||
cp lib/oldwrappers/lua/lualib.nim $libdir/oldwrappers/lua/lualib.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/lua/lualib.nim
|
|
||||||
cp lib/oldwrappers/opengl/gl.nim $libdir/oldwrappers/opengl/gl.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/opengl/gl.nim
|
|
||||||
cp lib/oldwrappers/opengl/glext.nim $libdir/oldwrappers/opengl/glext.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/opengl/glext.nim
|
|
||||||
cp lib/oldwrappers/opengl/glu.nim $libdir/oldwrappers/opengl/glu.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/opengl/glu.nim
|
|
||||||
cp lib/oldwrappers/opengl/glut.nim $libdir/oldwrappers/opengl/glut.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/opengl/glut.nim
|
|
||||||
cp lib/oldwrappers/opengl/glx.nim $libdir/oldwrappers/opengl/glx.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/opengl/glx.nim
|
|
||||||
cp lib/oldwrappers/opengl/wingl.nim $libdir/oldwrappers/opengl/wingl.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/opengl/wingl.nim
|
|
||||||
cp lib/oldwrappers/pcre/pcre.nim $libdir/oldwrappers/pcre/pcre.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/pcre/pcre.nim
|
|
||||||
cp lib/oldwrappers/pcre/pcre_all.c $libdir/oldwrappers/pcre/pcre_all.c || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/pcre/pcre_all.c
|
|
||||||
cp lib/oldwrappers/sdl/sdl.nim $libdir/oldwrappers/sdl/sdl.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/sdl/sdl.nim
|
|
||||||
cp lib/oldwrappers/sdl/sdl_gfx.nim $libdir/oldwrappers/sdl/sdl_gfx.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/sdl/sdl_gfx.nim
|
|
||||||
cp lib/oldwrappers/sdl/sdl_image.nim $libdir/oldwrappers/sdl/sdl_image.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/sdl/sdl_image.nim
|
|
||||||
cp lib/oldwrappers/sdl/sdl_mixer.nim $libdir/oldwrappers/sdl/sdl_mixer.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/sdl/sdl_mixer.nim
|
|
||||||
cp lib/oldwrappers/sdl/sdl_mixer_nosmpeg.nim $libdir/oldwrappers/sdl/sdl_mixer_nosmpeg.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/sdl/sdl_mixer_nosmpeg.nim
|
|
||||||
cp lib/oldwrappers/sdl/sdl_net.nim $libdir/oldwrappers/sdl/sdl_net.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/sdl/sdl_net.nim
|
|
||||||
cp lib/oldwrappers/sdl/sdl_ttf.nim $libdir/oldwrappers/sdl/sdl_ttf.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/sdl/sdl_ttf.nim
|
|
||||||
cp lib/oldwrappers/sdl/smpeg.nim $libdir/oldwrappers/sdl/smpeg.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/sdl/smpeg.nim
|
|
||||||
cp lib/oldwrappers/x11/cursorfont.nim $libdir/oldwrappers/x11/cursorfont.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/cursorfont.nim
|
|
||||||
cp lib/oldwrappers/x11/keysym.nim $libdir/oldwrappers/x11/keysym.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/keysym.nim
|
|
||||||
cp lib/oldwrappers/x11/x.nim $libdir/oldwrappers/x11/x.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/x.nim
|
|
||||||
cp lib/oldwrappers/x11/xatom.nim $libdir/oldwrappers/x11/xatom.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/xatom.nim
|
|
||||||
cp lib/oldwrappers/x11/xcms.nim $libdir/oldwrappers/x11/xcms.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/xcms.nim
|
|
||||||
cp lib/oldwrappers/x11/xf86dga.nim $libdir/oldwrappers/x11/xf86dga.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/xf86dga.nim
|
|
||||||
cp lib/oldwrappers/x11/xf86vmode.nim $libdir/oldwrappers/x11/xf86vmode.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/xf86vmode.nim
|
|
||||||
cp lib/oldwrappers/x11/xi.nim $libdir/oldwrappers/x11/xi.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/xi.nim
|
|
||||||
cp lib/oldwrappers/x11/xinerama.nim $libdir/oldwrappers/x11/xinerama.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/xinerama.nim
|
|
||||||
cp lib/oldwrappers/x11/xkb.nim $libdir/oldwrappers/x11/xkb.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/xkb.nim
|
|
||||||
cp lib/oldwrappers/x11/xkblib.nim $libdir/oldwrappers/x11/xkblib.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/xkblib.nim
|
|
||||||
cp lib/oldwrappers/x11/xlib.nim $libdir/oldwrappers/x11/xlib.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/xlib.nim
|
|
||||||
cp lib/oldwrappers/x11/xrandr.nim $libdir/oldwrappers/x11/xrandr.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/xrandr.nim
|
|
||||||
cp lib/oldwrappers/x11/xrender.nim $libdir/oldwrappers/x11/xrender.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/xrender.nim
|
|
||||||
cp lib/oldwrappers/x11/xresource.nim $libdir/oldwrappers/x11/xresource.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/xresource.nim
|
|
||||||
cp lib/oldwrappers/x11/xshm.nim $libdir/oldwrappers/x11/xshm.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/xshm.nim
|
|
||||||
cp lib/oldwrappers/x11/xutil.nim $libdir/oldwrappers/x11/xutil.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/xutil.nim
|
|
||||||
cp lib/oldwrappers/x11/xv.nim $libdir/oldwrappers/x11/xv.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/xv.nim
|
|
||||||
cp lib/oldwrappers/x11/xvlib.nim $libdir/oldwrappers/x11/xvlib.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/x11/xvlib.nim
|
|
||||||
cp lib/oldwrappers/zip/libzip.nim $libdir/oldwrappers/zip/libzip.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/zip/libzip.nim
|
|
||||||
cp lib/oldwrappers/zip/zlib.nim $libdir/oldwrappers/zip/zlib.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/zip/zlib.nim
|
|
||||||
cp lib/oldwrappers/zip/zzip.nim $libdir/oldwrappers/zip/zzip.nim || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/zip/zzip.nim
|
|
||||||
cp lib/oldwrappers/zip/libzip_all.c $libdir/oldwrappers/zip/libzip_all.c || exit 1
|
|
||||||
chmod 644 $libdir/oldwrappers/zip/libzip_all.c
|
|
||||||
cp lib/windows/mmsystem.nim $libdir/windows/mmsystem.nim || exit 1
|
cp lib/windows/mmsystem.nim $libdir/windows/mmsystem.nim || exit 1
|
||||||
chmod 644 $libdir/windows/mmsystem.nim
|
chmod 644 $libdir/windows/mmsystem.nim
|
||||||
cp lib/windows/nb30.nim $libdir/windows/nb30.nim || exit 1
|
cp lib/windows/nb30.nim $libdir/windows/nb30.nim || exit 1
|
||||||
|
|
|
||||||
|
|
@ -143,8 +143,6 @@ else:
|
||||||
var c = cast[ptr TThreadProcClosure[TParam]](closure)
|
var c = cast[ptr TThreadProcClosure[TParam]](closure)
|
||||||
c.fn(c.data)
|
c.fn(c.data)
|
||||||
|
|
||||||
{.passL: "-pthread".}
|
|
||||||
{.passC: "-pthread".}
|
|
||||||
|
|
||||||
const
|
const
|
||||||
noDeadlocks = true # compileOption("deadlockPrevention")
|
noDeadlocks = true # compileOption("deadlockPrevention")
|
||||||
|
|
@ -285,6 +283,7 @@ proc createThread*[TParam](t: var TThread[TParam],
|
||||||
## proc `tp`. `param` is passed to `tp`.
|
## proc `tp`. `param` is passed to `tp`.
|
||||||
t.c.data = param
|
t.c.data = param
|
||||||
t.c.fn = tp
|
t.c.fn = tp
|
||||||
|
CreateThreadLocalStorage()
|
||||||
when hostOS == "windows":
|
when hostOS == "windows":
|
||||||
var dummyThreadId: int32
|
var dummyThreadId: int32
|
||||||
t.sys = CreateThread(nil, 0'i32, threadProcWrapper[TParam],
|
t.sys = CreateThread(nil, 0'i32, threadProcWrapper[TParam],
|
||||||
|
|
|
||||||
|
|
@ -400,15 +400,6 @@ static unsigned long nimNaN[2]={0xffffffff, 0x7fffffff};
|
||||||
# define INF (1.0 / 0.0)
|
# define INF (1.0 / 0.0)
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
/*
|
|
||||||
typedef struct TSafePoint TSafePoint;
|
|
||||||
struct TSafePoint {
|
|
||||||
NI exc;
|
|
||||||
NCSTRING excname;
|
|
||||||
NCSTRING msg;
|
|
||||||
TSafePoint* prev;
|
|
||||||
jmp_buf context;
|
|
||||||
}; */
|
|
||||||
|
|
||||||
typedef struct TFrame TFrame;
|
typedef struct TFrame TFrame;
|
||||||
struct TFrame {
|
struct TFrame {
|
||||||
|
|
@ -419,25 +410,8 @@ struct TFrame {
|
||||||
NI len;
|
NI len;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
extern TFrame* framePtr;
|
|
||||||
extern TSafePoint* excHandler; */
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
struct NimException {
|
|
||||||
TSafePoint sp;
|
|
||||||
|
|
||||||
NimException(NI aExc, NCSTRING aExcname, NCSTRING aMsg) {
|
|
||||||
sp.exc = aExc; sp.excname = aExcname; sp.msg = aMsg;
|
|
||||||
sp.prev = excHandler;
|
|
||||||
excHandler = &sp;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define NIM_POSIX_INIT __attribute__((constructor))
|
#define NIM_POSIX_INIT __attribute__((constructor))
|
||||||
|
|
||||||
|
|
||||||
#if defined(_MSCVER) && defined(__i386__)
|
#if defined(_MSCVER) && defined(__i386__)
|
||||||
__declspec(naked) int __fastcall NimXadd(volatile int* pNum, int val) {
|
__declspec(naked) int __fastcall NimXadd(volatile int* pNum, int val) {
|
||||||
__asm {
|
__asm {
|
||||||
|
|
|
||||||
|
|
@ -44,10 +44,6 @@ type
|
||||||
typeDesc* {.magic: TypeDesc.} ## meta type to denote
|
typeDesc* {.magic: TypeDesc.} ## meta type to denote
|
||||||
## a type description (for templates)
|
## a type description (for templates)
|
||||||
|
|
||||||
const
|
|
||||||
hasThreadSupport = false # deactivate for now: thread stack walking
|
|
||||||
# is missing!
|
|
||||||
|
|
||||||
proc defined*[T](x: T): bool {.magic: "Defined", noSideEffect.}
|
proc defined*[T](x: T): bool {.magic: "Defined", noSideEffect.}
|
||||||
## Special compile-time procedure that checks whether `x` is
|
## Special compile-time procedure that checks whether `x` is
|
||||||
## defined. `x` has to be an identifier or a qualified identifier.
|
## defined. `x` has to be an identifier or a qualified identifier.
|
||||||
|
|
@ -780,6 +776,9 @@ proc compileOption*(option, arg: string): bool {.
|
||||||
## when compileOption("opt", "size") and compileOption("gc", "boehm"):
|
## when compileOption("opt", "size") and compileOption("gc", "boehm"):
|
||||||
## echo "compiled with optimization for size and uses Boehm's GC"
|
## echo "compiled with optimization for size and uses Boehm's GC"
|
||||||
|
|
||||||
|
const
|
||||||
|
hasThreadSupport = compileOption("threads")
|
||||||
|
|
||||||
include "system/inclrtl"
|
include "system/inclrtl"
|
||||||
|
|
||||||
when not defined(ecmascript) and not defined(nimrodVm):
|
when not defined(ecmascript) and not defined(nimrodVm):
|
||||||
|
|
@ -1391,19 +1390,20 @@ type
|
||||||
filename: CString
|
filename: CString
|
||||||
len: int # length of slots (when not debugging always zero)
|
len: int # length of slots (when not debugging always zero)
|
||||||
|
|
||||||
var
|
when defined(ecmaScript):
|
||||||
framePtr {.threadvar, compilerproc.}: PFrame
|
var
|
||||||
|
framePtr {.compilerproc.}: PFrame
|
||||||
|
|
||||||
when not defined(ECMAScript):
|
when not defined(ECMAScript):
|
||||||
{.push overflow_checks:off}
|
{.push stack_trace:off}
|
||||||
proc add* (x: var string, y: cstring) =
|
proc add*(x: var string, y: cstring) =
|
||||||
var i = 0
|
var i = 0
|
||||||
while y[i] != '\0':
|
while y[i] != '\0':
|
||||||
add(x, y[i])
|
add(x, y[i])
|
||||||
inc(i)
|
inc(i)
|
||||||
{.pop.}
|
{.pop.}
|
||||||
else:
|
else:
|
||||||
proc add* (x: var string, y: cstring) {.pure.} =
|
proc add*(x: var string, y: cstring) {.pure.} =
|
||||||
asm """
|
asm """
|
||||||
var len = `x`[0].length-1;
|
var len = `x`[0].length-1;
|
||||||
for (var i = 0; i < `y`.length; ++i) {
|
for (var i = 0; i < `y`.length; ++i) {
|
||||||
|
|
@ -1413,10 +1413,6 @@ else:
|
||||||
`x`[0][len] = 0
|
`x`[0][len] = 0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
proc `/`*(x, y: int): float {.inline, noSideEffect.} =
|
|
||||||
## integer division that results in a float.
|
|
||||||
result = toFloat(x) / toFloat(y)
|
|
||||||
|
|
||||||
proc echo*[Ty](x: openarray[Ty]) {.magic: "Echo".}
|
proc echo*[Ty](x: openarray[Ty]) {.magic: "Echo".}
|
||||||
## equivalent to ``writeln(stdout, x); flush(stdout)``. BUT: This is
|
## equivalent to ``writeln(stdout, x); flush(stdout)``. BUT: This is
|
||||||
## available for the ECMAScript target too!
|
## available for the ECMAScript target too!
|
||||||
|
|
@ -1450,6 +1446,7 @@ proc quit*(errorcode: int = QuitSuccess) {.
|
||||||
## unless a quit procedure calls ``GC_collect``.
|
## unless a quit procedure calls ``GC_collect``.
|
||||||
|
|
||||||
when not defined(EcmaScript) and not defined(NimrodVM):
|
when not defined(EcmaScript) and not defined(NimrodVM):
|
||||||
|
{.push stack_trace: off.}
|
||||||
|
|
||||||
proc atomicInc*(memLoc: var int, x: int): int {.inline.}
|
proc atomicInc*(memLoc: var int, x: int): int {.inline.}
|
||||||
## atomic increment of `memLoc`. Returns the value after the operation.
|
## atomic increment of `memLoc`. Returns the value after the operation.
|
||||||
|
|
@ -1475,8 +1472,6 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||||
initStackBottom()
|
initStackBottom()
|
||||||
initGC() # BUGFIX: need to be called here!
|
initGC() # BUGFIX: need to be called here!
|
||||||
|
|
||||||
{.push stack_trace: off.}
|
|
||||||
|
|
||||||
include "system/ansi_c"
|
include "system/ansi_c"
|
||||||
|
|
||||||
proc cmp(x, y: string): int =
|
proc cmp(x, y: string): int =
|
||||||
|
|
@ -1650,25 +1645,6 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||||
## retrieves the current position of the file pointer that is used to
|
## retrieves the current position of the file pointer that is used to
|
||||||
## read from the file `f`. The file's first byte has the index zero.
|
## read from the file `f`. The file's first byte has the index zero.
|
||||||
|
|
||||||
include "system/sysio"
|
|
||||||
|
|
||||||
iterator lines*(filename: string): string =
|
|
||||||
## Iterate over any line in the file named `filename`.
|
|
||||||
## If the file does not exist `EIO` is raised.
|
|
||||||
var f = open(filename)
|
|
||||||
var res = ""
|
|
||||||
while not endOfFile(f):
|
|
||||||
rawReadLine(f, res)
|
|
||||||
yield res
|
|
||||||
Close(f)
|
|
||||||
|
|
||||||
iterator lines*(f: TFile): string =
|
|
||||||
## Iterate over any line in the file `f`.
|
|
||||||
var res = ""
|
|
||||||
while not endOfFile(f):
|
|
||||||
rawReadLine(f, res)
|
|
||||||
yield res
|
|
||||||
|
|
||||||
proc fileHandle*(f: TFile): TFileHandle {.importc: "fileno",
|
proc fileHandle*(f: TFile): TFileHandle {.importc: "fileno",
|
||||||
header: "<stdio.h>"}
|
header: "<stdio.h>"}
|
||||||
## returns the OS file handle of the file ``f``. This is only useful for
|
## returns the OS file handle of the file ``f``. This is only useful for
|
||||||
|
|
@ -1694,6 +1670,26 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||||
# as it would recurse endlessly!
|
# as it would recurse endlessly!
|
||||||
include "system/arithm"
|
include "system/arithm"
|
||||||
{.pop.} # stack trace
|
{.pop.} # stack trace
|
||||||
|
|
||||||
|
include "system/sysio"
|
||||||
|
|
||||||
|
iterator lines*(filename: string): string =
|
||||||
|
## Iterate over any line in the file named `filename`.
|
||||||
|
## If the file does not exist `EIO` is raised.
|
||||||
|
var f = open(filename)
|
||||||
|
var res = ""
|
||||||
|
while not endOfFile(f):
|
||||||
|
rawReadLine(f, res)
|
||||||
|
yield res
|
||||||
|
Close(f)
|
||||||
|
|
||||||
|
iterator lines*(f: TFile): string =
|
||||||
|
## Iterate over any line in the file `f`.
|
||||||
|
var res = ""
|
||||||
|
while not endOfFile(f):
|
||||||
|
rawReadLine(f, res)
|
||||||
|
yield res
|
||||||
|
|
||||||
include "system/dyncalls"
|
include "system/dyncalls"
|
||||||
include "system/sets"
|
include "system/sets"
|
||||||
|
|
||||||
|
|
@ -1723,14 +1719,18 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||||
result = n.sons[n.len]
|
result = n.sons[n.len]
|
||||||
|
|
||||||
include "system/systhread"
|
include "system/systhread"
|
||||||
|
{.push stack_trace: off.}
|
||||||
include "system/mmdisp"
|
include "system/mmdisp"
|
||||||
|
{.pop.}
|
||||||
|
|
||||||
include "system/sysstr"
|
include "system/sysstr"
|
||||||
include "system/assign"
|
include "system/assign"
|
||||||
include "system/repr"
|
include "system/repr"
|
||||||
|
|
||||||
proc getCurrentException*(): ref E_Base {.compilerRtl, inl.} =
|
proc getCurrentException*(): ref E_Base {.compilerRtl, inl.} =
|
||||||
## retrieves the current exception; if there is none, nil is returned.
|
## retrieves the current exception; if there is none, nil is returned.
|
||||||
result = currException
|
ThreadGlobals()
|
||||||
|
result = ||currException
|
||||||
|
|
||||||
proc getCurrentExceptionMsg*(): string {.inline.} =
|
proc getCurrentExceptionMsg*(): string {.inline.} =
|
||||||
## retrieves the error message that was attached to the current
|
## retrieves the error message that was attached to the current
|
||||||
|
|
@ -1789,6 +1789,10 @@ proc quit*(errormsg: string, errorcode = QuitFailure) {.noReturn.} =
|
||||||
{.pop.} # checks
|
{.pop.} # checks
|
||||||
{.pop.} # hints
|
{.pop.} # hints
|
||||||
|
|
||||||
|
proc `/`*(x, y: int): float {.inline, noSideEffect.} =
|
||||||
|
## integer division that results in a float.
|
||||||
|
result = toFloat(x) / toFloat(y)
|
||||||
|
|
||||||
template `-|`(b, s: expr): expr =
|
template `-|`(b, s: expr): expr =
|
||||||
(if b >= 0: b else: s.len + b)
|
(if b >= 0: b else: s.len + b)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,50 +23,3 @@ proc nimLoadLibraryError(path: string) {.compilerproc, noinline.}
|
||||||
|
|
||||||
proc setStackBottom(theStackBottom: pointer) {.compilerRtl, noinline.}
|
proc setStackBottom(theStackBottom: pointer) {.compilerRtl, noinline.}
|
||||||
|
|
||||||
when false:
|
|
||||||
# Support for thread local storage:
|
|
||||||
when defined(windows):
|
|
||||||
type
|
|
||||||
TThreadVarSlot {.compilerproc.} = distinct int32
|
|
||||||
|
|
||||||
proc TlsAlloc(): TThreadVarSlot {.
|
|
||||||
importc: "TlsAlloc", stdcall, dynlib: "kernel32".}
|
|
||||||
proc TlsSetValue(dwTlsIndex: TThreadVarSlot, lpTlsValue: pointer) {.
|
|
||||||
importc: "TlsSetValue", stdcall, dynlib: "kernel32".}
|
|
||||||
proc TlsGetValue(dwTlsIndex: TThreadVarSlot): pointer {.
|
|
||||||
importc: "TlsGetValue", stdcall, dynlib: "kernel32".}
|
|
||||||
|
|
||||||
proc ThreadVarAlloc(): TThreadVarSlot {.compilerproc, inline.} =
|
|
||||||
result = TlsAlloc()
|
|
||||||
proc ThreadVarSetValue(s: TThreadVarSlot, value: pointer) {.
|
|
||||||
compilerproc, inline.} =
|
|
||||||
TlsSetValue(s, value)
|
|
||||||
proc ThreadVarGetValue(s: TThreadVarSlot): pointer {.
|
|
||||||
compilerproc, inline.} =
|
|
||||||
result = TlsGetValue(s)
|
|
||||||
|
|
||||||
else:
|
|
||||||
type
|
|
||||||
Tpthread_key {.importc: "pthread_key_t",
|
|
||||||
header: "<sys/types.h>".} = distinct int
|
|
||||||
TThreadVarSlot {.compilerproc.} = Tpthread_key
|
|
||||||
|
|
||||||
proc pthread_getspecific(a1: Tpthread_key): pointer {.
|
|
||||||
importc: "pthread_getspecific", header: "<pthread.h>".}
|
|
||||||
proc pthread_key_create(a1: ptr Tpthread_key,
|
|
||||||
destruct: proc (x: pointer) {.noconv.}): int32 {.
|
|
||||||
importc: "pthread_key_create", header: "<pthread.h>".}
|
|
||||||
proc pthread_key_delete(a1: Tpthread_key): int32 {.
|
|
||||||
importc: "pthread_key_delete", header: "<pthread.h>".}
|
|
||||||
|
|
||||||
proc pthread_setspecific(a1: Tpthread_key, a2: pointer): int32 {.
|
|
||||||
importc: "pthread_setspecific", header: "<pthread.h>".}
|
|
||||||
|
|
||||||
proc ThreadVarAlloc(): TThreadVarSlot {.compilerproc, inline.} =
|
|
||||||
discard pthread_key_create(addr(result), nil)
|
|
||||||
proc ThreadVarSetValue(s: TThreadVarSlot, value: pointer) {.
|
|
||||||
compilerproc, inline.} =
|
|
||||||
discard pthread_setspecific(s, value)
|
|
||||||
proc ThreadVarGetValue(s: TThreadVarSlot): pointer {.compilerproc, inline.} =
|
|
||||||
result = pthread_getspecific(s)
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,8 +85,7 @@ proc openAppend(filename: string): TFile =
|
||||||
write(result, "----------------------------------------\n")
|
write(result, "----------------------------------------\n")
|
||||||
|
|
||||||
proc dbgRepr(p: pointer, typ: PNimType): string =
|
proc dbgRepr(p: pointer, typ: PNimType): string =
|
||||||
var
|
var cl: TReprClosure
|
||||||
cl: TReprClosure
|
|
||||||
initReprClosure(cl)
|
initReprClosure(cl)
|
||||||
cl.recDepth = maxDisplayRecDepth
|
cl.recDepth = maxDisplayRecDepth
|
||||||
# locks for the GC turned out to be a bad idea...
|
# locks for the GC turned out to be a bad idea...
|
||||||
|
|
@ -139,8 +138,10 @@ proc dbgShowCurrentProc(dbgFramePointer: PFrame) =
|
||||||
write(stdout, "*** endb| (procedure name not available) ***\n")
|
write(stdout, "*** endb| (procedure name not available) ***\n")
|
||||||
|
|
||||||
proc dbgShowExecutionPoint() =
|
proc dbgShowExecutionPoint() =
|
||||||
write(stdout, "*** endb| " & $framePtr.filename & "(" & $framePtr.line &
|
ThreadGlobals()
|
||||||
") " & $framePtr.procname & " ***\n")
|
write(stdout, "*** endb| " & $(||framePtr).filename &
|
||||||
|
"(" & $(||framePtr).line & ") " &
|
||||||
|
$(||framePtr).procname & " ***\n")
|
||||||
|
|
||||||
when defined(windows) or defined(dos) or defined(os2):
|
when defined(windows) or defined(dos) or defined(os2):
|
||||||
{.define: FileSystemCaseInsensitive.}
|
{.define: FileSystemCaseInsensitive.}
|
||||||
|
|
@ -171,9 +172,10 @@ proc fileMatches(c, bp: cstring): bool =
|
||||||
return true
|
return true
|
||||||
|
|
||||||
proc dbgBreakpointReached(line: int): int =
|
proc dbgBreakpointReached(line: int): int =
|
||||||
|
ThreadGlobals()
|
||||||
for i in 0..dbgBPlen-1:
|
for i in 0..dbgBPlen-1:
|
||||||
if line >= dbgBP[i].low and line <= dbgBP[i].high and
|
if line >= dbgBP[i].low and line <= dbgBP[i].high and
|
||||||
fileMatches(framePtr.filename, dbgBP[i].filename): return i
|
fileMatches((||framePtr).filename, dbgBP[i].filename): return i
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
proc scanAndAppendWord(src: string, a: var string, start: int): int =
|
proc scanAndAppendWord(src: string, a: var string, start: int): int =
|
||||||
|
|
@ -255,6 +257,7 @@ proc hasExt(s: string): bool =
|
||||||
return false
|
return false
|
||||||
|
|
||||||
proc setBreakPoint(s: string, start: int) =
|
proc setBreakPoint(s: string, start: int) =
|
||||||
|
ThreadGlobals()
|
||||||
var dbgTemp: string
|
var dbgTemp: string
|
||||||
var i = scanWord(s, dbgTemp, start)
|
var i = scanWord(s, dbgTemp, start)
|
||||||
if i <= start:
|
if i <= start:
|
||||||
|
|
@ -269,7 +272,7 @@ proc setBreakPoint(s: string, start: int) =
|
||||||
i = scanNumber(s, dbgBP[x].low, i)
|
i = scanNumber(s, dbgBP[x].low, i)
|
||||||
if dbgBP[x].low == 0:
|
if dbgBP[x].low == 0:
|
||||||
# set to current line:
|
# set to current line:
|
||||||
dbgBP[x].low = framePtr.line
|
dbgBP[x].low = (||framePtr).line
|
||||||
i = scanNumber(s, dbgBP[x].high, i)
|
i = scanNumber(s, dbgBP[x].high, i)
|
||||||
if dbgBP[x].high == 0: # set to low:
|
if dbgBP[x].high == 0: # set to low:
|
||||||
dbgBP[x].high = dbgBP[x].low
|
dbgBP[x].high = dbgBP[x].low
|
||||||
|
|
@ -278,7 +281,7 @@ proc setBreakPoint(s: string, start: int) =
|
||||||
if not hasExt(dbgTemp): add(dbgTemp, ".nim")
|
if not hasExt(dbgTemp): add(dbgTemp, ".nim")
|
||||||
dbgBP[x].filename = dbgTemp
|
dbgBP[x].filename = dbgTemp
|
||||||
else: # use current filename
|
else: # use current filename
|
||||||
dbgBP[x].filename = $framePtr.filename
|
dbgBP[x].filename = $(||framePtr).filename
|
||||||
# skip whitespace:
|
# skip whitespace:
|
||||||
while s[i] in {' ', '\t'}: inc(i)
|
while s[i] in {' ', '\t'}: inc(i)
|
||||||
if s[i] != '\0':
|
if s[i] != '\0':
|
||||||
|
|
@ -347,9 +350,10 @@ proc dbgStackFrame(s: string, start: int, currFrame: PExtendedFrame) =
|
||||||
|
|
||||||
proc CommandPrompt() =
|
proc CommandPrompt() =
|
||||||
# if we return from this routine, user code executes again
|
# if we return from this routine, user code executes again
|
||||||
|
ThreadGlobals()
|
||||||
var
|
var
|
||||||
again = True
|
again = True
|
||||||
dbgFramePtr = framePtr # for going down and up the stack
|
dbgFramePtr = ||framePtr # for going down and up the stack
|
||||||
dbgDown = 0 # how often we did go down
|
dbgDown = 0 # how often we did go down
|
||||||
|
|
||||||
while again:
|
while again:
|
||||||
|
|
@ -366,11 +370,11 @@ proc CommandPrompt() =
|
||||||
again = false
|
again = false
|
||||||
of "n", "next":
|
of "n", "next":
|
||||||
dbgState = dbStepOver
|
dbgState = dbStepOver
|
||||||
dbgSkipToFrame = framePtr
|
dbgSkipToFrame = ||framePtr
|
||||||
again = false
|
again = false
|
||||||
of "f", "skipcurrent":
|
of "f", "skipcurrent":
|
||||||
dbgState = dbSkipCurrent
|
dbgState = dbSkipCurrent
|
||||||
dbgSkipToFrame = framePtr.prev
|
dbgSkipToFrame = (||framePtr).prev
|
||||||
again = false
|
again = false
|
||||||
of "c", "continue":
|
of "c", "continue":
|
||||||
dbgState = dbBreakpoints
|
dbgState = dbBreakpoints
|
||||||
|
|
@ -401,7 +405,7 @@ proc CommandPrompt() =
|
||||||
if dbgDown <= 0:
|
if dbgDown <= 0:
|
||||||
debugOut("[Warning] cannot go up any further ")
|
debugOut("[Warning] cannot go up any further ")
|
||||||
else:
|
else:
|
||||||
dbgFramePtr = framePtr
|
dbgFramePtr = ||framePtr
|
||||||
for j in 0 .. dbgDown-2: # BUGFIX
|
for j in 0 .. dbgDown-2: # BUGFIX
|
||||||
dbgFramePtr = dbgFramePtr.prev
|
dbgFramePtr = dbgFramePtr.prev
|
||||||
dec(dbgDown)
|
dec(dbgDown)
|
||||||
|
|
@ -442,16 +446,17 @@ proc endbStep() =
|
||||||
CommandPrompt()
|
CommandPrompt()
|
||||||
|
|
||||||
proc checkForBreakpoint() =
|
proc checkForBreakpoint() =
|
||||||
var i = dbgBreakpointReached(framePtr.line)
|
ThreadGlobals()
|
||||||
|
var i = dbgBreakpointReached((||framePtr).line)
|
||||||
if i >= 0:
|
if i >= 0:
|
||||||
write(stdout, "*** endb| reached ")
|
write(stdout, "*** endb| reached ")
|
||||||
write(stdout, dbgBP[i].name)
|
write(stdout, dbgBP[i].name)
|
||||||
write(stdout, " in ")
|
write(stdout, " in ")
|
||||||
write(stdout, framePtr.filename)
|
write(stdout, (||framePtr).filename)
|
||||||
write(stdout, "(")
|
write(stdout, "(")
|
||||||
write(stdout, framePtr.line)
|
write(stdout, (||framePtr).line)
|
||||||
write(stdout, ") ")
|
write(stdout, ") ")
|
||||||
write(stdout, framePtr.procname)
|
write(stdout, (||framePtr).procname)
|
||||||
write(stdout, " ***\n")
|
write(stdout, " ***\n")
|
||||||
CommandPrompt()
|
CommandPrompt()
|
||||||
|
|
||||||
|
|
@ -482,7 +487,8 @@ proc endb(line: int) {.compilerproc.} =
|
||||||
# Thus, it must have as few parameters as possible to keep the
|
# Thus, it must have as few parameters as possible to keep the
|
||||||
# code size small!
|
# code size small!
|
||||||
# Check if we are at an enabled breakpoint or "in the mood"
|
# Check if we are at an enabled breakpoint or "in the mood"
|
||||||
framePtr.line = line # this is done here for smaller code size!
|
ThreadGlobals()
|
||||||
|
(||framePtr).line = line # this is done here for smaller code size!
|
||||||
if dbgLineHook != nil: dbgLineHook()
|
if dbgLineHook != nil: dbgLineHook()
|
||||||
case dbgState
|
case dbgState
|
||||||
of dbStepInto:
|
of dbStepInto:
|
||||||
|
|
@ -490,7 +496,7 @@ proc endb(line: int) {.compilerproc.} =
|
||||||
dbgShowExecutionPoint()
|
dbgShowExecutionPoint()
|
||||||
CommandPrompt()
|
CommandPrompt()
|
||||||
of dbSkipCurrent, dbStepOver: # skip current routine
|
of dbSkipCurrent, dbStepOver: # skip current routine
|
||||||
if framePtr == dbgSkipToFrame:
|
if ||framePtr == dbgSkipToFrame:
|
||||||
dbgShowExecutionPoint()
|
dbgShowExecutionPoint()
|
||||||
CommandPrompt()
|
CommandPrompt()
|
||||||
else: # breakpoints are wanted though (I guess)
|
else: # breakpoints are wanted though (I guess)
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
# However, the interface has been designed to take platform differences into
|
# However, the interface has been designed to take platform differences into
|
||||||
# account and been ported to all major platforms.
|
# account and been ported to all major platforms.
|
||||||
|
|
||||||
|
{.push stack_trace: off.}
|
||||||
|
|
||||||
const
|
const
|
||||||
NilLibHandle: TLibHandle = nil
|
NilLibHandle: TLibHandle = nil
|
||||||
|
|
||||||
|
|
@ -135,3 +137,6 @@ elif defined(mac):
|
||||||
|
|
||||||
else:
|
else:
|
||||||
{.error: "no implementation for dyncalls".}
|
{.error: "no implementation for dyncalls".}
|
||||||
|
|
||||||
|
{.pop.}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
var
|
var
|
||||||
stackTraceNewLine* = "\n" ## undocumented feature; it is replaced by ``<br>``
|
stackTraceNewLine* = "\n" ## undocumented feature; it is replaced by ``<br>``
|
||||||
## for CGI applications
|
## for CGI applications
|
||||||
|
isMultiThreaded: bool # true when prog created at least 1 thread
|
||||||
|
|
||||||
when not defined(windows) or not defined(guiapp):
|
when not defined(windows) or not defined(guiapp):
|
||||||
proc writeToStdErr(msg: CString) = write(stdout, msg)
|
proc writeToStdErr(msg: CString) = write(stdout, msg)
|
||||||
|
|
@ -36,30 +37,139 @@ type
|
||||||
TSafePoint {.compilerproc, final.} = object
|
TSafePoint {.compilerproc, final.} = object
|
||||||
prev: PSafePoint # points to next safe point ON THE STACK
|
prev: PSafePoint # points to next safe point ON THE STACK
|
||||||
status: int
|
status: int
|
||||||
exc: ref E_Base # XXX only needed for bootstrapping; unused
|
|
||||||
context: C_JmpBuf
|
context: C_JmpBuf
|
||||||
|
|
||||||
#when hasThreadSupport: nil
|
when hasThreadSupport:
|
||||||
|
# Support for thread local storage:
|
||||||
|
when defined(windows):
|
||||||
|
type
|
||||||
|
TThreadVarSlot {.compilerproc.} = distinct int32
|
||||||
|
|
||||||
var
|
proc TlsAlloc(): TThreadVarSlot {.
|
||||||
excHandler {.threadvar, compilerproc.}: PSafePoint = nil
|
importc: "TlsAlloc", stdcall, dynlib: "kernel32".}
|
||||||
# list of exception handlers
|
proc TlsSetValue(dwTlsIndex: TThreadVarSlot, lpTlsValue: pointer) {.
|
||||||
# a global variable for the root of all try blocks
|
importc: "TlsSetValue", stdcall, dynlib: "kernel32".}
|
||||||
currException {.threadvar.}: ref E_Base
|
proc TlsGetValue(dwTlsIndex: TThreadVarSlot): pointer {.
|
||||||
|
importc: "TlsGetValue", stdcall, dynlib: "kernel32".}
|
||||||
|
|
||||||
|
proc ThreadVarAlloc(): TThreadVarSlot {.compilerproc, inline.} =
|
||||||
|
result = TlsAlloc()
|
||||||
|
proc ThreadVarSetValue(s: TThreadVarSlot, value: pointer) {.
|
||||||
|
compilerproc, inline.} =
|
||||||
|
TlsSetValue(s, value)
|
||||||
|
proc ThreadVarGetValue(s: TThreadVarSlot): pointer {.
|
||||||
|
compilerproc, inline.} =
|
||||||
|
result = TlsGetValue(s)
|
||||||
|
|
||||||
|
else:
|
||||||
|
{.passL: "-pthread".}
|
||||||
|
{.passC: "-pthread".}
|
||||||
|
|
||||||
|
type
|
||||||
|
Tpthread_key {.importc: "pthread_key_t",
|
||||||
|
header: "<sys/types.h>".} = distinct int
|
||||||
|
TThreadVarSlot {.compilerproc.} = Tpthread_key
|
||||||
|
|
||||||
|
proc pthread_getspecific(a1: Tpthread_key): pointer {.
|
||||||
|
importc: "pthread_getspecific", header: "<pthread.h>".}
|
||||||
|
proc pthread_key_create(a1: ptr Tpthread_key,
|
||||||
|
destruct: proc (x: pointer) {.noconv.}): int32 {.
|
||||||
|
importc: "pthread_key_create", header: "<pthread.h>".}
|
||||||
|
proc pthread_key_delete(a1: Tpthread_key): int32 {.
|
||||||
|
importc: "pthread_key_delete", header: "<pthread.h>".}
|
||||||
|
|
||||||
|
proc pthread_setspecific(a1: Tpthread_key, a2: pointer): int32 {.
|
||||||
|
importc: "pthread_setspecific", header: "<pthread.h>".}
|
||||||
|
|
||||||
|
proc specificDestroy(mem: pointer) {.noconv.} = dealloc(mem)
|
||||||
|
|
||||||
|
proc ThreadVarAlloc(): TThreadVarSlot {.compilerproc, inline.} =
|
||||||
|
discard pthread_key_create(addr(result), specificDestroy)
|
||||||
|
proc ThreadVarSetValue(s: TThreadVarSlot, value: pointer) {.
|
||||||
|
compilerproc, inline.} =
|
||||||
|
discard pthread_setspecific(s, value)
|
||||||
|
proc ThreadVarGetValue(s: TThreadVarSlot): pointer {.compilerproc, inline.} =
|
||||||
|
result = pthread_getspecific(s)
|
||||||
|
|
||||||
|
type
|
||||||
|
TGlobals {.final, pure.} = object
|
||||||
|
excHandler: PSafePoint
|
||||||
|
currException: ref E_Base
|
||||||
|
framePtr: PFrame
|
||||||
|
buf: string # cannot be allocated on the stack!
|
||||||
|
assertBuf: string # we need a different buffer for
|
||||||
|
# assert, as it raises an exception and
|
||||||
|
# exception handler needs the buffer too
|
||||||
|
gAssertionFailed: ref EAssertionFailed
|
||||||
|
tempFrames: array [0..127, PFrame] # cannot be allocated on the stack!
|
||||||
|
data: float # compiler should add thread local variables here!
|
||||||
|
PGlobals = ptr TGlobals
|
||||||
|
|
||||||
|
var globalsSlot = ThreadVarAlloc()
|
||||||
|
proc CreateThreadLocalStorage*() {.inl.} =
|
||||||
|
isMultiThreaded = true
|
||||||
|
ThreadVarSetValue(globalsSlot, alloc0(sizeof(TGlobals)))
|
||||||
|
|
||||||
|
proc GetGlobals(): PGlobals {.compilerRtl, inl.} =
|
||||||
|
result = cast[PGlobals](ThreadVarGetValue(globalsSlot))
|
||||||
|
|
||||||
|
# create for the main thread:
|
||||||
|
ThreadVarSetValue(globalsSlot, alloc0(sizeof(TGlobals)))
|
||||||
|
|
||||||
|
when hasThreadSupport:
|
||||||
|
template ThreadGlobals =
|
||||||
|
var globals = GetGlobals()
|
||||||
|
template `||`(varname: expr): expr = globals.varname
|
||||||
|
|
||||||
|
ThreadGlobals()
|
||||||
|
else:
|
||||||
|
template ThreadGlobals = nil # nothing
|
||||||
|
template `||`(varname: expr): expr = varname
|
||||||
|
|
||||||
|
var
|
||||||
|
framePtr {.compilerproc.}: PFrame # XXX only temporarily a compilerproc
|
||||||
|
excHandler: PSafePoint = nil
|
||||||
|
# list of exception handlers
|
||||||
|
# a global variable for the root of all try blocks
|
||||||
|
currException: ref E_Base
|
||||||
|
|
||||||
|
buf: string # cannot be allocated on the stack!
|
||||||
|
assertBuf: string # we need a different buffer for
|
||||||
|
# assert, as it raises an exception and
|
||||||
|
# exception handler needs the buffer too
|
||||||
|
tempFrames: array [0..127, PFrame] # cannot be allocated on the stack!
|
||||||
|
gAssertionFailed: ref EAssertionFailed
|
||||||
|
|
||||||
|
proc pushFrame(s: PFrame) {.compilerRtl, inl.} =
|
||||||
|
ThreadGlobals()
|
||||||
|
s.prev = ||framePtr
|
||||||
|
||framePtr = s
|
||||||
|
|
||||||
|
proc popFrame {.compilerRtl, inl.} =
|
||||||
|
ThreadGlobals()
|
||||||
|
||framePtr = (||framePtr).prev
|
||||||
|
|
||||||
|
proc setFrame(s: PFrame) {.compilerRtl, inl.} =
|
||||||
|
ThreadGlobals()
|
||||||
|
||framePtr = s
|
||||||
|
|
||||||
proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} =
|
proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} =
|
||||||
s.prev = excHandler
|
ThreadGlobals()
|
||||||
excHandler = s
|
s.prev = ||excHandler
|
||||||
|
||excHandler = s
|
||||||
|
|
||||||
proc popSafePoint {.compilerRtl, inl.} =
|
proc popSafePoint {.compilerRtl, inl.} =
|
||||||
excHandler = excHandler.prev
|
ThreadGlobals()
|
||||||
|
||excHandler = (||excHandler).prev
|
||||||
|
|
||||||
proc pushCurrentException(e: ref E_Base) {.compilerRtl, inl.} =
|
proc pushCurrentException(e: ref E_Base) {.compilerRtl, inl.} =
|
||||||
e.parent = currException
|
ThreadGlobals()
|
||||||
currException = e
|
e.parent = ||currException
|
||||||
|
||currException = e
|
||||||
|
|
||||||
proc popCurrentException {.compilerRtl, inl.} =
|
proc popCurrentException {.compilerRtl, inl.} =
|
||||||
currException = currException.parent
|
ThreadGlobals()
|
||||||
|
||currException = (||currException).parent
|
||||||
|
|
||||||
# some platforms have native support for stack traces:
|
# some platforms have native support for stack traces:
|
||||||
const
|
const
|
||||||
|
|
@ -80,11 +190,16 @@ when defined(nativeStacktrace) and nativeStackTraceSupported:
|
||||||
proc dladdr(addr1: pointer, info: ptr TDl_info): int {.
|
proc dladdr(addr1: pointer, info: ptr TDl_info): int {.
|
||||||
importc: "dladdr", header: "<dlfcn.h>".}
|
importc: "dladdr", header: "<dlfcn.h>".}
|
||||||
|
|
||||||
var
|
when not hasThreadSupport:
|
||||||
tempAddresses: array [0..127, pointer] # cannot be allocated on the stack!
|
var
|
||||||
tempDlInfo: TDl_info
|
tempAddresses: array [0..127, pointer] # should not be alloc'd on stack
|
||||||
|
tempDlInfo: TDl_info
|
||||||
|
|
||||||
proc auxWriteStackTraceWithBacktrace(s: var string) =
|
proc auxWriteStackTraceWithBacktrace(s: var string) =
|
||||||
|
when hasThreadSupport:
|
||||||
|
var
|
||||||
|
tempAddresses: array [0..127, pointer] # but better than a threadvar
|
||||||
|
tempDlInfo: TDl_info
|
||||||
# This is allowed to be expensive since it only happens during crashes
|
# This is allowed to be expensive since it only happens during crashes
|
||||||
# (but this way you don't need manual stack tracing)
|
# (but this way you don't need manual stack tracing)
|
||||||
var size = backtrace(cast[ptr pointer](addr(tempAddresses)),
|
var size = backtrace(cast[ptr pointer](addr(tempAddresses)),
|
||||||
|
|
@ -109,23 +224,17 @@ when defined(nativeStacktrace) and nativeStackTraceSupported:
|
||||||
# interested in
|
# interested in
|
||||||
enabled = true
|
enabled = true
|
||||||
|
|
||||||
var
|
|
||||||
buf: string # cannot be allocated on the stack!
|
|
||||||
assertBuf: string # we need a different buffer for
|
|
||||||
# assert, as it raises an exception and
|
|
||||||
# exception handler needs the buffer too
|
|
||||||
tempFrames: array [0..127, PFrame] # cannot be allocated on the stack!
|
|
||||||
|
|
||||||
proc auxWriteStackTrace(f: PFrame, s: var string) =
|
proc auxWriteStackTrace(f: PFrame, s: var string) =
|
||||||
const
|
const
|
||||||
firstCalls = 32
|
firstCalls = 32
|
||||||
|
ThreadGlobals()
|
||||||
var
|
var
|
||||||
it = f
|
it = f
|
||||||
i = 0
|
i = 0
|
||||||
total = 0
|
total = 0
|
||||||
while it != nil and i <= high(tempFrames)-(firstCalls-1):
|
while it != nil and i <= high(||tempFrames)-(firstCalls-1):
|
||||||
# the (-1) is for a nil entry that marks where the '...' should occur
|
# the (-1) is for a nil entry that marks where the '...' should occur
|
||||||
tempFrames[i] = it
|
(||tempFrames)[i] = it
|
||||||
inc(i)
|
inc(i)
|
||||||
inc(total)
|
inc(total)
|
||||||
it = it.prev
|
it = it.prev
|
||||||
|
|
@ -136,37 +245,38 @@ proc auxWriteStackTrace(f: PFrame, s: var string) =
|
||||||
for j in 1..total-i-(firstCalls-1):
|
for j in 1..total-i-(firstCalls-1):
|
||||||
if b != nil: b = b.prev
|
if b != nil: b = b.prev
|
||||||
if total != i:
|
if total != i:
|
||||||
tempFrames[i] = nil
|
(||tempFrames)[i] = nil
|
||||||
inc(i)
|
inc(i)
|
||||||
while b != nil and i <= high(tempFrames):
|
while b != nil and i <= high(||tempFrames):
|
||||||
tempFrames[i] = b
|
(||tempFrames)[i] = b
|
||||||
inc(i)
|
inc(i)
|
||||||
b = b.prev
|
b = b.prev
|
||||||
for j in countdown(i-1, 0):
|
for j in countdown(i-1, 0):
|
||||||
if tempFrames[j] == nil:
|
if (||tempFrames)[j] == nil:
|
||||||
add(s, "(")
|
add(s, "(")
|
||||||
add(s, $(total-i-1))
|
add(s, $(total-i-1))
|
||||||
add(s, " calls omitted) ...")
|
add(s, " calls omitted) ...")
|
||||||
else:
|
else:
|
||||||
var oldLen = s.len
|
var oldLen = s.len
|
||||||
add(s, tempFrames[j].filename)
|
add(s, (||tempFrames)[j].filename)
|
||||||
if tempFrames[j].line > 0:
|
if (||tempFrames)[j].line > 0:
|
||||||
add(s, '(')
|
add(s, '(')
|
||||||
add(s, $tempFrames[j].line)
|
add(s, $(||tempFrames)[j].line)
|
||||||
add(s, ')')
|
add(s, ')')
|
||||||
for k in 1..max(1, 25-(s.len-oldLen)): add(s, ' ')
|
for k in 1..max(1, 25-(s.len-oldLen)): add(s, ' ')
|
||||||
add(s, tempFrames[j].procname)
|
add(s, (||tempFrames)[j].procname)
|
||||||
add(s, stackTraceNewLine)
|
add(s, stackTraceNewLine)
|
||||||
|
|
||||||
proc rawWriteStackTrace(s: var string) =
|
proc rawWriteStackTrace(s: var string) =
|
||||||
when nimrodStackTrace:
|
when nimrodStackTrace:
|
||||||
if framePtr == nil:
|
ThreadGlobals()
|
||||||
|
if ||framePtr == nil:
|
||||||
add(s, "No stack traceback available")
|
add(s, "No stack traceback available")
|
||||||
add(s, stackTraceNewLine)
|
add(s, stackTraceNewLine)
|
||||||
else:
|
else:
|
||||||
add(s, "Traceback (most recent call last)")
|
add(s, "Traceback (most recent call last)")
|
||||||
add(s, stackTraceNewLine)
|
add(s, stackTraceNewLine)
|
||||||
auxWriteStackTrace(framePtr, s)
|
auxWriteStackTrace(||framePtr, s)
|
||||||
elif defined(nativeStackTrace) and nativeStackTraceSupported:
|
elif defined(nativeStackTrace) and nativeStackTraceSupported:
|
||||||
add(s, "Traceback from system (most recent call last)")
|
add(s, "Traceback from system (most recent call last)")
|
||||||
add(s, stackTraceNewLine)
|
add(s, stackTraceNewLine)
|
||||||
|
|
@ -184,53 +294,53 @@ proc quitOrDebug() {.inline.} =
|
||||||
proc raiseException(e: ref E_Base, ename: CString) {.compilerRtl.} =
|
proc raiseException(e: ref E_Base, ename: CString) {.compilerRtl.} =
|
||||||
GC_disable() # a bad thing is an error in the GC while raising an exception
|
GC_disable() # a bad thing is an error in the GC while raising an exception
|
||||||
e.name = ename
|
e.name = ename
|
||||||
if excHandler != nil:
|
ThreadGlobals()
|
||||||
|
if ||excHandler != nil:
|
||||||
pushCurrentException(e)
|
pushCurrentException(e)
|
||||||
c_longjmp(excHandler.context, 1)
|
c_longjmp((||excHandler).context, 1)
|
||||||
else:
|
else:
|
||||||
if not isNil(buf):
|
if not isNil(||buf):
|
||||||
setLen(buf, 0)
|
setLen(||buf, 0)
|
||||||
rawWriteStackTrace(buf)
|
rawWriteStackTrace(||buf)
|
||||||
if e.msg != nil and e.msg[0] != '\0':
|
if e.msg != nil and e.msg[0] != '\0':
|
||||||
add(buf, "Error: unhandled exception: ")
|
add(||buf, "Error: unhandled exception: ")
|
||||||
add(buf, $e.msg)
|
add(||buf, $e.msg)
|
||||||
else:
|
else:
|
||||||
add(buf, "Error: unhandled exception")
|
add(||buf, "Error: unhandled exception")
|
||||||
add(buf, " [")
|
add(||buf, " [")
|
||||||
add(buf, $ename)
|
add(||buf, $ename)
|
||||||
add(buf, "]\n")
|
add(||buf, "]\n")
|
||||||
writeToStdErr(buf)
|
writeToStdErr(||buf)
|
||||||
else:
|
else:
|
||||||
writeToStdErr(ename)
|
writeToStdErr(ename)
|
||||||
quitOrDebug()
|
quitOrDebug()
|
||||||
GC_enable()
|
GC_enable()
|
||||||
|
|
||||||
proc reraiseException() {.compilerRtl.} =
|
proc reraiseException() {.compilerRtl.} =
|
||||||
if currException == nil:
|
ThreadGlobals()
|
||||||
|
if ||currException == nil:
|
||||||
raise newException(ENoExceptionToReraise, "no exception to reraise")
|
raise newException(ENoExceptionToReraise, "no exception to reraise")
|
||||||
else:
|
else:
|
||||||
raiseException(currException, currException.name)
|
raiseException(||currException, (||currException).name)
|
||||||
|
|
||||||
var
|
|
||||||
gAssertionFailed: ref EAssertionFailed
|
|
||||||
|
|
||||||
proc internalAssert(file: cstring, line: int, cond: bool) {.compilerproc.} =
|
proc internalAssert(file: cstring, line: int, cond: bool) {.compilerproc.} =
|
||||||
if not cond:
|
if not cond:
|
||||||
|
ThreadGlobals()
|
||||||
#c_fprintf(c_stdout, "Assertion failure: file %s line %ld\n", file, line)
|
#c_fprintf(c_stdout, "Assertion failure: file %s line %ld\n", file, line)
|
||||||
#quit(1)
|
#quit(1)
|
||||||
GC_disable() # BUGFIX: `$` allocates a new string object!
|
GC_disable() # BUGFIX: `$` allocates a new string object!
|
||||||
if not isNil(assertBuf):
|
if not isNil(||assertBuf):
|
||||||
# BUGFIX: when debugging the GC, assertBuf may be nil
|
# BUGFIX: when debugging the GC, assertBuf may be nil
|
||||||
setLen(assertBuf, 0)
|
setLen(||assertBuf, 0)
|
||||||
add(assertBuf, "[Assertion failure] file: ")
|
add(||assertBuf, "[Assertion failure] file: ")
|
||||||
add(assertBuf, file)
|
add(||assertBuf, file)
|
||||||
add(assertBuf, " line: ")
|
add(||assertBuf, " line: ")
|
||||||
add(assertBuf, $line)
|
add(||assertBuf, $line)
|
||||||
add(assertBuf, "\n")
|
add(||assertBuf, "\n")
|
||||||
gAssertionFailed.msg = assertBuf
|
(||gAssertionFailed).msg = ||assertBuf
|
||||||
GC_enable()
|
GC_enable()
|
||||||
if gAssertionFailed != nil:
|
if ||gAssertionFailed != nil:
|
||||||
raise gAssertionFailed
|
raise ||gAssertionFailed
|
||||||
else:
|
else:
|
||||||
c_fprintf(c_stdout, "Assertion failure: file %s line %ld\n", file, line)
|
c_fprintf(c_stdout, "Assertion failure: file %s line %ld\n", file, line)
|
||||||
quit(1)
|
quit(1)
|
||||||
|
|
@ -245,23 +355,24 @@ var
|
||||||
|
|
||||||
proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
|
proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
|
||||||
# print stack trace and quit
|
# print stack trace and quit
|
||||||
|
ThreadGlobals()
|
||||||
var s = sig
|
var s = sig
|
||||||
GC_disable()
|
GC_disable()
|
||||||
setLen(buf, 0)
|
setLen(||buf, 0)
|
||||||
rawWriteStackTrace(buf)
|
rawWriteStackTrace(||buf)
|
||||||
|
|
||||||
if s == SIGINT: add(buf, "SIGINT: Interrupted by Ctrl-C.\n")
|
if s == SIGINT: add(||buf, "SIGINT: Interrupted by Ctrl-C.\n")
|
||||||
elif s == SIGSEGV:
|
elif s == SIGSEGV:
|
||||||
add(buf, "SIGSEGV: Illegal storage access. (Attempt to read from nil?)\n")
|
add(||buf, "SIGSEGV: Illegal storage access. (Attempt to read from nil?)\n")
|
||||||
elif s == SIGABRT:
|
elif s == SIGABRT:
|
||||||
if dbgAborting: return # the debugger wants to abort
|
if dbgAborting: return # the debugger wants to abort
|
||||||
add(buf, "SIGABRT: Abnormal termination.\n")
|
add(||buf, "SIGABRT: Abnormal termination.\n")
|
||||||
elif s == SIGFPE: add(buf, "SIGFPE: Arithmetic error.\n")
|
elif s == SIGFPE: add(||buf, "SIGFPE: Arithmetic error.\n")
|
||||||
elif s == SIGILL: add(buf, "SIGILL: Illegal operation.\n")
|
elif s == SIGILL: add(||buf, "SIGILL: Illegal operation.\n")
|
||||||
elif s == SIGBUS:
|
elif s == SIGBUS:
|
||||||
add(buf, "SIGBUS: Illegal storage access. (Attempt to read from nil?)\n")
|
add(||buf, "SIGBUS: Illegal storage access. (Attempt to read from nil?)\n")
|
||||||
else: add(buf, "unknown signal\n")
|
else: add(||buf, "unknown signal\n")
|
||||||
writeToStdErr(buf)
|
writeToStdErr(||buf)
|
||||||
dbgAborting = True # play safe here...
|
dbgAborting = True # play safe here...
|
||||||
GC_enable()
|
GC_enable()
|
||||||
quit(1) # always quit when SIGABRT
|
quit(1) # always quit when SIGABRT
|
||||||
|
|
@ -278,11 +389,9 @@ when not defined(noSignalHandler):
|
||||||
registerSignalHandler() # call it in initialization section
|
registerSignalHandler() # call it in initialization section
|
||||||
# for easier debugging of the GC, this memory is only allocated after the
|
# for easier debugging of the GC, this memory is only allocated after the
|
||||||
# signal handlers have been registered
|
# signal handlers have been registered
|
||||||
new(gAssertionFailed)
|
new(||gAssertionFailed)
|
||||||
buf = newString(2048)
|
||buf = newStringOfCap(2000)
|
||||||
assertBuf = newString(2048)
|
||assertBuf = newStringOfCap(2000)
|
||||||
setLen(buf, 0)
|
|
||||||
setLen(assertBuf, 0)
|
|
||||||
|
|
||||||
proc raiseRangeError(val: biggestInt) {.compilerproc, noreturn, noinline.} =
|
proc raiseRangeError(val: biggestInt) {.compilerproc, noreturn, noinline.} =
|
||||||
raise newException(EOutOfRange, "value " & $val & " out of range")
|
raise newException(EOutOfRange, "value " & $val & " out of range")
|
||||||
|
|
|
||||||
|
|
@ -391,7 +391,7 @@ proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
|
||||||
assert((cast[TAddress](res) and (MemAlign-1)) == 0)
|
assert((cast[TAddress](res) and (MemAlign-1)) == 0)
|
||||||
# now it is buffered in the ZCT
|
# now it is buffered in the ZCT
|
||||||
res.typ = typ
|
res.typ = typ
|
||||||
when debugGC:
|
when debugGC and not hasThreadSupport:
|
||||||
if framePtr != nil and framePtr.prev != nil:
|
if framePtr != nil and framePtr.prev != nil:
|
||||||
res.filename = framePtr.prev.filename
|
res.filename = framePtr.prev.filename
|
||||||
res.line = framePtr.prev.line
|
res.line = framePtr.prev.line
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Nimrod's Runtime Library
|
# Nimrod's Runtime Library
|
||||||
# (c) Copyright 2009 Andreas Rumpf
|
# (c) Copyright 2011 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,6 @@ else:
|
||||||
inc(p, val)
|
inc(p, val)
|
||||||
result = p
|
result = p
|
||||||
|
|
||||||
var
|
|
||||||
isMultiThreaded: bool # true when prog created at least 1 thread
|
|
||||||
|
|
||||||
proc atomicInc(memLoc: var int, x: int): int =
|
proc atomicInc(memLoc: var int, x: int): int =
|
||||||
when hasThreadSupport:
|
when hasThreadSupport:
|
||||||
result = sync_add_and_fetch(memLoc, x)
|
result = sync_add_and_fetch(memLoc, x)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
discard """
|
discard """
|
||||||
file: "texcsub.nim"
|
file: "texcsub.nim"
|
||||||
output: "caught!"
|
output: "caught!"
|
||||||
disabled: true
|
|
||||||
"""
|
"""
|
||||||
# Test inheritance for exception matching:
|
# Test inheritance for exception matching:
|
||||||
|
|
||||||
|
|
|
||||||
4
todo.txt
4
todo.txt
|
|
@ -1,5 +1,4 @@
|
||||||
* thread support: threadvar on Windows seems broken;
|
* add --deadlock_prevention:on|off switch; timeout for locks
|
||||||
add --deadlock_prevention:on|off switch
|
|
||||||
* implicit ref/ptr->var conversion
|
* implicit ref/ptr->var conversion
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -21,7 +20,6 @@ Bugs
|
||||||
----
|
----
|
||||||
- proc (x: int) is passable to proc (x: var int) !?
|
- proc (x: int) is passable to proc (x: var int) !?
|
||||||
- the parser allows empty object case branches
|
- the parser allows empty object case branches
|
||||||
- Exception matching needs to take subclasses into account
|
|
||||||
- pegs: the anchor '^' does not work because many procs use a linear search
|
- pegs: the anchor '^' does not work because many procs use a linear search
|
||||||
and matchLen()
|
and matchLen()
|
||||||
- BUG: generic assign still buggy
|
- BUG: generic assign still buggy
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ proc processFile(filename: string) =
|
||||||
if t.first <= 0: break
|
if t.first <= 0: break
|
||||||
inc(line, countLines(buffer, i, t.first-1))
|
inc(line, countLines(buffer, i, t.first-1))
|
||||||
|
|
||||||
var wholeMatch = buffer.copy(t.first, t.last)
|
var wholeMatch = buffer.substr(t.first, t.last)
|
||||||
|
|
||||||
if optReplace notin options:
|
if optReplace notin options:
|
||||||
highlight(buffer, wholeMatch, "", t, line, showRepl=false)
|
highlight(buffer, wholeMatch, "", t, line, showRepl=false)
|
||||||
|
|
@ -168,15 +168,15 @@ proc processFile(filename: string) =
|
||||||
else:
|
else:
|
||||||
highlight(buffer, wholeMatch, r, t, line, showRepl=reallyReplace)
|
highlight(buffer, wholeMatch, r, t, line, showRepl=reallyReplace)
|
||||||
if reallyReplace:
|
if reallyReplace:
|
||||||
result.add(buffer.copy(i, t.first-1))
|
result.add(buffer.substr(i, t.first-1))
|
||||||
result.add(r)
|
result.add(r)
|
||||||
else:
|
else:
|
||||||
result.add(buffer.copy(i, t.last))
|
result.add(buffer.substr(i, t.last))
|
||||||
|
|
||||||
inc(line, countLines(buffer, t.first, t.last))
|
inc(line, countLines(buffer, t.first, t.last))
|
||||||
i = t.last+1
|
i = t.last+1
|
||||||
if optReplace in options:
|
if optReplace in options:
|
||||||
result.add(copy(buffer, i))
|
result.add(substr(buffer, i))
|
||||||
var f: TFile
|
var f: TFile
|
||||||
if open(f, filename, fmWrite):
|
if open(f, filename, fmWrite):
|
||||||
f.write(result)
|
f.write(result)
|
||||||
|
|
@ -185,7 +185,7 @@ proc processFile(filename: string) =
|
||||||
quit "cannot open file for overwriting: " & filename
|
quit "cannot open file for overwriting: " & filename
|
||||||
|
|
||||||
proc hasRightExt(filename: string, exts: seq[string]): bool =
|
proc hasRightExt(filename: string, exts: seq[string]): bool =
|
||||||
var y = splitFile(filename).ext.copy(1) # skip leading '.'
|
var y = splitFile(filename).ext.substr(1) # skip leading '.'
|
||||||
for x in items(exts):
|
for x in items(exts):
|
||||||
if os.cmpPaths(x, y) == 0: return true
|
if os.cmpPaths(x, y) == 0: return true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ proc parseCmdLine(c: var TConfigData) =
|
||||||
of "var":
|
of "var":
|
||||||
var idx = val.find('=')
|
var idx = val.find('=')
|
||||||
if idx < 0: quit("invalid command line")
|
if idx < 0: quit("invalid command line")
|
||||||
c.vars[copy(val, 0, idx-1)] = copy(val, idx+1)
|
c.vars[substr(val, 0, idx-1)] = substr(val, idx+1)
|
||||||
else: quit(Usage)
|
else: quit(Usage)
|
||||||
of cmdEnd: break
|
of cmdEnd: break
|
||||||
if c.infile.len == 0: quit(Usage)
|
if c.infile.len == 0: quit(Usage)
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ proc parseCmdLine(c: var TConfigData) =
|
||||||
of "var":
|
of "var":
|
||||||
var idx = val.find('=')
|
var idx = val.find('=')
|
||||||
if idx < 0: quit("invalid command line")
|
if idx < 0: quit("invalid command line")
|
||||||
c.vars[copy(val, 0, idx-1)] = copy(val, idx+1)
|
c.vars[substr(val, 0, idx-1)] = substr(val, idx+1)
|
||||||
else: quit(Usage)
|
else: quit(Usage)
|
||||||
of cmdEnd: break
|
of cmdEnd: break
|
||||||
if c.infile.len == 0: quit(Usage)
|
if c.infile.len == 0: quit(Usage)
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ Bugfixes
|
||||||
copied.
|
copied.
|
||||||
- Bugfix: The compiler does not emit very inaccurate floating point literals
|
- Bugfix: The compiler does not emit very inaccurate floating point literals
|
||||||
anymore.
|
anymore.
|
||||||
|
- Bugfix: Subclasses are taken into account for ``try except`` matching.
|
||||||
- Lots of other bugfixes: Too many to list them all.
|
- Lots of other bugfixes: Too many to list them all.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue