summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ccgtypes.nim41
-rw-r--r--compiler/cgen.nim13
-rw-r--r--compiler/cgendata.nim8
-rw-r--r--compiler/pragmas.nim9
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}: