summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-05-19 02:49:10 +0200
committerAraq <rumpf_a@web.de>2013-05-19 02:49:10 +0200
commit38ed2373aba94832db01e387c592915c8eec4e60 (patch)
treea96c41d8fa14852a411356ef3ffa6a05689a5c2d /compiler
parent62c80cd570dfcfbb3117e09dea90f4fa10eec33b (diff)
downloadNim-38ed2373aba94832db01e387c592915c8eec4e60.tar.gz
fixes #432, fixes #427
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ccgexprs.nim31
-rw-r--r--compiler/semfold.nim9
2 files changed, 36 insertions, 4 deletions
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: