c - 使 gcc/clang 将函数识别为内置函数

标签 c gcc clang posix built-in

在 neovim 项目中,我们使用了一些标准功能,但并未在所有目标平台上实现。值得注意的是,stpcpy 以及即将推出的 mempcpyCurrently we're solving that by supplying and using our own x variants of these functions .

一个例子:

char *xstpcpy(char *restrict dst, const char *restrict src)
  FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
  const size_t len = strlen(src);
  return (char *)memcpy(dst, src, len + 1) + len;
}

然而,这仍然不是完全最优的,因为一些编译器,如 gcc,知道这些函数的标准版本是做什么的,并且在给定足够的上下文时可以生成更好的代码:gcc code for stpcpy builtin .

我想在它们周围放置 #ifdef 守卫,只有当它们未定义时才应由我们提供,并且我们应该开始使用常规名称(stpcpy 而不是 xstpcpy)。但在这一点上,这将是一个更具侵入性的变化。我的问题是我是否可以通过其他方式通知 gcc xstpcpystpcpy 完全一样?

P.S.:一个相关的问题:是否有一个标志,例如 -std=c99,强制 gcc/clang 无论如何发出对标准函数的调用?我好像记得有这么一件事,但现在找不到相关资料了。如果 -std=c99 确实禁用了内置扩展,我想知道如何在保持 -std=c99 的同时启用内置扩展。

编辑:由于一切似乎都有些模糊,我一直在尝试一些事情。先上代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
    const char str[] = "we have stpcpy";

    printf("static\n");
    {
        char p1[256];
        char p2[256];

        char *end1 = stpcpy(p1, str);
        char *end2 = (stpcpy)(p2, str);

        printf("static using stpcpy?\np1 = %s (end = %p)\np2 = %s (end = %p)\n",
                p1, end1, p2, end2);
    }

    return 0;
}

结果(我在 OSX 上,但 godbolt 表明它在 linux 上类似):

命令行:gcc-4.9 -O3 -save-temps -march=native stpcpy.c -o stpcpy gcc 4.9 似乎发出对 stpcpy_chk 的调用来代替 stpcpy() 行,并发出常规 _stpcpy (libc 调用)来代替(stpcpy)() 行。我本来希望 gcc 将其降低为 mempcpy 作为 stpcpy builtin code in the gcc codebase made最初让我相信。

命令行:clang -O3 -save-temps -march=native stpcpy.c -o stpcpy(XCode clang 3.4) Clang 或多或少具有我对 gcc 的预期行为。它完全优化了对 stpcpy 的调用。像这样创建 asm:

leaq    -258(%rbp), %rdx
movabsq $34182044572742432, %rax ## imm = 0x79706370747320
movq    %rax, -265(%rbp)
movabsq $2334402142592329079, %rcx ## imm = 0x2065766168206577
movq    %rcx, -272(%rbp)

而不是调用 _stpcpy

我想知道我是否可以让 gcc-4.9 做我想做的事。在不同版本中使用 godbolt,我无法使用 gcc 创建与 clang 类似的代码。

最佳答案

我不知道 stpcpy 的内置函数是如何工作的,但是对于 memcpy 它要求大小是一个编译时间常数并且小于或等于 8192 字节。如果您的代码满足这两个要求(并且您不使用 -fno-builtin),GCC 将使用内置的 memcpy。我不知道有什么方法可以强制它使用 builtin 来获得更大的尺寸。

要禁用内置函数,您可以使用 -fno-builtin。但是,-fno-builtin only seems to work for GCC 4.9.x .

编辑: 要将内置函数与 -std=c99 一起使用,请使用 __builtin_memcpy。我只是试过这个并查看了 assemblby。使用 memcpy 调用 memcpy。使用 __builtin_memcpy 直接构建内存副本。但是,如果您设置的大小大于 8192,它会调用 memcpy 函数。这与使用 -std=gnu99 相同。

关于c - 使 gcc/clang 将函数识别为内置函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25668350/

相关文章:

objective-c - 在 CocoaPods 项目中使用@import

c++ - 使用 gcc 但使用 Clang 时没有关于模板函数中未使用参数的警告

c - sscanf() 双显示零

对 htonl 输出感到困惑

c++ - 如何以正确的方式学习 C++ 编程

c - C 中负奇实数的黎曼 Zeta 函数

c - 如何更正我的 Makefile,以便它构建我的所有源文件? (答案: check for hidden tabs)

c - 如果格式字符串没有 % 引用,vsprintf() 是否保证不访问 va_list?

无法使用 Xcode 11 包管理器在 Swift 包中包含 C 文件

android - 如何修复找不到 libgcc.a : No such file or directory error