summary refs log tree commit diff stats
path: root/compiler/vm.nim
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-11-25 13:04:11 +0100
committerAraq <rumpf_a@web.de>2013-11-25 13:04:11 +0100
commit9035d15ed22de1f80486d94ec63e720a4d04cbc0 (patch)
tree0f6f4f58d598c7905ef0ab32d90afca385c82401 /compiler/vm.nim
parent4cda0861f507c414bfd622a1f759353c2c623941 (diff)
downloadNim-9035d15ed22de1f80486d94ec63e720a4d04cbc0.tar.gz
next steps for FFI support
Diffstat (limited to 'compiler/vm.nim')
-rw-r--r--compiler/vm.nim58
1 files changed, 38 insertions, 20 deletions
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 1596e4220..019397bbc 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -14,10 +14,13 @@ import ast except getstr
 
 import
   strutils, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, unsigned,
-  parser, vmdeps, idents, trees, renderer
+  parser, vmdeps, idents, trees, renderer, options
 
 from semfold import leValueConv, ordinalValToString
 
+when hasFFI:
+  import evalffi
+
 type
   PStackFrame* = ref TStackFrame
   TStackFrame* = object
@@ -608,24 +611,39 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
       let rc = instr.regC
       let isClosure = regs[rb].kind == nkPar
       let prc = if not isClosure: regs[rb].sym else: regs[rb].sons[0].sym
-      let newPc = compile(c, prc)
-      #echo "new pc ", newPc, " calling: ", prc.name.s
-      var newFrame = PStackFrame(prc: prc, comesFrom: pc, next: tos)
-      newSeq(newFrame.slots, prc.position)
-      if not isEmptyType(prc.typ.sons[0]):
-        newFrame.slots[0] = getNullValue(prc.typ.sons[0], prc.info)
-      # pass every parameter by var (the language definition allows this):
-      for i in 1 .. rc-1:
-        newFrame.slots[i] = regs[rb+i]
-      if isClosure:
-        newFrame.slots[rc] = regs[rb].sons[1]
-      # allocate the temporaries:
-      for i in rc+ord(isClosure) .. <prc.position:
-        newFrame.slots[i] = newNode(nkEmpty)
-      tos = newFrame
-      move(regs, newFrame.slots)
-      # -1 for the following 'inc pc'
-      pc = newPc-1
+      if sfImportc in prc.flags:
+        if allowFFI notin c.features:
+          globalError(c.debug[pc], errGenerated, "VM not allowed to do FFI")
+        # we pass 'tos.slots' instead of 'regs' so that the compiler can keep
+        # 'regs' in a register:
+        when hasFFI:
+          let newValue = callForeignFunction(c.globals.sons[prc.position-1],
+                                             prc.typ, tos.slots,
+                                             rb+1, rc-1, c.debug[pc])
+          if newValue.kind != nkEmpty:
+            assert instr.opcode == opcIndCallAsgn
+            regs[ra] = newValue
+        else:
+          globalError(c.debug[pc], errGenerated, "VM not built with FFI support")
+      else:
+        let newPc = compile(c, prc)
+        #echo "new pc ", newPc, " calling: ", prc.name.s
+        var newFrame = PStackFrame(prc: prc, comesFrom: pc, next: tos)
+        newSeq(newFrame.slots, prc.offset)
+        if not isEmptyType(prc.typ.sons[0]):
+          newFrame.slots[0] = getNullValue(prc.typ.sons[0], prc.info)
+        # pass every parameter by var (the language definition allows this):
+        for i in 1 .. rc-1:
+          newFrame.slots[i] = regs[rb+i]
+        if isClosure:
+          newFrame.slots[rc] = regs[rb].sons[1]
+        # allocate the temporaries:
+        for i in rc+ord(isClosure) .. <prc.offset:
+          newFrame.slots[i] = newNode(nkEmpty)
+        tos = newFrame
+        move(regs, newFrame.slots)
+        # -1 for the following 'inc pc'
+        pc = newPc-1
     of opcTJmp:
       # jump Bx if A != 0
       let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
@@ -1054,7 +1072,7 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
   let start = genProc(c, sym)
 
   var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil)
-  let maxSlots = sym.position
+  let maxSlots = sym.offset
   newSeq(tos.slots, maxSlots)
   # setup arguments:
   var L = n.safeLen