/* -----------------------------------------------------------------------------
 *
 * (c) The GHC Team, 2000
 *
 * A mapping for Haskell types to C types, including the corresponding bounds.
 * Intended to be used in conjuction with the FFI.
 *
 * WARNING: Keep this file and StgTypes.h in synch!
 *
 * ---------------------------------------------------------------------------*/

#ifndef HSFFI_H
#define HSFFI_H

#ifdef __cplusplus
extern "C" {
#endif

/* get types from GHC's runtime system */
#include "ghcconfig.h"
#include "stg/Types.h"

/* get limits for integral types */
#if defined HAVE_STDINT_H && !defined USE_INTTYPES_H_FOR_RTS_PROBES_D
/* ISO C 99 says:
 * "C++ implementations should define these macros only when
 * __STDC_LIMIT_MACROS is defined before <stdint.h> is included."
 */
#define __STDC_LIMIT_MACROS
#include <stdint.h>
#elif defined(HAVE_INTTYPES_H)
#include <inttypes.h>
#else
/* second best guess (e.g. on Solaris) */
#include <limits.h>
#endif

#ifdef INT8_MIN
#define __INT8_MIN              INT8_MIN
#define __INT16_MIN             INT16_MIN
#define __INT32_MIN             INT32_MIN
#define __INT64_MIN             INT64_MIN
#define __INT8_MAX              INT8_MAX
#define __INT16_MAX             INT16_MAX
#define __INT32_MAX             INT32_MAX
#define __INT64_MAX             INT64_MAX
#define __UINT8_MAX             UINT8_MAX
#define __UINT16_MAX            UINT16_MAX
#define __UINT32_MAX            UINT32_MAX
#define __UINT64_MAX            UINT64_MAX
#else
/* if we had no luck, let's do it for ourselves (assuming 64bit long longs) */
#define __INT8_MIN              (-128)
#define __INT16_MIN             (-32767-1)
#define __INT32_MIN             (-2147483647-1)
#define __INT64_MIN             (-9223372036854775807LL-1)
#define __INT8_MAX              (127)
#define __INT16_MAX             (32767)
#define __INT32_MAX             (2147483647)
#define __INT64_MAX             (9223372036854775807LL)
#define __UINT8_MAX             (255U)
#define __UINT16_MAX            (65535U)
#define __UINT32_MAX            (4294967295U)
#define __UINT64_MAX            (18446744073709551615ULL)
#endif

/* get limits for floating point types */
#include <float.h>

typedef StgChar                 HsChar;
typedef StgInt                  HsInt;
typedef StgInt8                 HsInt8;
typedef StgInt16                HsInt16;
typedef StgInt32                HsInt32;
typedef StgInt64                HsInt64;
typedef StgWord                 HsWord;
typedef StgWord8                HsWord8;
typedef StgWord16               HsWord16;
typedef StgWord32               HsWord32;
typedef StgWord64               HsWord64;
typedef StgFloat                HsFloat;
typedef StgDouble               HsDouble;
typedef StgInt                  HsBool;
typedef void*                   HsPtr;          /* this should better match StgAddr */
typedef void                    (*HsFunPtr)(void); /* this should better match StgAddr */
typedef void*                   HsStablePtr;

/* this should correspond to the type of StgChar in StgTypes.h */
#define HS_CHAR_MIN             0
#define HS_CHAR_MAX             0x10FFFF

/* is it true or not?  */
#define HS_BOOL_FALSE           0
#define HS_BOOL_TRUE            1

#define HS_BOOL_MIN             HS_BOOL_FALSE
#define HS_BOOL_MAX             HS_BOOL_TRUE

/* this mirrors the distinction of cases in StgTypes.h */
#if   SIZEOF_VOID_P == 8
#define HS_INT_MIN              __INT64_MIN
#define HS_INT_MAX              __INT64_MAX
#define HS_WORD_MAX             __UINT64_MAX
#elif SIZEOF_VOID_P == 4
#define HS_INT_MIN              __INT32_MIN
#define HS_INT_MAX              __INT32_MAX
#define HS_WORD_MAX             __UINT32_MAX
#else
#error GHC untested on this architecture: sizeof(void *) != 4 or 8
#endif

#define HS_INT8_MIN             __INT8_MIN
#define HS_INT8_MAX             __INT8_MAX
#define HS_INT16_MIN            __INT16_MIN
#define HS_INT16_MAX            __INT16_MAX
#define HS_INT32_MIN            __INT32_MIN
#define HS_INT32_MAX            __INT32_MAX
#define HS_INT64_MIN            __INT64_MIN
#define HS_INT64_MAX            __INT64_MAX
#define HS_WORD8_MAX            __UINT8_MAX
#define HS_WORD16_MAX           __UINT16_MAX
#define HS_WORD32_MAX           __UINT32_MAX
#define HS_WORD64_MAX           __UINT64_MAX

#define HS_FLOAT_RADIX          FLT_RADIX
#define HS_FLOAT_ROUNDS         FLT_ROUNDS
#define HS_FLOAT_EPSILON        FLT_EPSILON
#define HS_FLOAT_DIG            FLT_DIG
#define HS_FLOAT_MANT_DIG       FLT_MANT_DIG
#define HS_FLOAT_MIN            FLT_MIN
#define HS_FLOAT_MIN_EXP        FLT_MIN_EXP
#define HS_FLOAT_MIN_10_EXP     FLT_MIN_10_EXP
#define HS_FLOAT_MAX            FLT_MAX
#define HS_FLOAT_MAX_EXP        FLT_MAX_EXP
#define HS_FLOAT_MAX_10_EXP     FLT_MAX_10_EXP

#define HS_DOUBLE_RADIX         DBL_RADIX
#define HS_DOUBLE_ROUNDS        DBL_ROUNDS
#define HS_DOUBLE_EPSILON       DBL_EPSILON
#define HS_DOUBLE_DIG           DBL_DIG
#define HS_DOUBLE_MANT_DIG      DBL_MANT_DIG
#define HS_DOUBLE_MIN           DBL_MIN
#define HS_DOUBLE_MIN_EXP       DBL_MIN_EXP
#define HS_DOUBLE_MIN_10_EXP    DBL_MIN_10_EXP
#define HS_DOUBLE_MAX           DBL_MAX
#define HS_DOUBLE_MAX_EXP       DBL_MAX_EXP
#define HS_DOUBLE_MAX_10_EXP    DBL_MAX_10_EXP

extern void hs_init     (int *argc, char **argv[]);
extern void hs_exit     (void);
extern void hs_set_argv (int argc, char *argv[]);
extern void hs_add_root (void (*init_root)(void));
extern void hs_thread_done (void);

extern void hs_perform_gc (void);

extern void hs_lock_stable_tables (void);
extern void hs_unlock_stable_tables (void);
extern void hs_free_stable_ptr_unsafe (HsStablePtr sp);

extern void hs_free_stable_ptr (HsStablePtr sp);
extern void hs_free_fun_ptr    (HsFunPtr fp);

extern StgPtr hs_spt_lookup(StgWord64 key[2]);
extern int hs_spt_keys(StgPtr keys[], int szKeys);
extern int hs_spt_key_count (void);

/* -------------------------------------------------------------------------- */

#ifdef __cplusplus
}
#endif

#endif /* HSFFI_H */
