Nim sets and C flags have a different byte representation, use another type to distinguish between both.
Example [https://github.com/numforge/laser/blob/d1e6ae61/laser/photon_jit/photon_osalloc.nim#L50-L61](https://github.com/numforge/laser/blob/d1e6ae61/laser/photon_jit/photon_osalloc.nim#L50-L61) type MemProt* {.size: cint.sizeof.} = enum # is *not* a flag on Win32! ProtRead = 1 # Page can be read ProtWrite = 2 # Page can be written ProtExec = 4 # Page can be executed type Flag*[E: enum] = distinct cint func flag*[E: enum](e: varargs[E]): Flag[E] {.inline.} = ## Enum should only have power of 2 fields # static: # for val in E: # assert (ord(val) and (ord(val) - 1)) == 0, "Enum values should all be power of 2, found " & # $val & " with value " & $ord(val) & "." var flags = 0 for val in e: flags = flags or ord(val) result = Flag[E](flags) proc mmap*( adr: pointer, len: int, prot: Flag[MemProt], flags: Flag[MemMap], file_descriptor: cint, # -1 for anonymous memory offset: cint # Offset in the file descriptor, PageSize aligned. Return Offset ): pointer {.header: "<sys/mman.h>", sideeffect.} ## The only portable address adr is "nil" to let OS decide ## where to alloc ## Returns -1 if error proc mprotect*(adr: pointer, len: int, prot: Flag[MemProt]) {.header: "<sys/mman.h>", sideeffect.} ## len should be a multiple of PageSize ## replace previously existing protection with a set of new ones ## If an access is disallowed, program will segfault Run Also regarding low-level types, Nim offers bitfields with the same representation as C bitfields [https://nim-lang.org/docs/manual.html#implementation-specific-pragmas-bitsize-pragma](https://nim-lang.org/docs/manual.html#implementation-specific-pragmas-bitsize-pragma)