summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2017-10-10 13:18:32 +0200
committerAndreas Rumpf <rumpf_a@web.de>2017-10-10 13:18:32 +0200
commit13f974336eff453fe4384ef2566f069b6fde75a1 (patch)
treeb0849d565dafa26ae4d062e4bd18981c00714241 /compiler
parent8bd9c7a4e6cb789cd0e37d30c4c59080744cea39 (diff)
parent91981c07bd9335dbd32afb636bd1437a588f39eb (diff)
downloadNim-13f974336eff453fe4384ef2566f069b6fde75a1.tar.gz
Merge branch 'araq-stringify-array' into devel
Diffstat (limited to 'compiler')
-rw-r--r--compiler/condsyms.nim1
-rw-r--r--compiler/destroyer.nim62
-rw-r--r--compiler/renderer.nim5
-rw-r--r--compiler/rodutils.nim14
-rw-r--r--compiler/sigmatch.nim13
-rw-r--r--compiler/types.nim8
6 files changed, 82 insertions, 21 deletions
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim
index 9863e90bb..02c31163a 100644
--- a/compiler/condsyms.nim
+++ b/compiler/condsyms.nim
@@ -108,3 +108,4 @@ proc initDefines*() =
   defineSymbol("nimHasCppDefine")
   defineSymbol("nimGenericInOutFlags")
   when false: defineSymbol("nimHasOpt")
+  defineSymbol("nimNoArrayToCstringConversion")
diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim
index 2ccef1724..e7ff00bb9 100644
--- a/compiler/destroyer.nim
+++ b/compiler/destroyer.nim
@@ -39,6 +39,9 @@
 ## x = y where y is read only once
 ## is the same as:  move(x, y)
 ##
+## Actually the more general rule is: The *last* read of ``y``
+## can become a move if ``y`` is the result of a construction.
+##
 ## We also need to keep in mind here that the number of reads is
 ## control flow dependent:
 ## let x = foo()
@@ -183,10 +186,67 @@ when false:
     of nkVarSection, nkLetSection: collectVarSection(c, n)
     else: discard
 
+type
+  Con = object
+    owner: PSym
+    g: ControlFlowGraph
+    tmps: PType
+
+proc isHarmlessVar*(s: PSym; c: Con): bool =
+  # 's' is harmless if it used only once and its
+  # definition/usage are not split by any labels:
+  #
+  # let s = foo()
+  # while true:
+  #   a[i] = s
+  #
+  # produces:
+  #
+  # def s
+  # L1:
+  #   use s
+  # goto L1
+  #
+  # let s = foo()
+  # if cond:
+  #   a[i] = s
+  # else:
+  #   a[j] = s
+  #
+  # produces:
+  #
+  # def s
+  # fork L2
+  # use s
+  # goto L3
+  # L2:
+  # use s
+  # L3
+  #
+  # So this analysis is for now overly conservative, but correct.
+  discard
+
+template interestingSym(s: PSym): bool =
+  s.owner == owner and s.kind in InterestingSyms and hasDestructor(s.typ)
+
+proc p(n, parent: PNode; c: var Con) =
+  case n.kind
+  of nkVarSection, nkLetSection:
+    discard "transform; var x = y to  var x; x op y  where op is a move or copy"
+  of nkCallKinds:
+    if n.typ != nil and hasDestructor(n.typ):
+      discard "produce temp creation"
+  of nkAsgn, nkFastAsgn:
+    if n[0].kind == nkSym and interestingSym(n[0].sym):
+      discard "use move or assignment"
+  else:
+    for i in 0..<n.len:
+      p(n[i], n, c)
+
 proc injectDestructorCalls*(owner: PSym; n: PNode;
                             disableExceptions = false): PNode =
   when false:
     var c = Con(t: initTable[int, VarInfo](), owner: owner)
     collectData(c, n)
   var allTemps = createObj(owner, n.info)
-
+  let cfg = constructCfg(owner, n)
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index fba4dc9ea..4fbac45ab 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -1011,7 +1011,10 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
   of nkPrefix:
     gsub(g, n, 0)
     if n.len > 1:
-      if n[1].kind == nkPrefix:
+      let opr = if n[0].kind == nkIdent: n[0].ident
+                elif n[0].kind == nkSym: n[0].sym.name
+                else: nil
+      if n[1].kind == nkPrefix or (opr != nil and renderer.isKeyword(opr)):
         put(g, tkSpaces, Space)
       if n.sons[1].kind == nkInfix:
         put(g, tkParLe, "(")
diff --git a/compiler/rodutils.nim b/compiler/rodutils.nim
index 77f7c844f..0456e9349 100644
--- a/compiler/rodutils.nim
+++ b/compiler/rodutils.nim
@@ -10,7 +10,7 @@
 ## Serialization utilities for the compiler.
 import strutils
 
-proc c_sprintf(buf, frmt: cstring) {.importc: "sprintf", header: "<stdio.h>", nodecl, varargs.}
+proc c_snprintf(s: cstring; n:uint; frmt: cstring): cint {.importc: "snprintf", header: "<stdio.h>", nodecl, varargs.}
 
 proc toStrMaxPrecision*(f: BiggestFloat, literalPostfix = ""): string =
   if f != f:
@@ -21,9 +21,14 @@ proc toStrMaxPrecision*(f: BiggestFloat, literalPostfix = ""): string =
     if f > 0.0: result = "INF"
     else: result = "-INF"
   else:
-    var buf: array[0..80, char]
-    c_sprintf(buf, "%#.16e" & literalPostfix, f)
-    result = $buf
+    when defined(nimNoArrayToCstringConversion):
+      result = newString(81)
+      let n = c_snprintf(result.cstring, result.len.uint, "%#.16e%s", f, literalPostfix.cstring)
+      setLen(result, n)
+    else:
+      var buf: array[0..80, char]
+      discard c_snprintf(buf.cstring, buf.len.uint, "%#.16e%s", f, literalPostfix.cstring)
+      result = $buf.cstring
 
 proc encodeStr*(s: string, result: var string) =
   for i in countup(0, len(s) - 1):
@@ -133,4 +138,3 @@ iterator decodeStrArray*(s: cstring): string =
   while s[i] != '\0':
     yield decodeStr(s, i)
     if s[i] == ' ': inc i
-
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index f2bc24399..50d4178b6 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -1288,12 +1288,13 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
     of tyString: result = isConvertible
     of tyPtr:
       # ptr[Tag, char] is not convertible to 'cstring' for now:
-      if a.len == 1 and a.sons[0].kind == tyChar: result = isConvertible
-    of tyArray:
-      if (firstOrd(a.sons[0]) == 0) and
-          (skipTypes(a.sons[0], {tyRange}).kind in {tyInt..tyInt64}) and
-          (a.sons[1].kind == tyChar):
-        result = isConvertible
+      if a.len == 1:
+        let pointsTo = a.sons[0].skipTypes(abstractInst)
+        if pointsTo.kind == tyChar: result = isConvertible
+        elif pointsTo.kind == tyArray and firstOrd(pointsTo.sons[0]) == 0 and
+            skipTypes(pointsTo.sons[0], {tyRange}).kind in {tyInt..tyInt64} and
+            pointsTo.sons[1].kind == tyChar:
+          result = isConvertible
     else: discard
 
   of tyEmpty, tyVoid:
diff --git a/compiler/types.nim b/compiler/types.nim
index 3dbf6fd18..f32b0da18 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -667,14 +667,6 @@ proc lengthOrd*(t: PType): BiggestInt =
     else:
       result = lastOrd(t) - firstOrd(t) + 1
 
-proc isCompatibleToCString*(a: PType): bool =
-  if a.kind == tyArray:
-    if (firstOrd(a.sons[0]) == 0) and
-        (skipTypes(a.sons[0], {tyRange, tyGenericInst, tyAlias}).kind in
-            {tyInt..tyInt64, tyUInt..tyUInt64}) and
-        (a.sons[1].kind == tyChar):
-      result = true
-
 # -------------- type equality -----------------------------------------------
 
 type