diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2018-12-30 02:45:34 +0100 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2018-12-30 02:45:43 +0100 |
commit | 062d7e3a398f7afb039ce568cceb32e908e3340e (patch) | |
tree | 1e3026bc3bb489f50d0cbcf03435cdcc4ac9131e | |
parent | dd33f418779c1476b6d8199f72611e282f889199 (diff) | |
download | Nim-062d7e3a398f7afb039ce568cceb32e908e3340e.tar.gz |
fixes #10082
-rw-r--r-- | compiler/sizealignoffsetimpl.nim | 36 | ||||
-rw-r--r-- | tests/misc/tsizeof.nim | 11 |
2 files changed, 22 insertions, 25 deletions
diff --git a/compiler/sizealignoffsetimpl.nim b/compiler/sizealignoffsetimpl.nim index a34383d9f..ea4730f57 100644 --- a/compiler/sizealignoffsetimpl.nim +++ b/compiler/sizealignoffsetimpl.nim @@ -18,7 +18,7 @@ const szIllegalRecursion* = -2 szUncomputedSize* = -1 -proc computeSizeAlign(conf: ConfigRef; typ: PType): void +proc computeSizeAlign(conf: ConfigRef; typ: PType) proc computeSubObjectAlign(conf: ConfigRef; n: PNode): BiggestInt = ## returns object alignment @@ -49,13 +49,14 @@ proc computeSubObjectAlign(conf: ConfigRef; n: PNode): BiggestInt = else: 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 ## ``align`` maximum alignment from all sub nodes assert n != nil if n.typ != nil and n.typ.size == szIllegalRecursion: result.offset = szIllegalRecursion - result.align = szIllegalRecursion + result.align = szIllegalRecursion return result.align = 1 @@ -71,66 +72,52 @@ proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOffset: of nkOfBranch, nkElse: # offset parameter cannot be known yet, it needs to know the alignment first let align = computeSubObjectAlign(conf, n.sons[i].lastSon) - if align == szIllegalRecursion: - result.offset = szIllegalRecursion + result.offset = szIllegalRecursion result.align = szIllegalRecursion return - if align == szUnknownSize or maxChildAlign == szUnknownSize: maxChildAlign = szUnknownSize else: maxChildAlign = max(maxChildAlign, align) else: internalError(conf, "computeObjectOffsetsFoldFunction(record case branch)") - if maxChildAlign == szUnknownSize: result.align = szUnknownSize result.offset = szUnknownSize else: # the union neds to be aligned first, before the offsets can be assigned let kindUnionOffset = align(kindOffset, maxChildAlign) - var maxChildOffset: BiggestInt = 0 for i in 1 ..< sonsLen(n): let (offset, align) = computeObjectOffsetsFoldFunction(conf, n.sons[i].lastSon, kindUnionOffset) maxChildOffset = max(maxChildOffset, offset) - result.align = max(kindAlign, maxChildAlign) result.offset = maxChildOffset - - of nkRecList: result.align = 1 # maximum of all member alignments var offset = initialOffset - for i, child in n.sons: let (new_offset, align) = computeObjectOffsetsFoldFunction(conf, child, offset) - if new_offset == szIllegalRecursion: result.offset = szIllegalRecursion result.align = szIllegalRecursion return - elif new_offset == szUnknownSize or offset == szUnknownSize: # if anything is unknown, the rest becomes unknown as well offset = szUnknownSize result.align = szUnknownSize - else: offset = new_offset result.align = max(result.align, align) - # final alignment if offset == szUnknownSize: result.offset = szUnknownSize else: result.offset = align(offset, result.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 @@ -155,7 +142,6 @@ proc computePackedObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOf let kindOffset = computePackedObjectOffsetsFoldFunction(conf, n.sons[0], initialOffset, debug) # the union neds to be aligned first, before the offsets can be assigned let kindUnionOffset = kindOffset - var maxChildOffset: BiggestInt = kindUnionOffset for i in 1 ..< sonsLen(n): let offset = computePackedObjectOffsetsFoldFunction(conf, n.sons[i].lastSon, kindUnionOffset, debug) @@ -168,9 +154,12 @@ proc computePackedObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOf if result == szIllegalRecursion: break of nkSym: - computeSizeAlign(conf, n.sym.typ) - n.sym.offset = initialOffset.int - result = n.sym.offset + n.sym.typ.size + if n.sym.bitsize == 0: + computeSizeAlign(conf, n.sym.typ) + n.sym.offset = initialOffset.int + result = n.sym.offset + n.sym.typ.size + else: + result = szUnknownSize else: result = szUnknownSize @@ -324,7 +313,6 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) = var headerAlign: int16 if typ.sons[0] != nil: # compute header size - if conf.cmd == cmdCompileToCpp: # 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 @@ -364,7 +352,6 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) = typ.size = szUnknownSize typ.align = szUnknownSize return - # header size is already in size from computeObjectOffsetsFoldFunction # maxAlign is probably not changed at all from headerAlign if tfPacked in typ.flags: @@ -373,7 +360,6 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) = else: typ.align = int16(max(align, headerAlign)) typ.size = align(offset, typ.align) - of tyInferred: if typ.len > 1: computeSizeAlign(conf, typ.lastSon) diff --git a/tests/misc/tsizeof.nim b/tests/misc/tsizeof.nim index a73b3dcde..4422e900e 100644 --- a/tests/misc/tsizeof.nim +++ b/tests/misc/tsizeof.nim @@ -391,6 +391,17 @@ type 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: quit("FAIL") else: |