简体   繁体   English

如何提供 memcpy 的实现

[英]How to provide an implementation of memcpy

I am trying to write some bare metal code with a memset -style loop in it:我正在尝试编写一些带有memset样式循环的裸机代码:

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() .它是用 GCC 和 GCC 编译的,它足够聪明,可以将其转换为对memset()的调用。 Unfortunately because it's bare metal I have no memset() (normally in libc) so I get a link error.不幸的是,因为它是裸机,所以我没有memset() (通常在 libc 中),所以我收到链接错误。

 undefined reference to `memset'

It seems like the optimisation that does this transformation is -ftree-loop-distribute-patterns :似乎进行这种转换的优化是-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 .默认情况下,此标志在 -O2 及更高版本以及-fprofile-use-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 .我还发现这个非常有用的页面解释了-ffreestanding不足以让 GCC 不这样做,而且基本上别无选择,只能提供自己的memcpymemmovememsetmemcmp实现。 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:如果我只是编写memset ,编译器将检测其中的循环并将其转换为对 memset 的调用: 事实上,在我正在使用的 CPU 供应商提供的代码中,我实际上发现了以下注释:

/*
// 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?如何提供memset的 C 实现,而不需要编译器将其优化为对自身的调用并且不禁用该优化?

Aha I checked inthe glibc code and there's a inhibit_loop_to_libcall modifier which sounds like it should do this.啊哈,我检查了 glibc 代码,并且有一个inhibit_loop_to_libcall修饰符,听起来它应该这样做。 It is defined like this :它是这样定义的

/* Add the compiler optimization to inhibit loop transformation to library
   calls.  This is used to avoid recursive calls in memset and memmove
   default implementations.  */
#ifdef HAVE_CC_INHIBIT_LOOP_TO_LIBCALL
# define inhibit_loop_to_libcall \
    __attribute__ ((__optimize__ ("-fno-tree-loop-distribute-patterns")))
#else
# define inhibit_loop_to_libcall
#endif

You mention in your question:您在问题中提到:

It seems like the optimisation that does this transformation is -ftree-loop-distribute-patterns似乎进行这种转换的优化是-ftree-loop-distribute-patterns

all you need to do to turn off this optimization is pass -fno-tree-loop-distribute-patterns to the compiler.关闭此优化所需要做的就是将-fno-tree-loop-distribute-patterns传递给编译器。 This turns off the optimization globally.这将关闭全局优化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM