sizealign of union type (#10780)
* sizealign of union type * add error message for packed union
This commit is contained in:
parent
ebe0473511
commit
1d9b88f25d
2 changed files with 62 additions and 4 deletions
|
|
@ -145,6 +145,9 @@ proc computePackedObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOf
|
|||
var maxChildOffset: BiggestInt = kindUnionOffset
|
||||
for i in 1 ..< sonsLen(n):
|
||||
let offset = computePackedObjectOffsetsFoldFunction(conf, n.sons[i].lastSon, kindUnionOffset, debug)
|
||||
if offset < 0:
|
||||
result = offset
|
||||
break
|
||||
maxChildOffset = max(maxChildOffset, offset)
|
||||
result = maxChildOffset
|
||||
of nkRecList:
|
||||
|
|
@ -168,7 +171,47 @@ proc computePackedObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOf
|
|||
else:
|
||||
result = szUnknownSize
|
||||
|
||||
# TODO this one needs an alignment map of the individual types
|
||||
proc computeUnionObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, debug: bool): tuple[offset, align: BiggestInt] =
|
||||
## ``result`` is the offset from the larget member of the union.
|
||||
case n.kind
|
||||
of nkRecCase:
|
||||
result.offset = szUnknownSize
|
||||
result.align = szUnknownSize
|
||||
localError(conf, n.info, "Illegal use of ``case`` in union type.")
|
||||
#internalError(conf, "Illegal use of ``case`` in union type.")
|
||||
of nkRecList:
|
||||
var maxChildOffset: BiggestInt = 0
|
||||
for i, child in n.sons:
|
||||
let (offset, align) = computeUnionObjectOffsetsFoldFunction(conf, child, debug)
|
||||
if offset == szIllegalRecursion or align == szIllegalRecursion:
|
||||
result.offset = szIllegalRecursion
|
||||
result.align = szIllegalRecursion
|
||||
elif offset == szUnknownSize or align == szUnknownSize:
|
||||
result.offset = szUnknownSize
|
||||
result.align = szUnknownSize
|
||||
else:
|
||||
assert offset != szUncomputedSize
|
||||
assert align != szUncomputedSize
|
||||
result.offset = max(result.offset, offset)
|
||||
result.align = max(result.align, align)
|
||||
of nkSym:
|
||||
var size = szUnknownSize
|
||||
var align = szUnknownSize
|
||||
if n.sym.bitsize == 0: # 0 represents bitsize not set
|
||||
computeSizeAlign(conf, n.sym.typ)
|
||||
size = n.sym.typ.size.int
|
||||
align = n.sym.typ.align.int
|
||||
|
||||
result.align = align
|
||||
if size == szUnknownSize:
|
||||
n.sym.offset = szUnknownSize
|
||||
result.offset = szUnknownSize
|
||||
else:
|
||||
n.sym.offset = 0
|
||||
result.offset = n.sym.typ.size
|
||||
else:
|
||||
result.offset = szUnknownSize
|
||||
result.align = szUnknownSize
|
||||
|
||||
proc computeSizeAlign(conf: ConfigRef; typ: PType) =
|
||||
## computes and sets ``size`` and ``align`` members of ``typ``
|
||||
|
|
@ -343,7 +386,14 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
|
|||
headerSize = 0
|
||||
headerAlign = 1
|
||||
let (offset, align) =
|
||||
if tfPacked in typ.flags:
|
||||
if tfUnion in typ.flags:
|
||||
if tfPacked in typ.flags:
|
||||
let info = if typ.sym != nil: typ.sym.info else: unknownLineInfo()
|
||||
localError(conf, info, "type may not be packed and union at the same time.")
|
||||
(BiggestInt(szUnknownSize), BiggestInt(szUnknownSize))
|
||||
else:
|
||||
computeUnionObjectOffsetsFoldFunction(conf, typ.n, false)
|
||||
elif tfPacked in typ.flags:
|
||||
(computePackedObjectOffsetsFoldFunction(conf, typ.n, headerSize, false), BiggestInt(1))
|
||||
else:
|
||||
computeObjectOffsetsFoldFunction(conf, typ.n, headerSize)
|
||||
|
|
|
|||
|
|
@ -401,7 +401,7 @@ assert sizeof(Bar) == 12
|
|||
type
|
||||
A = int8 # change to int16 and get sizeof(C)==6
|
||||
B = int16
|
||||
C = object {.packed.}
|
||||
C {.packed.} = object
|
||||
d {.bitsize: 1.}: A
|
||||
e {.bitsize: 7.}: A
|
||||
f {.bitsize: 16.}: B
|
||||
|
|
@ -410,7 +410,7 @@ assert sizeof(C) == 3
|
|||
|
||||
|
||||
type
|
||||
MixedBitsize = object {.packed.}
|
||||
MixedBitsize {.packed.} = object
|
||||
a: uint32
|
||||
b {.bitsize: 8.}: uint8
|
||||
c {.bitsize: 1.}: uint8
|
||||
|
|
@ -420,6 +420,14 @@ type
|
|||
|
||||
doAssert sizeof(MixedBitsize) == 12
|
||||
|
||||
|
||||
type
|
||||
MyUnionType {.union.} = object
|
||||
a: int32
|
||||
b: float32
|
||||
|
||||
doAssert sizeof(MyUnionType) == 4
|
||||
|
||||
##########################################
|
||||
# bug #9794
|
||||
##########################################
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue