summary refs log tree commit diff stats
path: root/compiler/vmgen.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/vmgen.nim')
-rw-r--r--compiler/vmgen.nim37
1 files changed, 33 insertions, 4 deletions
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index a4ddc2e15..e0e34306c 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -1,6 +1,6 @@
 #
 #
-#           The Nimrod Compiler
+#           The Nim Compiler
 #        (c) Copyright 2014 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
@@ -46,7 +46,6 @@ proc debugInfo(info: TLineInfo): string =
 proc codeListing(c: PCtx, result: var string, start=0; last = -1) =
   # first iteration: compute all necessary labels:
   var jumpTargets = initIntSet()
-  
   let last = if last < 0: c.code.len-1 else: min(last, c.code.len-1)
   for i in start..last:
     let x = c.code[i]
@@ -83,7 +82,7 @@ proc codeListing(c: PCtx, result: var string, start=0; last = -1) =
     result.add("\n")
     inc i
 
-proc echoCode*(c: PCtx, start=0; last = -1) {.deprecated.} =
+proc echoCode*(c: PCtx; start=0; last = -1) {.deprecated.} =
   var buf = ""
   codeListing(c, buf, start, last)
   echo buf
@@ -1068,6 +1067,9 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
         c.gABC(n, opcNodeToReg, dest, dest)
     elif c.prc.slots[tmp].kind >= slotTempUnknown:
       gABC(c, n, opcAddrNode, dest, tmp)
+      # XXX this can still be wrong sometimes; hopefully it's only generated
+      # in call contexts, where it is safe
+      #message(n.info, warnUser, "suspicious opcode used")
     else:
       gABC(c, n, opcAddrReg, dest, tmp)
     c.freeTemp(tmp)
@@ -1124,6 +1126,7 @@ proc checkCanEval(c: PCtx; n: PNode) =
   # we need to ensure that we don't evaluate 'x' here:
   # proc foo() = var x ...
   let s = n.sym
+  if {sfCompileTime, sfGlobal} <= s.flags: return
   if s.kind in {skVar, skTemp, skLet, skParam, skResult} and 
       not s.isOwnedBy(c.prc.sym) and s.owner != c.module:
     cannotEval(n)
@@ -1134,6 +1137,9 @@ proc isTemp(c: PCtx; dest: TDest): bool =
 template needsAdditionalCopy(n): expr =
   not c.isTemp(dest) and not fitsRegister(n.typ)
 
+proc skipDeref(n: PNode): PNode =
+  result = if n.kind in {nkDerefExpr, nkHiddenDeref}: n.sons[0] else: n
+
 proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode;
                        dest, idx, value: TRegister) =
   # opcLdObj et al really means "load address". We sometimes have to create a
@@ -1497,6 +1503,26 @@ proc genTupleConstr(c: PCtx, n: PNode, dest: var TDest) =
 
 proc genProc*(c: PCtx; s: PSym): int
 
+proc matches(s: PSym; x: string): bool =
+  let y = x.split('.')
+  var s = s
+  var L = y.len-1
+  while L >= 0:
+    if s == nil or y[L].cmpIgnoreStyle(s.name.s) != 0: return false
+    s = s.owner
+    dec L
+  result = true
+
+proc procIsCallback(c: PCtx; s: PSym): bool =
+  if s.offset < -1: return true
+  var i = -2
+  for key, value in items(c.callbacks):
+    if s.matches(key): 
+      doAssert s.offset == -1
+      s.offset = i
+      return true
+    dec i
+
 proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
   case n.kind
   of nkSym:
@@ -1507,7 +1533,8 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
       genRdVar(c, n, dest, flags)
     of skProc, skConverter, skMacro, skTemplate, skMethod, skIterators:
       # 'skTemplate' is only allowed for 'getAst' support:
-      if sfImportc in s.flags: c.importcSym(n.info, s)
+      if procIsCallback(c, s): discard
+      elif sfImportc in s.flags: c.importcSym(n.info, s)
       genLit(c, n, dest)
     of skConst:
       gen(c, s.ast, dest)
@@ -1569,6 +1596,8 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
     let L = n.len-1
     for i in 0 .. <L: gen(c, n.sons[i])
     gen(c, n.sons[L], dest, flags)
+  of nkPragmaBlock:
+    gen(c, n.lastSon, dest, flags)
   of nkDiscardStmt:
     unused(n, dest)
     gen(c, n.sons[0])