mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
MangleProcs following the Itanium spec so they are demangled in the debugger call stack (#23260)
 --------- Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
This commit is contained in:
@@ -55,13 +55,31 @@ proc mangleField(m: BModule; name: PIdent): string =
|
||||
if isKeyword(name):
|
||||
result.add "_0"
|
||||
|
||||
proc mangleProc(m: BModule; s: PSym; makeUnique: bool): string =
|
||||
result = "_Z" # Common prefix in Itanium ABI
|
||||
result.add encodeSym(m, s, makeUnique)
|
||||
if s.typ.len > 1: #we dont care about the return param
|
||||
for i in 1..<s.typ.len:
|
||||
if s.typ[i].isNil: continue
|
||||
result.add encodeType(m, s.typ[i])
|
||||
|
||||
if result in m.g.mangledPrcs:
|
||||
result = mangleProc(m, s, true)
|
||||
else:
|
||||
m.g.mangledPrcs.incl(result)
|
||||
|
||||
proc fillBackendName(m: BModule; s: PSym) =
|
||||
if s.loc.r == "":
|
||||
var result = s.name.s.mangle.rope
|
||||
result.add "__"
|
||||
result.add m.g.graph.ifaces[s.itemId.module].uniqueName
|
||||
result.add "_u"
|
||||
result.addInt s.itemId.item # s.disamb #
|
||||
var result: Rope
|
||||
if s.kind in routineKinds and optCDebug in m.g.config.globalOptions and
|
||||
m.g.config.symbolFiles == disabledSf:
|
||||
result = mangleProc(m, s, false).rope
|
||||
else:
|
||||
result = s.name.s.mangle.rope
|
||||
result.add "__"
|
||||
result.add m.g.graph.ifaces[s.itemId.module].uniqueName
|
||||
result.add "_u"
|
||||
result.addInt s.itemId.item # s.disamb #
|
||||
if m.hcrOn:
|
||||
result.add '_'
|
||||
result.add(idOrSig(s, m.module.name.s.mangle, m.sigConflicts, m.config))
|
||||
|
||||
@@ -13,7 +13,7 @@ import
|
||||
ast, types, msgs, wordrecg,
|
||||
platform, trees, options, cgendata
|
||||
|
||||
import std/[hashes, strutils]
|
||||
import std/[hashes, strutils, formatFloat]
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
@@ -153,3 +153,62 @@ proc ccgIntroducedPtr*(conf: ConfigRef; s: PSym, retType: PType): bool =
|
||||
result = not (pt.kind in {tyVar, tyArray, tyOpenArray, tyVarargs, tyRef, tyPtr, tyPointer} or
|
||||
pt.kind == tySet and mapSetType(conf, pt) == ctArray)
|
||||
|
||||
proc encodeName*(name: string): string =
|
||||
result = mangle(name)
|
||||
result = $result.len & result
|
||||
|
||||
proc makeUnique(m: BModule; s: PSym, name: string = ""): string =
|
||||
result = if name == "": s.name.s else: name
|
||||
result.add "__"
|
||||
result.add m.g.graph.ifaces[s.itemId.module].uniqueName
|
||||
result.add "_u"
|
||||
result.add $s.itemId.item
|
||||
|
||||
proc encodeSym*(m: BModule; s: PSym; makeUnique: bool = false): string =
|
||||
#Module::Type
|
||||
var name = s.name.s
|
||||
if makeUnique:
|
||||
name = makeUnique(m, s, name)
|
||||
"N" & encodeName(s.owner.name.s) & encodeName(name) & "E"
|
||||
|
||||
proc encodeType*(m: BModule; t: PType): string =
|
||||
result = ""
|
||||
var kindName = ($t.kind)[2..^1]
|
||||
kindName[0] = toLower($kindName[0])[0]
|
||||
case t.kind
|
||||
of tyObject, tyEnum, tyDistinct, tyUserTypeClass, tyGenericParam:
|
||||
result = encodeSym(m, t.sym)
|
||||
of tyGenericInst, tyUserTypeClassInst, tyGenericBody:
|
||||
result = encodeName(t[0].sym.name.s)
|
||||
result.add "I"
|
||||
for i in 1..<t.len - 1:
|
||||
result.add encodeType(m, t[i])
|
||||
result.add "E"
|
||||
of tySequence, tyOpenArray, tyArray, tyVarargs, tyTuple, tyProc, tySet, tyTypeDesc,
|
||||
tyPtr, tyRef, tyVar, tyLent, tySink, tyStatic, tyUncheckedArray, tyOr, tyAnd, tyBuiltInTypeClass:
|
||||
result =
|
||||
case t.kind:
|
||||
of tySequence: encodeName("seq")
|
||||
else: encodeName(kindName)
|
||||
result.add "I"
|
||||
for i in 0..<t.len:
|
||||
let s = t[i]
|
||||
if s.isNil: continue
|
||||
result.add encodeType(m, s)
|
||||
result.add "E"
|
||||
of tyRange:
|
||||
var val = "range_"
|
||||
if t.n[0].typ.kind in {tyFloat..tyFloat128}:
|
||||
val.addFloat t.n[0].floatVal
|
||||
val.add "_"
|
||||
val.addFloat t.n[1].floatVal
|
||||
else:
|
||||
val.add $t.n[0].intVal & "_" & $t.n[1].intVal
|
||||
result = encodeName(val)
|
||||
of tyString..tyUInt64, tyPointer, tyBool, tyChar, tyVoid, tyAnything, tyNil, tyEmpty:
|
||||
result = encodeName(kindName)
|
||||
of tyAlias, tyInferred, tyOwned:
|
||||
result = encodeType(m, t.elementType)
|
||||
else:
|
||||
assert false, "encodeType " & $t.kind
|
||||
|
||||
|
||||
@@ -137,6 +137,7 @@ type
|
||||
# unconditionally...
|
||||
# nimtvDeps is VERY hard to cache because it's
|
||||
# not a list of IDs nor can it be made to be one.
|
||||
mangledPrcs*: HashSet[string]
|
||||
|
||||
TCGen = object of PPassContext # represents a C source file
|
||||
s*: TCFileSections # sections of the C file
|
||||
|
||||
192
tests/codegen/titaniummangle.nim
Normal file
192
tests/codegen/titaniummangle.nim
Normal file
@@ -0,0 +1,192 @@
|
||||
discard """
|
||||
targets: "c cpp"
|
||||
matrix: "--debugger:native"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE6stringN14titaniummangle3FooE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE3int7varargsI6stringE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncEN14titaniummangle3BooE'"
|
||||
ccodecheck: "'_ZN8testFunc8testFuncE8typeDescIN14titaniummangle17EnumAnotherSampleEE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE3ptrI14uncheckedArrayI3intEE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE3setIN14titaniummangle10EnumSampleEE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE4procI6string6stringE'"
|
||||
ccodecheck: "'_ZN8testFunc8testFuncE3intN10Comparable10ComparableE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE3int3int'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncEN14titaniummangle10EnumSampleE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncEN14titaniummangle17EnumAnotherSampleE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE3int3int'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncEN14titaniummangle10EnumSampleE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncEN14titaniummangle17EnumAnotherSampleE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE5tupleI3int3intE7cstring'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE5tupleI5float5floatE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE3ptrI3intE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE3ptrIN14titaniummangle3FooEE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE3ptrI3ptrI3intEE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE3refIN14titaniummangle3FooEE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE3varIN14titaniummangle3FooEE5int325int323refIN14titaniummangle3FooEE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE3varI3intE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE9openArrayI6stringE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE5arrayI7range013intE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE9ContainerI3intE'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE10Container2I5int325int32E'"
|
||||
ccodecheck: "'_ZN14titaniummangle8testFuncE9ContainerI10Container2I5int325int32EE'"
|
||||
"""
|
||||
|
||||
#When debugging this notice that if one check fails, it can be due to any of the above.
|
||||
|
||||
type
|
||||
Comparable = concept x, y
|
||||
(x < y) is bool
|
||||
|
||||
type
|
||||
Foo = object
|
||||
a: int32
|
||||
b: int32
|
||||
|
||||
FooTuple = tuple
|
||||
a: int
|
||||
b: int
|
||||
Container[T] = object
|
||||
data: T
|
||||
Container2[T, T2] = object
|
||||
data: T
|
||||
data2: T2
|
||||
|
||||
Boo = distinct Foo
|
||||
|
||||
Coo = Foo
|
||||
|
||||
Doo = Boo | Foo
|
||||
|
||||
TestProc = proc(a:string): string
|
||||
|
||||
type EnumSample = enum
|
||||
a, b, c
|
||||
|
||||
type EnumAnotherSample = enum
|
||||
a, b, c
|
||||
|
||||
proc testFunc(a: set[EnumSample]) =
|
||||
echo $a
|
||||
|
||||
proc testFunc(a: typedesc) =
|
||||
echo $a
|
||||
|
||||
proc testFunc(a: ptr Foo) =
|
||||
echo repr a
|
||||
|
||||
proc testFunc(s: string, a: Coo) =
|
||||
echo repr a
|
||||
|
||||
proc testFunc(s: int, a: Comparable) =
|
||||
echo repr a
|
||||
|
||||
proc testFunc(a: TestProc) =
|
||||
let b = ""
|
||||
echo repr a("")
|
||||
|
||||
proc testFunc(a: ref Foo) =
|
||||
echo repr a
|
||||
|
||||
proc testFunc(b: Boo) =
|
||||
echo repr b
|
||||
|
||||
proc testFunc(a: ptr UncheckedArray[int]) =
|
||||
echo repr a
|
||||
|
||||
proc testFunc(a: ptr int) =
|
||||
echo repr a
|
||||
|
||||
proc testFunc(a: ptr ptr int) =
|
||||
echo repr a
|
||||
|
||||
proc testFunc(e: FooTuple, str: cstring) =
|
||||
echo e
|
||||
|
||||
proc testFunc(e: (float, float)) =
|
||||
echo e
|
||||
|
||||
proc testFunc(e: EnumSample) =
|
||||
echo e
|
||||
|
||||
proc testFunc(e: var int) =
|
||||
echo e
|
||||
|
||||
proc testFunc(e: var Foo, a, b: int32, refFoo: ref Foo) =
|
||||
echo e
|
||||
|
||||
proc testFunc(xs: Container[int]) =
|
||||
let a = 2
|
||||
echo xs
|
||||
|
||||
proc testFunc(xs: Container2[int32, int32]) =
|
||||
let a = 2
|
||||
echo xs
|
||||
|
||||
proc testFunc(xs: Container[Container2[int32, int32]]) =
|
||||
let a = 2
|
||||
echo xs
|
||||
|
||||
proc testFunc(xs: seq[int]) =
|
||||
let a = 2
|
||||
echo xs
|
||||
|
||||
proc testFunc(xs: openArray[string]) =
|
||||
let a = 2
|
||||
echo xs
|
||||
|
||||
proc testFunc(xs: array[2, int]) =
|
||||
let a = 2
|
||||
echo xs
|
||||
|
||||
proc testFunc(e: EnumAnotherSample) =
|
||||
echo e
|
||||
|
||||
proc testFunc(a, b: int) =
|
||||
echo "hola"
|
||||
discard
|
||||
|
||||
proc testFunc(a: int, xs: varargs[string]) =
|
||||
let a = 10
|
||||
for x in xs:
|
||||
echo x
|
||||
|
||||
proc testFunc() =
|
||||
var a = 2
|
||||
var aPtr = a.addr
|
||||
var foo = Foo()
|
||||
let refFoo : ref Foo = new(Foo)
|
||||
let b = Foo().Boo()
|
||||
let d: Doo = Foo()
|
||||
testFunc("", Coo())
|
||||
testFunc(1, )
|
||||
testFunc(b)
|
||||
testFunc(EnumAnotherSample)
|
||||
var t = [1, 2]
|
||||
let uArr = cast[ptr UncheckedArray[int]](t.addr)
|
||||
testFunc(uArr)
|
||||
testFunc({})
|
||||
testFunc(proc(s:string): string = "test")
|
||||
testFunc(20, a.int32)
|
||||
testFunc(20, 2)
|
||||
testFunc(EnumSample.c)
|
||||
testFunc(EnumAnotherSample.c)
|
||||
testFunc((2, 1), "adios")
|
||||
testFunc((22.1, 1.2))
|
||||
testFunc(a.addr)
|
||||
testFunc(foo.addr)
|
||||
testFunc(aPtr.addr)
|
||||
testFunc(refFoo)
|
||||
testFunc(foo, 2, 1, refFoo)
|
||||
testFunc(a)
|
||||
testFunc(@[2, 1, 2])
|
||||
testFunc(@["hola"])
|
||||
testFunc(2, "hola", "adios")
|
||||
let arr: array[2, int] = [2, 1]
|
||||
testFunc(arr)
|
||||
testFunc(Container[int](data: 10))
|
||||
let c2 = Container2[int32, int32](data: 10, data2: 20)
|
||||
testFunc(c2)
|
||||
testFunc(Container[Container2[int32, int32]](data: c2))
|
||||
|
||||
|
||||
testFunc()
|
||||
Reference in New Issue
Block a user