NEMU中IFDEF宏的实现方法

NEMU中marco.h的宏实现十分神奇,这里以IFDEF宏的实现为例子,简单介绍一下.

本文章为一生一芯教学项目的个人理解,笔者并不能保证其正确,请注意学术诚信
笔者并非计算机科班,内容难免存在错误,如您发现,欢迎与我联系.

目的:实现#IFDEF(CONFIG_ITRACE, init_disasm())宏,若CONFIG_ITRACE宏被定义,则执行函数init_disasm(),否则不执行任何函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#define CHOOSE2nd(a, b, ...) b
#define MUX_WITH_COMMA(contain_comma, a, b) CHOOSE2nd(contain_comma a, b)
#define MUX_MACRO_PROPERTY(p, macro, a, b) MUX_WITH_COMMA(concat(p, macro), a, b)
// define placeholders for some property
#define __P_DEF_0 X,
#define __P_DEF_1 X,
#define __P_ONE_1 X,
#define __P_ZERO_0 X,
// define some selection functions based on the properties of BOOLEAN macro
#define MUXDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, X, Y)
#define MUXNDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, Y, X)
#define MUXONE(macro, X, Y) MUX_MACRO_PROPERTY(__P_ONE_, macro, X, Y)
#define MUXZERO(macro, X, Y) MUX_MACRO_PROPERTY(__P_ZERO_,macro, X, Y)

// simplification for conditional compilation
#define __IGNORE(...)
#define __KEEP(...) __VA_ARGS__
// keep the code if a boolean macro is defined
#define IFDEF(macro, ...) MUXDEF(macro, __KEEP, __IGNORE)(__VA_ARGS__)
// keep the code if a boolean macro is undefined
#define IFNDEF(macro, ...) MUXNDEF(macro, __KEEP, __IGNORE)(__VA_ARGS__)
// keep the code if a boolean macro is defined to 1
#define IFONE(macro, ...) MUXONE(macro, __KEEP, __IGNORE)(__VA_ARGS__)
// keep the code if a boolean macro is defined to 0
#define IFZERO(macro, ...) MUXZERO(macro, __KEEP, __IGNORE)(__VA_ARGS__)

#define ISDEF(macro) MUXDEF(macro, 1, 0)
#define MUXDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, X, Y)
#define MUX_MACRO_PROPERTY(p, macro, a, b) MUX_WITH_COMMA(concat(p, macro), a, b)
若MARCO_1被定义:
MUXDEF(MACRO_1, 1, 0)
被展开为
MUX_MACRO_PROPERTY(__P_DEF_, MACRO_1, 1, 0)
拼接连接符
concat(__P_DEF_, MACRO_1) // 结果为 __P_DEF_0
#define __P_DEF_0 X, // 包含逗号
被展开为MUX_WITH_COMMA(__P_DEF_0, 1, 0)
被展开为CHOOSE2nd(X, , 1, 0) // 选择第二个参数:space
(逗号替换逻辑,这里‘X,’作为一个整体传进去,即X,就是一个参数,space之后的逗号是分割这个整体的,而’X,’内的逗号又会导致其被解析成两个参数。)

对于
#define CONFIG_ITRACE // 假设 CONFIG_ITRACE 被定义
IFDEF(CONFIG_ITRACE, init_disasm());
调用#IFDEF
MUXDEF(CONFIG_ITRACE, __KEEP, __IGNORE)(init_disasm());
展开MUXDEF
MUX_MACRO_PROPERTY(__P_DEF_, CONFIG_ITRACE, __KEEP, __IGNORE)(init_disasm());
拼接连接符
concat(__P_DEF_, CONFIG_ITRACE) -> __P_DEF_1
#define __P_DEF_1 X,
其结果
MUX_WITH_COMMA(__P_DEF_1, __KEEP, __IGNORE)(init_disasm());
处理MUX_WITH_COMMA
CHOOSE2nd(__P_DEF_1 __KEEP, __IGNORE)(init_disasm());
__P_DEF_1 包含一个逗号,被展开为’ X,__KEEP, __IGNORE’,所以选择第二个参数 __KEEP:
__KEEP(init_disasm());
调用__KEEP
init_disasm();
实现若CONFIG_ITRACE被定义,执行init_disasm();的效果。

而若CONFIG_ITRACE宏未定义:
IFDEF(CONFIG_ITRACE, init_disasm());
调用#IFDEF
MUXDEF(CONFIG_ITRACE, __KEEP, __IGNORE)(init_disasm());
拼接连接符,现在其未被定义
concat(__P_DEF_, CONFIG_ITRACE) -> __P_DEF_ CONFIG_ITRACE
其结果
MUX_WITH_COMMA(__P_DEF_ CONFIG_ITRACE, __KEEP, __IGNORE)(init_disasm());
处理MUX_WITH_COMMA
CHOOSE2nd(__P_DEF_ CONFIG_ITRACE __KEEP, __IGNORE)(init_disasm());
现在__P_DEF_ CONFIG_ITRACE __KEEP,未被定义(不像上个例子能被展开为‘X,’)
此时选择第二个参数__IGNORE
__IGNORE(init_disasm())
展开为空。
实现若CONFIG_ITRACE未被定义,不执行任何函数的效果。


NEMU中IFDEF宏的实现方法
http://example.com/2025/02/26/NEMU中IFDEF宏的实现方法/
作者
lethe
发布于
2025年2月26日
许可协议