100 lines
2.5 KiB
C
100 lines
2.5 KiB
C
#ifndef INCLUDED_MEMORY_H
|
|
#define INCLUDED_MEMORY_H
|
|
|
|
#include <float.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
|
|
// 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
|