2014-06-18 33 views
2

我开发了一个GCC插件,用于检测正在编译的应用程序。应用程序使用C语言编写,并且在x86 Linux系统上使用GCC 4.7(4.8和4.9也是选件)构建。GCC插件:复制函数的参数

我的插件实现了一个编译过程,放在“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(),但它也没有。海湾合作委员会仍然在同一地点崩溃。我可以提供回溯,但我觉得我只是缺少一些基本的东西。

我还查看了从TYPE_ARG_TYPES (TREE_TYPE (current_function_decl))开始并进一步通过TREE_CHAIN(...)树的遍历,但似乎给出了参数的类型而不是各自的变量。

所以,问题是,如何正确添加函数参数的拷贝。

注意 也许,这可能是与熔体或GCC的Python插件的帮助下完成的,但在这个项目中,我需要执行只有本身就提供什么GCC使用的代码的所有转换。

回答

2

我发现参数的复制与GCC 4.8和4.9一起使用,但不与4.7一起使用。 Here is the code现在适合我(instrument_fentry()执行复制)。

为了避免在稍后的编译过程中删除副本,我将相应的变量设置为volatile。此外,如果没有为给定参数指定默认定义语句的SSA_NAME(请参见SSA_NAME_IS_DEFAULT_DEF()),我添加了带有GIMPLE_NOPs的SSA_NAME作为定义语句。

到目前为止,这对GCC 4.8和4.9有效,所以它看起来像GCC 4.7中的错误或GCC 4.7和4.8之间的规则更改。尽管如此,我仍然无法确定确切的承诺。

+0

'get_or_create_ssa_default_def'? –

+0

@MarcGlisse:你的意思是使用'get_or_create_ssa_default_def'而不是手动插入GIMPLE_NOPs?也许吧。保存一些输入。 – Eugene