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.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.gemrelease +2 -0
  3. data/.gitignore +16 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.rake +8 -0
  6. data/Gemfile.rake.lock +51 -0
  7. data/LICENSE.txt +373 -0
  8. data/Makefile +6 -0
  9. data/README.md +43 -0
  10. data/Rakefile +128 -0
  11. data/bin/gdb +2 -0
  12. data/data/tables/README.md +19 -0
  13. data/data/tables/x64.csv +1684 -0
  14. data/data/templates/evoasm-x64.c.erb +319 -0
  15. data/data/templates/evoasm-x64.h.erb +126 -0
  16. data/evoasm.gemspec +30 -0
  17. data/examples/abs.yml +20 -0
  18. data/examples/popcnt.yml +17 -0
  19. data/examples/sym_reg.yml +26 -0
  20. data/exe/evoasm-search +13 -0
  21. data/ext/evoasm_ext/evoasm-alloc.c +145 -0
  22. data/ext/evoasm_ext/evoasm-alloc.h +59 -0
  23. data/ext/evoasm_ext/evoasm-arch.c +44 -0
  24. data/ext/evoasm_ext/evoasm-arch.h +161 -0
  25. data/ext/evoasm_ext/evoasm-bitmap.h +114 -0
  26. data/ext/evoasm_ext/evoasm-buf.c +130 -0
  27. data/ext/evoasm_ext/evoasm-buf.h +47 -0
  28. data/ext/evoasm_ext/evoasm-error.c +31 -0
  29. data/ext/evoasm_ext/evoasm-error.h +75 -0
  30. data/ext/evoasm_ext/evoasm-free-list.c.tmpl +121 -0
  31. data/ext/evoasm_ext/evoasm-free-list.h.tmpl +86 -0
  32. data/ext/evoasm_ext/evoasm-log.c +108 -0
  33. data/ext/evoasm_ext/evoasm-log.h +69 -0
  34. data/ext/evoasm_ext/evoasm-misc.c +23 -0
  35. data/ext/evoasm_ext/evoasm-misc.h +282 -0
  36. data/ext/evoasm_ext/evoasm-param.h +37 -0
  37. data/ext/evoasm_ext/evoasm-search.c +2145 -0
  38. data/ext/evoasm_ext/evoasm-search.h +214 -0
  39. data/ext/evoasm_ext/evoasm-util.h +40 -0
  40. data/ext/evoasm_ext/evoasm-x64.c +275624 -0
  41. data/ext/evoasm_ext/evoasm-x64.h +5436 -0
  42. data/ext/evoasm_ext/evoasm.c +7 -0
  43. data/ext/evoasm_ext/evoasm.h +23 -0
  44. data/ext/evoasm_ext/evoasm_ext.c +1757 -0
  45. data/ext/evoasm_ext/extconf.rb +31 -0
  46. data/lib/evoasm/cli/search.rb +127 -0
  47. data/lib/evoasm/cli.rb +6 -0
  48. data/lib/evoasm/core_ext/array.rb +9 -0
  49. data/lib/evoasm/core_ext/integer.rb +10 -0
  50. data/lib/evoasm/core_ext/kwstruct.rb +13 -0
  51. data/lib/evoasm/core_ext/range.rb +5 -0
  52. data/lib/evoasm/core_ext.rb +1 -0
  53. data/lib/evoasm/error.rb +20 -0
  54. data/lib/evoasm/examples.rb +27 -0
  55. data/lib/evoasm/gen/enum.rb +169 -0
  56. data/lib/evoasm/gen/name_util.rb +80 -0
  57. data/lib/evoasm/gen/state.rb +176 -0
  58. data/lib/evoasm/gen/state_dsl.rb +152 -0
  59. data/lib/evoasm/gen/strio.rb +27 -0
  60. data/lib/evoasm/gen/translator.rb +1102 -0
  61. data/lib/evoasm/gen/version.rb +5 -0
  62. data/lib/evoasm/gen/x64/funcs.rb +495 -0
  63. data/lib/evoasm/gen/x64/inst.rb +781 -0
  64. data/lib/evoasm/gen/x64.rb +237 -0
  65. data/lib/evoasm/gen.rb +8 -0
  66. data/lib/evoasm/program.rb +23 -0
  67. data/lib/evoasm/search.rb +40 -0
  68. data/lib/evoasm/tasks/gen_task.rb +86 -0
  69. data/lib/evoasm/tasks/template_task.rb +52 -0
  70. data/lib/evoasm/version.rb +3 -0
  71. data/lib/evoasm.rb +22 -0
  72. data/test/test_helper.rb +1 -0
  73. data/test/x64/test_helper.rb +19 -0
  74. data/test/x64/x64_test.rb +87 -0
  75. 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
+ }