<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Mu - 083scenario_screen_test.mu</title>
<meta name="Generator" content="Vim/7.4">
<meta name="plugin-version" content="vim7.4_v2">
<meta name="syntax" content="none">
<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
<meta name="colorscheme" content="minimal">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; }
* { font-size: 12pt; font-size: 1em; }
.Comment { color: #9090ff; }
.Constant { color: #00a0a0; }
.Special { color: #c00000; }
.muScenario { color: #00af00; }
-->
</style>
<script type='text/javascript'>
<!--
-->
</script>
</pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */#
#
# The Nim Compiler
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## code owner: Arne Döring
## e-mail: arne.doering@gmx.net
proc align(address, alignment: BiggestInt): BiggestInt =
result = (address + (alignment - 1)) and not (alignment - 1)
const
## a size is concidered "unknown" when it is an imported type from C
## or C++.
szUnknownSize* = -3
szIllegalRecursion* = -2
szUncomputedSize* = -1
proc computeSizeAlign(conf: ConfigRef; typ: PType): void
proc computeSubObjectAlign(conf: ConfigRef; n: PNode): BiggestInt =
## returns object alignment
case n.kind
of nkRecCase:
assert(n.sons[0].kind == nkSym)
result = computeSubObjectAlign(conf, n.sons[0])
for i in 1 ..< sonsLen(n):
let child = n.sons[i]
case child.kind
of nkOfBranch, nkElse:
let align = computeSubObjectAlign(conf, child.lastSon)
if align < 0:
return align
result = max(result, align)
else:
internalError(conf, "computeSubObjectAlign")
of nkRecList:
result = 1
for i, child in n.sons:
let align = computeSubObjectAlign(conf, n.sons[i])
if align < 0:
return align
result = max(result, align)
of nkSym:
computeSizeAlign(conf, n.sym.typ)
result = n.sym.typ.align
else:
result = 1
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
return
result.align = 1
case n.kind
of nkRecCase:
assert(n.sons[0].kind == nkSym)
let (kindOffset, kindAlign) = computeObjectOffsetsFoldFunction(conf, n.sons[0], initialOffset)
var maxChildAlign: BiggestInt = 0
for i in 1 ..< sonsLen(n):
let child = n.sons[i]
case child.kind
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.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
align = n.sym.typ.align.int
result.align = align
if initialOffset == szUnknownSize or size == szUnknownSize:
n.sym.offset = szUnknownSize
result.offset = szUnknownSize
else:
n.sym.offset = align(initialOffset, align).int
result.offset = n.sym.offset + n.sym.typ.size
else:
result.align = szUnknownSize
result.offset = szUnknownSize
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
case n.kind
of nkRecCase:
assert(n.sons[0].kind == nkSym)
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)
maxChildOffset = max(maxChildOffset, offset)
result = maxChildOffset
of nkRecList:
result = initialOffset
for i, child in n.sons:
result = computePackedObjectOffsetsFoldFunction(conf, child, result, debug)
if result == szIllegalRecursion:
break
of nkSym:
computeSizeAlign(conf, n.sym.typ)
n.sym.offset = initialOffset.int
result = n.sym.offset + n.sym.typ.size
else:
result = szUnknownSize
# TODO this one needs an alignment map of the individual types
proc computeSizeAlign(conf: ConfigRef; typ: PType) =
## computes and sets ``size`` and ``align`` members of ``typ``
assert typ != nil
let hasSize = typ.size != szUncomputedSize
let hasAlign = typ.align != szUncomputedSize
if hasSize and hasAlign:
# nothing to do, size and align already computed
return
# This function can only calculate both, size and align at the same time.
# If one of them is already set this value is stored here and reapplied
let revertSize = typ.size
let revertAlign = typ.align
defer:
if hasSize:
typ.size = revertSize
if hasAlign:
typ.align = revertAlign
if typ.size == szIllegalRecursion or typ.align == szIllegalRecursion:
# we are already computing the size of the type
# --> illegal recursion in type
return
# mark computation in progress
typ.size = szIllegalRecursion
typ.align = szIllegalRecursion
var maxAlign, sizeAccum, length: BiggestInt
var tk = typ.kind
case tk
of tyProc:
if typ.callConv == ccClosure:
typ.size = 2 * conf.target.ptrSize
else:
typ.size = conf.target.ptrSize
typ.align = int16(conf.target.ptrSize)
of tyNil:
typ.size = conf.target.ptrSize
typ.align = int16(conf.target.ptrSize)
of tyString:
if conf.selectedGC == gcDestructors:
typ.size = conf.target.ptrSize * 2
else:
typ.size = conf.target.ptrSize
typ.align = int16(conf.target.ptrSize)
of tyCString, tySequence, tyPtr, tyRef, tyVar, tyLent, tyOpenArray:
let base = typ.lastSon
if base == typ:
# this is not the correct location to detect ``type A = ptr A``
typ.size = szIllegalRecursion
typ.align = szIllegalRecursion
return
# recursive tuplers are not allowed and should be detected in the frontend
if base.kind == tyTuple:
computeSizeAlign(conf, base)
if base.size < 0:
typ.size = base.size
typ.align = base.align
return
typ.align = int16(conf.target.ptrSize)
if typ.kind == tySequence and conf.selectedGC == gcDestructors:
typ.size = conf.target.ptrSize * 2
else:
typ.size = conf.target.ptrSize
of tyArray:
computeSizeAlign(conf, typ.sons[1])
let elemSize = typ.sons[1].size
if elemSize < 0:
typ.size = elemSize
typ.align = int16(elemSize)
else:
typ.size = lengthOrd(conf, typ.sons[0]) * elemSize
typ.align = typ.sons[1].align
of tyUncheckedArray:
let base = typ.lastSon
computeSizeAlign(conf, base)
typ.size = szUnknownSize
typ.align = base.align
of tyEnum:
if firstOrd(conf, typ) < 0:
typ.size = 4 # use signed int32
typ.align = 4
else:
length = lastOrd(conf, typ) # BUGFIX: use lastOrd!
if length + 1 < `shl`(1, 8):
typ.size = 1
typ.align = 1
elif length + 1 < `shl`(1, 16):
typ.size = 2
typ.align = 2
elif length + 1 < `shl`(BiggestInt(1), 32):
typ.size = 4
typ.align = 4
else:
typ.size = 8
typ.align = 8
of tySet:
if typ.sons[0].kind == tyGenericParam:
typ.size = szUncomputedSize
typ.align = szUncomputedSize # in original version this was 1
else:
length = lengthOrd(conf, typ.sons[0])
if length <= 8:
typ.size = 1
elif length <= 16:
typ.size = 2
elif length <= 32:
typ.size = 4
elif length <= 64:
typ.size = 8
elif align(length, 8) mod 8 == 0:
typ.size = align(length, 8) div 8
else:
typ.size = align(length, 8) div 8 + 1
typ.align = int16(typ.size)
of tyRange:
computeSizeAlign(conf, typ.sons[0])
typ.size = typ.sons[0].size
typ.align = typ.sons[0].align
of tyTuple:
maxAlign = 1
sizeAccum = 0
for i in countup(0, sonsLen(typ) - 1):
let child = typ.sons[i]
computeSizeAlign(conf, child)
if child.size < 0:
typ.size = child.size
typ.align = child.align
return
maxAlign = max(maxAlign, child.align)
sizeAccum = align(sizeAccum, child.align) + child.size
typ.size = align(sizeAccum, maxAlign)
typ.align = int16(maxAlign)
of tyObject:
var headerSize: BiggestInt
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
# moment it is not supported to calculate that.
headerSize = szUnknownSize
headerAlign = szUncomputedSize
else:
var st = typ.sons[0]
while st.kind in skipPtrs:
st = st.sons[^1]
computeSizeAlign(conf, st)
if st.size == szIllegalRecursion:
typ.size = st.size
typ.align = st.align
return
headerSize = st.size
headerAlign = st.align
elif isObjectWithTypeFieldPredicate(typ):
# this branch is taken for RootObj
headerSize = conf.target.intSize
headerAlign = conf.target.intSize.int16
else:
headerSize = 0
headerAlign = 1
let (offset, align) =
if tfPacked in typ.flags:
(computePackedObjectOffsetsFoldFunction(conf, typ.n, headerSize, false), BiggestInt(1))
else:
computeObjectOffsetsFoldFunction(conf, typ.n, headerSize)
if offset == szIllegalRecursion:
typ.size = szIllegalRecursion
typ.align = szIllegalRecursion
return
if offset == szUnknownSize or (
typ.sym != nil and
typ.sym.flags * {sfCompilerProc, sfImportc} == {sfImportc}):
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:
typ.size = offset
typ.align = 1
else:
typ.align = int16(max(align, headerAlign))
typ.size = align(offset, typ.align)
of tyInferred:
if typ.len > 1:
computeSizeAlign(conf, typ.lastSon)
typ.size = typ.lastSon.size
typ.align = typ.lastSon.align
of tyGenericInst, tyDistinct, tyGenericBody, tyAlias, tySink:
computeSizeAlign(conf, typ.lastSon)
typ.size = typ.lastSon.size
typ.align = typ.lastSon.align
of tyTypeClasses:
if typ.isResolvedUserTypeClass:
computeSizeAlign(conf, typ.lastSon)
typ.size = typ.lastSon.size
typ.align = typ.lastSon.align
else:
typ.size = szUncomputedSize
typ.align = szUncomputedSize
of tyTypeDesc:
computeSizeAlign(conf, typ.base)
typ.size = typ.base.size
typ.align = typ.base.align
of tyForward:
# is this really illegal recursion, or maybe just unknown?
typ.size = szIllegalRecursion
typ.align = szIllegalRecursion
of tyStatic:
if typ.n != nil:
computeSizeAlign(conf, typ.lastSon)
typ.size = typ.lastSon.size
typ.align = typ.lastSon.align
else:
typ.size = szUncomputedSize
typ.align = szUncomputedSize
else:
typ.size = szUncomputedSize
typ.align = szUncomputedSize