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
|