diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ccgtypes.nim | 41 | ||||
-rw-r--r-- | compiler/cgen.nim | 13 | ||||
-rw-r--r-- | compiler/cgendata.nim | 8 | ||||
-rw-r--r-- | compiler/pragmas.nim | 9 |
4 files changed, 54 insertions, 17 deletions
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index ccf4545ac..8f4db126e 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -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, diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 94a856773..538111663 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -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) diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index 77d031d71..a91858b86 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -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): diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index e750cc390..c88451de6 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -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}: |