Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compile-time usage of parts of strutils fails when using -d:useNimRtl #8405

Closed
awr1 opened this issue Jul 23, 2018 · 5 comments

Comments

@awr1
Copy link
Contributor

commented Jul 23, 2018

import strutils

const a = "abc" in "abcdef"
echo(a)

console output:

c:/nimtests $ nim c -d:useNimRtl conststr.nim
Hint: used config file 'c:\Nim\config\nim.cfg' [Conf]
Hint: system [Processing]
Hint: conststr [Processing]
Hint: strutils [Processing]
Hint: parseutils [Processing]
Hint: math [Processing]
Hint: bitops [Processing]
Hint: algorithm [Processing]
Hint: unicode [Processing]
lib\pure\strutils.nim(1501, 10) Error: cannot 'importc' variable at compile time

Numerous procs in strutils have the same problem, e.g. contains and toUpperASCII. We should not be trying to link to nimrtl in matters of compile-time evaluation (as far as most everything in strutils is concerned).

@Araq

This comment has been minimized.

Copy link
Member

commented Jul 23, 2018

Yeah, I know about this problem too, but I fail to see a solution. If you link dynamically, why can we assume the current version is fine for compiletime evaluation?

@awr1

This comment has been minimized.

Copy link
Contributor Author

commented Aug 26, 2018

Is there a way of fixing something like this with when nimvm? I took a crack at it but, while it "fixed" the issue, it ended up not producing exports for the functions in nimrtl upon closer inspection. Not technically ideal. Also worth mentioning that in the docs it isn't made obvious that nimrtl is the complete standard library beyond the GC manager. Perahaps an option to build a stripped-down nimrtl - "mini_nimrtl" - containing just the GC might be nice? IDK.

Currently I have a personal project I've been working on that uses a fork of the standard library with the {.rtl.} pragma removed in strutils and elsewhere.

@ccll

This comment has been minimized.

Copy link

commented Sep 3, 2018

Being blocked by this one while modeling a DLL based plugin system.
Any workarounds (except hacking the standard library)?

Or:
What are the consequences if I load multiple Nim DLLs compiled without '-d:useNimRtl'?

My best guess is some ref object created by DLL A could be collected in a different DLL B?
Is this a problem if I can make sure that DLL A and DLL B are using the same version of Nim stdlib?

@Araq

This comment has been minimized.

Copy link
Member

commented May 22, 2019

Thas has been fixed.

@Araq Araq closed this May 22, 2019

@timotheecour

This comment has been minimized.

Copy link
Contributor

commented Jul 1, 2019

can we reopen this or add explanations on how this was fixed? The original post still gives compile time error:

nim c -r -d:useNimRtl --skipUserCfg --skipParentCfg main.nim

Error: VM not allowed to do FFI, see `compiletimeFFI`

Likewise when using any proc marked with {.rtl.} at compile time, making rtl (and therefore shared libraries) unusable in lots of cases (as soon as a rtl proc is used at compile time, which covers a lot of basic procs; eg simply import pkg/regex will fail with -d:useNimRtl)
(verified with nim 0.20 or latest devel e7471ce)

As explained in #10150 (comment), #10150 helps but doesn't quite fix #8405 because there are still unhandled cases of type mappings in mapType; eg Natural, tyRange, distinct aren't mapped, and returning string isn't correct currently. I've done more work (in private fork) to improve CTFFI support but as of now nim devel doesn't handle those cases; so even with ctfii enabled, the above example still fails.

The correct fix IMO is to ignore {.importc.} pragma when the proc has a body and is used at compile time (or ignore when a pragma vmignoreimportc is given; which would be added to rtl pragma). I tried defining a macro rtl that could be used as a pragma to replace{.rtl.} as follows:

  macro rtl(fun: untyped) =
    result = fun
    let funBody = result[6]
    let ret = result[3][0]
    let isVoid = ret.kind == nnkEmpty # TODO: handle `void` return, auto etc
    let fun0 = $(fun[0])
    let fun2 = copy(fun)
    fun2[0] = ident"funImpl"
    fun2[6] = newEmptyNode()
    fun2[4] = newTree(nnkPragma, newTree(nnkExprColonExpr,ident"importc", newLit fun0))
    let call = newCall(fun2[0])
    for ai in result[3][1..^1]:
      call.add ai[0]
    let retAux = quote do:
      when nimvm:
        `funBody`
      else:
        `fun2`
        `call`

    result[6] = if isVoid:
      newTree(nnkAsgn, ident"result", retAux)
    else:
      retAux

which, when used as follows:

proc fun2(a0: int; a1 = "bar"): int {.rtl.} =
  1 + 2

produces:

proc fun2(a0: int; a1 = "bar"): int =
  when nimvm:
    1 + 2
  else:
    proc funImpl(a0: int; a1 = "bar"): int {.importc: "fun2".}
    funImpl(a0, a1)

however, that doesn't work (yet, at least, help welcome), for eg {.rtl.} is used in places where std/macros isn't defined (std/macros itself includes inclrtl.nim); furthermore, this really should be handled by the compiler instead (which has more context, etc; eg would avoid having to use nimvm or guessing whether the proc returns void)

slimmer rtl

as mentioned in #8405 (comment), I wonder why rtl isn't limited to just the gc parts instead of additional procs scattered in strutils etc; at the very least there should be an option for a mini_nimrtl that would do that, as mentioned by @awr1

timotheecour added a commit to timotheecour/Nim that referenced this issue Jul 2, 2019

timotheecour added a commit to timotheecour/Nim that referenced this issue Jul 3, 2019

Araq added a commit that referenced this issue Jul 3, 2019

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

narimiran added a commit that referenced this issue Jul 8, 2019

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

(cherry picked from commit 64168d4)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.