fixes #8405: -d:useNimRtl now works even when {.rtl.} procs are used at compile time; CTFFI now works with {dynlib} (#11635)

This commit is contained in:
Timothee Cour 2019-07-03 14:57:52 -07:00 • committed by Andreas Rumpf
commit 64168d4aea
5 changed files with 68 additions and 61 deletions

View file

@ -1863,7 +1863,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
" operator has to be enabled with {.experimental: \"callOperator\".}") " operator has to be enabled with {.experimental: \"callOperator\".}")
if n.sons[bodyPos].kind != nkEmpty and sfError notin s.flags: 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: if sfBorrow in s.flags:
localError(c.config, n.sons[bodyPos].info, errImplOfXNotAllowed % s.name.s) localError(c.config, n.sons[bodyPos].info, errImplOfXNotAllowed % s.name.s)
let usePseudoGenerics = kind in {skMacro, skTemplate} let usePseudoGenerics = kind in {skMacro, skTemplate}
@ -1881,12 +1881,11 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
c.p.wasForwarded = proto != nil c.p.wasForwarded = proto != nil
maybeAddResult(c, s, n) maybeAddResult(c, s, n)
if lfDynamicLib notin s.loc.flags: # semantic checking also needed with importc in case used in VM
# no semantic checking for importc: s.ast[bodyPos] = hloBody(c, semProcBody(c, n.sons[bodyPos]))
s.ast[bodyPos] = hloBody(c, semProcBody(c, n.sons[bodyPos])) # unfortunately we cannot skip this step when in 'system.compiles'
# unfortunately we cannot skip this step when in 'system.compiles' # context as it may even be evaluated in 'system.compiles':
# context as it may even be evaluated in 'system.compiles': trackProc(c, s, s.ast[bodyPos])
trackProc(c, s, s.ast[bodyPos])
if s.kind == skMethod: semMethodPrototype(c, s, n) if s.kind == skMethod: semMethodPrototype(c, s, n)
else: else:
if (s.typ.sons[0] != nil and kind != skIterator) or kind == skMacro: 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) fixupInstantiatedSymbols(c, s)
if s.kind == skMethod: semMethodPrototype(c, s, n) if s.kind == skMethod: semMethodPrototype(c, s, n)
if sfImportc in s.flags: if sfImportc in s.flags:
# so we just ignore the body after semantic checking for importc: # don't ignore the body in case used in VM
n.sons[bodyPos] = c.graph.emptyNode # n.sons[bodyPos] = c.graph.emptyNode
discard
popProcCon(c) popProcCon(c)
else: else:
if s.kind == skMethod: semMethodPrototype(c, s, n) if s.kind == skMethod: semMethodPrototype(c, s, n)

View file

@ -1082,12 +1082,15 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[pointer](regs), VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[pointer](regs),
currentException: c.currentExceptionA, currentException: c.currentExceptionA,
currentLineInfo: c.debug[pc])) currentLineInfo: c.debug[pc]))
elif sfImportc in prc.flags: elif importcCond(prc):
if compiletimeFFI notin c.config.features: if compiletimeFFI notin c.config.features:
globalError(c.config, c.debug[pc], "VM not allowed to do FFI, see `compiletimeFFI`") 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 # we pass 'tos.slots' instead of 'regs' so that the compiler can keep
# 'regs' in a register: # 'regs' in a register:
when hasFFI: 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] let prcValue = c.globals.sons[prc.position-1]
if prcValue.kind == nkEmpty: if prcValue.kind == nkEmpty:
globalError(c.config, c.debug[pc], "cannot run " & prc.name.s) globalError(c.config, c.debug[pc], "cannot run " & prc.name.s)

View file

@ -1544,8 +1544,11 @@ proc genTypeLit(c: PCtx; t: PType; dest: var TDest) =
n.typ = t n.typ = t
genLit(c, n, dest) genLit(c, n, dest)
proc importcCond(s: PSym): bool {.inline.} = proc importcCond*(s: PSym): bool {.inline.} =
sfImportc in s.flags and (lfDynamicLib notin s.loc.flags or s.ast == nil) ## 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) = proc importcSym(c: PCtx; info: TLineInfo; s: PSym) =
when hasFFI: when hasFFI:
@ -1553,7 +1556,8 @@ proc importcSym(c: PCtx; info: TLineInfo; s: PSym) =
c.globals.add(importcSymbol(c.config, s)) c.globals.add(importcSymbol(c.config, s))
s.position = c.globals.len s.position = c.globals.len
else: 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: else:
localError(c.config, info, localError(c.config, info,
"cannot 'importc' variable at compile time; " & s.name.s) "cannot 'importc' variable at compile time; " & s.name.s)

View file

@ -366,43 +366,42 @@ proc next*(p: var OptParser) {.rtl, extern: "npo$1".} =
inc p.idx inc p.idx
p.pos = 0 p.pos = 0
when declared(os.paramCount): proc cmdLineRest*(p: OptParser): TaintedString {.rtl, extern: "npo$1".} =
proc cmdLineRest*(p: OptParser): TaintedString {.rtl, extern: "npo$1".} = ## Retrieves the rest of the command line that has not been parsed yet.
## Retrieves the rest of the command line that has not been parsed yet. ##
## ## See also:
## See also: ## * `remainingArgs proc<#remainingArgs,OptParser>`_
## * `remainingArgs proc<#remainingArgs,OptParser>`_ ##
## ## **Examples:**
## **Examples:** ##
## ## .. code-block::
## .. code-block:: ## var p = initOptParser("--left -r:2 -- foo.txt bar.txt")
## var p = initOptParser("--left -r:2 -- foo.txt bar.txt") ## while true:
## while true: ## p.next()
## p.next() ## if p.kind == cmdLongOption and p.key == "": # Look for "--"
## if p.kind == cmdLongOption and p.key == "": # Look for "--" ## break
## break ## else: continue
## else: continue ## doAssert p.cmdLineRest == "foo.txt bar.txt"
## doAssert p.cmdLineRest == "foo.txt bar.txt" result = p.cmds[p.idx .. ^1].quoteShellCommand.TaintedString
result = p.cmds[p.idx .. ^1].quoteShellCommand.TaintedString
proc remainingArgs*(p: OptParser): seq[TaintedString] {.rtl, extern: "npo$1".} = proc remainingArgs*(p: OptParser): seq[TaintedString] {.rtl, extern: "npo$1".} =
## Retrieves a sequence of the arguments that have not been parsed yet. ## Retrieves a sequence of the arguments that have not been parsed yet.
## ##
## See also: ## See also:
## * `cmdLineRest proc<#cmdLineRest,OptParser>`_ ## * `cmdLineRest proc<#cmdLineRest,OptParser>`_
## ##
## **Examples:** ## **Examples:**
## ##
## .. code-block:: ## .. code-block::
## var p = initOptParser("--left -r:2 -- foo.txt bar.txt") ## var p = initOptParser("--left -r:2 -- foo.txt bar.txt")
## while true: ## while true:
## p.next() ## p.next()
## if p.kind == cmdLongOption and p.key == "": # Look for "--" ## if p.kind == cmdLongOption and p.key == "": # Look for "--"
## break ## break
## else: continue ## else: continue
## doAssert p.remainingArgs == @["foo.txt", "bar.txt"] ## doAssert p.remainingArgs == @["foo.txt", "bar.txt"]
result = @[] result = @[]
for i in p.idx..<p.cmds.len: result.add TaintedString(p.cmds[i]) 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] = iterator getopt*(p: var OptParser): tuple[kind: CmdLineKind, key, val: TaintedString] =
## Convenience iterator for iterating over the given ## Convenience iterator for iterating over the given

View file

@ -299,18 +299,19 @@ when not defined(useNimRtl):
add result, "(invalid data!)" add result, "(invalid data!)"
inc(cl.recdepth) inc(cl.recdepth)
proc reprOpenArray(p: pointer, length: int, elemtyp: PNimType): string {. when not defined(useNimRtl):
compilerRtl.} = proc reprOpenArray(p: pointer, length: int, elemtyp: PNimType): string {.
var compilerRtl.} =
cl: ReprClosure var
initReprClosure(cl) cl: ReprClosure
result = "[" initReprClosure(cl)
var bs = elemtyp.size result = "["
for i in 0..length - 1: var bs = elemtyp.size
if i > 0: add result, ", " for i in 0..length - 1:
reprAux(result, cast[pointer](cast[ByteAddress](p) + i*bs), elemtyp, cl) if i > 0: add result, ", "
add result, "]" reprAux(result, cast[pointer](cast[ByteAddress](p) + i*bs), elemtyp, cl)
deinitReprClosure(cl) add result, "]"
deinitReprClosure(cl)
when not defined(useNimRtl): when not defined(useNimRtl):
proc reprAny(p: pointer, typ: PNimType): string = proc reprAny(p: pointer, typ: PNimType): string =