Add support for custom legalization actions.
The custom_legalize() method on XFormGroup can be used to call a custom function to legalize specific opcodes. This will be used shortly to expand global_addr which has an expansion that depends on the details of the global variable being referenced.
This commit is contained in:
@@ -4,6 +4,7 @@ Instruction transformations.
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from .ast import Def, Var, Apply
|
from .ast import Def, Var, Apply
|
||||||
from .ti import ti_xform, TypeEnv, get_type_env, TypeConstraint
|
from .ti import ti_xform, TypeEnv, get_type_env, TypeConstraint
|
||||||
|
from collections import OrderedDict
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -12,7 +13,7 @@ try:
|
|||||||
from .ast import Expr, VarAtomMap # noqa
|
from .ast import Expr, VarAtomMap # noqa
|
||||||
from .isa import TargetISA # noqa
|
from .isa import TargetISA # noqa
|
||||||
from .typevar import TypeVar # noqa
|
from .typevar import TypeVar # noqa
|
||||||
from .instructions import ConstrList # noqa
|
from .instructions import ConstrList, Instruction # noqa
|
||||||
DefApply = Union[Def, Apply]
|
DefApply = Union[Def, Apply]
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
@@ -370,6 +371,7 @@ class XFormGroup(object):
|
|||||||
def __init__(self, name, doc, isa=None, chain=None):
|
def __init__(self, name, doc, isa=None, chain=None):
|
||||||
# type: (str, str, TargetISA, XFormGroup) -> None
|
# type: (str, str, TargetISA, XFormGroup) -> None
|
||||||
self.xforms = list() # type: List[XForm]
|
self.xforms = list() # type: List[XForm]
|
||||||
|
self.custom = OrderedDict() # type: OrderedDict[Instruction, str]
|
||||||
self.name = name
|
self.name = name
|
||||||
self.__doc__ = doc
|
self.__doc__ = doc
|
||||||
self.isa = isa
|
self.isa = isa
|
||||||
@@ -405,3 +407,17 @@ class XFormGroup(object):
|
|||||||
xform = XForm(Rtl(src), dst)
|
xform = XForm(Rtl(src), dst)
|
||||||
xform.verify_legalize()
|
xform.verify_legalize()
|
||||||
self.xforms.append(xform)
|
self.xforms.append(xform)
|
||||||
|
|
||||||
|
def custom_legalize(self, inst, funcname):
|
||||||
|
# type: (Instruction, str) -> None
|
||||||
|
"""
|
||||||
|
Add a custom legalization action for `inst`.
|
||||||
|
|
||||||
|
The `funcname` parameter is the fully qualified name of a Rust function
|
||||||
|
which takes the same arguments as the `isa::Legalize` actions.
|
||||||
|
|
||||||
|
The custom function will be called to legalize `inst` and any return
|
||||||
|
value is ignored.
|
||||||
|
"""
|
||||||
|
assert inst not in self.custom, "Duplicate custom_legalize"
|
||||||
|
self.custom[inst] = funcname
|
||||||
|
|||||||
@@ -367,16 +367,27 @@ def gen_xform_group(xgrp, fmt, type_sets):
|
|||||||
xforms[inst.camel_name].append(xform)
|
xforms[inst.camel_name].append(xform)
|
||||||
|
|
||||||
with fmt.indented('{', '}'):
|
with fmt.indented('{', '}'):
|
||||||
fmt.line(
|
with fmt.indented('match func.dfg[inst].opcode() {', '}'):
|
||||||
'let pos = &mut ir::Cursor::new(&mut func.layout)'
|
|
||||||
'.at_inst(inst);')
|
|
||||||
fmt.line('let dfg = &mut func.dfg;')
|
|
||||||
with fmt.indented('match dfg[inst].opcode() {', '}'):
|
|
||||||
for camel_name in sorted(xforms.keys()):
|
for camel_name in sorted(xforms.keys()):
|
||||||
with fmt.indented(
|
with fmt.indented(
|
||||||
'ir::Opcode::{} => {{'.format(camel_name), '}'):
|
'ir::Opcode::{} => {{'.format(camel_name), '}'):
|
||||||
|
fmt.line(
|
||||||
|
'let pos = &mut '
|
||||||
|
'ir::Cursor::new(&mut func.layout)'
|
||||||
|
'.at_inst(inst);')
|
||||||
|
fmt.line('let dfg = &mut func.dfg;')
|
||||||
for xform in xforms[camel_name]:
|
for xform in xforms[camel_name]:
|
||||||
gen_xform(xform, fmt, type_sets)
|
gen_xform(xform, fmt, type_sets)
|
||||||
|
|
||||||
|
# Emit the custom transforms. The Rust compiler will complain
|
||||||
|
# about any overlap with the normal xforms.
|
||||||
|
for inst, funcname in xgrp.custom.items():
|
||||||
|
with fmt.indented(
|
||||||
|
'ir::Opcode::{} => {{'
|
||||||
|
.format(inst.camel_name), '}'):
|
||||||
|
fmt.format('{}(inst, func, cfg);', funcname)
|
||||||
|
fmt.line('return true;')
|
||||||
|
|
||||||
# We'll assume there are uncovered opcodes.
|
# We'll assume there are uncovered opcodes.
|
||||||
fmt.line('_ => {},')
|
fmt.line('_ => {},')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user