This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
64-bit obstack support
- From: Alan Modra <amodra at gmail dot com>
- To: libc-alpha at sourceware dot org
- Date: Wed, 16 Jul 2014 17:34:12 +0930
- Subject: 64-bit obstack support
- Authentication-results: sourceware.org; auth=none
In https://sourceware.org/ml/binutils/2014-07/msg00137.html, I bumped
OBSTACK_INTERFACE_VERSION, thinking that with an int -> size_t change
on some function parameters we obviously have an ABI change.
However, it seems that the bump is not really necessary due to the
following:
- the existing obstack support only works for obstacks sized up to
INTMAX, so we only need to be compatible if passing a size_t in the
positive int range.
- on 32-bit targets supported by glibc, sizeof(int) == sizeof(size_t),
so for those targets the change is just substituting an unsigned
parameter for one that was signed.
- on 64-bit targets supported by glibc, a size_t parameter (at least
for the first or second parameter) or return from a function, is
passed in the same register as an int. I checked aarch64, alpha,
mips64, powerpc64, s390x, sh64, sparc64, tilegx, x64_64.
That leaves non-glibc supported targets to consider, but I wonder if
they are worth worrying about.. I expect that most modern 64-bit
targets would prove to be similar in that int and size_t are passed to
functions in registers.
Note that in contrast to my previous patch, this one does not make
obstack.chunk_size a size_t, over concern that x86_64-mingw would see
an ABI change if I did that.
Comments? (Maybe at the Cauldron, I'm about to catch a plane!)
PR gdb/17133
* malloc/obstack.h: Formatting. Test HAVE_STRING_H.
(__PTR_INT_TYPE): Rename from PTR_INT_TYPE.
(__attribute_pure__): Define without reference to glibc macro.
(__extension__): Avoid warning when __GNUC_MINOR__ undefined.
(struct obstack): Make chunk_size unsigned long, and temp union
with size_t. Correct chunkfun prototype to take a size_t.
(_obstack_newchunk): Update prototype.
(_obstack_begin, _obstack_begin_1, _obstack_memory_used): Likewise.
(__obstack_free): Define as _obstack_free.
(obstack_init, obstack_begin, obstack_specify_allocation_with_arg,
obstack_chunkfun): Update alloc function casts, formatting.
For __STDC__ versions of the following macros:
(obstack_object_size): Return size_t.
(obstack_room): Likewise, and rename __o.
(obstack_make_room): Make __len size_t, and use obstack_room.
(obstack_grow, obstack_grow0, obstack_1grow, obstack_ptr_grow,
obstack_int_grow, obstack_blank): Likewise.
(obstack_finish): Use unsigned comparison when comparing aligned
next_free against chunk_limit.
(obstack_free): Cast OBJ to remove possible const qualifier.
Don't wrap __obstack_free in parentheses.
For !__STDC__ versions of the following macros:
(obstack_object_size, obstack_room): Return size_t.
(obstack_make_room): Use temp.i and obstack_room.
(obstack_grow, obstack_grow0, obstack_1grow, obstack_ptr_grow,
obstack_int_grow, obstack_blank): Likewise.
(obstack_finish): Use temp.p. Use unsigned comparision when
comparing aligned next_free against chunk_limit.
(obstack_free): Use temp.p and same comparisons as __STDC__ version.
Don't wrap __obstack_free in parentheses.
* malloc/obstack.c: Test HAVE_CONFIG_H. Include gnu-versions.h.
(COPYING_UNIT): Delete.
(_Noreturn): Don't rely on this being defined, define ..
(__attribute_noreturn__): ..and use this instead.
(CALL_CHUNKFUN): Update chunkfun cast.
(chunkfun_t, freefun_t): New typdefs.
(_obstack_begin_worker): Split out from ..
(_obstack_begin, _obstack_begin_1): ..here. Make "size" param
unsigned long, and correct chunkfun prototype.
(_obstack_newchunk): Make "length" param size_t and local
vars size_t. Use memcpy to move existing object.
(obstack_free): Update alias.
(_obstack_memory_used): Return and use size_t local.
diff --git a/malloc/obstack.h b/malloc/obstack.h
index 59ae6e5..be64816 100644
--- a/malloc/obstack.h
+++ b/malloc/obstack.h
@@ -96,7 +96,7 @@
Because of the way we do it, you can "unwind" an obstack
back to a previous state. (You may remove objects much
as you would with a stack.)
- */
+*/
/* Don't do the contents of this file more than once. */
@@ -110,10 +110,10 @@
and use ptrdiff_t. */
#ifdef __PTRDIFF_TYPE__
-# define PTR_INT_TYPE __PTRDIFF_TYPE__
+# define __PTR_INT_TYPE __PTRDIFF_TYPE__
#else
# include <stddef.h>
-# define PTR_INT_TYPE ptrdiff_t
+# define __PTR_INT_TYPE ptrdiff_t
#endif
/* If B is the base of an object addressed by P, return the result of
@@ -122,77 +122,88 @@
#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A)))
-/* Similar to _BPTR_ALIGN (B, P, A), except optimize the common case
+/* Similar to __BPTR_ALIGN (B, P, A), except optimize the common case
where pointers can be converted to integers, aligned as integers,
- and converted back again. If PTR_INT_TYPE is narrower than a
+ and converted back again. If __PTR_INT_TYPE is narrower than a
pointer (e.g., the AS/400), play it safe and compute the alignment
relative to B. Otherwise, use the faster strategy of computing the
alignment relative to 0. */
#define __PTR_ALIGN(B, P, A) \
- __BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \
+ __BPTR_ALIGN (sizeof (__PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \
P, A)
-#include <string.h>
+#if defined _LIBC || defined HAVE_STRING_H
+# include <string.h>
+#endif
+/* Attribute 'pure' was valid as of gcc 3.0. */
#ifndef __attribute_pure__
-# define __attribute_pure__ _GL_ATTRIBUTE_PURE
+# if defined __GNUC__ && __GNUC__ >= 3
+# define __attribute_pure__ __attribute__ ((__pure__))
+# else
+# define __attribute_pure__
+# endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
-struct _obstack_chunk /* Lives at front of each chunk. */
+struct _obstack_chunk /* Lives at front of each chunk. */
{
- char *limit; /* 1 past end of this chunk */
- struct _obstack_chunk *prev; /* address of prior chunk or NULL */
- char contents[4]; /* objects begin here */
+ char *limit; /* 1 past end of this chunk */
+ struct _obstack_chunk *prev; /* address of prior chunk or NULL */
+ char contents[4]; /* objects begin here */
};
-struct obstack /* control current object in current chunk */
+struct obstack /* control current object in current chunk */
{
- long chunk_size; /* preferred size to allocate chunks in */
- struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */
- char *object_base; /* address of object we are building */
- char *next_free; /* where to add next char to current object */
- char *chunk_limit; /* address of char after current chunk */
+ unsigned long chunk_size; /* Initial chunk size. Should be a size_t,
+ along with the 2nd. arg of obstack_begin*,
+ but we can't change without bumping the ABI.
+ Some targets, eg. x64_64-mingw, have a
+ 32-bit long and 64-bit size_t. */
+ struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */
+ char *object_base; /* address of object we are building */
+ char *next_free; /* where to add next char to current object */
+ char *chunk_limit; /* address of char after current chunk */
union
{
- PTR_INT_TYPE tempint;
- void *tempptr;
- } temp; /* Temporary for some macros. */
- int alignment_mask; /* Mask of alignment for each object. */
+ size_t i;
+ void *p;
+ } temp; /* Temporary for some macros. */
+ int alignment_mask; /* Mask of alignment for each object. */
/* These prototypes vary based on 'use_extra_arg', and we use
casts to the prototypeless function type in all assignments,
but having prototypes here quiets -Wstrict-prototypes. */
- struct _obstack_chunk *(*chunkfun) (void *, long);
+ struct _obstack_chunk *(*chunkfun) (void *, size_t);
void (*freefun) (void *, struct _obstack_chunk *);
- void *extra_arg; /* first arg for chunk alloc/dealloc funcs */
- unsigned use_extra_arg : 1; /* chunk alloc/dealloc funcs take extra arg */
+ void *extra_arg; /* first arg for chunk alloc/dealloc funcs */
+ unsigned use_extra_arg : 1; /* chunk alloc/dealloc funcs take extra arg */
unsigned maybe_empty_object : 1; /* There is a possibility that the current
chunk contains a zero-length object. This
prevents freeing the chunk if we allocate
a bigger chunk to replace it. */
- unsigned alloc_failed : 1; /* No longer used, as we now call the failed
+ unsigned alloc_failed : 1; /* No longer used, as we now call the failed
handler on error, but retained for binary
compatibility. */
};
/* Declare the external functions we use; they are in obstack.c. */
-extern void _obstack_newchunk (struct obstack *, int);
-extern int _obstack_begin (struct obstack *, int, int,
- void *(*)(long), void (*)(void *));
-extern int _obstack_begin_1 (struct obstack *, int, int,
- void *(*)(void *, long),
- void (*)(void *, void *), void *);
-extern int _obstack_memory_used (struct obstack *) __attribute_pure__;
+extern void _obstack_newchunk (struct obstack *, size_t);
+extern int _obstack_begin (struct obstack *, unsigned long, int,
+ void *(*) (size_t), void (*) (void *));
+extern int _obstack_begin_1 (struct obstack *, unsigned long, int,
+ void *(*) (void *, size_t),
+ void (*) (void *, void *), void *);
+extern size_t _obstack_memory_used (struct obstack *) __attribute_pure__;
-/* The default name of the function for freeing a chunk is 'obstack_free',
+/* The default name of the function for freeing a chunk is '_obstack_free',
but gnulib users can override this by defining '__obstack_free'. */
#ifndef __obstack_free
-# define __obstack_free obstack_free
+# define __obstack_free _obstack_free
#endif
extern void __obstack_free (struct obstack *, void *);
@@ -218,38 +229,38 @@ extern int obstack_exit_failure;
/* Pointer to next byte not yet allocated in current chunk. */
-#define obstack_next_free(h) ((h)->next_free)
+#define obstack_next_free(h) ((h)->next_free)
/* Mask specifying low bits that should be clear in address of an object. */
#define obstack_alignment_mask(h) ((h)->alignment_mask)
/* To prevent prototype warnings provide complete argument list. */
-#define obstack_init(h) \
- _obstack_begin ((h), 0, 0, \
- (void *(*)(long))obstack_chunk_alloc, \
- (void (*)(void *))obstack_chunk_free)
+#define obstack_init(h) \
+ _obstack_begin ((h), 0, 0, \
+ (void *(*) (size_t)) obstack_chunk_alloc, \
+ (void (*) (void *)) obstack_chunk_free)
-#define obstack_begin(h, size) \
- _obstack_begin ((h), (size), 0, \
- (void *(*)(long))obstack_chunk_alloc, \
- (void (*)(void *))obstack_chunk_free)
+#define obstack_begin(h, size) \
+ _obstack_begin ((h), (size), 0, \
+ (void *(*) (size_t)) obstack_chunk_alloc, \
+ (void (*) (void *)) obstack_chunk_free)
-#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
- _obstack_begin ((h), (size), (alignment), \
- (void *(*)(long))(chunkfun), \
- (void (*)(void *))(freefun))
+#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
+ _obstack_begin ((h), (size), (alignment), \
+ (void *(*) (size_t)) (chunkfun), \
+ (void (*) (void *)) (freefun))
#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
- _obstack_begin_1 ((h), (size), (alignment), \
- (void *(*)(void *, long))(chunkfun), \
- (void (*)(void *, void *))(freefun), (arg))
+ _obstack_begin_1 ((h), (size), (alignment), \
+ (void *(*) (void *, size_t)) (chunkfun), \
+ (void (*) (void *, void *)) (freefun), (arg))
#define obstack_chunkfun(h, newchunkfun) \
- ((h)->chunkfun = (struct _obstack_chunk *(*)(void *, long))(newchunkfun))
+ ((h)->chunkfun = (struct _obstack_chunk *(*)(void *, size_t)) (newchunkfun))
#define obstack_freefun(h, newfreefun) \
- ((h)->freefun = (void (*)(void *, struct _obstack_chunk *))(newfreefun))
+ ((h)->freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun))
#define obstack_1grow_fast(h, achar) (*((h)->next_free)++ = (achar))
@@ -258,7 +269,7 @@ extern int obstack_exit_failure;
#define obstack_memory_used(h) _obstack_memory_used (h)
#if defined __GNUC__
-# if ! (2 < __GNUC__ + (8 <= __GNUC_MINOR__))
+# if !defined __GNUC_MINOR__ || __GNUC__ * 1000 + __GNUC_MINOR__ < 2008
# define __extension__
# endif
@@ -267,159 +278,160 @@ extern int obstack_exit_failure;
without using a global variable.
Also, we can avoid using the 'temp' slot, to make faster code. */
-# define obstack_object_size(OBSTACK) \
- __extension__ \
- ({ struct obstack const *__o = (OBSTACK); \
- (unsigned) (__o->next_free - __o->object_base); })
-
-# define obstack_room(OBSTACK) \
- __extension__ \
- ({ struct obstack const *__o = (OBSTACK); \
- (unsigned) (__o->chunk_limit - __o->next_free); })
-
-# define obstack_make_room(OBSTACK, length) \
- __extension__ \
- ({ struct obstack *__o = (OBSTACK); \
- int __len = (length); \
- if (__o->chunk_limit - __o->next_free < __len) \
- _obstack_newchunk (__o, __len); \
- (void) 0; })
-
-# define obstack_empty_p(OBSTACK) \
- __extension__ \
- ({ struct obstack const *__o = (OBSTACK); \
- (__o->chunk->prev == 0 \
- && __o->next_free == __PTR_ALIGN ((char *) __o->chunk, \
- __o->chunk->contents, \
- __o->alignment_mask)); })
-
-# define obstack_grow(OBSTACK, where, length) \
- __extension__ \
- ({ struct obstack *__o = (OBSTACK); \
- int __len = (length); \
- if (__o->next_free + __len > __o->chunk_limit) \
- _obstack_newchunk (__o, __len); \
- memcpy (__o->next_free, where, __len); \
- __o->next_free += __len; \
- (void) 0; })
-
-# define obstack_grow0(OBSTACK, where, length) \
- __extension__ \
- ({ struct obstack *__o = (OBSTACK); \
- int __len = (length); \
- if (__o->next_free + __len + 1 > __o->chunk_limit) \
- _obstack_newchunk (__o, __len + 1); \
- memcpy (__o->next_free, where, __len); \
- __o->next_free += __len; \
- *(__o->next_free)++ = 0; \
- (void) 0; })
-
-# define obstack_1grow(OBSTACK, datum) \
- __extension__ \
- ({ struct obstack *__o = (OBSTACK); \
- if (__o->next_free + 1 > __o->chunk_limit) \
- _obstack_newchunk (__o, 1); \
- obstack_1grow_fast (__o, datum); \
- (void) 0; })
+# define obstack_object_size(OBSTACK) \
+ __extension__ \
+ ({ struct obstack const *__o = (OBSTACK); \
+ (size_t) (__o->next_free - __o->object_base); })
+
+/* The local variable is named __o1 to avoid a shadowed variable
+ warning when invoked from other obstack macros. */
+# define obstack_room(OBSTACK) \
+ __extension__ \
+ ({ struct obstack const *__o1 = (OBSTACK); \
+ (size_t) (__o1->chunk_limit - __o1->next_free); })
+
+# define obstack_make_room(OBSTACK, length) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ size_t __len = (length); \
+ if (obstack_room (__o) < __len) \
+ _obstack_newchunk (__o, __len); \
+ (void) 0; })
+
+# define obstack_empty_p(OBSTACK) \
+ __extension__ \
+ ({ struct obstack const *__o = (OBSTACK); \
+ (__o->chunk->prev == 0 \
+ && __o->next_free == __PTR_ALIGN ((char *) __o->chunk, \
+ __o->chunk->contents, \
+ __o->alignment_mask)); })
+
+# define obstack_grow(OBSTACK, where, length) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ size_t __len = (length); \
+ if (obstack_room (__o) < __len) \
+ _obstack_newchunk (__o, __len); \
+ memcpy (__o->next_free, where, __len); \
+ __o->next_free += __len; \
+ (void) 0; })
+
+# define obstack_grow0(OBSTACK, where, length) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ size_t __len = (length); \
+ if (obstack_room (__o) < __len + 1) \
+ _obstack_newchunk (__o, __len + 1); \
+ memcpy (__o->next_free, where, __len); \
+ __o->next_free += __len; \
+ *(__o->next_free)++ = 0; \
+ (void) 0; })
+
+# define obstack_1grow(OBSTACK, datum) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ if (obstack_room (__o) < 1) \
+ _obstack_newchunk (__o, 1); \
+ obstack_1grow_fast (__o, datum); \
+ (void) 0; })
/* These assume that the obstack alignment is good enough for pointers
or ints, and that the data added so far to the current object
shares that much alignment. */
-# define obstack_ptr_grow(OBSTACK, datum) \
- __extension__ \
- ({ struct obstack *__o = (OBSTACK); \
- if (__o->next_free + sizeof (void *) > __o->chunk_limit) \
- _obstack_newchunk (__o, sizeof (void *)); \
- obstack_ptr_grow_fast (__o, datum); }) \
-
-# define obstack_int_grow(OBSTACK, datum) \
- __extension__ \
- ({ struct obstack *__o = (OBSTACK); \
- if (__o->next_free + sizeof (int) > __o->chunk_limit) \
- _obstack_newchunk (__o, sizeof (int)); \
- obstack_int_grow_fast (__o, datum); })
-
-# define obstack_ptr_grow_fast(OBSTACK, aptr) \
- __extension__ \
- ({ struct obstack *__o1 = (OBSTACK); \
- void *__p1 = __o1->next_free; \
- *(const void **) __p1 = (aptr); \
- __o1->next_free += sizeof (const void *); \
- (void) 0; })
-
-# define obstack_int_grow_fast(OBSTACK, aint) \
- __extension__ \
- ({ struct obstack *__o1 = (OBSTACK); \
- void *__p1 = __o1->next_free; \
- *(int *) __p1 = (aint); \
- __o1->next_free += sizeof (int); \
- (void) 0; })
-
-# define obstack_blank(OBSTACK, length) \
- __extension__ \
- ({ struct obstack *__o = (OBSTACK); \
- int __len = (length); \
- if (__o->chunk_limit - __o->next_free < __len) \
- _obstack_newchunk (__o, __len); \
- obstack_blank_fast (__o, __len); \
- (void) 0; })
-
-# define obstack_alloc(OBSTACK, length) \
- __extension__ \
- ({ struct obstack *__h = (OBSTACK); \
- obstack_blank (__h, (length)); \
- obstack_finish (__h); })
-
-# define obstack_copy(OBSTACK, where, length) \
- __extension__ \
- ({ struct obstack *__h = (OBSTACK); \
- obstack_grow (__h, (where), (length)); \
- obstack_finish (__h); })
-
-# define obstack_copy0(OBSTACK, where, length) \
- __extension__ \
- ({ struct obstack *__h = (OBSTACK); \
- obstack_grow0 (__h, (where), (length)); \
- obstack_finish (__h); })
-
-/* The local variable is named __o1 to avoid a name conflict
- when obstack_blank is called. */
-# define obstack_finish(OBSTACK) \
- __extension__ \
- ({ struct obstack *__o1 = (OBSTACK); \
- void *__value = (void *) __o1->object_base; \
- if (__o1->next_free == __value) \
- __o1->maybe_empty_object = 1; \
- __o1->next_free \
- = __PTR_ALIGN (__o1->object_base, __o1->next_free, \
- __o1->alignment_mask); \
- if (__o1->next_free - (char *) __o1->chunk \
- > __o1->chunk_limit - (char *) __o1->chunk) \
- __o1->next_free = __o1->chunk_limit; \
- __o1->object_base = __o1->next_free; \
- __value; })
-
-# define obstack_free(OBSTACK, OBJ) \
- __extension__ \
- ({ struct obstack *__o = (OBSTACK); \
- void *__obj = (OBJ); \
- if (__obj > (void *) __o->chunk && __obj < (void *) __o->chunk_limit) \
- __o->next_free = __o->object_base = (char *) __obj; \
- else (__obstack_free) (__o, __obj); })
+# define obstack_ptr_grow(OBSTACK, datum) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ if (obstack_room (__o) < sizeof (void *)) \
+ _obstack_newchunk (__o, sizeof (void *)); \
+ obstack_ptr_grow_fast (__o, datum); })
+
+# define obstack_int_grow(OBSTACK, datum) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ if (obstack_room (__o) < sizeof (int)) \
+ _obstack_newchunk (__o, sizeof (int)); \
+ obstack_int_grow_fast (__o, datum); })
+
+# define obstack_ptr_grow_fast(OBSTACK, aptr) \
+ __extension__ \
+ ({ struct obstack *__o1 = (OBSTACK); \
+ void *__p1 = __o1->next_free; \
+ *(const void **) __p1 = (aptr); \
+ __o1->next_free += sizeof (const void *); \
+ (void) 0; })
+
+# define obstack_int_grow_fast(OBSTACK, aint) \
+ __extension__ \
+ ({ struct obstack *__o1 = (OBSTACK); \
+ void *__p1 = __o1->next_free; \
+ *(int *) __p1 = (aint); \
+ __o1->next_free += sizeof (int); \
+ (void) 0; })
+
+# define obstack_blank(OBSTACK, length) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ size_t __len = (length); \
+ if (obstack_room (__o) < __len) \
+ _obstack_newchunk (__o, __len); \
+ obstack_blank_fast (__o, __len); \
+ (void) 0; })
+
+# define obstack_alloc(OBSTACK, length) \
+ __extension__ \
+ ({ struct obstack *__h = (OBSTACK); \
+ obstack_blank (__h, (length)); \
+ obstack_finish (__h); })
+
+# define obstack_copy(OBSTACK, where, length) \
+ __extension__ \
+ ({ struct obstack *__h = (OBSTACK); \
+ obstack_grow (__h, (where), (length)); \
+ obstack_finish (__h); })
+
+# define obstack_copy0(OBSTACK, where, length) \
+ __extension__ \
+ ({ struct obstack *__h = (OBSTACK); \
+ obstack_grow0 (__h, (where), (length)); \
+ obstack_finish (__h); })
+
+# define obstack_finish(OBSTACK) \
+ __extension__ \
+ ({ struct obstack *__o1 = (OBSTACK); \
+ void *__value = (void *) __o1->object_base; \
+ if (__o1->next_free == __value) \
+ __o1->maybe_empty_object = 1; \
+ __o1->next_free = __PTR_ALIGN (__o1->object_base, __o1->next_free, \
+ __o1->alignment_mask); \
+ if ((size_t) (__o1->next_free - (char *) __o1->chunk) \
+ > (size_t) (__o1->chunk_limit - (char *) __o1->chunk)) \
+ __o1->next_free = __o1->chunk_limit; \
+ __o1->object_base = __o1->next_free; \
+ __value; })
+
+# define obstack_free(OBSTACK, OBJ) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ void *__obj = (void *) (OBJ); \
+ if (__obj > (void *) __o->chunk \
+ && __obj < (void *) __o->chunk_limit) \
+ __o->next_free = __o->object_base = (char *) __obj; \
+ else \
+ __obstack_free (__o, __obj); })
#else /* not __GNUC__ */
# define obstack_object_size(h) \
- (unsigned) ((h)->next_free - (h)->object_base)
+ ((size_t) ((h)->next_free - (h)->object_base))
-# define obstack_room(h) \
- (unsigned) ((h)->chunk_limit - (h)->next_free)
+# define obstack_room(h) \
+ ((size_t) ((h)->chunk_limit - (h)->next_free))
# define obstack_empty_p(h) \
- ((h)->chunk->prev == 0 \
- && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk, \
- (h)->chunk->contents, \
+ ((h)->chunk->prev == 0 \
+ && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk, \
+ (h)->chunk->contents, \
(h)->alignment_mask))
/* Note that the call to _obstack_newchunk is enclosed in (..., 0)
@@ -427,89 +439,86 @@ extern int obstack_exit_failure;
in the arms of the conditional expression.
Casting the third operand to void was tried before,
but some compilers won't accept it. */
-
-# define obstack_make_room(h, length) \
- ((h)->temp.tempint = (length), \
- (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0))
-
-# define obstack_grow(h, where, length) \
- ((h)->temp.tempint = (length), \
- (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \
- memcpy ((h)->next_free, where, (h)->temp.tempint), \
- (h)->next_free += (h)->temp.tempint)
-
-# define obstack_grow0(h, where, length) \
- ((h)->temp.tempint = (length), \
- (((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), (h)->temp.tempint + 1), 0) : 0), \
- memcpy ((h)->next_free, where, (h)->temp.tempint), \
- (h)->next_free += (h)->temp.tempint, \
+# define obstack_make_room(h, length) \
+ ((h)->temp.i = (length), \
+ ((obstack_room (h) < (h)->temp.i) \
+ ? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0))
+
+# define obstack_grow(h, where, length) \
+ ((h)->temp.i = (length), \
+ ((obstack_room (h) < (h)->temp.i) \
+ ? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0), \
+ memcpy ((h)->next_free, where, (h)->temp.i), \
+ (h)->next_free += (h)->temp.i)
+
+# define obstack_grow0(h, where, length) \
+ ((h)->temp.i = (length), \
+ ((obstack_room (h) < (h)->temp.i + 1) \
+ ? (_obstack_newchunk ((h), (h)->temp.i + 1), 0) : 0), \
+ memcpy ((h)->next_free, where, (h)->temp.i), \
+ (h)->next_free += (h)->temp.i, \
*((h)->next_free)++ = 0)
-# define obstack_1grow(h, datum) \
- ((((h)->next_free + 1 > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), 1), 0) : 0), \
+# define obstack_1grow(h, datum) \
+ (((obstack_room (h) < 1) \
+ ? (_obstack_newchunk ((h), 1), 0) : 0), \
obstack_1grow_fast (h, datum))
-# define obstack_ptr_grow(h, datum) \
- ((((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
+# define obstack_ptr_grow(h, datum) \
+ ((((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
obstack_ptr_grow_fast (h, datum))
-# define obstack_int_grow(h, datum) \
- ((((h)->next_free + sizeof (int) > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
+# define obstack_int_grow(h, datum) \
+ (((obstack_room (h) < sizeof (int)) \
+ ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
obstack_int_grow_fast (h, datum))
-# define obstack_ptr_grow_fast(h, aptr) \
+# define obstack_ptr_grow_fast(h, aptr) \
(((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr))
-# define obstack_int_grow_fast(h, aint) \
+# define obstack_int_grow_fast(h, aint) \
(((int *) ((h)->next_free += sizeof (int)))[-1] = (aint))
-# define obstack_blank(h, length) \
- ((h)->temp.tempint = (length), \
- (((h)->chunk_limit - (h)->next_free < (h)->temp.tempint) \
- ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \
- obstack_blank_fast (h, (h)->temp.tempint))
+# define obstack_blank(h, length) \
+ ((h)->temp.i = (length), \
+ ((obstack_room (h) < (h)->temp.i) \
+ ? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0), \
+ obstack_blank_fast (h, (h)->temp.i))
-# define obstack_alloc(h, length) \
+# define obstack_alloc(h, length) \
(obstack_blank ((h), (length)), obstack_finish ((h)))
-# define obstack_copy(h, where, length) \
+# define obstack_copy(h, where, length) \
(obstack_grow ((h), (where), (length)), obstack_finish ((h)))
-# define obstack_copy0(h, where, length) \
+# define obstack_copy0(h, where, length) \
(obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
-# define obstack_finish(h) \
- (((h)->next_free == (h)->object_base \
- ? (((h)->maybe_empty_object = 1), 0) \
- : 0), \
- (h)->temp.tempptr = (h)->object_base, \
- (h)->next_free \
- = __PTR_ALIGN ((h)->object_base, (h)->next_free, \
- (h)->alignment_mask), \
- (((h)->next_free - (char *) (h)->chunk \
- > (h)->chunk_limit - (char *) (h)->chunk) \
- ? ((h)->next_free = (h)->chunk_limit) : 0), \
- (h)->object_base = (h)->next_free, \
- (h)->temp.tempptr)
-
-# define obstack_free(h, obj) \
- ((h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk, \
- ((((h)->temp.tempint > 0 \
- && (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk)) \
- ? (void) ((h)->next_free = (h)->object_base \
- = (h)->temp.tempint + (char *) (h)->chunk) \
- : (__obstack_free) (h, (h)->temp.tempint + (char *) (h)->chunk)))
+# define obstack_finish(h) \
+ (((h)->next_free == (h)->object_base \
+ ? (((h)->maybe_empty_object = 1), 0) \
+ : 0), \
+ (h)->temp.p = (h)->object_base, \
+ (h)->next_free = __PTR_ALIGN ((h)->object_base, (h)->next_free, \
+ (h)->alignment_mask), \
+ (((size_t) ((h)->next_free - (char *) (h)->chunk) \
+ > (size_t) ((h)->chunk_limit - (char *) (h)->chunk)) \
+ ? ((h)->next_free = (h)->chunk_limit) : 0), \
+ (h)->object_base = (h)->next_free, \
+ (h)->temp.p)
+
+# define obstack_free(h, obj) \
+ ((h)->temp.p = (void *) (obj), \
+ (((h)->temp.p > (void *) (h)->chunk \
+ && (h)->temp.p < (void *) (h)->chunk_limit) \
+ ? (void) ((h)->next_free = (h)->object_base = (char *) (h)->temp.p) \
+ : __obstack_free ((h), (h)->temp.p)))
#endif /* not __GNUC__ */
#ifdef __cplusplus
-} /* C++ */
+} /* C++ */
#endif
-#endif /* obstack.h */
+#endif /* _OBSTACK_H */
diff --git a/malloc/obstack.c b/malloc/obstack.c
index fa4fefc..1838115 100644
--- a/malloc/obstack.c
+++ b/malloc/obstack.c
@@ -21,7 +21,9 @@
# include <obstack.h>
# include <shlib-compat.h>
#else
-# include <config.h>
+# ifdef HAVE_CONFIG_H
+# include "config.h"
+# endif
# include "obstack.h"
#endif
@@ -47,11 +49,9 @@
# endif
#endif
-#include <stddef.h>
-
#ifndef ELIDE_CODE
-
+# include <stddef.h>
# include <stdint.h>
/* Determine default alignment. */
@@ -75,22 +75,22 @@ enum
DEFAULT_ROUNDING = sizeof (union fooround)
};
-/* When we copy a long block of data, this is the unit to do it with.
- On some machines, copying successive ints does not work;
- in such a case, redefine COPYING_UNIT to 'long' (if that works)
- or 'char' as a last resort. */
-# ifndef COPYING_UNIT
-# define COPYING_UNIT int
-# endif
-
-
/* The functions allocating more room by calling 'obstack_chunk_alloc'
jump to the handler pointed to by 'obstack_alloc_failed_handler'.
This can be set to a user defined function which should either
abort gracefully or use longjump - but shouldn't return. This
variable by default points to the internal function
'print_and_abort'. */
-static _Noreturn void print_and_abort (void);
+
+# ifndef __attribute_noreturn__
+# if (defined __GNUC__ && defined __GNUC_MINOR__ \
+ && __GNUC__ * 1000 + __GNUC_MINOR__ >= 2007)
+# define __attribute_noreturn__ __attribute__ ((__noreturn__))
+# else
+# define __attribute_noreturn__
+# endif
+# endif
+static void __attribute_noreturn__ print_and_abort (void);
void (*obstack_alloc_failed_handler) (void) = print_and_abort;
/* Exit value used when 'print_and_abort' is used. */
@@ -119,17 +119,17 @@ compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
do not allow (expr) ? void : void. */
# define CALL_CHUNKFUN(h, size) \
- (((h)->use_extra_arg) \
- ? (*(h)->chunkfun)((h)->extra_arg, (size)) \
- : (*(struct _obstack_chunk *(*)(long))(h)->chunkfun)((size)))
+ (((h)->use_extra_arg) \
+ ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
+ : (*(struct _obstack_chunk *(*) (size_t)) (h)->chunkfun) ((size)))
# define CALL_FREEFUN(h, old_chunk) \
- do { \
- if ((h)->use_extra_arg) \
- (*(h)->freefun)((h)->extra_arg, (old_chunk)); \
- else \
- (*(void (*)(void *))(h)->freefun)((old_chunk)); \
- } while (0)
+ do { \
+ if ((h)->use_extra_arg) \
+ (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
+ else \
+ (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
+ } while (0)
/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
@@ -140,11 +140,14 @@ compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
Return nonzero if successful, calls obstack_alloc_failed_handler if
allocation fails. */
-int
-_obstack_begin (struct obstack *h,
- int size, int alignment,
- void *(*chunkfun) (long),
- void (*freefun) (void *))
+typedef struct _obstack_chunk * (*chunkfun_t) (void *, size_t);
+typedef void (*freefun_t) (void *, struct _obstack_chunk *);
+
+static int
+_obstack_begin_worker (struct obstack *h,
+ unsigned long size, int alignment,
+ chunkfun_t chunkfun, freefun_t freefun,
+ void *arg, int use_extra_arg)
{
struct _obstack_chunk *chunk; /* points to new chunk */
@@ -167,19 +170,19 @@ _obstack_begin (struct obstack *h,
size = 4096 - extra;
}
- h->chunkfun = (struct _obstack_chunk * (*) (void *, long)) chunkfun;
- h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+ h->chunkfun = chunkfun;
+ h->freefun = freefun;
h->chunk_size = size;
h->alignment_mask = alignment - 1;
- h->use_extra_arg = 0;
+ h->extra_arg = arg;
+ h->use_extra_arg = use_extra_arg;
chunk = h->chunk = CALL_CHUNKFUN (h, h->chunk_size);
if (!chunk)
(*obstack_alloc_failed_handler) ();
h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
alignment - 1);
- h->chunk_limit = chunk->limit
- = (char *) chunk + h->chunk_size;
+ h->chunk_limit = chunk->limit = (char *) chunk + h->chunk_size;
chunk->prev = 0;
/* The initial chunk now contains no empty object. */
h->maybe_empty_object = 0;
@@ -188,51 +191,26 @@ _obstack_begin (struct obstack *h,
}
int
-_obstack_begin_1 (struct obstack *h, int size, int alignment,
- void *(*chunkfun) (void *, long),
+_obstack_begin (struct obstack *h,
+ unsigned long size, int alignment,
+ void *(*chunkfun) (size_t),
+ void (*freefun) (void *))
+{
+ return _obstack_begin_worker (h, size, alignment,
+ (chunkfun_t) chunkfun, (freefun_t) freefun,
+ NULL, 0);
+}
+
+int
+_obstack_begin_1 (struct obstack *h,
+ unsigned long size, int alignment,
+ void *(*chunkfun) (void *, size_t),
void (*freefun) (void *, void *),
void *arg)
{
- struct _obstack_chunk *chunk; /* points to new chunk */
-
- if (alignment == 0)
- alignment = DEFAULT_ALIGNMENT;
- if (size == 0)
- /* Default size is what GNU malloc can fit in a 4096-byte block. */
- {
- /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
- Use the values for range checking, because if range checking is off,
- the extra bytes won't be missed terribly, but if range checking is on
- and we used a larger request, a whole extra 4096 bytes would be
- allocated.
-
- These number are irrelevant to the new GNU malloc. I suspect it is
- less sensitive to the size of the request. */
- int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
- + 4 + DEFAULT_ROUNDING - 1)
- & ~(DEFAULT_ROUNDING - 1));
- size = 4096 - extra;
- }
-
- h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
- h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
- h->chunk_size = size;
- h->alignment_mask = alignment - 1;
- h->extra_arg = arg;
- h->use_extra_arg = 1;
-
- chunk = h->chunk = CALL_CHUNKFUN (h, h->chunk_size);
- if (!chunk)
- (*obstack_alloc_failed_handler) ();
- h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
- alignment - 1);
- h->chunk_limit = chunk->limit
- = (char *) chunk + h->chunk_size;
- chunk->prev = 0;
- /* The initial chunk now contains no empty object. */
- h->maybe_empty_object = 0;
- h->alloc_failed = 0;
- return 1;
+ return _obstack_begin_worker (h, size, alignment,
+ (chunkfun_t) chunkfun, (freefun_t) freefun,
+ arg, 1);
}
/* Allocate a new current chunk for the obstack *H
@@ -242,14 +220,12 @@ _obstack_begin_1 (struct obstack *h, int size, int alignment,
to the beginning of the new one. */
void
-_obstack_newchunk (struct obstack *h, int length)
+_obstack_newchunk (struct obstack *h, size_t length)
{
struct _obstack_chunk *old_chunk = h->chunk;
struct _obstack_chunk *new_chunk;
- long new_size;
- long obj_size = h->next_free - h->object_base;
- long i;
- long already;
+ size_t new_size;
+ size_t obj_size = h->next_free - h->object_base;
char *object_base;
/* Compute size for new chunk. */
@@ -260,7 +236,7 @@ _obstack_newchunk (struct obstack *h, int length)
/* Allocate and initialize the new chunk. */
new_chunk = CALL_CHUNKFUN (h, new_size);
if (!new_chunk)
- (*obstack_alloc_failed_handler)();
+ (*obstack_alloc_failed_handler) ();
h->chunk = new_chunk;
new_chunk->prev = old_chunk;
new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
@@ -269,25 +245,8 @@ _obstack_newchunk (struct obstack *h, int length)
object_base =
__PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask);
- /* Move the existing object to the new chunk.
- Word at a time is fast and is safe if the object
- is sufficiently aligned. */
- if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
- {
- for (i = obj_size / sizeof (COPYING_UNIT) - 1;
- i >= 0; i--)
- ((COPYING_UNIT *) object_base)[i]
- = ((COPYING_UNIT *) h->object_base)[i];
- /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
- but that can cross a page boundary on a machine
- which does not do strict alignment for COPYING_UNITS. */
- already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
- }
- else
- already = 0;
- /* Copy remaining bytes one by one. */
- for (i = already; i < obj_size; i++)
- object_base[i] = h->object_base[i];
+ /* Move the existing object to the new chunk. */
+ memcpy (object_base, h->object_base, obj_size);
/* If the object just copied was the only data in OLD_CHUNK,
free that chunk and remove it from the chain.
@@ -321,8 +280,8 @@ int _obstack_allocated_p (struct obstack *h, void *obj) __attribute_pure__;
int
_obstack_allocated_p (struct obstack *h, void *obj)
{
- struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
- struct _obstack_chunk *plp; /* point to previous chunk if any */
+ struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
+ struct _obstack_chunk *plp; /* point to previous chunk if any */
lp = (h)->chunk;
/* We use >= rather than > since the object cannot be exactly at
@@ -344,8 +303,8 @@ _obstack_allocated_p (struct obstack *h, void *obj)
void
__obstack_free (struct obstack *h, void *obj)
{
- struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
- struct _obstack_chunk *plp; /* point to previous chunk if any */
+ struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
+ struct _obstack_chunk *plp; /* point to previous chunk if any */
lp = h->chunk;
/* We use >= because there cannot be an object at the beginning of a chunk.
@@ -372,21 +331,19 @@ __obstack_free (struct obstack *h, void *obj)
}
# ifdef _LIBC
-/* Older versions of libc used a function _obstack_free intended to be
- called by non-GCC compilers. */
-strong_alias (obstack_free, _obstack_free)
+/* Older versions of libc declared both _obstack_free and obstack_free. */
+strong_alias (__obstack_free, obstack_free)
# endif
-int
+size_t
_obstack_memory_used (struct obstack *h)
{
struct _obstack_chunk *lp;
- int nbytes = 0;
+ size_t nbytes = 0;
for (lp = h->chunk; lp != 0; lp = lp->prev)
- {
- nbytes += lp->limit - (char *) lp;
- }
+ nbytes += lp->limit - (char *) lp;
+
return nbytes;
}
@@ -404,7 +361,8 @@ _obstack_memory_used (struct obstack *h)
# include <libio/iolibio.h>
# endif
-static _Noreturn void
+static void
+__attribute_noreturn__
print_and_abort (void)
{
/* Don't change any of these strings. Yes, it would be possible to add
@@ -420,4 +378,4 @@ print_and_abort (void)
exit (obstack_exit_failure);
}
-#endif /* !ELIDE_CODE */
+#endif /* !ELIDE_CODE */
--
Alan Modra
Australia Development Lab, IBM