| from llvmlite.ir import CallInstr |
|
|
|
|
| class Visitor(object): |
| def visit(self, module): |
| self._module = module |
| for func in module.functions: |
| self.visit_Function(func) |
|
|
| def visit_Function(self, func): |
| self._function = func |
| for bb in func.blocks: |
| self.visit_BasicBlock(bb) |
|
|
| def visit_BasicBlock(self, bb): |
| self._basic_block = bb |
| for instr in bb.instructions: |
| self.visit_Instruction(instr) |
|
|
| def visit_Instruction(self, instr): |
| raise NotImplementedError |
|
|
| @property |
| def module(self): |
| return self._module |
|
|
| @property |
| def function(self): |
| return self._function |
|
|
| @property |
| def basic_block(self): |
| return self._basic_block |
|
|
|
|
| class CallVisitor(Visitor): |
| def visit_Instruction(self, instr): |
| if isinstance(instr, CallInstr): |
| self.visit_Call(instr) |
|
|
| def visit_Call(self, instr): |
| raise NotImplementedError |
|
|
|
|
| class ReplaceCalls(CallVisitor): |
| def __init__(self, orig, repl): |
| super(ReplaceCalls, self).__init__() |
| self.orig = orig |
| self.repl = repl |
| self.calls = [] |
|
|
| def visit_Call(self, instr): |
| if instr.callee == self.orig: |
| instr.replace_callee(self.repl) |
| self.calls.append(instr) |
|
|
|
|
| def replace_all_calls(mod, orig, repl): |
| """Replace all calls to `orig` to `repl` in module `mod`. |
| Returns the references to the returned calls |
| """ |
| rc = ReplaceCalls(orig, repl) |
| rc.visit(mod) |
| return rc.calls |
|
|