From 6e453cf0a29718a9c5e825bf6eff9eda948b7eab Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Mon, 1 Jul 2019 21:43:23 -0700 Subject: [PATCH] fix #8405: -d:useNimRtl does not prevent using procs at CT --- compiler/semstmts.nim | 11 ++++--- compiler/vm.nim | 5 ++- compiler/vmgen.nim | 6 ++++ lib/pure/parseopt.nim | 71 +++++++++++++++++++++---------------------- lib/system/repr.nim | 25 +++++++-------- 5 files changed, 64 insertions(+), 54 deletions(-) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 68da6d3b2be4c..a2c9fa676a7e6 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,8 +1881,8 @@ 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: + if lfDynamicLib notin s.loc.flags or n.sons[bodyPos] != nil: + # semantic checking for importc needed 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': @@ -1899,8 +1899,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 2919e865a1167..a8a63be7a621d 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 shouldImportcSymbol(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 08d79bbb78ef6..b3037e6b038a0 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1547,6 +1547,12 @@ proc genTypeLit(c: PCtx; t: PType; dest: var TDest) = proc importcCond(s: PSym): bool {.inline.} = sfImportc in s.flags and (lfDynamicLib notin s.loc.flags or s.ast == nil) +proc shouldImportcSymbol*(s: PSym): bool = + ## return true to importc `s`, false to execute its body instead (refs #8405) + if sfImportc in s.flags: + assert s.kind == skProc + return s.ast.sons[bodyPos].kind == nkEmpty + proc importcSym(c: PCtx; info: TLineInfo; s: PSym) = when hasFFI: if compiletimeFFI in c.config.features: diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim index fab32060a0e2f..545f9f00aae01 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..`_ + ## + ## **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.. 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 =