-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Centralize and document TRACE tags using X-macros #7657
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Centralize and document TRACE tags using X-macros #7657
Conversation
- Created trace_tags.def to centralize TRACE tag definitions - Each tag includes a symbolic name and description - Set up enum class TraceTag for type-safe usage in TRACE macros
- Python script parses trace_tags.def and outputs trace_tags.md
scripts/generate_trace_tag_docs.py
Outdated
@@ -0,0 +1,35 @@ | |||
# generate_trace_tag_docs.py |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
something calls this script, e.g., called from doc/mk_api_doc.py to include in api doc package?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, the script is intended to be run manually and is not yet hooked into doc/mk_api_doc.py.
Integration into the API doc pipeline can be considered in the future if that makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right, first this script has to be pushed :-)
src/smt/smt_context.cpp
Outdated
@@ -1702,6 +1702,7 @@ namespace smt { | |||
*/ | |||
bool context::propagate() { | |||
TRACE("propagate", tout << "propagating... " << m_qhead << ":" << m_assigned_literals.size() << "\n";); | |||
TRACE_NEW(TraceTag::propagate, tout << "propagating... " << m_qhead << ":" << m_assigned_literals.size() << "\n";); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replacing TRACE by TRACE_NEW and populating trace_tags.def is definitely scriptable.
Based on the original github issue is there any "module" information you wanted to add?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes — I’d like to categorize all TRACE tags, starting with:
- SMT Internalization: tracking e-graph construction
- Congruence Closure Core: focusing on quantifier instantiation
The goal is to build a structured view of all trace points across the solver.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So what is then the plan to achieve this based on C macros?
Have a third column with a class (which is also defined in the enum column) and create a map from class to members such that when the class is traced and TRACE is hit for a member, the trace is invoked?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’d like to propose the following structure:
- Add a class column to
trace_tags.def
- Keep the current
-tr:tag_name
option for enabling individual trace tags - Introduce a new
-tr_class:tag_class_name
option that enables all tags associated with the specified class
If -tr_class:tag_class_name
is used, all tags under that class would be activated for tracing.
Let me know if this direction makes sense or if you'd suggest a different approach!
If we proceed with this structure, I’d really appreciate your input on how to conceptually group the existing trace tags into classes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the simpler and also usable approach would be if you use a single name-space for tag_name and tag-class-name and introduce a hierarchy by making X be of the form
X(tag_name, tag_class_name, "description")
X(tag_class_name, tag_class_name, "description")
So all classes are also tags and we can either take the 1step closure or transitive closure if that turns out to be more useful.
There would be no extra -tr_class option either.
I would merge this PR first and implement tags everywhere so rename TRACE_NEW to TRACE.
Porting all other tags is scriptable by assigning every tag to its own class by default.
It may be an AI query hack to refactor into classes, except the code base is not a friend of small context windows.
src/util/trace.h
Outdated
@@ -81,6 +82,7 @@ static inline void finalize_trace() {} | |||
#define STRACEBODY(CODE) CODE; tout.flush() | |||
|
|||
#define TRACE(TAG, CODE) TRACE_CODE(if (is_trace_enabled(TAG)) { THREAD_LOCK(TRACEBODY(TAG, CODE)); }) | |||
#define TRACE_NEW(TAG, CODE) TRACE_CODE(if (is_trace_enabled(to_string(TAG))) { THREAD_LOCK(TRACEBODY(to_string(TAG), CODE)); }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in a separate round, maybe is_trace_enabled uses the enum directly?
Using strings in first round is the way to go.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated the code as suggested — is_trace_enabled
accepts the enum directly.
The changes are included in commit cac9782.
Please take a look and let me know if anything else needs refinement!
src/util/trace.h
Outdated
@@ -81,6 +82,7 @@ static inline void finalize_trace() {} | |||
#define STRACEBODY(CODE) CODE; tout.flush() | |||
|
|||
#define TRACE(TAG, CODE) TRACE_CODE(if (is_trace_enabled(TAG)) { THREAD_LOCK(TRACEBODY(TAG, CODE)); }) | |||
#define TRACE_NEW(TAG, CODE) TRACE_CODE(if (is_trace_enabled(to_string(TAG))) { THREAD_LOCK(TRACEBODY(to_string(TAG), CODE)); }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't the TRACE macro itself pre-pend the class name TraceTag to eliminate common clutter from uses?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated the code as suggested — TRACE_NEW
now prepends TraceTag.
The changes are included in commit cac9782.
Please take a look and let me know if anything else needs refinement!
Stepping back a little, who needs to know about the tracing mechanism besides the Z3 developers? Probably no one. Also, a simple grep (e.g. |
this would benefit also from trace classes which is then more systematic, and also some discipline implied by a def manifest which avoids dealing with silly typos creating two tags instead of one. |
While it's true that we can extract trace tags using Even though TRACE is primarily a debugging mechanism, exposing it in a more systematic and categorized way could help advanced users trace how specific components like |
FWIW, a simple AI prompt created basically this. Reverted push: Not all cpp versions like musing ##TAG to stringify the identifier in some settings.
|
- Introduce hierarchical tag-class structure: enabling a tag class activates all child tags - Unify TRACE, STRACE, SCTRACE, and CTRACE under enum TraceTag - Implement initial version of trace_tag.def using X(tag, tag_class, description) (class names and descriptions to be refined in a future update)
- Migrated all TRACE, STRACE, SCTRACE, and CTRACE macros to use enum TraceTag values instead of raw string literals
@NikolajBjorner |
src/util/trace_tags.h
Outdated
#define X(tag, class, desc) if (strncmp(#tag, tag_str, strlen(#tag)) == 0) return TraceTag::tag; | ||
#include "trace_tags.def" | ||
#undef X | ||
return TraceTag::Count; // 매칭되는 태그가 없는 경우 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove unicode comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. PTAL.
src/util/trace_tags.h
Outdated
#include <cstring> | ||
|
||
enum class TraceTag { | ||
#define X(tag, class, desc) tag, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to be safer, avoid identifier "class". I run into compiler incompatibilities a lot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed. PTAL.
src/util/trace_tags.h
Outdated
inline const TraceTag* get_tags_by_class(TraceTag cls, int& count) { | ||
count = count_tags_in_class(cls); | ||
static TraceTag* class_tags = nullptr; | ||
if (class_tags) delete[] class_tags; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this will cause bug reports with leaks and all memory should go over memory_manager.
We use init/finalize for global memory.
Also, wouldn't an approach where members are added to a single linked list within an array of all tags that gets allocated once do the job?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe just get rid of this class altogether?
If this is to keep, you can just define an iterator that generates the result on-the-fly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@NikolajBjorner @nunoplopes
Thanks for the review!
I've created a follow-up issue to track the implementation. (#7663)
I'd appreciate any feedback or suggestions on the proposed implementation direction in that issue!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you disable or remove this for the current PR?
Then I can merge what there is. With the code below exposed, someone will just start filing a gotcha fuzz bug that there is a memory leak.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Disabled the code per your comment. PTAL.
Suggestuin is to defer implementing this feature in first pr. Then merging will be quicker. Milestone 1 is using enums. |
…ode comment in trace_tags.h.
618b120
to
b003937
Compare
Thanks for the suggestion — I've added a TODO to defer this feature. |
For enabling tag classes, let us use a separate PR after this has gone through all builds.
Though, these are elements of a consecutive enum type, so I don't think this method does anything that can't be done by playing with values of the enum type itself. what you could expose is a method that returns a static array where elements of each tag class are linked in a cyclic (or TraceTag::Count terminated) list.
|
Summary
This PR refactors the tracing infrastructure to introduce a structured, hierarchical tagging system using enum class TraceTag. All TRACE, STRACE, SCTRACE, and CTRACE macros have been updated to use enum-based tags instead of string literals, enabling type-safe, consistent trace logging throughout the codebase.
Key Changes
Testing
I enabled
g_enable_all_trace_tags
and compared the.z3-trace
output for my existing SMT-LIB expressions before and after the changes. The outputs were identical, indicating functional equivalence.TODO
However, since this change touches a large portion of the codebase, broader testing with more SMT-LIB expressions would be helpful to ensure full coverage and correctness.