This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

std::mt19937 with ARM Compiler 6 uses sys_open and breaks retarget.c

I'm using Keil V5.30.0.0 and ArmClang.exe V6.14.

When I tried using std::mt19937, like so:

#include <random>

std::mt19937 mt;
std::uniform_int_distribution< uint32_t > dist(0);

auto a = dist( mt );

I got linker errors:

.\obj\rcu.axf: Error: L6200E: Symbol __stdin multiply defined (by stdio_streams.o and retarget.o).
.\obj\rcu.axf: Error: L6200E: Symbol __stdout multiply defined (by stdio_streams.o and retarget.o).
.\obj\rcu.axf: Error: L6200E: Symbol __stderr multiply defined (by stdio_streams.o and retarget.o).

I'm using more or less classical retarget.c, tuned for armclang.

I tried to remove those definitions from retarget.c and then got error:

.\obj\rcu.axf: Error: L6915E: Library reports error: __use_no_semihosting_swi was requested, but _sys_open was referenced

Then I removed asm(".global __use_no_semihosting_swi\n"); and my firmware hit BKPT before main, in call to _sys_open.

Why is this happening? mt19937 and uniform_int_distribution by themselves should not use any IO, should they? 

Parents
  • This explains the original linker error: _sys_open is needed by the iostream functions pulled in from <random>, your retarget.cpp doesn't provide a definition and you disabled semihosting, so the linker complained that it couldn't find a suitable _sys_open. Allowing semihosting pulls in version of _sys_open that uses semihosting, which is why you end up on a breakpoint before main. (If you want to decode the semihosting call, see Chapter 7 in the ARM Compiler Software Development Guide.)

    The bulk of your 84KB binary is most likely due to locale and other I/O support. <random> includes <istream> and <ostream>, which is enough to pull in the IO libraries, even if your <random> objects don't use streams.  Large binary sizes aren't really the fault of retarget_io.c -- it's just a very small part of the overall puzzle. 

Reply
  • This explains the original linker error: _sys_open is needed by the iostream functions pulled in from <random>, your retarget.cpp doesn't provide a definition and you disabled semihosting, so the linker complained that it couldn't find a suitable _sys_open. Allowing semihosting pulls in version of _sys_open that uses semihosting, which is why you end up on a breakpoint before main. (If you want to decode the semihosting call, see Chapter 7 in the ARM Compiler Software Development Guide.)

    The bulk of your 84KB binary is most likely due to locale and other I/O support. <random> includes <istream> and <ostream>, which is enough to pull in the IO libraries, even if your <random> objects don't use streams.  Large binary sizes aren't really the fault of retarget_io.c -- it's just a very small part of the overall puzzle. 

Children
  • Hmm, looks like you are correct; removing #include <random> leads to small binary.

    Why this include pulls so much unused code that isn't removed even with -LTO and -ffunction-sections - is a whole other story, albeit very interesting :)

    Thanks for explanation!

    However.. when I used retarget_io.c, provided by RTE Manager, I didn't disable semihosting and still ended up on a breakpoint before main..