Merge branch 'devel' into sighashes

This commit is contained in:
Araq 2016-11-28 20:59:30 +01:00
commit 27723af469
75 changed files with 1258 additions and 361 deletions

View file

@ -354,6 +354,14 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
else: internalError("genAssignment: " & $ty.kind)
if optMemTracker in p.options and dest.s in {OnHeap, OnUnknown}:
#writeStackTrace()
#echo p.currLineInfo, " requesting"
linefmt(p, cpsStmts, "#memTrackerWrite((void*)$1, $2, $3, $4);$n",
addrLoc(dest), rope getSize(dest.t),
makeCString(p.currLineInfo.toFullPath),
rope p.currLineInfo.safeLineNm)
proc genDeepCopy(p: BProc; dest, src: TLoc) =
var ty = skipTypes(dest.t, abstractVarRange)
case ty.kind
@ -1940,6 +1948,7 @@ proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
d.s = OnStatic
proc expr(p: BProc, n: PNode, d: var TLoc) =
p.currLineInfo = n.info
case n.kind
of nkSym:
var sym = n.sym

View file

@ -221,6 +221,10 @@ proc cacheGetType(tab: TypeCache; sig: SigHash): Rope =
# linear search is not necessary anymore:
result = tab.getOrDefault(sig)
proc addAbiCheck(m: BModule, t: PType, name: Rope) =
if isDefined("checkabi"):
addf(m.s[cfsTypeInfo], "NIM_CHECK_SIZE($1, $2);$n", [name, rope(getSize(t))])
proc getTempName(m: BModule): Rope =
result = m.tmpBase & rope(m.labels)
inc m.labels
@ -282,6 +286,11 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope =
result = getSimpleTypeDesc(m, lastSon typ)
else: result = nil
if result != nil and typ.isImportedType():
if cacheGetType(m.typeCache, typ) == nil:
idTablePut(m.typeCache, typ, result)
addAbiCheck(m, typ, result)
proc pushType(m: BModule, typ: PType) =
add(m.typeStack, typ)
@ -678,6 +687,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
let foo = getTypeDescAux(m, t.sons[1], check)
addf(m.s[cfsTypes], "typedef $1 $2[$3];$n",
[foo, result, rope(n)])
else: addAbiCheck(m, t, result)
of tyObject, tyTuple:
if isImportedCppType(t) and origTyp.kind == tyGenericInst:
# for instantiated templates we do not go through the type cache as the
@ -739,7 +749,9 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
m.typeCache[sig] = result # always call for sideeffects:
let recdesc = if t.kind != tyTuple: getRecordDesc(m, t, result, check)
else: getTupleDesc(m, t, result, check)
if not isImportedType(t): add(m.s[cfsTypes], recdesc)
if not isImportedType(t):
add(m.s[cfsTypes], recdesc)
elif tfIncompleteStruct notin t.flags: addAbiCheck(m, t, result)
of tySet:
result = getTypeName(m, t.lastSon, hashType t.lastSon) & "_Set"
m.typeCache[sig] = result
@ -841,6 +853,8 @@ proc genTypeInfoAuxBase(m: BModule; typ, origType: PType; name, base: Rope) =
#else MessageOut("can contain a cycle: " & typeToString(typ))
if flags != 0:
addf(m.s[cfsTypeInit3], "$1.flags = $2;$n", [name, rope(flags)])
if isDefined("nimTypeNames"):
addf(m.s[cfsTypeInit3], "$1.name = $2;$n", [name, makeCstring typeToString origType])
discard cgsym(m, "TNimType")
addf(m.s[cfsVars], "TNimType $1; /* $2 */$n",
[name, rope(typeToString(typ))])

View file

@ -69,6 +69,7 @@ type
beforeRetNeeded*: bool # true iff 'BeforeRet' label for proc is needed
threadVarAccessed*: bool # true if the proc already accessed some threadvar
lastLineInfo*: TLineInfo # to avoid generating excessive 'nimln' statements
currLineInfo*: TLineInfo # AST codegen will make this superfluous
nestedTryStmts*: seq[PNode] # in how many nested try statements we are
# (the vars must be volatile then)
inExceptBlock*: int # are we currently inside an except block?

View file

@ -242,6 +242,7 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
of "linetrace": result = contains(gOptions, optLineTrace)
of "debugger": result = contains(gOptions, optEndb)
of "profiler": result = contains(gOptions, optProfiler)
of "memtracker": result = contains(gOptions, optMemTracker)
of "checks", "x": result = gOptions * ChecksOptions == ChecksOptions
of "floatchecks":
result = gOptions * {optNaNCheck, optInfCheck} == {optNaNCheck, optInfCheck}
@ -264,6 +265,7 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
of "implicitstatic": result = contains(gOptions, optImplicitStatic)
of "patterns": result = contains(gOptions, optPatterns)
of "experimental": result = gExperimentalMode
of "excessivestacktrace": result = contains(gGlobalOptions, optExcessiveStackTrace)
else: invalidCmdLineOption(passCmd1, switch, info)
proc processPath(path: string, info: TLineInfo,
@ -445,6 +447,10 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
processOnOffSwitch({optProfiler}, arg, pass, info)
if optProfiler in gOptions: defineSymbol("profiler")
else: undefSymbol("profiler")
of "memtracker":
processOnOffSwitch({optMemTracker}, arg, pass, info)
if optMemTracker in gOptions: defineSymbol("memtracker")
else: undefSymbol("memtracker")
of "checks", "x": processOnOffSwitch(ChecksOptions, arg, pass, info)
of "floatchecks":
processOnOffSwitch({optNaNCheck, optInfCheck}, arg, pass, info)

View file

@ -100,7 +100,7 @@ proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
let ident = lookups.considerQuotedIdent(n)
let s = strTableGet(fromMod.tab, ident)
if s == nil:
localError(n.info, errUndeclaredIdentifier, ident.s)
errorUndeclaredIdentifier(c, n.info, ident.s)
else:
if s.kind == skStub: loadStub(s)
if s.kind notin ExportableSymKinds:
@ -162,12 +162,26 @@ proc importModuleAs(n: PNode, realModule: PSym): PSym =
proc myImportModule(c: PContext, n: PNode): PSym =
var f = checkModuleName(n)
if f != InvalidFileIDX:
let L = c.graph.importStack.len
let recursion = c.graph.importStack.find(f)
c.graph.importStack.add f
#echo "adding ", toFullPath(f), " at ", L+1
if recursion >= 0:
var err = ""
for i in countup(recursion, L-1):
if i > recursion: err.add "\n"
err.add toFullPath(c.graph.importStack[i]) & " imports " &
toFullPath(c.graph.importStack[i+1])
c.recursiveDep = err
result = importModuleAs(n, gImportModule(c.graph, c.module, f, c.cache))
#echo "set back to ", L
c.graph.importStack.setLen(L)
# we cannot perform this check reliably because of
# test: modules/import_in_config)
if result.info.fileIndex == c.module.info.fileIndex and
result.info.fileIndex == n.info.fileIndex:
localError(n.info, errGenerated, "A module cannot import itself")
when true:
if result.info.fileIndex == c.module.info.fileIndex and
result.info.fileIndex == n.info.fileIndex:
localError(n.info, errGenerated, "A module cannot import itself")
if sfDeprecated in result.flags:
message(n.info, warnDeprecated, result.name.s)
#suggestSym(n.info, result, false)

View file

@ -242,6 +242,15 @@ proc errorUseQualifier*(c: PContext; info: TLineInfo; s: PSym) =
inc i
localError(info, errGenerated, err)
proc errorUndeclaredIdentifier*(c: PContext; info: TLineInfo; name: string) =
var err = "undeclared identifier: '" & name & "'"
if c.recursiveDep.len > 0:
err.add "\nThis might be caused by a recursive module dependency: "
err.add c.recursiveDep
# prevent excessive errors for 'nim check'
c.recursiveDep = nil
localError(info, errGenerated, err)
proc lookUp*(c: PContext, n: PNode): PSym =
# Looks up a symbol. Generates an error in case of nil.
case n.kind
@ -249,7 +258,7 @@ proc lookUp*(c: PContext, n: PNode): PSym =
result = searchInScopes(c, n.ident).skipAlias(n)
if result == nil:
fixSpelling(n, n.ident, searchInScopes)
localError(n.info, errUndeclaredIdentifier, n.ident.s)
errorUndeclaredIdentifier(c, n.info, n.ident.s)
result = errorSym(c, n)
of nkSym:
result = n.sym
@ -258,7 +267,7 @@ proc lookUp*(c: PContext, n: PNode): PSym =
result = searchInScopes(c, ident).skipAlias(n)
if result == nil:
fixSpelling(n, ident, searchInScopes)
localError(n.info, errUndeclaredIdentifier, ident.s)
errorUndeclaredIdentifier(c, n.info, ident.s)
result = errorSym(c, n)
else:
internalError(n.info, "lookUp")
@ -282,7 +291,7 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym =
result = searchInScopes(c, ident, allExceptModule).skipAlias(n)
if result == nil and checkUndeclared in flags:
fixSpelling(n, ident, searchInScopes)
localError(n.info, errUndeclaredIdentifier, ident.s)
errorUndeclaredIdentifier(c, n.info, ident.s)
result = errorSym(c, n)
elif checkAmbiguity in flags and result != nil and
contains(c.ambiguousSymbols, result.id):
@ -307,7 +316,7 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym =
result = strTableGet(m.tab, ident).skipAlias(n)
if result == nil and checkUndeclared in flags:
fixSpelling(n.sons[1], ident, searchInScopes)
localError(n.sons[1].info, errUndeclaredIdentifier, ident.s)
errorUndeclaredIdentifier(c, n.sons[1].info, ident.s)
result = errorSym(c, n.sons[1])
elif n.sons[1].kind == nkSym:
result = n.sons[1].sym

View file

@ -36,6 +36,8 @@ type
invalidTransitiveClosure: bool
inclToMod*: Table[int32, int32] # mapping of include file to the
# first module that included it
importStack*: seq[int32] # The current import stack. Used for detecting recursive
# module dependencies.
{.this: g.}
@ -44,12 +46,14 @@ proc newModuleGraph*(): ModuleGraph =
initStrTable(result.packageSyms)
result.deps = initIntSet()
result.modules = @[]
result.importStack = @[]
result.inclToMod = initTable[int32, int32]()
proc resetAllModules*(g: ModuleGraph) =
initStrTable(packageSyms)
deps = initIntSet()
modules = @[]
importStack = @[]
inclToMod = initTable[int32, int32]()
proc getModule*(g: ModuleGraph; fileIdx: int32): PSym =

View file

@ -231,6 +231,7 @@ proc compileProject*(graph: ModuleGraph; cache: IdentCache;
wantMainModule()
let systemFileIdx = fileInfoIdx(options.libpath / "system.nim")
let projectFile = if projectFileIdx < 0: gProjectMainIdx else: projectFileIdx
graph.importStack.add projectFile
if projectFile == systemFileIdx:
discard graph.compileModule(projectFile, cache, {sfMainModule, sfSystemModule})
else:

View file

@ -35,7 +35,7 @@ type
errNoneSpeedOrSizeExpectedButXFound, errGuiConsoleOrLibExpectedButXFound,
errUnknownOS, errUnknownCPU, errGenOutExpectedButXFound,
errArgsNeedRunOption, errInvalidMultipleAsgn, errColonOrEqualsExpected,
errExprExpected, errUndeclaredIdentifier, errUndeclaredField,
errExprExpected, errUndeclaredField,
errUndeclaredRoutine, errUseQualifier,
errTypeExpected,
errSystemNeeds, errExecutionOfProgramFailed, errNotOverloadable,
@ -197,7 +197,6 @@ const
errInvalidMultipleAsgn: "multiple assignment is not allowed",
errColonOrEqualsExpected: "\':\' or \'=\' expected, but found \'$1\'",
errExprExpected: "expression expected, but found \'$1\'",
errUndeclaredIdentifier: "undeclared identifier: \'$1\'",
errUndeclaredField: "undeclared field: \'$1\'",
errUndeclaredRoutine: "attempting to call undeclared routine: \'$1\'",
errUseQualifier: "ambiguous identifier: \'$1\' -- use a qualifier",
@ -676,9 +675,8 @@ proc getInfoContext*(index: int): TLineInfo =
if i >=% L: result = unknownLineInfo()
else: result = msgContext[i]
proc toFilename*(fileIdx: int32): string =
if fileIdx < 0: result = "???"
else: result = fileInfos[fileIdx].projPath
template toFilename*(fileIdx: int32): string =
(if fileIdx < 0: "???" else: fileInfos[fileIdx].projPath)
proc toFullPath*(fileIdx: int32): string =
if fileIdx < 0: result = "???"

View file

@ -46,7 +46,7 @@ proc handleCmdLine(cache: IdentCache) =
if gProjectName == "-":
gProjectName = "stdinfile"
gProjectFull = "stdinfile"
gProjectPath = getCurrentDir()
gProjectPath = canonicalizePath getCurrentDir()
gProjectIsStdin = true
elif gProjectName != "":
try:
@ -54,10 +54,10 @@ proc handleCmdLine(cache: IdentCache) =
except OSError:
gProjectFull = gProjectName
let p = splitFile(gProjectFull)
gProjectPath = p.dir
gProjectPath = canonicalizePath p.dir
gProjectName = p.name
else:
gProjectPath = getCurrentDir()
gProjectPath = canonicalizePath getCurrentDir()
loadConfigs(DefaultConfig) # load all config files
let scriptFile = gProjectFull.changeFileExt("nims")
if fileExists(scriptFile):

View file

@ -8,10 +8,9 @@
#
## exposes the Nim VM to clients.
import
ast, modules, passes, passaux, condsyms,
options, nimconf, lists, sem, semdata, llstream, vm
options, nimconf, lists, sem, semdata, llstream, vm, modulegraphs, idents
proc execute*(program: string) =
passes.gIncludeFile = includeModule
@ -27,7 +26,9 @@ proc execute*(program: string) =
registerPass(evalPass)
appendStr(searchPaths, options.libpath)
compileSystemModule()
var m = makeStdinModule()
var graph = newModuleGraph()
var cache = newIdentCache()
var m = makeStdinModule(graph)
incl(m.flags, sfMainModule)
processModule(m, llStreamOpen(program), nil)
compileSystemModule(graph,cache)
processModule(graph,m, llStreamOpen(program), nil, cache)

View file

@ -34,7 +34,8 @@ type # please make sure we have under 32 options
optProfiler, # profiler turned on
optImplicitStatic, # optimization: implicit at compile time
# evaluation
optPatterns # en/disable pattern matching
optPatterns, # en/disable pattern matching
optMemTracker
TOptions* = set[TOption]
TGlobalOption* = enum # **keep binary compatible**
@ -231,10 +232,10 @@ proc canonicalizePath*(path: string): string =
proc shortenDir*(dir: string): string =
## returns the interesting part of a dir
var prefix = getPrefixDir() & DirSep
var prefix = gProjectPath & DirSep
if startsWith(dir, prefix):
return substr(dir, len(prefix))
prefix = gProjectPath & DirSep
prefix = getPrefixDir() & DirSep
if startsWith(dir, prefix):
return substr(dir, len(prefix))
result = dir

View file

@ -149,14 +149,25 @@ proc closePassesCached(a: var TPassContextArray) =
m = gPasses[i].close(a[i], m)
a[i] = nil # free the memory here
proc resolveMod(module, relativeTo: string): int32 =
let fullPath = findModule(module, relativeTo)
if fullPath.len == 0:
result = InvalidFileIDX
else:
result = fullPath.fileInfoIdx
proc processImplicits(implicits: seq[string], nodeKind: TNodeKind,
a: var TPassContextArray) =
a: var TPassContextArray; m: PSym) =
# XXX fixme this should actually be relative to the config file!
let relativeTo = m.info.toFullPath
for module in items(implicits):
var importStmt = newNodeI(nodeKind, gCmdLineInfo)
var str = newStrNode(nkStrLit, module)
str.info = gCmdLineInfo
importStmt.addSon str
if not processTopLevelStmt(importStmt, a): break
# implicit imports should not lead to a module importing itself
if m.position != resolveMod(module, relativeTo):
var importStmt = newNodeI(nodeKind, gCmdLineInfo)
var str = newStrNode(nkStrLit, module)
str.info = gCmdLineInfo
importStmt.addSon str
if not processTopLevelStmt(importStmt, a): break
proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
rd: PRodReader; cache: IdentCache): bool {.discardable.} =
@ -183,8 +194,8 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
# modules to include between compilation runs? we'd need to track that
# in ROD files. I think we should enable this feature only
# for the interactive mode.
processImplicits implicitImports, nkImportStmt, a
processImplicits implicitIncludes, nkIncludeStmt, a
processImplicits implicitImports, nkImportStmt, a, module
processImplicits implicitIncludes, nkIncludeStmt, a, module
while true:
var n = parseTopLevelStmt(p)

View file

@ -323,7 +323,8 @@ proc processOption(c: PContext, n: PNode): bool =
of wStacktrace: onOff(c, n, {optStackTrace})
of wLinetrace: onOff(c, n, {optLineTrace})
of wDebugger: onOff(c, n, {optEndb})
of wProfiler: onOff(c, n, {optProfiler})
of wProfiler: onOff(c, n, {optProfiler, optMemTracker})
of wMemTracker: onOff(c, n, {optMemTracker})
of wByRef: onOff(c, n, {optByRef})
of wDynlib: processDynLib(c, n, nil)
of wOptimization:

View file

@ -110,6 +110,7 @@ type
cache*: IdentCache
graph*: ModuleGraph
signatures*: TStrTable
recursiveDep*: string
proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair =
result.genericSym = s

View file

@ -1553,7 +1553,7 @@ proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym =
if isCallExpr(n):
var expandedSym = qualifiedLookUp(c, n[0], {checkUndeclared})
if expandedSym == nil:
localError(n.info, errUndeclaredIdentifier, n[0].renderTree)
errorUndeclaredIdentifier(c, n.info, n[0].renderTree)
return errorSym(c, n[0])
if expandedSym.kind notin {skMacro, skTemplate}:

View file

@ -107,7 +107,7 @@ proc lookup(c: PContext, n: PNode, flags: TSemGenericFlags,
var s = searchInScopes(c, ident).skipAlias(n)
if s == nil:
if ident.id notin ctx.toMixin and withinMixin notin flags:
localError(n.info, errUndeclaredIdentifier, ident.s)
errorUndeclaredIdentifier(c, n.info, ident.s)
else:
if withinBind in flags:
result = symChoice(c, n, s, scClosed)
@ -195,7 +195,7 @@ proc semGenericStmt(c: PContext, n: PNode,
if s == nil and withinMixin notin flags and
fn.kind in {nkIdent, nkAccQuoted} and
considerQuotedIdent(fn).id notin ctx.toMixin:
localError(n.info, errUndeclaredIdentifier, fn.renderTree)
errorUndeclaredIdentifier(c, n.info, fn.renderTree)
var first = 0
var mixinContext = false

View file

@ -143,7 +143,7 @@ proc semBindSym(c: PContext, n: PNode): PNode =
var sc = symChoice(c, id, s, TSymChoiceRule(isMixin.intVal))
result.add(sc)
else:
localError(n.sons[1].info, errUndeclaredIdentifier, sl.strVal)
errorUndeclaredIdentifier(c, n.sons[1].info, sl.strVal)
proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode

View file

@ -34,7 +34,7 @@ type
wColon, wColonColon, wEquals, wDot, wDotDot,
wStar, wMinus,
wMagic, wThread, wFinal, wProfiler, wObjChecks,
wMagic, wThread, wFinal, wProfiler, wMemTracker, wObjChecks,
wIntDefine, wStrDefine,
wDestroy,
@ -121,7 +121,7 @@ const
":", "::", "=", ".", "..",
"*", "-",
"magic", "thread", "final", "profiler", "objchecks", "intdefine", "strdefine",
"magic", "thread", "final", "profiler", "memtracker", "objchecks", "intdefine", "strdefine",
"destroy",