Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mypyc] Fix ircheck if register is initialized through LoadAddress #13944

Merged
merged 1 commit into from Oct 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 6 additions & 2 deletions mypyc/analysis/ircheck.py
Expand Up @@ -129,7 +129,11 @@ def check_op_sources_valid(fn: FuncIR) -> list[FnError]:
for block in fn.blocks:
valid_ops.update(block.ops)

valid_registers.update([op.dest for op in block.ops if isinstance(op, BaseAssign)])
for op in block.ops:
if isinstance(op, BaseAssign):
valid_registers.add(op.dest)
elif isinstance(op, LoadAddress) and isinstance(op.src, Register):
valid_registers.add(op.src)

valid_registers.update(fn.arg_regs)

Expand All @@ -150,7 +154,7 @@ def check_op_sources_valid(fn: FuncIR) -> list[FnError]:
if source not in valid_registers:
errors.append(
FnError(
source=op, desc=f"Invalid op reference to register {source.name}"
source=op, desc=f"Invalid op reference to register {source.name!r}"
)
)

Expand Down
31 changes: 29 additions & 2 deletions mypyc/test/test_ircheck.py
Expand Up @@ -5,7 +5,17 @@
from mypyc.analysis.ircheck import FnError, can_coerce_to, check_func_ir
from mypyc.ir.class_ir import ClassIR
from mypyc.ir.func_ir import FuncDecl, FuncIR, FuncSignature
from mypyc.ir.ops import Assign, BasicBlock, Goto, Integer, LoadLiteral, Op, Register, Return
from mypyc.ir.ops import (
Assign,
BasicBlock,
Goto,
Integer,
LoadAddress,
LoadLiteral,
Op,
Register,
Return,
)
from mypyc.ir.pprint import format_func
from mypyc.ir.rtypes import (
RInstance,
Expand All @@ -16,6 +26,7 @@
int64_rprimitive,
none_rprimitive,
object_rprimitive,
pointer_rprimitive,
str_rprimitive,
)

Expand Down Expand Up @@ -88,7 +99,7 @@ def test_invalid_register_source(self) -> None:
ret = Return(value=Register(type=none_rprimitive, name="r1"))
block = self.basic_block([ret])
fn = FuncIR(decl=self.func_decl(name="func_1"), arg_regs=[], blocks=[block])
assert_has_error(fn, FnError(source=ret, desc="Invalid op reference to register r1"))
assert_has_error(fn, FnError(source=ret, desc="Invalid op reference to register 'r1'"))

def test_invalid_op_source(self) -> None:
ret = Return(value=LoadLiteral(value="foo", rtype=str_rprimitive))
Expand Down Expand Up @@ -170,3 +181,19 @@ def test_pprint(self) -> None:
" goto L1",
" ERR: Invalid control operation target: 1",
]

def test_load_address_declares_register(self) -> None:
rx = Register(str_rprimitive, "x")
ry = Register(pointer_rprimitive, "y")
load_addr = LoadAddress(pointer_rprimitive, rx)
assert_no_errors(
FuncIR(
decl=self.func_decl(name="func_1"),
arg_regs=[],
blocks=[
self.basic_block(
ops=[load_addr, Assign(ry, load_addr), Return(value=NONE_VALUE)]
)
],
)
)