I am using Nim on embedded system, so RAM is quite precious.
If we do following in C:
const int a[] = {1,2,3};
a will be stored in ROM, and no RAM is consumed.
While in Nim, if we declare it in a let statement:
let a = [1,2,3]
a will be allocated in RAM, and its content is initialized (copied from ROM) in startup. If we declare it in a const statement, then we are not allowed to get its address. But I need this address to call other C functions.
For C backend, is it possible to make let variables read-only and eliminate the copy operation?
I'm pretty sure I saw a proposition somewhere (IRC?) to have some {.rodata.} pragma or similar to ensure let globals are in a specific segment of the binary.
Otherwise, this is related: https://github.com/nim-lang/Nim/issues/12216.
Did you check where the data is put with
let a {.compiletime.}= [1,2,3]
You can always workaround this by creating a nice macro which will generate something like:
{.emit: """
const int a[] = {1,2,3};
""".}
Then, I need to import this C var into nim? This does not look like a good idea.
Yeahh, in my project I'm using this pattern all over the place, because it's basically the only option right now. It works but it's cumbersome, I'm looking forward to the day when Nim has a proper solution to this.
I think implementing a {.readonly.} pragma for let variables is the best course of action. Having the compiler auto-detect cases where the readonly codegen can be applied would be a nice extra, but I don't think it really adds much. As embedded users, I think we would prefer to be explicit about these things, right?
At some point Araq said "You write an RFC, we implement it." so I did, but then that changed to "you implement it" which uh, I'm not against trying but I don't think I can find the time for it right now. If someone more experienced with the Nim codebase could take over and get this done, I'd really appreciate it.
I am following your RFC.
In my opinion, let variables are already "readonly" once they got assigned. {.readonly.} pragma seems a little bit redundant. The problem here is that, from the perspective of nim compiler, when to initialize let variables? While some can be initialized in compile time in C, there are also some that must be initialized in run time. Based on this, {.compileTime.} seems to be a solution, but its effects is that variables are initialized in each function they are used.
Treatment of {.compileTime.} is problematic. A let variable marked as {.compileTime.} means its content can be determined at compile time. So, they are fully possible to be compiled into const data in C.
So, my suggestion is to polish the handling of {.compileTime.}.
Correct me if I am wrong.