This is an automated email from the ASF dual-hosted git repository.
tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git
The following commit(s) were added to refs/heads/main by this push:
new 64721bde7e [TVMScript] Fill AST locations at compilation and simplify
span inputs (#20450)
64721bde7e is described below
commit 64721bde7ea22d2712eb5f8f3ecd729ee2a53839
Author: Tianqi Chen <[email protected]>
AuthorDate: Fri Sep 25 11:21:13 2026 -0400
[TVMScript] Fill AST locations at compilation and simplify span inputs
(#20450)
Remove the redundant AST location fill after rewriting; fill missing
locations at each compilation boundary after the generated builder has
been assembled.
Restrict script builder span inputs to native spans, span entries, or
`None`. Unwrap entries at native boundaries and remove tuple/string
source-range normalization while preserving span attachment, context
handling, and emission receipts. Place the receipt class before the
span-entry class.
---
python/tvm/relax/script/ir_builder/__init__.py | 56 ++++++++-----
.../tvm/relax/script/ir_builder/parser_protocol.py | 30 +++----
python/tvm/script/ir_builder/base.py | 94 +++++++++-------------
python/tvm/script/ir_builder/ir.py | 10 +--
python/tvm/script/ir_builder/parser_protocol.py | 58 ++++++-------
python/tvm/script/parser/transpile.py | 2 +-
python/tvm/tirx/script/ir_builder/__init__.py | 5 +-
.../tvm/tirx/script/ir_builder/parser_protocol.py | 14 ++--
tests/python/script/test_source_locations.py | 2 +-
9 files changed, 138 insertions(+), 133 deletions(-)
diff --git a/python/tvm/relax/script/ir_builder/__init__.py
b/python/tvm/relax/script/ir_builder/__init__.py
index a9919cf4d2..2ca8e53e25 100644
--- a/python/tvm/relax/script/ir_builder/__init__.py
+++ b/python/tvm/relax/script/ir_builder/__init__.py
@@ -28,8 +28,8 @@ from tvm.relax.distributed import DTensorType as _DTensorType
from tvm.relax.distributed import Placement as _Placement
from tvm.relax.distributed import device_mesh as device_mesh
from tvm.script.ir_builder import resolve_global_info_args as
_resolve_global_info_args
+from tvm.script.ir_builder.base import SpanEntry as _SpanEntry
from tvm.script.ir_builder.base import at as _at
-from tvm.script.ir_builder.base import source_span as _source_span
from tvm.script.parser.protocol_registry import constexpr as constexpr
from . import distributed as dist
@@ -101,7 +101,7 @@ def Tensor(shape=None, dtype=None, vdevice=None, ndim=-1,
*, span=None):
ndim : int, optional
Rank when shape is unknown; -1 means unknown rank. Do not supply
an explicit rank together with a known shape.
- span : Span or source location, optional
+ span : SpanEntry, Span or None, optional
Source location attached to the constructed IR; None leaves it
unspecified.
Returns
@@ -112,7 +112,9 @@ def Tensor(shape=None, dtype=None, vdevice=None, ndim=-1,
*, span=None):
"""
if isinstance(shape, _python.str) and dtype is None:
dtype, shape = shape, None
- return _relax.TensorType(shape, dtype, vdevice, ndim, _source_span(span))
+ return _relax.TensorType(
+ shape, dtype, vdevice, ndim, span.span if isinstance(span, _SpanEntry)
else span
+ )
@_resolve_global_info_args("device_mesh", resolver=resolve_global_info_)
@@ -135,7 +137,7 @@ def DTensor(shape=None, dtype=None, device_mesh=None,
placement="", *, ndim=-1,
parsed with Placement.from_text.
ndim : int, optional
Global rank when shape is unknown; -1 means unknown rank.
- span : Span or source location, optional
+ span : SpanEntry, Span or None, optional
Source location attached to the constructed IR; None leaves it
unspecified.
Returns
@@ -148,7 +150,12 @@ def DTensor(shape=None, dtype=None, device_mesh=None,
placement="", *, ndim=-1,
device_mesh = _DeviceMesh([], _ir.Range(0, 1))
if isinstance(placement, _python.str):
placement = _Placement.from_text(placement)
- return _DTensorType(Tensor(shape, dtype, ndim=ndim), device_mesh,
placement, _source_span(span))
+ return _DTensorType(
+ Tensor(shape, dtype, ndim=ndim),
+ device_mesh,
+ placement,
+ span.span if isinstance(span, _SpanEntry) else span,
+ )
# The distributed source spelling shares the decorated concrete constructor.
@@ -172,7 +179,7 @@ def Shape(values=None, ndim=-1, *, span=None):
ndim : int, optional
Number of dimensions when values is None; -1 leaves it unknown.
Do not supply an explicit count together with known values.
- span : Span or source location, optional
+ span : SpanEntry, Span or None, optional
Source location attached to the constructed IR; None leaves it
unspecified.
Returns
@@ -180,7 +187,7 @@ def Shape(values=None, ndim=-1, *, span=None):
result : ShapeType
The constructed shape type.
"""
- return _relax.ShapeType(values, ndim, _source_span(span))
+ return _relax.ShapeType(values, ndim, span.span if isinstance(span,
_SpanEntry) else span)
def _type(value):
@@ -212,7 +219,7 @@ def Callable(params=None, ret=None, purity=None,
derive_func=None, *, span=None)
derive_func : str or EnvFunc, optional
Custom result-type derivation for an opaque callable. It is not
accepted when params supplies a concrete parameter list.
- span : Span or source location, optional
+ span : SpanEntry, Span or None, optional
Source location attached to the constructed IR; None leaves it
unspecified.
Returns
@@ -233,14 +240,17 @@ def Callable(params=None, ret=None, purity=None,
derive_func=None, *, span=None)
ret=None if ret is None else _type(ret),
derive_func=derive_func,
purity=purity,
- span=_source_span(span),
+ span=span.span if isinstance(span, _SpanEntry) else span,
)
if derive_func is not None:
raise ValueError("A derivation function requires an opaque callable")
if not isinstance(params, list | _python.tuple):
params = [params]
return _relax.FuncType(
- [_type(param) for param in params], _type(ret), purity,
_source_span(span)
+ [_type(param) for param in params],
+ _type(ret),
+ purity,
+ span.span if isinstance(span, _SpanEntry) else span,
)
@@ -252,7 +262,7 @@ def Tuple(*fields, span=None):
fields : Type or callable
Field annotations as positional arguments, or one list or tuple.
Each annotation is normalized to a type; None denotes an empty tuple.
- span : Span or source location, optional
+ span : SpanEntry, Span or None, optional
Source location attached to the constructed IR; None leaves it
unspecified.
Returns
@@ -262,7 +272,9 @@ def Tuple(*fields, span=None):
"""
if len(fields) == 1 and isinstance(fields[0], list | _python.tuple):
fields = fields[0]
- return _ir.TupleType([_type(field) for field in fields],
_source_span(span))
+ return _ir.TupleType(
+ [_type(field) for field in fields], span.span if isinstance(span,
_SpanEntry) else span
+ )
def Object(*, span=None):
@@ -270,7 +282,7 @@ def Object(*, span=None):
Parameters
----------
- span : Span or source location, optional
+ span : SpanEntry, Span or None, optional
Source location attached to the constructed IR; None leaves it
unspecified.
Returns
@@ -278,7 +290,7 @@ def Object(*, span=None):
result : AnyType
A type accepting any Relax value.
"""
- return _relax.AnyType(_source_span(span))
+ return _relax.AnyType(span.span if isinstance(span, _SpanEntry) else span)
Any = Object
@@ -296,7 +308,7 @@ def type_var(name, *, dtype=None, span=None):
Name of the symbol.
dtype : str or PrimType, optional
Primitive type of the symbol; None selects "int64".
- span : Span or source location, optional
+ span : SpanEntry, Span or None, optional
Source location attached to the constructed IR; None leaves it
unspecified.
Returns
@@ -309,7 +321,11 @@ def type_var(name, *, dtype=None, span=None):
This constructor creates a new symbol on each call. Use the language
variant
resolver for symbols shared by name within a function signature.
"""
- return _ir.Var(name, "int64" if dtype is None else dtype,
_source_span(span))
+ return _ir.Var(
+ name,
+ "int64" if dtype is None else dtype,
+ span.span if isinstance(span, _SpanEntry) else span,
+ )
func_ret_ty = func_ret_type
@@ -320,7 +336,7 @@ def dataflow(*, span=None):
Parameters
----------
- span : Span or source location, optional
+ span : SpanEntry, Span or None, optional
Source location attached to the constructed IR.
Returns
@@ -351,7 +367,7 @@ def match_cast(value, ty, *, span=None):
are converted to Relax expressions; None is not accepted.
ty : Type or callable
Asserted type, or a zero-argument factory producing its annotation.
- span : Span or source location, optional
+ span : SpanEntry, Span or None, optional
Source location attached to the constructed IR; None leaves it
unspecified.
Returns
@@ -363,7 +379,9 @@ def match_cast(value, ty, *, span=None):
if value is None:
raise ValueError("The match-cast value cannot be None")
ty = _type(ty)
- return _relax.MatchCast(_ir.Var("", ty), _value(value), ty,
_source_span(span))
+ return _relax.MatchCast(
+ _ir.Var("", ty), _value(value), ty, span.span if isinstance(span,
_SpanEntry) else span
+ )
__all__ = [
diff --git a/python/tvm/relax/script/ir_builder/parser_protocol.py
b/python/tvm/relax/script/ir_builder/parser_protocol.py
index f7ba61e7c7..85ac05e23e 100644
--- a/python/tvm/relax/script/ir_builder/parser_protocol.py
+++ b/python/tvm/relax/script/ir_builder/parser_protocol.py
@@ -45,7 +45,7 @@ from . import _ffi_api
from . import frame as _frame
from . import ir as _native
-_Span = _base.SpanEntry | _ir.Span | tuple[_ir.SourceName, int, int, int, int]
| None
+_Span = _base.SpanEntry | _ir.Span | None
# --------------------------------------
@@ -172,7 +172,7 @@ def lt_(lhs: Any, rhs: Any, *, span: _Span = None) ->
_ir.Expr:
lhs = _relax.const(lhs) if isinstance(lhs, _numbers.Number) else lhs
rhs = _relax.const(rhs) if isinstance(rhs, _numbers.Number) else rhs
return _base.at_(span, _relax.op.less(lhs, rhs))
- return _prim_ffi._OpLT(lhs, rhs, _base.source_span(span))
+ return _prim_ffi._OpLT(lhs, rhs, span.span if isinstance(span,
_base.SpanEntry) else span)
def le_(lhs: Any, rhs: Any, *, span: _Span = None) -> _ir.Expr:
@@ -181,7 +181,7 @@ def le_(lhs: Any, rhs: Any, *, span: _Span = None) ->
_ir.Expr:
lhs = _relax.const(lhs) if isinstance(lhs, _numbers.Number) else lhs
rhs = _relax.const(rhs) if isinstance(rhs, _numbers.Number) else rhs
return _base.at_(span, _relax.op.less_equal(lhs, rhs))
- return _prim_ffi._OpLE(lhs, rhs, _base.source_span(span))
+ return _prim_ffi._OpLE(lhs, rhs, span.span if isinstance(span,
_base.SpanEntry) else span)
def gt_(lhs: Any, rhs: Any, *, span: _Span = None) -> _ir.Expr:
@@ -190,7 +190,7 @@ def gt_(lhs: Any, rhs: Any, *, span: _Span = None) ->
_ir.Expr:
lhs = _relax.const(lhs) if isinstance(lhs, _numbers.Number) else lhs
rhs = _relax.const(rhs) if isinstance(rhs, _numbers.Number) else rhs
return _base.at_(span, _relax.op.greater(lhs, rhs))
- return _prim_ffi._OpGT(lhs, rhs, _base.source_span(span))
+ return _prim_ffi._OpGT(lhs, rhs, span.span if isinstance(span,
_base.SpanEntry) else span)
def ge_(lhs: Any, rhs: Any, *, span: _Span = None) -> _ir.Expr:
@@ -199,7 +199,7 @@ def ge_(lhs: Any, rhs: Any, *, span: _Span = None) ->
_ir.Expr:
lhs = _relax.const(lhs) if isinstance(lhs, _numbers.Number) else lhs
rhs = _relax.const(rhs) if isinstance(rhs, _numbers.Number) else rhs
return _base.at_(span, _relax.op.greater_equal(lhs, rhs))
- return _prim_ffi._OpGE(lhs, rhs, _base.source_span(span))
+ return _prim_ffi._OpGE(lhs, rhs, span.span if isinstance(span,
_base.SpanEntry) else span)
def eq_(lhs: Any, rhs: Any, *, span: _Span = None) -> _ir.Expr:
@@ -208,7 +208,7 @@ def eq_(lhs: Any, rhs: Any, *, span: _Span = None) ->
_ir.Expr:
lhs = _relax.const(lhs) if isinstance(lhs, _numbers.Number) else lhs
rhs = _relax.const(rhs) if isinstance(rhs, _numbers.Number) else rhs
return _base.at_(span, _relax.op.equal(lhs, rhs))
- return _prim_ffi._OpEQ(lhs, rhs, _base.source_span(span))
+ return _prim_ffi._OpEQ(lhs, rhs, span.span if isinstance(span,
_base.SpanEntry) else span)
def ne_(lhs: Any, rhs: Any, *, span: _Span = None) -> _ir.Expr:
@@ -217,7 +217,7 @@ def ne_(lhs: Any, rhs: Any, *, span: _Span = None) ->
_ir.Expr:
lhs = _relax.const(lhs) if isinstance(lhs, _numbers.Number) else lhs
rhs = _relax.const(rhs) if isinstance(rhs, _numbers.Number) else rhs
return _base.at_(span, _relax.op.not_equal(lhs, rhs))
- return _prim_ffi._OpNE(lhs, rhs, _base.source_span(span))
+ return _prim_ffi._OpNE(lhs, rhs, span.span if isinstance(span,
_base.SpanEntry) else span)
# --------------------------------------
@@ -350,7 +350,7 @@ def arg(name: str, ty: Any, *, span: _Span = None) ->
_ir.Var:
:func:`tvm.script.ir_builder.parser_protocol.arg` contract. Primitive
annotations resolve through the active signature symbol context; an
existing variable retains its identity.
- span : Span or source location, optional
+ span : SpanEntry, Span or None, optional
Source location attached to the constructed IR; None leaves it
unspecified.
Returns
@@ -446,14 +446,18 @@ def bind_(
Relax values emit a binding or MatchCast; value_span belongs to the actual
RHS and span to the binding target. Metadata passes through unchanged.
"""
- name_span = _base.source_span(span if name_span is None else name_span)
+ if isinstance(span, _base.SpanEntry):
+ span = span.span
+ name_span = span if name_span is None else name_span
+ if isinstance(name_span, _base.SpanEntry):
+ name_span = name_span.span
if frame_value:
if isinstance(value, _python.list | _python.tuple | _ir.Array):
for index, item in enumerate(value):
bind_(
item,
name=None if name is None else f"{name}_{index}",
- span=_base.source_span(span),
+ span=span,
name_span=name_span,
frame_value=True,
)
@@ -472,12 +476,10 @@ def bind_(
_base.at_(value_span, value.value)
if ty is not None and not _ffi.structural_equal(ty, value.ty):
raise TypeError("The binding annotation differs from the
match-cast type")
- result = _ffi_api.EmitMatchCastWithSpan(
- value.value, value.ty, name_span, _base.source_span(span)
- )
+ result = _ffi_api.EmitMatchCastWithSpan(value.value, value.ty,
name_span, span)
elif isinstance(value, _relax.Expr):
_base.at_(value_span, value)
- result = _ffi_api.EmitWithSpan(value, ty, name_span,
_base.source_span(span))
+ result = _ffi_api.EmitWithSpan(value, ty, name_span, span)
else:
return value
if name is not None:
diff --git a/python/tvm/script/ir_builder/base.py
b/python/tvm/script/ir_builder/base.py
index bba7ea9471..0543fd8613 100644
--- a/python/tvm/script/ir_builder/base.py
+++ b/python/tvm/script/ir_builder/base.py
@@ -274,6 +274,29 @@ class IRBuilder(_Object):
_T = TypeVar("_T")
+class AlreadyEmitted(Generic[_T]):
+ """Hold the exact emitted value; location handling preserves this receipt.
+
+ Parameters
+ ----------
+ value : Any
+ Object already emitted by a language variant's builder. The receipt
+ retains this object without copying it. Binding or emitting the receipt
+ must not emit the object again.
+
+ Attributes
+ ----------
+ value : Any
+ The same emitted object, available for identity checks and source-span
+ attachment.
+ """
+
+ __slots__ = ("value",)
+
+ def __init__(self, value: _T) -> None:
+ self.value = value
+
+
class SpanEntry:
"""A materialized source range shared by generated builder operations.
@@ -282,7 +305,7 @@ class SpanEntry:
during evaluation. ``ctx(thunk, attach_result=False)`` supplies only the
evaluation context, leaving result attachment to the binding operation.
Both compose the active caller context at invocation.
- Builders accepting an explicit span normalize an entry with
``source_span``.
+ Builders accepting an explicit span unwrap the entry at native boundaries.
"""
__slots__ = ("span",)
@@ -303,54 +326,14 @@ class SpanEntry:
return with_at_group_(self.span, thunk, attach_result=attach_result)
-def source_span(
- location: SpanEntry | ir.Span | tuple[str | ir.SourceName, int, int, int,
int] | None,
-) -> ir.Span | None:
- """Normalize an entry or materialize a range without retaining source-unit
state."""
- if isinstance(location, SpanEntry):
- return location.span
- if location is None or isinstance(location, ir.Span | ir.SequentialSpan):
- return location
- source_name, line, end_line, column, end_column = location
- if isinstance(source_name, str):
- source_name = ir.SourceName(source_name)
- return ir.Span(source_name, line, end_line, column, end_column)
-
-
-class AlreadyEmitted(Generic[_T]):
- """Hold the exact emitted value; location handling preserves this receipt.
-
- Parameters
- ----------
- value : Any
- Object already emitted by a language variant's builder. The receipt
- retains this object without copying it. Binding or emitting the receipt
- must not emit the object again.
-
- Attributes
- ----------
- value : Any
- The same emitted object, available for identity checks and source-span
- attachment.
- """
-
- __slots__ = ("value",)
-
- def __init__(self, value: _T) -> None:
- self.value = value
-
-
-def at(
- span: SpanEntry | ir.Span | tuple[str | ir.SourceName, int, int, int, int]
| None, value: _T
-) -> _T:
+def at(span: SpanEntry | ir.Span | None, value: _T) -> _T:
"""Attach source context to the same IR node, emission receipt, or frame.
Parameters
----------
- span : SpanEntry, Span, tuple or None
- Source location to compose with the active construction context. A
tuple
- contains ``(source_name, line, end_line, column, end_column)``; its
source
- name may be a string or SourceName. None leaves the value unchanged.
+ span : SpanEntry, Span or None
+ Source location to compose with the active construction context.
+ None leaves the value unchanged.
value : Any
Native object, :class:`AlreadyEmitted` receipt, or list/tuple of native
objects to annotate. A receipt's contained object receives the span.
@@ -369,16 +352,18 @@ def at(
"""
if span is None or not IRBuilder.is_in_scope():
return value
+ if isinstance(span, SpanEntry):
+ span = span.span
target = value.value if isinstance(value, AlreadyEmitted) else value
targets = target if isinstance(target, list | tuple) else (target,)
for item in targets:
if isinstance(item, _Object):
- _ffi_api.IRBuilderSetSourceSpan(IRBuilder.current(), item,
source_span(span))
+ _ffi_api.IRBuilderSetSourceSpan(IRBuilder.current(), item, span)
return value
def with_at_group_(
- location: SpanEntry | ir.Span | tuple[str | ir.SourceName, int, int, int,
int] | None,
+ location: SpanEntry | ir.Span | None,
thunk: Callable[[], _T],
*,
attach_result: bool = True,
@@ -387,10 +372,9 @@ def with_at_group_(
Parameters
----------
- location : SpanEntry, Span, tuple or None
- Source context for the call. A tuple contains
- ``(source_name, line, end_line, column, end_column)``. None, or the
- absence of an active builder, leaves construction context unchanged.
+ location : SpanEntry, Span or None
+ Source context for the call. None, or the absence of an active builder,
+ leaves construction context unchanged.
thunk : Callable[[], Any]
Zero-argument callable evaluated exactly once inside that context.
attach_result : bool, optional
@@ -409,7 +393,7 @@ def with_at_group_(
exception propagates unchanged. Frames created during the call retain their
construction spans regardless of ``attach_result``.
"""
- span = source_span(location)
+ span = location.span if isinstance(location, SpanEntry) else location
context = (
IRBuilder.current().with_source_span(span)
if span is not None and IRBuilder.is_in_scope()
@@ -417,7 +401,7 @@ def with_at_group_(
)
with context:
value = thunk()
- return at(location, value) if attach_result else value
+ return at(span, value) if attach_result else value
at_ = at
@@ -435,7 +419,9 @@ def _resolve_type_var(frame, ffi_resolver, name,
dtype=None, *, value=None, span
raise TypeError("A symbolic variable requires a primitive type")
if value is not None and not ir.is_prim_var(value):
raise TypeError("A symbolic binding requires a primitive Var")
- return ffi_resolver(frame, name, dtype, value, source_span(span))
+ return ffi_resolver(
+ frame, name, dtype, value, span.span if isinstance(span, SpanEntry)
else span
+ )
def _current_function_frame():
diff --git a/python/tvm/script/ir_builder/ir.py
b/python/tvm/script/ir_builder/ir.py
index 7230bdba71..7f46a436f1 100644
--- a/python/tvm/script/ir_builder/ir.py
+++ b/python/tvm/script/ir_builder/ir.py
@@ -19,17 +19,17 @@
import inspect
from typing import TypeVar
-from tvm.ir import BaseFunc, GlobalInfo, GlobalVar, Var
+from tvm.ir import BaseFunc, GlobalInfo, GlobalVar, Span, Var
from tvm.runtime import Object as tvm_Object
from . import _ffi_api
-from .base import IRBuilder, source_span
+from .base import IRBuilder, SpanEntry
from .frame import IRModuleFrame
T = TypeVar("T")
-def dynamic(name: str, dtype: str = "int64", *, span=None) -> Var:
+def dynamic(name: str, dtype: str = "int64", *, span: SpanEntry | Span | None
= None) -> Var:
"""Create a fresh primitive symbolic variable, independently of builder
scope.
Parameters
@@ -38,7 +38,7 @@ def dynamic(name: str, dtype: str = "int64", *, span=None) ->
Var:
The symbol's display name. Repeated names do not share identity.
dtype : str
Primitive dtype, defaulting to int64.
- span : Optional[Span]
+ span : SpanEntry, Span or None
Source location of the symbol.
Returns
@@ -47,7 +47,7 @@ def dynamic(name: str, dtype: str = "int64", *, span=None) ->
Var:
A fresh symbol. Reuse this object to share dimensions across
annotations
and function bodies, including outside an ``I.ir_module`` definition.
"""
- return Var(name, dtype, source_span(span))
+ return Var(name, dtype, span.span if isinstance(span, SpanEntry) else span)
def meta_var(value: T) -> T:
diff --git a/python/tvm/script/ir_builder/parser_protocol.py
b/python/tvm/script/ir_builder/parser_protocol.py
index 1d09c15eaa..cc28473634 100644
--- a/python/tvm/script/ir_builder/parser_protocol.py
+++ b/python/tvm/script/ir_builder/parser_protocol.py
@@ -35,7 +35,7 @@ from tvm import ir as _ir
from .base import MISSING, AlreadyEmitted, IRBuilderFrame, SpanEntry
-_Span = SpanEntry | _ir.Span | tuple[_ir.SourceName, int, int, int, int] | None
+_Span = SpanEntry | _ir.Span | None
# --------------------------------------
@@ -60,7 +60,7 @@ def if_(condition: Any, *, span: _Span = None) ->
IRBuilderFrame:
condition : Expr or bool
Already-evaluated predicate; both branch bodies construct IR without
testing it
in Python.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -99,7 +99,7 @@ def then_(*, span: _Span = None) -> IRBuilderFrame:
Parameters
----------
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -137,7 +137,7 @@ def else_(*, span: _Span = None) -> IRBuilderFrame:
Parameters
----------
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -184,7 +184,7 @@ def for_(
Source target names, including at most one ``*starred`` group. None
(the default)
retains constructor defaults. Native configuration expands/validates
them before
entry; names never control the entry return shape.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -222,7 +222,7 @@ def while_(condition: Any, *, span: _Span = None) ->
IRBuilderFrame:
----------
condition : Expr or bool
Loop predicate expression, constructed once and evaluated by the IR at
runtime.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -288,7 +288,7 @@ def break_(*, span: _Span = None) -> AlreadyEmitted[Any]:
Parameters
----------
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -319,7 +319,7 @@ def continue_(*, span: _Span = None) -> AlreadyEmitted[Any]:
Parameters
----------
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -495,7 +495,7 @@ def lt_(lhs: Any, rhs: Any, *, span: _Span = None) ->
_ir.Expr:
Already-evaluated left operand.
rhs : Expr or scalar
Already-evaluated right operand.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -531,7 +531,7 @@ def le_(lhs: Any, rhs: Any, *, span: _Span = None) ->
_ir.Expr:
Already-evaluated left operand.
rhs : Expr or scalar
Already-evaluated right operand.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -567,7 +567,7 @@ def gt_(lhs: Any, rhs: Any, *, span: _Span = None) ->
_ir.Expr:
Already-evaluated left operand.
rhs : Expr or scalar
Already-evaluated right operand.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -603,7 +603,7 @@ def ge_(lhs: Any, rhs: Any, *, span: _Span = None) ->
_ir.Expr:
Already-evaluated left operand.
rhs : Expr or scalar
Already-evaluated right operand.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -639,7 +639,7 @@ def eq_(lhs: Any, rhs: Any, *, span: _Span = None) ->
_ir.Expr:
Already-evaluated left operand.
rhs : Expr or scalar
Already-evaluated right operand.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -675,7 +675,7 @@ def ne_(lhs: Any, rhs: Any, *, span: _Span = None) ->
_ir.Expr:
Already-evaluated left operand.
rhs : Expr or scalar
Already-evaluated right operand.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -764,7 +764,7 @@ def resolve_type_var_(
value : Var, optional
Existing primitive variable to register without replacement. None
creates a
variable only if the name is not already registered.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -890,7 +890,7 @@ def function_(*, decl: bool = False, span: _Span = None,
**options: Any) -> IRBu
decl : bool, optional
False (default) constructs a complete function on one entry. True
collects a
signature on the first entry and retains this frame for body re-entry.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -940,7 +940,7 @@ def arg(name: str, annotation: Any, *, span: _Span = None)
-> _ir.Var:
annotation : Type, Var, Buffer or callable
Concrete rewritten annotation or existing native parameter. A callable
annotation is evaluated; an existing variable retains identity.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -1007,7 +1007,7 @@ def func_ret_type(annotation: Any, *, span: _Span = None)
-> None:
annotation : Type, Expr or callable
Rewritten return annotation; expression annotations supply their type.
None
denotes a void/empty tuple return as supported by the language variant.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -1109,15 +1109,15 @@ def bind_(
the binding type.
name : str, optional
Source target name. None (the default) requests no source-derived name.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Binding-target location for a newly constructed binding. None (the
default)
leaves it unspecified; this is separate from the RHS location.
- value_span : SpanEntry, Span or source-location tuple, optional
+ value_span : SpanEntry, Span or None, optional
RHS source location, passed separately without first stamping the
returned value.
None (the default) leaves explicit RHS attribution unspecified. The
language variant
applies it only when binding/conversion requires value attribution;
TIRx
variable and metadata passthrough retain producer names and spans.
- name_span : SpanEntry, Span or source-location tuple, optional
+ name_span : SpanEntry, Span or None, optional
Location of the target identifier. None (the default) uses span; it
can differ
from the emitted statement location.
frame_value : bool, optional
@@ -1182,11 +1182,11 @@ def decl_mutable_cell_(
created storage handle.
name : str, optional
Source target name. None (the default) requests no source-derived name.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
- name_span : SpanEntry, Span or source-location tuple, optional
+ name_span : SpanEntry, Span or None, optional
Location of the target identifier. None (the default) uses span; it
can differ
from the emitted statement location.
@@ -1224,7 +1224,7 @@ def set_mutable_cell_(target: Any, value: Any, *, span:
_Span = None) -> Already
value : Expr or scalar convertible to Expr
Once-evaluated value to store. Native store checking validates its
type and
indices against the target.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location of the emitted store. None (the default) leaves explicit
location
unspecified; existing source-call provenance is retained.
@@ -1305,7 +1305,7 @@ def emit_(value: Any, *, span: _Span = None) -> None:
value : Any
Once-evaluated expression result. AlreadyEmitted receipts and None
produce no
additional emission.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location of the emitted statement and expression, or the existing node
in an
AlreadyEmitted receipt. None leaves explicit attribution unspecified.
Active
caller provenance is composed without adding a construction context;
native
@@ -1345,7 +1345,7 @@ def return_(value: Any = None, *, span: _Span = None) ->
AlreadyEmitted[Any] | N
value : Any, optional
Return operand. None (the default) means an empty tuple in Relax; TIRx
requires
an expression.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -1384,7 +1384,7 @@ def setitem_(target: Any, key: Any, value: Any, *, span:
_Span = None) -> Alread
Indices in written order; native buffer-store rules validate supported
forms.
value : Expr or scalar
Once-evaluated stored value.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -1424,7 +1424,7 @@ def setattr_(
Attribute identifier, evaluated by source syntax before this hook.
value : Any
Once-evaluated replacement or stored value.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
@@ -1467,7 +1467,7 @@ def assert_(
message : str or assertion metadata, optional
Empty text by default. Relax requires construction-time text. TIRx
also accepts
message parts or an (error_kind, parts) pair.
- span : SpanEntry, Span or source-location tuple, optional
+ span : SpanEntry, Span or None, optional
Location for the constructed result. None (the default) leaves
explicit location
unspecified; active source-call provenance is composed by the builder.
Frames
retain their location until finalization.
diff --git a/python/tvm/script/parser/transpile.py
b/python/tvm/script/parser/transpile.py
index b62f9f6ec2..1a41a587cc 100644
--- a/python/tvm/script/parser/transpile.py
+++ b/python/tvm/script/parser/transpile.py
@@ -2412,4 +2412,4 @@ class IRBuilderTranspiler(ast.NodeTransformer):
root, result, python_functions,
check_well_formed=check_well_formed
)
)
- return ast.fix_missing_locations(ast.Module(translated, [])), result
+ return ast.Module(translated, []), result
diff --git a/python/tvm/tirx/script/ir_builder/__init__.py
b/python/tvm/tirx/script/ir_builder/__init__.py
index 6f2e2ed550..3677ba9b02 100644
--- a/python/tvm/tirx/script/ir_builder/__init__.py
+++ b/python/tvm/tirx/script/ir_builder/__init__.py
@@ -26,7 +26,6 @@ from tvm import tirx as _tir
from tvm.script.ir_builder import dynamic as dynamic
from tvm.script.ir_builder.base import annotation_constructor as
_annotation_constructor
from tvm.script.ir_builder.base import at as _at
-from tvm.script.ir_builder.base import source_span as _source_span
from tvm.script.parser.protocol_registry import constexpr as constexpr
from tvm.script.parser.protocol_registry import (
mutable_cell_decl as _mutable_cell_decl,
@@ -155,7 +154,7 @@ def Buffer(
buffer_name : str
The name of the buffer.
- span : Span or source location, optional
+ span : SpanEntry, Span or None, optional
Source location attached to the constructed IR.
Returns
@@ -196,7 +195,7 @@ def Ptr(dtype, storage_scope="global", *, span=None):
storage_scope : str
The storage scope of the pointer.
- span : Span or source location, optional
+ span : SpanEntry, Span or None, optional
Source location attached to the constructed IR.
Returns
diff --git a/python/tvm/tirx/script/ir_builder/parser_protocol.py
b/python/tvm/tirx/script/ir_builder/parser_protocol.py
index 0d170dbc54..47de5704bf 100644
--- a/python/tvm/tirx/script/ir_builder/parser_protocol.py
+++ b/python/tvm/tirx/script/ir_builder/parser_protocol.py
@@ -40,7 +40,7 @@ from . import _ffi_api
from . import frame as _frame
from . import ir as _native
-_Span = _base.SpanEntry | _ir.Span | tuple[_ir.SourceName, int, int, int, int]
| None
+_Span = _base.SpanEntry | _ir.Span | None
# --------------------------------------
@@ -160,32 +160,32 @@ def not_(value: Any) -> Any:
def lt_(lhs: Any, rhs: Any, *, span: _Span = None) -> _ir.Expr:
"""Implements :func:`tvm.script.ir_builder.parser_protocol.lt_`."""
- return _prim_ffi._OpLT(lhs, rhs, _base.source_span(span))
+ return _prim_ffi._OpLT(lhs, rhs, span.span if isinstance(span,
_base.SpanEntry) else span)
def le_(lhs: Any, rhs: Any, *, span: _Span = None) -> _ir.Expr:
"""Implements :func:`tvm.script.ir_builder.parser_protocol.le_`."""
- return _prim_ffi._OpLE(lhs, rhs, _base.source_span(span))
+ return _prim_ffi._OpLE(lhs, rhs, span.span if isinstance(span,
_base.SpanEntry) else span)
def gt_(lhs: Any, rhs: Any, *, span: _Span = None) -> _ir.Expr:
"""Implements :func:`tvm.script.ir_builder.parser_protocol.gt_`."""
- return _prim_ffi._OpGT(lhs, rhs, _base.source_span(span))
+ return _prim_ffi._OpGT(lhs, rhs, span.span if isinstance(span,
_base.SpanEntry) else span)
def ge_(lhs: Any, rhs: Any, *, span: _Span = None) -> _ir.Expr:
"""Implements :func:`tvm.script.ir_builder.parser_protocol.ge_`."""
- return _prim_ffi._OpGE(lhs, rhs, _base.source_span(span))
+ return _prim_ffi._OpGE(lhs, rhs, span.span if isinstance(span,
_base.SpanEntry) else span)
def eq_(lhs: Any, rhs: Any, *, span: _Span = None) -> _ir.Expr:
"""Implements :func:`tvm.script.ir_builder.parser_protocol.eq_`."""
- return _prim_ffi._OpEQ(lhs, rhs, _base.source_span(span))
+ return _prim_ffi._OpEQ(lhs, rhs, span.span if isinstance(span,
_base.SpanEntry) else span)
def ne_(lhs: Any, rhs: Any, *, span: _Span = None) -> _ir.Expr:
"""Implements :func:`tvm.script.ir_builder.parser_protocol.ne_`."""
- return _prim_ffi._OpNE(lhs, rhs, _base.source_span(span))
+ return _prim_ffi._OpNE(lhs, rhs, span.span if isinstance(span,
_base.SpanEntry) else span)
# --------------------------------------
diff --git a/tests/python/script/test_source_locations.py
b/tests/python/script/test_source_locations.py
index e54dea0156..4ec3cfc97d 100644
--- a/tests/python/script/test_source_locations.py
+++ b/tests/python/script/test_source_locations.py
@@ -336,7 +336,7 @@ def
test_native_view_keeps_producer_identity_name_and_span(monkeypatch):
captured = T.Buffer((4, 4), "float32")
original = type(captured).view
seen, produced, observed = [], [], []
- span = base.source_span(("producer.py", 7, 7, 2, 19))
+ span = ir.Span(ir.SourceName("producer.py"), 7, 7, 2, 19)
@wraps(original)
def view(buffer, *args):