Files
mercury/runtime/mercury_std.h
Julien Fischer d68a860938 Fix a problem with the runtime when using GCC in C99 mode.
Branches: main, 11.07

Fix a problem with the runtime when using GCC in C99 mode.

runtime/mercury_std.h:
	GCC uses the C99 semantics for inline functions when
	it is in C99 mode, we need to too.
2012-01-04 13:56:12 +00:00

331 lines
12 KiB
C

/*
** Copyright (C) 1993-1995, 1997-2005, 2011-2012 The University of Melbourne.
** This file may only be copied under the terms of the GNU Library General
** Public License - see the file COPYING.LIB in the Mercury distribution.
*/
/*
** std.h - "standard" [sic] definitions for C:
** MR_bool, MR_TRUE, MR_FALSE, MR_min(), MR_max(), MR_streq(), etc.
*/
#ifndef MERCURY_STD_H
#define MERCURY_STD_H
/*
** We include mercury_regs.h to ensure we define any global register variables
** before any functions, even if the system libraries we include below it
** define any functions.
*/
#include "mercury_regs.h"
#include <stdlib.h> /* for size_t */
#include <assert.h> /* for assert() */
#include <errno.h> /* for EINTR */
#ifndef IN_GCC
#include <ctype.h> /* for isalnum(), etc. */
#else
/*
** When building compiler/gcc.m, we #include GCC back-end
** header files that include libiberty's "safe-ctype.h",
** and we can't include both safe-ctype.h and ctype.h,
** since they conflict, so include safe-ctype.h
** rather than ctype.h.
*/
#include "safe-ctype.h"
#endif
/*
** The boolean type, MR_bool, with constants MR_TRUE and MR_FALSE.
**
** We use `int' rather than `char' for MR_bool, because GCC has problems
** optimizing tail calls for functions that return types smaller than `int'.
** In most cases, `int' is more efficient anyway.
** The only exception is that in some cases it is more important to optimize
** space rather than time; in those (rare) cases, you can use `MR_small_bool'
** instead of `MR_bool'.
*/
typedef int MR_bool;
typedef char MR_small_bool;
/*
** The values of MR_TRUE and MR_FALSE should correspond with the representation
** of the Mercury standard library type bool.bool, so that they can be used as
** values for bool arguments of exported Mercury procs.
*/
#define MR_TRUE 1
#define MR_FALSE 0
#define MR_YES MR_TRUE
#define MR_NO MR_FALSE
#define MR_max(a, b) ((a) > (b) ? (a) : (b))
#define MR_min(a, b) ((a) < (b) ? (a) : (b))
/*
** The ANSI C isalnum(), etc. macros require that the argument be cast to
** `unsigned char'; if you pass a signed char, the behaviour is undefined.
** Hence we define `MR_' versions of these that do the cast -- you should
** make sure to always use the `MR_' versions rather than the standard ones.
*/
#define MR_isupper(c) isupper((unsigned char) (c))
#define MR_islower(c) islower((unsigned char) (c))
#define MR_isalpha(c) isalpha((unsigned char) (c))
#define MR_isalnum(c) isalnum((unsigned char) (c))
#define MR_isdigit(c) isdigit((unsigned char) (c))
#define MR_isspace(c) isspace((unsigned char) (c))
#define MR_isalnumunder(c) (isalnum((unsigned char) (c)) || (c) == '_')
#define MR_streq(s1, s2) (strcmp(s1, s2) == 0)
#define MR_strdiff(s1, s2) (strcmp(s1, s2) != 0)
#define MR_strtest(s1, s2) (strcmp(s1, s2))
#define MR_strneq(s1, s2, n) (strncmp(s1, s2, n) == 0)
#define MR_strndiff(s1, s2, n) (strncmp(s1, s2, n) != 0)
#define MR_strntest(s1, s2, n) (strncmp(s1, s2, n))
#define MR_ungetchar(c) ungetc(c, stdin)
/*
** For speed, turn assertions off,
** unless low-level debugging is enabled.
*/
#ifdef MR_LOWLEVEL_DEBUG
#define MR_assert(ASSERTION) assert(ASSERTION)
#else
#define MR_assert(ASSERTION) ((void)0)
#endif
/*---------------------------------------------------------------------------*/
#ifdef EINTR
#define MR_is_eintr(x) ((x) == EINTR)
#else
#define MR_is_eintr(x) MR_FALSE
#endif
/*---------------------------------------------------------------------------*/
/*
** Macros for inlining.
**
** Inlining is treated differently by C++, C99, and GNU C.
** We also need to make it work for C89, which doesn't have
** any explicit support for inlining.
**
** To make a function inline, you should declare it as either
** `MR_INLINE', `MR_EXTERN_INLINE', or `MR_STATIC_INLINE'.
** You should not use `extern' or `static' in combination with these macros.
**
** `MR_STATIC_INLINE' should be used for functions that are defined and
** used only in a single translation unit (i.e. a single C source file).
**
** If the inline function is to be used from more than one translation unit,
** then the function definition (not just declaration) should go in
** a header file, and you should use either MR_INLINE or MR_EXTERN_INLINE;
** the difference between these two is explained below.
**
** MR_INLINE creates an inline definition of the function, and
** if needed it also creates an out-of-line definition of the function
** for the current translation unit, in case the function can't be inlined
** (e.g. because the function's address was taken, or because the
** file is compiled with the C compiler's optimizations turned off.)
** For C++, these definitions will be shared between different
** compilation units, but for C, each compilation unit that needs
** an out-of-line definition will gets its own definition.
** Generally that is not much of a problem, but if the C compiler
** doesn't optimize away such out-of-line definitions when they're
** not needed, this can get quite bad.
**
** MR_EXTERN_INLINE creates an inline definition of the function,
** but it does NOT guarantee to create an out-of-line definition,
** even if one might be needed. You need to explicitly provide
** an out-of-line definition for the function in one of the C files.
** This should be done using the MR_OUTLINE_DEFN(decl,body) macro,
** e.g. `MR_OUTLINE_DEFN(int foo(int x), { return x; })'.
**
** The advantage of MR_EXTERN_INLINE is that it is more code-space-efficient,
** especially in the case where you are compiling with C compiler optimizations
** turned off.
**
** It is OK to take the address of an inline function,
** but you should not assume that the address of a function declared
** MR_INLINE or MR_EXTERN_INLINE will be the same in all translation units.
*/
#if defined(__cplusplus)
/* C++ */
#define MR_STATIC_INLINE static inline
#define MR_INLINE inline
#define MR_EXTERN_INLINE inline
#define MR_OUTLINE_DEFN(DECL,BODY)
#elif defined(MR_CLANG)
/* clang: note that since clang also defines the macro __GNUC__
** we must handle it before we handle the GCC case.
** XXX why don't the C99 definitions work for clang?
*/
#define MR_STATIC_INLINE static
#define MR_INLINE static
#define MR_EXTERN_INLINE static
#define MR_OUTLINE_DEFN(DECL,BODY)
#elif defined(MR_GNUC)
/* GNU C: in (GNU) C99 or later mode GCC will use C99 style
** inline functions; otherwise GNU style inline functions will
** will be used.
*/
#if defined(__GNUC_STDC_INLINE__)
/* C99 style inlining. */
#define MR_STATIC_INLINE static inline
#define MR_INLINE static inline
#define MR_EXTERN_INLINE inline
#define MR_OUTLINE_DEFN(DECL,BODY) extern DECL;
#else
/* GNU C90 style inlining. */
#define MR_STATIC_INLINE static __inline__
#define MR_INLINE static __inline__
#define MR_EXTERN_INLINE extern __inline__
#define MR_OUTLINE_DEFN(DECL,BODY) DECL BODY
#endif /* ! __GNUC_STDC_INLINE */
#elif defined(MR_MSVC)
#define MR_STATIC_INLINE static __inline
#define MR_INLINE static __inline
#define MR_EXTERN_INLINE extern __inline
#define MR_OUTLINE_DEFN(DECL, BODY)
#elif __STDC_VERSION__ >= 199901
/* C99 */
#define MR_STATIC_INLINE static inline
#define MR_INLINE static inline
#define MR_EXTERN_INLINE inline
#define MR_OUTLINE_DEFN(DECL,BODY) extern DECL;
#else
/* C89 */
#define MR_STATIC_INLINE static
#define MR_INLINE static
#define MR_EXTERN_INLINE static
#define MR_OUTLINE_DEFN(DECL,BODY)
#endif
/*---------------------------------------------------------------------------*/
/* A macro for declaring functions that never return */
#if defined(MR_GNUC) || defined(MR_CLANG)
#define MR_NO_RETURN(x) x __attribute__((noreturn))
#elif defined(MR_MSVC)
#define MR_NO_RETURN(x) __declspec(noreturn) x
#else
#define MR_NO_RETURN(x) x
#endif
/*---------------------------------------------------------------------------*/
/*
** MR_CALL:
** A macro for specifying the calling convention to use
** for C functions generated by the MLDS back-end
** (and for builtins such as unification which must use
** the same calling convention).
** This can expand to whatever implementation-specific magic
** is required to tell the C compiler to use a different
** calling convention.
**
** If MR_USE_REGPARM is defined, and we're using gcc on x86,
** then we use a non-standard but more efficient calling
** convention that passes parameters in registers.
** Otherwise we just use the default C calling convention.
**
** Any changes here (e.g. adding additional calling conventions,
** or adding support for other C compilers or other processors)
** should be reflected in the mangled grade name produced by
** runtime/mercury_grade.h.
**
** It might be slightly more efficient to use __regparm__(3) rather than
** __regparm__(2), but GCC won't do tail-call optimization for calls via
** function pointers if we use __regparm__(3), since there may be no spare
** caller-save registers to hold the function pointer. Tail call
** optimization is more likely to be important than squeezing the last 1%
** in performance.
*/
#if defined(MR_USE_REGPARM) && defined(MR_GNUC) && defined(__i386__)
#define MR_CALL __attribute__((__stdcall__, __regparm__(2)))
#else
#define MR_CALL
#endif
/*---------------------------------------------------------------------------*/
/*
** C preprocessor tricks.
*/
/* convert a macro to a string */
#define MR_STRINGIFY(x) MR_STRINGIFY_2(x)
#define MR_STRINGIFY_2(x) #x
/* paste some macros together */
#define MR_PASTE2(a,b) MR_PASTE2_2(a,b)
#define MR_PASTE2_2(a,b) a##b
#define MR_PASTE3(a,b,c) MR_PASTE3_2(a,b,c)
#define MR_PASTE3_2(a,b,c) a##b##c
#define MR_PASTE4(a,b,c,d) MR_PASTE4_2(a,b,c,d)
#define MR_PASTE4_2(a,b,c,d) a##b##c##d
#define MR_PASTE5(a,b,c,d,e) MR_PASTE5_2(a,b,c,d,e)
#define MR_PASTE5_2(a,b,c,d,e) a##b##c##d##e
#define MR_PASTE6(a,b,c,d,e,f) MR_PASTE6_2(a,b,c,d,e,f)
#define MR_PASTE6_2(a,b,c,d,e,f) a##b##c##d##e##f
#define MR_PASTE7(a,b,c,d,e,f,g) MR_PASTE7_2(a,b,c,d,e,f,g)
#define MR_PASTE7_2(a,b,c,d,e,f,g) a##b##c##d##e##f##g
#define MR_PASTE8(a,b,c,d,e,f,g,h) MR_PASTE8_2(a,b,c,d,e,f,g,h)
#define MR_PASTE8_2(a,b,c,d,e,f,g,h) a##b##c##d##e##f##g##h
#define MR_PASTE9(a,b,c,d,e,f,g,h,i) MR_PASTE9_2(a,b,c,d,e,f,g,h,i)
#define MR_PASTE9_2(a,b,c,d,e,f,g,h,i) a##b##c##d##e##f##g##h##i
#define MR_PASTE10(a,b,c,d,e,f,g,h,i,j) MR_PASTE10_2(a,b,c,d,e,f,g,h,i,j)
#define MR_PASTE10_2(a,b,c,d,e,f,g,h,i,j) a##b##c##d##e##f##g##h##i##j
#define MR_PASTE11(a,b,c,d,e,f,g,h,i,j,k) \
MR_PASTE11_2(a,b,c,d,e,f,g,h,i,j,k)
#define MR_PASTE11_2(a,b,c,d,e,f,g,h,i,j,k) \
a##b##c##d##e##f##g##h##i##j##k
#define MR_PASTE12(a,b,c,d,e,f,g,h,i,j,k,l) \
MR_PASTE12_2(a,b,c,d,e,f,g,h,i,j,k,l)
#define MR_PASTE12_2(a,b,c,d,e,f,g,h,i,j,k,l) \
a##b##c##d##e##f##g##h##i##j##k##l
/*
** MR_CHECK_EXPR_TYPE(expr, type):
** This macro checks that the given expression has a type
** which is compatible with (assignable to) the specified type,
** forcing a compile error if it does not.
** It does not evaluate the expression.
** Note that the specified type must be a complete type,
** i.e. it must not be a pointer to a struct which has
** not been defined.
**
** This macro is useful for defining type-safe function-like macros.
**
** The implementation of this macro looks like it dereferences
** a null pointer, but because that code is inside sizeof(), it will
** not get executed; the compiler will instead just check that it is
** type-correct.
*/
#define MR_CHECK_EXPR_TYPE(expr, type) \
((void) sizeof(*(type *)NULL = (expr)))
/*---------------------------------------------------------------------------*/
#define MR_SORRY(msg) MR_fatal_error("Sorry, not yet implemented: " msg);
/*---------------------------------------------------------------------------*/
/*
** MR_IF is for writing if-then-elses that must expand to expressions, not
** statements.
*/
#define MR_IF(cond, val) ((cond) ? ((val), (void)0) : (void)0)
/*---------------------------------------------------------------------------*/
#endif /* not MERCURY_STD_H */