title: compiler
categories:
- linux
- include
tags: - linux
- include
abbrlink: aa62bd49
date: 2025-10-03 09:01:49

文章目录
- include/linux/build_bug.h
-
- [static_assert 静态编译警告](#static_assert 静态编译警告)
- [BUILD_BUG_ON_MSG 中断编译提供BUG信息](#BUILD_BUG_ON_MSG 中断编译提供BUG信息)
- [BUILD_BUG_ON_INVALID 不会生成编译时的警告](#BUILD_BUG_ON_INVALID 不会生成编译时的警告)
- BUILD_BUG_ON
- [include/linux/compiler.h 编译时完成](#include/linux/compiler.h 编译时完成)
-
- [unreachable 不可达代码](#unreachable 不可达代码)
- [likely && unlikely 优化分支预测](#likely && unlikely 优化分支预测)
-
- [未启用CONFIG_TRACE_BRANCH_PROFILING 追踪分支分析](#未启用CONFIG_TRACE_BRANCH_PROFILING 追踪分支分析)
- [启用CONFIG_TRACE_BRANCH_PROFILING 追踪分支分析](#启用CONFIG_TRACE_BRANCH_PROFILING 追踪分支分析)
- [barrier 内存屏障](#barrier 内存屏障)
- [is_signed_type is_unsigned_type 有符号类型 无符号类型](#is_signed_type is_unsigned_type 有符号类型 无符号类型)
- [statically_true 编译时判断为常量](#statically_true 编译时判断为常量)
- include/linux/compiler_types.h
-
- [__cold 表示该函数很少被调用](#__cold 表示该函数很少被调用)
- [__latent_entropy 随机性](#__latent_entropy 随机性)
- [__always_inline 强制内联](#__always_inline 强制内联)
- [__alloc_size __realloc_size 分配大小](#__alloc_size __realloc_size 分配大小)
- [__force 强制转换](#__force 强制转换)
- [compiletime_assert 中断编译提供BUG信息](#compiletime_assert 中断编译提供BUG信息)
- BTF_TYPE_TAG
- [__native_word 本机字节长度](#__native_word 本机字节长度)
- [__unqual_scalar_typeof 用于获取变量的非限定标量类型](#__unqual_scalar_typeof 用于获取变量的非限定标量类型)
- [noinstr 禁止内联插桩的段](#noinstr 禁止内联插桩的段)
- [__same_type 类型是否相等](#__same_type 类型是否相等)
- include/linux/kbuild.h
- include/linux/kconfig.h
include/linux/build_bug.h
static_assert 静态编译警告
c
/**
* static_assert - 在构建时检查整数常量表达式
*
* static_assert() 是 C11 _Static_assert的包装器,具有
* little 宏魔术使消息成为可选的(默认为
* 测试表达式的字符串化)。
*
* 与 BUILD_BUG_ON() 相反,static_assert() 可以在 global
* 范围,但要求表达式为整数常量
* 表达式(即,__builtin_constant_p() 是不够的
* true 表示 expr)。
*
* 另请注意BUILD_BUG_ON,如果条件为
* true,而 static_assert() 如果表达式为
*假。
*/
#define static_assert(expr, ...) __static_assert(expr, ##__VA_ARGS__, #expr)
#define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
BUILD_BUG_ON_MSG 中断编译提供BUG信息
c
/**
* BUILD_BUG_ON_MSG - 如果条件为真,则中断编译并提供 emit
*错误信息。
* @condition:编译器应该知道的条件是 false。
*
* 有关说明,请参见 BUILD_BUG_ON。
*/
#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
BUILD_BUG_ON_INVALID 不会生成编译时的警告
c
/* BUILD_BUG_ON_INVALID() 允许编译器检查表达式的有效性,但避免生成任何代码,即使该表达式具有副作用。
*/
#define BUILD_BUG_ON_INVALID(e) ((void)(sizeof((__force long)(e))))
BUILD_BUG_ON
c
/**
* BUILD_BUG_ON - 如果条件为 true,则中断编译。
* @condition:编译器应该知道的条件是 false。
*
* 如果你有一些代码依赖于某些常量相等,或者
* 其他一些编译时评估的条件,您应该使用 BUILD_BUG_ON 来
* 检测是否有人更改它。
*/
#define BUILD_BUG_ON(condition) \
BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
include/linux/compiler.h 编译时完成
unreachable 不可达代码
unreachable是一个宏,用于标记不可达的代码路径。它通常用于在编译器优化时提供提示,告诉编译器某些代码永远不会被执行。这可以帮助编译器进行更好的优化,并且在调试时可以帮助开发人员识别潜在的错误或不一致之处。barrier_before_unreachable是一个宏,用于在不可达代码之前插入一个屏障。这个屏障可以防止编译器对不可达代码进行优化,从而确保编译器不会删除或重排这些代码。这个宏通常用于调试和错误检查,以确保不可达代码在编译时不会被优化掉。
c
#define unreachable() do { \
barrier_before_unreachable(); \
__builtin_unreachable(); \
} while (0)
likely && unlikely 优化分支预测
- unlikely(x) 的返回值与 x 的布尔值相同
- likely(x) 的返回值与 x 的布尔值相同
未启用CONFIG_TRACE_BRANCH_PROFILING 追踪分支分析
- __builtin_expect 是 GCC 提供的一个内建函数,用于向编译器提供分支预测信息。!!(x) 将 x 转换为布尔值,1 表示这个条件很可能为真。通过使用这个宏,开发者可以提示编译器优化代码路径,使得这个条件为真的情况执行得更快。
c
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
启用CONFIG_TRACE_BRANCH_PROFILING 追踪分支分析
c
#define __branch_check__(x, expect, is_constant) ({ \
long ______r; \
static struct ftrace_likely_data \
__aligned(4) \
__section("_ftrace_annotated_branch") \
______f = { \
.data.func = __func__, \
.data.file = __FILE__, \
.data.line = __LINE__, \
}; \
______r = __builtin_expect(!!(x), expect); \
ftrace_likely_update(&______f, ______r, \
expect, is_constant); \
______r; \
})
/*
* Using __builtin_constant_p(x) to ignore cases where the return
* value is always the same. This idea is taken from a similar patch
* written by Daniel Walker.
*/
# ifndef likely
# define likely(x) (__branch_check__(x, 1, __builtin_constant_p(x)))
# endif
# ifndef unlikely
# define unlikely(x) (__branch_check__(x, 0, __builtin_constant_p(x)))
# endif
barrier 内存屏障
barrier是一个宏,用于在编译器优化时插入一个内存屏障。内存屏障是一种指令,用于防止编译器和处理器对内存操作进行重排序,从而确保内存操作的顺序性。这在多线程和并发编程中非常重要,因为它可以确保不同线程之间的内存访问是可预测的。
c
# define barrier() __asm__ __volatile__("": : :"memory")
: : : "memory"是汇编指令的操作数部分。"memory"告诉编译器,这段汇编代码会影响内存的状态,因此编译器在这段代码之前和之后不能对内存访问进行重新排序。
is_signed_type is_unsigned_type 有符号类型 无符号类型
c
/*
* 'type' 是有符号类型还是无符号类型。支持标量类型,
* bool 以及指针类型。
*/
#define is_signed_type(type) (((type)(-1)) < (__force type)1)
#define is_unsigned_type(type) (!is_signed_type(type))
statically_true 编译时判断为常量
c
/*
* "Is this condition know at compile-work?" 的有用简写
*
* 请注意,该条件可能涉及非常量值,但编译器可能对这些值的详细信息有足够的了解,从而确定该条件是否为静态 true。
*/
#define statically_true(x) (__builtin_constant_p(x) && (x))
include/linux/compiler_types.h
__cold 表示该函数很少被调用
- 这是 GCC 编译器的一个属性,表示该函数很少被调用。编译器可以利用这个信息进行优化,例如将这些函数放置在不常用的代码段中,减少对常用代码段的干扰,从而提高缓存命中率和整体性能。
- CONFIG_CC_HAS_SANE_FUNCTION_ALIGNMENT:
- 这个宏用于检查编译器是否支持合理的函数对齐。函数对齐是指将函数的起始地址对齐到特定的字节边界,以提高访问效率和性能。
- CONFIG_FUNCTION_ALIGNMENT:
- 这个宏用于设置函数的对齐方式。函数对齐可以提高函数调用的效率,尤其是在某些架构上,函数调用需要特定的对齐方式才能正常工作。
c
#if defined(CONFIG_CC_HAS_SANE_FUNCTION_ALIGNMENT) || (CONFIG_FUNCTION_ALIGNMENT == 0)
#define __cold __attribute__((__cold__))
#else
#define __cold
#endif
__latent_entropy 随机性
- 这个属性通常用于内核开发中,特别是在 Linux 内核中。它用于标记那些在系统启动时需要一些随机性(entropy)的函数或变量。通过使用这个属性,编译器会确保在系统启动时,这些函数或变量能够获得一些随机数据,从而增强系统的安全性和不可预测性
c
#if defined(LATENT_ENTROPY_PLUGIN) && !defined(__CHECKER__)
#define __latent_entropy __attribute__((latent_entropy))
#endif
__always_inline 强制内联
__attribute__((__always_inline__))是 GCC 编译器特定的扩展属性,强制编译器始终内联标记的函数,即使在优化级别较低的情况下也会内联。这对于性能关键的代码段非常有用,因为它确保了函数调用的开销被最小化。
c
#define __always_inline inline __attribute__((__always_inline__))
__alloc_size __realloc_size 分配大小
__alloc_size和__realloc_size是 GCC 编译器的属性,用于标记函数的参数,以指示这些参数表示分配的内存大小。这些属性可以帮助编译器进行更好的优化和静态分析,确保在内存分配时使用正确的大小。
__force 强制转换
__force是 GCC 编译器的一个属性,用于强制类型转换。它通常用于指示编译器在进行类型转换时要强制执行,而不考虑潜在的类型不匹配或警告。这在某些情况下是有用的,例如在处理低级别的硬件编程或内核开发时。
c
#define __force __attribute__((force))
compiletime_assert 中断编译提供BUG信息
-
启用
__OPTIMIZE__时,将prefix与suffix连接成一个函数,并且这个函数是__compiletime_error类型的,这个函数会在编译时检查条件是否成立。 -
如果条件不成立,则调用这个函数,从而中断编译并提供错误信息。
-
__COUNTER__是一个预定义宏,它在每次使用时都会递增,用于生成唯一的后缀,确保每次调用compiletime_assert时都生成不同的函数名。所以prefix##suffix将会生成一个唯一的函数名。- 例如
c__noreturn extern void prefix ## suffix(void) \ __compiletime_error(msg); \ __noreturn extern void __compiletime_assert_1(void) __compiletime_error("int size is not 4 bytes");
c
#ifdef __OPTIMIZE__
# define __compiletime_assert(condition, msg, prefix, suffix) \
do { \
/* \
* 需要__noreturn来为编译器提供足够的 \
* 避免某些可能未初始化的信息 \
* 警告(无论构建是否失败)。 \
*/ \
__noreturn extern void prefix ## suffix(void) \
__compiletime_error(msg); \
if (!(condition)) \
prefix ## suffix(); \
} while (0)
#else
# define __compiletime_assert(condition, msg, prefix, suffix) do { } while (0)
#endif
#define _compiletime_assert(condition, msg, prefix, suffix) \
__compiletime_assert(condition, msg, prefix, suffix)
/**
* compiletime_assert - 如果 Condition 为 false,则中断构建并发出 msg
* @condition:要检查的编译时常量条件
* @msg:如果 condition 为 false,则发出一条消息
*
* 按照 POSIX 断言的传统,如果
* 提供的条件为 *false*,如果
* 编译器支持这样做。
*/
#define compiletime_assert(condition, msg) \
_compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
BTF_TYPE_TAG
BTF_TYPE_TAG是一个宏,用于在编译时为类型添加 BTF(BPF Type Format)标签。BTF 是一种用于描述内核数据结构的格式,主要用于 BPF(Berkeley Packet Filter)程序的类型信息。- 通过添加 btf_type_tag 属性,可以为类型提供额外的元数据,帮助调试和分析工具更好地理解和处理这些类型。
c
#if defined(CONFIG_DEBUG_INFO_BTF) && defined(CONFIG_PAHOLE_HAS_BTF_TAG) && \
__has_attribute(btf_type_tag) && !defined(__BINDGEN__)
# define BTF_TYPE_TAG(value) __attribute__((btf_type_tag(#value)))
#else
# define BTF_TYPE_TAG(value) /* nothing */
#endif
__native_word 本机字节长度
c
/* 此类型是本机字大小吗 -- 对原子作有用 */
#define __native_word(t) \
(sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || \
sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
__unqual_scalar_typeof 用于获取变量的非限定标量类型
_Generic: _Generic 是 C11 标准中的一种泛型选择机制,它根据表达式的类型选择一个对应的表达式。在这里,它用于选择适当的类型转换表达式
c
/*
* __unqual_scalar_typeof(x) - 声明一个非限定标量类型,留下
* 非标量类型保持不变。
*/
/*
* 首选 C11 _Generic以获得更好的编译时间和更简单的代码。注意: 'char'
* 与 'signed char' 类型不兼容,我们定义一个单独的 case。
*/
#define __scalar_type_to_expr_cases(type) \
unsigned type: (unsigned type)0, \
signed type: (signed type)0
#define __unqual_scalar_typeof(x) typeof( \
_Generic((x), \
char: (char)0, \
__scalar_type_to_expr_cases(char), \
__scalar_type_to_expr_cases(short), \
__scalar_type_to_expr_cases(int), \
__scalar_type_to_expr_cases(long), \
__scalar_type_to_expr_cases(long long), \
default: (x)))
noinstr 禁止内联插桩的段
- noinstr 是一个内核特定的函数属性,用于标记那些不允许插入任何额外代码(如调试、性能分析或跟踪代码)的函数。这些函数通常是与硬件或中断处理密切相关的关键代码,任何额外的插桩代码都可能导致不可预测的行为或性能问题。
c
/* Section for code which can't be instrumented at all */
#define __noinstr_section(section) \
noinline notrace __attribute((__section__(section))) \
__no_kcsan __no_sanitize_address __no_profile __no_sanitize_coverage \
__no_sanitize_memory __signed_wrap
#define noinstr __noinstr_section(".noinstr.text")
__same_type 类型是否相等
c
/* Are two types/vars the same type (ignoring qualifiers)? */
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
include/linux/kbuild.h
- 定义了.c生成.s的相关宏
c
#define DEFINE(sym, val) \
asm volatile("\n.ascii \"->" #sym " %0 " #val "\"" : : "i" (val))
#define BLANK() asm volatile("\n.ascii \"->\"" : : )
#define OFFSET(sym, str, mem) \
DEFINE(sym, offsetof(struct str, mem))
#define COMMENT(x) \
asm volatile("\n.ascii \"->#" x "\"")
include/linux/kconfig.h
#define __ARG_PLACEHOLDER_1 0,定义了一个宏__ARG_PLACEHOLDER_1,它的值是0,。这个宏用于在后续的宏中作为占位符。- 如果宏没有定义,则这里的
__ARG_PLACEHOLDER_1将不会被替换,而是直接使用0,作为参数。 #define __take_second_arg(__ignored, val, ...) val定义了一个宏__take_second_arg,它接受多个参数,但只返回第二个参数val。这个宏用于在后续的宏中提取第二个参数。- 所以宏有定义,则返回第二个参数1,没有定义,则返回第3个参数0
c
#define __ARG_PLACEHOLDER_1 0,
#define __take_second_arg(__ignored, val, ...) val
/*
* The use of "&&" / "||" is limited in certain expressions.
* The following enable to calculate "and" / "or" with macro expansion only.
*/
#define __and(x, y) ___and(x, y)
#define ___and(x, y) ____and(__ARG_PLACEHOLDER_##x, y)
#define ____and(arg1_or_junk, y) __take_second_arg(arg1_or_junk y, 0)
#define __or(x, y) ___or(x, y)
#define ___or(x, y) ____or(__ARG_PLACEHOLDER_##x, y)
#define ____or(arg1_or_junk, y) __take_second_arg(arg1_or_junk 1, y)
/*
* Helper macros to use CONFIG_ options in C/CPP expressions. Note that
* these only work with boolean and tristate options.
*/
/*
* Getting something that works in C and CPP for an arg that may or may
* not be defined is tricky. Here, if we have "#define CONFIG_BOOGER 1"
* we match on the placeholder define, insert the "0," for arg1 and generate
* the triplet (0, 1, 0). Then the last step cherry picks the 2nd arg (a one).
* When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when
* the last step cherry picks the 2nd arg, we get a zero.
*/
#define __is_defined(x) ___is_defined(x)
#define ___is_defined(val) ____is_defined(__ARG_PLACEHOLDER_##val)
#define ____is_defined(arg1_or_junk) __take_second_arg(arg1_or_junk 1, 0)
/*
* IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0
* otherwise. For boolean options, this is equivalent to
* IS_ENABLED(CONFIG_FOO).
*/
#define IS_BUILTIN(option) __is_defined(option)
/*
* IS_MODULE(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'm', 0
* otherwise. CONFIG_FOO=m results in "#define CONFIG_FOO_MODULE 1" in
* autoconf.h.
*/
#define IS_MODULE(option) __is_defined(option##_MODULE)
/*
* IS_REACHABLE(CONFIG_FOO) evaluates to 1 if the currently compiled
* code can call a function defined in code compiled based on CONFIG_FOO.
* This is similar to IS_ENABLED(), but returns false when invoked from
* built-in code when CONFIG_FOO is set to 'm'.
*/
#define IS_REACHABLE(option) __or(IS_BUILTIN(option), \
__and(IS_MODULE(option), __is_defined(MODULE)))
/*
* IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm',
* 0 otherwise. Note that CONFIG_FOO=y results in "#define CONFIG_FOO 1" in
* autoconf.h, while CONFIG_FOO=m results in "#define CONFIG_FOO_MODULE 1".
*/
#define IS_ENABLED(option) __or(IS_BUILTIN(option), IS_MODULE(option))