gh-106812: Small stack effect fixes (#107759)

- Generalize the syntax for the type of a stack effect to allow a trailing `*`,
  so we can declare something as e.g. `PyCodeObject *`.

- When generating assignments for stack effects,
  the type of the value on the stack should be the default (i.e., `PyObject *`)
  even when the variable copied to/from it has a different type,
  so that an appropriate cast is generated
  However, not when the variable is an array --
  then the type is taken from the variable (as it is always `PyObject **`).
This commit is contained in:
Guido van Rossum 2023-08-07 21:32:42 -07:00 committed by GitHub
parent 707018cc75
commit 2df58dcd50
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 15 additions and 20 deletions

View file

@ -108,7 +108,7 @@ and a piece of C code describing its semantics::
NAME [":" type] [ "if" "(" C-expression ")" ]
type:
NAME
NAME ["*"]
stream:
NAME "/" size

View file

@ -252,12 +252,14 @@ class Parser(PLexer):
@contextual
def stack_effect(self) -> StackEffect | None:
# IDENTIFIER [':' IDENTIFIER] ['if' '(' expression ')']
# 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 += " *"
cond_text = ""
if self.expect(lx.IF):
self.require(lx.LPAREN)

View file

@ -120,6 +120,14 @@ class StackItem:
), f"Push or pop above current stack level: {res}"
return res
def as_stack_effect(self, lax: bool = False) -> StackEffect:
return StackEffect(
self.as_variable(lax=lax),
self.effect.type if self.effect.size else "",
self.effect.cond,
self.effect.size,
)
@dataclasses.dataclass
class CopyEffect:
@ -356,24 +364,14 @@ def write_components(
for peek in mgr.peeks:
out.assign(
peek.effect,
StackEffect(
peek.as_variable(),
peek.effect.type,
peek.effect.cond,
peek.effect.size,
),
peek.as_stack_effect(),
)
# Initialize array outputs
for poke in mgr.pokes:
if poke.effect.size and poke.effect.name not in mgr.instr.unmoved_names:
out.assign(
poke.effect,
StackEffect(
poke.as_variable(lax=True),
poke.effect.type,
poke.effect.cond,
poke.effect.size,
),
poke.as_stack_effect(lax=True),
)
if len(parts) == 1:
@ -390,11 +388,6 @@ def write_components(
for poke in mgr.pokes:
if not poke.effect.size and poke.effect.name not in mgr.instr.unmoved_names:
out.assign(
StackEffect(
poke.as_variable(),
poke.effect.type,
poke.effect.cond,
poke.effect.size,
),
poke.as_stack_effect(),
poke.effect,
)