From 38ed2373aba94832db01e387c592915c8eec4e60 Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 19 May 2013 02:49:10 +0200 Subject: fixes #432, fixes #427 --- compiler/ccgexprs.nim | 31 ++++++++++++++++++++++++++++--- compiler/semfold.nim | 9 ++++++++- 2 files changed, 36 insertions(+), 4 deletions(-) (limited to 'compiler') diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 3a419393d..410e65ac9 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1378,7 +1378,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) = proc genOrd(p: BProc, e: PNode, d: var TLoc) = unaryExprChar(p, e, d, "$1") -proc genCast(p: BProc, e: PNode, d: var TLoc) = +proc genSomeCast(p: BProc, e: PNode, d: var TLoc) = const ValueTypes = {tyTuple, tyObject, tyArray, tyOpenArray, tyVarargs, tyArrayConstr} @@ -1397,6 +1397,31 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) = putIntoDest(p, d, e.typ, ropef("(($1) ($2))", [getTypeDesc(p.module, e.typ), rdCharLoc(a)])) +proc genCast(p: BProc, e: PNode, d: var TLoc) = + const floatTypes = {tyFloat..tyFloat128} + let + destt = skipTypes(e.typ, abstractRange) + srct = skipTypes(e.sons[1].typ, abstractRange) + if destt.kind in floatTypes or srct.kind in floatTypes: + # 'cast' and some float type involved? --> use a union. + inc(p.labels) + var lbl = p.labels.toRope + var tmp: TLoc + tmp.r = ropef("LOC$1.source", lbl) + linefmt(p, cpsLocals, "union { $1 source; $2 dest; } LOC$3;$n", + getTypeDesc(p.module, srct), getTypeDesc(p.module, destt), lbl) + tmp.k = locExpr + tmp.a = -1 + tmp.t = srct + tmp.s = OnStack + tmp.flags = {} + expr(p, e.sons[1], tmp) + putIntoDest(p, d, e.typ, ropef("LOC$#.dest", lbl)) + else: + # I prefer the shorter cast version for pointer types -> generate less + # C code; plus it's the right thing to do for closures: + genSomeCast(p, e, d) + proc genRangeChck(p: BProc, n: PNode, d: var TLoc, magic: string) = var a: TLoc var dest = skipTypes(n.typ, abstractVar) @@ -1418,7 +1443,7 @@ proc genConv(p: BProc, e: PNode, d: var TLoc) = if compareTypes(e.typ, e.sons[1].typ, dcEqIgnoreDistinct): expr(p, e.sons[1], d) else: - genCast(p, e, d) + genSomeCast(p, e, d) proc convStrToCStr(p: BProc, n: PNode, d: var TLoc) = var a: TLoc @@ -1531,7 +1556,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = let t = e.sons[1].typ.skipTypes({tyTypeDesc}) putIntoDest(p, d, e.typ, ropef("((NI)sizeof($1))", [getTypeDesc(p.module, t)])) - of mChr: genCast(p, e, d) + of mChr: genSomeCast(p, e, d) of mOrd: genOrd(p, e, d) of mLengthArray, mHigh, mLengthStr, mLengthSeq, mLengthOpenArray: genArrayLen(p, e, d, op) diff --git a/compiler/semfold.nim b/compiler/semfold.nim index cc1f4b5ee..6fdb780c9 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -698,10 +698,17 @@ proc getConstExpr(m: PSym, n: PNode): PNode = if a == nil: return result = a result.typ = n.typ - of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkCast: + of nkHiddenStdConv, nkHiddenSubConv, nkConv: var a = getConstExpr(m, n.sons[1]) if a == nil: return result = foldConv(n, a, check=n.kind == nkHiddenStdConv) + of nkCast: + var a = getConstExpr(m, n.sons[1]) + if a == nil: return + if n.typ.kind in NilableTypes: + # we allow compile-time 'cast' for pointer types: + result = a + result.typ = n.typ of nkBracketExpr: result = foldArrayAccess(m, n) of nkDotExpr: result = foldFieldAccess(m, n) else: -- cgit 1.4.1-2-gfad0