fixed a serious code generation bug leading to wrong RTTI
This commit is contained in:
parent
b800b77a1a
commit
3f82352c2e
7 changed files with 76 additions and 29 deletions
|
|
@ -856,7 +856,10 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
result = s.typ
|
result = s.typ
|
||||||
else:
|
else:
|
||||||
assignType(prev, s.typ)
|
assignType(prev, s.typ)
|
||||||
prev.id = s.typ.id
|
# bugfix: keep the fresh id for aliases to integral types:
|
||||||
|
if s.typ.kind notin {tyBool, tyChar, tyInt..tyInt64, tyFloat..tyFloat128,
|
||||||
|
tyUInt..tyUInt64}:
|
||||||
|
prev.id = s.typ.id
|
||||||
result = prev
|
result = prev
|
||||||
of nkSym:
|
of nkSym:
|
||||||
if n.sym.kind == skType and n.sym.typ != nil:
|
if n.sym.kind == skType and n.sym.typ != nil:
|
||||||
|
|
|
||||||
|
|
@ -1961,11 +1961,11 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||||
## for debug builds.
|
## for debug builds.
|
||||||
when hostOS != "standalone":
|
when hostOS != "standalone":
|
||||||
proc getStackTrace*(): string
|
proc getStackTrace*(): string
|
||||||
## gets the current stack trace. This is only works for debug builds.
|
## gets the current stack trace. This only works for debug builds.
|
||||||
|
|
||||||
proc getStackTrace*(e: ref E_Base): string
|
proc getStackTrace*(e: ref E_Base): string
|
||||||
## gets the stack trace associated with `e`, which is the stack that
|
## gets the stack trace associated with `e`, which is the stack that
|
||||||
## lead to the ``raise`` statement. This is only works for debug builds.
|
## lead to the ``raise`` statement. This only works for debug builds.
|
||||||
|
|
||||||
{.push stack_trace: off, profiler:off.}
|
{.push stack_trace: off, profiler:off.}
|
||||||
when hostOS == "standalone":
|
when hostOS == "standalone":
|
||||||
|
|
|
||||||
|
|
@ -553,7 +553,7 @@ proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer =
|
||||||
sysAssert(allocInv(a), "rawAlloc: before listRemove test")
|
sysAssert(allocInv(a), "rawAlloc: before listRemove test")
|
||||||
ListRemove(a.freeSmallChunks[s], c)
|
ListRemove(a.freeSmallChunks[s], c)
|
||||||
sysAssert(allocInv(a), "rawAlloc: end listRemove test")
|
sysAssert(allocInv(a), "rawAlloc: end listRemove test")
|
||||||
sysAssert(((cast[TAddress](result) and PageMask) -% smallChunkOverhead()) %%
|
sysAssert(((cast[TAddress](result) and PageMask) - smallChunkOverhead()) %%
|
||||||
size == 0, "rawAlloc 21")
|
size == 0, "rawAlloc 21")
|
||||||
sysAssert(allocInv(a), "rawAlloc: end small size")
|
sysAssert(allocInv(a), "rawAlloc: end small size")
|
||||||
else:
|
else:
|
||||||
|
|
@ -582,7 +582,7 @@ proc rawDealloc(a: var TMemRegion, p: pointer) =
|
||||||
# `p` is within a small chunk:
|
# `p` is within a small chunk:
|
||||||
var c = cast[PSmallChunk](c)
|
var c = cast[PSmallChunk](c)
|
||||||
var s = c.size
|
var s = c.size
|
||||||
sysAssert(((cast[TAddress](p) and PageMask) -% smallChunkOverhead()) %%
|
sysAssert(((cast[TAddress](p) and PageMask) - smallChunkOverhead()) %%
|
||||||
s == 0, "rawDealloc 3")
|
s == 0, "rawDealloc 3")
|
||||||
var f = cast[ptr TFreeCell](p)
|
var f = cast[ptr TFreeCell](p)
|
||||||
#echo("setting to nil: ", $cast[TAddress](addr(f.zeroField)))
|
#echo("setting to nil: ", $cast[TAddress](addr(f.zeroField)))
|
||||||
|
|
@ -605,7 +605,7 @@ proc rawDealloc(a: var TMemRegion, p: pointer) =
|
||||||
ListRemove(a.freeSmallChunks[s div memAlign], c)
|
ListRemove(a.freeSmallChunks[s div memAlign], c)
|
||||||
c.size = SmallChunkSize
|
c.size = SmallChunkSize
|
||||||
freeBigChunk(a, cast[PBigChunk](c))
|
freeBigChunk(a, cast[PBigChunk](c))
|
||||||
sysAssert(((cast[TAddress](p) and PageMask) -% smallChunkOverhead()) %%
|
sysAssert(((cast[TAddress](p) and PageMask) - smallChunkOverhead()) %%
|
||||||
s == 0, "rawDealloc 2")
|
s == 0, "rawDealloc 2")
|
||||||
else:
|
else:
|
||||||
# set to 0xff to check for usage after free bugs:
|
# set to 0xff to check for usage after free bugs:
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ proc genericAssignAux(dest, src: Pointer, mt: PNimType, shallow: bool) =
|
||||||
unsureAsgnRef(x, s2)
|
unsureAsgnRef(x, s2)
|
||||||
return
|
return
|
||||||
sysAssert(dest != nil, "genericAssignAux 3")
|
sysAssert(dest != nil, "genericAssignAux 3")
|
||||||
unsureAsgnRef(x, newObj(mt, seq.len * mt.base.size + GenericSeqSize))
|
unsureAsgnRef(x, newSeq(mt, seq.len))
|
||||||
var dst = cast[taddress](cast[ppointer](dest)[])
|
var dst = cast[taddress](cast[ppointer](dest)[])
|
||||||
for i in 0..seq.len-1:
|
for i in 0..seq.len-1:
|
||||||
genericAssignAux(
|
genericAssignAux(
|
||||||
|
|
@ -68,9 +68,6 @@ proc genericAssignAux(dest, src: Pointer, mt: PNimType, shallow: bool) =
|
||||||
cast[pointer](cast[taddress](s2) +% i *% mt.base.size +%
|
cast[pointer](cast[taddress](s2) +% i *% mt.base.size +%
|
||||||
GenericSeqSize),
|
GenericSeqSize),
|
||||||
mt.Base, shallow)
|
mt.Base, shallow)
|
||||||
var dstseq = cast[PGenericSeq](dst)
|
|
||||||
dstseq.len = seq.len
|
|
||||||
dstseq.reserved = seq.len
|
|
||||||
of tyObject:
|
of tyObject:
|
||||||
# we need to copy m_type field for tyObject, as it could be empty for
|
# we need to copy m_type field for tyObject, as it could be empty for
|
||||||
# sequence reallocations:
|
# sequence reallocations:
|
||||||
|
|
@ -98,6 +95,35 @@ proc genericShallowAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.} =
|
||||||
genericAssignAux(dest, src, mt, true)
|
genericAssignAux(dest, src, mt, true)
|
||||||
GC_enable()
|
GC_enable()
|
||||||
|
|
||||||
|
when false:
|
||||||
|
proc debugNimType(t: PNimType) =
|
||||||
|
if t.isNil:
|
||||||
|
cprintf("nil!")
|
||||||
|
return
|
||||||
|
var k: cstring
|
||||||
|
case t.kind
|
||||||
|
of tyBool: k = "bool"
|
||||||
|
of tyChar: k = "char"
|
||||||
|
of tyEnum: k = "enum"
|
||||||
|
of tyArray: k = "array"
|
||||||
|
of tyObject: k = "object"
|
||||||
|
of tyTuple: k = "tuple"
|
||||||
|
of tyRange: k = "range"
|
||||||
|
of tyPtr: k = "ptr"
|
||||||
|
of tyRef: k = "ref"
|
||||||
|
of tyVar: k = "var"
|
||||||
|
of tySequence: k = "seq"
|
||||||
|
of tyProc: k = "proc"
|
||||||
|
of tyPointer: k = "range"
|
||||||
|
of tyOpenArray: k = "openarray"
|
||||||
|
of tyString: k = "string"
|
||||||
|
of tyCString: k = "cstring"
|
||||||
|
of tyInt: k = "int"
|
||||||
|
of tyInt32: k = "int32"
|
||||||
|
else: k = "other"
|
||||||
|
cprintf("%s %ld\n", k, t.size)
|
||||||
|
debugNimType(t.base)
|
||||||
|
|
||||||
proc genericSeqAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.} =
|
proc genericSeqAssign(dest, src: Pointer, mt: PNimType) {.compilerProc.} =
|
||||||
var src = src # ugly, but I like to stress the parser sometimes :-)
|
var src = src # ugly, but I like to stress the parser sometimes :-)
|
||||||
genericAssign(dest, addr(src), mt)
|
genericAssign(dest, addr(src), mt)
|
||||||
|
|
|
||||||
|
|
@ -664,6 +664,9 @@ proc dbgRegisterWatchpoint(address: pointer, name: cstring,
|
||||||
Watchpoints[L].oldValue = genericHash(address, typ)
|
Watchpoints[L].oldValue = genericHash(address, typ)
|
||||||
inc WatchpointsLen
|
inc WatchpointsLen
|
||||||
|
|
||||||
|
proc dbgUnregisterWatchpoints*() =
|
||||||
|
WatchpointsLen = 0
|
||||||
|
|
||||||
proc dbgWriteStackTrace(f: PFrame) =
|
proc dbgWriteStackTrace(f: PFrame) =
|
||||||
const
|
const
|
||||||
firstCalls = 32
|
firstCalls = 32
|
||||||
|
|
@ -706,15 +709,22 @@ proc dbgWriteStackTrace(f: PFrame) =
|
||||||
write(stdout, tempFrames[j].procname)
|
write(stdout, tempFrames[j].procname)
|
||||||
write(stdout, "\n")
|
write(stdout, "\n")
|
||||||
|
|
||||||
|
proc strstr(s1, s2: cstring): cstring {.importc, header: "<string.h>".}
|
||||||
|
|
||||||
|
proc interestingFilename(filename: cstring): bool =
|
||||||
|
#result = strstr(filename, "/rst.nim") == nil
|
||||||
|
result = true
|
||||||
|
|
||||||
proc checkWatchpoints =
|
proc checkWatchpoints =
|
||||||
let L = WatchpointsLen
|
let L = WatchpointsLen
|
||||||
for i in 0.. <L:
|
for i in 0.. <L:
|
||||||
let newHash = genericHash(Watchpoints[i].address, Watchpoints[i].typ)
|
let newHash = genericHash(Watchpoints[i].address, Watchpoints[i].typ)
|
||||||
if newHash != Watchpoints[i].oldValue:
|
if newHash != Watchpoints[i].oldValue:
|
||||||
dbgWriteStackTrace(framePtr)
|
if interestingFilename(framePtr.filename):
|
||||||
debugOut(Watchpoints[i].name)
|
dbgWriteStackTrace(framePtr)
|
||||||
|
debugOut(Watchpoints[i].name)
|
||||||
Watchpoints[i].oldValue = newHash
|
Watchpoints[i].oldValue = newHash
|
||||||
|
|
||||||
proc endb(line: int) {.compilerproc.} =
|
proc endb(line: int) {.compilerproc.} =
|
||||||
# This proc is called before every Nimrod code line!
|
# This proc is called before every Nimrod code line!
|
||||||
# Thus, it must have as few parameters as possible to keep the
|
# Thus, it must have as few parameters as possible to keep the
|
||||||
|
|
|
||||||
|
|
@ -192,11 +192,7 @@ proc quitOrDebug() {.inline.} =
|
||||||
else:
|
else:
|
||||||
endbStep() # call the debugger
|
endbStep() # call the debugger
|
||||||
|
|
||||||
proc raiseException(e: ref E_Base, ename: CString) {.compilerRtl.} =
|
proc raiseExceptionAux(e: ref E_Base) =
|
||||||
e.name = ename
|
|
||||||
when hasSomeStackTrace:
|
|
||||||
e.trace = ""
|
|
||||||
rawWriteStackTrace(e.trace)
|
|
||||||
if localRaiseHook != nil:
|
if localRaiseHook != nil:
|
||||||
if not localRaiseHook(e): return
|
if not localRaiseHook(e): return
|
||||||
if globalRaiseHook != nil:
|
if globalRaiseHook != nil:
|
||||||
|
|
@ -205,7 +201,7 @@ proc raiseException(e: ref E_Base, ename: CString) {.compilerRtl.} =
|
||||||
pushCurrentException(e)
|
pushCurrentException(e)
|
||||||
c_longjmp(excHandler.context, 1)
|
c_longjmp(excHandler.context, 1)
|
||||||
elif e[] of EOutOfMemory:
|
elif e[] of EOutOfMemory:
|
||||||
writeToStdErr(ename)
|
writeToStdErr(e.name)
|
||||||
quitOrDebug()
|
quitOrDebug()
|
||||||
else:
|
else:
|
||||||
when hasSomeStackTrace:
|
when hasSomeStackTrace:
|
||||||
|
|
@ -214,7 +210,7 @@ proc raiseException(e: ref E_Base, ename: CString) {.compilerRtl.} =
|
||||||
add(buf, "Error: unhandled exception: ")
|
add(buf, "Error: unhandled exception: ")
|
||||||
if not isNil(e.msg): add(buf, e.msg)
|
if not isNil(e.msg): add(buf, e.msg)
|
||||||
add(buf, " [")
|
add(buf, " [")
|
||||||
add(buf, $ename)
|
add(buf, $e.name)
|
||||||
add(buf, "]\n")
|
add(buf, "]\n")
|
||||||
writeToStdErr(buf)
|
writeToStdErr(buf)
|
||||||
else:
|
else:
|
||||||
|
|
@ -230,16 +226,23 @@ proc raiseException(e: ref E_Base, ename: CString) {.compilerRtl.} =
|
||||||
add(buf, "Error: unhandled exception: ")
|
add(buf, "Error: unhandled exception: ")
|
||||||
if not isNil(e.msg): add(buf, e.msg)
|
if not isNil(e.msg): add(buf, e.msg)
|
||||||
add(buf, " [")
|
add(buf, " [")
|
||||||
xadd(buf, ename, c_strlen(ename))
|
xadd(buf, e.name, c_strlen(e.name))
|
||||||
add(buf, "]\n")
|
add(buf, "]\n")
|
||||||
writeToStdErr(buf)
|
writeToStdErr(buf)
|
||||||
quitOrDebug()
|
quitOrDebug()
|
||||||
|
|
||||||
|
proc raiseException(e: ref E_Base, ename: CString) {.compilerRtl.} =
|
||||||
|
e.name = ename
|
||||||
|
when hasSomeStackTrace:
|
||||||
|
e.trace = ""
|
||||||
|
rawWriteStackTrace(e.trace)
|
||||||
|
raiseExceptionAux(e)
|
||||||
|
|
||||||
proc reraiseException() {.compilerRtl.} =
|
proc reraiseException() {.compilerRtl.} =
|
||||||
if currException == nil:
|
if currException == nil:
|
||||||
raise newException(ENoExceptionToReraise, "no exception to reraise")
|
raise newException(ENoExceptionToReraise, "no exception to reraise")
|
||||||
else:
|
else:
|
||||||
raiseException(currException, currException.name)
|
raiseExceptionAux(currException)
|
||||||
|
|
||||||
proc WriteStackTrace() =
|
proc WriteStackTrace() =
|
||||||
when hasSomeStackTrace:
|
when hasSomeStackTrace:
|
||||||
|
|
|
||||||
|
|
@ -318,13 +318,18 @@ proc rstMessage(p: TRstParser, msgKind: TMsgKind) =
|
||||||
p.col + p.tok[p.idx].col, msgKind,
|
p.col + p.tok[p.idx].col, msgKind,
|
||||||
p.tok[p.idx].symbol)
|
p.tok[p.idx].symbol)
|
||||||
|
|
||||||
|
when false:
|
||||||
|
proc corrupt(p: TRstParser) =
|
||||||
|
assert p.indentStack[0] == 0
|
||||||
|
for i in 1 .. high(p.indentStack): assert p.indentStack[i] < 1_000
|
||||||
|
|
||||||
proc currInd(p: TRstParser): int =
|
proc currInd(p: TRstParser): int =
|
||||||
result = p.indentStack[high(p.indentStack)]
|
result = p.indentStack[high(p.indentStack)]
|
||||||
|
|
||||||
proc pushInd(p: var TRstParser, ind: int) =
|
proc pushInd(p: var TRstParser, ind: int) =
|
||||||
add(p.indentStack, ind)
|
add(p.indentStack, ind)
|
||||||
|
|
||||||
proc popInd(p: var TRstParser) =
|
proc popInd(p: var TRstParser) =
|
||||||
if len(p.indentStack) > 1: setlen(p.indentStack, len(p.indentStack) - 1)
|
if len(p.indentStack) > 1: setlen(p.indentStack, len(p.indentStack) - 1)
|
||||||
|
|
||||||
proc initParser(p: var TRstParser, sharedState: PSharedState) =
|
proc initParser(p: var TRstParser, sharedState: PSharedState) =
|
||||||
|
|
@ -616,8 +621,8 @@ when false:
|
||||||
|
|
||||||
proc isURL(p: TRstParser, i: int): bool =
|
proc isURL(p: TRstParser, i: int): bool =
|
||||||
result = (p.tok[i+1].symbol == ":") and (p.tok[i+2].symbol == "//") and
|
result = (p.tok[i+1].symbol == ":") and (p.tok[i+2].symbol == "//") and
|
||||||
(p.tok[i+3].kind == tkWord) and
|
(p.tok[i+3].kind == tkWord) and
|
||||||
(p.tok[i].symbol in ["http", "ftp", "gopher", "telnet", "file"])
|
(p.tok[i].symbol in ["http", "https", "ftp", "telnet", "file"])
|
||||||
|
|
||||||
proc parseURL(p: var TRstParser, father: PRstNode) =
|
proc parseURL(p: var TRstParser, father: PRstNode) =
|
||||||
#if p.tok[p.idx].symbol[strStart] == '<':
|
#if p.tok[p.idx].symbol[strStart] == '<':
|
||||||
|
|
@ -1062,7 +1067,7 @@ proc parseParagraph(p: var TRstParser, result: PRstNode) =
|
||||||
parseInline(p, result)
|
parseInline(p, result)
|
||||||
of tkWhite, tkWord, tkAdornment, tkOther:
|
of tkWhite, tkWord, tkAdornment, tkOther:
|
||||||
parseInline(p, result)
|
parseInline(p, result)
|
||||||
else: break
|
else: break
|
||||||
|
|
||||||
proc parseHeadline(p: var TRstParser): PRstNode =
|
proc parseHeadline(p: var TRstParser): PRstNode =
|
||||||
result = newRstNode(rnHeadline)
|
result = newRstNode(rnHeadline)
|
||||||
|
|
@ -1308,9 +1313,8 @@ proc parseSection(p: var TRstParser, result: PRstNode) =
|
||||||
popInd(p)
|
popInd(p)
|
||||||
else:
|
else:
|
||||||
leave = true
|
leave = true
|
||||||
break
|
break
|
||||||
if leave: break
|
if leave or p.tok[p.idx].kind == tkEof: break
|
||||||
if p.tok[p.idx].kind == tkEof: break
|
|
||||||
var a: PRstNode = nil
|
var a: PRstNode = nil
|
||||||
var k = whichSection(p)
|
var k = whichSection(p)
|
||||||
case k
|
case k
|
||||||
|
|
@ -1361,6 +1365,7 @@ proc parseDoc(p: var TRstParser): PRstNode =
|
||||||
isAllocatedPtr(cast[pointer](p.tok[i].symbol))
|
isAllocatedPtr(cast[pointer](p.tok[i].symbol))
|
||||||
echo "index: ", p.idx, " length: ", high(p.tok), "##",
|
echo "index: ", p.idx, " length: ", high(p.tok), "##",
|
||||||
p.tok[p.idx-1], p.tok[p.idx], p.tok[p.idx+1]
|
p.tok[p.idx-1], p.tok[p.idx], p.tok[p.idx+1]
|
||||||
|
#assert isAllocatedPtr(cast[pointer](p.indentStack))
|
||||||
rstMessage(p, meGeneralParseError)
|
rstMessage(p, meGeneralParseError)
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue