summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semstmts.nim18
-rw-r--r--compiler/vm.nim5
-rw-r--r--compiler/vmgen.nim10
-rw-r--r--lib/pure/parseopt.nim71
-rw-r--r--lib/system/repr.nim25
5 files changed, 68 insertions, 61 deletions
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 68da6d3b2..d77e619f9 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1863,7 +1863,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
         " operator has to be enabled with {.experimental: \"callOperator\".}")
 
   if n.sons[bodyPos].kind != nkEmpty and sfError notin s.flags:
-    # for DLL generation it is annoying to check for sfImportc!
+    # for DLL generation we allow sfImportc to have a body, for use in VM
     if sfBorrow in s.flags:
       localError(c.config, n.sons[bodyPos].info, errImplOfXNotAllowed % s.name.s)
     let usePseudoGenerics = kind in {skMacro, skTemplate}
@@ -1881,12 +1881,11 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
 
         c.p.wasForwarded = proto != nil
         maybeAddResult(c, s, n)
-        if lfDynamicLib notin s.loc.flags:
-          # no semantic checking for importc:
-          s.ast[bodyPos] = hloBody(c, semProcBody(c, n.sons[bodyPos]))
-          # unfortunately we cannot skip this step when in 'system.compiles'
-          # context as it may even be evaluated in 'system.compiles':
-          trackProc(c, s, s.ast[bodyPos])
+        # semantic checking also needed with importc in case used in VM
+        s.ast[bodyPos] = hloBody(c, semProcBody(c, n.sons[bodyPos]))
+        # unfortunately we cannot skip this step when in 'system.compiles'
+        # context as it may even be evaluated in 'system.compiles':
+        trackProc(c, s, s.ast[bodyPos])
         if s.kind == skMethod: semMethodPrototype(c, s, n)
       else:
         if (s.typ.sons[0] != nil and kind != skIterator) or kind == skMacro:
@@ -1899,8 +1898,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
           fixupInstantiatedSymbols(c, s)
         if s.kind == skMethod: semMethodPrototype(c, s, n)
       if sfImportc in s.flags:
-        # so we just ignore the body after semantic checking for importc:
-        n.sons[bodyPos] = c.graph.emptyNode
+        # don't ignore the body in case used in VM
+        # n.sons[bodyPos] = c.graph.emptyNode
+        discard
       popProcCon(c)
   else:
     if s.kind == skMethod: semMethodPrototype(c, s, n)
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 2919e865a..f2b288216 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -1082,12 +1082,15 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
           VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[pointer](regs),
                  currentException: c.currentExceptionA,
                  currentLineInfo: c.debug[pc]))
-      elif sfImportc in prc.flags:
+      elif importcCond(prc):
         if compiletimeFFI notin c.config.features:
           globalError(c.config, c.debug[pc], "VM not allowed to do FFI, see `compiletimeFFI`")
         # we pass 'tos.slots' instead of 'regs' so that the compiler can keep
         # 'regs' in a register:
         when hasFFI:
+          if prc.position - 1 < 0:
+            globalError(c.config, c.debug[pc],
+              "VM call invalid: prc.position: " & $prc.position)
           let prcValue = c.globals.sons[prc.position-1]
           if prcValue.kind == nkEmpty:
             globalError(c.config, c.debug[pc], "cannot run " & prc.name.s)
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 08d79bbb7..9e1c4d602 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -1544,8 +1544,11 @@ proc genTypeLit(c: PCtx; t: PType; dest: var TDest) =
   n.typ = t
   genLit(c, n, dest)
 
-proc importcCond(s: PSym): bool {.inline.} =
-  sfImportc in s.flags and (lfDynamicLib notin s.loc.flags or s.ast == nil)
+proc importcCond*(s: PSym): bool {.inline.} =
+  ## return true to importc `s`, false to execute its body instead (refs #8405)
+  if sfImportc in s.flags:
+    if s.kind in routineKinds:
+      return s.ast.sons[bodyPos].kind == nkEmpty
 
 proc importcSym(c: PCtx; info: TLineInfo; s: PSym) =
   when hasFFI:
@@ -1553,7 +1556,8 @@ proc importcSym(c: PCtx; info: TLineInfo; s: PSym) =
       c.globals.add(importcSymbol(c.config, s))
       s.position = c.globals.len
     else:
-      localError(c.config, info, "VM is not allowed to 'importc'")
+      localError(c.config, info,
+        "VM is not allowed to 'importc' without --experimental:compiletimeFFI")
   else:
     localError(c.config, info,
                "cannot 'importc' variable at compile time; " & s.name.s)
diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim
index fab32060a..545f9f00a 100644
--- a/lib/pure/parseopt.nim
+++ b/lib/pure/parseopt.nim
@@ -366,43 +366,42 @@ proc next*(p: var OptParser) {.rtl, extern: "npo$1".} =
     inc p.idx
     p.pos = 0
 
-when declared(os.paramCount):
-  proc cmdLineRest*(p: OptParser): TaintedString {.rtl, extern: "npo$1".} =
-    ## Retrieves the rest of the command line that has not been parsed yet.
-    ##
-    ## See also:
-    ## * `remainingArgs proc<#remainingArgs,OptParser>`_
-    ##
-    ## **Examples:**
-    ##
-    ## .. code-block::
-    ##   var p = initOptParser("--left -r:2 -- foo.txt bar.txt")
-    ##   while true:
-    ##     p.next()
-    ##     if p.kind == cmdLongOption and p.key == "":  # Look for "--"
-    ##       break
-    ##     else: continue
-    ##   doAssert p.cmdLineRest == "foo.txt bar.txt"
-    result = p.cmds[p.idx .. ^1].quoteShellCommand.TaintedString
+proc cmdLineRest*(p: OptParser): TaintedString {.rtl, extern: "npo$1".} =
+  ## Retrieves the rest of the command line that has not been parsed yet.
+  ##
+  ## See also:
+  ## * `remainingArgs proc<#remainingArgs,OptParser>`_
+  ##
+  ## **Examples:**
+  ##
+  ## .. code-block::
+  ##   var p = initOptParser("--left -r:2 -- foo.txt bar.txt")
+  ##   while true:
+  ##     p.next()
+  ##     if p.kind == cmdLongOption and p.key == "":  # Look for "--"
+  ##       break
+  ##     else: continue
+  ##   doAssert p.cmdLineRest == "foo.txt bar.txt"
+  result = p.cmds[p.idx .. ^1].quoteShellCommand.TaintedString
 
-  proc remainingArgs*(p: OptParser): seq[TaintedString] {.rtl, extern: "npo$1".} =
-    ## Retrieves a sequence of the arguments that have not been parsed yet.
-    ##
-    ## See also:
-    ## * `cmdLineRest proc<#cmdLineRest,OptParser>`_
-    ##
-    ## **Examples:**
-    ##
-    ## .. code-block::
-    ##   var p = initOptParser("--left -r:2 -- foo.txt bar.txt")
-    ##   while true:
-    ##     p.next()
-    ##     if p.kind == cmdLongOption and p.key == "":  # Look for "--"
-    ##       break
-    ##     else: continue
-    ##   doAssert p.remainingArgs == @["foo.txt", "bar.txt"]
-    result = @[]
-    for i in p.idx..<p.cmds.len: result.add TaintedString(p.cmds[i])
+proc remainingArgs*(p: OptParser): seq[TaintedString] {.rtl, extern: "npo$1".} =
+  ## Retrieves a sequence of the arguments that have not been parsed yet.
+  ##
+  ## See also:
+  ## * `cmdLineRest proc<#cmdLineRest,OptParser>`_
+  ##
+  ## **Examples:**
+  ##
+  ## .. code-block::
+  ##   var p = initOptParser("--left -r:2 -- foo.txt bar.txt")
+  ##   while true:
+  ##     p.next()
+  ##     if p.kind == cmdLongOption and p.key == "":  # Look for "--"
+  ##       break
+  ##     else: continue
+  ##   doAssert p.remainingArgs == @["foo.txt", "bar.txt"]
+  result = @[]
+  for i in p.idx..<p.cmds.len: result.add TaintedString(p.cmds[i])
 
 iterator getopt*(p: var OptParser): tuple[kind: CmdLineKind, key, val: TaintedString] =
   ## Convenience iterator for iterating over the given
diff --git a/lib/system/repr.nim b/lib/system/repr.nim
index 29c0d4ce9..a3212020a 100644
--- a/lib/system/repr.nim
+++ b/lib/system/repr.nim
@@ -299,18 +299,19 @@ when not defined(useNimRtl):
       add result, "(invalid data!)"
     inc(cl.recdepth)
 
-proc reprOpenArray(p: pointer, length: int, elemtyp: PNimType): string {.
-                   compilerRtl.} =
-  var
-    cl: ReprClosure
-  initReprClosure(cl)
-  result = "["
-  var bs = elemtyp.size
-  for i in 0..length - 1:
-    if i > 0: add result, ", "
-    reprAux(result, cast[pointer](cast[ByteAddress](p) + i*bs), elemtyp, cl)
-  add result, "]"
-  deinitReprClosure(cl)
+when not defined(useNimRtl):
+  proc reprOpenArray(p: pointer, length: int, elemtyp: PNimType): string {.
+                     compilerRtl.} =
+    var
+      cl: ReprClosure
+    initReprClosure(cl)
+    result = "["
+    var bs = elemtyp.size
+    for i in 0..length - 1:
+      if i > 0: add result, ", "
+      reprAux(result, cast[pointer](cast[ByteAddress](p) + i*bs), elemtyp, cl)
+    add result, "]"
+    deinitReprClosure(cl)
 
 when not defined(useNimRtl):
   proc reprAny(p: pointer, typ: PNimType): string =