I'd like to check that some "memory location" is annotated with {.volatile.}, to make sure my code only compiles, if I use {.volatile.} in the right place. I searc the lib code but didn't really find much, except this (asyncmacro.nim):
proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
# ...
# LINE NO: 385
# If proc has an explicit gcsafe pragma, we add it to iterator as well.
if prc.pragma.findChild(it.kind in {nnkSym, nnkIdent} and $it == "gcsafe") != nil:
closureIterator.addPragma(newIdentNode("gcsafe"))
I gave it a try, but did not get very far, as I'm still "practicing" the language itself, and haven't learned (or more precisely already forgot), how the meta-programming works.
Here is what I tried:
import macros, strutils
type
VolatilePtr*[T] = distinct ptr T
# Means it's a pointer to some volatile value
proc hasAnnotation(stuff: NimNode, annotation: static[string]): bool {.compileTime.} =
(stuff.pragma.findChild(it.kind in {nnkSym, nnkIdent} and $it == annotation) != nil)
template toVolatilePtr*[T](t: untyped) =
when hasAnnotation(t, "volatile"):
VolatilePtr[T](addr t)
else:
{.error: "t is not volatile!".}
when isMainModule:
var tua = 42'i32
let p: VolatilePtr[int32] = toVolatilePtr[int32](tua)
let tua2: int32 = 42'i32 #atomicLoadNSeqCST[int32](p)
assert(tua2 == tua)