clang bpf:属性 always_inline 不起作用

clang bpf: attribute always_inline does not working

我写了一个 BPF 目标文件,其中包含一个部分和一个静态内联函数,定义如下:

static inline __attribute__((always_inline)) bpf_call_func(...);
__section("entry") bpf_func(...); // called bpf_call_func

它运行良好,当我使用 llvm-objdump 时,它显示 bpf_call_func 已经被内联。

但是当我在同一个目标文件中定义另一个ection时,也称为bpf_call_func

static inline __attribute__((always_inline)) bpf_call_func(...);
__section("entry") bpf_func(...); // called bpf_call_func
__section("entry2") bpf_func2(...); // called bpf_call_func

llvm-objdump 显示 bpf_call_func 没有在 bpf_funcbpf_func2 中内联。它只是定义在 .text 部分,bpf_funcbpf_func2 使用 call 指令调用 bpf_call_func.

bpf_call_func大约是600条指令。 bpf_funcbpf_func 大约是 250 条指令。

我查看了 gcc 手册,它说:

Note that certain usages in a function definition can make it unsuitable for inline substitution. Among these usages are: variadic functions, use of alloca, use of computed goto (see Labels as Values), use of nonlocal goto, use of nested functions, use of setjmp, use of __builtin_longjmp and use of __builtin_return or __builtin_apply_args. Using -Winline warns when a function marked inline could not be substituted, and gives the reason for the failure.

但我不知道哪些情况符合我的情况。

我想知道为什么 bpf_call_func 在有两个部分调用时不内联? 与bpf_call_func's instructions'号有关吗?

据我所知,没有办法真正强制 clang 内联一个函数,这是 clang reference for always_inline:

Inlining heuristics are disabled and inlining is always attempted regardless of optimization level.

Does not guarantee that inline substitution actually occurs.

这似乎是一个 clang 事情,因为 GCC states 它总是像属性建议的那样内联,或者抛出错误(对于单元内的调用):

always_inline

Generally, functions are not inlined unless optimization is specified. For functions declared inline, this attribute inlines the function independent of any restrictions that otherwise apply to inlining. Failure to inline such a function is diagnosed as an error. Note that if such a function is called indirectly the compiler may or may not inline it depending on optimization level and a failure to inline an indirect call may or may not be diagnosed.

GCC 提供了一个 -Winline 标志,因此编译器会警告未内联的函数,但 clang ignores this:

-Winline

This diagnostic flag exists for GCC compatibility, and has no effect in Clang.

因此,似乎 clang 将 always_inline 属性视为提示,并且很乐意在没有错误或警告的情况下不内联函数。在你的情况下,它可能决定你的内联函数太大了。

公平地说,除非您需要支持低于 4.16 的内核,否则这无关紧要,因为 eBPF supports functions calls nowadays.