4fd6cfab15
Structural diagnostics can identify a field below an object that TVMScript renders without exposing that field. An underline alone then points at the nearest visible parent and hides the full internal location. This change keeps Script string-returning while making the diagnostic context self-contained. When the requested path is <root>.dtype, Script now returns this string by default: ```text Access path: <root>.dtype Note: The underlined object is the nearest visible parent of this path. T.int32 ^^^^^^^ ``` render_invisible_path_info defaults to true. Calls without target paths are unchanged, and callers can set it to false to retain the legacy underline-only string. The implementation reuses the printer span-selection logic to capture the deepest visible path and assembles the minimal access-path/note/script block in C++. Pass-error enrichment uses the same Script path. Production Python remains unchanged; focused Python tests assert the complete strings for default-on, explicit-false, hidden, exact-visible, unavailable-visible, pass-error, and structural-equality cases.
175 lines
5.2 KiB
Python
175 lines
5.2 KiB
Python
# Licensed to the Apache Software Foundation (ASF) under one
|
|
# or more contributor license agreements. See the NOTICE file
|
|
# distributed with this work for additional information
|
|
# regarding copyright ownership. The ASF licenses this file
|
|
# to you under the Apache License, Version 2.0 (the
|
|
# "License"); you may not use this file except in compliance
|
|
# with the License. You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing,
|
|
# software distributed under the License is distributed on an
|
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
# KIND, either express or implied. See the License for the
|
|
# specific language governing permissions and limitations
|
|
# under the License.
|
|
# ruff: noqa: F841
|
|
|
|
import pytest
|
|
from tvm_ffi.access_path import AccessPath
|
|
|
|
import tvm
|
|
from tvm.ir import assert_structural_equal
|
|
from tvm.script import ir as I
|
|
from tvm.script import tirx as T
|
|
|
|
|
|
def _error_message(exception):
|
|
return str(exception)
|
|
|
|
|
|
def _expected_result(func1, func2, objpath1, objpath2):
|
|
return f"""StructuralEqual check failed, caused by lhs at {objpath1}:
|
|
{func1.script(path_to_underline=[objpath1], syntax_sugar=False)}
|
|
and rhs at {objpath2}:
|
|
{func2.script(path_to_underline=[objpath2], syntax_sugar=False)}"""
|
|
|
|
|
|
def test_prim_type_hidden_path_exact_message():
|
|
with pytest.raises(ValueError) as exc_info:
|
|
assert_structural_equal(tvm.ir.PrimType("int32"), tvm.ir.PrimType("float32"))
|
|
|
|
assert str(exc_info.value) == (
|
|
"StructuralEqual check failed, caused by lhs at <root>.dtype:\n"
|
|
"Access path: <root>.dtype\n"
|
|
"Note: The underlined object is the nearest visible parent of this path.\n\n"
|
|
"T.int32\n"
|
|
"^^^^^^^\n"
|
|
"and rhs at <root>.dtype:\n"
|
|
"Access path: <root>.dtype\n"
|
|
"Note: The underlined object is the nearest visible parent of this path.\n\n"
|
|
"T.float32\n"
|
|
"^^^^^^^^^"
|
|
)
|
|
|
|
|
|
def test_prim_func_buffer_map():
|
|
@T.prim_func(s_tir=True)
|
|
def func1(a: T.handle, b: T.handle):
|
|
A = T.match_buffer(a, (128, 128))
|
|
B = T.match_buffer(b, (128, 128))
|
|
|
|
@T.prim_func(s_tir=True)
|
|
def func2(a: T.handle, b: T.handle):
|
|
A = T.match_buffer(a, (128, 128))
|
|
B = T.match_buffer(b, (128, 256))
|
|
|
|
func1 = func1.with_attr("global_symbol", "main")
|
|
func2 = func2.with_attr("global_symbol", "main")
|
|
|
|
with pytest.raises(ValueError) as ve:
|
|
assert_structural_equal(func1, func2)
|
|
assert _error_message(ve.value) == _expected_result(
|
|
func1,
|
|
func2,
|
|
AccessPath.root()
|
|
.attr("buffer_map")
|
|
.map_item(func1.params[1])
|
|
.attr("shape")
|
|
.array_item(1)
|
|
.attr("value"),
|
|
AccessPath.root()
|
|
.attr("buffer_map")
|
|
.map_item(func2.params[1])
|
|
.attr("shape")
|
|
.array_item(1)
|
|
.attr("value"),
|
|
)
|
|
|
|
|
|
def test_evaluate():
|
|
@I.ir_module(s_tir=True)
|
|
class module1:
|
|
@T.prim_func(s_tir=True)
|
|
def func():
|
|
T.evaluate(0)
|
|
|
|
@I.ir_module(s_tir=True)
|
|
class module2:
|
|
@T.prim_func(s_tir=True)
|
|
def func():
|
|
T.evaluate(1)
|
|
|
|
with pytest.raises(ValueError) as ve:
|
|
assert_structural_equal(module1, module2)
|
|
assert _error_message(ve.value) == _expected_result(
|
|
module1,
|
|
module2,
|
|
AccessPath.root()
|
|
.attr("functions")
|
|
.map_item(module1.get_global_var("func"))
|
|
.attr("body")
|
|
.attr("value")
|
|
.attr("value"),
|
|
AccessPath.root()
|
|
.attr("functions")
|
|
.map_item(module2.get_global_var("func"))
|
|
.attr("body")
|
|
.attr("value")
|
|
.attr("value"),
|
|
)
|
|
|
|
|
|
def test_allocate():
|
|
@T.prim_func(s_tir=True)
|
|
def func1():
|
|
a = T.alloc_buffer((128, 128), dtype="float32")
|
|
|
|
@T.prim_func(s_tir=True)
|
|
def func2():
|
|
a = T.alloc_buffer((256, 128), dtype="float32")
|
|
|
|
func1 = func1.with_attr("global_symbol", "main")
|
|
func2 = func2.with_attr("global_symbol", "main")
|
|
|
|
with pytest.raises(ValueError) as ve:
|
|
assert_structural_equal(func1, func2)
|
|
|
|
assert _error_message(ve.value) == _expected_result(
|
|
func1,
|
|
func2,
|
|
AccessPath.root().attr("body").attr("buffer").attr("shape").array_item(0).attr("value"),
|
|
AccessPath.root().attr("body").attr("buffer").attr("shape").array_item(0).attr("value"),
|
|
)
|
|
|
|
|
|
def test_for():
|
|
@T.prim_func(s_tir=True)
|
|
def func1():
|
|
for i, j in T.grid(128, 128):
|
|
with T.sblock():
|
|
pass
|
|
|
|
@T.prim_func(s_tir=True)
|
|
def func2():
|
|
for i, j, k in T.grid(128, 128, 128):
|
|
with T.sblock():
|
|
pass
|
|
|
|
func1 = func1.with_attr("global_symbol", "main")
|
|
func2 = func2.with_attr("global_symbol", "main")
|
|
|
|
with pytest.raises(ValueError) as ve:
|
|
assert_structural_equal(func1, func2)
|
|
assert _error_message(ve.value) == _expected_result(
|
|
func1,
|
|
func2,
|
|
AccessPath.root().attr("body").attr("block").attr("body").attr("body").attr("body"),
|
|
AccessPath.root().attr("body").attr("block").attr("body").attr("body").attr("body"),
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
tvm.testing.main()
|