sizeof(UncheckedArray) should be invalid; fixed the formating of sizealignoffsetimpl.nim to make it bearable

This commit is contained in:
Araq 2018-10-14 00:58:43 +02:00
commit 8232bd04f9

View file

@ -5,9 +5,9 @@ proc align(address, alignment: BiggestInt): BiggestInt =
const const
## a size is concidered "unknown" when it is an imported type from C ## a size is concidered "unknown" when it is an imported type from C
## or C++. ## or C++.
szUnknownSize* = -3 szUnknownSize* = -3
szIllegalRecursion* = -2 szIllegalRecursion* = -2
szUncomputedSize* = -1 szUncomputedSize* = -1
proc computeSizeAlign(conf: ConfigRef; typ: PType): void proc computeSizeAlign(conf: ConfigRef; typ: PType): void
@ -17,7 +17,6 @@ proc computeSubObjectAlign(conf: ConfigRef; n: PNode): BiggestInt =
of nkRecCase: of nkRecCase:
assert(n.sons[0].kind == nkSym) assert(n.sons[0].kind == nkSym)
result = computeSubObjectAlign(conf, n.sons[0]) result = computeSubObjectAlign(conf, n.sons[0])
for i in 1 ..< sonsLen(n): for i in 1 ..< sonsLen(n):
let child = n.sons[i] let child = n.sons[i]
case child.kind case child.kind
@ -28,28 +27,22 @@ proc computeSubObjectAlign(conf: ConfigRef; n: PNode): BiggestInt =
result = max(result, align) result = max(result, align)
else: else:
internalError(conf, "computeSubObjectAlign") internalError(conf, "computeSubObjectAlign")
of nkRecList: of nkRecList:
result = 1 result = 1
for i, child in n.sons: for i, child in n.sons:
let align = computeSubObjectAlign(conf, n.sons[i]) let align = computeSubObjectAlign(conf, n.sons[i])
if align < 0: if align < 0:
return align return align
result = max(result, align) result = max(result, align)
of nkSym: of nkSym:
computeSizeAlign(conf, n.sym.typ) computeSizeAlign(conf, n.sym.typ)
result = n.sym.typ.align result = n.sym.typ.align
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
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
@ -58,12 +51,10 @@ proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOffset:
result.align = 1 result.align = 1
case n.kind case n.kind
of nkRecCase: of nkRecCase:
assert(n.sons[0].kind == nkSym) assert(n.sons[0].kind == nkSym)
let (kindOffset, kindAlign) = computeObjectOffsetsFoldFunction(conf, n.sons[0], initialOffset) let (kindOffset, kindAlign) = computeObjectOffsetsFoldFunction(conf, n.sons[0], initialOffset)
var maxChildAlign: BiggestInt = 0 var maxChildAlign: BiggestInt = 0
for i in 1 ..< sonsLen(n): for i in 1 ..< sonsLen(n):
let child = n.sons[i] let child = n.sons[i]
case child.kind case child.kind
@ -86,7 +77,6 @@ proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOffset:
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)
@ -97,27 +87,25 @@ proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOffset:
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
@ -131,37 +119,23 @@ proc computeObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOffset:
of nkSym: of nkSym:
computeSizeAlign(conf, n.sym.typ) computeSizeAlign(conf, n.sym.typ)
let size = n.sym.typ.size let size = n.sym.typ.size
let align = n.sym.typ.align let align = n.sym.typ.align
result.align = align result.align = align
if initialOffset == szUnknownSize: if initialOffset == szUnknownSize:
n.sym.offset = szUnknownSize n.sym.offset = szUnknownSize
result.offset = szUnknownSize result.offset = szUnknownSize
else: else:
n.sym.offset = align(initialOffset, align).int n.sym.offset = align(initialOffset, align).int
result.offset = n.sym.offset + n.sym.typ.size result.offset = n.sym.offset + n.sym.typ.size
else: else:
result.align = szUnknownSize result.align = szUnknownSize
result.offset = szUnknownSize result.offset = szUnknownSize
proc computePackedObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOffset: BiggestInt, debug: bool): BiggestInt =
var recDepth = 0
proc computePackedObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOffset: BiggestInt, debug : bool): BiggestInt =
## ``result`` is the offset within the object, after the node has been written, no padding bytes added ## ``result`` is the offset within the object, after the node has been written, no padding bytes added
recDepth += 1
defer:
recDepth -= 1
if debug:
if n.kind == nkSym:
echo repeat("--", recDepth) & "> ", initialOffset, " ", n.kind, " ", n.sym.name.s
else:
echo repeat("--", recDepth) & "> ", initialOffset, " ", n.kind
case n.kind case n.kind
of nkRecCase: of nkRecCase:
assert(n.sons[0].kind == nkSym) assert(n.sons[0].kind == nkSym)
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
@ -171,24 +145,17 @@ proc computePackedObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOf
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)
maxChildOffset = max(maxChildOffset, offset) maxChildOffset = max(maxChildOffset, offset)
result = maxChildOffset
if debug:
echo repeat(" ", recDepth), "result: ", maxChildOffset
result = maxChildOffset
of nkRecList: of nkRecList:
result = initialOffset result = initialOffset
for i, child in n.sons: for i, child in n.sons:
result = computePackedObjectOffsetsFoldFunction(conf, child, result, debug) result = computePackedObjectOffsetsFoldFunction(conf, child, result, debug)
if result == szIllegalRecursion: if result == szIllegalRecursion:
break break
of nkSym: of nkSym:
computeSizeAlign(conf, n.sym.typ) computeSizeAlign(conf, n.sym.typ)
n.sym.offset = initialOffset.int n.sym.offset = initialOffset.int
result = n.sym.offset + n.sym.typ.size result = n.sym.offset + n.sym.typ.size
else: else:
result = szUnknownSize result = szUnknownSize
@ -197,7 +164,7 @@ proc computePackedObjectOffsetsFoldFunction(conf: ConfigRef; n: PNode, initialOf
proc computeSizeAlign(conf: ConfigRef; typ: PType) = proc computeSizeAlign(conf: ConfigRef; typ: PType) =
## computes and sets ``size`` and ``align`` members of ``typ`` ## computes and sets ``size`` and ``align`` members of ``typ``
let hasSize = typ.size != szUncomputedSize let hasSize = typ.size != szUncomputedSize
let hasAlign = typ.align != szUncomputedSize let hasAlign = typ.align != szUncomputedSize
if hasSize and hasAlign: if hasSize and hasAlign:
@ -220,7 +187,7 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
return return
# mark computation in progress # mark computation in progress
typ.size = szIllegalRecursion typ.size = szIllegalRecursion
typ.align = szIllegalRecursion typ.align = szIllegalRecursion
var maxAlign, sizeAccum, length: BiggestInt var maxAlign, sizeAccum, length: BiggestInt
@ -249,7 +216,7 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
let base = typ.lastSon let base = typ.lastSon
if base == typ: if base == typ:
# this is not the correct location to detect ``type A = ptr A`` # this is not the correct location to detect ``type A = ptr A``
typ.size = szIllegalRecursion typ.size = szIllegalRecursion
typ.align = szIllegalRecursion typ.align = szIllegalRecursion
return return
@ -257,40 +224,39 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
if base.kind == tyTuple: if base.kind == tyTuple:
computeSizeAlign(conf, base) computeSizeAlign(conf, base)
if base.size == szIllegalRecursion: if base.size == szIllegalRecursion:
typ.size = szIllegalRecursion typ.size = szIllegalRecursion
typ.align = szIllegalRecursion typ.align = szIllegalRecursion
return return
typ.align = int16(conf.target.ptrSize) typ.align = int16(conf.target.ptrSize)
if typ.kind == tySequence and tfHasAsgn in typ.flags: if typ.kind == tySequence and tfHasAsgn in typ.flags:
typ.size = conf.target.ptrSize * 2 typ.size = conf.target.ptrSize * 2
else: else:
typ.size = conf.target.ptrSize typ.size = conf.target.ptrSize
of tyArray: of tyArray:
computeSizeAlign(conf, typ.sons[1]) computeSizeAlign(conf, typ.sons[1])
let elemSize = typ.sons[1].size let elemSize = typ.sons[1].size
if elemSize < 0: if elemSize < 0:
typ.size = elemSize typ.size = elemSize
typ.align = int16(elemSize) typ.align = int16(elemSize)
else: else:
typ.size = lengthOrd(conf, typ.sons[0]) * elemSize typ.size = lengthOrd(conf, typ.sons[0]) * elemSize
typ.align = typ.sons[1].align typ.align = typ.sons[1].align
of tyUncheckedArray: of tyUncheckedArray:
let base = typ.lastSon let base = typ.lastSon
computeSizeAlign(conf, base) computeSizeAlign(conf, base)
# this should probably be szUnknownSize typ.size = szUnknownSize
typ.size = 0
typ.align = base.align typ.align = base.align
of tyEnum: of tyEnum:
if firstOrd(conf, typ) < 0: if firstOrd(conf, typ) < 0:
typ.size = 4 # use signed int32 typ.size = 4 # use signed int32
typ.align = 4 typ.align = 4
else: else:
length = lastOrd(conf, typ) # BUGFIX: use lastOrd! length = lastOrd(conf, typ) # BUGFIX: use lastOrd!
if length + 1 < `shl`(1, 8): if length + 1 < `shl`(1, 8):
typ.size = 1 typ.size = 1
typ.align = 1 typ.align = 1
elif length + 1 < `shl`(1, 16): elif length + 1 < `shl`(1, 16):
typ.size = 2 typ.size = 2
@ -301,10 +267,9 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
else: else:
typ.size = 8 typ.size = 8
typ.align = 8 typ.align = 8
of tySet: of tySet:
if typ.sons[0].kind == tyGenericParam: if typ.sons[0].kind == tyGenericParam:
typ.size = szUncomputedSize typ.size = szUncomputedSize
typ.align = szUncomputedSize # in original version this was 1 typ.align = szUncomputedSize # in original version this was 1
else: else:
length = lengthOrd(conf, typ.sons[0]) length = lengthOrd(conf, typ.sons[0])
@ -317,92 +282,74 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
elif length <= 64: elif length <= 64:
typ.size = 8 typ.size = 8
elif align(length, 8) mod 8 == 0: elif align(length, 8) mod 8 == 0:
typ.size = align(length, 8) div 8 typ.size = align(length, 8) div 8
else: else:
typ.size = align(length, 8) div 8 + 1 typ.size = align(length, 8) div 8 + 1
typ.align = int16(typ.size) typ.align = int16(typ.size)
of tyRange: of tyRange:
computeSizeAlign(conf, typ.sons[0]) computeSizeAlign(conf, typ.sons[0])
typ.size = typ.sons[0].size typ.size = typ.sons[0].size
typ.align = typ.sons[0].align typ.align = typ.sons[0].align
of tyTuple: of tyTuple:
maxAlign = 1 maxAlign = 1
sizeAccum = 0 sizeAccum = 0
for i in countup(0, sonsLen(typ) - 1): for i in countup(0, sonsLen(typ) - 1):
let child = typ.sons[i] let child = typ.sons[i]
computeSizeAlign(conf, child) computeSizeAlign(conf, child)
if child.size == szIllegalRecursion: if child.size == szIllegalRecursion:
typ.size = szIllegalRecursion typ.size = szIllegalRecursion
typ.align = szIllegalRecursion typ.align = szIllegalRecursion
return return
maxAlign = max(maxAlign, child.align) maxAlign = max(maxAlign, child.align)
sizeAccum = align(sizeAccum, child.align) + child.size sizeAccum = align(sizeAccum, child.align) + child.size
typ.size = align(sizeAccum, maxAlign)
typ.size = align(sizeAccum, maxAlign)
typ.align = int16(maxAlign) typ.align = int16(maxAlign)
of tyObject: of tyObject:
var headerSize : BiggestInt var headerSize: BiggestInt
var headerAlign: int16 var headerAlign: int16
if typ.sons[0] != nil: if typ.sons[0] != nil:
# compute header size # compute header size
var st = typ.sons[0] var st = typ.sons[0]
while st.kind in skipPtrs: while st.kind in skipPtrs:
st = st.sons[^1] st = st.sons[^1]
computeSizeAlign(conf, st) computeSizeAlign(conf, st)
if st.size == szIllegalRecursion: if st.size == szIllegalRecursion:
typ.size = st.size typ.size = st.size
typ.align = st.align typ.align = st.align
return return
headerSize = st.size
headerSize = st.size
headerAlign = st.align headerAlign = st.align
elif isObjectWithTypeFieldPredicate(typ): elif isObjectWithTypeFieldPredicate(typ):
# this branch is taken for RootObj # this branch is taken for RootObj
headerSize = conf.target.intSize headerSize = conf.target.intSize
headerAlign = conf.target.intSize.int16 headerAlign = conf.target.intSize.int16
else: else:
headerSize = 0 headerSize = 0
headerAlign = 1 headerAlign = 1
let (offset, align) = let (offset, align) =
if tfPacked in typ.flags: if tfPacked in typ.flags:
(computePackedObjectOffsetsFoldFunction(conf, typ.n, headerSize, false), BiggestInt(1)) (computePackedObjectOffsetsFoldFunction(conf, typ.n, headerSize, false), BiggestInt(1))
else: else:
computeObjectOffsetsFoldFunction(conf, typ.n, headerSize) computeObjectOffsetsFoldFunction(conf, typ.n, headerSize)
if offset == szIllegalRecursion: if offset == szIllegalRecursion:
typ.size = szIllegalRecursion typ.size = szIllegalRecursion
typ.align = szIllegalRecursion typ.align = szIllegalRecursion
return return
if offset == szUnknownSize or ( if offset == szUnknownSize or (
typ.sym != nil and typ.sym != nil and
typ.sym.flags * {sfCompilerProc, sfImportc} == {sfImportc} typ.sym.flags * {sfCompilerProc, sfImportc} == {sfImportc}):
): 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:
typ.size = offset typ.size = offset
typ.align = 1 typ.align = 1
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:
@ -443,5 +390,5 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
typ.size = szUncomputedSize typ.size = szUncomputedSize
typ.align = szUncomputedSize typ.align = szUncomputedSize
else: else:
typ.size = szUncomputedSize typ.size = szUncomputedSize
typ.align = szUncomputedSize typ.align = szUncomputedSize