vm: FFI improvements
This commit is contained in:
parent
4447c1b7e3
commit
32ef1f8f32
6 changed files with 56 additions and 28 deletions
|
|
@ -41,6 +41,8 @@ proc getDll(cache: var TDllCache; dll: string; info: TLineInfo): pointer =
|
||||||
const
|
const
|
||||||
nkPtrLit = nkIntLit # hopefully we can get rid of this hack soon
|
nkPtrLit = nkIntLit # hopefully we can get rid of this hack soon
|
||||||
|
|
||||||
|
var myerrno {.importc: "errno", header: "<errno.h>".}: cint ## error variable
|
||||||
|
|
||||||
proc importcSymbol*(sym: PSym): PNode =
|
proc importcSymbol*(sym: PSym): PNode =
|
||||||
let name = ropeToStr(sym.loc.r)
|
let name = ropeToStr(sym.loc.r)
|
||||||
|
|
||||||
|
|
@ -51,6 +53,7 @@ proc importcSymbol*(sym: PSym): PNode =
|
||||||
of "stdin": result.intVal = cast[TAddress](system.stdin)
|
of "stdin": result.intVal = cast[TAddress](system.stdin)
|
||||||
of "stdout": result.intVal = cast[TAddress](system.stdout)
|
of "stdout": result.intVal = cast[TAddress](system.stdout)
|
||||||
of "stderr": result.intVal = cast[TAddress](system.stderr)
|
of "stderr": result.intVal = cast[TAddress](system.stderr)
|
||||||
|
of "vmErrnoWrapper": result.intVal = cast[TAddress](myerrno)
|
||||||
else:
|
else:
|
||||||
let lib = sym.annex
|
let lib = sym.annex
|
||||||
if lib != nil and lib.path.kind notin {nkStrLit..nkTripleStrLit}:
|
if lib != nil and lib.path.kind notin {nkStrLit..nkTripleStrLit}:
|
||||||
|
|
|
||||||
|
|
@ -945,10 +945,7 @@ proc genTypeLit(c: PCtx; t: PType; dest: var TDest) =
|
||||||
proc importcSym(c: PCtx; info: TLineInfo; s: PSym) =
|
proc importcSym(c: PCtx; info: TLineInfo; s: PSym) =
|
||||||
when hasFFI:
|
when hasFFI:
|
||||||
if allowFFI in c.features:
|
if allowFFI in c.features:
|
||||||
if s.kind == skVar and lfNoDecl in s.loc.flags:
|
c.globals.add(importcSymbol(s))
|
||||||
c.globals.add(copyNode(emptyNode))
|
|
||||||
else:
|
|
||||||
c.globals.add(importcSymbol(s))
|
|
||||||
s.position = c.globals.len
|
s.position = c.globals.len
|
||||||
else:
|
else:
|
||||||
localError(info, errGenerated, "VM is not allowed to 'importc'")
|
localError(info, errGenerated, "VM is not allowed to 'importc'")
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,10 @@ proc `..`*[T](b: T): TSlice[T] {.noSideEffect, inline.} =
|
||||||
when not defined(niminheritable):
|
when not defined(niminheritable):
|
||||||
{.pragma: inheritable.}
|
{.pragma: inheritable.}
|
||||||
|
|
||||||
when not defined(JS) and not defined(NimrodVM):
|
const NoFakeVars* = defined(NimrodVM) ## true if the backend doesn't support \
|
||||||
|
## "fake variables" like 'var EBADF {.importc.}: cint'.
|
||||||
|
|
||||||
|
when not defined(JS):
|
||||||
type
|
type
|
||||||
TGenericSeq {.compilerproc, pure, inheritable.} = object
|
TGenericSeq {.compilerproc, pure, inheritable.} = object
|
||||||
len, reserved: int
|
len, reserved: int
|
||||||
|
|
@ -195,7 +198,8 @@ when not defined(JS) and not defined(NimrodVM):
|
||||||
NimStringDesc {.compilerproc, final.} = object of TGenericSeq
|
NimStringDesc {.compilerproc, final.} = object of TGenericSeq
|
||||||
data: array[0..100_000_000, char]
|
data: array[0..100_000_000, char]
|
||||||
NimString = ptr NimStringDesc
|
NimString = ptr NimStringDesc
|
||||||
|
|
||||||
|
when not defined(JS) and not defined(NimrodVM):
|
||||||
template space(s: PGenericSeq): int {.dirty.} =
|
template space(s: PGenericSeq): int {.dirty.} =
|
||||||
s.reserved and not seqShallowFlag
|
s.reserved and not seqShallowFlag
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,21 +40,31 @@ var
|
||||||
|
|
||||||
# constants faked as variables:
|
# constants faked as variables:
|
||||||
when not defined(SIGINT):
|
when not defined(SIGINT):
|
||||||
var
|
when NoFakeVars:
|
||||||
SIGINT {.importc: "SIGINT", nodecl.}: cint
|
when defined(windows):
|
||||||
SIGSEGV {.importc: "SIGSEGV", nodecl.}: cint
|
const
|
||||||
SIGABRT {.importc: "SIGABRT", nodecl.}: cint
|
SIGABRT = cint(22)
|
||||||
SIGFPE {.importc: "SIGFPE", nodecl.}: cint
|
SIGFPE = cint(8)
|
||||||
SIGILL {.importc: "SIGILL", nodecl.}: cint
|
SIGILL = cint(4)
|
||||||
|
SIGINT = cint(2)
|
||||||
|
SIGSEGV = cint(11)
|
||||||
|
SIGTERM = cint(15)
|
||||||
|
else:
|
||||||
|
{.error: "SIGABRT not ported to your platform".}
|
||||||
|
else:
|
||||||
|
var
|
||||||
|
SIGINT {.importc: "SIGINT", nodecl.}: cint
|
||||||
|
SIGSEGV {.importc: "SIGSEGV", nodecl.}: cint
|
||||||
|
SIGABRT {.importc: "SIGABRT", nodecl.}: cint
|
||||||
|
SIGFPE {.importc: "SIGFPE", nodecl.}: cint
|
||||||
|
SIGILL {.importc: "SIGILL", nodecl.}: cint
|
||||||
|
|
||||||
when defined(macosx):
|
when defined(macosx):
|
||||||
var
|
var
|
||||||
SIGBUS {.importc: "SIGBUS", nodecl.}: cint
|
SIGBUS {.importc: "SIGBUS", nodecl.}: cint
|
||||||
# hopefully this does not lead to new bugs
|
# hopefully this does not lead to new bugs
|
||||||
else:
|
else:
|
||||||
var
|
template SIGBUS: expr = SIGSEGV
|
||||||
SIGBUS {.importc: "SIGSEGV", nodecl.}: cint
|
|
||||||
# only Mac OS X has this shit
|
|
||||||
|
|
||||||
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
|
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
|
||||||
header: "<setjmp.h>", importc: "longjmp".}
|
header: "<setjmp.h>", importc: "longjmp".}
|
||||||
|
|
@ -111,16 +121,22 @@ proc c_realloc(p: pointer, newsize: int): pointer {.
|
||||||
|
|
||||||
when hostOS != "standalone":
|
when hostOS != "standalone":
|
||||||
when not defined(errno):
|
when not defined(errno):
|
||||||
var errno {.importc, header: "<errno.h>".}: cint ## error variable
|
when defined(NimrodVM):
|
||||||
|
var vmErrnoWrapper {.importc.}: ptr cint
|
||||||
|
template errno: expr =
|
||||||
|
bind vmErrnoWrapper
|
||||||
|
vmErrnoWrapper[]
|
||||||
|
else:
|
||||||
|
var errno {.importc, header: "<errno.h>".}: cint ## error variable
|
||||||
proc strerror(errnum: cint): cstring {.importc, header: "<string.h>".}
|
proc strerror(errnum: cint): cstring {.importc, header: "<string.h>".}
|
||||||
|
|
||||||
proc c_remove(filename: CString): cint {.
|
proc c_remove(filename: cstring): cint {.
|
||||||
importc: "remove", header: "<stdio.h>".}
|
importc: "remove", header: "<stdio.h>".}
|
||||||
proc c_rename(oldname, newname: CString): cint {.
|
proc c_rename(oldname, newname: cstring): cint {.
|
||||||
importc: "rename", header: "<stdio.h>".}
|
importc: "rename", header: "<stdio.h>".}
|
||||||
|
|
||||||
proc c_system(cmd: CString): cint {.importc: "system", header: "<stdlib.h>".}
|
proc c_system(cmd: cstring): cint {.importc: "system", header: "<stdlib.h>".}
|
||||||
proc c_getenv(env: CString): CString {.importc: "getenv", header: "<stdlib.h>".}
|
proc c_getenv(env: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".}
|
||||||
proc c_putenv(env: CString): cint {.importc: "putenv", header: "<stdlib.h>".}
|
proc c_putenv(env: cstring): cint {.importc: "putenv", header: "<stdlib.h>".}
|
||||||
|
|
||||||
{.pop}
|
{.pop}
|
||||||
|
|
|
||||||
|
|
@ -45,9 +45,17 @@ proc setvbuf(stream: TFile, buf: pointer, typ, size: cint): cint {.
|
||||||
proc write(f: TFile, c: cstring) = fputs(c, f)
|
proc write(f: TFile, c: cstring) = fputs(c, f)
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
var
|
when NoFakeVars:
|
||||||
IOFBF {.importc: "_IOFBF", nodecl.}: cint
|
when defined(windows):
|
||||||
IONBF {.importc: "_IONBF", nodecl.}: cint
|
const
|
||||||
|
IOFBF = cint(0)
|
||||||
|
IONBF = cint(4)
|
||||||
|
else:
|
||||||
|
{.error: "IOFBF not ported to your platform".}
|
||||||
|
else:
|
||||||
|
var
|
||||||
|
IOFBF {.importc: "_IOFBF", nodecl.}: cint
|
||||||
|
IONBF {.importc: "_IONBF", nodecl.}: cint
|
||||||
|
|
||||||
const
|
const
|
||||||
buf_size = 4000
|
buf_size = 4000
|
||||||
|
|
@ -149,7 +157,7 @@ proc writeFile(filename, content: string) =
|
||||||
finally:
|
finally:
|
||||||
close(f)
|
close(f)
|
||||||
|
|
||||||
proc EndOfFile(f: TFile): bool =
|
proc endOfFile(f: TFile): bool =
|
||||||
# do not blame me; blame the ANSI C standard this is so brain-damaged
|
# do not blame me; blame the ANSI C standard this is so brain-damaged
|
||||||
var c = fgetc(f)
|
var c = fgetc(f)
|
||||||
ungetc(c, f)
|
ungetc(c, f)
|
||||||
|
|
@ -223,10 +231,10 @@ proc fwrite(buf: Pointer, size, n: int, f: TFile): int {.
|
||||||
proc readBuffer(f: TFile, buffer: pointer, len: int): int =
|
proc readBuffer(f: TFile, buffer: pointer, len: int): int =
|
||||||
result = fread(buffer, 1, len, f)
|
result = fread(buffer, 1, len, f)
|
||||||
|
|
||||||
proc ReadBytes(f: TFile, a: var openarray[int8], start, len: int): int =
|
proc readBytes(f: TFile, a: var openarray[int8], start, len: int): int =
|
||||||
result = readBuffer(f, addr(a[start]), len)
|
result = readBuffer(f, addr(a[start]), len)
|
||||||
|
|
||||||
proc ReadChars(f: TFile, a: var openarray[char], start, len: int): int =
|
proc readChars(f: TFile, a: var openarray[char], start, len: int): int =
|
||||||
result = readBuffer(f, addr(a[start]), len)
|
result = readBuffer(f, addr(a[start]), len)
|
||||||
|
|
||||||
{.push stackTrace:off, profiler:off.}
|
{.push stackTrace:off, profiler:off.}
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ proc main =
|
||||||
if not myExec(gen.addFileExt(ExeExt)): quit(1)
|
if not myExec(gen.addFileExt(ExeExt)): quit(1)
|
||||||
else:
|
else:
|
||||||
if not myExec("./" & gen): quit(1)
|
if not myExec("./" & gen): quit(1)
|
||||||
removeFile(addFileExt(gen, "c"))
|
#removeFile(addFileExt(gen, "c"))
|
||||||
echo("Success")
|
echo("Success")
|
||||||
|
|
||||||
proc v(name: string, typ: TTypeKind=cint) =
|
proc v(name: string, typ: TTypeKind=cint) =
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue