summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2017-10-08 08:04:02 +0200
committerAndreas Rumpf <rumpf_a@web.de>2017-10-09 21:12:40 +0200
commit7eaa2474a27893d42e4ee46aedd2ab4d54a2d06e (patch)
tree2c033e6545dbe22b64d59b995a1e0e9ce05c9cd3
parentb9511a2d7f6b2037ed461abddfc85b3afd5108d9 (diff)
downloadNim-7eaa2474a27893d42e4ee46aedd2ab4d54a2d06e.tar.gz
disable the new DFA
-rw-r--r--compiler/dfa.nim57
-rw-r--r--compiler/sempass2.nim7
2 files changed, 38 insertions, 26 deletions
diff --git a/compiler/dfa.nim b/compiler/dfa.nim
index b9ca81065..8361273c8 100644
--- a/compiler/dfa.nim
+++ b/compiler/dfa.nim
@@ -345,32 +345,41 @@ proc dfa(code: seq[Instr]) =
   # any further than necessary.
   var w = @[0]
   while w.len > 0:
-    var pc = w.pop()
-    #var undefB: IntSet
-    #assign(undefB, undef)
-
-    #[
-    new := ![I[pc]!](s[pc])
-    if I[pc] = (goto l) then
-      pc' := l
-    else
-      pc' := pc + 1
-      if I[pc] = (if ψ goto l) and new < s[l] then
-        W := W + l
-        s[l] := new
-      end
-    end
-    if new < s[pc] then
-      s[pc'] := new
-      pc := pc'
-    else
-      break
-    end
-    if pc >= code.len: break
-    ]#
-
+    var pc = w[^1]
     # this simulates a single linear control flow execution:
     while true:
+      # according to the paper, it is better to shrink the working set here
+      # in this inner loop:
+      let widx = w.find(pc)
+      if widx >= 0: w.del(widx)
+      # our interpretation ![I!]:
+      var sid = -1
+      case code[pc].kind
+      of goto, fork: discard
+      of use:
+        let sym = code[pc].sym
+        if s[pc].contains(sym.id):
+          localError(code[pc].n.info, "variable read before initialized: " & sym.name.s)
+      of def:
+        sid = code[pc].sym.id
+
+      var pc2: int
+      if code[pc].kind == goto:
+        pc2 = pc + code[pc].dest
+      else:
+        pc2 = pc + 1
+        if code[pc].kind == fork:
+          let l = pc + code[pc].dest
+          if sid >= 0 and s[l].missingOrExcl(sid):
+            w.add l
+
+      if sid >= 0 and s[pc2].missingOrExcl(sid):
+        pc = pc2
+      else:
+        break
+      if pc >= code.len: break
+
+    when false:
       case code[pc].kind
       of use:
         let s = code[pc].sym
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index bf5735fc1..17bdf0902 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -9,7 +9,10 @@
 
 import
   intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
-  wordrecg, strutils, options, guards, writetracking, dfa
+  wordrecg, strutils, options, guards, writetracking
+
+when defined(useDfa):
+  import dfa
 
 # Second semantic checking pass over the AST. Necessary because the old
 # way had some inherent problems. Performs:
@@ -980,7 +983,7 @@ proc trackProc*(s: PSym, body: PNode) =
       "declared lock level is $1, but real lock level is $2" %
         [$s.typ.lockLevel, $t.maxLockLevel])
   if s.kind == skFunc:
-    dataflowAnalysis(s, body)
+    when defined(dfa): dataflowAnalysis(s, body)
     trackWrites(s, body)
 
 proc trackTopLevelStmt*(module: PSym; n: PNode) =