mirror of
https://github.com/netwide-assembler/nasm.git
synced 2024-11-27 08:10:07 +08:00
Better support for function attributes, autoconf cleanups
Use autoconf to detect function attributes; some compilers like Sun CC do support some gcc-style attributes, but don't define __GNUC__. Also -U__STRICT_ANSI__ already in configure.ac so our tests match what we might eventually encounter. Add const_func and pure_func attributes. Decorate functions in nasmlib.h with const_func and pure_func. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
This commit is contained in:
parent
70d0458050
commit
8b19083483
26
aclocal.m4
vendored
26
aclocal.m4
vendored
@ -47,3 +47,29 @@ if test x"$LIBEXT" = x; then
|
||||
fi
|
||||
AC_MSG_RESULT([$LIBEXT])
|
||||
AC_SUBST([LIBEXT])])
|
||||
|
||||
dnl --------------------------------------------------------------------------
|
||||
dnl PA_FUNC_ATTRIBUTE
|
||||
dnl
|
||||
dnl See if this compiler supports the equivalent of a specific gcc
|
||||
dnl attribute on a function, using the __attribute__(()) syntax.
|
||||
dnl All arguments except the attribute name are optional.
|
||||
dnl PA_FUNC_ATTRIBUTE(attribute, attribute_opts, return_type,
|
||||
dnl prototype_args, call_args)
|
||||
dnl --------------------------------------------------------------------------
|
||||
AC_DEFUN(PA_FUNC_ATTRIBUTE,
|
||||
[AC_MSG_CHECKING([if $CC supports the $1 function attribute])
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
||||
#include <stdarg.h>
|
||||
extern ifelse([$3],[],[void *],[$3]) __attribute__(($1$2))
|
||||
bar(ifelse([$4],[],[int],[$4]));
|
||||
void *foo(void)
|
||||
{
|
||||
return bar(ifelse([$5],[],[1],[$5]));
|
||||
}
|
||||
])],
|
||||
[AC_MSG_RESULT([yes])
|
||||
AC_DEFINE(m4_toupper([HAVE_FUNC_ATTRIBUTE_$1]), 1,
|
||||
[Define to 1 if your compiler supports __attribute__(($1)) on functions])],
|
||||
[AC_MSG_RESULT([no])])
|
||||
])
|
||||
|
72
configure.ac
72
configure.ac
@ -4,46 +4,6 @@ AC_PREREQ(2.63)
|
||||
AC_INIT(config/config.h.in)
|
||||
AC_CONFIG_HEADERS(config/config.h)
|
||||
|
||||
dnl Check for broken VPATH handling on older NetBSD makes.
|
||||
AC_DEFUN(AC_PROG_MAKE_VPATHOK,
|
||||
[AC_MSG_CHECKING(whether ${MAKE-make} has sane VPATH handling)
|
||||
set dummy ${MAKE-make}; ac_make=`echo "[$]2" | sed 'y%./+-%__p_%'`
|
||||
AC_CACHE_VAL(ac_cv_prog_make_vpathok,
|
||||
[mkdir conftestdir
|
||||
cat > conftestdir/conftestmake <<\EOF
|
||||
VPATH = ..
|
||||
conftestfoo: conftestbar
|
||||
@echo ac_make2temp=ok
|
||||
conftestbar: conftestbaz
|
||||
@echo ac_maketemp=broken
|
||||
@touch conftestbar
|
||||
EOF
|
||||
echo > conftestbaz # these two lines need to be...
|
||||
echo > conftestbar # ... in this order not the other
|
||||
changequote(, )dnl
|
||||
unset ac_maketemp
|
||||
unset ac_make2temp
|
||||
# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
|
||||
eval `cd conftestdir; ${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
|
||||
changequote([, ])dnl
|
||||
if test -n "$ac_maketemp"; then
|
||||
ac_cv_prog_make_vpathok=no
|
||||
else
|
||||
if test -n "$ac_make2temp"; then
|
||||
ac_cv_prog_make_vpathok=yes
|
||||
else
|
||||
ac_cv_prog_make_vpathok=no
|
||||
fi
|
||||
fi
|
||||
rm -rf conftestdir
|
||||
rm -f conftestbar conftestbaz])dnl
|
||||
if test $ac_cv_prog_make_vpathok = yes; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
])
|
||||
|
||||
AC_PREFIX_PROGRAM(nasm)
|
||||
|
||||
dnl Checks for programs.
|
||||
@ -54,12 +14,6 @@ AC_PROG_CC
|
||||
AC_PROG_CC_STDC
|
||||
AC_PROG_LN_S
|
||||
AC_PROG_MAKE_SET
|
||||
if test -f nasm.c; then
|
||||
# we're building in the source dir, so we don't need this check at all
|
||||
ac_cv_prog_make_vpathok=yes
|
||||
else
|
||||
AC_PROG_MAKE_VPATHOK
|
||||
fi
|
||||
AC_PROG_INSTALL
|
||||
|
||||
dnl Check for library extension
|
||||
@ -78,10 +32,16 @@ AH_TEMPLATE(WORDS_LITTLEENDIAN,
|
||||
[Define to 1 if your processor stores words with the least significant
|
||||
byte first (like Intel and VAX, unlike Motorola and SPARC).])
|
||||
|
||||
PA_ADD_CFLAGS([-std=c99])
|
||||
|
||||
dnl Force gcc and gcc-compatible compilers treat signed integers
|
||||
dnl as 2's complement
|
||||
PA_ADD_CFLAGS([-fwrapv])
|
||||
|
||||
dnl Some environments abuse __STRICT_ANSI__ to disable some
|
||||
dnl function declarations
|
||||
PA_ADD_CFLAGS([-U__STRICT_ANSI__])
|
||||
|
||||
dnl Don't put things in common if we can avoid it. We don't want to
|
||||
dnl assume all compilers support common, and this will help find those
|
||||
dnl problems. This also works around an OSX linker problem.
|
||||
@ -152,6 +112,7 @@ AC_CHECK_FUNCS([access _access faccessat])
|
||||
PA_HAVE_FUNC(__builtin_ctz, (0U))
|
||||
PA_HAVE_FUNC(__builtin_ctzl, (0UL))
|
||||
PA_HAVE_FUNC(__builtin_ctzll, (0ULL))
|
||||
PA_HAVE_FUNC(__builtin_expect, (1,1))
|
||||
|
||||
dnl Functions for which we have replacements available in lib/
|
||||
AC_CHECK_FUNCS([vsnprintf _vsnprintf])
|
||||
@ -172,12 +133,18 @@ AC_CHECK_DECLS(strnlen)
|
||||
dnl Check for missing types
|
||||
AC_TYPE_UINTPTR_T
|
||||
|
||||
if test $ac_cv_prog_make_vpathok = no; then
|
||||
echo Copying generated srcs into build directory to compensate for VPATH breakage
|
||||
for file in macros.c insnsa.c insnsd.c insnsn.c insnsi.h version.h version.mac; do
|
||||
if test ! -f $file; then cp -p ${srcdir}/${file} .; fi
|
||||
done
|
||||
fi
|
||||
dnl
|
||||
dnl Check for supported gcc attributes; some compilers (e.g. Sun CC)
|
||||
dnl support these, but don't define __GNUC__ as they don't support
|
||||
dnl some other features of gcc.
|
||||
dnl
|
||||
PA_FUNC_ATTRIBUTE(noreturn)
|
||||
PA_FUNC_ATTRIBUTE(returns_nonnull)
|
||||
PA_FUNC_ATTRIBUTE(malloc)
|
||||
PA_FUNC_ATTRIBUTE(alloc_size, (1))
|
||||
PA_FUNC_ATTRIBUTE(format, [(printf,1,2)], int, [const char *, ...], ["%d",1])
|
||||
PA_FUNC_ATTRIBUTE(const)
|
||||
PA_FUNC_ATTRIBUTE(pure)
|
||||
|
||||
dnl
|
||||
dnl support cchace
|
||||
@ -190,7 +157,6 @@ AC_ARG_ENABLE([ccache],
|
||||
dnl If we have gcc, add appropriate code cleanliness options
|
||||
PA_ADD_CFLAGS([-W])
|
||||
PA_ADD_CFLAGS([-Wall])
|
||||
PA_ADD_CFLAGS([-std=c99])
|
||||
PA_ADD_CFLAGS([-pedantic])
|
||||
dnl LLVM doesn't error out on invalid -W options unless this option is
|
||||
dnl specified first. Enable this so this script can actually discover
|
||||
|
@ -172,7 +172,7 @@ char *strsep(char **, const char *);
|
||||
* Hints to the compiler that a particular branch of code is more or
|
||||
* less likely to be taken.
|
||||
*/
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3
|
||||
#if HAVE_BUILTIN_EXPECT
|
||||
# define likely(x) __builtin_expect(!!(x), 1)
|
||||
# define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#else
|
||||
@ -183,25 +183,23 @@ char *strsep(char **, const char *);
|
||||
/*
|
||||
* Hints about malloc-like functions that never return NULL
|
||||
*/
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4 /* ? */
|
||||
#ifdef HAVE_FUNC_ATTRIBUTE_RETURNS_NONNULL
|
||||
# define never_null __attribute__((returns_nonnull))
|
||||
#else
|
||||
# define never_null
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FUNC_ATTRIBUTE_MALLOC
|
||||
# define safe_alloc never_null __attribute__((malloc))
|
||||
# ifdef __has_attribute
|
||||
# if __has_attribute(alloc_size)
|
||||
#else
|
||||
# define safe_alloc
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FUNC_ATTRIBUTE_ALLOC_SIZE
|
||||
# define safe_malloc(s) safe_alloc __attribute__((alloc_size(s)))
|
||||
# define safe_malloc2(s1,s2) safe_alloc __attribute__((alloc_size(s1,s2)))
|
||||
# define safe_realloc(s) never_null __attribute__((alloc_size(s)))
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef never_null
|
||||
# define never_null
|
||||
#endif
|
||||
#ifndef safe_alloc
|
||||
# define safe_alloc
|
||||
#endif
|
||||
#ifndef safe_malloc
|
||||
#else
|
||||
# define safe_malloc(s) safe_alloc
|
||||
# define safe_malloc2(s1,s2) safe_alloc
|
||||
# define safe_realloc(s) never_null
|
||||
@ -210,7 +208,7 @@ char *strsep(char **, const char *);
|
||||
/*
|
||||
* How to tell the compiler that a function doesn't return
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
#ifdef HAVE_FUNC_ATTRIBUTE_NORETURN
|
||||
# define no_return void __attribute__((noreturn))
|
||||
#else
|
||||
# define no_return void
|
||||
@ -219,10 +217,31 @@ char *strsep(char **, const char *);
|
||||
/*
|
||||
* How to tell the compiler that a function takes a printf-like string
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
#ifdef HAVE_FUNC_ATTRIBUTE_FORMAT
|
||||
# define printf_func(fmt, list) __attribute__((format(printf, fmt, list)))
|
||||
#else
|
||||
# define printf_func(fmt, list)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* How to tell the compiler that a function is pure arithmetic
|
||||
*/
|
||||
#ifdef HAVE_FUNC_ATTRIBUTE_CONST
|
||||
# define const_func __attribute__((const))
|
||||
#else
|
||||
# define const_func
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function has no side effects, but depends on its arguments,
|
||||
* memory pointed to by its arguments, or global variables.
|
||||
* NOTE: functions that return a value by modifying memory pointed to
|
||||
* by a pointer argument are *NOT* considered pure.
|
||||
*/
|
||||
#ifdef HAVE_FUNC_ATTRIBUTE_PURE
|
||||
# define pure_func __attribute__((pure))
|
||||
#else
|
||||
# define pure_func
|
||||
#endif
|
||||
|
||||
#endif /* NASM_COMPILER_H */
|
||||
|
@ -186,7 +186,7 @@ no_return nasm_assert_failed(const char *, int, const char *);
|
||||
#elif defined(HAVE_STRICMP)
|
||||
#define nasm_stricmp stricmp
|
||||
#else
|
||||
int nasm_stricmp(const char *, const char *);
|
||||
int pure_func nasm_stricmp(const char *, const char *);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_STRNCASECMP)
|
||||
@ -194,10 +194,10 @@ int nasm_stricmp(const char *, const char *);
|
||||
#elif defined(HAVE_STRNICMP)
|
||||
#define nasm_strnicmp strnicmp
|
||||
#else
|
||||
int nasm_strnicmp(const char *, const char *, size_t);
|
||||
int pure_func nasm_strnicmp(const char *, const char *, size_t);
|
||||
#endif
|
||||
|
||||
int nasm_memicmp(const char *, const char *, size_t);
|
||||
int pure_func nasm_memicmp(const char *, const char *, size_t);
|
||||
|
||||
#if defined(HAVE_STRSEP)
|
||||
#define nasm_strsep strsep
|
||||
@ -206,7 +206,7 @@ char *nasm_strsep(char **stringp, const char *delim);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_DECL_STRNLEN
|
||||
size_t strnlen(const char *, size_t);
|
||||
size_t pure_func strnlen(const char *, size_t);
|
||||
#endif
|
||||
|
||||
/* This returns the numeric value of a given 'digit'. */
|
||||
@ -230,8 +230,8 @@ int64_t readstrnum(char *str, int length, bool *warn);
|
||||
* seg_init: Initialise the segment-number allocator.
|
||||
* seg_alloc: allocate a hitherto unused segment number.
|
||||
*/
|
||||
void seg_init(void);
|
||||
int32_t seg_alloc(void);
|
||||
void pure_func seg_init(void);
|
||||
int32_t pure_func seg_alloc(void);
|
||||
|
||||
/*
|
||||
* many output formats will be able to make use of this: a standard
|
||||
@ -436,7 +436,7 @@ char *nasm_opt_val(char *p, char **opt, char **val);
|
||||
*/
|
||||
char *nasm_realpath(const char *rel_path);
|
||||
|
||||
const char *prefix_name(int);
|
||||
const char * pure_func prefix_name(int);
|
||||
|
||||
/*
|
||||
* Wrappers around fopen()... for future change to a dedicated structure
|
||||
@ -482,7 +482,7 @@ off_t nasm_file_size(FILE *f);
|
||||
off_t nasm_file_size_by_path(const char *pathname);
|
||||
void fwritezero(off_t bytes, FILE *fp);
|
||||
|
||||
static inline bool overflow_general(int64_t value, int bytes)
|
||||
static inline bool const_func overflow_general(int64_t value, int bytes)
|
||||
{
|
||||
int sbit;
|
||||
int64_t vmax, vmin;
|
||||
@ -497,7 +497,7 @@ static inline bool overflow_general(int64_t value, int bytes)
|
||||
return value < vmin || value > vmax;
|
||||
}
|
||||
|
||||
static inline bool overflow_signed(int64_t value, int bytes)
|
||||
static inline bool const_func overflow_signed(int64_t value, int bytes)
|
||||
{
|
||||
int sbit;
|
||||
int64_t vmax, vmin;
|
||||
@ -512,7 +512,7 @@ static inline bool overflow_signed(int64_t value, int bytes)
|
||||
return value < vmin || value > vmax;
|
||||
}
|
||||
|
||||
static inline bool overflow_unsigned(int64_t value, int bytes)
|
||||
static inline bool const_func overflow_unsigned(int64_t value, int bytes)
|
||||
{
|
||||
int sbit;
|
||||
int64_t vmax, vmin;
|
||||
@ -527,7 +527,7 @@ static inline bool overflow_unsigned(int64_t value, int bytes)
|
||||
return value < vmin || value > vmax;
|
||||
}
|
||||
|
||||
static inline int64_t signed_bits(int64_t value, int bits)
|
||||
static inline int64_t const_func signed_bits(int64_t value, int bits)
|
||||
{
|
||||
if (bits < 64) {
|
||||
value &= ((int64_t)1 << bits) - 1;
|
||||
@ -537,7 +537,7 @@ static inline int64_t signed_bits(int64_t value, int bits)
|
||||
return value;
|
||||
}
|
||||
|
||||
int idata_bytes(int opcode);
|
||||
int const_func idata_bytes(int opcode);
|
||||
|
||||
/* check if value is power of 2 */
|
||||
#define is_power2(v) ((v) && ((v) & ((v) - 1)) == 0)
|
||||
@ -545,13 +545,13 @@ int idata_bytes(int opcode);
|
||||
/*
|
||||
* floor(log2(v))
|
||||
*/
|
||||
int ilog2_32(uint32_t v);
|
||||
int ilog2_64(uint64_t v);
|
||||
int const_func ilog2_32(uint32_t v);
|
||||
int const_func ilog2_64(uint64_t v);
|
||||
|
||||
/*
|
||||
* v == 0 ? 0 : is_power2(x) ? ilog2_X(v) : -1
|
||||
*/
|
||||
int alignlog2_32(uint32_t v);
|
||||
int alignlog2_64(uint64_t v);
|
||||
int const_func alignlog2_32(uint32_t v);
|
||||
int const_func alignlog2_64(uint64_t v);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user