Add support files
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
commit
4f5cafdebf
8 changed files with 553 additions and 0 deletions
101
src/util/debug.cpp
Normal file
101
src/util/debug.cpp
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
|
||||
Author: Leonardo de Moura
|
||||
*/
|
||||
#include "debug.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#ifndef _WINDOWS
|
||||
// Support for pid
|
||||
#include<unistd.h>
|
||||
#endif
|
||||
|
||||
namespace lean {
|
||||
|
||||
static volatile bool g_enable_assertions = true;
|
||||
static std::unique_ptr<std::set<std::string>> g_enabled_debug_tags;
|
||||
|
||||
void enable_assertions(bool f) {
|
||||
g_enable_assertions = f;
|
||||
}
|
||||
|
||||
bool assertions_enabled() {
|
||||
return g_enable_assertions;
|
||||
}
|
||||
|
||||
void notify_assertion_violation(const char * fileName, int line, const char * condition) {
|
||||
std::cerr << "LEAN ASSERTION VIOLATION\n";
|
||||
std::cerr << "File: " << fileName << "\n";
|
||||
std::cerr << "Line: " << line << "\n";
|
||||
std::cerr << condition << "\n";
|
||||
std::cerr.flush();
|
||||
}
|
||||
|
||||
void enable_debug(char const * tag) {
|
||||
if (!g_enabled_debug_tags)
|
||||
g_enabled_debug_tags.reset(new std::set<std::string>());
|
||||
g_enabled_debug_tags->insert(tag);
|
||||
}
|
||||
|
||||
void disable_debug(char const * tag) {
|
||||
if (g_enabled_debug_tags)
|
||||
g_enabled_debug_tags->erase(tag);
|
||||
}
|
||||
|
||||
bool is_debug_enabled(const char * tag) {
|
||||
return g_enabled_debug_tags && g_enabled_debug_tags->find(tag) != g_enabled_debug_tags->end();
|
||||
}
|
||||
|
||||
void invoke_debugger() {
|
||||
int * x = 0;
|
||||
for (;;) {
|
||||
#ifdef _WINDOWS
|
||||
std::cerr << "(C)ontinue, (A)bort, (S)top\n";
|
||||
#else
|
||||
std::cerr << "(C)ontinue, (A)bort, (S)top, Invoke (G)DB\n";
|
||||
#endif
|
||||
char result;
|
||||
std::cin >> result;
|
||||
switch(result) {
|
||||
case 'C':
|
||||
case 'c':
|
||||
return;
|
||||
case 'A':
|
||||
case 'a':
|
||||
exit(1);
|
||||
case 'S':
|
||||
case 's':
|
||||
// force seg fault...
|
||||
*x = 0;
|
||||
return;
|
||||
#ifndef _WINDOWS
|
||||
case 'G':
|
||||
case 'g': {
|
||||
std::cerr << "INVOKING GDB...\n";
|
||||
std::ostringstream buffer;
|
||||
buffer << "gdb -nw /proc/" << getpid() << "/exe " << getpid();
|
||||
if (system(buffer.str().c_str()) == 0) {
|
||||
std::cerr << "continuing the execution...\n";
|
||||
}
|
||||
else {
|
||||
std::cerr << "ERROR STARTING GDB...\n";
|
||||
// forcing seg fault.
|
||||
int * x = 0;
|
||||
*x = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
std::cerr << "INVALID COMMAND\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
42
src/util/debug.h
Normal file
42
src/util/debug.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
|
||||
Author: Leonardo de Moura
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifndef __has_builtin
|
||||
#define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#ifdef LEAN_DEBUG
|
||||
#define DEBUG_CODE(CODE) CODE
|
||||
#else
|
||||
#define DEBUG_CODE(CODE)
|
||||
#endif
|
||||
|
||||
#define lean_assert(COND) DEBUG_CODE({if (!(COND)) { lean::notify_assertion_violation(__FILE__, __LINE__, #COND); lean::invoke_debugger(); }})
|
||||
#define lean_cond_assert(TAG, COND) DEBUG_CODE({if (lean::is_debug_enabled(TAG) && !(COND)) { lean::notify_assertion_violation(__FILE__, __LINE__, #COND); lean::invoke_debugger(); }})
|
||||
|
||||
#if __has_builtin(__builtin_unreachable)
|
||||
#define lean_unreachable() __builtin_unreachable()
|
||||
#else
|
||||
#define lean_unreachable() DEBUG_CODE({lean::notify_assertion_violation(__FILE__, __LINE__, "UNREACHABLE CODE WAS REACHED."); lean::invoke_debugger();})
|
||||
#endif
|
||||
|
||||
#ifdef LEAN_DEBUG
|
||||
#define lean_verify(COND) if (!(COND)) { lean::notify_assertion_violation(__FILE__, __LINE__, #COND); lean::invoke_debugger(); }
|
||||
#else
|
||||
#define lean_verify(COND) (COND)
|
||||
#endif
|
||||
|
||||
namespace lean {
|
||||
|
||||
void notify_assertion_violation(char const * file_name, int line, char const * condition);
|
||||
void enable_debug(char const * tag);
|
||||
void disable_debug(char const * tag);
|
||||
bool is_debug_enabled(char const * tag);
|
||||
void invoke_debugger();
|
||||
|
||||
}
|
27
src/util/exception.cpp
Normal file
27
src/util/exception.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
|
||||
Author: Leonardo de Moura
|
||||
*/
|
||||
#include "exception.h"
|
||||
|
||||
namespace lean {
|
||||
|
||||
exception::exception(char const * msg):m_msg(msg) {
|
||||
}
|
||||
|
||||
exception::exception(std::string const & msg):m_msg(msg) {
|
||||
}
|
||||
|
||||
exception::exception(exception const & e):m_msg(e.m_msg) {
|
||||
}
|
||||
|
||||
exception::~exception() {
|
||||
}
|
||||
|
||||
char const * exception::what() const noexcept {
|
||||
return m_msg.c_str();
|
||||
}
|
||||
|
||||
}
|
23
src/util/exception.h
Normal file
23
src/util/exception.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
|
||||
Author: Leonardo de Moura
|
||||
*/
|
||||
#pragma once
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
namespace lean {
|
||||
|
||||
class exception : public std::exception {
|
||||
std::string m_msg;
|
||||
public:
|
||||
exception(char const * msg);
|
||||
exception(std::string const & msg);
|
||||
exception(exception const & ex);
|
||||
virtual ~exception();
|
||||
virtual char const * what() const noexcept;
|
||||
};
|
||||
|
||||
}
|
229
src/util/name.cpp
Normal file
229
src/util/name.cpp
Normal file
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
|
||||
Author: Leonardo de Moura
|
||||
*/
|
||||
#include <cstring>
|
||||
#include "name.h"
|
||||
#include "debug.h"
|
||||
|
||||
namespace lean {
|
||||
|
||||
constexpr char const * anonymous_str = "[anonymous]";
|
||||
|
||||
struct name::imp {
|
||||
bool m_is_string;
|
||||
unsigned m_rc;
|
||||
imp * m_prefix;
|
||||
union {
|
||||
char * m_str;
|
||||
unsigned m_k;
|
||||
};
|
||||
|
||||
void inc_ref() { m_rc++; }
|
||||
|
||||
void dec_ref() {
|
||||
imp * curr = this;
|
||||
while (curr) {
|
||||
lean_assert(curr->m_rc > 0);
|
||||
curr->m_rc--;
|
||||
if (curr->m_rc == 0) {
|
||||
imp * p = curr->m_prefix;
|
||||
if (curr->m_is_string)
|
||||
delete[] reinterpret_cast<char*>(curr);
|
||||
else
|
||||
delete curr;
|
||||
curr = p;
|
||||
}
|
||||
else {
|
||||
curr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imp(bool s, imp * p):m_is_string(s), m_rc(1), m_prefix(p) { if (p) p->inc_ref(); }
|
||||
|
||||
static void display_core(std::ostream & out, char const * sep, imp * p) {
|
||||
lean_assert(p != nullptr);
|
||||
if (p->m_prefix) {
|
||||
display_core(out, sep, p->m_prefix);
|
||||
out << sep;
|
||||
}
|
||||
if (p->m_is_string)
|
||||
out << p->m_str;
|
||||
else
|
||||
out << p->m_k;
|
||||
}
|
||||
|
||||
static void display(std::ostream & out, char const * sep, imp * p) {
|
||||
if (p == nullptr)
|
||||
out << anonymous_str;
|
||||
else
|
||||
display_core(out, sep, p);
|
||||
}
|
||||
};
|
||||
|
||||
name::name(imp * p) {
|
||||
m_imp = p;
|
||||
if (m_imp)
|
||||
m_imp->inc_ref();
|
||||
}
|
||||
|
||||
name::name() {
|
||||
m_imp = nullptr;
|
||||
}
|
||||
|
||||
name::name(name const & prefix, char const * name) {
|
||||
size_t sz = strlen(name);
|
||||
lean_assert(sz < 1u<<31);
|
||||
char * mem = new char[sizeof(imp) + sz + 1];
|
||||
m_imp = new (mem) imp(true, prefix.m_imp);
|
||||
memcpy(mem + sizeof(imp), name, sz + 1);
|
||||
m_imp->m_str = mem + sizeof(imp);
|
||||
}
|
||||
|
||||
name::name(name const & prefix, unsigned k) {
|
||||
m_imp = new imp(false, prefix.m_imp);
|
||||
m_imp->m_k = k;
|
||||
}
|
||||
|
||||
name::name(char const * n):name(name(), n) {
|
||||
}
|
||||
|
||||
name::name(unsigned k):name(name(), k) {
|
||||
}
|
||||
|
||||
name::name(name const & other):m_imp(other.m_imp) {
|
||||
m_imp->inc_ref();
|
||||
}
|
||||
|
||||
name::name(name && other):m_imp(other.m_imp) {
|
||||
other.m_imp = 0;
|
||||
}
|
||||
|
||||
name::~name() {
|
||||
if (m_imp)
|
||||
m_imp->dec_ref();
|
||||
}
|
||||
|
||||
name & name::operator=(name const & other) {
|
||||
if (other.m_imp)
|
||||
other.m_imp->inc_ref();
|
||||
if (m_imp)
|
||||
m_imp->dec_ref();
|
||||
m_imp = other.m_imp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
name & name::operator=(name && other) {
|
||||
lean_assert(this != &other);
|
||||
if (m_imp)
|
||||
m_imp->dec_ref();
|
||||
m_imp = other.m_imp;
|
||||
other.m_imp = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
name::kind name::get_kind() const {
|
||||
if (m_imp == nullptr)
|
||||
return kind::ANONYMOUS;
|
||||
else
|
||||
return m_imp->m_is_string ? kind::STRING : kind::NUMERAL;
|
||||
}
|
||||
|
||||
unsigned name::get_numeral() const {
|
||||
lean_assert(is_numeral());
|
||||
return m_imp->m_k;
|
||||
}
|
||||
|
||||
char const * name::get_string() const {
|
||||
lean_assert(is_string());
|
||||
return m_imp->m_str;
|
||||
}
|
||||
|
||||
bool name::operator==(name const & other) const {
|
||||
imp * i1 = m_imp;
|
||||
imp * i2 = other.m_imp;
|
||||
while (true) {
|
||||
if (i1 == i2)
|
||||
return true;
|
||||
if ((i1 == nullptr) != (i2 == nullptr))
|
||||
return false;
|
||||
lean_assert(i1 != nullptr);
|
||||
lean_assert(i2 != nullptr);
|
||||
if (i1->m_is_string != i2->m_is_string)
|
||||
return false;
|
||||
if (m_imp->m_is_string) {
|
||||
if (strcmp(get_string(), other.get_string()) != 0)
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (get_numeral() != other.get_numeral())
|
||||
return false;
|
||||
}
|
||||
i1 = i1->m_prefix;
|
||||
i2 = i2->m_prefix;
|
||||
}
|
||||
}
|
||||
|
||||
bool name::is_atomic() const {
|
||||
return m_imp == nullptr || m_imp->m_prefix == nullptr;
|
||||
}
|
||||
|
||||
name name::get_prefix() const {
|
||||
lean_assert(!is_atomic());
|
||||
return name(m_imp->m_prefix);
|
||||
}
|
||||
|
||||
static unsigned num_digits(unsigned k) {
|
||||
if (k == 0)
|
||||
return 1;
|
||||
int r = 0;
|
||||
while (k != 0) {
|
||||
k /= 10;
|
||||
r++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
size_t name::size(char const * sep) const {
|
||||
if (m_imp == nullptr) {
|
||||
return strlen(anonymous_str);
|
||||
}
|
||||
else {
|
||||
imp * i = m_imp;
|
||||
size_t sep_sz = strlen(sep);
|
||||
size_t r = 0;
|
||||
while (true) {
|
||||
if (i->m_is_string) {
|
||||
r += strlen(i->m_str);
|
||||
}
|
||||
else {
|
||||
r += num_digits(i->m_k);
|
||||
}
|
||||
if (i->m_prefix) {
|
||||
r += sep_sz;
|
||||
i = i->m_prefix;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & out, name const & n) {
|
||||
name::imp::display(out, default_name_separator, n.m_imp);
|
||||
return out;
|
||||
}
|
||||
|
||||
name::sep::sep(name const & n, char const * s):m_name(n), m_sep(s) {}
|
||||
|
||||
std::ostream & operator<<(std::ostream & out, name::sep const & s) {
|
||||
name::imp::display(out, s.m_sep, s.m_name.m_imp);
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
58
src/util/name.h
Normal file
58
src/util/name.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
|
||||
Author: Leonardo de Moura
|
||||
*/
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
|
||||
namespace lean {
|
||||
|
||||
constexpr char const * default_name_separator = "::";
|
||||
|
||||
/**
|
||||
\brief Hierarchical names.
|
||||
*/
|
||||
class name {
|
||||
enum class kind { ANONYMOUS, STRING, NUMERAL };
|
||||
struct imp;
|
||||
imp * m_imp;
|
||||
name(imp * p);
|
||||
public:
|
||||
name();
|
||||
name(char const * name);
|
||||
name(unsigned k);
|
||||
name(name const & prefix, char const * name);
|
||||
name(name const & prefix, unsigned k);
|
||||
name(name const & other);
|
||||
name(name && other);
|
||||
~name();
|
||||
name & operator=(name const & other);
|
||||
name & operator=(name && other);
|
||||
bool operator==(name const & other) const;
|
||||
bool operator!=(name const & other) const { return !operator==(other); }
|
||||
kind get_kind() const;
|
||||
bool is_anonymous() const { return get_kind() == kind::ANONYMOUS; }
|
||||
bool is_string() const { return get_kind() == kind::STRING; }
|
||||
bool is_numeral() const { return get_kind() == kind::NUMERAL; }
|
||||
unsigned get_numeral() const;
|
||||
char const * get_string() const;
|
||||
bool is_atomic() const;
|
||||
name get_prefix() const;
|
||||
/**
|
||||
\brief Size of the this name (in characters) when using the given separator.
|
||||
*/
|
||||
size_t size(char const * sep = default_name_separator) const;
|
||||
friend std::ostream & operator<<(std::ostream & out, name const & n);
|
||||
class sep {
|
||||
name const & m_name;
|
||||
char const * m_sep;
|
||||
public:
|
||||
sep(name const & n, char const * s);
|
||||
friend std::ostream & operator<<(std::ostream & out, sep const & s);
|
||||
};
|
||||
friend std::ostream & operator<<(std::ostream & out, sep const & s);
|
||||
};
|
||||
|
||||
}
|
42
src/util/trace.cpp
Normal file
42
src/util/trace.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
|
||||
Author: Leonardo de Moura
|
||||
*/
|
||||
|
||||
#include "trace.h"
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#ifndef LEAN_TRACE_OUT
|
||||
#define LEAN_TRACE_OUT ".lean_trace"
|
||||
#endif
|
||||
|
||||
namespace lean {
|
||||
|
||||
#ifdef LEAN_TRACE
|
||||
std::ofstream tout(LEAN_TRACE_OUT);
|
||||
std::mutex trace_mutex;
|
||||
#endif
|
||||
|
||||
static std::unique_ptr<std::set<std::string>> g_enabled_trace_tags;
|
||||
|
||||
void enable_trace(char const * tag) {
|
||||
if (!g_enabled_trace_tags)
|
||||
g_enabled_trace_tags.reset(new std::set<std::string>());
|
||||
g_enabled_trace_tags->insert(tag);
|
||||
}
|
||||
|
||||
void disable_trace(char const * tag) {
|
||||
if (g_enabled_trace_tags)
|
||||
g_enabled_trace_tags->erase(tag);
|
||||
}
|
||||
|
||||
bool is_trace_enabled(char const * tag) {
|
||||
return g_enabled_trace_tags && g_enabled_trace_tags->find(tag) != g_enabled_trace_tags->end();
|
||||
}
|
||||
|
||||
}
|
||||
|
31
src/util/trace.h
Normal file
31
src/util/trace.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
|
||||
Author: Leonardo de Moura
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef LEAN_TRACE
|
||||
#include <fstream>
|
||||
#include <mutex>
|
||||
namespace lean {
|
||||
extern std::ofstream tout;
|
||||
extern std::mutex trace_mutex;
|
||||
}
|
||||
#define TRACE_CODE(CODE) { std::lock_guard<std::mutex> _lean_trace_lock_(lean::trace_mutex); CODE }
|
||||
#else
|
||||
#define TRACE_CODE(CODE)
|
||||
#endif
|
||||
|
||||
#define lean_trace(TAG, CODE) TRACE_CODE(if (lean::is_trace_enabled(TAG)) { lean::tout << "-------- [" << TAG << "] " << __FUNCTION__ << " " << __FILE__ << ":" << __LINE__ << " ---------\n"; CODE lean::tout << "------------------------------------------------\n"; lean::tout.flush(); })
|
||||
|
||||
#define lean_simple_trace(TAG, CODE) TRACE_CODE(if (lean::is_trace_enabled(TAG)) { CODE lean::tout.flush(); })
|
||||
|
||||
#define lean_cond_trace(TAG, COND, CODE) TRACE_CODE(if (lean::is_trace_enabled(TAG) && (COND)) { lean::tout << "-------- [" << TAG << "] " << __FUNCTION__ << " " << __FILE__ << ":" << __LINE__ << " ---------\n"; CODE lean::tout << "------------------------------------------------\n"; lean::tout.flush(); })
|
||||
|
||||
namespace lean {
|
||||
void enable_trace(char const * tag);
|
||||
void disable_trace(char const * tag);
|
||||
bool is_trace_enabled(char const * tag);
|
||||
}
|
Loading…
Reference in a new issue