Skip to content

Commit

Permalink
make bug visible
Browse files Browse the repository at this point in the history
  • Loading branch information
krux02 committed Apr 19, 2017
1 parent 527afa6 commit d305ae6
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 73 deletions.
2 changes: 0 additions & 2 deletions compiler/semmagic.nim
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,6 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
elif n[1].kind == nkCheckedFieldExpr:
dotExpr = n[1][0]
else:
#echo "evaluating: ", n, " type1: ", type1, " type2: ", type2
debug n[1]
illFormedAst(n)

assert dotExpr != nil
Expand Down
39 changes: 19 additions & 20 deletions compiler/sigmatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type
sym*: PSym
unmatchedVarParam*: int
diagnostics*: seq[string]

CandidateErrors* = seq[CandidateError]

TCandidate* = object
Expand Down Expand Up @@ -68,7 +68,7 @@ type
# future.
mutabilityProblem*: uint8 # tyVar mismatch
inheritancePenalty: int # to prefer closest father object type

TTypeRelation* = enum # order is important!
isNone, isConvertible,
isIntConv,
Expand Down Expand Up @@ -639,7 +639,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
makeTypeDesc(c, typ)

typeParams.safeAdd((param, typ))

addDecl(c, param)

for param in typeClass.n[0]:
Expand Down Expand Up @@ -676,7 +676,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
flags: TExprFlags = {}
collectDiagnostics = m.diagnostics != nil or
sfExplain in typeClass.sym.flags

if collectDiagnostics:
oldWriteHook = writelnHook
# XXX: we can't write to m.diagnostics directly, because
Expand All @@ -688,13 +688,13 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
let msg = s.replace("Error:", errorPrefix)
if oldWriteHook != nil: oldWriteHook msg
diagnostics.add msg

var checkedBody = c.semTryExpr(c, body.copyTree, flags)

if collectDiagnostics:
writelnHook = oldWriteHook
for msg in diagnostics: m.diagnostics.safeAdd msg

if checkedBody == nil: return nil

# The inferrable type params have been identified during the semTryExpr above.
Expand Down Expand Up @@ -746,7 +746,7 @@ proc inferStaticParam*(lhs: PNode, rhs: BiggestInt): PType =
#
# Preconditions:
#
# * The input of this proc must be semantized
# * The input of this proc must be semantized
# - all templates should be expanded
# - aby constant folding possible should already be performed
#
Expand All @@ -769,48 +769,48 @@ proc inferStaticParam*(lhs: PNode, rhs: BiggestInt): PType =
return inferStaticParam(lhs[2], rhs - lhs[1].intVal)
elif lhs[2].kind == nkIntLit:
return inferStaticParam(lhs[1], rhs - lhs[2].intVal)

of mDec, mSubI, mSubU, mPred:
if lhs[1].kind == nkIntLit:
return inferStaticParam(lhs[2], lhs[1].intVal - rhs)
elif lhs[2].kind == nkIntLit:
return inferStaticParam(lhs[1], rhs + lhs[2].intVal)

of mMulI, mMulU:
if lhs[1].kind == nkIntLit:
if rhs mod lhs[1].intVal == 0:
return inferStaticParam(lhs[2], rhs div lhs[1].intVal)
elif lhs[2].kind == nkIntLit:
if rhs mod lhs[2].intVal == 0:
return inferStaticParam(lhs[1], rhs div lhs[2].intVal)

of mDivI, mDivU:
if lhs[1].kind == nkIntLit:
if lhs[1].intVal mod rhs == 0:
return inferStaticParam(lhs[2], lhs[1].intVal div rhs)
elif lhs[2].kind == nkIntLit:
return inferStaticParam(lhs[1], lhs[2].intVal * rhs)

of mShlI:
if lhs[2].kind == nkIntLit:
return inferStaticParam(lhs[1], rhs shr lhs[2].intVal)

of mShrI:
if lhs[2].kind == nkIntLit:
return inferStaticParam(lhs[1], rhs shl lhs[2].intVal)

of mUnaryMinusI:
return inferStaticParam(lhs[1], -rhs)

of mUnaryPlusI, mToInt, mToBiggestInt:
return inferStaticParam(lhs[1], rhs)

else: discard

elif lhs.kind == nkSym and lhs.typ.kind == tyStatic and lhs.typ.n == nil:
lhs.typ.n = newIntNode(nkIntLit, rhs)
return lhs.typ

return nil

proc failureToInferStaticParam(n: PNode) =
Expand All @@ -825,7 +825,7 @@ proc inferStaticsInRange(c: var TCandidate,
allowUnresolved = true)
let upperBound = tryResolvingStaticExpr(c, inferred.n[1],
allowUnresolved = true)

template doInferStatic(c: var TCandidate, e: PNode, r: BiggestInt) =
var exp = e
var rhs = r
Expand Down Expand Up @@ -1049,7 +1049,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
result = typeRel(c, f.sons[1].skipTypes({tyTypeDesc}),
a.sons[1].skipTypes({tyTypeDesc}))
if result < isGeneric: return isNone

if fRange.rangeHasUnresolvedStatic:
return inferStaticsInRange(c, fRange, a)
elif c.c.inTypeClass > 0 and aRange.rangeHasUnresolvedStatic:
Expand Down Expand Up @@ -2217,4 +2217,3 @@ tests:

yes int, ordinal
no string, ordinal

27 changes: 15 additions & 12 deletions compiler/types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1204,7 +1204,7 @@ proc computeSubObjectAlign(n: PNode): BiggestInt =
return align
result = max(result, align)
else:
internalError("computeObjectOffsetsRecursive(record case branch)")
internalError("computeSubObjectAlign")

of nkRecList:
result = 1
Expand All @@ -1223,15 +1223,16 @@ proc computeSubObjectAlign(n: PNode): BiggestInt =
else:
result = 1

proc computeObjectOffsetsRecursive(n: PNode, initialOffset: BiggestInt): tuple[size, align: BiggestInt] =
proc computeObjectOffsetsRecursive(n: PNode, initialOffset: BiggestInt, debug: bool): tuple[size, align: BiggestInt] =
## ``size`` object size without padding bytes at the end
## ``align`` maximum alignment from all sub nodes

result.align = 1
case n.kind
of nkRecCase:

assert(n.sons[0].kind == nkSym)
let (kindSize, kindAlign) = computeObjectOffsetsRecursive(n.sons[0], initialOffset)
let (kindSize, kindAlign) = computeObjectOffsetsRecursive(n.sons[0], initialOffset, debug)

var maxChildAlign: BiggestInt = 0

Expand All @@ -1256,11 +1257,14 @@ proc computeObjectOffsetsRecursive(n: PNode, initialOffset: BiggestInt): tuple[s

var maxChildSize: BiggestInt = 0
for i in 1 ..< sonsLen(n):
let (size, align) = computeObjectOffsetsRecursive(n.sons[i].lastSon, kindUnionOffset)
let (size, align) = computeObjectOffsetsRecursive(n.sons[i].lastSon, kindUnionOffset, debug)
maxChildSize = max(maxChildSize, size)

result.align = max(kindAlign, maxChildAlign)
result.size = align(align(kindSize, maxChildAlign) + maxChildSize, result.align)
result.size = align(maxChildSize, result.align)

if debug:
echo "result.size: ", result.size, " result.align: ", result.align

of nkRecList:

Expand All @@ -1269,7 +1273,7 @@ proc computeObjectOffsetsRecursive(n: PNode, initialOffset: BiggestInt): tuple[s
var offset = initialOffset

for i, child in n.sons:
let (size,align) = computeObjectOffsetsRecursive(child, offset)
let (size,align) = computeObjectOffsetsRecursive(child, offset, debug)

if size < 0:
result.size = size
Expand Down Expand Up @@ -1304,9 +1308,6 @@ proc computeSizeAlign(typ: PType): void =
# nothing to do, size already computed
return

if typ.sym != nil and typ.sym.name.s == "RootObj":
debug typ.sym

if typ.size == szIllegalRecursion:
# we are already computing the size of the type
# --> illegal recursion in type
Expand Down Expand Up @@ -1439,8 +1440,6 @@ proc computeSizeAlign(typ: PType): void =
var headerSize : BiggestInt
var headerAlign: int16

var isRootObj = false

if typ.sons[0] != nil:
var st = typ.sons[0]
#echo "skipTypes, "
Expand Down Expand Up @@ -1477,7 +1476,11 @@ proc computeSizeAlign(typ: PType): void =
headerSize = 0
headerAlign = 1

let (size, align) = computeObjectOffsetsRecursive(typ.n, headerSize)
let debug = typ.sym.name.s == "PaddingBeforeBranchA"
let (size,align) = computeObjectOffsetsRecursive(typ.n, headerSize, debug)

if debug:
echo " size: ", size, " align: ", align

if size < 0:
typ.size = size
Expand Down
101 changes: 62 additions & 39 deletions testsizeof.nim
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ type
ValueA
ValueB

EnumObjectA = object
a : Enum1
b : Enum2
c : Enum4
d : Enum8

EnumObjectB = object
a : Enum8
b : Enum4
c : Enum2
d : Enum1

TrivialType = object
x,y,z: int8

Expand Down Expand Up @@ -129,17 +141,16 @@ type
import macros, typetraits

proc strAlign(arg: string): string =
const minLen = 20
const minLen = 22
result = arg
for i in 0 ..< minLen - arg.len:
result &= ' '

proc intAlign(arg: int): string =
const minLen = 4
result = ""
for i in 0 ..< minLen - result.len:
result &= ' '
result &= $arg
result = $arg
while result.len < minLen:
result.insert(" ")

macro c_offsetof(a: typed, b: untyped): int32 =
let bliteral = newLit(repr(b))
Expand Down Expand Up @@ -168,65 +179,77 @@ proc main(): void =
e2: Enum2
e4: Enum4
e8: Enum8
var
eoa: EnumObjectA
eob: EnumObjectB

echo "sizes:"

macro testSizeAlignOf(args: varargs[untyped]): untyped =
result = newStmtList()
for arg in args:
result.add quote do:
echo `arg`.type.name.strAlign, ": ", intAlign(sizeof(`arg`)), "\t", intAlign(alignof(`arg`)), "\t", intAlign(c_sizeof(`arg`))

testSizeAlignOf(a,b,c,d,e,f,g,ro, e1, e2, e4, e8)

echo "alignof(a.a): ", alignof(a.a)

echo "offsets:"
let
c_size = c_sizeof(`arg`)
nim_size = sizeof(`arg`)
if nim_size != c_size:
echo strAlign(`arg`.type.name & ": "), " size: ",
intAlign(c_size), " != ",
intAlign(nim_size), " align: ",
intAlign(alignof(`arg`))

testSizeAlignOf(a,b,c,d,e,f,g,ro, e1, e2, e4, e8, eoa, eob)

template testOffsetOf(a,b1,b2: untyped): untyped =
let
c_offset = c_offsetof(a,b1)
nim_offset = offsetof(a,b2)
if c_offset != nim_offset:
echo a.type.name, " offset: ", c_offset, " != ", nim_offset

template testOffsetOf(a,b: untyped): untyped =
echo c_offsetof(a,b), " <--> ", offsetof(a, b)
testOffsetOf(a,b,b)

var h: TrivialType
testOffsetOf(TrivialType, z)

# SimpleAlignment
testOffsetOf(SimpleAlignment, a)
testOffsetOf(SimpleAlignment, b)
testOffsetOf(SimpleAlignment, c)
testOffsetOf(AlignAtEnd, a)
testOffsetOf(AlignAtEnd, b)
testOffsetOf(AlignAtEnd, c)

echo "SimpleBranch"
testOffsetOf(SimpleBranch, kindU, a)
testOffsetOf(SimpleBranch, kindU, b)
testOffsetOf(SimpleBranch, kindU, c)

echo c_offsetof(SimpleBranch, kindU), " <--> ", offsetof(SimpleBranch, a)
echo c_offsetof(SimpleBranch, kindU), " <--> ", offsetof(SimpleBranch, b)
echo c_offsetof(SimpleBranch, kindU), " <--> ", offsetof(SimpleBranch, c)
testOffsetOf(PaddingBeforeBranchA, cause)
testOffsetOf(PaddingBeforeBranchA, kindU, a)
testOffsetOf(PaddingBeforeBranchB, cause)
testOffsetOf(PaddingBeforeBranchB, kindU, a)

echo "PaddingBeforeBranch"
testOffsetOf(PaddingAfterBranch, kindU, a)
testOffsetOf(PaddingAfterBranch, cause)

echo c_offsetof(PaddingBeforeBranchA, cause), " <--> ", offsetof(PaddingBeforeBranchA, cause)
echo c_offsetof(PaddingBeforeBranchA, kindU), " <--> ", offsetof(PaddingBeforeBranchA, a)
echo c_offsetof(PaddingBeforeBranchB, cause), " <--> ", offsetof(PaddingBeforeBranchB, cause)
echo c_offsetof(PaddingBeforeBranchB, kindU), " <--> ", offsetof(PaddingBeforeBranchB, a)
testOffsetOf(Foobar, c)

echo "PaddingAfterBranch"
testOffsetOf(Bazing, a)

echo c_offsetof(PaddingAfterBranch, kindU), " <--> ", offsetof(PaddingAfterBranch, a)
echo c_offsetof(PaddingAfterBranch, cause), " <--> ", offsetof(PaddingAfterBranch, cause)
testOffsetOf(InheritanceA, a)
testOffsetOf(InheritanceB, b)
testOffsetOf(InheritanceC, c)

echo "Foobar"
testOffsetOf(EnumObjectA, a)
testOffsetOf(EnumObjectA, b)
testOffsetOf(EnumObjectA, c)
testOffsetOf(EnumObjectA, d)
testOffsetOf(EnumObjectB, a)
testOffsetOf(EnumObjectB, b)
testOffsetOf(EnumObjectB, c)
testOffsetOf(EnumObjectB, d)

echo c_offsetof(Foobar, c), " <--> ", offsetof(Foobar, c)

echo "Bazing"

echo c_offsetof(Bazing, a), " <--> ", offsetof(Bazing, a)

echo "Inheritance"

echo c_offsetof(InheritanceA, a), " <--> ", offsetof(InheritanceC, a)
echo c_offsetof(InheritanceB, b), " <--> ", offsetof(InheritanceC, b)
echo c_offsetof(InheritanceC, c), " <--> ", offsetof(InheritanceC, c)

main()

result.size: 16 result.align: 8
size: 24 align: 8

0 comments on commit d305ae6

Please sign in to comment.