#ifndef INCLUDED_MEMORY_H #define INCLUDED_MEMORY_H #include #include #include #include // Geneal macros #ifndef __has_attribute # define __has_attribute(attr) 0 #endif #if __has_attribute(always_inline) # define ALWAYS_INLINE inline __attribute__((always_inline)) #else # define ALWAYS_INLINE inline #endif // Byte order stuff typedef enum { ENDIAN_LITTLE, ENDIAN_BIG, } Endianness; static ALWAYS_INLINE Endianness ENDIANNESS(void) { uint16_t x = 1; return *(char *) &x == 1 ? ENDIAN_LITTLE : ENDIAN_BIG; } static ALWAYS_INLINE bool LITTLE_ENDIAN_P(void) { return ENDIANNESS() == ENDIAN_LITTLE; } // General float stuff #if SIZE_MAX == 0xffffffff # define LISP_WORD_BITS 32 #elif SIZE_MAX == 0xffffffffffffffff # define LISP_WORD_BITS 64 #else # error "Unablem to determine system word size!" #endif // Check if we support this system's floating point implementation #if FLT_RADIX != 2 || FLT_MANT_DIG != 24 || DBL_MANT_DIG != 53 \ || FLT_MAX_EXP != 128 || DBL_MAX_EXP != 1024 # error "Floating point implementation not supported." #endif typedef float lisp_float32_t; typedef double lisp_float64_t; static ALWAYS_INLINE uint32_t FLOAT32_TO_INT_BITS(lisp_float32_t flt) { union { uint32_t int_val; lisp_float32_t flt_val; } conv = {.flt_val = flt}; return conv.int_val; } static ALWAYS_INLINE uint64_t FLOAT64_TO_INT_BITS(lisp_float64_t flt) { union { uint64_t int_val; lisp_float64_t flt_val; } conv = {.flt_val = flt}; return conv.int_val; } #define FLOAT_TO_INT_BITS(flt) \ _Generic((flt), \ lisp_float32_t: FLOAT32_TO_INT_BITS(flt), \ lisp_float64_t: FLOAT64_TO_INT_BITS(flt)) static ALWAYS_INLINE lisp_float32_t INT_TO_FLOAT32_BITS(uint32_t i) { union { uint32_t int_val; lisp_float32_t flt_val; } conv = {.int_val = i}; return conv.flt_val; } static ALWAYS_INLINE lisp_float64_t INT_TO_FLOAT64_BITS(uint64_t i) { union { uint64_t int_val; lisp_float64_t flt_val; } conv = {.int_val = i}; return conv.flt_val; } #define INT_TO_FLOAT_BITS(i) \ _Generic((i), \ uint32_t: INT_TO_FLOAT32_BITS(i), \ uint64_t: INT_TO_FLOAT64_BITS(i)) // Allocator void *lisp_realloc(void *oldptr, size_t size); void *lisp_malloc(size_t size); void *lisp_malloc0(size_t size); void *lisp_aligned_alloc(size_t alignment, size_t size); #endif