mirror of
https://github.com/python/cpython.git
synced 2025-07-07 19:35:27 +00:00
GH-135379: Remove types from stack items in code generator. (GH-135384)
* Make casts explicit in the instruction definitions
This commit is contained in:
parent
49d72365cd
commit
c87b5b2cb6
13 changed files with 257 additions and 255 deletions
|
@ -135,15 +135,13 @@ class Flush:
|
|||
@dataclass
|
||||
class StackItem:
|
||||
name: str
|
||||
type: str | None
|
||||
size: str
|
||||
peek: bool = False
|
||||
used: bool = False
|
||||
|
||||
def __str__(self) -> str:
|
||||
size = f"[{self.size}]" if self.size else ""
|
||||
type = "" if self.type is None else f"{self.type} "
|
||||
return f"{type}{self.name}{size} {self.peek}"
|
||||
return f"{self.name}{size} {self.peek}"
|
||||
|
||||
def is_array(self) -> bool:
|
||||
return self.size != ""
|
||||
|
@ -345,7 +343,7 @@ def override_error(
|
|||
def convert_stack_item(
|
||||
item: parser.StackEffect, replace_op_arg_1: str | None
|
||||
) -> StackItem:
|
||||
return StackItem(item.name, item.type, item.size)
|
||||
return StackItem(item.name, item.size)
|
||||
|
||||
def check_unused(stack: list[StackItem], input_names: dict[str, lexer.Token]) -> None:
|
||||
"Unused items cannot be on the stack above used, non-peek items"
|
||||
|
@ -683,6 +681,8 @@ NON_ESCAPING_FUNCTIONS = (
|
|||
"PyStackRef_IsNullOrInt",
|
||||
"PyStackRef_IsError",
|
||||
"PyStackRef_IsValid",
|
||||
"PyStackRef_Wrap",
|
||||
"PyStackRef_Unwrap",
|
||||
)
|
||||
|
||||
|
||||
|
@ -811,7 +811,7 @@ def stack_effect_only_peeks(instr: parser.InstDef) -> bool:
|
|||
if len(stack_inputs) == 0:
|
||||
return False
|
||||
return all(
|
||||
(s.name == other.name and s.type == other.type and s.size == other.size)
|
||||
(s.name == other.name and s.size == other.size)
|
||||
for s, other in zip(stack_inputs, instr.outputs)
|
||||
)
|
||||
|
||||
|
|
|
@ -56,9 +56,7 @@ def root_relative_path(filename: str) -> str:
|
|||
|
||||
|
||||
def type_and_null(var: StackItem) -> tuple[str, str]:
|
||||
if var.type:
|
||||
return var.type, "NULL"
|
||||
elif var.is_array():
|
||||
if var.is_array():
|
||||
return "_PyStackRef *", "NULL"
|
||||
else:
|
||||
return "_PyStackRef", "PyStackRef_NULL"
|
||||
|
|
|
@ -73,8 +73,6 @@ def validate_uop(override: Uop, uop: Uop) -> None:
|
|||
def type_name(var: StackItem) -> str:
|
||||
if var.is_array():
|
||||
return "JitOptSymbol **"
|
||||
if var.type:
|
||||
return var.type
|
||||
return "JitOptSymbol *"
|
||||
|
||||
|
||||
|
@ -230,7 +228,7 @@ def generate_abstract_interpreter(
|
|||
declare_variables(override, out, skip_inputs=False)
|
||||
else:
|
||||
declare_variables(uop, out, skip_inputs=True)
|
||||
stack = Stack(extract_bits=False, cast_type="JitOptSymbol *")
|
||||
stack = Stack()
|
||||
write_uop(override, uop, out, stack, debug, skip_inputs=(override is None))
|
||||
out.start_line()
|
||||
out.emit("break;\n")
|
||||
|
|
|
@ -247,12 +247,11 @@ class SimpleStmt(Stmt):
|
|||
@dataclass
|
||||
class StackEffect(Node):
|
||||
name: str = field(compare=False) # __eq__ only uses type, cond, size
|
||||
type: str = "" # Optional `:type`
|
||||
size: str = "" # Optional `[size]`
|
||||
# Note: size cannot be combined with type or cond
|
||||
|
||||
def __repr__(self) -> str:
|
||||
items = [self.name, self.type, self.size]
|
||||
items = [self.name, self.size]
|
||||
while items and items[-1] == "":
|
||||
del items[-1]
|
||||
return f"StackEffect({', '.join(repr(item) for item in items)})"
|
||||
|
@ -463,20 +462,13 @@ class Parser(PLexer):
|
|||
# IDENTIFIER [':' IDENTIFIER [TIMES]] ['if' '(' expression ')']
|
||||
# | IDENTIFIER '[' expression ']'
|
||||
if tkn := self.expect(lx.IDENTIFIER):
|
||||
type_text = ""
|
||||
if self.expect(lx.COLON):
|
||||
type_text = self.require(lx.IDENTIFIER).text.strip()
|
||||
if self.expect(lx.TIMES):
|
||||
type_text += " *"
|
||||
size_text = ""
|
||||
if self.expect(lx.LBRACKET):
|
||||
if type_text:
|
||||
raise self.make_syntax_error("Unexpected [")
|
||||
if not (size := self.expression()):
|
||||
raise self.make_syntax_error("Expected expression")
|
||||
self.require(lx.RBRACKET)
|
||||
size_text = size.text.strip()
|
||||
return StackEffect(tkn.text, type_text, size_text)
|
||||
return StackEffect(tkn.text, size_text)
|
||||
return None
|
||||
|
||||
@contextual
|
||||
|
|
|
@ -168,7 +168,7 @@ class Local:
|
|||
|
||||
@staticmethod
|
||||
def register(name: str) -> "Local":
|
||||
item = StackItem(name, None, "", False, True)
|
||||
item = StackItem(name, "", False, True)
|
||||
return Local(item, None, True)
|
||||
|
||||
def kill(self) -> None:
|
||||
|
@ -216,13 +216,11 @@ def array_or_scalar(var: StackItem | Local) -> str:
|
|||
return "array" if var.is_array() else "scalar"
|
||||
|
||||
class Stack:
|
||||
def __init__(self, extract_bits: bool=True, cast_type: str = "uintptr_t") -> None:
|
||||
def __init__(self) -> None:
|
||||
self.base_offset = PointerOffset.zero()
|
||||
self.physical_sp = PointerOffset.zero()
|
||||
self.logical_sp = PointerOffset.zero()
|
||||
self.variables: list[Local] = []
|
||||
self.extract_bits = extract_bits
|
||||
self.cast_type = cast_type
|
||||
|
||||
def drop(self, var: StackItem, check_liveness: bool) -> None:
|
||||
self.logical_sp = self.logical_sp.pop(var)
|
||||
|
@ -268,10 +266,8 @@ class Stack:
|
|||
self.base_offset = self.logical_sp
|
||||
if var.name in UNUSED or not var.used:
|
||||
return Local.unused(var, self.base_offset)
|
||||
cast = f"({var.type})" if (not indirect and var.type) else ""
|
||||
bits = ".bits" if cast and self.extract_bits else ""
|
||||
c_offset = (self.base_offset - self.physical_sp).to_c()
|
||||
assign = f"{var.name} = {cast}{indirect}stack_pointer[{c_offset}]{bits};\n"
|
||||
assign = f"{var.name} = {indirect}stack_pointer[{c_offset}];\n"
|
||||
out.emit(assign)
|
||||
self._print(out)
|
||||
return Local.from_memory(var, self.base_offset)
|
||||
|
@ -292,12 +288,8 @@ class Stack:
|
|||
out: CWriter,
|
||||
var: StackItem,
|
||||
stack_offset: PointerOffset,
|
||||
cast_type: str,
|
||||
extract_bits: bool,
|
||||
) -> None:
|
||||
cast = f"({cast_type})" if var.type else ""
|
||||
bits = ".bits" if cast and extract_bits else ""
|
||||
out.emit(f"stack_pointer[{stack_offset.to_c()}]{bits} = {cast}{var.name};\n")
|
||||
out.emit(f"stack_pointer[{stack_offset.to_c()}] = {var.name};\n")
|
||||
|
||||
def _save_physical_sp(self, out: CWriter) -> None:
|
||||
if self.physical_sp != self.logical_sp:
|
||||
|
@ -320,7 +312,7 @@ class Stack:
|
|||
self._print(out)
|
||||
var.memory_offset = var_offset
|
||||
stack_offset = var_offset - self.physical_sp
|
||||
Stack._do_emit(out, var.item, stack_offset, self.cast_type, self.extract_bits)
|
||||
Stack._do_emit(out, var.item, stack_offset)
|
||||
self._print(out)
|
||||
var_offset = var_offset.push(var.item)
|
||||
|
||||
|
@ -350,7 +342,7 @@ class Stack:
|
|||
out.emit(self.as_comment() + "\n")
|
||||
|
||||
def copy(self) -> "Stack":
|
||||
other = Stack(self.extract_bits, self.cast_type)
|
||||
other = Stack()
|
||||
other.base_offset = self.base_offset
|
||||
other.physical_sp = self.physical_sp
|
||||
other.logical_sp = self.logical_sp
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue