Llvm 如何获取表达式上所有操作数的内存地址
我有一些表达式,如Llvm 如何获取表达式上所有操作数的内存地址,llvm,llvm-clang,llvm-3.0,llvm-ir,Llvm,Llvm Clang,Llvm 3.0,Llvm Ir,我有一些表达式,如a=b+c-d*e,在LLVM pass的帮助下,我想制作一个如下的字符串 “[b'的十六进制地址][c'的十六进制地址][c'的十六进制地址][d'的十六进制地址][d'的十六进制地址][e'的十六进制地址][操作码*] 首先,记住变量不一定存在于内存中;它们可以存储在寄存器中,也可以完全省略。在LLVM IR的上下文中,这意味着该值将直接从另一个值使用(无存储或加载) 假设所有涉及的变量都需要从内存中加载,我能想到的最简单的方法是定位存储,然后通过操作数向后执行后序DFS,
a=b+c-d*e
,在LLVM pass的帮助下,我想制作一个如下的字符串
“[b'的十六进制地址][c'的十六进制地址][c'的十六进制地址][d'的十六进制地址][d'的十六进制地址][e'的十六进制地址][操作码*]
首先,记住变量不一定存在于内存中;它们可以存储在寄存器中,也可以完全省略。在LLVM IR的上下文中,这意味着该值将直接从另一个值使用(无存储或加载) 假设所有涉及的变量都需要从内存中加载,我能想到的最简单的方法是定位
存储
,然后通过操作数向后执行后序DFS,记录操作码,并在识别加载时停止。对于您提供的代码段,它应该给您b的负载,然后加上操作码,然后是c的负载,然后减去操作码,等等
现在您已经有了这样一个序列,我想说从中生成字符串的最简单方法是使用动态构建的格式字符串插入对C的sprintf
的调用,并将找到的指针传递给它(从中加载)
不过,我认为上述问题有两个:
(b+c-d)*e
与b+(c-d)*e
。因此,我认为在输入算术指令和离开算术指令时,分别记录“(”和“)”是有意义的tmp=b+c;a=tmp-d*e代码>,并且tmp
被优化掉,那么它在IR中的外观将相同。我唯一能想到的强制执行方法是使用调试符号编译并深入挖掘这些符号以识别不同的表达式(尽管我真的不知道这是否可行),或者实际修改Clang以记录表达式边界:\
functionPass:
对于每个指令:
如果指令被存储:
processExpression(存储)
processExpression(存储):
因为您需要地址,所以在编译期间无法完全构造这样的字符串。。。您是否希望将printf
调用注入代码或类似的内容?另外,请记住,您需要确保所有变量都实际驻留在内存中。实际上,我想将此字符串作为参数传递给函数(假设它只在stdout上打印),并且在每个存储指令之前调用此函数。你知道怎么做吗。“use def”在这个场景中有什么用吗?@AbhinashJain当然,但你需要递归调用它-它只给你立即的操作数,而你也需要操作数的操作数,依此类推(直到load
s)。但我将在哪个加载点停止(最近的还是最旧的)?我的意思是在不同的表达式上会有不同数量的操作数,因此也会有不同数量的加载操作。那么,如何有效地使用“use def”来实现这一目的呢?@AbhinashJain我的意思是,在遇到加载
-换句话说,当看到加载
时,添加指向序列的指针,并且不要继续访问加载
的操作数。load
s的数量应该与表达式中变量的数量相同(我在上面的回答中提到了注意事项)。是的,我得到了您的DFS概念,但仍然不确定的是,我如何知道表达式中变量的数量?
functionPass:
for each instruction:
if instruction is store:
processExpression(store)
processExpression(store):
sequence <- initialize
visit(sequence, store.value)
generateSprintfCallFromSequence(sequence)
visit(sequence, value):
if value is load:
sequence.add(load.pointer)
else if value is binaryop:
// sequence.add(openingParen)
visit(sequence, binaryop.operand(0))
sequence.add(binaryop.opcode)
visit(sequence, binaryop.operand(1))
// sequence.add(closingParen);