init
This commit is contained in:
commit
38355d2442
9083 changed files with 1225834 additions and 0 deletions
315
.venv/lib/python3.8/site-packages/mypyc/ir/func_ir.py
Normal file
315
.venv/lib/python3.8/site-packages/mypyc/ir/func_ir.py
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
"""Intermediate representation of functions."""
|
||||
|
||||
from typing import List, Optional, Sequence
|
||||
from typing_extensions import Final
|
||||
|
||||
from mypy.nodes import FuncDef, Block, ArgKind, ARG_POS
|
||||
|
||||
from mypyc.common import JsonDict, get_id_from_name, short_id_from_name
|
||||
from mypyc.ir.ops import (
|
||||
DeserMaps, BasicBlock, Value, Register, Assign, AssignMulti, ControlOp, LoadAddress
|
||||
)
|
||||
from mypyc.ir.rtypes import RType, deserialize_type
|
||||
from mypyc.namegen import NameGenerator
|
||||
|
||||
|
||||
class RuntimeArg:
|
||||
"""Description of a function argument in IR.
|
||||
|
||||
Argument kind is one of ARG_* constants defined in mypy.nodes.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, name: str, typ: RType, kind: ArgKind = ARG_POS, pos_only: bool = False) -> None:
|
||||
self.name = name
|
||||
self.type = typ
|
||||
self.kind = kind
|
||||
self.pos_only = pos_only
|
||||
|
||||
@property
|
||||
def optional(self) -> bool:
|
||||
return self.kind.is_optional()
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return 'RuntimeArg(name=%s, type=%s, optional=%r, pos_only=%r)' % (
|
||||
self.name, self.type, self.optional, self.pos_only)
|
||||
|
||||
def serialize(self) -> JsonDict:
|
||||
return {'name': self.name, 'type': self.type.serialize(), 'kind': int(self.kind.value),
|
||||
'pos_only': self.pos_only}
|
||||
|
||||
@classmethod
|
||||
def deserialize(cls, data: JsonDict, ctx: DeserMaps) -> 'RuntimeArg':
|
||||
return RuntimeArg(
|
||||
data['name'],
|
||||
deserialize_type(data['type'], ctx),
|
||||
ArgKind(data['kind']),
|
||||
data['pos_only'],
|
||||
)
|
||||
|
||||
|
||||
class FuncSignature:
|
||||
"""Signature of a function in IR."""
|
||||
|
||||
# TODO: Track if method?
|
||||
|
||||
def __init__(self, args: Sequence[RuntimeArg], ret_type: RType) -> None:
|
||||
self.args = tuple(args)
|
||||
self.ret_type = ret_type
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return 'FuncSignature(args=%r, ret=%r)' % (self.args, self.ret_type)
|
||||
|
||||
def serialize(self) -> JsonDict:
|
||||
return {'args': [t.serialize() for t in self.args], 'ret_type': self.ret_type.serialize()}
|
||||
|
||||
@classmethod
|
||||
def deserialize(cls, data: JsonDict, ctx: DeserMaps) -> 'FuncSignature':
|
||||
return FuncSignature(
|
||||
[RuntimeArg.deserialize(arg, ctx) for arg in data['args']],
|
||||
deserialize_type(data['ret_type'], ctx),
|
||||
)
|
||||
|
||||
|
||||
FUNC_NORMAL: Final = 0
|
||||
FUNC_STATICMETHOD: Final = 1
|
||||
FUNC_CLASSMETHOD: Final = 2
|
||||
|
||||
|
||||
class FuncDecl:
|
||||
"""Declaration of a function in IR (without body or implementation).
|
||||
|
||||
A function can be a regular module-level function, a method, a
|
||||
static method, a class method, or a property getter/setter.
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
name: str,
|
||||
class_name: Optional[str],
|
||||
module_name: str,
|
||||
sig: FuncSignature,
|
||||
kind: int = FUNC_NORMAL,
|
||||
is_prop_setter: bool = False,
|
||||
is_prop_getter: bool = False) -> None:
|
||||
self.name = name
|
||||
self.class_name = class_name
|
||||
self.module_name = module_name
|
||||
self.sig = sig
|
||||
self.kind = kind
|
||||
self.is_prop_setter = is_prop_setter
|
||||
self.is_prop_getter = is_prop_getter
|
||||
if class_name is None:
|
||||
self.bound_sig: Optional[FuncSignature] = None
|
||||
else:
|
||||
if kind == FUNC_STATICMETHOD:
|
||||
self.bound_sig = sig
|
||||
else:
|
||||
self.bound_sig = FuncSignature(sig.args[1:], sig.ret_type)
|
||||
|
||||
# this is optional because this will be set to the line number when the corresponding
|
||||
# FuncIR is created
|
||||
self._line: Optional[int] = None
|
||||
|
||||
@property
|
||||
def line(self) -> int:
|
||||
assert self._line is not None
|
||||
return self._line
|
||||
|
||||
@line.setter
|
||||
def line(self, line: int) -> None:
|
||||
self._line = line
|
||||
|
||||
@property
|
||||
def id(self) -> str:
|
||||
assert self.line is not None
|
||||
return get_id_from_name(self.name, self.fullname, self.line)
|
||||
|
||||
@staticmethod
|
||||
def compute_shortname(class_name: Optional[str], name: str) -> str:
|
||||
return class_name + '.' + name if class_name else name
|
||||
|
||||
@property
|
||||
def shortname(self) -> str:
|
||||
return FuncDecl.compute_shortname(self.class_name, self.name)
|
||||
|
||||
@property
|
||||
def fullname(self) -> str:
|
||||
return self.module_name + '.' + self.shortname
|
||||
|
||||
def cname(self, names: NameGenerator) -> str:
|
||||
partial_name = short_id_from_name(self.name, self.shortname, self._line)
|
||||
return names.private_name(self.module_name, partial_name)
|
||||
|
||||
def serialize(self) -> JsonDict:
|
||||
return {
|
||||
'name': self.name,
|
||||
'class_name': self.class_name,
|
||||
'module_name': self.module_name,
|
||||
'sig': self.sig.serialize(),
|
||||
'kind': self.kind,
|
||||
'is_prop_setter': self.is_prop_setter,
|
||||
'is_prop_getter': self.is_prop_getter,
|
||||
}
|
||||
|
||||
# TODO: move this to FuncIR?
|
||||
@staticmethod
|
||||
def get_id_from_json(func_ir: JsonDict) -> str:
|
||||
"""Get the id from the serialized FuncIR associated with this FuncDecl"""
|
||||
decl = func_ir['decl']
|
||||
shortname = FuncDecl.compute_shortname(decl['class_name'], decl['name'])
|
||||
fullname = decl['module_name'] + '.' + shortname
|
||||
return get_id_from_name(decl['name'], fullname, func_ir['line'])
|
||||
|
||||
@classmethod
|
||||
def deserialize(cls, data: JsonDict, ctx: DeserMaps) -> 'FuncDecl':
|
||||
return FuncDecl(
|
||||
data['name'],
|
||||
data['class_name'],
|
||||
data['module_name'],
|
||||
FuncSignature.deserialize(data['sig'], ctx),
|
||||
data['kind'],
|
||||
data['is_prop_setter'],
|
||||
data['is_prop_getter'],
|
||||
)
|
||||
|
||||
|
||||
class FuncIR:
|
||||
"""Intermediate representation of a function with contextual information.
|
||||
|
||||
Unlike FuncDecl, this includes the IR of the body (basic blocks).
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
decl: FuncDecl,
|
||||
arg_regs: List[Register],
|
||||
blocks: List[BasicBlock],
|
||||
line: int = -1,
|
||||
traceback_name: Optional[str] = None) -> None:
|
||||
# Declaration of the function, including the signature
|
||||
self.decl = decl
|
||||
# Registers for all the arguments to the function
|
||||
self.arg_regs = arg_regs
|
||||
# Body of the function
|
||||
self.blocks = blocks
|
||||
self.decl.line = line
|
||||
# The name that should be displayed for tracebacks that
|
||||
# include this function. Function will be omitted from
|
||||
# tracebacks if None.
|
||||
self.traceback_name = traceback_name
|
||||
|
||||
@property
|
||||
def line(self) -> int:
|
||||
return self.decl.line
|
||||
|
||||
@property
|
||||
def args(self) -> Sequence[RuntimeArg]:
|
||||
return self.decl.sig.args
|
||||
|
||||
@property
|
||||
def ret_type(self) -> RType:
|
||||
return self.decl.sig.ret_type
|
||||
|
||||
@property
|
||||
def class_name(self) -> Optional[str]:
|
||||
return self.decl.class_name
|
||||
|
||||
@property
|
||||
def sig(self) -> FuncSignature:
|
||||
return self.decl.sig
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return self.decl.name
|
||||
|
||||
@property
|
||||
def fullname(self) -> str:
|
||||
return self.decl.fullname
|
||||
|
||||
@property
|
||||
def id(self) -> str:
|
||||
return self.decl.id
|
||||
|
||||
def cname(self, names: NameGenerator) -> str:
|
||||
return self.decl.cname(names)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
if self.class_name:
|
||||
return '<FuncIR {}.{}>'.format(self.class_name, self.name)
|
||||
else:
|
||||
return '<FuncIR {}>'.format(self.name)
|
||||
|
||||
def serialize(self) -> JsonDict:
|
||||
# We don't include blocks in the serialized version
|
||||
return {
|
||||
'decl': self.decl.serialize(),
|
||||
'line': self.line,
|
||||
'traceback_name': self.traceback_name,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def deserialize(cls, data: JsonDict, ctx: DeserMaps) -> 'FuncIR':
|
||||
return FuncIR(
|
||||
FuncDecl.deserialize(data['decl'], ctx),
|
||||
[],
|
||||
[],
|
||||
data['line'],
|
||||
data['traceback_name'],
|
||||
)
|
||||
|
||||
|
||||
INVALID_FUNC_DEF: Final = FuncDef("<INVALID_FUNC_DEF>", [], Block([]))
|
||||
|
||||
|
||||
def all_values(args: List[Register], blocks: List[BasicBlock]) -> List[Value]:
|
||||
"""Return the set of all values that may be initialized in the blocks.
|
||||
|
||||
This omits registers that are only read.
|
||||
"""
|
||||
values: List[Value] = list(args)
|
||||
seen_registers = set(args)
|
||||
|
||||
for block in blocks:
|
||||
for op in block.ops:
|
||||
if not isinstance(op, ControlOp):
|
||||
if isinstance(op, (Assign, AssignMulti)):
|
||||
if op.dest not in seen_registers:
|
||||
values.append(op.dest)
|
||||
seen_registers.add(op.dest)
|
||||
elif op.is_void:
|
||||
continue
|
||||
else:
|
||||
# If we take the address of a register, it might get initialized.
|
||||
if (isinstance(op, LoadAddress)
|
||||
and isinstance(op.src, Register)
|
||||
and op.src not in seen_registers):
|
||||
values.append(op.src)
|
||||
seen_registers.add(op.src)
|
||||
values.append(op)
|
||||
|
||||
return values
|
||||
|
||||
|
||||
def all_values_full(args: List[Register], blocks: List[BasicBlock]) -> List[Value]:
|
||||
"""Return set of all values that are initialized or accessed."""
|
||||
values: List[Value] = list(args)
|
||||
seen_registers = set(args)
|
||||
|
||||
for block in blocks:
|
||||
for op in block.ops:
|
||||
for source in op.sources():
|
||||
# Look for uninitialized registers that are accessed. Ignore
|
||||
# non-registers since we don't allow ops outside basic blocks.
|
||||
if isinstance(source, Register) and source not in seen_registers:
|
||||
values.append(source)
|
||||
seen_registers.add(source)
|
||||
if not isinstance(op, ControlOp):
|
||||
if isinstance(op, (Assign, AssignMulti)):
|
||||
if op.dest not in seen_registers:
|
||||
values.append(op.dest)
|
||||
seen_registers.add(op.dest)
|
||||
elif op.is_void:
|
||||
continue
|
||||
else:
|
||||
values.append(op)
|
||||
|
||||
return values
|
||||
Loading…
Add table
Add a link
Reference in a new issue