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
13 changes: 11 additions & 2 deletions exir/error.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
# Copyright 2026 Arm Limited and/or its affiliates.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

# pyre-strict
from enum import Enum
from typing import Any


class ExportErrorType(Enum):
Expand All @@ -21,15 +23,22 @@ class ExportErrorType(Enum):
UNINITIALIZED = 6 # User is usingan API without proper initialization step.


def internal_assert(pred: bool, assert_msg: str) -> None:
def internal_assert(pred: bool, assert_msg: str, *args: Any) -> None:
"""
This is exir's custom assert method. It internally just throws InternalError.
Note that the sole purpose is to throw our own error while maintaining similar syntax
as python assert.

Additional arguments use logging-style percent formatting only on failure.

For example, pass values as args to avoid materializing the message string
unless the assertion fails::

internal_assert(node.op == "call_function", "Unexpected node: %s", node)
"""

if not pred:
raise InternalError(assert_msg)
raise InternalError(assert_msg % args if args else assert_msg)


class InternalError(Exception):
Expand Down
22 changes: 16 additions & 6 deletions exir/memory_planning.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,13 @@ def lifetime_overlap(cls, lhs_spec: TensorSpec, rhs_spec: TensorSpec) -> bool:
rhs_lifetime = rhs_spec.lifetime
internal_assert(
lhs_lifetime[0] is not None and lhs_lifetime[1] is not None,
f"{lhs_spec} should have valid start and end",
"%s should have valid start and end",
lhs_spec,
)
internal_assert(
rhs_lifetime[0] is not None and rhs_lifetime[1] is not None,
f"{rhs_spec} should have valid start and end",
"%s should have valid start and end",
rhs_spec,
)
return cls.has_overlap(lhs_lifetime, rhs_lifetime)

Expand All @@ -138,11 +140,13 @@ def storage_overlap(cls, lhs_spec: TensorSpec, rhs_spec: TensorSpec) -> bool:
for spec in [lhs_spec, rhs_spec]:
internal_assert(
spec.allocated_memory >= 0,
f"{spec} should have non-zero allocated memory",
"%s should have non-zero allocated memory",
spec,
)
internal_assert(
isinstance(spec.mem_offset, int) and spec.mem_offset >= 0,
f"{spec} should have specified memory offset",
"%s should have specified memory offset",
spec,
)
intervals.append(
[spec.mem_offset, spec.mem_offset + spec.allocated_memory - 1]
Expand Down Expand Up @@ -524,7 +528,9 @@ def collect_specs_from_nodes( # noqa: C901
torch.ops.higher_order.map_impl,
executorch_call_delegate,
],
f"Unexpected op {node.op}, target {node.target}",
"Unexpected op %s, target %s",
node.op,
node.target,
)
for spec in specs:
if spec is None:
Expand Down Expand Up @@ -916,7 +922,11 @@ def _resolve_storage_base_specs(
)
internal_assert(
(base_alloc_offset + storage_base_offset) % spec.alignment == 0,
f"Storage-backed TensorSpec allocation must respect alignment, got offset {storage_base_offset} inside parent with offset {base_alloc_offset} for alignment {spec.alignment}.",
"Storage-backed TensorSpec allocation must respect alignment, got offset %s "
"inside parent with offset %s for alignment %s.",
storage_base_offset,
base_alloc_offset,
spec.alignment,
)
internal_assert(
storage_base_offset + allocated_memory <= base_allocated_memory,
Expand Down
Loading