【问题标题】:clang bpf: attribute always_inline does not workingclang bpf:属性 always_inline 不起作用
【发布时间】:2021-12-30 09:32:10
【问题描述】:

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

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

效果很好,当我使用 llvm-objdump 时,它显示 bpf_call_func 已经被内联了。

但是当我在同一个目标文件中定义了另一个动作时,也称为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 手册,上面写着:

请注意,函数定义中的某些用法可能使其不适合内联替换。这些用法包​​括:可变参数函数、alloca 的使用、计算的 goto 的使用(参见作为值的标签)、非本地 goto 的使用、嵌套函数的使用、setjmp 的使用、__builtin_longjmp 的使用以及 __builtin_return 或 __builtin_apply_args 的使用。当标记为 inline 的函数无法替换时,使用 -Winline 会发出警告,并给出失败的原因。

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

我想知道为什么bpf_call_func inline 有两个部分时不调用它? 和bpf_call_func的指令号有关系吗?

【问题讨论】:

  • 您能否分享一个always_inline 不起作用的最小可重现示例(使用函数的主体和原型)?

标签: compiler-construction clang inline ebpf


【解决方案1】:

据我所知,实际上没有办法强制 clang 内联函数,这是clang reference for always_inline

内联启发式被禁用,无论优化级别如何,总是尝试内联。

不保证实际发生内联替换。

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

always_inline

通常,除非指定优化,否则函数不会内联。对于声明为内联的函数,此属性内联函数独立于其他适用于内联的任何限制。未能内联此类功能被诊断为错误。请注意,如果间接调用此类函数,编译器可能会或可能不会内联它,具体取决于优化级别,并且可能会或可能不会诊断出内联间接调用失败。

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

-Winline

此诊断标志的存在是为了与 GCC 兼容,在 Clang 中无效。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-06
    • 2014-09-22
    • 2011-03-31
    • 2018-11-19
    • 2012-07-23
    • 2016-07-16
    • 2020-01-24
    • 2015-09-05
    相关资源
    最近更新 更多