I've started to play with LLVM clang. I suddenly run into a problem, which seems strange.
When I use -O0, clang generates calls to memset and memcpy, despite the "-ffreestanding" and "-fno-builtin" flags.
When -O1 used, there are no such calls, but the generated Assembly is just wrong (contains "brk" instruction). Out of curiousity, I've checked it with gcc too. Interestingly -O0 works (gcc 7.2, 7.3, 8.1), and -O1 works for 7.2, 7.3 but not with gcc 8.1, which generates the same bad Assembly code (and not only for AArch64, the x86_64 output is bad too, there it emmits "ud" instruction). Using -O2 breaks with gcc 7.2 and 7.3 too.
Anybody has a workaround here? I think this is clearly a C compiler bug, because:
1. -ffreestanding clearly tells the compiler there's no libc, so it should not rely on memset and memcpy library functions
2. -fno-builtin clearly tells the compiler not to use builtins, like llvm.memset or llvm.memcpy intristics
3. -O0 clearly tells the compiler to compile as-is, do not use any optimisations
4. Optimizer generates bad Assembly with -O1 and above, that's a bug, no doubt. Under no circumstances should a simple ANSI C source compiled into a "brk" (unconditional machine exception) instruction
After googling half a day, I was unable to find a solution, but maybe someone here with more experience on clang and bare metal knows a workaround? Maybe there is a magic flag like "--do-exactly-as-i-say-i-know-what-i-am-doing" that I missed? Or do I need to add "volatile" to my every single variable? I read on one forum that it might help to avoid memset and memcpy.
Or is there any other free compiler alternatives that support both AArch64 and x86_64 targets? I've checked a fork of tcc, still not good enough unfortunately

(Just a sidenote, I've found plenty of complaints about the opposite: removal of a deliberate memset call by the optimizer, which poses a security threat, as for example password is not cleared from memory.)
Cheers,
bzt