allow packed union (#14868)
Co-authored-by: Arne Döring <arne.doering@gmx.net>
This commit is contained in:
parent
1edb9a6178
commit
1440e70c62
2 changed files with 17 additions and 9 deletions
|
|
@ -164,7 +164,7 @@ proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, packed: bool, a
|
||||||
accum.maxAlign = szUnknownSize
|
accum.maxAlign = szUnknownSize
|
||||||
accum.offset = szUnknownSize
|
accum.offset = szUnknownSize
|
||||||
|
|
||||||
proc computeUnionObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode; accum: var OffsetAccum) =
|
proc computeUnionObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode; packed: bool; accum: var OffsetAccum) =
|
||||||
## ``accum.offset`` will the offset from the larget member of the union.
|
## ``accum.offset`` will the offset from the larget member of the union.
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkRecCase:
|
of nkRecCase:
|
||||||
|
|
@ -175,7 +175,7 @@ proc computeUnionObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode; accum: var
|
||||||
let accumRoot = accum # copy, because each branch should start af the same offset
|
let accumRoot = accum # copy, because each branch should start af the same offset
|
||||||
for i, child in n.sons:
|
for i, child in n.sons:
|
||||||
var branchAccum = accumRoot
|
var branchAccum = accumRoot
|
||||||
computeUnionObjectOffsetsFoldFunction(conf, child, branchAccum)
|
computeUnionObjectOffsetsFoldFunction(conf, child, packed, branchAccum)
|
||||||
accum.mergeBranch(branchAccum)
|
accum.mergeBranch(branchAccum)
|
||||||
of nkSym:
|
of nkSym:
|
||||||
var size = szUnknownSize
|
var size = szUnknownSize
|
||||||
|
|
@ -183,7 +183,7 @@ proc computeUnionObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode; accum: var
|
||||||
if n.sym.bitsize == 0: # 0 represents bitsize not set
|
if n.sym.bitsize == 0: # 0 represents bitsize not set
|
||||||
computeSizeAlign(conf, n.sym.typ)
|
computeSizeAlign(conf, n.sym.typ)
|
||||||
size = n.sym.typ.size.int
|
size = n.sym.typ.size.int
|
||||||
align = n.sym.typ.align.int
|
align = if packed: 1 else: n.sym.typ.align.int
|
||||||
accum.align(align)
|
accum.align(align)
|
||||||
if n.sym.alignment > 0:
|
if n.sym.alignment > 0:
|
||||||
accum.align(n.sym.alignment)
|
accum.align(n.sym.alignment)
|
||||||
|
|
@ -365,16 +365,14 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
|
||||||
else:
|
else:
|
||||||
OffsetAccum(maxAlign: 1)
|
OffsetAccum(maxAlign: 1)
|
||||||
if tfUnion in typ.flags:
|
if tfUnion in typ.flags:
|
||||||
if tfPacked in typ.flags:
|
if accum.offset != 0:
|
||||||
let info = if typ.sym != nil: typ.sym.info else: unknownLineInfo
|
|
||||||
localError(conf, info, "union type may not be packed.")
|
|
||||||
accum = OffsetAccum(offset: szUnknownSize, maxAlign: szUnknownSize)
|
|
||||||
elif accum.offset != 0:
|
|
||||||
let info = if typ.sym != nil: typ.sym.info else: unknownLineInfo
|
let info = if typ.sym != nil: typ.sym.info else: unknownLineInfo
|
||||||
localError(conf, info, "union type may not have an object header")
|
localError(conf, info, "union type may not have an object header")
|
||||||
accum = OffsetAccum(offset: szUnknownSize, maxAlign: szUnknownSize)
|
accum = OffsetAccum(offset: szUnknownSize, maxAlign: szUnknownSize)
|
||||||
|
elif tfPacked in typ.flags:
|
||||||
|
computeUnionObjectOffsetsFoldFunction(conf, typ.n, true, accum)
|
||||||
else:
|
else:
|
||||||
computeUnionObjectOffsetsFoldFunction(conf, typ.n, accum)
|
computeUnionObjectOffsetsFoldFunction(conf, typ.n, false, accum)
|
||||||
elif tfPacked in typ.flags:
|
elif tfPacked in typ.flags:
|
||||||
accum.maxAlign = 1
|
accum.maxAlign = 1
|
||||||
computeObjectOffsetsFoldFunction(conf, typ.n, true, accum)
|
computeObjectOffsetsFoldFunction(conf, typ.n, true, accum)
|
||||||
|
|
|
||||||
|
|
@ -694,3 +694,13 @@ type
|
||||||
|
|
||||||
doAssert sizeof(O0) == 1
|
doAssert sizeof(O0) == 1
|
||||||
doAssert sizeof(T0) == 1
|
doAssert sizeof(T0) == 1
|
||||||
|
|
||||||
|
|
||||||
|
type
|
||||||
|
# this thing may not have padding bytes at the end
|
||||||
|
PackedUnion* {.union, packed.} = object
|
||||||
|
a*: array[11, byte]
|
||||||
|
b*: int64
|
||||||
|
|
||||||
|
doAssert sizeof(PackedUnion) == 11
|
||||||
|
doAssert alignof(PackedUnion) == 1
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue