new name mangling scheme implemented

This commit is contained in:
Andreas Rumpf
2017-02-02 10:30:01 +01:00
parent d9cf9b079e
commit 56aa1ac5bc
5 changed files with 55 additions and 18 deletions

View File

@@ -116,13 +116,42 @@ proc mangleName(m: BModule; s: PSym): Rope =
add(result, m.idOrSig(s))
s.loc.r = result
template mangleParamName(m: BModule; s: PSym): Rope = mangleName(m, s)
proc mangleParamName(m: BModule; s: PSym): Rope =
## we cannot use 'sigConflicts' here since we have a BModule, not a BProc.
## Fortunately C's scoping rules are sane enough so that that doesn't
## cause any trouble.
result = s.loc.r
if result == nil:
result = s.name.s.mangle.rope
if isKeyword(s.name) or m.g.config.cppDefines.contains(s.name.s):
result.add "0"
s.loc.r = result
when false:
proc mangleName(p: BProc; s: PSym): Rope =
assert s.kind in skLocalVars
if sfGlobal in s.flags: return mangleName(p.module, s)
if isKeyword(s.name): discard
proc mangleLocalName(p: BProc; s: PSym): Rope =
assert s.kind in skLocalVars+{skTemp}
assert sfGlobal notin s.flags
result = s.loc.r
if result == nil:
var key = s.name.s.mangle
shallow(key)
let counter = p.sigConflicts.getOrDefault(key)
result = key.rope
if s.kind == skTemp:
# speed up conflict search for temps (these are quite common):
if counter != 0: result.add "_" & rope(counter+1)
elif counter != 0 or isKeyword(s.name) or p.module.g.config.cppDefines.contains(s.name.s):
result.add "_" & rope(counter+1)
p.sigConflicts.inc(key)
s.loc.r = result
proc scopeMangledParam(p: BProc; param: PSym) =
## parameter generation only takes BModule, not a BProc, so we have to
## remember these parameter names are already in scope to be able to
## generate unique identifiers reliably (consider that ``var a = a`` is
## even an idiom in Nim).
var key = param.name.s.mangle
shallow(key)
p.sigConflicts.inc(key)
const
irrelevantForBackend = {tyGenericBody, tyGenericInst, tyGenericInvocation,

View File

@@ -14,7 +14,7 @@ import
nversion, nimsets, msgs, securehash, bitsets, idents, lists, types,
ccgutils, os, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases,
lowerings, semparallel, tables
lowerings, semparallel, tables, sets
import strutils except `%` # collides with ropes.`%`
@@ -369,7 +369,7 @@ proc localDebugInfo(p: BProc, s: PSym) =
proc localVarDecl(p: BProc; s: PSym): Rope =
if s.loc.k == locNone:
fillLoc(s.loc, locLocalVar, s.typ, mangleName(p.module, s), OnStack)
fillLoc(s.loc, locLocalVar, s.typ, mangleLocalName(p, s), OnStack)
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
result = getTypeDesc(p.module, s.typ)
if s.constraint.isNil:
@@ -434,6 +434,7 @@ proc assignGlobalVar(p: BProc, s: PSym) =
proc assignParam(p: BProc, s: PSym) =
assert(s.loc.r != nil)
scopeMangledParam(p, s)
localDebugInfo(p, s)
proc fillProcLoc(m: BModule; sym: PSym) =
@@ -1212,13 +1213,13 @@ proc newModule(g: BModuleList; module: PSym): BModule =
if (sfDeadCodeElim in module.flags):
internalError("added pending module twice: " & module.filename)
template injectG() {.dirty.} =
template injectG(config) {.dirty.} =
if graph.backend == nil:
graph.backend = newModuleList()
graph.backend = newModuleList(config)
let g = BModuleList(graph.backend)
proc myOpen(graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext =
injectG()
injectG(graph.config)
result = newModule(g, module)
if optGenIndex in gGlobalOptions and g.generatedHeader == nil:
let f = if graph.config.headerFile.len > 0: graph.config.headerFile else: gProjectFull
@@ -1258,7 +1259,7 @@ proc getCFile(m: BModule): string =
result = changeFileExt(completeCFilePath(m.cfilename.withPackageName), ext)
proc myOpenCached(graph: ModuleGraph; module: PSym, rd: PRodReader): PPassContext =
injectG()
injectG(graph.config)
assert optSymbolFiles in gGlobalOptions
var m = newModule(g, module)
readMergeInfo(getCFile(m), m)

View File

@@ -76,7 +76,7 @@ type
# leaving such scopes by raise or by return must
# execute any applicable finally blocks
finallySafePoints*: seq[Rope] # For correctly cleaning up exceptions when
# using return in finally statements
# using return in finally statements
labels*: Natural # for generating unique labels in the C proc
blocks*: seq[TBlock] # nested blocks
breakIdx*: int # the block that will be exited
@@ -92,6 +92,7 @@ type
# (yes, C++ is weird like that)
gcFrameId*: Natural # for the GC stack marking
gcFrameType*: Rope # the struct {} we put the GC markers into
sigConflicts*: CountTable[string]
TTypeSeq* = seq[PType]
TypeCache* = Table[SigHash, Rope]
@@ -163,9 +164,10 @@ proc newProc*(prc: PSym, module: BModule): BProc =
newSeq(result.blocks, 1)
result.nestedTryStmts = @[]
result.finallySafePoints = @[]
result.sigConflicts = initCountTable[string]()
proc newModuleList*(): BModuleList =
BModuleList(modules: @[], typeInfoMarker: initTable[SigHash, Rope]())
proc newModuleList*(config: ConfigRef): BModuleList =
BModuleList(modules: @[], typeInfoMarker: initTable[SigHash, Rope](), config: config)
iterator cgenModules*(g: BModuleList): BModule =
for i in 0..high(g.modules):

View File

@@ -665,9 +665,14 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
of wExportc:
makeExternExport(sym, getOptionalStr(c, it, "$1"), it.info)
incl(sym.flags, sfUsed) # avoid wrong hints
of wImportc: makeExternImport(sym, getOptionalStr(c, it, "$1"), it.info)
of wImportc:
let name = getOptionalStr(c, it, "$1")
cppDefine(c.graph.config, name)
makeExternImport(sym, name, it.info)
of wImportCompilerProc:
processImportCompilerProc(sym, getOptionalStr(c, it, "$1"), it.info)
let name = getOptionalStr(c, it, "$1")
cppDefine(c.graph.config, name)
processImportCompilerProc(sym, name, it.info)
of wExtern: setExternName(sym, expectStrLit(c, it), it.info)
of wImmediate:
if sym.kind in {skTemplate, skMacro}:

View File

@@ -1,7 +1,7 @@
discard """
output: "1"
cmd: r"nim c --hints:on $options -d:release $file"
ccodecheck: "'NI volatile state0;'"
ccodecheck: "'NI volatile state;'"
"""
# bug #1539