在第一节分析了compiler.h文件,定义了当编译器为GCC时包含文件compiler-gcc.h。该文件是gcc编译器通用的定义。现在开始解析该文件的compiler-gcc.h。
/* Optimization barrier */
/* The "volatile" is due to gcc bugs */
#define barrier() __asm__ __volatile__("": : :"memory")
barrier函数在之前介绍过了,就是做内存栅栏,它的作用是让栅栏上下的代码隔离开,不进行优化。
/*
* This macro obfuscates arithmetic on a variable address so that gcc
* shouldn't recognize the original var, and make assumptions about it.
*
* This is needed because the C standard makes it undefined to do
* pointer arithmetic on "objects" outside their boundaries and the
* gcc optimizers assume this is the case. In particular they
* assume such arithmetic does not wrap.
*
* A miscompilation has been observed because of this on PPC.
* To work around it we hide the relationship of the pointer and the object
* using this macro.
*
* Versions of the ppc64 compiler before 4.1 had a bug where use of
* RELOC_HIDE could trash r30. The bug can be worked around by changing
* the inline assembly constraint from =g to =r, in this particular
* case either is valid.
*/
#define RELOC_HIDE(ptr, off) /
({ unsigned long __ptr; /
__asm__ ("" : "=r"(__ptr) : "0"(ptr)); /
(typeof(ptr)) (__ptr + (off)); })
该宏利用一条汇编语句,隐藏传入指针的类型,计算偏移后的地址。
/* &a[0] degrades to a pointer: a different type from an array */
#define __must_be_array(a) /
BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a), typeof(&a[0])))
/* Force a compilation error if condition is true, but also produce a
result (of value 0 and type size_t), so the expression can be used
e.g. in a structure initializer (or where-ever else comma expressions
aren't permitted). */
#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1)
该宏用于判断变量a是否是数组。该宏利用&a[0]的类型与a的类型不同的原则。__builtin_types_compatible_p(type1, type2)判断两个类型是否相同。BUILD_BUG_ON_ZERO宏在e为非0值时产生编译错误,为0时返回值0。
/*
* Force always-inline if the user requests it so via the .config,
* or if gcc is too old:
*/
#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || /
!defined(CONFIG_OPTIMIZE_INLINING) || (__GNUC__ < 4)
# define inline inline __attribute__((always_inline))
# define __inline__ __inline__ __attribute__((always_inline))
# define __inline __inline __attribute__((always_inline))
#endif
这部分定义inline内联,用户可以通过.config文件配置。或者在GCC版本小于4.0时强制内联。
#define __deprecated __attribute__((deprecated))
#define __packed __attribute__((packed))
#define __weak __attribute__((weak))
__deprecated说明该函数被声明为废除,任何对该函数的调用,GCC都会产生一个告警。
__packed用于修饰struct,union,enum类型定义,使得修饰后的类型占用最少的内存空间。对于类型为enum时,会选择采用最小内存的int指针。
__weak修改符会将相应的声明的为弱符号,这经常会用在库函数里面,在库函数里面定义的弱函数可以在用户的应用的代码中的实现覆盖它。
/*
* it doesn't make sense on ARM (currently the only user of __naked) to trace
* naked functions because then mcount is called without stack and frame pointer
* being set up and there is no chance to restore the lr register to the value
* before mcount was called.
*/
#define __naked __attribute__((naked)) notrace
naked属性使编译器不产生函数的入口和出口,只编译函数体。naked把应用程序控制器交给了用户,怎样保存函数的上下文都由用户决定。
#define __noreturn __attribute__((noreturn))
noruten属性说明该函数不会返回。
/*
* From the GCC manual:
*
* Many functions have no effects except the return value and their
* return value depends only on the parameters and/or global
* variables. Such a function can be subject to common subexpression
* elimination and loop optimization just as an arithmetic operator
* would be.
* [...]
*/
#define __pure __attribute__((pure))
pure属性修饰函数,说明该函数的输出完全依赖于函数的输入或全局的变量,这样的函数容易被通用的子表达式替换或优化成数学运算。
#define __aligned(x) __attribute__((aligned(x)))
#define __printf(a,b) __attribute__((format(printf,a,b)))
#define noinline __attribute__((noinline))
#define __attribute_const__ __attribute__((__const__))
#define __maybe_unused __attribute__((unused))
aligend为内存对齐修饰符
format告诉编译器像检查printf,scanf等函数的输入参数格式一样检查该函数的输入参数。a表示第几个参数是字符串格式,b表示从第几个参数开始按字符串格式检查。
noinline不进行内联的修饰符。
__attribute_const__ 常量修饰符。
__maybe_unused 修饰该函数可能不会被使用,gcc不会为这个函数产生警告。
#define __gcc_header(x) #x
#define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h)
#define gcc_header(x) _gcc_header(x)
#include gcc_header(__GNUC__)
这个部分用于包含当前gcc版本相应的头文件compiler-gcc[x].h。
转载时请注明出处和作者联系方式
作者联系方式:张天才 mythfish@gmail.com