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.nim42
1 files changed, 33 insertions, 9 deletions
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 332184e0d..46edad2cd 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -11,7 +11,10 @@
 
 import
   unsigned, strutils, ast, astalgo, types, msgs, renderer, vmdef, 
-  trees, intsets, rodread, magicsys
+  trees, intsets, rodread, magicsys, options
+
+when hasFFI:
+  import evalffi
 
 proc codeListing(c: PCtx, result: var string) =
   # first iteration: compute all necessary labels:
@@ -395,9 +398,14 @@ proc genReturn(c: PCtx; n: PNode) =
 proc genCall(c: PCtx; n: PNode; dest: var TDest) =
   if dest < 0 and not isEmptyType(n.typ): dest = getTemp(c, n.typ)
   let x = c.getTempRange(n.len, slotTempUnknown)
-  for i in 0.. <n.len: 
+  # varargs need 'opcSetType' for the FFI support:
+  let fntyp = n.sons[0].typ
+  for i in 0.. <n.len:
     var r: TRegister = x+i
     c.gen(n.sons[i], r)
+    if i >= fntyp.len:
+      internalAssert tfVarargs in fntyp.flags
+      c.gABx(n, opcSetType, r, c.genType(n.sons[i].typ))
   if dest < 0:
     c.gABC(n, opcIndCall, 0, x, n.len)
   else:
@@ -884,13 +892,26 @@ proc genLit(c: PCtx; n: PNode; dest: var TDest) =
   let lit = genLiteral(c, n)
   c.gABx(n, opc, dest, lit)
 
+proc importcSym(c: PCtx; info: TLineInfo; s: PSym) =
+  when hasFFI:
+    if allowFFI in c.features:
+      c.globals.add(importcSymbol(s))
+      s.position = c.globals.len
+    else:
+      localError(info, errGenerated, "VM is not allowed to 'importc'")
+  else:
+    localError(info, errGenerated,
+               "cannot 'importc' variable at compile time")
+
 proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
   let s = n.sym
   if sfGlobal in s.flags:
     if dest < 0: dest = c.getTemp(s.typ)
     if s.position == 0:
-      c.globals.add(s.ast)
-      s.position = c.globals.len
+      if sfImportc in s.flags: c.importcSym(n.info, s)
+      else:
+        c.globals.add(s.ast)
+        s.position = c.globals.len
       # XXX var g = codeHere() ?
     c.gABx(n, opcLdGlobal, dest, s.position)
   else:
@@ -1003,9 +1024,11 @@ proc genVarSection(c: PCtx; n: PNode) =
       let s = a.sons[0].sym
       if sfGlobal in s.flags:
         if s.position == 0:
-          let sa = if s.ast.isNil: getNullValue(s.typ, a.info) else: s.ast
-          c.globals.add(sa)
-          s.position = c.globals.len
+          if sfImportc in s.flags: c.importcSym(a.info, s)
+          else:
+            let sa = if s.ast.isNil: getNullValue(s.typ, a.info) else: s.ast
+            c.globals.add(sa)
+            s.position = c.globals.len
         if a.sons[2].kind == nkEmpty:
           when false:
             withTemp(tmp, s.typ):
@@ -1103,6 +1126,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest) =
     of skVar, skForVar, skTemp, skLet, skParam, skResult:
       genRdVar(c, n, dest)
     of skProc, skConverter, skMacro, skMethod, skIterator:
+      if sfImportc in s.flags: c.importcSym(n.info, s)
       genLit(c, n, dest)
     of skConst:
       gen(c, s.ast, dest)
@@ -1317,11 +1341,11 @@ proc genProc(c: PCtx; s: PSym): int =
     c.patch(procStart)
     c.gABC(body, opcEof, eofInstr.regA)
     c.optimizeJumps(result)
-    s.position = c.prc.maxSlots
+    s.offset = c.prc.maxSlots
     #if s.name.s == "innerProc":
     #  c.echoCode
     #  echo renderTree(body)
     c.prc = oldPrc
   else:
-    c.prc.maxSlots = s.position
+    c.prc.maxSlots = s.offset
     result = x.intVal.int