diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2017-02-03 09:49:36 +0100 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2017-02-03 09:49:36 +0100 |
commit | 848676cec6ba75e9bd0f8f590c6e47f6be7e696e (patch) | |
tree | 542fcc65dba46c46666ae9f2089da235958372d1 /compiler | |
parent | 04c4d3d77f86086efa2447c0c9b47ba84342d245 (diff) | |
download | Nim-848676cec6ba75e9bd0f8f590c6e47f6be7e696e.tar.gz |
name mangling bugfixes; ndi file generation for debugger support
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ccgstmts.nim | 2 | ||||
-rw-r--r-- | compiler/ccgtypes.nim | 73 | ||||
-rw-r--r-- | compiler/ccgutils.nim | 12 | ||||
-rw-r--r-- | compiler/cgen.nim | 6 | ||||
-rw-r--r-- | compiler/cgendata.nim | 3 | ||||
-rw-r--r-- | compiler/ndi.nim | 40 |
6 files changed, 71 insertions, 65 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 09b455ec0..45d675f64 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -64,7 +64,7 @@ proc genVarTuple(p: BProc, n: PNode) = field.r = "$1.Field$2" % [rdLoc(tup), rope(i)] else: if t.n.sons[i].kind != nkSym: internalError(n.info, "genVarTuple") - field.r = "$1.$2" % [rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)] + field.r = "$1.$2" % [rdLoc(tup), mangleRecFieldName(p.module, t.n.sons[i].sym, t)] putLocIntoDest(p, v.loc, field) proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false) diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index ba505facb..e30fe5598 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -22,12 +22,10 @@ proc isKeyword(w: PIdent): bool = ord(wInline): return true else: return false -proc mangleField(name: PIdent): string = +proc mangleField(m: BModule; name: PIdent): string = result = mangle(name.s) - if isKeyword(name): - result[0] = result[0].toUpperAscii - # Mangling makes everything lowercase, - # but some identifiers are C keywords + if isKeyword(name) or m.g.config.cppDefines.contains(result): + result.add "_0" when false: proc hashOwner(s: PSym): SigHash = @@ -67,54 +65,10 @@ proc idOrSig(m: BModule; s: PSym): Rope = proc mangleName(m: BModule; s: PSym): Rope = result = s.loc.r if result == nil: - let keepOrigName = s.kind in skLocalVars - {skForVar} and - {sfFromGeneric, sfGlobal, sfShadowed, sfGenSym} * s.flags == {} and - not isKeyword(s.name) - # Even with all these inefficient checks, the bootstrap - # time is actually improved. This is probably because so many - # rope concatenations are now eliminated. - # - # sfFromGeneric is needed in order to avoid multiple - # definitions of certain variables generated in transf with - # names such as: - # `r`, `res` - # I need to study where these come from. - # - # about sfShadowed: - # consider the following Nim code: - # var x = 10 - # block: - # var x = something(x) - # The generated C code will be: - # NI x; - # x = 10; - # { - # NI x; - # x = something(x); // Oops, x is already shadowed here - # } - # Right now, we work-around by not keeping the original name - # of the shadowed variable, but we can do better - we can - # create an alternative reference to it in the outer scope and - # use that in the inner scope. - # - # about isCKeyword: - # Nim variable names can be C keywords. - # We need to avoid such names in the generated code. - # - # about sfGlobal: - # This seems to be harder - a top level extern variable from - # another modules can have the same name as a local one. - # Maybe we should just implement sfShadowed for them too. - # - # about skForVar: - # These are not properly scoped now - we need to add blocks - # around for loops in transf result = s.name.s.mangle.rope - if keepOrigName: - result.add "0" - else: - add(result, m.idOrSig(s)) + add(result, m.idOrSig(s)) s.loc.r = result + writeMangledName(m.ndi, s) proc mangleParamName(m: BModule; s: PSym): Rope = ## we cannot use 'sigConflicts' here since we have a BModule, not a BProc. @@ -122,10 +76,12 @@ proc mangleParamName(m: BModule; s: PSym): Rope = ## 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" + var res = s.name.s.mangle + if isKeyword(s.name) or m.g.config.cppDefines.contains(res): + res.add "_0" + result = res.rope s.loc.r = result + writeMangledName(m.ndi, s) proc mangleLocalName(p: BProc; s: PSym): Rope = assert s.kind in skLocalVars+{skTemp} @@ -139,10 +95,11 @@ proc mangleLocalName(p: BProc; s: PSym): 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): + elif counter != 0 or isKeyword(s.name) or p.module.g.config.cppDefines.contains(key): result.add "_" & rope(counter+1) p.sigConflicts.inc(key) s.loc.r = result + if s.kind != skTemp: writeMangledName(p.module.ndi, s) proc scopeMangledParam(p: BProc; param: PSym) = ## parameter generation only takes BModule, not a BProc, so we have to @@ -472,12 +429,12 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope, else: add(params, ")") params = "(" & params -proc mangleRecFieldName(field: PSym, rectype: PType): Rope = +proc mangleRecFieldName(m: BModule; field: PSym, rectype: PType): Rope = if (rectype.sym != nil) and ({sfImportc, sfExportc} * rectype.sym.flags != {}): result = field.loc.r else: - result = rope(mangleField(field.name)) + result = rope(mangleField(m, field.name)) if result == nil: internalError(field.info, "mangleRecFieldName") proc genRecordFieldsAux(m: BModule, n: PNode, @@ -516,7 +473,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode, let field = n.sym if field.typ.kind == tyVoid: return #assert(field.ast == nil) - let sname = mangleRecFieldName(field, rectype) + let sname = mangleRecFieldName(m, field, rectype) let ae = if accessExpr != nil: "$1.$2" % [accessExpr, sname] else: sname fillLoc(field.loc, locField, field.typ, ae, OnUnknown) diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim index 0985759b9..d42f0438f 100644 --- a/compiler/ccgutils.nim +++ b/compiler/ccgutils.nim @@ -164,9 +164,6 @@ proc makeSingleLineCString*(s: string): string = result.add('\"') proc mangle*(name: string): string = - ## Lowercases the given name and manges any non-alphanumeric characters - ## so they are represented as `HEX____`. If the name starts with a number, - ## `N` is prepended result = newStringOfCap(name.len) var start = 0 if name[0] in Digits: @@ -179,8 +176,15 @@ proc mangle*(name: string): string = for i in start..(name.len-1): let c = name[i] case c - of 'a'..'z', '0'..'9', 'A'..'Z', '_': + of 'a'..'z', '0'..'9', 'A'..'Z': add(result, c) + of '_': + # we generate names like 'foo_9' for scope disambiguations and so + # disallow this here: + if i < name.len-1 and name[i] in Digits: + discard + else: + add(result, c) of '$': special "dollar" of '%': special "percent" of '&': special "amp" diff --git a/compiler/cgen.nim b/compiler/cgen.nim index ae735d30b..62ed9ad6e 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, sets + lowerings, semparallel, tables, sets, ndi import strutils except `%` # collides with ropes.`%` @@ -1152,6 +1152,9 @@ proc rawNewModule(g: BModuleList; module: PSym, filename: string): BModule = incl result.flags, preventStackTrace excl(result.preInitProc.options, optStackTrace) excl(result.postInitProc.options, optStackTrace) + let ndiName = if optCDebug in gGlobalOptions: changeFileExt(completeCFilePath(filename), "ndi") + else: "" + open(result.ndi, ndiName) proc nullify[T](arr: var T) = for i in low(arr)..high(arr): @@ -1343,6 +1346,7 @@ proc writeModule(m: BModule, pending: bool) = var cf = Cfile(cname: cfile, obj: completeCFilePath(toObjFile(cfile)), flags: {}) if not existsFile(cf.obj): cf.flags = {CfileFlag.Cached} addFileToCompile(cf) + close(m.ndi) proc updateCachedModule(m: BModule) = let cfile = getCFile(m) diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index a91858b86..565399ead 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -11,7 +11,7 @@ import ast, astalgo, ropes, passes, options, intsets, lists, platform, sighashes, - tables + tables, ndi from msgs import TLineInfo @@ -146,6 +146,7 @@ type injectStmt*: Rope sigConflicts*: CountTable[SigHash] g*: BModuleList + ndi*: NdiFile proc s*(p: BProc, s: TCProcSection): var Rope {.inline.} = # section in the current block diff --git a/compiler/ndi.nim b/compiler/ndi.nim new file mode 100644 index 000000000..a7ca02193 --- /dev/null +++ b/compiler/ndi.nim @@ -0,0 +1,40 @@ +# +# +# The Nim Compiler +# (c) Copyright 2017 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This module implements the generation of ``.ndi`` files for better debugging +## support of Nim code. "ndi" stands for "Nim debug info". + +import ast, msgs, ropes + +type + NdiFile* = object + enabled: bool + f: File + buf: string + +proc doWrite(f: var NdiFile; s: PSym) = + f.buf.setLen 0 + f.buf.add s.info.line.int + f.buf.add "\t" + f.buf.add s.info.col.int + f.f.write(s.name.s, "\t") + f.f.writeRope(s.loc.r) + f.f.writeLine("\t", s.info.toFullPath, "\t", f.buf) + +template writeMangledName*(f: NdiFile; s: PSym) = + if f.enabled: doWrite(f, s) + +proc open*(f: var NdiFile; filename: string) = + f.enabled = filename.len > 0 + if f.enabled: + f.f = open(filename, fmWrite, 8000) + f.buf = newStringOfCap(20) + +proc close*(f: var NdiFile) = + if f.enabled: close(f.f) |