@@ -123,51 +123,97 @@ def __init__(self):
123123 self ._enter_constraint_context = _mod ("enter_constraint_context" )
124124 self ._can_prove_equal = _mod ("can_prove_equal" )
125125 self ._can_prove = _mod ("can_prove" )
126+ self ._is_z3_enabled = _mod ("is_z3_enabled" )
126127 self ._get_smtlib2 = _mod ("get_smtlib2" )
127128 self ._set_z3_timeout_ms = _mod ("set_z3_timeout_ms" )
128129 self ._set_z3_rlimit = _mod ("set_z3_rlimit" )
129130 self ._get_z3_stats = _mod ("get_z3_stats" )
130131 self ._get_enabled_extensions = _mod ("get_enabled_extensions" )
131132 self ._set_enabled_extensions = _mod ("set_enabled_extensions" )
132133
133- def get_smtlib2 (self , expr : tirx .PrimExpr = None ) -> str :
134+ @property
135+ def is_z3_enabled (self ) -> bool :
136+ """Whether this build includes the Z3 backend (``USE_Z3=ON``).
137+
138+ The Z3-specific methods (:py:meth:`get_smtlib2`, :py:meth:`get_z3_stats`,
139+ :py:meth:`set_z3_timeout_ms`, :py:meth:`set_z3_rlimit`) only work when
140+ this is ``True``.
141+ """
142+ return bool (self ._is_z3_enabled ())
143+
144+ def _check_z3_enabled (self ) -> None :
145+ if not self .is_z3_enabled :
146+ raise RuntimeError (
147+ "The Z3 backend is not available in this build. "
148+ "Rebuild TVM with USE_Z3=ON to use Z3-specific Analyzer APIs."
149+ )
150+
151+ def get_smtlib2 (self , expr : tirx .PrimExpr | None = None ) -> str :
134152 """Get the current Z3 problem in SMT-LIB2 format.
135153
154+ Raises
155+ ------
156+ RuntimeError
157+ If TVM was built without Z3 (``USE_Z3=OFF``), since there is no
158+ solver state to export. Use :py:attr:`is_z3_enabled` to check first.
159+
136160 Parameters
137161 ----------
138162 expr : Optional[PrimExpr]
139163 The expression to prove. If provided, its negation is added to the problem.
140164 """
165+ self ._check_z3_enabled ()
141166 return self ._get_smtlib2 (expr )
142167
143168 def set_z3_timeout_ms (self , timeout_ms : int ) -> None :
144169 """Set Z3 timeout in milliseconds.
145170
171+ Raises
172+ ------
173+ RuntimeError
174+ If TVM was built without Z3 (``USE_Z3=OFF``).
175+
146176 Parameters
147177 ----------
148178 timeout_ms : int
149179 The timeout in milliseconds.
150180 """
181+ self ._check_z3_enabled ()
151182 self ._set_z3_timeout_ms (timeout_ms )
152183
153184 def set_z3_rlimit (self , rlimit : int ) -> None :
154185 """Set Z3 resource limit.
155186
187+ The resource limit gives deterministic solver budgeting (unlike a wall
188+ clock timeout). A value of ``0`` disables the limit.
189+
190+ Raises
191+ ------
192+ RuntimeError
193+ If TVM was built without Z3 (``USE_Z3=OFF``).
194+
156195 Parameters
157196 ----------
158197 rlimit : int
159198 The resource limit.
160199 """
200+ self ._check_z3_enabled ()
161201 self ._set_z3_rlimit (rlimit )
162202
163203 def get_z3_stats (self ) -> str :
164204 """Get Z3 solver statistics.
165205
206+ Raises
207+ ------
208+ RuntimeError
209+ If TVM was built without Z3 (``USE_Z3=OFF``).
210+
166211 Returns
167212 -------
168213 stats : str
169214 The Z3 statistics.
170215 """
216+ self ._check_z3_enabled ()
171217 return self ._get_z3_stats ()
172218
173219 def const_int_bound (self , expr : tirx .PrimExpr ) -> ConstIntBound :
@@ -301,7 +347,9 @@ def can_prove(
301347 The expression.
302348
303349 strength: ProofStrength
304- The proof strength
350+ The proof strength. When TVM is built with Z3 (``USE_Z3=ON``), the
351+ optional Z3 fallback is only consulted at ``SYMBOLIC_BOUND`` or
352+ higher, after the native analyzers fail to prove the predicate.
305353
306354 Returns
307355 -------
0 commit comments