Browse Source

new: 增加一些编译器相关的宏

fslongjin 2 years ago
parent
commit
9b37ff3e5a

+ 15 - 0
kernel/arch/x86_64/asm.h → kernel/arch/x86_64/asm/asm.h

@@ -18,6 +18,21 @@
 #define io_lfence() __asm__ __volatile__("lfence\n\t" :: \
                                              : "memory") // 在lfence指令前的读操作必须在lfence指令后的读操作前完成。
 
+/*
+ * Macros to generate condition code outputs from inline assembly,
+ * The output operand must be type "bool".
+ */
+// 如果编译器支持输出标志寄存器值到变量的话,则会定义__GCC_ASM_FLAG_OUTPUTS__
+#ifdef __GCC_ASM_FLAG_OUTPUTS__
+// CC_SET(c)则是用于设置标志寄存器中的某一位
+#define CC_SET(c) "\n\t/* output condition code " #c "*/\n"
+// "=@cccond"的用法是,将标志寄存器中的cond(也就是指令集定义的标准条件)的值输出到变量中
+#define CC_OUT(c) "=@cc" #c
+#else
+#define CC_SET(c) "\n\tset" #c " %[_cc_" #c "]\n"
+#define CC_OUT(c) [_cc_##c] "=qm"
+#endif
+
 #define rdtsc() ({                                    \
     uint64_t tmp1 = 0, tmp2 = 0;                      \
     asm volatile("rdtsc"                              \

+ 30 - 12
kernel/common/compiler.h

@@ -1,6 +1,6 @@
 #pragma once
 
-#define __force __attribute__((force))
+#include <common/compiler_attributes.h>
 
 #define likely(x) __builtin_expect(!!(x), 1)
 #define unlikely(x) __builtin_expect(!!(x), 0)
@@ -11,19 +11,37 @@
                                            : "memory");
 #endif
 
-// 编译器属性
-
-// 当函数的返回值未被使用时,编译器抛出警告信息
-#define __must_check __attribute__((__warn_unused_result__))
+/**
+ * @brief 编译时断言,如果condition不为1,则输出msg
+ * 
+ * @param prefix 一个“不存在的函数名”的前缀
+ * @param suffix 一个“不存在的函数名”的后缀
+ */
+#define __compiletime_assert(condition, msg, prefix, suffix)                                          \
+    do                                                                                                \
+    {                                                                                                 \
+        /**                                                                                           \
+         * 声明一个不存在的函数的extern,如果assert失败,就调用它,从而导致 \
+         * 链接时出错,进而达到“编译时断言”的功能。                            \
+         */                                                                                           \
+        __noreturn extern void prefix##suffix(void)                                                   \
+            __compiletime_error(msg);                                                                 \
+        if (!(condition))                                                                             \
+            prefix##suffix();                                                                         \
+    } while (0)
 
-typedef uint8_t __attribute__((__may_alias__)) __u8_alias_t;
-typedef uint16_t __attribute__((__may_alias__)) __u16_alias_t;
-typedef uint32_t __attribute__((__may_alias__)) __u32_alias_t;
-typedef uint64_t __attribute__((__may_alias__)) __u64_alias_t;
+/**
+ * @brief 当condition是false时,中断编译,并输出指定的错误信息
+ * 
+ * @param condition assert的情况
+ * @param msg condition为false时输出的错误信息
+ */
+#define complietime_assert(condition, msg)  \
+    __compiletime_assert(condition, msg, __compiletime_assert__, __COUNTER__)
 
 /**
  * @brief 从src读取数据到dst,该过程避免编译器优化。
- * 
+ *
  * @param dst 目标地址指针
  * @param src 源地址指针
  * @param size 要读取的数据大小(建议1、2、4、8字节,若不满足要求,则采用memcpy读取。)
@@ -54,7 +72,7 @@ static __always_inline void __read_once_size(void *dst, const volatile void *src
 
 /**
  * @brief 把src处的数据到dst,该过程避免编译器优化。
- * 
+ *
  * @param dst 目标地址指针
  * @param src 源地址指针
  * @param size 要写入的数据大小(建议1、2、4、8字节,若不满足要求,则采用memcpy传输。)
@@ -94,7 +112,7 @@ static __always_inline void __write_once_size(volatile void *dst, void *src, int
  * 2.确保编译器不会折叠、旋转或以其他方式对代码进行优化,从而破坏数据访问顺序。
  *
  * 这两个宏的union __u内的__c用作这个union的地址的指针
- * 
+ *
  * 关于READ_ONCE和WRITE_ONCE的简单说明,请转到:https://bbs.dragonos.org/forum.php?mod=viewthread&tid=24
  */
 

+ 22 - 0
kernel/common/compiler_attributes.h

@@ -0,0 +1,22 @@
+#pragma once
+
+// 当函数的返回值未被使用时,编译器抛出警告信息
+#define __must_check __attribute__((__warn_unused_result__))
+#define __force __attribute__((force))
+// 无返回值的属性
+#define __noreturn __attribute__((__noreturn__))
+/*
+ * Optional: only supported since clang >= 14.0
+ *
+ *   gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-error-function-attribute
+ */
+#if __has_attribute(__error__)
+#define __compiletime_error(msg) __attribute__((__error__(msg)))
+#else
+#define __compiletime_error(msg)
+#endif
+
+typedef uint8_t __attribute__((__may_alias__)) __u8_alias_t;
+typedef uint16_t __attribute__((__may_alias__)) __u16_alias_t;
+typedef uint32_t __attribute__((__may_alias__)) __u32_alias_t;
+typedef uint64_t __attribute__((__may_alias__)) __u64_alias_t;

+ 1 - 1
kernel/common/glib.h

@@ -14,7 +14,7 @@
 #include <common/list.h>
 
 #if ARCH(I386) || ARCH(X86_64)
-#include <arch/x86_64/asm.h>
+#include <arch/x86_64/asm/asm.h>
 #else
 #error Arch not supported.
 #endif

+ 1 - 1
kernel/common/list.h

@@ -2,7 +2,7 @@
 #include <common/stddef.h>
 
 #if ARCH(I386) || ARCH(X86_64)
-#include <arch/x86_64/asm.h>
+#include <arch/x86_64/asm/asm.h>
 #else
 #error Arch not supported.
 #endif

+ 8 - 1
kernel/common/sys/types.h

@@ -87,4 +87,11 @@ typedef struct __pthread_condattr_t
     int clockid; // clockid_t
 } pthread_condattr_t;
 
-typedef uint64_t gfp_t;
+typedef uint64_t gfp_t;
+
+// 定义8字节对齐变量属性
+#ifndef __aligned_u64
+    #define __aligned_u64 uint64_t __attribute__((aligned(8)))
+#endif
+
+#define aligned_u64 __aligned_u64

+ 17 - 1
kernel/debug/bug.h

@@ -29,7 +29,7 @@
 
 /**
  * @brief 当condition不为0时输出警告信息,且只会输出一次警告信息
- * 
+ *
  */
 #define WARN_ON_ONCE(condition) ({              \
     static int __warned;                        \
@@ -49,4 +49,20 @@
         goto to;                       \
     unlikely(__ret_warn_on);           \
 })
+
+/**
+ * @brief 当condition为true时,中断编译,并输出错误信息msg
+ * 
+ * 如果你的代码依赖于一些能够在编译期间计算出来的值,那么请使用这个宏以防止其他人错误的修改了这些值,从而导致程序运行错误
+ */
+#define BUILD_BUG_ON_MSG(condition, msg) complietime_assert(!(condition), msg)
+
+/**
+ * @brief 当condition为true时,中断编译。
+ * 
+ * 如果你的代码依赖于一些能够在编译期间计算出来的值,那么请使用这个宏以防止其他人错误的修改了这些值,从而导致程序运行错误
+ */
+#define BUILD_BUG_ON(condition) \
+    BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
+
 #pragma GCC pop_options