Files
mercury/runtime/mercury_int.h
Mark Brown d465fa53cb Update the COPYING.LIB file and references to it.
Discussion of these changes can be found on the Mercury developers
mailing list archives from June 2018.

COPYING.LIB:
    Add a special linking exception to the LGPL.

*:
    Update references to COPYING.LIB.

    Clean up some minor errors that have accumulated in copyright
    messages.
2018-06-09 17:43:12 +10:00

260 lines
11 KiB
C

// vim: ts=4 sw=4 expandtab ft=c
// Copyright (C) 2017-2018 The Mercury team.
// This file is distributed under the terms specified in COPYING.LIB.
// mercury_int.h - integer type handling
#ifndef MERCURY_INT_H
#define MERCURY_INT_H
#include "mercury_conf.h" // for MR_BOXED_INT64S, MR_CONSERVATIVE_GC
#include "mercury_types.h" // for `MR_Word'
#include "mercury_std.h" // for `MR_bool'
#include <stdint.h>
#define MR_INT64_WORDS ((sizeof(int64_t) + sizeof(MR_Word) - 1) \
/ sizeof(MR_Word))
#define MR_UINT64_WORDS ((sizeof(uint64_t) + sizeof(MR_Word) - 1) \
/ sizeof(MR_Word))
// See the comment on the definitions of MR_Float_Aligned in mercury_float.h.
//
// Any changes here will probably also need to be made for floats
// in mercury_float.h.
#if defined(MR_GNUC) || defined(MR_CLANG)
typedef int64_t MR_Int64Aligned __attribute__((aligned(sizeof(MR_Word))));
typedef uint64_t MR_Uint64Aligned __attribute__((aligned(sizeof(MR_Word))));
#elif defined(MR_MSVC)
typedef __declspec(align(MR_BYTES_PER_WORD)) int64_t MR_Int64Aligned;
typedef __declspec(align(MR_BYTES_PER_WORD)) uint64_t MR_Uint64Aligned;
#else
typedef int64_t MR_Int64Aligned;
typedef uint64_t MR_Uint64Aligned;
#endif
#if defined(MR_BOXED_INT64S)
#define MR_word_to_int64(w) (* (int64_t *) (w))
#define MR_word_to_uint64(w) (* (uint64_t *) (w))
#if defined(MR_CONSERVATIVE_GC)
#define MR_make_hp_int64_aligned() ((void) 0)
#define MR_make_hp_uint64_aligned() ((void) 0)
#define MR_int64_to_word(i) \
( \
MR_hp_alloc_atomic_msg(MR_INT64_WORDS, MR_ALLOC_SITE_INT64, NULL), \
* (int64_t *) (void *) (MR_hp - MR_INT64_WORDS) = (i), \
/* return */ (MR_Word) (MR_hp - MR_INT64_WORDS) \
)
#define MR_uint64_to_word(u) \
( \
MR_hp_alloc_atomic_msg(MR_UINT64_WORDS, MR_ALLOC_SITE_UINT64, NULL), \
* (uint64_t *) (void *) (MR_hp - MR_UINT64_WORDS) = (u), \
/* return */ (MR_Word) (MR_hp - MR_UINT64_WORDS) \
)
#else // ! defined(MR_CONSERVATIVE_GC)
// We need to ensure that what we allocated on the heap is properly
// aligned for a 64-bit integer value, by rounding MR_hp up to the
// nearest int64-aligned boundary.
#define MR_make_hp_int64_aligned() \
( ((MR_Word) MR_hp & (sizeof(int64_t) - 1)) ? \
MR_hp_alloc_atomic_msg(1, MR_ALLOC_SITE_INT64, NULL) \
: \
(void) 0 \
)
#define MR_make_hp_uint64_aligned() \
( ((MR_Word) MR_hp & (sizeof(uint64_t) - 1)) ? \
MR_hp_alloc_atomic_msg(1, MR_ALLOC_SITE_UINT64, NULL) \
: \
(void) 0 \
)
#define MR_int64_to_word(i) \
( \
MR_make_hp_int64_aligned(), \
MR_hp_alloc_atomic_msg(MR_INT64_WORDS, MR_ALLOC_SITE_INT64, NULL), \
* (int64_t *) (void *) (MR_hp - MR_INT64_WORDS) = (i), \
/* return */ (MR_Word) (MR_hp - MR_INT64_WORDS) \
)
#define MR_uint64_to_word(u) \
( \
MR_make_hp_uint64_aligned(), \
MR_hp_alloc_atomic_msg(MR_UINT64_WORDS, MR_ALLOC_SITE_UINT64, NULL), \
* (uint64_t *) (void *) (MR_hp - MR_UINT64_WORDS) = (u), \
/* return */ (MR_Word) (MR_hp - MR_UINT64_WORDS) \
)
#endif // MR_CONSERVATIVE_GC
#ifdef MR_GNUC
#define MR_int64_const(i) ({ static const int64_t d = i; (MR_Word) &d; })
#define MR_uint64_const(u) ({ static const uint64_t d = u; (MR_Word) &d; })
#else
#define MR_int64_const(i) MR_int64_to_word(i) // inefficient
#define MR_uint64_const(u) MR_uint64_to_word(u) // inefficient
#endif
union MR_Int64Dword {
int64_t i64;
MR_Word i64w[2];
};
union MR_Uint64Dword {
uint64_t ui64;
MR_Word ui64w[2];
};
#if defined(MR_GNUC) || defined(MR_CLANG)
#define MR_dword_int64_get_word0(i64) \
(((union MR_Int64Dword) (int64_t) (i64)).i64w[0])
#define MR_dword_int64_get_word1(i64) \
(((union MR_Int64Dword) (int64_t) (i64)).i64w[1])
#define MR_dword_uint64_get_word0(ui64) \
(((union MR_Uint64Dword) (uint64_t) (ui64)).ui64w[0])
#define MR_dword_uint64_get_word1(ui64) \
(((union MR_Uint64Dword) (uint64_t) (ui64)).ui64w[1])
#else // ! (defined(MR_GNUC) || defined(MR_CLANG))
MR_EXTERN_INLINE MR_Word MR_dword_int64_get_word0(int64_t i64);
MR_EXTERN_INLINE MR_Word MR_dword_int64_get_word1(int64_t i64);
MR_EXTERN_INLINE MR_Word MR_dword_uint64_get_word0(uint64_t ui64);
MR_EXTERN_INLINE MR_Word MR_dword_uint64_get_word1(uint64_t ui64);
MR_EXTERN_INLINE MR_Word
MR_dword_int64_get_word0(int64_t i64)
{
union MR_Int64Dword __i64dw;
__i64dw.i64 = i64;
return __i64dw.i64w[0];
}
MR_EXTERN_INLINE MR_Word
MR_dword_int64_get_word1(int64_t i64)
{
union MR_Int64Dword __i64dw;
__i64dw.i64 = i64;
return __i64dw.i64w[1];
}
MR_EXTERN_INLINE MR_Word
MR_dword_uint64_get_word0(uint64_t ui64)
{
union MR_Uint64Dword __ui64dw;
__ui64dw.ui64 = ui64;
return __ui64dw.ui64w[0];
}
MR_EXTERN_INLINE MR_Word
MR_dword_uint64_get_word1(uint64_t ui64)
{
union MR_Uint64Dword __ui64dw;
__ui64dw.ui64 = ui64;
return __ui64dw.ui64w[1];
}
#endif // defined(MR_GNUC) || defined(MR_CLANG)
#define MR_int64_from_dword_ptr(ptr) \
(((union MR_Int64Dword *) (ptr))->i64)
#define MR_uint64_from_dword_ptr(ptr) \
(((union MR_Uint64Dword *) (ptr))->ui64)
#if defined(MR_GNUC) || defined(MR_CLANG)
#define MR_int64_from_dword(w0, w1) \
({ \
union MR_Int64Dword __i64dw; \
__i64dw.i64w[0] = (MR_Word) (w0); \
__i64dw.i64w[1] = (MR_Word) (w1); \
__i64dw.i64; \
})
#define MR_uint64_from_dword(w0, w1) \
({ \
union MR_Uint64Dword __ui64dw; \
__ui64dw.ui64w[0] = (MR_Word) (w0); \
__ui64dw.ui64w[1] = (MR_Word) (w1); \
__ui64dw.ui64; \
})
#else // ! (defined(MR_GNUC) || defined(MR_CLANG))
#define MR_int64_from_dword(w0, w1) \
MR_int64_from_dword_func((MR_Word) (w0), (MR_Word) (w1))
#define MR_uint64_from_dword(w0, w1) \
MR_uint64_from_dword_func((MR_Word) (w0), (MR_Word) (w1))
MR_EXTERN_INLINE int64_t
MR_int64_from_dword_func(MR_Word w0, MR_Word w1);
MR_EXTERN_INLINE uint64_t
MR_uint64_from_dword_func(MR_Word w0, MR_Word w1);
MR_EXTERN_INLINE int64_t
MR_int64_from_dword_func(MR_Word w0, MR_Word w1)
{
union MR_Int64Dword __i64dw;
__i64dw.i64w[0] = (MR_Word) (w0);
__i64dw.i64w[1] = (MR_Word) (w1);
return __i64dw.i64;
}
MR_EXTERN_INLINE uint64_t
MR_uint64_from_dword_func(MR_Word w0, MR_Word w1)
{
union MR_Uint64Dword __ui64dw;
__ui64dw.ui64w[0] = (MR_Word) (w0);
__ui64dw.ui64w[1] = (MR_Word) (w1);
return __ui64dw.ui64;
}
#endif // defined(MR_GNUC) || defined(MR_CLANG)
#else // ! MR_BOXED_INT64S
// Unboxed int64s means we can assume sizeof(int64_t) <= sizeof(MR_Word)
// and sizeof(uint64_t) <= sizeof(MR_Word).
#define MR_make_hp_int64_aligned() ((void) 0)
#define MR_make_hp_uint64_aligned() ((void) 0)
#define MR_int64_to_word(i) ((MR_Word) (i))
#define MR_uint64_to_word(u) ((MR_Word) (u))
#define MR_word_to_int64(w) ((int64_t) (w))
#define MR_word_to_uint64(w) ((uint64_t) (w))
#endif // not MR_BOXED_INT64S
extern MR_Integer MR_hash_int64(int64_t);
extern MR_Integer MR_hash_uint64(uint64_t);
#if defined(MR_HAVE_BUILTIN_BSWAP16)
#define MR_uint16_reverse_bytes(U) __builtin_bswap16((U))
#elif defined(MR_MSVC)
#define MR_uint16_reverse_bytes(U) _byteswap_ushort((U))
#else
#define MR_uint16_reverse_bytes(U) (((U & 0xff00) >> 8) | \
((U & 0x00ff) << 8))
#endif
#if defined(MR_HAVE_BUILTIN_BSWAP32)
#define MR_uint32_reverse_bytes(U) __builtin_bswap32((U))
#elif defined(MR_MSVC)
#define MR_uint32_reverse_bytes(U) _byteswap_ulong((U))
#else
#define MR_uint32_reverse_bytes(U) ((U & UINT32_C(0x000000ff)) << 24 | \
(U & UINT32_C(0x0000ff00)) << 8 | \
(U & UINT32_C(0x00ff0000)) >> 8 | \
(U & UINT32_C(0xff000000)) >> 24 )
#endif
#if defined(MR_HAVE_BUILTIN_BSWAP64)
#define MR_uint64_reverse_bytes(U) __builtin_bswap64((U))
#elif defined(MR_MSVC)
#define MR_uint64_reverse_bytes(U) _byteswap_uint64((U))
#else
#define MR_uint64_reverse_bytes(U) \
((U & UINT64_C(0x00000000000000ff)) << 56 | \
(U & UINT64_C(0x000000000000ff00)) << 40 | \
(U & UINT64_C(0x0000000000ff0000)) << 24 | \
(U & UINT64_C(0x00000000ff000000)) << 8 | \
(U & UINT64_C(0x000000ff00000000)) >> 8 | \
(U & UINT64_C(0x0000ff0000000000)) >> 24 | \
(U & UINT64_C(0x00ff000000000000)) >> 40 | \
(U & UINT64_C(0xff00000000000000)) >> 56)
#endif
#endif // not MERCURY_INT_H