Skip to content

Top-level volatileLoad/volatileStore leads to invalid codegen #14623

@exelotl

Description

@exelotl

When calling volatileLoad/volatileStore at the top level, the {.emit.}'d code goes at the top level in the generated C code, where it really should go in the module's init function, to be executed at runtime.

Example

import volatile

let REG_DEBUG_ENABLE = cast[ptr uint16](0x4FFF780)
volatileStore(REG_DEBUG_ENABLE, 0xC0DE)

var a: int
a = 123

Current Output

...
Hint: test1 [Processing]
Hint: volatile [Processing]
CC: stdlib_system.nim
CC: test1.nim
/home/exelotl/nim/test/nimcache/@mtest1.nim.c:25:4: error: expected identifier or ‘(’ before ‘NU16’
   25 | *((NU16 volatile*)(REG_DEBUG_ENABLE__khri9ceh1x2KIEd5doOjFrg)) = ((NI) 49374);
      |    ^~~~
/home/exelotl/nim/test/nimcache/@mtest1.nim.c:25:19: error: expected ‘)’ before ‘(’ token
   25 | *((NU16 volatile*)(REG_DEBUG_ENABLE__khri9ceh1x2KIEd5doOjFrg)) = ((NI) 49374);
      |                   ^
      |                   )
Error: execution of an external compiler program 'gcc -c  -w   -I/home/exelotl/.choosenim/toolchains/nim-1.2.0/lib -I/home/exelotl/nim/test -o /home/exelotl/nim/test/nimcache/@mtest1.nim.c.o /home/exelotl/nim/test/nimcache/@mtest1.nim.c' failed with exit code: 1

Generated C code:

...
#undef powerpc
#undef unix
#define nimfr_(x, y)
#define nimln_(x, y)
*((NU16 volatile*)(REG_DEBUG_ENABLE__khri9ceh1x2KIEd5doOjFrg)) = ((NI) 49374);
static N_INLINE(void, initStackBottomWith)(void* locals);
N_LIB_PRIVATE N_NOINLINE(void, nimGC_setStackBottom)(void* theStackBottom);
N_LIB_PRIVATE N_NIMCALL(void, systemDatInit000)(void);
N_LIB_PRIVATE N_NIMCALL(void, systemInit000)(void);
...
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void) {
{
	a__Aq9aygSlXJ6MYmHZ6kpikbw = ((NI) 123);
}
}

Expected Output

Program should compile, generated C code should look like:

...
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void) {
{
	*((NU16 volatile*)(REG_DEBUG_ENABLE__khri9ceh1x2KIEd5doOjFrg)) = ((NI) 49374);
	a__Aq9aygSlXJ6MYmHZ6kpikbw = ((NI) 123);
}
}

Possible Solutions

a) Use magic for volatileLoad/volatileStore?
b) Use procs instead of templates, and hope the C compiler will inline them?
c) Add a new /*FOOSECTION*/ prefix for the {.emit.} pragma, which causes the generated code to go in the correct place in the module's init function?

$ nim -v
Nim Compiler Version 1.2.0 [Linux: amd64]

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions