File: sail.h

package info (click to toggle)
sail-ocaml 0.19.1%2Bdfsg5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 18,008 kB
  • sloc: ml: 75,941; ansic: 8,848; python: 1,342; exp: 560; sh: 474; makefile: 218; cpp: 36
file content (394 lines) | stat: -rw-r--r-- 12,582 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
#ifndef __SAIL_LIB__
#define __SAIL_LIB__

/*
 * Only use libraries here that work with -ffreestanding and -nostdlib
 */
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>

#ifdef SAIL_X86INTRIN
#include <x64intrin.h>
#endif

static inline uint64_t sail_bzhi_u64(uint64_t op1, uint64_t op2)
{
#ifdef SAIL_X64INTRIN
     return _bzhi_u64(op1, op2);
#else
     return (op1 << (64 - op2)) >> (64 - op2);
#endif
}

/*
 * The Sail compiler expects functions to follow a specific naming
 * convention for allocation, deallocation, and (deep)-copying. These
 * macros implement this naming convention.
 */
#define CREATE(type) create_ ## type
#define RECREATE(type) recreate_ ## type
#define CREATE_OF(type1, type2) create_ ## type1 ## _of_ ## type2
#define RECREATE_OF(type1, type2) recreate_ ## type1 ## _of_ ## type2
#define CONVERT_OF(type1, type2) convert_ ## type1 ## _of_ ## type2
#define COPY(type) copy_ ## type
#define KILL(type) kill_ ## type
#define UNDEFINED(type) undefined_ ## type
#define EQUAL(type) eq_ ## type

/*
 * This is only needed for types that are not just simple C types that
 * live on the stack, and need some kind of setup and teardown
 * routines, as Sail won't use these otherwise.
 */
#define SAIL_BUILTIN_TYPE(type)\
  void create_ ## type(type *);\
  void recreate_ ## type(type *);\
  void copy_ ## type(type *, const type);\
  void kill_ ## type(type *);

/* ********************************************************************** */
/* Sail unit type                                                         */
/* ********************************************************************** */

typedef int unit;

#define UNIT 0

static inline unit UNDEFINED(unit)(const unit u)
{
     return UNIT;
}

static inline bool EQUAL(unit)(const unit u1, const unit u2)
{
     return true;
}

/* ********************************************************************** */
/* Sail booleans                                                          */
/* ********************************************************************** */

/*
 * and_bool and or_bool are special-cased by the compiler to ensure
 * proper short-circuiting evaluation.
 */

#ifndef __cplusplus
static inline bool not(bool b)
{
     return !b;
}
#endif

static inline bool EQUAL(bool)(const bool a, const bool b)
{
     return a == b;
}

static inline bool UNDEFINED(bool)(const unit u)
{
     return false;
}

/* ********************************************************************** */
/* Sail strings                                                           */
/* ********************************************************************** */

/*
 * Sail strings are just C strings.
 */
typedef char *sail_string;
typedef const char *const_sail_string;

SAIL_BUILTIN_TYPE(sail_string)

void undefined_string(sail_string *str, const unit u);

bool eq_string(const_sail_string, const_sail_string);
bool EQUAL(sail_string)(const_sail_string, const_sail_string);

void concat_str(sail_string *stro, const_sail_string str1, const_sail_string str2);
bool string_startswith(const_sail_string s, const_sail_string prefix);

/* ********************************************************************** */
/* Sail integers                                                          */
/* ********************************************************************** */

/* First, we define a type for machine-precision integers, int64_t */

typedef int64_t mach_int;
#define MACH_INT_MAX INT64_MAX
#define MACH_INT_MIN INT64_MIN

static inline bool EQUAL(mach_int)(const mach_int a, const mach_int b)
{
     return a == b;
}

/*
 * For arbitrary precision types, we define a type sail_int. Currently
 * sail_int can either be using GMP arbitrary-precision integers
 * (default) or using __int128 or int64_t which is potentially unsound
 * but MUCH faster. the SAIL_INT_FUNCTION macro allows defining
 * function prototypes that work for either case.
 */
#if defined(SAIL_INT64) || defined(SAIL_INT128)

#ifdef SAIL_INT64
typedef int64_t sail_int;
#define SAIL_INT_MAX INT64_MAX
#define SAIL_INT_MIN INT64_MIN
#else
typedef __int128 sail_int;
#define SAIL_INT_MAX (((__int128) 0x7FFFFFFFFFFFFFFF << 64) | (__int128) 0xFFFFFFFFFFFFFFFF)
#define SAIL_INT_MIN (~SAIL_INT_MAX)
#endif
#define SAIL_INT_FUNCTION(fname, ...) sail_int fname(__VA_ARGS__)

static inline uint64_t sail_int_get_ui(const sail_int op)
{
     return (uint64_t) op;
}

#else

typedef mpz_t sail_int;
#define SAIL_INT_FUNCTION(fname, ...) void fname(sail_int*, __VA_ARGS__)

static inline uint64_t sail_int_get_ui(const sail_int op)
{
     return (uint64_t) mpz_get_ui(op);
}

#endif

SAIL_INT_FUNCTION(CREATE_OF(sail_int, mach_int), const mach_int);
SAIL_INT_FUNCTION(CREATE_OF(sail_int, sail_string), const_sail_string);
mach_int CREATE_OF(mach_int, sail_int)(const sail_int);

SAIL_INT_FUNCTION(CONVERT_OF(sail_int, mach_int), const mach_int);
SAIL_INT_FUNCTION(CONVERT_OF(sail_int, sail_string), const_sail_string);
mach_int CONVERT_OF(mach_int, sail_int)(const sail_int);

/*
 * Comparison operators for integers
 */
bool eq_int(const sail_int, const sail_int);
bool EQUAL(sail_int)(const sail_int, const sail_int);

bool lt(const sail_int, const sail_int);
bool gt(const sail_int, const sail_int);
bool lteq(const sail_int, const sail_int);
bool gteq(const sail_int, const sail_int);

/*
 * Left and right shift for integers
 */
mach_int shl_mach_int(const mach_int, const mach_int);
mach_int shr_mach_int(const mach_int, const mach_int);
SAIL_INT_FUNCTION(shl_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(shr_int, const sail_int, const sail_int);

/*
 * undefined_int and undefined_range can't use the UNDEFINED(TYPE)
 * macro, because they're slightly magical. They take extra parameters
 * to ensure that no undefined integer can violate any type-guaranteed
 * constraints.
 */
SAIL_INT_FUNCTION(undefined_int, const int);
SAIL_INT_FUNCTION(undefined_range, const sail_int, const sail_int);

/*
 * Arithmetic operations in integers. We include functions for both
 * truncating towards zero, and rounding towards -infinity (floor) as
 * fdiv/fmod and tdiv/tmod respectively. Plus euclidian division
 * ediv/emod.
 */
SAIL_INT_FUNCTION(add_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(sub_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(sub_nat, const sail_int, const sail_int);
SAIL_INT_FUNCTION(mult_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(ediv_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(emod_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(tdiv_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(tmod_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(fdiv_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(fmod_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(max_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(min_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(neg_int, const sail_int);
SAIL_INT_FUNCTION(abs_int, const sail_int);
SAIL_INT_FUNCTION(pow_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(pow2, const sail_int);

/* ********************************************************************** */
/* Sail bitvectors                                                        */
/* ********************************************************************** */

/*
 * Sail bitvectors are divided into three types:
 * - (f)ixed, statically known bitvectors fbits
 * - (s)mall bitvectors of an unknown width, but guaranteed to be less than 64-bits, sbits
 * - Arbitrarily (l)arge bitvectors of an unknown width, lbits
 *
 * These types form a total order where each can be losslessly
 * converted upwards into the other.
 */

typedef uint64_t fbits;

static inline bool EQUAL(fbits)(const fbits op1, const fbits op2)
{
  return op1 == op2;
}

static inline fbits safe_rshift(const fbits x, const fbits n)
{
     if (n >= 64) {
          return 0;
     } else {
          return x >> n;
     }
}

/*
 * For backwards compatibility with older Sail C libraries
 */
typedef uint64_t mach_bits;

typedef struct {
     uint64_t len;
     uint64_t bits;
} sbits;

static inline sbits CONVERT_OF(sbits, fbits)(const fbits op, const uint64_t len, const bool order)
{
     sbits rop;
     rop.len = len;
     rop.bits = op;
     return rop;
}

static inline fbits CONVERT_OF(fbits, sbits)(const sbits op, const bool order)
{
     return op.bits;
}

/*
 * If the SAIL_BITS64 symbol is defined, we will use sbits as the
 * lbits type.
 */

#ifdef SAIL_BITS64

typedef sbits lbits;
#define SAIL_BITS_FUNCTION(fname, ...) lbits fname(__VA_ARGS__)

static inline lbits CREATE_OF(lbits, fbits)(const fbits op, const uint64_t len, const bool order)
{
     lbits rop;
     rop.bits = op;
     rop.len = len;
     return rop;
}

static inline lbits CREATE_OF(lbits, sbits)(const sbits op, const bool order)
{
     return op;
}

#else

typedef struct {
  mp_bitcnt_t len;
  mpz_t *bits;
} lbits;
#define SAIL_BITS_FUNCTION(fname, ...) void fname(lbits*, __VA_ARGS__)
SAIL_BUILTIN_TYPE(lbits)

SAIL_BITS_FUNCTION(CREATE_OF(lbits, fbits), const fbits, const uint64_t, const bool);
SAIL_BITS_FUNCTION(CREATE_OF(lbits, sbits), const fbits, const bool);
SAIL_BITS_FUNCTION(RECREATE_OF(lbits, fbits), const fbits, const uint64_t, const bool);
SAIL_BITS_FUNCTION(RECREATE_OF(lbits, sbits), const fbits, const bool);

#endif

SAIL_BITS_FUNCTION(CONVERT_OF(lbits, fbits), const fbits, const uint64_t, const bool);
fbits CONVERT_OF(fbits, lbits)(const lbits, const bool);
SAIL_BITS_FUNCTION(CONVERT_OF(lbits, sbits), const sbits, const bool);
sbits CONVERT_OF(sbits, lbits)(const lbits, const bool);

SAIL_BITS_FUNCTION(UNDEFINED(lbits), const sail_int);

bool eq_bits(const lbits, const lbits);
bool EQUAL(lbits)(const lbits, const lbits);
bool neq_bits(const lbits, const lbits);

SAIL_BITS_FUNCTION(not_bits, const lbits);
SAIL_BITS_FUNCTION(and_bits, const lbits, const lbits);
SAIL_BITS_FUNCTION(or_bits, const lbits, const lbits);
SAIL_BITS_FUNCTION(xor_bits, const lbits, const lbits);

SAIL_BITS_FUNCTION(add_bits, const lbits, const lbits);
SAIL_BITS_FUNCTION(sub_bits, const lbits, const lbits);
SAIL_BITS_FUNCTION(add_bits_int, const lbits, const sail_int);
SAIL_BITS_FUNCTION(sub_bits_int, const lbits, const sail_int);

SAIL_INT_FUNCTION(sail_signed, const lbits op);
SAIL_INT_FUNCTION(sail_unsigned, const lbits op);

fbits bitvector_access(const lbits bv, const sail_int n);
SAIL_BITS_FUNCTION(slice, const lbits, const sail_int, const sail_int);
SAIL_BITS_FUNCTION(set_slice, const sail_int len, const sail_int slen, const lbits op, const sail_int start, const lbits slice);
SAIL_BITS_FUNCTION(append, const lbits, const lbits);
SAIL_INT_FUNCTION(length_lbits, const lbits);
SAIL_BITS_FUNCTION(zeros, const sail_int);
SAIL_BITS_FUNCTION(replicate_bits, const lbits op, const sail_int n);
SAIL_BITS_FUNCTION(get_slice_int, const sail_int len, const sail_int n, const sail_int start);
SAIL_INT_FUNCTION(set_slice_int, const sail_int len, const sail_int n, const sail_int start, const lbits slice);
SAIL_BITS_FUNCTION(vector_subrange_lbits, const lbits op, const sail_int n, const sail_int m);
SAIL_BITS_FUNCTION(vector_update_subrange_lbits, const lbits op, const sail_int n, const sail_int m, const lbits slice);

/* ********************************************************************** */
/* Sail reals                                                             */
/* ********************************************************************** */

#ifdef SAIL_FLOATING_REAL
typedef double real;
#else
typedef mpq_t real;
#endif

SAIL_BUILTIN_TYPE(real)

void CREATE_OF(real, sail_string)(real *rop, const_sail_string op);
void CONVERT_OF(real, sail_string)(real *rop, const_sail_string op);

void UNDEFINED(real)(real *rop, unit u);

void neg_real(real *rop, const real op);

void mult_real(real *rop, const real op1, const real op2);
void sub_real(real *rop, const real op1, const real op2);
void add_real(real *rop, const real op1, const real op2);
void div_real(real *rop, const real op1, const real op2);

void sqrt_real(real *rop, const real op);
void abs_real(real *rop, const real op);

SAIL_INT_FUNCTION(round_up, const real op);
SAIL_INT_FUNCTION(round_down, const real op);

void to_real(real *rop, const sail_int op);

bool EQUAL(real)(const real op1, const real op2);

bool lt_real(const real op1, const real op2);
bool gt_real(const real op1, const real op2);
bool lteq_real(const real op1, const real op2);
bool gteq_real(const real op1, const real op2);

void real_power(real *rop, const real base, const sail_int exp);

#endif