fixed a serious code generation bug leading to wrong RTTI

This commit is contained in:
Araq 2012-10-19 01:59:28 +02:00
commit 3f82352c2e
7 changed files with 76 additions and 29 deletions

View file

@ -856,6 +856,9 @@ 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)
# 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 prev.id = s.typ.id
result = prev result = prev
of nkSym: of nkSym:

View file

@ -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":

View file

@ -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:

View file

@ -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)

View file

@ -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,11 +709,18 @@ 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:
if interestingFilename(framePtr.filename):
dbgWriteStackTrace(framePtr) dbgWriteStackTrace(framePtr)
debugOut(Watchpoints[i].name) debugOut(Watchpoints[i].name)
Watchpoints[i].oldValue = newHash Watchpoints[i].oldValue = newHash

View file

@ -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:

View file

@ -318,6 +318,11 @@ 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)]
@ -617,7 +622,7 @@ 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] == '<':
@ -1309,8 +1314,7 @@ proc parseSection(p: var TRstParser, result: PRstNode) =
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