Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions mypyc/analysis/ircheck.py
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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)]
)
],
)
)