summary refs log tree commit diff stats
path: root/compiler/vmgen.nim
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2015-10-15 09:31:43 +0200
committerAraq <rumpf_a@web.de>2015-10-15 09:31:54 +0200
commitc97cbe7abd85d134e95ad1a7044fc314c60e5bed (patch)
tree018959820cb3510daf9db092946a7a210c384cc6 /compiler/vmgen.nim
parent7d6c9143d70d1ba09ef43d1580a0ad870d46e2a6 (diff)
downloadNim-c97cbe7abd85d134e95ad1a7044fc314c60e5bed.tar.gz
fixes #3299
Diffstat (limited to 'compiler/vmgen.nim')
-rw-r--r--compiler/vmgen.nim22
1 files changed, 22 insertions, 0 deletions
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 92db0d513..97c6a5580 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -1091,10 +1091,32 @@ proc requiresCopy(n: PNode): bool =
 proc unneededIndirection(n: PNode): bool =
   n.typ.skipTypes(abstractInst-{tyTypeDesc}).kind == tyRef
 
+proc canElimAddr(n: PNode): PNode =
+  case n.sons[0].kind
+  of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:
+    var m = n.sons[0].sons[0]
+    if m.kind in {nkDerefExpr, nkHiddenDeref}:
+      # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x)
+      result = copyNode(n.sons[0])
+      result.add m.sons[0]
+  of nkHiddenStdConv, nkHiddenSubConv, nkConv:
+    var m = n.sons[0].sons[1]
+    if m.kind in {nkDerefExpr, nkHiddenDeref}:
+      # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x)
+      result = copyNode(n.sons[0])
+      result.add m.sons[0]
+  else:
+    if n.sons[0].kind in {nkDerefExpr, nkHiddenDeref}:
+      # addr ( deref ( x )) --> x
+      result = n.sons[0].sons[0]
+
 proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
                   flags: TGenFlags) =
   # a nop for certain types
   let isAddr = opc in {opcAddrNode, opcAddrReg}
+  if isAddr and (let m = canElimAddr(n); m != nil):
+    gen(c, m, dest, flags)
+    return
   let newflags = if isAddr: flags+{gfAddrOf} else: flags
   # consider:
   # proc foo(f: var ref int) =