mirror of https://github.com/m-labs/artiq.git
transforms.artiq_ir_generator: devirtualize method calls.
This commit is contained in:
parent
b6c8c9f480
commit
48f1f48f09
|
@ -6,9 +6,9 @@ but without too much detail, such as exposing the reference/value
|
|||
semantics explicitly.
|
||||
"""
|
||||
|
||||
from collections import OrderedDict
|
||||
from collections import OrderedDict, defaultdict
|
||||
from pythonparser import algorithm, diagnostic, ast
|
||||
from .. import types, builtins, ir
|
||||
from .. import types, builtins, asttyped, ir
|
||||
|
||||
def _readable_name(insn):
|
||||
if isinstance(insn, ir.Constant):
|
||||
|
@ -100,18 +100,27 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
|||
self.unwind_target = None
|
||||
self.function_map = dict()
|
||||
self.variable_map = dict()
|
||||
self.method_map = dict()
|
||||
self.method_map = defaultdict(lambda: [])
|
||||
|
||||
def annotate_calls(self, devirtualization):
|
||||
for var_node in devirtualization.variable_map:
|
||||
callee_node = devirtualization.variable_map[var_node]
|
||||
callee = self.function_map[callee_node]
|
||||
|
||||
call_target = self.variable_map[var_node]
|
||||
for use in call_target.uses:
|
||||
if isinstance(use, (ir.Call, ir.Invoke)) and \
|
||||
use.target_function() == call_target:
|
||||
use.static_target_function = callee
|
||||
|
||||
for type_and_method in devirtualization.method_map:
|
||||
callee_node = devirtualization.method_map[type_and_method]
|
||||
callee = self.function_map[callee_node]
|
||||
|
||||
for call in self.method_map[type_and_method]:
|
||||
assert isinstance(call, (ir.Call, ir.Invoke))
|
||||
call.static_target_function = callee
|
||||
|
||||
def add_block(self, name=""):
|
||||
block = ir.BasicBlock([], name)
|
||||
self.current_function.add(block)
|
||||
|
@ -1553,12 +1562,18 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
|||
assert None not in args
|
||||
|
||||
if self.unwind_target is None:
|
||||
return self.append(ir.Call(func, args))
|
||||
insn = self.append(ir.Call(func, args))
|
||||
else:
|
||||
after_invoke = self.add_block()
|
||||
invoke = self.append(ir.Invoke(func, args, after_invoke, self.unwind_target))
|
||||
insn = self.append(ir.Invoke(func, args, after_invoke, self.unwind_target))
|
||||
self.current_block = after_invoke
|
||||
return invoke
|
||||
|
||||
method_key = None
|
||||
if isinstance(node.func, asttyped.AttributeT):
|
||||
attr_node = node.func
|
||||
self.method_map[(attr_node.value.type, attr_node.attr)].append(insn)
|
||||
|
||||
return insn
|
||||
|
||||
def visit_QuoteT(self, node):
|
||||
return self.append(ir.Quote(node.value, node.type))
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
# RUN: env ARTIQ_DUMP_IR=1 %python -m artiq.compiler.testbench.embedding +compile %s 2>%t
|
||||
# RUN: OutputCheck %s --file-to-check=%t
|
||||
|
||||
from artiq.language.core import *
|
||||
from artiq.language.types import *
|
||||
|
||||
class foo:
|
||||
@kernel
|
||||
def bar(self):
|
||||
pass
|
||||
x = foo()
|
||||
|
||||
@kernel
|
||||
def entrypoint():
|
||||
# CHECK-L: ; calls testbench.foo.bar
|
||||
x.bar()
|
Loading…
Reference in New Issue