mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 03:32:28 +00:00 
			
		
		
		
	* Introduce X-macro-based trace tag definition - 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 * Add script to generate Markdown documentation from trace_tags.def - Python script parses trace_tags.def and outputs trace_tags.md * Refactor TRACE_NEW to prepend TraceTag and pass enum to is_trace_enabled * trace: improve trace tag handling system with hierarchical tagging - 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) * trace: replace all string-based TRACE tags with enum TraceTag - Migrated all TRACE, STRACE, SCTRACE, and CTRACE macros to use enum TraceTag values instead of raw string literals * trace : add cstring header * trace : Add Markdown documentation generation from trace_tags.def via mk_api_doc.py * trace : rename macro parameter 'class' to 'tag_class' and remove Unicode comment in trace_tags.h. * trace : Add TODO comment for future implementation of tag_class activation * trace : Disable code related to tag_class until implementation is ready (#7663).
		
			
				
	
	
		
			298 lines
		
	
	
	
		
			7.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			298 lines
		
	
	
	
		
			7.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*++
 | |
| Copyright (c) 2014 Microsoft Corporation
 | |
| 
 | |
| Module Name:
 | |
| 
 | |
|     tbv.cpp
 | |
| 
 | |
| Abstract:
 | |
| 
 | |
|     ternary bit-vector utilities.
 | |
| 
 | |
| Author:
 | |
| 
 | |
|     Nikolaj Bjorner (nbjorner) 2014-09-15
 | |
| 
 | |
| Revision History:
 | |
| 
 | |
| 
 | |
| --*/
 | |
| 
 | |
| #include "util/tbv.h"
 | |
| #include "util/hashtable.h"
 | |
| 
 | |
| 
 | |
| static bool s_debug_alloc = false;
 | |
| 
 | |
| void tbv_manager::debug_alloc() {
 | |
|     s_debug_alloc = true;
 | |
| }
 | |
| 
 | |
| tbv_manager::~tbv_manager() {    
 | |
|     DEBUG_CODE(
 | |
|         for (auto t : allocated_tbvs)
 | |
|             TRACE(doc, tout << "dangling: " << t << "\n";););
 | |
| }
 | |
| 
 | |
| void tbv_manager::reset() {
 | |
|     m.reset();
 | |
| }
 | |
| tbv* tbv_manager::allocate() {
 | |
|     tbv* r = static_cast<tbv*>(m.allocate());
 | |
|     m.reset(*r);
 | |
|     DEBUG_CODE(
 | |
|         if (s_debug_alloc) {
 | |
|             TRACE(doc, tout << allocated_tbvs.size() << " " << r << "\n";);
 | |
|         }
 | |
|         allocated_tbvs.insert(r);
 | |
|         );
 | |
|     return r;
 | |
| }
 | |
| tbv* tbv_manager::allocate1() {
 | |
|     tbv* v = allocate();
 | |
|     fill1(*v);
 | |
|     return v;
 | |
| }
 | |
| tbv* tbv_manager::allocate0() {
 | |
|     tbv* v = allocate();
 | |
|     fill0(*v);
 | |
|     return v;
 | |
| }
 | |
| tbv* tbv_manager::allocateX() {
 | |
|     tbv* v = allocate();
 | |
|     fillX(*v);
 | |
|     return v;
 | |
| }
 | |
| tbv* tbv_manager::allocate(tbv const& bv) {
 | |
|     tbv* r = allocate();
 | |
|     copy(*r, bv);
 | |
|     return r;
 | |
| }
 | |
| tbv* tbv_manager::allocate(uint64_t val) {
 | |
|     tbv* v = allocate0();
 | |
|     for (unsigned bit = std::min(64u, num_tbits()); bit-- > 0;) {
 | |
|         if (val & (1ULL << bit)) {                        
 | |
|             set(*v, bit, BIT_1);
 | |
|         } else {
 | |
|             set(*v, bit, BIT_0);
 | |
|         }
 | |
|     }
 | |
|     return v;
 | |
| }
 | |
| 
 | |
| tbv* tbv_manager::allocate(uint64_t val, unsigned hi, unsigned lo) {
 | |
|     tbv* v = allocateX();
 | |
|     SASSERT(64 >= num_tbits() && num_tbits() > hi && hi >= lo);
 | |
|     set(*v, val, hi, lo);
 | |
|     return v;
 | |
| }
 | |
| tbv* tbv_manager::allocate(tbv const& bv, unsigned const* permutation) {
 | |
|     tbv* r = allocate();
 | |
|     unsigned sz = num_tbits();
 | |
|     for (unsigned i = 0; i < sz; ++i) {
 | |
|         set(*r, permutation[i], bv[i]);
 | |
|     }
 | |
|     return r;
 | |
| }
 | |
| tbv* tbv_manager::allocate(char const* bv) {
 | |
|     tbv* result = allocateX();
 | |
|     unsigned i = 0, sz = num_tbits();
 | |
|     while(*bv && i < sz) {
 | |
|         if (*bv == '0') set(*result, i++, BIT_0);
 | |
|         else if (*bv == '1') set(*result, i++, BIT_1);
 | |
|         else if (*bv == '*') i++;
 | |
|         else if (*bv == 'x') i++;
 | |
|         else if (i == 0 && (*bv == ' ' || *bv == '\t')) ;
 | |
|         else break;
 | |
|         ++bv;
 | |
|     }
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| tbv* tbv_manager::project(bit_vector const& to_delete, tbv const& src) {
 | |
|     tbv* r = allocate();
 | |
|     unsigned i, j;
 | |
|     unsigned n = to_delete.size();
 | |
|     for (i = 0, j = 0; i < n; ++i) {
 | |
|         if (!to_delete.get(i)) {
 | |
|             set(*r, j, src[i]);
 | |
|             ++j;
 | |
|         }
 | |
|     }
 | |
|     SASSERT(num_tbits() == j);
 | |
|     return r;
 | |
| }
 | |
| 
 | |
| void tbv_manager::set(tbv& dst, unsigned index, tbit value) {
 | |
|     SASSERT(index < num_tbits());
 | |
|     m.set(dst, 2*index,   (value & 2) != 0);
 | |
|     m.set(dst, 2*index+1, (value & 1) != 0);    
 | |
| }
 | |
| 
 | |
| 
 | |
| void tbv_manager::set(tbv& dst, uint64_t val, unsigned hi, unsigned lo) {
 | |
|     SASSERT(lo <= hi && hi < num_tbits());
 | |
|     for (unsigned i = 0; i < hi - lo + 1; ++i) {
 | |
|         set(dst, lo + i, (val & (1ULL << i))?BIT_1:BIT_0);
 | |
|     }
 | |
| }
 | |
| void tbv_manager::set(tbv& dst, rational const& r, unsigned hi, unsigned lo) {
 | |
|     SASSERT(lo <= hi && hi < num_tbits());
 | |
|     if (r.is_uint64()) {
 | |
|         set(dst, r.get_uint64(), hi, lo);
 | |
|         return;
 | |
|     }
 | |
|     for (unsigned i = 0; i < hi - lo + 1; ++i)
 | |
|         set(dst, lo + i, r.get_bit(i) ? BIT_1 : BIT_0);
 | |
| }
 | |
| 
 | |
| void tbv_manager::set(tbv& dst, tbv const& other, unsigned hi, unsigned lo) {
 | |
|     dst.set(other, 2*hi+1, 2*lo);
 | |
| }
 | |
| 
 | |
| 
 | |
| tbv* tbv_manager::allocate(rational const& r) {
 | |
|     if (r.is_uint64()) {
 | |
|         return allocate(r.get_uint64());
 | |
|     }
 | |
|     tbv* v = allocate0();
 | |
|     for (unsigned bit = num_tbits(); bit > 0; ) {
 | |
|         --bit;
 | |
|         if (bitwise_and(r, rational::power_of_two(bit)).is_zero()) {
 | |
|             set(*v, bit, BIT_0);
 | |
|         } else {
 | |
|             set(*v, bit, BIT_1);
 | |
|         }
 | |
|     }            
 | |
|     return v;
 | |
| }
 | |
| void tbv_manager::deallocate(tbv* bv) {
 | |
| #if 0
 | |
|     DEBUG_CODE(
 | |
|         if (!allocated_tbvs.contains(bv)) {
 | |
|             std::cout << "double deallocate: " << bv << "\n";
 | |
|             UNREACHABLE();
 | |
|         }
 | |
|         if (s_debug_alloc) {
 | |
|             TRACE(doc, tout << "deallocate: " << bv << "\n";);
 | |
|         }
 | |
|         allocated_tbvs.erase(bv););
 | |
| #endif
 | |
|     m.deallocate(bv);
 | |
| }    
 | |
| void tbv_manager::copy(tbv& dst, tbv const& src) const {
 | |
|     m.copy(dst, src);
 | |
| }    
 | |
| tbv& tbv_manager::fill0(tbv& bv) const { 
 | |
|     // 10101010 = 2 + 8 + 32 + 128
 | |
|     memset(bv.m_data, 2 + 8 + 32 + 128, m.num_bytes());
 | |
|     return bv; 
 | |
| }
 | |
| tbv& tbv_manager::fill1(tbv& bv) const {  
 | |
|     // 01010101 = 1 + 4 + 16 + 64
 | |
|     memset(bv.m_data, 1 + 4 + 16 + 64, m.num_bytes());
 | |
|     return bv; 
 | |
| }
 | |
| tbv& tbv_manager::fillX(tbv& bv) const { 
 | |
|     m.fill1(bv); 
 | |
|     return bv; 
 | |
| }
 | |
| 
 | |
| tbv& tbv_manager::set_or(tbv& dst,  tbv const& src) const {
 | |
|     m.set_or(dst, src); 
 | |
|     return dst;
 | |
| }
 | |
| bool tbv_manager::set_and(tbv& dst,  tbv const& src) const {
 | |
|     m.set_and(dst, src); 
 | |
|     return is_well_formed(dst);
 | |
| }
 | |
| 
 | |
| bool tbv_manager::is_well_formed(tbv const& dst) const {
 | |
|     unsigned nw = m.num_words();
 | |
|     unsigned w;
 | |
|     for (unsigned i = 0; i + 1 < nw; ++i) {
 | |
|         w = dst.get_word(i);
 | |
|         w = w | (w << 1) | 0x55555555;
 | |
|         if (w != 0xFFFFFFFF) return false;
 | |
|     }
 | |
|     if (nw > 0) {        
 | |
|         w = m.last_word(dst);
 | |
|         w = w | (w << 1) | 0x55555555 | ~m.get_mask();
 | |
|         if (w != 0xFFFFFFFF) return false;
 | |
|     }
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| void tbv_manager::complement(tbv const& src, ptr_vector<tbv>& result) {
 | |
|     tbv* r;
 | |
|     unsigned n = num_tbits();
 | |
|     for (unsigned i = 0; i < n; ++i) {
 | |
|         switch (src.get(i)) {
 | |
|         case BIT_0:
 | |
|             r = allocate(src);
 | |
|             set(*r, i, BIT_1);
 | |
|             result.push_back(r);
 | |
|             break;
 | |
|         case BIT_1:
 | |
|             r = allocate(src);
 | |
|             set(*r, i, BIT_0);
 | |
|             result.push_back(r);
 | |
|             break;
 | |
|         default:
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| bool tbv_manager::equals(tbv const& a, tbv const& b) const {
 | |
|     return m.equals(a, b);
 | |
| }
 | |
| unsigned tbv_manager::hash(tbv const& src) const {
 | |
|     return m.hash(src);
 | |
| }
 | |
| bool tbv_manager::contains(tbv const& a, tbv const& b) const {
 | |
|     return m.contains(a, b);
 | |
| }
 | |
| 
 | |
| bool tbv_manager::contains(tbv const& a, unsigned_vector const& colsa,
 | |
|                            tbv const& b, unsigned_vector const& colsb) const {
 | |
|     for (unsigned i = 0; i < colsa.size(); ++i) {
 | |
|         tbit bit_a = a[colsa[i]];
 | |
|         if (bit_a == BIT_x) continue;
 | |
|         if (bit_a != b[colsb[i]]) return false;
 | |
|     }
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| bool tbv_manager::intersect(tbv const& a, tbv const& b, tbv& result) {
 | |
|     copy(result, a);
 | |
|     return set_and(result, b);
 | |
| }
 | |
| 
 | |
| std::ostream& tbv_manager::display(std::ostream& out, tbv const& b, unsigned hi, unsigned lo) const {
 | |
|     SASSERT(lo <= hi && hi < num_tbits());
 | |
|     for (unsigned i = hi+1; i-- > lo; ) {
 | |
|         switch (b.get(i)) {
 | |
|         case BIT_0:
 | |
|             out << '0';
 | |
|             break;
 | |
|         case BIT_1:
 | |
|             out << '1';
 | |
|             break;
 | |
|         case BIT_x:
 | |
|             out << 'x';
 | |
|             break;
 | |
|         case BIT_z:
 | |
|             out << 'z';
 | |
|             break;
 | |
|         default:
 | |
|             UNREACHABLE();
 | |
|         }
 | |
|     }
 | |
|     return out;
 | |
| }
 | |
| 
 | |
| std::ostream& tbv_manager::display(std::ostream& out, tbv const& b) const {
 | |
|     if (num_tbits() == 0) return out << "[]";
 | |
|     return display(out, b, num_tbits()-1, 0);
 | |
| }
 |