evoasm 0.0.2.pre7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gemrelease +2 -0
- data/.gitignore +16 -0
- data/Gemfile +4 -0
- data/Gemfile.rake +8 -0
- data/Gemfile.rake.lock +51 -0
- data/LICENSE.txt +373 -0
- data/Makefile +6 -0
- data/README.md +43 -0
- data/Rakefile +128 -0
- data/bin/gdb +2 -0
- data/data/tables/README.md +19 -0
- data/data/tables/x64.csv +1684 -0
- data/data/templates/evoasm-x64.c.erb +319 -0
- data/data/templates/evoasm-x64.h.erb +126 -0
- data/evoasm.gemspec +30 -0
- data/examples/abs.yml +20 -0
- data/examples/popcnt.yml +17 -0
- data/examples/sym_reg.yml +26 -0
- data/exe/evoasm-search +13 -0
- data/ext/evoasm_ext/evoasm-alloc.c +145 -0
- data/ext/evoasm_ext/evoasm-alloc.h +59 -0
- data/ext/evoasm_ext/evoasm-arch.c +44 -0
- data/ext/evoasm_ext/evoasm-arch.h +161 -0
- data/ext/evoasm_ext/evoasm-bitmap.h +114 -0
- data/ext/evoasm_ext/evoasm-buf.c +130 -0
- data/ext/evoasm_ext/evoasm-buf.h +47 -0
- data/ext/evoasm_ext/evoasm-error.c +31 -0
- data/ext/evoasm_ext/evoasm-error.h +75 -0
- data/ext/evoasm_ext/evoasm-free-list.c.tmpl +121 -0
- data/ext/evoasm_ext/evoasm-free-list.h.tmpl +86 -0
- data/ext/evoasm_ext/evoasm-log.c +108 -0
- data/ext/evoasm_ext/evoasm-log.h +69 -0
- data/ext/evoasm_ext/evoasm-misc.c +23 -0
- data/ext/evoasm_ext/evoasm-misc.h +282 -0
- data/ext/evoasm_ext/evoasm-param.h +37 -0
- data/ext/evoasm_ext/evoasm-search.c +2145 -0
- data/ext/evoasm_ext/evoasm-search.h +214 -0
- data/ext/evoasm_ext/evoasm-util.h +40 -0
- data/ext/evoasm_ext/evoasm-x64.c +275624 -0
- data/ext/evoasm_ext/evoasm-x64.h +5436 -0
- data/ext/evoasm_ext/evoasm.c +7 -0
- data/ext/evoasm_ext/evoasm.h +23 -0
- data/ext/evoasm_ext/evoasm_ext.c +1757 -0
- data/ext/evoasm_ext/extconf.rb +31 -0
- data/lib/evoasm/cli/search.rb +127 -0
- data/lib/evoasm/cli.rb +6 -0
- data/lib/evoasm/core_ext/array.rb +9 -0
- data/lib/evoasm/core_ext/integer.rb +10 -0
- data/lib/evoasm/core_ext/kwstruct.rb +13 -0
- data/lib/evoasm/core_ext/range.rb +5 -0
- data/lib/evoasm/core_ext.rb +1 -0
- data/lib/evoasm/error.rb +20 -0
- data/lib/evoasm/examples.rb +27 -0
- data/lib/evoasm/gen/enum.rb +169 -0
- data/lib/evoasm/gen/name_util.rb +80 -0
- data/lib/evoasm/gen/state.rb +176 -0
- data/lib/evoasm/gen/state_dsl.rb +152 -0
- data/lib/evoasm/gen/strio.rb +27 -0
- data/lib/evoasm/gen/translator.rb +1102 -0
- data/lib/evoasm/gen/version.rb +5 -0
- data/lib/evoasm/gen/x64/funcs.rb +495 -0
- data/lib/evoasm/gen/x64/inst.rb +781 -0
- data/lib/evoasm/gen/x64.rb +237 -0
- data/lib/evoasm/gen.rb +8 -0
- data/lib/evoasm/program.rb +23 -0
- data/lib/evoasm/search.rb +40 -0
- data/lib/evoasm/tasks/gen_task.rb +86 -0
- data/lib/evoasm/tasks/template_task.rb +52 -0
- data/lib/evoasm/version.rb +3 -0
- data/lib/evoasm.rb +22 -0
- data/test/test_helper.rb +1 -0
- data/test/x64/test_helper.rb +19 -0
- data/test/x64/x64_test.rb +87 -0
- metadata +221 -0
@@ -0,0 +1,121 @@
|
|
1
|
+
#include <assert.h>
|
2
|
+
#include <errno.h>
|
3
|
+
|
4
|
+
#include "$-s.h"
|
5
|
+
#include "evoasm-alloc.h"
|
6
|
+
|
7
|
+
$includes
|
8
|
+
|
9
|
+
void
|
10
|
+
$s_clear($s *free_list, $s_index start, $s_index end) {
|
11
|
+
for($s_index i = start; i < end - 1; i++) {
|
12
|
+
$S_DATA(free_list)[i].free = true;
|
13
|
+
$S_DATA(free_list)[i].next_free = i + 1;
|
14
|
+
}
|
15
|
+
$S_DATA(free_list)[end - 1].next_free = $S_NULL_IDX;
|
16
|
+
$S_DATA(free_list)[end - 1].free = true;
|
17
|
+
|
18
|
+
free_list->last_free = end - 1;
|
19
|
+
}
|
20
|
+
|
21
|
+
|
22
|
+
$e *
|
23
|
+
$s_data($s *free_list) {
|
24
|
+
return $S_DATA(free_list);
|
25
|
+
}
|
26
|
+
|
27
|
+
evoasm_success
|
28
|
+
$s_init($s *free_list, $s_index capa) {
|
29
|
+
|
30
|
+
#if $embed > 0
|
31
|
+
free_list->data = NULL;
|
32
|
+
free_list->capa = EVOASM_SEQ_EMBED_N;
|
33
|
+
#else
|
34
|
+
size_t size = sizeof($e) * capa;
|
35
|
+
free_list->data = evoasm_malloc(size);
|
36
|
+
if(free_list->data == NULL) {
|
37
|
+
evoasm_set_error(EVOASM_ERROR_TYPE_MEMORY, EVOASM_ERROR_CODE_NONE,
|
38
|
+
NULL, "Allocationg buffer of size %zu failed: %s", size, strerror(errno));
|
39
|
+
return false;
|
40
|
+
}
|
41
|
+
free_list->capa = capa;
|
42
|
+
#endif
|
43
|
+
|
44
|
+
free_list->first_free = 0;
|
45
|
+
free_list->len = 0;
|
46
|
+
|
47
|
+
$s_clear(free_list, 0, free_list->capa);
|
48
|
+
return true;
|
49
|
+
}
|
50
|
+
|
51
|
+
evoasm_success
|
52
|
+
_$s_grow($s *free_list) {
|
53
|
+
$s_index new_capa = free_list->capa + free_list->capa / 2;
|
54
|
+
|
55
|
+
#if $embed > 0
|
56
|
+
if(free_list->data == NULL) {
|
57
|
+
free_list->data = malloc(sizeof($e) * new_capa);
|
58
|
+
memcpy(free_list->data, free_list->_data, sizeof($e) * free_list->capa);
|
59
|
+
goto update;
|
60
|
+
}
|
61
|
+
#endif
|
62
|
+
|
63
|
+
{
|
64
|
+
size_t size = sizeof($e) * new_capa;
|
65
|
+
$e *new_data = evoasm_realloc(free_list->data, size);
|
66
|
+
|
67
|
+
if(EVOASM_UNLIKELY(new_data == NULL)) {
|
68
|
+
evoasm_set_error(EVOASM_ERROR_TYPE_MEMORY, EVOASM_ERROR_CODE_NONE,
|
69
|
+
NULL, "Reallocationg buffer of size %zu failed: %s", size, strerror(errno));
|
70
|
+
return false;
|
71
|
+
}
|
72
|
+
}
|
73
|
+
update:
|
74
|
+
free_list->first_free = free_list->capa;
|
75
|
+
$s_clear(free_list, free_list->capa, new_capa);
|
76
|
+
free_list->capa = new_capa;
|
77
|
+
return true;
|
78
|
+
}
|
79
|
+
|
80
|
+
$e *
|
81
|
+
$s_delete($s *free_list, $e *e) {
|
82
|
+
$s_index idx = $s_index(free_list, e);
|
83
|
+
|
84
|
+
e->next_free = free_list->first_free;
|
85
|
+
e->free = true;
|
86
|
+
|
87
|
+
// only free slot
|
88
|
+
if(free_list->last_free == $S_NULL_IDX) {
|
89
|
+
free_list->last_free = idx;
|
90
|
+
}
|
91
|
+
|
92
|
+
free_list->first_free = idx;
|
93
|
+
free_list->len--;
|
94
|
+
return e;
|
95
|
+
}
|
96
|
+
|
97
|
+
bool
|
98
|
+
$s_eql($s *a, $s *b) {
|
99
|
+
$eql
|
100
|
+
}
|
101
|
+
|
102
|
+
bool
|
103
|
+
$s_find($s *free_list, $e *value, $s_index *index) {
|
104
|
+
|
105
|
+
if(free_list->len == 0) return false;
|
106
|
+
|
107
|
+
for($s_index i = 0; i < free_list->capa; i++) {
|
108
|
+
if(!$S_DATA(free_list)[i].free) {
|
109
|
+
if($s_cmp(value, &$S_DATA(free_list)[i])) {
|
110
|
+
if(index != NULL) *index = i;
|
111
|
+
return true;
|
112
|
+
}
|
113
|
+
}
|
114
|
+
}
|
115
|
+
return false;
|
116
|
+
}
|
117
|
+
|
118
|
+
void
|
119
|
+
$s_destroy($s *free_list) {
|
120
|
+
evoasm_free(free_list->data);
|
121
|
+
}
|
@@ -0,0 +1,86 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include <stdint.h>
|
4
|
+
#include "evoasm-error.h"
|
5
|
+
|
6
|
+
$includes
|
7
|
+
|
8
|
+
#if $embed > 0
|
9
|
+
# define $S_DATA(free_list) (free_list->data != NULL ? free_list->data : free_list->_data)
|
10
|
+
#else
|
11
|
+
# define $S_DATA(free_list) (free_list->data)
|
12
|
+
#endif
|
13
|
+
|
14
|
+
#define $S_NULL_IDX ((uint$w_t)-1)
|
15
|
+
|
16
|
+
typedef uint$w_t $s_index;
|
17
|
+
|
18
|
+
typedef struct $s {
|
19
|
+
$s_index capa;
|
20
|
+
$s_index len;
|
21
|
+
$s_index first_free;
|
22
|
+
$s_index last_free;
|
23
|
+
$e *data;
|
24
|
+
|
25
|
+
#if $embed > 0
|
26
|
+
$e _data[$embed];
|
27
|
+
#endif
|
28
|
+
} $s;
|
29
|
+
|
30
|
+
static inline uint32_t
|
31
|
+
$s_get_index($s *free_list, $e *e) {
|
32
|
+
return (uint32_t)(e - $S_DATA(free_list));
|
33
|
+
}
|
34
|
+
|
35
|
+
static inline $e *
|
36
|
+
$s_get($s *free_list, $s_index index) {
|
37
|
+
#if 0
|
38
|
+
if(index >= free_list->capa) {
|
39
|
+
return NULL;
|
40
|
+
}
|
41
|
+
return $S_DATA(free_list)[index].free ? NULL : &$S_DATA(free_list)[index];
|
42
|
+
#endif
|
43
|
+
return &$S_DATA(free_list)[index];
|
44
|
+
}
|
45
|
+
|
46
|
+
evoasm_success _$s_grow($s *free_list);
|
47
|
+
|
48
|
+
static inline evoasm_success
|
49
|
+
$s_push($s *free_list, $e **ee, $s_index *ridx) {
|
50
|
+
if(free_list->first_free == $S_NULL_IDX) {
|
51
|
+
if(!_$s_grow(free_list)) {
|
52
|
+
return false;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
{
|
57
|
+
$e *entry = &$S_DATA(free_list)[free_list->first_free];
|
58
|
+
|
59
|
+
$s_index idx = free_list->first_free;
|
60
|
+
|
61
|
+
// used up last free slot
|
62
|
+
if(entry->next_free == $S_NULL_IDX){
|
63
|
+
assert(idx == free_list->last_free);
|
64
|
+
free_list->last_free = $S_NULL_IDX;
|
65
|
+
}
|
66
|
+
|
67
|
+
free_list->first_free = entry->next_free;
|
68
|
+
|
69
|
+
entry->free = false;
|
70
|
+
entry->next_free = $S_NULL_IDX;
|
71
|
+
|
72
|
+
free_list->len++;
|
73
|
+
|
74
|
+
*ee = entry;
|
75
|
+
if(ridx) {
|
76
|
+
*ridx = idx;
|
77
|
+
}
|
78
|
+
return true;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
void $s_clear($s *free_list, uint32_t start, uint32_t end);
|
83
|
+
evoasm_success $s_init($s *free_list, $s_index capa);
|
84
|
+
$e *$s_delete($s *free_list, $e *e);
|
85
|
+
void $s_destroy($s *free_list);
|
86
|
+
$e * $s_data($s *free_list);
|
@@ -0,0 +1,108 @@
|
|
1
|
+
#define _DEFAULT_SOURCE
|
2
|
+
|
3
|
+
#include <stdarg.h>
|
4
|
+
#include <stdio.h>
|
5
|
+
#include <string.h>
|
6
|
+
#include <stdint.h>
|
7
|
+
#include <stdlib.h>
|
8
|
+
#include <stdbool.h>
|
9
|
+
#include <alloca.h>
|
10
|
+
|
11
|
+
#ifdef _WIN32
|
12
|
+
#include <io.h>
|
13
|
+
#define isatty _isatty
|
14
|
+
#else
|
15
|
+
#include <unistd.h>
|
16
|
+
#endif
|
17
|
+
|
18
|
+
#include "evoasm-log.h"
|
19
|
+
#include "evoasm-alloc.h"
|
20
|
+
|
21
|
+
evoasm_log_level evoasm_min_log_level = EVOASM_LOG_LEVEL_WARN;
|
22
|
+
FILE * evoasm_log_file;
|
23
|
+
|
24
|
+
static const char *const log_levels[EVOASM_N_LOG_LEVELS] = {
|
25
|
+
"TRACE",
|
26
|
+
"DEBUG",
|
27
|
+
"INFO",
|
28
|
+
"WARN",
|
29
|
+
"ERROR",
|
30
|
+
"FATAL"
|
31
|
+
};
|
32
|
+
|
33
|
+
static const char *const log_colors[EVOASM_N_LOG_LEVELS] = {
|
34
|
+
"\x1b[30;1m",
|
35
|
+
"\x1b[30;1m",
|
36
|
+
"\x1b[32;1m",
|
37
|
+
"\x1b[33;1m",
|
38
|
+
"\x1b[31;1m",
|
39
|
+
"\x1b[31;1m",
|
40
|
+
};
|
41
|
+
|
42
|
+
|
43
|
+
void
|
44
|
+
evoasm_log(evoasm_log_level level, const char *tag, const char *format, ...)
|
45
|
+
{
|
46
|
+
if(level < evoasm_min_log_level) return;
|
47
|
+
|
48
|
+
va_list args;
|
49
|
+
|
50
|
+
static const char *prefix = "evoasm:";
|
51
|
+
static const char *sep1 = ":";
|
52
|
+
static const char *sep2 = ": ";
|
53
|
+
static const char *color_reset = "\x1b[0m";
|
54
|
+
bool is_tty = isatty(fileno(evoasm_log_file));
|
55
|
+
|
56
|
+
size_t prefix_len = strlen(prefix);
|
57
|
+
size_t color_len = is_tty ? strlen(log_colors[level]) : 0;
|
58
|
+
size_t level_len = strlen(log_levels[level]);
|
59
|
+
size_t color_reset_len = is_tty ? strlen(color_reset) : 0;
|
60
|
+
size_t tag_len = strlen(tag);
|
61
|
+
size_t sep1_len = strlen(sep1);
|
62
|
+
size_t sep2_len = strlen(sep2);
|
63
|
+
bool print_prefix = format[0] != ' ';
|
64
|
+
const char *format_ = format + (print_prefix ? 0 : 1);
|
65
|
+
size_t format_len = strlen(format_);
|
66
|
+
bool print_new_line = format_[format_len - 1] != ' ';
|
67
|
+
if(!print_new_line) format_len--;
|
68
|
+
char *full_format = evoasm_alloca(prefix_len
|
69
|
+
+ color_len
|
70
|
+
+ level_len
|
71
|
+
+ color_reset_len
|
72
|
+
+ sep1_len
|
73
|
+
+ tag_len
|
74
|
+
+ sep2_len
|
75
|
+
+ format_len
|
76
|
+
+ 2);
|
77
|
+
size_t i = 0;
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
#define __CPY(s, l) \
|
82
|
+
memcpy(full_format + i, (s), (l)); i+= (l);
|
83
|
+
|
84
|
+
if(print_prefix) {
|
85
|
+
__CPY(prefix, prefix_len)
|
86
|
+
__CPY(log_colors[level], color_len)
|
87
|
+
__CPY(log_levels[level], level_len)
|
88
|
+
__CPY(color_reset, color_reset_len)
|
89
|
+
__CPY(sep1, sep1_len)
|
90
|
+
__CPY(tag, tag_len)
|
91
|
+
__CPY(sep2, sep2_len)
|
92
|
+
}
|
93
|
+
__CPY(format_, format_len)
|
94
|
+
|
95
|
+
#undef __CPY
|
96
|
+
|
97
|
+
if(print_new_line) {
|
98
|
+
full_format[i] = '\n'; i++;
|
99
|
+
}
|
100
|
+
full_format[i] = '\0'; i++;
|
101
|
+
|
102
|
+
//fprintf(stderr, "printing '%s'\n", full_format);
|
103
|
+
va_start(args, format);
|
104
|
+
vfprintf(evoasm_log_file, full_format, args);
|
105
|
+
va_end(args);
|
106
|
+
}
|
107
|
+
|
108
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include <stdlib.h>
|
4
|
+
#include <stdio.h>
|
5
|
+
#include <stdint.h>
|
6
|
+
|
7
|
+
typedef uint8_t evoasm_log_level;
|
8
|
+
#define EVOASM_LOG_LEVEL_TRACE 0
|
9
|
+
#define EVOASM_LOG_LEVEL_DEBUG 1
|
10
|
+
#define EVOASM_LOG_LEVEL_INFO 2
|
11
|
+
#define EVOASM_LOG_LEVEL_WARN 3
|
12
|
+
#define EVOASM_LOG_LEVEL_ERROR 4
|
13
|
+
#define EVOASM_LOG_LEVEL_FATAL 5
|
14
|
+
#define EVOASM_N_LOG_LEVELS 6
|
15
|
+
|
16
|
+
#ifndef EVOASM_MIN_LOG_LEVEL
|
17
|
+
# define EVOASM_MIN_LOG_LEVEL EVOASM_LOG_LEVEL_INFO
|
18
|
+
#endif
|
19
|
+
|
20
|
+
extern evoasm_log_level evoasm_min_log_level;
|
21
|
+
extern FILE * evoasm_log_file;
|
22
|
+
|
23
|
+
#ifdef __GNUC__
|
24
|
+
# define EVOASM_LOG_ATTRS __attribute__ ((format(printf, 3, 4)))
|
25
|
+
#else
|
26
|
+
# define EVOASM_LOG_ATTRS
|
27
|
+
#endif
|
28
|
+
|
29
|
+
#define EVOASM_DECL_LOG_TAG(tag) evoasm_used static const char *_evoasm_log_tag = tag;
|
30
|
+
#define EVOASM_LOG_TAG _evoasm_log_tag
|
31
|
+
|
32
|
+
void
|
33
|
+
evoasm_log(evoasm_log_level level, const char *tag, const char *format, ...) EVOASM_LOG_ATTRS;
|
34
|
+
|
35
|
+
#if EVOASM_MIN_LOG_LEVEL <= EVOASM_LOG_LEVEL_TRACE
|
36
|
+
# define evoasm_trace(...) evoasm_log(EVOASM_LOG_LEVEL_TRACE, EVOASM_LOG_TAG, __VA_ARGS__)
|
37
|
+
#else
|
38
|
+
# define evoasm_trace(...)
|
39
|
+
#endif
|
40
|
+
|
41
|
+
#if EVOASM_MIN_LOG_LEVEL <= EVOASM_LOG_LEVEL_DEBUG
|
42
|
+
# define evoasm_debug(...) evoasm_log(EVOASM_LOG_LEVEL_DEBUG, EVOASM_LOG_TAG, __VA_ARGS__)
|
43
|
+
#else
|
44
|
+
# define evoasm_debug(...)
|
45
|
+
#endif
|
46
|
+
|
47
|
+
#if EVOASM_MIN_LOG_LEVEL <= EVOASM_LOG_LEVEL_INFO
|
48
|
+
# define evoasm_info(...) evoasm_log(EVOASM_LOG_LEVEL_INFO, EVOASM_LOG_TAG, __VA_ARGS__)
|
49
|
+
#else
|
50
|
+
# define evoasm_info(...)
|
51
|
+
#endif
|
52
|
+
|
53
|
+
#if EVOASM_MIN_LOG_LEVEL <= EVOASM_LOG_LEVEL_WARN
|
54
|
+
# define evoasm_warn(...) evoasm_log(EVOASM_LOG_LEVEL_WARN, EVOASM_LOG_TAG, __VA_ARGS__)
|
55
|
+
#else
|
56
|
+
# define evoasm_warn(...)
|
57
|
+
#endif
|
58
|
+
|
59
|
+
#if EVOASM_MIN_LOG_LEVEL <= EVOASM_LOG_LEVEL_ERROR
|
60
|
+
# define evoasm_error(...) evoasm_log(EVOASM_LOG_LEVEL_ERROR, EVOASM_LOG_TAG, __VA_ARGS__)
|
61
|
+
#else
|
62
|
+
# define evoasm_error(...)
|
63
|
+
#endif
|
64
|
+
|
65
|
+
#if EVOASM_MIN_LOG_LEVEL <= EVOASM_LOG_LEVEL_FATAL
|
66
|
+
# define evoasm_fatal(...) evoasm_log(EVOASM_LOG_LEVEL_FATAL, EVOASM_LOG_TAG, __VA_ARGS__)
|
67
|
+
#else
|
68
|
+
# define evoasm_fatal(...)
|
69
|
+
#endif
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#include "evoasm.h"
|
2
|
+
#include "evoasm-util.h"
|
3
|
+
|
4
|
+
//static const char *_evoasm_log_tag = "general";
|
5
|
+
|
6
|
+
void
|
7
|
+
evoasm_prng64_init(struct evoasm_prng64 *prng, evoasm_prng64_seed *seed) {
|
8
|
+
prng->s = *seed;
|
9
|
+
}
|
10
|
+
|
11
|
+
void
|
12
|
+
evoasm_prng64_destroy(struct evoasm_prng64 *prng) {
|
13
|
+
}
|
14
|
+
|
15
|
+
void
|
16
|
+
evoasm_prng32_init(struct evoasm_prng32 *prng, evoasm_prng32_seed *seed) {
|
17
|
+
prng->s = *seed;
|
18
|
+
}
|
19
|
+
|
20
|
+
void
|
21
|
+
evoasm_prng32_destroy(struct evoasm_prng32 *prng) {
|
22
|
+
}
|
23
|
+
|
@@ -0,0 +1,282 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "evoasm-error.h"
|
4
|
+
|
5
|
+
#define _EVOASM_DOMAIN_HEADER \
|
6
|
+
evoasm_domain_type type: 8; \
|
7
|
+
unsigned index :24;
|
8
|
+
|
9
|
+
#define _EVOASM_ENUM_HEADER \
|
10
|
+
_EVOASM_DOMAIN_HEADER \
|
11
|
+
uint16_t len;
|
12
|
+
|
13
|
+
#define _EVOASM_DECL_ENUM_TYPE(l) \
|
14
|
+
typedef struct { \
|
15
|
+
_EVOASM_ENUM_HEADER \
|
16
|
+
int64_t vals[l]; \
|
17
|
+
} evoasm_enum ## l;
|
18
|
+
|
19
|
+
|
20
|
+
#define EVOASM_ENUM_MAX_LEN 32
|
21
|
+
|
22
|
+
#define EVOASM_ENUM_VALS_SIZE(len) ((size_t)(len) * sizeof(int64_t))
|
23
|
+
#define EVOASM_ENUM_SIZE(len) (sizeof(evoasm_enum) + EVOASM_ENUM_VALS_SIZE(len))
|
24
|
+
|
25
|
+
typedef enum {
|
26
|
+
EVOASM_DOMAIN_TYPE_ENUM,
|
27
|
+
EVOASM_DOMAIN_TYPE_INTERVAL,
|
28
|
+
EVOASM_DOMAIN_TYPE_INTERVAL64,
|
29
|
+
EVOASM_N_DOMAIN_TYPES
|
30
|
+
} evoasm_domain_type;
|
31
|
+
|
32
|
+
typedef struct {
|
33
|
+
_EVOASM_DOMAIN_HEADER
|
34
|
+
int64_t pad[EVOASM_ENUM_MAX_LEN];
|
35
|
+
} evoasm_domain;
|
36
|
+
|
37
|
+
typedef struct {
|
38
|
+
_EVOASM_DOMAIN_HEADER
|
39
|
+
int64_t min;
|
40
|
+
int64_t max;
|
41
|
+
} evoasm_interval;
|
42
|
+
|
43
|
+
typedef struct {
|
44
|
+
_EVOASM_ENUM_HEADER
|
45
|
+
int64_t vals[];
|
46
|
+
} evoasm_enum;
|
47
|
+
|
48
|
+
_EVOASM_DECL_ENUM_TYPE(2)
|
49
|
+
_EVOASM_DECL_ENUM_TYPE(3)
|
50
|
+
_EVOASM_DECL_ENUM_TYPE(4)
|
51
|
+
_EVOASM_DECL_ENUM_TYPE(8)
|
52
|
+
_EVOASM_DECL_ENUM_TYPE(11)
|
53
|
+
_EVOASM_DECL_ENUM_TYPE(16)
|
54
|
+
|
55
|
+
typedef struct {
|
56
|
+
uint64_t data[16];
|
57
|
+
} evoasm_prng64_seed;
|
58
|
+
|
59
|
+
typedef struct {
|
60
|
+
uint32_t data[4];
|
61
|
+
} evoasm_prng32_seed;
|
62
|
+
|
63
|
+
typedef struct evoasm_prng64 {
|
64
|
+
/* xorshift1024star */
|
65
|
+
evoasm_prng64_seed s;
|
66
|
+
int p;
|
67
|
+
} evoasm_prng64;
|
68
|
+
|
69
|
+
typedef struct evoasm_prng32 {
|
70
|
+
/* xorshift128 */
|
71
|
+
evoasm_prng32_seed s;
|
72
|
+
int p;
|
73
|
+
} evoasm_prng32;
|
74
|
+
|
75
|
+
void
|
76
|
+
evoasm_prng64_init(struct evoasm_prng64 *prng, evoasm_prng64_seed *seed);
|
77
|
+
|
78
|
+
void
|
79
|
+
evoasm_prng64_destroy(struct evoasm_prng64 *prng);
|
80
|
+
|
81
|
+
void
|
82
|
+
evoasm_prng32_init(struct evoasm_prng32 *prng, evoasm_prng32_seed *seed);
|
83
|
+
|
84
|
+
void
|
85
|
+
evoasm_prng32_destroy(struct evoasm_prng32 *prng);
|
86
|
+
|
87
|
+
/* From: https://en.wikipedia.org/wiki/Xorshift */
|
88
|
+
static inline uint64_t
|
89
|
+
evoasm_prng64_rand(struct evoasm_prng64 *prng) {
|
90
|
+
uint64_t *s = prng->s.data;
|
91
|
+
const uint64_t s0 = s[prng->p];
|
92
|
+
uint64_t s1 = s[prng->p = (prng->p + 1) & 15];
|
93
|
+
s1 ^= s1 << 31; // a
|
94
|
+
s[prng->p] = s1 ^ s0 ^ (s1 >> 11) ^ (s0 >> 30); // b,c
|
95
|
+
return s[prng->p] * UINT64_C(1181783497276652981);
|
96
|
+
}
|
97
|
+
|
98
|
+
static inline uint32_t
|
99
|
+
evoasm_prng32_rand(struct evoasm_prng32 *prng) {
|
100
|
+
uint32_t *s = prng->s.data;
|
101
|
+
uint32_t t = s[0];
|
102
|
+
t ^= t << 11;
|
103
|
+
t ^= t >> 8;
|
104
|
+
s[0] = s[1]; s[1] = s[2]; s[2] = s[3];
|
105
|
+
s[3] ^= s[3] >> 19;
|
106
|
+
s[3] ^= t;
|
107
|
+
return s[3];
|
108
|
+
}
|
109
|
+
|
110
|
+
static inline int64_t
|
111
|
+
evoasm_prng64_rand_between(struct evoasm_prng64 *prng, int64_t min, int64_t max) {
|
112
|
+
return min + (int64_t)(evoasm_prng64_rand(prng) % (uint64_t)(max - min + 1ll));
|
113
|
+
}
|
114
|
+
|
115
|
+
static inline int32_t
|
116
|
+
evoasm_prng32_rand_between(struct evoasm_prng32 *prng, int32_t min, int32_t max) {
|
117
|
+
return min + (int32_t)(evoasm_prng32_rand(prng) % (uint32_t)(max - min + 1ll));
|
118
|
+
}
|
119
|
+
|
120
|
+
static inline int64_t
|
121
|
+
evoasm_domain_rand(evoasm_domain *domain, struct evoasm_prng64 *prng) {
|
122
|
+
switch(domain->type) {
|
123
|
+
case EVOASM_DOMAIN_TYPE_INTERVAL: {
|
124
|
+
evoasm_interval *interval = (evoasm_interval *) domain;
|
125
|
+
return evoasm_prng64_rand_between(prng, interval->min, interval->max);
|
126
|
+
}
|
127
|
+
case EVOASM_DOMAIN_TYPE_INTERVAL64: {
|
128
|
+
return (int64_t) evoasm_prng64_rand(prng);
|
129
|
+
}
|
130
|
+
case EVOASM_DOMAIN_TYPE_ENUM: {
|
131
|
+
evoasm_enum *enm = (evoasm_enum *) domain;
|
132
|
+
return enm->vals[evoasm_prng64_rand(prng) % enm->len];
|
133
|
+
}
|
134
|
+
default:
|
135
|
+
evoasm_assert_not_reached();
|
136
|
+
return 0;
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
static inline size_t
|
141
|
+
evoasm_domain_size(evoasm_domain *domain) {
|
142
|
+
switch(domain->type){
|
143
|
+
case EVOASM_DOMAIN_TYPE_INTERVAL:
|
144
|
+
case EVOASM_DOMAIN_TYPE_INTERVAL64: return sizeof(evoasm_interval);
|
145
|
+
case EVOASM_DOMAIN_TYPE_ENUM: return EVOASM_ENUM_SIZE(((evoasm_enum *) domain)->len);
|
146
|
+
default:
|
147
|
+
evoasm_assert_not_reached();
|
148
|
+
return 0;
|
149
|
+
}
|
150
|
+
}
|
151
|
+
|
152
|
+
static inline void
|
153
|
+
evoasm_domain_clone(evoasm_domain * restrict domain, evoasm_domain * restrict domain_dst) {
|
154
|
+
domain_dst->type = domain->type;
|
155
|
+
|
156
|
+
switch(domain->type) {
|
157
|
+
case EVOASM_DOMAIN_TYPE_INTERVAL:
|
158
|
+
case EVOASM_DOMAIN_TYPE_INTERVAL64: {
|
159
|
+
evoasm_interval *interval = (evoasm_interval *) domain;
|
160
|
+
evoasm_interval *interval_dst = (evoasm_interval *) domain_dst;
|
161
|
+
interval_dst->min = interval->min;
|
162
|
+
interval_dst->max = interval->max;
|
163
|
+
break;
|
164
|
+
}
|
165
|
+
case EVOASM_DOMAIN_TYPE_ENUM: {
|
166
|
+
evoasm_enum *enm = (evoasm_enum *) domain;
|
167
|
+
evoasm_enum *enm_dst = (evoasm_enum *) domain_dst;
|
168
|
+
enm_dst->len = enm->len;
|
169
|
+
memcpy(enm_dst->vals, enm->vals, EVOASM_ENUM_VALS_SIZE(enm->len));
|
170
|
+
break;
|
171
|
+
}
|
172
|
+
default: evoasm_assert_not_reached();
|
173
|
+
}
|
174
|
+
}
|
175
|
+
|
176
|
+
|
177
|
+
static inline void
|
178
|
+
evoasm_domain_intersect(evoasm_domain * restrict domain1, evoasm_domain * restrict domain2, evoasm_domain * restrict domain_dst) {
|
179
|
+
|
180
|
+
#define _EVOASM_DOMAIN_TYPES2(type_a, type_b) (int)(((type_a) << 8) | (type_b))
|
181
|
+
|
182
|
+
switch(_EVOASM_DOMAIN_TYPES2(domain1->type, domain2->type)) {
|
183
|
+
case _EVOASM_DOMAIN_TYPES2(EVOASM_DOMAIN_TYPE_INTERVAL, EVOASM_DOMAIN_TYPE_INTERVAL64):
|
184
|
+
case _EVOASM_DOMAIN_TYPES2(EVOASM_DOMAIN_TYPE_INTERVAL, EVOASM_DOMAIN_TYPE_INTERVAL):
|
185
|
+
case _EVOASM_DOMAIN_TYPES2(EVOASM_DOMAIN_TYPE_INTERVAL64, EVOASM_DOMAIN_TYPE_INTERVAL64):
|
186
|
+
case _EVOASM_DOMAIN_TYPES2(EVOASM_DOMAIN_TYPE_INTERVAL64, EVOASM_DOMAIN_TYPE_INTERVAL): {
|
187
|
+
evoasm_interval *interval1 = (evoasm_interval *) domain1;
|
188
|
+
evoasm_interval *interval2 = (evoasm_interval *) domain2;
|
189
|
+
evoasm_interval *interval_dst = (evoasm_interval *) domain_dst;
|
190
|
+
|
191
|
+
interval_dst->min = EVOASM_MAX(interval1->min, interval2->min);
|
192
|
+
interval_dst->max = EVOASM_MIN(interval1->max, interval2->max);
|
193
|
+
break;
|
194
|
+
}
|
195
|
+
case _EVOASM_DOMAIN_TYPES2(EVOASM_DOMAIN_TYPE_ENUM, EVOASM_DOMAIN_TYPE_ENUM): {
|
196
|
+
unsigned i = 0, j = 0;
|
197
|
+
evoasm_enum *enum1 = (evoasm_enum *) domain1;
|
198
|
+
evoasm_enum *enum2 = (evoasm_enum *) domain2;
|
199
|
+
evoasm_enum *enum_dst = (evoasm_enum *) domain_dst;
|
200
|
+
|
201
|
+
enum_dst->len = 0;
|
202
|
+
/*
|
203
|
+
* NOTE: vals are sorted (INC)
|
204
|
+
*/
|
205
|
+
|
206
|
+
while(i < enum1->len && j < enum2->len) {
|
207
|
+
int64_t v1 = enum1->vals[i];
|
208
|
+
int64_t v2 = enum2->vals[j];
|
209
|
+
|
210
|
+
if(v1 < v2) {
|
211
|
+
i++;
|
212
|
+
}
|
213
|
+
else if(v2 < v1) {
|
214
|
+
j++;
|
215
|
+
}
|
216
|
+
else {
|
217
|
+
enum_dst->vals[enum_dst->len++] = v1;
|
218
|
+
i++;
|
219
|
+
j++;
|
220
|
+
}
|
221
|
+
}
|
222
|
+
break;
|
223
|
+
}
|
224
|
+
{
|
225
|
+
evoasm_enum *enm;
|
226
|
+
evoasm_interval *interval;
|
227
|
+
unsigned i;
|
228
|
+
|
229
|
+
case _EVOASM_DOMAIN_TYPES2(EVOASM_DOMAIN_TYPE_ENUM, EVOASM_DOMAIN_TYPE_INTERVAL):
|
230
|
+
case _EVOASM_DOMAIN_TYPES2(EVOASM_DOMAIN_TYPE_ENUM, EVOASM_DOMAIN_TYPE_INTERVAL64):
|
231
|
+
enm = (evoasm_enum *) domain1;
|
232
|
+
interval = (evoasm_interval *) domain2;
|
233
|
+
goto intersect;
|
234
|
+
case _EVOASM_DOMAIN_TYPES2(EVOASM_DOMAIN_TYPE_INTERVAL, EVOASM_DOMAIN_TYPE_ENUM):
|
235
|
+
case _EVOASM_DOMAIN_TYPES2(EVOASM_DOMAIN_TYPE_INTERVAL64, EVOASM_DOMAIN_TYPE_ENUM):
|
236
|
+
enm = (evoasm_enum *) domain2;
|
237
|
+
interval = (evoasm_interval *) domain1;
|
238
|
+
intersect: {
|
239
|
+
evoasm_enum *enum_dst = (evoasm_enum *) domain_dst;
|
240
|
+
enum_dst->len = 0;
|
241
|
+
for(i = 0; i < enm->len; i++) {
|
242
|
+
if(enm->vals[i] >= interval->min && enm->vals[i] <= interval->max) {
|
243
|
+
enum_dst->vals[enum_dst->len++] = enm->vals[i];
|
244
|
+
}
|
245
|
+
}
|
246
|
+
}
|
247
|
+
break;
|
248
|
+
}
|
249
|
+
default:
|
250
|
+
evoasm_assert_not_reached();
|
251
|
+
}
|
252
|
+
|
253
|
+
#undef _EVOASM_DOMAIN_TYPES2
|
254
|
+
}
|
255
|
+
|
256
|
+
static inline bool
|
257
|
+
evoasm_domain_contains_p(evoasm_domain *domain, int64_t val) {
|
258
|
+
switch(domain->type) {
|
259
|
+
case EVOASM_DOMAIN_TYPE_INTERVAL: {
|
260
|
+
evoasm_interval *interval = (evoasm_interval *) domain;
|
261
|
+
return val >= interval->min && val <= interval->max;
|
262
|
+
}
|
263
|
+
case EVOASM_DOMAIN_TYPE_ENUM: {
|
264
|
+
unsigned i;
|
265
|
+
evoasm_enum *enm = (evoasm_enum *) domain;
|
266
|
+
for(i = 0; i < enm->len; i++) {
|
267
|
+
if(enm->vals[i] == val) return true;
|
268
|
+
}
|
269
|
+
return false;
|
270
|
+
}
|
271
|
+
default:
|
272
|
+
evoasm_assert_not_reached();
|
273
|
+
return false;
|
274
|
+
}
|
275
|
+
}
|
276
|
+
|
277
|
+
static inline int64_t
|
278
|
+
evoasm_log2(int64_t num) {
|
279
|
+
uint64_t log = 0;
|
280
|
+
while (num >>= 1) ++log;
|
281
|
+
return (int64_t)log;
|
282
|
+
}
|