How to provide an implementation of memcpy

34

I am trying to write some bare metal code with a memset-style loop in it:

for (int i = 0; i < N; ++i) {
  arr[i] = 0;
}

It is compiled with GCC and GCC is smart enough to turn that into a call to memset(). Unfortunately because it's bare metal I have no memset() (normally in libc) so I get a link error.

 undefined reference to `memset'

It seems like the optimisation that does this transformation is -ftree-loop-distribute-patterns:

Perform loop distribution of patterns that can be code generated with calls to a library. This flag is enabled by default at -O2 and higher, and by -fprofile-use and -fauto-profile.

So one person's solution was to just lower the optimisation level. Not very satisfying.

I also found this really helpful page that explains that -ffreestanding is not enough to get GCC not to do this, and there's basically no option but to provide your own implementations of memcpy, memmove, memset and memcmp. I'm happy to do that, but how?

If I just write memset the compiler will detect the loop inside it and transform it into a call to memset! In fact in the code provided by the CPU vendor I'm using I actually found this comment:

/*
// This is commented out because the assembly code that the compiler generates appears to be
// wrong.  The code would recursively call the memset function and eventually overruns the
// stack space.
void * memset(void *dest, int ch, size_t count)
...

So I assume that is the issue they ran into.

How do I supply a C implementation of memset without the compiler optimising it to a call to itself and without disabling that optimisation?

Share
Improve this question
24
  • 2
    Does this answer your question? stackoverflow.com/questions/2548486/compiling-without-libc – YSC Apr 22 at 9:32
  • 2
    Weird, -ffreestanding works for me. – ssbssa Apr 22 at 10:37
  • 1
    @Lundin: I don't see why you need to know the target system. I think you misunderstood. – Timmmm Apr 22 at 10:55
  • 4
    @EricPostpischil It turns out the compiler really inserts memset and memcpy calls even with -ffreestanding, when initializing/copying large structs. This is also mentioned in the gcc documentation: GCC requires the freestanding environment provide memcpy, memmove, memset and memcmp. – ssbssa Apr 22 at 17:36
  • 1
    @supercat I think the answer provided here is the "correct" way, since glibc is doing it like this (and AFAIK they work hand in hand with gcc). – ssbssa Apr 22 at 18:56

Comments

Popular posts from this blog

Meaning of `{}` for return expression

Get current scroll position of ScrollView in React Native

flutter websocket connection issue