1 GCC plugins

引用官方说明:

GCC plugins are loadable modules that provide extra features to the compiler. Like GCC itself they can be distributed in source and binary forms.

GCC plugins provide developers with a rich subset of the GCC API to allow them to extend GCC as they see fit. Whether it is writing an additional optimization pass, transforming code, or analyzing information, plugins can be quite useful.

GCC plugins特点:可动态加载,无需重新编译GCC,方便扩展GCC新特性。

2 加载plugin

编译时添加如下选项:

-fplugin=name -fplugin-arg-name-key1[=value1]

name 是GCC plugin插件名称

key1 是插件的第一个参数

value1是插件第一个参数的值

3 plugin框架

常见的plugin至少包括plugin_is_GPL_compatible、plugin_init。代码如下:

plugin.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "gcc-plugin.h"
#include "plugin-version.h"

int plugin_is_GPL_compatible; // 框架要求必须有该变量声明

// 插件初始化,当指定编译插件时,首先调用该函数。
__visible int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)
{
// 检查插件版本与当前编译器版本是否一致, 也可以不检查。
if (!plugin_default_version_check(version, &gcc_version)) {
error(G_("incompatible gcc/plugin versions"));
return 1;
}

return 0;
}

test.c

1
2
3
4
5
6
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("hello\n");
return 0;
}
1
2
3
编译:
g++ -I`gcc -print-file-name=plugin`/include -fPIC -shared -o plugin1.so plugin1.c
g++ -O0 -g -fplugin=plugin1.so test.c -o test.exe

编译器粗略分为词法分析,语法分析,类型检查,中间代码生成,代码优化,目标代码生成,目标代码优化。

GCC编译过程中分为几个部分:前端、中端、后端。

前端主要做词法分析,语法分析,类型检查,中间代码生成。

中端实现中间代码的优化。

后端实现对各个平台的汇编代码。

在gcc的实现通过pass进行上述过程的映射。 pass定义在GCC passes.def

3.1 注册pass

1)基于gcc plugin

​ 参考 https://zhuanlan.zhihu.com/p/49490338

2)基于linux kernel

​ Linux Kernel封装了一系列宏,简化了plugin的使用。
代码中实现了一个打印函数名称的功能。

3.2 plugin事件

有了plugin框架后,我们就可以添加plugin核心内容了。GCC plugin提供了一些plugin的事件,分别对应于plugin的各个过程。

通过register_callback函数注册回调钩子,当触发事件是回调相应的处理函数。

附:plugin事件列表。

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
enum plugin_event
{
PLUGIN_START_PARSE_FUNCTION, /* Called before parsing the body of a function. */
PLUGIN_FINISH_PARSE_FUNCTION, /* After finishing parsing a function. */
PLUGIN_PASS_MANAGER_SETUP, /* To hook into pass manager. */
PLUGIN_FINISH_TYPE, /* After finishing parsing a type. */
PLUGIN_FINISH_DECL, /* After finishing parsing a declaration. */
PLUGIN_FINISH_UNIT, /* Useful for summary processing. */
PLUGIN_PRE_GENERICIZE, /* Allows to see low level AST in C and C++ frontends. */
PLUGIN_FINISH, /* Called before GCC exits. */
PLUGIN_INFO, /* Information about the plugin. */
PLUGIN_GGC_START, /* Called at start of GCC Garbage Collection. */
PLUGIN_GGC_MARKING, /* Extend the GGC marking. */
PLUGIN_GGC_END, /* Called at end of GGC. */
PLUGIN_REGISTER_GGC_ROOTS, /* Register an extra GGC root table. */
PLUGIN_ATTRIBUTES, /* Called during attribute registration */
PLUGIN_START_UNIT, /* Called before processing a translation unit. */
PLUGIN_PRAGMAS, /* Called during pragma registration. */
/* Called before first pass from all_passes. */
PLUGIN_ALL_PASSES_START,
/* Called after last pass from all_passes. */
PLUGIN_ALL_PASSES_END,
/* Called before first ipa pass. */
PLUGIN_ALL_IPA_PASSES_START,
/* Called after last ipa pass. */
PLUGIN_ALL_IPA_PASSES_END,
/* Allows to override pass gate decision for current_pass. */
PLUGIN_OVERRIDE_GATE,
/* Called before executing a pass. */
PLUGIN_PASS_EXECUTION,
/* Called before executing subpasses of a GIMPLE_PASS in
execute_ipa_pass_list. */
PLUGIN_EARLY_GIMPLE_PASSES_START,
/* Called after executing subpasses of a GIMPLE_PASS in
execute_ipa_pass_list. */
PLUGIN_EARLY_GIMPLE_PASSES_END,
/* Called when a pass is first instantiated. */
PLUGIN_NEW_PASS,
/* Called when a file is #include-d or given via the #line directive.
This could happen many times. The event data is the included file path,
as a const char* pointer. */
PLUGIN_INCLUDE_FILE,

/* Called when -fanalyzer starts. The event data is an
ana::plugin_analyzer_init_iface *. */
PLUGIN_ANALYZER_INIT,

PLUGIN_EVENT_FIRST_DYNAMIC /* Dummy event used for indexing callback array. */
}

参考资料

1.GCC plugins官方文档:https://gcc.gnu.org/onlinedocs/gccint/Plugins.html#Plugins

2.GCC-Plugin的一些笔记(一):https://zhuanlan.zhihu.com/p/49490338

3.gcc插件:https://github.com/rofirrim/gcc-plugins.git