Add mypy types for gen_encoding.py.

This commit is contained in:
Jakob Stoklund Olesen
2017-03-30 17:07:24 -07:00
parent c5f2ef8edb
commit 49766bae12

View File

@@ -57,15 +57,21 @@ from collections import OrderedDict, defaultdict
import math import math
import itertools import itertools
from cdsl.registers import RegClass, Register from cdsl.registers import RegClass, Register
from cdsl.predicates import FieldPredicate
try: try:
from typing import Sequence # noqa from typing import Sequence, Set, Tuple, List, Iterable, DefaultDict, TYPE_CHECKING # noqa
from cdsl.isa import TargetISA, OperandConstraint # noqa if TYPE_CHECKING:
from cdsl.isa import TargetISA, OperandConstraint, Encoding, CPUMode # noqa
from cdsl.predicates import PredNode, PredLeaf # noqa
from cdsl.types import ValueType # noqa
from cdsl.instructions import Instruction # noqa
except ImportError: except ImportError:
pass pass
def emit_instp(instp, fmt): def emit_instp(instp, fmt):
# type: (PredNode, srcgen.Formatter) -> None
""" """
Emit code for matching an instruction predicate against an Emit code for matching an instruction predicate against an
`InstructionData` reference called `inst`. `InstructionData` reference called `inst`.
@@ -77,11 +83,15 @@ def emit_instp(instp, fmt):
# Which fields do we need in the InstructionData pattern match? # Which fields do we need in the InstructionData pattern match?
# Collect the leaf predicates. # Collect the leaf predicates.
leafs = set() leafs = set() # type: Set[PredLeaf]
instp.predicate_leafs(leafs) instp.predicate_leafs(leafs)
# All the leafs are FieldPredicate instances. Here we just care about # All the leafs are FieldPredicate instances. Here we just care about
# the field names. # the field names.
fields = ', '.join(sorted(set(p.field.name for p in leafs))) fnames = set() # type: Set[str]
for p in leafs:
assert isinstance(p, FieldPredicate)
fnames.add(p.field.name)
fields = ', '.join(sorted(fnames))
with fmt.indented('{} => {{'.format(instp.number), '}'): with fmt.indented('{} => {{'.format(instp.number), '}'):
with fmt.indented( with fmt.indented(
@@ -91,6 +101,7 @@ def emit_instp(instp, fmt):
def emit_instps(instps, fmt): def emit_instps(instps, fmt):
# type: (Sequence[PredNode], srcgen.Formatter) -> None
""" """
Emit a function for matching instruction predicates. Emit a function for matching instruction predicates.
""" """
@@ -141,6 +152,7 @@ CODE_FAIL = (1 << CODE_BITS) - 1
def seq_doc(enc): def seq_doc(enc):
# type: (Encoding) -> Tuple[Tuple[int, int, int], str]
""" """
Return a tuple containing u16 representations of the instruction predicate Return a tuple containing u16 representations of the instruction predicate
an recipe / encbits. an recipe / encbits.
@@ -169,13 +181,15 @@ class EncList(object):
""" """
def __init__(self, inst, ty): def __init__(self, inst, ty):
# type: (Instruction, ValueType) -> None
self.inst = inst self.inst = inst
self.ty = ty self.ty = ty
# List of applicable Encoding instances. # List of applicable Encoding instances.
# These will have different predicates. # These will have different predicates.
self.encodings = [] self.encodings = [] # type: List[Encoding]
def name(self): def name(self):
# type: () -> str
name = self.inst.name name = self.inst.name
if self.ty: if self.ty:
name = '{}.{}'.format(name, self.ty.name) name = '{}.{}'.format(name, self.ty.name)
@@ -184,6 +198,7 @@ class EncList(object):
return name return name
def by_isap(self): def by_isap(self):
# type: () -> Iterable[Tuple[PredNode, Tuple[Encoding, ...]]]
""" """
Group the encodings by ISA predicate without reordering them. Group the encodings by ISA predicate without reordering them.
@@ -192,17 +207,18 @@ class EncList(object):
have the same ISA predicate. have the same ISA predicate.
""" """
maxlen = CODE_FAIL >> PRED_BITS maxlen = CODE_FAIL >> PRED_BITS
for isap, group in itertools.groupby( for isap, groupi in itertools.groupby(
self.encodings, lambda enc: enc.isap): self.encodings, lambda enc: enc.isap):
group = tuple(group) group = tuple(groupi)
# This probably never happens, but we can't express more than # This probably never happens, but we can't express more than
# maxlen encodings per isap. # maxlen encodings per isap.
while len(group) > maxlen: while len(group) > maxlen:
yield (isap, group[0..maxlen]) yield (isap, group[0:maxlen])
group = group[maxlen:] group = group[maxlen:]
yield (isap, group) yield (isap, group)
def encode(self, seq_table, doc_table, isa): def encode(self, seq_table, doc_table, isa):
# type: (UniqueSeqTable, DefaultDict[int, List[str]], TargetISA) -> None # noqa
""" """
Encode this list as a sequence of u16 numbers. Encode this list as a sequence of u16 numbers.
@@ -211,8 +227,8 @@ class EncList(object):
Adds comment lines to `doc_table` keyed by seq_table offsets. Adds comment lines to `doc_table` keyed by seq_table offsets.
""" """
words = list() words = list() # type: List[int]
docs = list() docs = list() # type: List[Tuple[int, str]]
# Group our encodings by isap. # Group our encodings by isap.
for isap, group in self.by_isap(): for isap, group in self.by_isap():
@@ -249,21 +265,25 @@ class Level2Table(object):
""" """
def __init__(self, ty): def __init__(self, ty):
# type: (ValueType) -> None
self.ty = ty self.ty = ty
# Maps inst -> EncList # Maps inst -> EncList
self.lists = OrderedDict() self.lists = OrderedDict() # type: OrderedDict[Instruction, EncList]
def __getitem__(self, inst): def __getitem__(self, inst):
# type: (Instruction) -> EncList
ls = self.lists.get(inst) ls = self.lists.get(inst)
if not ls: if not ls:
ls = EncList(inst, self.ty) ls = EncList(inst, self.ty)
self.lists[inst] = ls self.lists[inst] = ls
return ls return ls
def __iter__(self): def enclists(self):
# type: () -> Iterable[EncList]
return iter(self.lists.values()) return iter(self.lists.values())
def layout_hashtable(self, level2_hashtables, level2_doc): def layout_hashtable(self, level2_hashtables, level2_doc):
# type: (List[EncList], DefaultDict[int, List[str]]) -> None
""" """
Compute the hash table mapping opcode -> enclist. Compute the hash table mapping opcode -> enclist.
@@ -290,20 +310,24 @@ class Level1Table(object):
""" """
def __init__(self): def __init__(self):
self.tables = OrderedDict() # type: () -> None
self.tables = OrderedDict() # type: OrderedDict[ValueType, Level2Table] # noqa
def __getitem__(self, ty): def __getitem__(self, ty):
# type: (ValueType) -> Level2Table
tbl = self.tables.get(ty) tbl = self.tables.get(ty)
if not tbl: if not tbl:
tbl = Level2Table(ty) tbl = Level2Table(ty)
self.tables[ty] = tbl self.tables[ty] = tbl
return tbl return tbl
def __iter__(self): def l2tables(self):
# type: () -> Iterable[Level2Table]
return iter(self.tables.values()) return iter(self.tables.values())
def make_tables(cpumode): def make_tables(cpumode):
# type: (CPUMode) -> Level1Table
""" """
Generate tables for `cpumode` as described above. Generate tables for `cpumode` as described above.
""" """
@@ -316,15 +340,17 @@ def make_tables(cpumode):
def encode_enclists(level1, seq_table, doc_table, isa): def encode_enclists(level1, seq_table, doc_table, isa):
# type: (Level1Table, UniqueSeqTable, DefaultDict[int, List[str]], TargetISA) -> None # noqa
""" """
Compute encodings and doc comments for encoding lists in `level1`. Compute encodings and doc comments for encoding lists in `level1`.
""" """
for level2 in level1: for level2 in level1.l2tables():
for enclist in level2: for enclist in level2.enclists():
enclist.encode(seq_table, doc_table, isa) enclist.encode(seq_table, doc_table, isa)
def emit_enclists(seq_table, doc_table, fmt): def emit_enclists(seq_table, doc_table, fmt):
# type: (UniqueSeqTable, DefaultDict[int, List[str]], srcgen.Formatter) -> None # noqa
with fmt.indented( with fmt.indented(
'pub static ENCLISTS: [u16; {}] = ['.format(len(seq_table.table)), 'pub static ENCLISTS: [u16; {}] = ['.format(len(seq_table.table)),
'];'): '];'):
@@ -342,11 +368,13 @@ def emit_enclists(seq_table, doc_table, fmt):
def encode_level2_hashtables(level1, level2_hashtables, level2_doc): def encode_level2_hashtables(level1, level2_hashtables, level2_doc):
for level2 in level1: # type: (Level1Table, List[EncList], DefaultDict[int, List[str]]) -> None
for level2 in level1.l2tables():
level2.layout_hashtable(level2_hashtables, level2_doc) level2.layout_hashtable(level2_hashtables, level2_doc)
def emit_level2_hashtables(level2_hashtables, offt, level2_doc, fmt): def emit_level2_hashtables(level2_hashtables, offt, level2_doc, fmt):
# type: (List[EncList], str, DefaultDict[int, List[str]], srcgen.Formatter) -> None # noqa
""" """
Emit the big concatenation of level 2 hash tables. Emit the big concatenation of level 2 hash tables.
""" """
@@ -370,6 +398,7 @@ def emit_level2_hashtables(level2_hashtables, offt, level2_doc, fmt):
def emit_level1_hashtable(cpumode, level1, offt, fmt): def emit_level1_hashtable(cpumode, level1, offt, fmt):
# type: (CPUMode, Level1Table, str, srcgen.Formatter) -> None # noqa
""" """
Emit a level 1 hash table for `cpumode`. Emit a level 1 hash table for `cpumode`.
""" """
@@ -399,6 +428,7 @@ def emit_level1_hashtable(cpumode, level1, offt, fmt):
def offset_type(length): def offset_type(length):
# type: (int) -> str
""" """
Compute an appropriate Rust integer type to use for offsets into a table of Compute an appropriate Rust integer type to use for offsets into a table of
the given length. the given length.
@@ -467,6 +497,7 @@ def emit_operand_constraints(seq, field, fmt):
def gen_isa(isa, fmt): def gen_isa(isa, fmt):
# type: (TargetISA, srcgen.Formatter) -> None
# First assign numbers to relevant instruction predicates and generate the # First assign numbers to relevant instruction predicates and generate the
# check_instp() function.. # check_instp() function..
emit_instps(isa.all_instps, fmt) emit_instps(isa.all_instps, fmt)
@@ -476,11 +507,11 @@ def gen_isa(isa, fmt):
# Tables for enclists with comments. # Tables for enclists with comments.
seq_table = UniqueSeqTable() seq_table = UniqueSeqTable()
doc_table = defaultdict(list) doc_table = defaultdict(list) # type: DefaultDict[int, List[str]]
# Single table containing all the level2 hash tables. # Single table containing all the level2 hash tables.
level2_hashtables = list() level2_hashtables = list() # type: List[EncList]
level2_doc = defaultdict(list) level2_doc = defaultdict(list) # type: DefaultDict[int, List[str]]
for cpumode in isa.cpumodes: for cpumode in isa.cpumodes:
level2_doc[len(level2_hashtables)].append(cpumode.name) level2_doc[len(level2_hashtables)].append(cpumode.name)
@@ -505,6 +536,7 @@ def gen_isa(isa, fmt):
def generate(isas, out_dir): def generate(isas, out_dir):
# type: (Sequence[TargetISA], str) -> None
for isa in isas: for isa in isas:
fmt = srcgen.Formatter() fmt = srcgen.Formatter()
gen_isa(isa, fmt) gen_isa(isa, fmt)