Added prime polynomial example, new Pumping function to address scalability challenges with primality testing, and some improvements to the streaming interface, where if you don't stream in values, then the python side doesn't end up printing out some 'empty' stream infos.

This commit is contained in:
Peter Goodman
2017-12-09 16:43:43 -05:00
parent 3aaaf71b85
commit 188d4517d8
11 changed files with 271 additions and 17 deletions
+24 -2
View File
@@ -59,6 +59,27 @@ extern int16_t DeepState_Short(void);
extern uint8_t DeepState_UChar(void);
extern int8_t DeepState_Char(void);
/* Returns the minimum satisfiable value for a given symbolic value, given
* the constraints present on that value. */
extern uint32_t DeepState_MinUInt(uint32_t);
extern int32_t DeepState_MinInt(int32_t);
DEEPSTATE_INLINE static uint16_t DeepState_MinUShort(uint16_t v) {
return DeepState_MinUInt(v);
}
DEEPSTATE_INLINE static uint8_t DeepState_MinUChar(uint8_t v) {
return DeepState_MinUInt(v);
}
DEEPSTATE_INLINE static int16_t DeepState_MinShort(int16_t v) {
return DeepState_MinInt(v);
}
DEEPSTATE_INLINE static int8_t DeepState_MinChar(int8_t v) {
return DeepState_MinInt(v);
}
/* Returns `1` if `expr` is true, and `0` otherwise. This is kind of an indirect
* way to take a symbolic value, introduce a fork, and on each size, replace its
* value with a concrete value. */
@@ -105,9 +126,10 @@ DEEPSTATE_MAKE_SYMBOLIC_ARRAY(UChar, unsigned char)
/* Creates an assumption about a symbolic value. Returns `1` if the assumption
* can hold and was asserted. */
extern void _DeepState_Assume(int expr);
extern void _DeepState_Assume(int expr, const char *expr_str, const char *file,
unsigned line);
#define DeepState_Assume(x) _DeepState_Assume(!!(x))
#define DeepState_Assume(x) _DeepState_Assume(!!(x), #x, __FILE__, __LINE__)
/* Abandon this test. We've hit some kind of internal problem. */
DEEPSTATE_NORETURN
+80
View File
@@ -192,6 +192,39 @@ class Symbolic<std::vector<T>> :
DEEPSTATE_INLINE operator tname (void) const { \
return value; \
} \
DEEPSTATE_INLINE tname operator+(const tname that) const { \
return value + that; \
} \
DEEPSTATE_INLINE tname operator-(const tname that) const { \
return value - that; \
} \
DEEPSTATE_INLINE tname operator*(const tname that) const { \
return value * that; \
} \
DEEPSTATE_INLINE tname operator/(const tname that) const { \
return value / that; \
} \
DEEPSTATE_INLINE tname operator|(const tname that) const { \
return value | that; \
} \
DEEPSTATE_INLINE tname operator&(const tname that) const { \
return value & that; \
} \
DEEPSTATE_INLINE tname operator^(const tname that) const { \
return value ^ that; \
} \
DEEPSTATE_INLINE tname operator~(void) const { \
return ~value; \
} \
DEEPSTATE_INLINE tname operator-(void) const { \
return -value; \
} \
DEEPSTATE_INLINE tname operator>>(const tname that) const { \
return value >> that; \
} \
DEEPSTATE_INLINE tname operator<<(const tname that) const { \
return value << that; \
} \
tname value; \
};
@@ -204,8 +237,55 @@ MAKE_SYMBOL_SPECIALIZATION(Short, int16_t)
MAKE_SYMBOL_SPECIALIZATION(UChar, uint8_t)
MAKE_SYMBOL_SPECIALIZATION(Char, int8_t)
using symbolic_char = Symbolic<char>;
using symbolic_short = Symbolic<short>;
using symbolic_int = Symbolic<int>;
using symbolic_unsigned = Symbolic<unsigned>;
using symbolic_long = Symbolic<long>;
using symbolic_int8_t = Symbolic<int8_t>;
using symbolic_uint8_t = Symbolic<uint8_t>;
using symbolic_int16_t = Symbolic<int16_t>;
using symbolic_uint16_t = Symbolic<uint16_t>;
using symbolic_int32_t = Symbolic<int32_t>;
using symbolic_uint32_t = Symbolic<uint32_t>;
using symbolic_int64_t = Symbolic<int64_t>;
using symbolic_uint64_t = Symbolic<uint64_t>;
#undef MAKE_SYMBOL_SPECIALIZATION
#define MAKE_MINIMIZER(Type, type) \
DEEPSTATE_INLINE static type Minimize(type val) { \
return DeepState_Min ## Type(val); \
}
MAKE_MINIMIZER(UInt, uint32_t)
MAKE_MINIMIZER(Int, int32_t)
MAKE_MINIMIZER(UShort, uint16_t)
MAKE_MINIMIZER(Short, int16_t)
MAKE_MINIMIZER(UChar, uint8_t)
MAKE_MINIMIZER(Char, int8_t)
#undef MAKE_MINIMIZER
template <typename T>
static T Pump(T val, unsigned max=10) {
if (!IsSymbolic(val)) {
return val;
}
for (auto i = 0U; i < max; ++i) {
T min_val = Minimize(val);
if (val == min_val) {
asm volatile ("" : : "m"(min_val) : "memory");
return min_val; // Force the concrete `min_val` to be returned,
// as opposed to compiler possibly choosing to
// return `val`.
}
}
return Minimize(val);
}
template <typename... Args>
inline static void ForAll(void (*func)(Args...)) {
func(Symbolic<Args>()...);
+3
View File
@@ -25,6 +25,9 @@
DEEPSTATE_BEGIN_EXTERN_C
/* Clear the contents of the stream and don't log it. */
extern void DeepState_ClearStream(enum DeepState_LogLevel level);
/* Flush the contents of the stream to a log. */
extern void DeepState_LogStream(enum DeepState_LogLevel level);
+12 -4
View File
@@ -28,9 +28,10 @@ namespace deepstate {
class Stream {
public:
DEEPSTATE_INLINE Stream(DeepState_LogLevel level_, bool do_log_,
const char *file, unsigned line)
const char *file, unsigned line)
: level(level_),
do_log(DeepState_IsTrue(do_log_)) {
do_log(!!DeepState_IsTrue(do_log_)),
has_something_to_log(false) {
DeepState_LogStream(level);
if (do_log) {
DeepState_StreamFormat(level, "%s(%u): ", file, line);
@@ -39,7 +40,11 @@ class Stream {
DEEPSTATE_INLINE ~Stream(void) {
if (do_log) {
DeepState_LogStream(level);
if (has_something_to_log) {
DeepState_LogStream(level);
} else {
DeepState_ClearStream(level);
}
}
}
@@ -47,6 +52,7 @@ class Stream {
DEEPSTATE_INLINE const Stream &operator<<(type val) const { \
if (do_log) { \
DeepState_Stream ## Type(level, expr); \
has_something_to_log = true; \
} \
return *this; \
}
@@ -82,6 +88,7 @@ class Stream {
DEEPSTATE_INLINE const Stream &operator<<(const std::string &str) const {
if (do_log && !str.empty()) {
DeepState_StreamCStr(level, str.c_str());
has_something_to_log = true;
}
return *this;
}
@@ -94,7 +101,8 @@ class Stream {
Stream &operator=(const Stream &) = delete;
const DeepState_LogLevel level;
const int do_log;
const bool do_log;
mutable bool has_something_to_log;
};
} // namespace deepstate
+19 -2
View File
@@ -15,6 +15,7 @@
*/
#include "deepstate/DeepState.h"
#include "deepstate/Log.h"
#include <assert.h>
#include <limits.h>
@@ -195,9 +196,22 @@ int8_t DeepState_Char(void) {
#undef MAKE_SYMBOL_FUNC
void _DeepState_Assume(int expr) {
/* Returns the minimum satisfiable value for a given symbolic value, given
* the constraints present on that value. */
uint32_t DeepState_MinUInt(uint32_t v) {
return v;
}
int32_t DeepState_MinInt(int32_t v) {
return v;
}
void _DeepState_Assume(int expr, const char *expr_str, const char *file,
unsigned line) {
if (!expr) {
DeepState_Abandon("");
DeepState_LogFormat(DeepState_LogFatal, "Assumption %s at %s:%u failed",
expr_str, file, line);
}
}
@@ -248,11 +262,14 @@ const struct DeepState_IndexEntry DeepState_API[] = {
{"IsSymbolicUInt", (void *) DeepState_IsSymbolicUInt},
{"ConcretizeData", (void *) DeepState_ConcretizeData},
{"ConcretizeCStr", (void *) DeepState_ConcretizeCStr},
{"MinUInt", (void *) DeepState_MinUInt},
{"MinInt", (void *) DeepState_MinInt},
/* Logging API. */
{"Log", (void *) DeepState_Log},
/* Streaming API for deferred logging. */
{"ClearStream", (void *) DeepState_ClearStream},
{"LogStream", (void *) DeepState_LogStream},
{"StreamInt", (void *) _DeepState_StreamInt},
{"StreamFloat", (void *) _DeepState_StreamFloat},
+10 -2
View File
@@ -251,6 +251,15 @@ void DeepState_StreamDouble(enum DeepState_LogLevel level, double val) {
_DeepState_StreamFloat(level, format, stream->unpack, &(stream->value.as_fp64));
}
/* Clear the contents of the stream and don't log it. */
void DeepState_ClearStream(enum DeepState_LogLevel level) {
struct DeepState_Stream *stream = &(DeepState_Streams[level]);
if (stream->size) {
memset(stream->message, 0, DeepState_StreamSize);
stream->size = 0;
}
}
/* Flush the contents of the stream to a log. */
void DeepState_LogStream(enum DeepState_LogLevel level) {
struct DeepState_Stream *stream = &(DeepState_Streams[level]);
@@ -258,8 +267,7 @@ void DeepState_LogStream(enum DeepState_LogLevel level) {
stream->message[stream->size] = '\0';
stream->message[DeepState_StreamSize] = '\0';
DeepState_Log(level, stream->message);
memset(stream->message, 0, DeepState_StreamSize);
stream->size = 0;
DeepState_ClearStream(level);
}
}