我开发了一个 GCC 插件来检测正在编译的应用程序。这些应用程序是用 C 语言编写的,并在 x86 Linux 系统上使用 GCC 4.7(4.8 和 4.9 也是一个选项)构建。
我的插件实现了一个编译通道,它放置在“ssa”标准通道之后并在 GIMPLE 表示上运行。除其他事项外,我需要实现以下内容,但目前无法弄清楚如何正确执行。
在处理 C 函数时,我需要在其开头插入将其参数复制到我创建的局部变量的代码,以供将来处理。
我的第一个天真的实现如下所示:
tree p;
gimple_seq seq = NULL;
gimple_stmt_iterator gsi = gsi_start_bb(single_succ(ENTRY_BLOCK_PTR));
for (p = DECL_ARGUMENTS(current_function_decl); p; p = DECL_CHAIN(param)) {
tree copy_par;
copy_par = create_tmp_var(TREE_TYPE(p), NULL);
add_referenced_var(copy_par);
copy_par = make_ssa_name(copy_par, NULL);
g = gimple_build_assign(copy_par, p);
SSA_NAME_DEF_STMT(copy_par) = g;
gimple_seq_add_stmt_without_update (&seq, g);
... // more processing here
}
...
gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
但是,这种方式会根据转储创建对变量的参数声明的无效分配:
gimple_assign <parm_decl,D.2206_11,par,NULL>
D.2206_11
对应于我创建的局部变量par
- 我要复制的函数的参数。
结果,GCC 在稍后的某个阶段崩溃,试图处理这个添加的语句。我想这是因为p
不是保存相应参数值的变量,而是该变量的声明。是这样吗?以及如何获得该变量?
我尝试使用gimple_build_assign_with_ops(NOP_EXPR, copy_par, p, NULL_TREE)
而不是,gimple_build_assign()
但它也没有这样做。GCC 仍然在同一个地方崩溃。我可以提供回溯,但我觉得我只是缺少一些基本的东西。
我还查看了从TYPE_ARG_TYPES (TREE_TYPE (current_function_decl))
via 开始并进一步遍历树,TREE_CHAIN(...)
但这似乎给出了参数的类型而不是相应的变量。
所以,问题是,如何正确添加函数参数的复制。
注意 也许,这可以在 MELT 或 GCC Python 插件的帮助下完成,但在这个项目中,我需要仅使用 GCC 本身提供的代码来执行所有代码转换。