use anon structs and unions for a much better debug experience (#10055)
This commit is contained in:
parent
68ec42cec7
commit
2fd522cf58
2 changed files with 29 additions and 39 deletions
|
|
@ -436,30 +436,25 @@ proc mangleRecFieldName(m: BModule; field: PSym): Rope =
|
||||||
if result == nil: internalError(m.config, field.info, "mangleRecFieldName")
|
if result == nil: internalError(m.config, field.info, "mangleRecFieldName")
|
||||||
|
|
||||||
proc genRecordFieldsAux(m: BModule, n: PNode,
|
proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||||
accessExpr: Rope, rectype: PType,
|
rectype: PType,
|
||||||
check: var IntSet): Rope =
|
check: var IntSet): Rope =
|
||||||
result = nil
|
result = nil
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
add(result, genRecordFieldsAux(m, n.sons[i], accessExpr, rectype, check))
|
add(result, genRecordFieldsAux(m, n.sons[i], rectype, check))
|
||||||
of nkRecCase:
|
of nkRecCase:
|
||||||
if n.sons[0].kind != nkSym: internalError(m.config, n.info, "genRecordFieldsAux")
|
if n.sons[0].kind != nkSym: internalError(m.config, n.info, "genRecordFieldsAux")
|
||||||
add(result, genRecordFieldsAux(m, n.sons[0], accessExpr, rectype, check))
|
add(result, genRecordFieldsAux(m, n.sons[0], rectype, check))
|
||||||
# prefix mangled name with "_U" to avoid clashes with other field names,
|
# prefix mangled name with "_U" to avoid clashes with other field names,
|
||||||
# since identifiers are not allowed to start with '_'
|
# since identifiers are not allowed to start with '_'
|
||||||
let uname = rope("_U" & mangle(n.sons[0].sym.name.s))
|
|
||||||
let ae = if accessExpr != nil: "$1.$2" % [accessExpr, uname]
|
|
||||||
else: uname
|
|
||||||
var unionBody: Rope = nil
|
var unionBody: Rope = nil
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
case n.sons[i].kind
|
case n.sons[i].kind
|
||||||
of nkOfBranch, nkElse:
|
of nkOfBranch, nkElse:
|
||||||
let k = lastSon(n.sons[i])
|
let k = lastSon(n.sons[i])
|
||||||
if k.kind != nkSym:
|
if k.kind != nkSym:
|
||||||
let sname = "S" & rope(i)
|
let a = genRecordFieldsAux(m, k, rectype, check)
|
||||||
let a = genRecordFieldsAux(m, k, "$1.$2" % [ae, sname], rectype,
|
|
||||||
check)
|
|
||||||
if a != nil:
|
if a != nil:
|
||||||
if tfPacked notin rectype.flags:
|
if tfPacked notin rectype.flags:
|
||||||
add(unionBody, "struct {")
|
add(unionBody, "struct {")
|
||||||
|
|
@ -469,22 +464,20 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||||
else:
|
else:
|
||||||
addf(unionBody, "#pragma pack(push, 1)$nstruct{", [])
|
addf(unionBody, "#pragma pack(push, 1)$nstruct{", [])
|
||||||
add(unionBody, a)
|
add(unionBody, a)
|
||||||
addf(unionBody, "} $1;$n", [sname])
|
addf(unionBody, "};$n", [])
|
||||||
if tfPacked in rectype.flags and hasAttribute notin CC[m.config.cCompiler].props:
|
if tfPacked in rectype.flags and hasAttribute notin CC[m.config.cCompiler].props:
|
||||||
addf(unionBody, "#pragma pack(pop)$n", [])
|
addf(unionBody, "#pragma pack(pop)$n", [])
|
||||||
else:
|
else:
|
||||||
add(unionBody, genRecordFieldsAux(m, k, ae, rectype, check))
|
add(unionBody, genRecordFieldsAux(m, k, rectype, check))
|
||||||
else: internalError(m.config, "genRecordFieldsAux(record case branch)")
|
else: internalError(m.config, "genRecordFieldsAux(record case branch)")
|
||||||
if unionBody != nil:
|
if unionBody != nil:
|
||||||
addf(result, "union{$n$1} $2;$n", [unionBody, uname])
|
addf(result, "union{$n$1};$n", [unionBody])
|
||||||
of nkSym:
|
of nkSym:
|
||||||
let field = n.sym
|
let field = n.sym
|
||||||
if field.typ.kind == tyVoid: return
|
if field.typ.kind == tyVoid: return
|
||||||
#assert(field.ast == nil)
|
#assert(field.ast == nil)
|
||||||
let sname = mangleRecFieldName(m, field)
|
let sname = mangleRecFieldName(m, field)
|
||||||
let ae = if accessExpr != nil: "$1.$2" % [accessExpr, sname]
|
fillLoc(field.loc, locField, n, sname, OnUnknown)
|
||||||
else: sname
|
|
||||||
fillLoc(field.loc, locField, n, ae, OnUnknown)
|
|
||||||
# for importcpp'ed objects, we only need to set field.loc, but don't
|
# for importcpp'ed objects, we only need to set field.loc, but don't
|
||||||
# have to recurse via 'getTypeDescAux'. And not doing so prevents problems
|
# have to recurse via 'getTypeDescAux'. And not doing so prevents problems
|
||||||
# with heavily templatized C++ code:
|
# with heavily templatized C++ code:
|
||||||
|
|
@ -505,7 +498,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||||
else: internalError(m.config, n.info, "genRecordFieldsAux()")
|
else: internalError(m.config, n.info, "genRecordFieldsAux()")
|
||||||
|
|
||||||
proc getRecordFields(m: BModule, typ: PType, check: var IntSet): Rope =
|
proc getRecordFields(m: BModule, typ: PType, check: var IntSet): Rope =
|
||||||
result = genRecordFieldsAux(m, typ.n, nil, typ, check)
|
result = genRecordFieldsAux(m, typ.n, typ, check)
|
||||||
|
|
||||||
proc fillObjectFields*(m: BModule; typ: PType) =
|
proc fillObjectFields*(m: BModule; typ: PType) =
|
||||||
# sometimes generic objects are not consistently merged. We patch over
|
# sometimes generic objects are not consistently merged. We patch over
|
||||||
|
|
|
||||||
|
|
@ -36,27 +36,24 @@ macro testSizeAlignOf(args: varargs[untyped]): untyped =
|
||||||
if nim_size != c_size or nim_align != c_align:
|
if nim_size != c_size or nim_align != c_align:
|
||||||
var msg = strAlign(`arg`.type.name & ": ")
|
var msg = strAlign(`arg`.type.name & ": ")
|
||||||
if nim_size != c_size:
|
if nim_size != c_size:
|
||||||
msg.add " size(got, expected): " & $nim_size & " != " & $c_size
|
msg.add " size(got, expected): " & $nim_size & " != " & $c_size
|
||||||
if nim_align != c_align:
|
if nim_align != c_align:
|
||||||
msg.add " align(get, expected): " & $nim_align & " != " & $c_align
|
msg.add " align(get, expected): " & $nim_align & " != " & $c_align
|
||||||
echo msg
|
echo msg
|
||||||
failed = true
|
failed = true
|
||||||
|
|
||||||
|
|
||||||
macro testOffsetOf(a,b1,b2: untyped): untyped =
|
macro testOffsetOf(a, b: untyped): untyped =
|
||||||
let typeName = newLit(a.repr)
|
let typeName = newLit(a.repr)
|
||||||
let member = newLit(b2.repr)
|
let member = newLit(b.repr)
|
||||||
result = quote do:
|
result = quote do:
|
||||||
let
|
let
|
||||||
c_offset = c_offsetof(`a`,`b1`)
|
c_offset = c_offsetof(`a`,`b`)
|
||||||
nim_offset = offsetof(`a`,`b2`)
|
nim_offset = offsetof(`a`,`b`)
|
||||||
if c_offset != nim_offset:
|
if c_offset != nim_offset:
|
||||||
echo `typeName`, ".", `member`, " offsetError, C: ", c_offset, " nim: ", nim_offset
|
echo `typeName`, ".", `member`, " offsetError, C: ", c_offset, " nim: ", nim_offset
|
||||||
failed = true
|
failed = true
|
||||||
|
|
||||||
template testOffsetOf(a,b: untyped): untyped =
|
|
||||||
testOffsetOf(a,b,b)
|
|
||||||
|
|
||||||
proc strAlign(arg: string): string =
|
proc strAlign(arg: string): string =
|
||||||
const minLen = 22
|
const minLen = 22
|
||||||
result = arg
|
result = arg
|
||||||
|
|
@ -337,16 +334,16 @@ testinstance:
|
||||||
testOffsetOf(AlignAtEnd, b)
|
testOffsetOf(AlignAtEnd, b)
|
||||||
testOffsetOf(AlignAtEnd, c)
|
testOffsetOf(AlignAtEnd, c)
|
||||||
|
|
||||||
testOffsetOf(SimpleBranch, "_Ukind", a)
|
testOffsetOf(SimpleBranch, a)
|
||||||
testOffsetOf(SimpleBranch, "_Ukind", b)
|
testOffsetOf(SimpleBranch, b)
|
||||||
testOffsetOf(SimpleBranch, "_Ukind", c)
|
testOffsetOf(SimpleBranch, c)
|
||||||
|
|
||||||
testOffsetOf(PaddingBeforeBranchA, cause)
|
testOffsetOf(PaddingBeforeBranchA, cause)
|
||||||
testOffsetOf(PaddingBeforeBranchA, "_Ukind", a)
|
testOffsetOf(PaddingBeforeBranchA, a)
|
||||||
testOffsetOf(PaddingBeforeBranchB, cause)
|
testOffsetOf(PaddingBeforeBranchB, cause)
|
||||||
testOffsetOf(PaddingBeforeBranchB, "_Ukind", a)
|
testOffsetOf(PaddingBeforeBranchB, a)
|
||||||
|
|
||||||
testOffsetOf(PaddingAfterBranch, "_Ukind", a)
|
testOffsetOf(PaddingAfterBranch, a)
|
||||||
testOffsetOf(PaddingAfterBranch, cause)
|
testOffsetOf(PaddingAfterBranch, cause)
|
||||||
|
|
||||||
testOffsetOf(Foobar, c)
|
testOffsetOf(Foobar, c)
|
||||||
|
|
@ -367,15 +364,15 @@ testinstance:
|
||||||
testOffsetOf(EnumObjectB, d)
|
testOffsetOf(EnumObjectB, d)
|
||||||
|
|
||||||
testOffsetOf(RecursiveStuff, kind)
|
testOffsetOf(RecursiveStuff, kind)
|
||||||
testOffsetOf(RecursiveStuff, "_Ukind.S1.a", a)
|
testOffsetOf(RecursiveStuff, a)
|
||||||
testOffsetOf(RecursiveStuff, "_Ukind.S2.b", b)
|
testOffsetOf(RecursiveStuff, b)
|
||||||
testOffsetOf(RecursiveStuff, "_Ukind.S3.kind2", kind2)
|
testOffsetOf(RecursiveStuff, kind2)
|
||||||
testOffsetOf(RecursiveStuff, "_Ukind.S3._Ukind2.S1.ca1", ca1)
|
testOffsetOf(RecursiveStuff, ca1)
|
||||||
testOffsetOf(RecursiveStuff, "_Ukind.S3._Ukind2.S1.ca2", ca2)
|
testOffsetOf(RecursiveStuff, ca2)
|
||||||
testOffsetOf(RecursiveStuff, "_Ukind.S3._Ukind2.S2.cb", cb)
|
testOffsetOf(RecursiveStuff, cb)
|
||||||
testOffsetOf(RecursiveStuff, "_Ukind.S3._Ukind2.S3.cc", cc)
|
testOffsetOf(RecursiveStuff, cc)
|
||||||
testOffsetOf(RecursiveStuff, "_Ukind.S3.d1", d1)
|
testOffsetOf(RecursiveStuff, d1)
|
||||||
testOffsetOf(RecursiveStuff, "_Ukind.S3.d2", d2)
|
testOffsetOf(RecursiveStuff, d2)
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue