fixes #10082
This commit is contained in:
parent
dd33f41877
commit
062d7e3a39
2 changed files with 22 additions and 25 deletions
|
|
@ -18,7 +18,7 @@ const
|
||||||
szIllegalRecursion* = -2
|
szIllegalRecursion* = -2
|
||||||
szUncomputedSize* = -1
|
szUncomputedSize* = -1
|
||||||
|
|
||||||
proc computeSizeAlign(conf: ConfigRef; typ: PType): void
|
proc computeSizeAlign(conf: ConfigRef; typ: PType)
|
||||||
|
|
||||||
proc computeSubObjectAlign(conf: ConfigRef; n: PNode): BiggestInt =
|
proc computeSubObjectAlign(conf: ConfigRef; n: PNode): BiggestInt =
|
||||||
## returns object alignment
|
## returns object alignment
|
||||||
|
|
@ -49,13 +49,14 @@ proc computeSubObjectAlign(conf: ConfigRef; n: PNode): BiggestInt =
|
||||||
else:
|
else:
|
||||||
result = 1
|
result = 1
|
||||||
|
|
||||||
proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOffset: BiggestInt): tuple[offset, align: BiggestInt] =
|
proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode,
|
||||||
|
initialOffset: BiggestInt): tuple[offset, align: BiggestInt] =
|
||||||
## ``offset`` is the offset within the object, after the node has been written, no padding bytes added
|
## ``offset`` is the offset within the object, after the node has been written, no padding bytes added
|
||||||
## ``align`` maximum alignment from all sub nodes
|
## ``align`` maximum alignment from all sub nodes
|
||||||
assert n != nil
|
assert n != nil
|
||||||
if n.typ != nil and n.typ.size == szIllegalRecursion:
|
if n.typ != nil and n.typ.size == szIllegalRecursion:
|
||||||
result.offset = szIllegalRecursion
|
result.offset = szIllegalRecursion
|
||||||
result.align = szIllegalRecursion
|
result.align = szIllegalRecursion
|
||||||
return
|
return
|
||||||
|
|
||||||
result.align = 1
|
result.align = 1
|
||||||
|
|
@ -71,66 +72,52 @@ proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOffset:
|
||||||
of nkOfBranch, nkElse:
|
of nkOfBranch, nkElse:
|
||||||
# offset parameter cannot be known yet, it needs to know the alignment first
|
# offset parameter cannot be known yet, it needs to know the alignment first
|
||||||
let align = computeSubObjectAlign(conf, n.sons[i].lastSon)
|
let align = computeSubObjectAlign(conf, n.sons[i].lastSon)
|
||||||
|
|
||||||
if align == szIllegalRecursion:
|
if align == szIllegalRecursion:
|
||||||
result.offset = szIllegalRecursion
|
result.offset = szIllegalRecursion
|
||||||
result.align = szIllegalRecursion
|
result.align = szIllegalRecursion
|
||||||
return
|
return
|
||||||
|
|
||||||
if align == szUnknownSize or maxChildAlign == szUnknownSize:
|
if align == szUnknownSize or maxChildAlign == szUnknownSize:
|
||||||
maxChildAlign = szUnknownSize
|
maxChildAlign = szUnknownSize
|
||||||
else:
|
else:
|
||||||
maxChildAlign = max(maxChildAlign, align)
|
maxChildAlign = max(maxChildAlign, align)
|
||||||
else:
|
else:
|
||||||
internalError(conf, "computeObjectOffsetsFoldFunction(record case branch)")
|
internalError(conf, "computeObjectOffsetsFoldFunction(record case branch)")
|
||||||
|
|
||||||
if maxChildAlign == szUnknownSize:
|
if maxChildAlign == szUnknownSize:
|
||||||
result.align = szUnknownSize
|
result.align = szUnknownSize
|
||||||
result.offset = szUnknownSize
|
result.offset = szUnknownSize
|
||||||
else:
|
else:
|
||||||
# the union neds to be aligned first, before the offsets can be assigned
|
# the union neds to be aligned first, before the offsets can be assigned
|
||||||
let kindUnionOffset = align(kindOffset, maxChildAlign)
|
let kindUnionOffset = align(kindOffset, maxChildAlign)
|
||||||
|
|
||||||
var maxChildOffset: BiggestInt = 0
|
var maxChildOffset: BiggestInt = 0
|
||||||
for i in 1 ..< sonsLen(n):
|
for i in 1 ..< sonsLen(n):
|
||||||
let (offset, align) = computeObjectOffsetsFoldFunction(conf, n.sons[i].lastSon, kindUnionOffset)
|
let (offset, align) = computeObjectOffsetsFoldFunction(conf, n.sons[i].lastSon, kindUnionOffset)
|
||||||
maxChildOffset = max(maxChildOffset, offset)
|
maxChildOffset = max(maxChildOffset, offset)
|
||||||
|
|
||||||
result.align = max(kindAlign, maxChildAlign)
|
result.align = max(kindAlign, maxChildAlign)
|
||||||
result.offset = maxChildOffset
|
result.offset = maxChildOffset
|
||||||
|
|
||||||
|
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
result.align = 1 # maximum of all member alignments
|
result.align = 1 # maximum of all member alignments
|
||||||
var offset = initialOffset
|
var offset = initialOffset
|
||||||
|
|
||||||
for i, child in n.sons:
|
for i, child in n.sons:
|
||||||
let (new_offset, align) = computeObjectOffsetsFoldFunction(conf, child, offset)
|
let (new_offset, align) = computeObjectOffsetsFoldFunction(conf, child, offset)
|
||||||
|
|
||||||
if new_offset == szIllegalRecursion:
|
if new_offset == szIllegalRecursion:
|
||||||
result.offset = szIllegalRecursion
|
result.offset = szIllegalRecursion
|
||||||
result.align = szIllegalRecursion
|
result.align = szIllegalRecursion
|
||||||
return
|
return
|
||||||
|
|
||||||
elif new_offset == szUnknownSize or offset == szUnknownSize:
|
elif new_offset == szUnknownSize or offset == szUnknownSize:
|
||||||
# if anything is unknown, the rest becomes unknown as well
|
# if anything is unknown, the rest becomes unknown as well
|
||||||
offset = szUnknownSize
|
offset = szUnknownSize
|
||||||
result.align = szUnknownSize
|
result.align = szUnknownSize
|
||||||
|
|
||||||
else:
|
else:
|
||||||
offset = new_offset
|
offset = new_offset
|
||||||
result.align = max(result.align, align)
|
result.align = max(result.align, align)
|
||||||
|
|
||||||
# final alignment
|
# final alignment
|
||||||
if offset == szUnknownSize:
|
if offset == szUnknownSize:
|
||||||
result.offset = szUnknownSize
|
result.offset = szUnknownSize
|
||||||
else:
|
else:
|
||||||
result.offset = align(offset, result.align)
|
result.offset = align(offset, result.align)
|
||||||
|
|
||||||
of nkSym:
|
of nkSym:
|
||||||
var size = szUnknownSize
|
var size = szUnknownSize
|
||||||
var align = szUnknownSize
|
var align = szUnknownSize
|
||||||
|
|
||||||
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
|
||||||
|
|
@ -155,7 +142,6 @@ proc computePackedObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOf
|
||||||
let kindOffset = computePackedObjectOffsetsFoldFunction(conf, n.sons[0], initialOffset, debug)
|
let kindOffset = computePackedObjectOffsetsFoldFunction(conf, n.sons[0], initialOffset, debug)
|
||||||
# the union neds to be aligned first, before the offsets can be assigned
|
# the union neds to be aligned first, before the offsets can be assigned
|
||||||
let kindUnionOffset = kindOffset
|
let kindUnionOffset = kindOffset
|
||||||
|
|
||||||
var maxChildOffset: BiggestInt = kindUnionOffset
|
var maxChildOffset: BiggestInt = kindUnionOffset
|
||||||
for i in 1 ..< sonsLen(n):
|
for i in 1 ..< sonsLen(n):
|
||||||
let offset = computePackedObjectOffsetsFoldFunction(conf, n.sons[i].lastSon, kindUnionOffset, debug)
|
let offset = computePackedObjectOffsetsFoldFunction(conf, n.sons[i].lastSon, kindUnionOffset, debug)
|
||||||
|
|
@ -168,9 +154,12 @@ proc computePackedObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOf
|
||||||
if result == szIllegalRecursion:
|
if result == szIllegalRecursion:
|
||||||
break
|
break
|
||||||
of nkSym:
|
of nkSym:
|
||||||
computeSizeAlign(conf, n.sym.typ)
|
if n.sym.bitsize == 0:
|
||||||
n.sym.offset = initialOffset.int
|
computeSizeAlign(conf, n.sym.typ)
|
||||||
result = n.sym.offset + n.sym.typ.size
|
n.sym.offset = initialOffset.int
|
||||||
|
result = n.sym.offset + n.sym.typ.size
|
||||||
|
else:
|
||||||
|
result = szUnknownSize
|
||||||
else:
|
else:
|
||||||
result = szUnknownSize
|
result = szUnknownSize
|
||||||
|
|
||||||
|
|
@ -324,7 +313,6 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
|
||||||
var headerAlign: int16
|
var headerAlign: int16
|
||||||
if typ.sons[0] != nil:
|
if typ.sons[0] != nil:
|
||||||
# compute header size
|
# compute header size
|
||||||
|
|
||||||
if conf.cmd == cmdCompileToCpp:
|
if conf.cmd == cmdCompileToCpp:
|
||||||
# if the target is C++ the members of this type are written
|
# if the target is C++ the members of this type are written
|
||||||
# into the padding byets at the end of the parent type. At the
|
# into the padding byets at the end of the parent type. At the
|
||||||
|
|
@ -364,7 +352,6 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
|
||||||
typ.size = szUnknownSize
|
typ.size = szUnknownSize
|
||||||
typ.align = szUnknownSize
|
typ.align = szUnknownSize
|
||||||
return
|
return
|
||||||
|
|
||||||
# header size is already in size from computeObjectOffsetsFoldFunction
|
# header size is already in size from computeObjectOffsetsFoldFunction
|
||||||
# maxAlign is probably not changed at all from headerAlign
|
# maxAlign is probably not changed at all from headerAlign
|
||||||
if tfPacked in typ.flags:
|
if tfPacked in typ.flags:
|
||||||
|
|
@ -373,7 +360,6 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
|
||||||
else:
|
else:
|
||||||
typ.align = int16(max(align, headerAlign))
|
typ.align = int16(max(align, headerAlign))
|
||||||
typ.size = align(offset, typ.align)
|
typ.size = align(offset, typ.align)
|
||||||
|
|
||||||
of tyInferred:
|
of tyInferred:
|
||||||
if typ.len > 1:
|
if typ.len > 1:
|
||||||
computeSizeAlign(conf, typ.lastSon)
|
computeSizeAlign(conf, typ.lastSon)
|
||||||
|
|
|
||||||
|
|
@ -391,6 +391,17 @@ type
|
||||||
|
|
||||||
assert sizeof(Bar) == 12
|
assert sizeof(Bar) == 12
|
||||||
|
|
||||||
|
# bug #10082
|
||||||
|
type
|
||||||
|
A = int8 # change to int16 and get sizeof(C)==6
|
||||||
|
B = int16
|
||||||
|
C = object {.packed.}
|
||||||
|
d {.bitsize: 1.}: A
|
||||||
|
e {.bitsize: 7.}: A
|
||||||
|
f {.bitsize: 16.}: B
|
||||||
|
|
||||||
|
assert sizeof(C) == 3
|
||||||
|
|
||||||
if failed:
|
if failed:
|
||||||
quit("FAIL")
|
quit("FAIL")
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue