vec.h, vec.c: New, type safe vector API.
authorNathan Sidwell <nathan@codesourcery.com>
Mon, 28 Jun 2004 10:30:21 +0000 (10:30 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Mon, 28 Jun 2004 10:30:21 +0000 (10:30 +0000)
* vec.h, vec.c: New, type safe vector API.
* Makefile.in (OBJS-common): Add vec.o.
(vec.o): New target.
(gengtype-lex.o): Depend on vec.h.

From-SVN: r83769

gcc/ChangeLog
gcc/Makefile.in
gcc/gengtype-lex.l
gcc/vec.c [new file with mode: 0644]
gcc/vec.h [new file with mode: 0644]

index 985a65aad0079bb530a16af0421c00fd6ed37006..133389b1060b8adac291fa47c9a0b6342dfadfec 100644 (file)
@@ -1,3 +1,10 @@
+2004-06-28  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * vec.h, vec.c: New, type safe vector API.
+       * Makefile.in (OBJS-common): Add vec.o.
+       (vec.o): New target.
+       (gengtype-lex.o): Depend on vec.h.
+
 2004-06-28  Paolo Bonzini  <bonzini@gnu.org>
 
        * fold-const.c (fold_cond_expr_with_comparison): Add ARG1
index 81b5b7e51eb53299d4a0c478c2195196c1827a30..62a5aa1d970e32f0d2ed389bb0b4e3e5e0975e0f 100644 (file)
@@ -914,7 +914,7 @@ OBJS-common = \
  sbitmap.o sched-deps.o sched-ebb.o sched-rgn.o sched-vis.o sdbout.o      \
  simplify-rtx.o sreal.o stmt.o stor-layout.o stringpool.o                \
  targhooks.o timevar.o toplev.o tracer.o tree.o tree-dump.o unroll.o      \
- varasm.o varray.o version.o vmsdbgout.o xcoffout.o alloc-pool.o          \
+ varasm.o varray.o vec.o version.o vmsdbgout.o xcoffout.o alloc-pool.o    \
  et-forest.o cfghooks.o bt-load.o pretty-print.o $(GGC) web.o passes.o    \
  rtl-profile.o tree-profile.o rtlhooks.o cfgexpand.o
 
@@ -1990,6 +1990,7 @@ global.o : global.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(FLAGS
    toplev.h $(TM_P_H)
 varray.o : varray.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) varray.h $(GGC_H) errors.h \
    $(HASHTAB_H)
+vec.o : vec.c $(CONFIG_H) coretypes.h vec.h ggc.h errors.h
 ra.o : ra.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TM_P_H) insn-config.h \
    $(RECOG_H) $(INTEGRATE_H) function.h $(REGS_H) $(OBSTACK_H) hard-reg-set.h \
    $(BASIC_BLOCK_H) $(DF_H) $(EXPR_H) output.h toplev.h $(FLAGS_H) reload.h $(RA_H)
@@ -2515,7 +2516,7 @@ gengtype.o : gengtype.c gengtype.h $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H)
   real.h $(RTL_BASE_H) gtyp-gen.h
 
 gengtype-lex.o : gengtype-lex.c gengtype.h gengtype-yacc.h \
-  $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H)
+  $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H) vec.h
        $(CC_FOR_BUILD) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(INCLUDES) \
         $< $(OUTPUT_OPTION)
 
index c5af2003f652eb1301ff24cdc8f8ecf2a97d1b71..ed9100829ee8e65329a509e79643123f1366b4db 100644 (file)
@@ -30,6 +30,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "gengtype.h"
 #include "gengtype-yacc.h"
 
+#define YY_INPUT(BUF,RESULT,SIZE) ((RESULT) = macro_input (BUF,SIZE))
+
+static unsigned macro_input (char *buffer, unsigned);
+static void push_macro_expansion (const char *, unsigned,
+                                 const char *, unsigned);
 static void update_lineno (const char *l, size_t len);
 
 struct fileloc lexer_line;
@@ -218,6 +223,35 @@ ITYPE      {IWORD}({WS}{IWORD})*
   return ENT_YACCUNION;
 }
 
+^"DEF_VEC_"[[:alnum:]_]*{WS}?"("{WS}?{ID}{WS}?")" {
+  char *macro, *arg;
+  unsigned macro_len, arg_len;
+  char *ptr = yytext;
+  type_p t;
+
+  /* Locate the macro and argument strings.  */
+  macro = ptr;
+  while (*ptr != '(' && !ISSPACE (*ptr))
+    ptr++;
+  macro_len = ptr - macro;
+  while (*ptr == '(' || ISSPACE (*ptr))
+    ptr++;
+  arg = ptr;
+  while (*ptr != ')' && !ISSPACE (*ptr))
+    ptr++;
+  arg_len = ptr - arg;
+
+  /* Push the macro for later expansion.  */
+  push_macro_expansion (macro, macro_len, arg, arg_len);
+
+  /* Create the struct and typedef.  */
+  ptr = xmemdup ("VEC_", 4, 4 + arg_len + 1);
+  memcpy (&ptr[4], arg, arg_len);
+  ptr[4 + arg_len] = 0;
+  t = find_structure (ptr, 0);
+  do_typedef (ptr, t, &lexer_line);
+}
+
 <in_struct>{
 
 "/*"                           { BEGIN(in_struct_comment); }
@@ -229,7 +263,6 @@ ITYPE       {IWORD}({WS}{IWORD})*
 {WS}                           { update_lineno (yytext, yyleng); }
 
 "const"/[^[:alnum:]_]          /* don't care */
-
 "GTY"/[^[:alnum:]_]            { return GTY_TOKEN; }
 "union"/[^[:alnum:]_]          { return UNION; }
 "struct"/[^[:alnum:]_]         { return STRUCT; }
@@ -254,6 +287,28 @@ ITYPE      {IWORD}({WS}{IWORD})*
   return SCALAR;
 }
 
+"VEC"{WS}?"("{WS}?{ID}{WS}?")" {
+  char *macro, *arg;
+  unsigned macro_len, arg_len;
+  char *ptr = yytext;
+
+  macro = ptr;
+  while (*ptr != '(' && !ISSPACE (*ptr))
+    ptr++;
+  macro_len = ptr - macro;
+  while (*ptr == '(' || ISSPACE (*ptr))
+    ptr++;
+  arg = ptr;
+  while (*ptr != ')' && !ISSPACE (*ptr))
+    ptr++;
+  arg_len = ptr - arg;
+  ptr = xmemdup (macro, macro_len, macro_len + arg_len + 2);
+  ptr[macro_len] = '_';
+  memcpy (&ptr[macro_len+1], arg, arg_len);
+  yylval.s = ptr;
+  return ID;
+}
+
 {ID}/[^[:alnum:]_]             {
   yylval.s = xmemdup (yytext, yyleng, yyleng+1);
   return ID;
@@ -340,6 +395,93 @@ ITYPE      {IWORD}({WS}{IWORD})*
 
 %%
 
+/* Deal with the expansion caused by the DEF_VEC_x macros.  */
+
+typedef struct macro
+{
+  const char *name;
+  const char *expansion;
+  struct macro *next;
+} macro_t;
+
+static const macro_t macro_defs[] = 
+{
+#define IN_GENGTYPE 1
+#include "vec.h"
+  {NULL, NULL, NULL}
+};
+
+/* Chain of macro expansions to do at end of scanning.  */
+static macro_t *macro_expns;
+
+/* Push macro NAME (NAME_LEN) with argument ARG (ARG_LEN) onto the
+   expansion queue.  We ensure NAME is known at this point.  */
+
+static void
+push_macro_expansion (const char *name, unsigned name_len,
+                     const char *arg, unsigned arg_len)
+{
+  unsigned ix;
+
+  for (ix = 0; macro_defs[ix].name; ix++)
+    if (strlen (macro_defs[ix].name) == name_len
+        && !memcmp (name, macro_defs[ix].name, name_len))
+      {
+        macro_t *expansion = xmalloc (sizeof (*expansion));
+
+       expansion->next = macro_expns;
+       expansion->name = xmemdup (arg, arg_len, arg_len+1);
+       expansion->expansion = macro_defs[ix].expansion;
+       macro_expns = expansion;
+       return;
+      }
+  error_at_line (&lexer_line, "unrecognized macro `%.*s(%.*s)'",
+                name_len, name, arg_len, arg);
+}
+
+/* Attempt to read some input.  Use fread until we're at the end of
+   file.  At end of file expand the next queued macro.  We presume the
+   buffer is large enough for the entire expansion.  */
+
+static unsigned
+macro_input (char *buffer, unsigned size)
+{
+  unsigned result;
+
+  result = fread (buffer, 1, size, yyin);
+  if (result)
+    /*NOP*/;
+  else if (ferror (yyin))
+    YY_FATAL_ERROR ("read of source file failed");
+  else if (macro_expns)
+    {
+      const char *expn;
+      unsigned len;
+
+      for (expn = macro_expns->expansion; *expn; expn++)
+        {
+         if (*expn == '#')
+           {
+             if (buffer[result-1] == ' ' && buffer[result-2] == '_')
+               result--;
+             len = strlen (macro_expns->name);
+             memcpy (&buffer[result], macro_expns->name, len);
+             result += len;
+           }
+         else
+           {
+             buffer[result++] = *expn;
+             if (*expn == ';' || *expn == '{')
+               buffer[result++] = '\n';
+           }
+        }
+      if (result > size)
+        YY_FATAL_ERROR ("buffer too small to expand macro");
+      macro_expns = macro_expns->next;
+    }
+  return result;
+}
+
 void
 yyerror (const char *s)
 {
diff --git a/gcc/vec.c b/gcc/vec.c
new file mode 100644 (file)
index 0000000..b8c5a32
--- /dev/null
+++ b/gcc/vec.c
@@ -0,0 +1,104 @@
+/* Vector API for GNU compiler.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   Contributed by Nathan Sidwell <nathan@codesourcery.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#include "config.h"
+#include "system.h"
+#include "ggc.h"
+#include "vec.h"
+#include "errors.h"
+#include "coretypes.h"
+#include "tree.h"
+
+struct vec_prefix 
+{
+  size_t num;
+  size_t alloc;
+  void *vec[1];
+};
+
+/* Ensure there are at least RESERVE free slots in VEC, if RESERVE !=
+   ~0u. If RESERVE == ~0u increase the current allocation
+   exponentially.  VEC can be NULL, to create a new vector.  */
+
+void *
+vec_p_reserve (void *vec, size_t reserve)
+{
+  return vec_o_reserve (vec, reserve,
+                       offsetof (struct vec_prefix, vec), sizeof (void *));
+}
+
+/* Ensure there are at least RESERVE free slots in VEC, if RESERVE !=
+   ~0u.  If RESERVE == ~0u, increase the current allocation
+   exponentially.  VEC can be NULL, in which case a new vector is
+   created.  The vector's trailing array is at VEC_OFFSET offset and
+   consistes of ELT_SIZE sized elements.  */
+
+void *
+vec_o_reserve (void *vec, size_t reserve, size_t vec_offset, size_t elt_size)
+{
+  struct vec_prefix *pfx = vec;
+  size_t alloc;
+
+  if (reserve + 1)
+    alloc = (pfx ? pfx->num : 0) + reserve;
+  else
+    alloc = pfx ? pfx->alloc * 2 : 4;
+  
+  if (!pfx || pfx->alloc < alloc)
+    {
+      vec = ggc_realloc (vec, vec_offset + alloc * elt_size);
+      ((struct vec_prefix *)vec)->alloc = alloc;
+      if (!pfx)
+       ((struct vec_prefix *)vec)->num = 0;
+    }
+  
+  return vec;
+}
+
+/* Allocate a structure which contains a vector as a trailing element.
+   The vector is at STRUCT_OFFSET offset within the struct and the
+   vector's array is at VEC_OFFSET offset within the vector.  */
+
+void *
+vec_embedded_alloc (size_t struct_offset, size_t vec_offset,
+                   size_t elt_size, size_t reserve)
+{
+  void *ptr = ggc_alloc (struct_offset + vec_offset + elt_size * reserve);
+  struct vec_prefix *pfx = (struct vec_prefix *)((char *)ptr + struct_offset);
+
+  pfx->num = 0;
+  pfx->alloc = reserve;
+
+  return ptr;
+}
+
+#if ENABLE_CHECKING
+/* Issue a vector domain error, and then fall over.  */
+
+void
+vec_assert_fail (const char *op, const char *struct_name,
+                const char *file, size_t line, const char *function)
+{
+  internal_error ("vector %s %s domain error, in %s at %s:%u",
+                 struct_name, op, function, function,
+                 trim_filename (file), line);
+}
+#endif
diff --git a/gcc/vec.h b/gcc/vec.h
new file mode 100644 (file)
index 0000000..42d1c1f
--- /dev/null
+++ b/gcc/vec.h
@@ -0,0 +1,567 @@
+/* Vector API for GNU compiler.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   Contributed by Nathan Sidwell <nathan@codesourcery.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
+
+#ifndef GCC_VEC_H
+#define GCC_VEC_H
+
+/* The macros here implement a set of templated vector types and
+   associated interfaces.  These templates are implemented with
+   macros, as we're not in C++ land.  The interface functions are
+   typesafe and use static inline functions, sometimes backed by
+   out-of-line generic functions.  The vectors are designed to
+   interoperate with the GTY machinery.
+
+   Because of the different behaviour of objects and of pointers to
+   objects, there are two flavours.  One to deal with a vector of
+   pointers to objects, and one to deal with a vector of objects
+   themselves.  Both of these pass pointers to objects around -- in
+   the former case the pointers are stored into the vector and in the
+   latter case the pointers are dereferenced and the objects copied
+   into the vector.  Therefore, when using a vector of pointers, the
+   objects pointed to must be long lived, but when dealing with a
+   vector of objects, the source objects need not be.
+
+   The vectors are implemented using the trailing array idiom, thus
+   they are not resizeable without changing the address of the vector
+   object itself.  This means you cannot have variables or fields of
+   vector type -- always use a pointer to a vector.  The one exception
+   is the final field of a structure, which could be a vector type.
+   You will have to use the embedded_alloc call to create such
+   objects, and they will probably not be resizeable (so don't use the
+   'safe' allocation variants).  The trailing array idiom is used
+   (rather than a pointer to an array of data), because, if we allow
+   NULL to also represent an empty vector, empty vectors occupy
+   minimal space in the structure containing them.
+
+   Each operation that increases the number of active elements is
+   available in 'quick' and 'safe' variants.  The former presumes that
+   there is sufficient allocated space for the operation to succeed
+   (it aborts if there is not).  The latter will reallocate the
+   vector, if needed.  Reallocation causes an exponential increase in
+   vector size.  If you know you will be adding N elements, it would
+   be more efficient to use the reserve operation before adding the
+   elements with the 'quick' operation.
+
+   You should prefer the push and pop operations, as they append and
+   remove from the end of the vector.  The insert and remove
+   operations allow you to change elements in the middle of the
+   vector.  There are two remove operations, one which preserves the
+   element ordering 'ordered_remove', and one which does not
+   'unordered_remove'.  The latter function copies the end element
+   into the removed slot, rather than invoke a memmove operation.
+   
+   Vector types are defined using a DEF_VEC_x(TYPEDEF) macro, and
+   variables of vector type are declared using a VEC(TYPEDEF)
+   macro. The 'x' letter indicates whether TYPEDEF is a pointer (P) or
+   object (O) type.
+
+   An example of their use would be,
+
+   DEF_VEC_P(tree);    // define a vector of tree pointers.  This must
+                       // appear at file scope.
+
+   struct my_struct {
+     VEC(tree) *v;      // A (pointer to) a vector of tree pointers.
+   };
+
+   struct my_struct *s;
+
+   if (VEC_length(tree,s)) { we have some contents }
+   VEC_safe_push(tree,s,decl); // append some decl onto the end
+   for (ix = 0; (t = VEC_iterate(tree,s,ix)); ix++)
+     { do something with t }
+
+*/
+
+/* Macros to invoke API calls.  A single macro works for both pointer
+   and object vectors, but the argument and return types might well be
+   different.  In each macro, TDEF is the typedef of the vector
+   elements.  Some of these macros pass the vector, V, by reference
+   (by taking its address), this is noted in the descriptions.  */
+
+/* Length of vector
+   size_t VEC_T_length(const VEC(T) *v);
+
+   Return the number of active elements in V.  V can be NULL, in which
+   case zero is returned.  */
+#define VEC_length(TDEF,V)             (VEC_OP(TDEF,length)(V))
+
+/* Get the final element of the vector.
+   T VEC_T_last(VEC(T) *v); // Pointer
+   T *VEC_T_last(VEC(T) *v); // Object
+
+   Return the final element.  If V is empty,  abort.  */
+#define VEC_last(TDEF,V)               (VEC_OP(TDEF,last)(V))
+
+/* Index into vector
+   T VEC_T_index(VEC(T) *v, size_t ix); // Pointer
+   T *VEC_T_index(VEC(T) *v, size_t ix); // Object
+
+   Return the IX'th element.  If IX is outside the domain of V,
+   abort.  */
+#define VEC_index(TDEF,V,I)            (VEC_OP(TDEF,index)(V,I))
+
+/* Iterate over vector
+   T VEC_T_index(VEC(T) *v, size_t ix); // Pointer
+   T *VEC_T_index(VEC(T) *v, size_t ix); // Object
+
+   Return the IX'th element or NULL. Use this to iterate over the
+   elements of a vector as follows,
+
+     for (ix = 0; (ptr = VEC_iterate(T,v,ix)); ix++)
+       continue;  */
+#define VEC_iterate(TDEF,V,I)          (VEC_OP(TDEF,iterate)(V,I))
+
+/* Allocate new vector.
+   VEC(T) *VEC_T_alloc(size_t reserve);
+
+   Allocate a new vector with space for RESERVE objects.  */
+#define VEC_alloc(TDEF,A)              (VEC_OP(TDEF,alloc)(A))
+
+/* Allocate new vector offset within a structure
+   void *VEC_T_embedded_alloc(size_t offset, size_t reserve);
+
+   Allocate a new vector which is at offset OFFSET within a structure,
+   and with space for RESERVE objects.  Return a pointer to the start
+   of the structure containing the vector.  Naturally, the vector must
+   be the last member of the structure.  */
+#define VEC_embedded_alloc(TDEF,O,A)   (VEC_OP(TDEF,embedded_alloc)(O,A))
+
+/* Reserve space.
+   void VEC_T_reserve(VEC(T) *&v, size_t reserve);
+
+   Ensure that V has at least RESERVE slots available.  Note this can
+   cause V to be reallocated.  */
+#define VEC_reserve(TDEF,V,R)          (VEC_OP(TDEF,reserve)(&(V),R))
+
+/* Push object with no reallocation
+   T *VEC_T_quick_push (VEC(T) *v, T obj); // Pointer
+   T *VEC_T_quick_push (VEC(T) *v, T *obj); // Object
+   
+   Push a new element onto the end, returns a pointer to the slot
+   filled in. For object vectors, the new value can be NULL, in which
+   case NO initialization is performed.  Aborts if there is
+   insufficient space in the vector. */
+#define VEC_quick_push(TDEF,V,O)       (VEC_OP(TDEF,quick_push)(V,O))
+
+/* Push object with reallocation
+   T *VEC_T_safe_push (VEC(T) *&v, T obj); // Pointer
+   T *VEC_T_safe_push (VEC(T) *&v, T *obj); // Object
+   
+   Push a new element onto the end, returns a pointer to the slot
+   filled in. For object vectors, the new value can be NULL, in which
+   case NO initialization is performed.  Reallocates V, if needed.  */
+#define VEC_safe_push(TDEF,V,O)                (VEC_OP(TDEF,safe_push)(&(V),O))
+
+/* Pop element off end
+   T VEC_T_pop (VEC(T) *v);            // Pointer
+   void VEC_T_pop (VEC(T) *v);         // Object
+
+   Pop the last element off the end. Returns the element popped, for
+   pointer vectors.  */
+#define VEC_pop(TDEF,V)                        (VEC_OP(TDEF,pop)(V))
+
+/* Replace element
+   T VEC_T_replace (VEC(T) *v, size_t ix, T val); // Pointer
+   T *VEC_T_replace (VEC(T) *v, size_t ix, T *val);  // Object
+   
+   Replace the IXth element of V with a new value, VAL.  For pointer
+   vectors returns the original value. For object vectors returns a
+   pointer to the new value.  For object vectors the new value can be
+   NULL, in which case no overwriting of the slot is actually
+   performed.  */
+#define VEC_replace(TDEF,V,I,O)                (VEC_OP(TDEF,replace)(V,I,O))
+
+/* Insert object with no reallocation
+   T *VEC_T_quick_insert (VEC(T) *v, size_t ix, T val); // Pointer
+   T *VEC_T_quick_insert (VEC(T) *v, size_t ix, T *val); // Object
+   
+   Insert an element, VAL, at the IXth position of V. Return a pointer
+   to the slot created.  For vectors of object, the new value can be
+   NULL, in which case no initialization of the inserted slot takes
+   place. Aborts if there is insufficient space.  */
+#define VEC_quick_insert(TDEF,V,I,O)   (VEC_OP(TDEF,quick_insert)(V,I,O))
+
+/* Insert object with reallocation
+   T *VEC_T_safe_insert (VEC(T) *&v, size_t ix, T val); // Pointer
+   T *VEC_T_safe_insert (VEC(T) *&v, size_t ix, T *val); // Object
+   
+   Insert an element, VAL, at the IXth position of V. Return a pointer
+   to the slot created.  For vectors of object, the new value can be
+   NULL, in which case no initialization of the inserted slot takes
+   place. Reallocate V, if necessary.  */
+#define VEC_safe_insert(TDEF,V,I,O)    (VEC_OP(TDEF,safe_insert)(&(V),I,O))
+     
+/* Remove element retaining order
+   T VEC_T_ordered_remove (VEC(T) *v, size_t ix); // Pointer
+   void VEC_T_ordered_remove (VEC(T) *v, size_t ix); // Object
+   
+   Remove an element from the IXth position of V. Ordering of
+   remaining elements is preserverd.  For pointer vectors returns the
+   removed object.  This is an O(N) operation due to a memmove.  */
+#define VEC_ordered_remove(TDEF,V,I)   (VEC_OP(TDEF,ordered_remove)(V,I))
+
+/* Remove element destroying order
+   T VEC_T_unordered_remove (VEC(T) *v, size_t ix); // Pointer
+   void VEC_T_unordered_remove (VEC(T) *v, size_t ix); // Object
+   
+   Remove an element from the IXth position of V. Ordering of
+   remaining elements is destroyed.  For pointer vectors returns the
+   removed object.  This is an O(1) operation.  */
+#define VEC_unordered_remove(TDEF,V,I) (VEC_OP(TDEF,unordered_remove)(V,I))
+
+#if !IN_GENGTYPE
+#include "auto-host.h"
+
+/* Reallocate an array of elements with prefix.  */
+extern void *vec_p_reserve (void *, size_t);
+extern void *vec_o_reserve (void *, size_t, size_t, size_t);
+extern void *vec_embedded_alloc (size_t, size_t, size_t, size_t);
+
+#if ENABLE_CHECKING
+extern void vec_assert_fail (const char *, const char *,
+                           const char *, size_t, const char *)
+     ATTRIBUTE_NORETURN;
+#define VEC_ASSERT_FAIL(OP,VEC) \
+  vec_assert_fail (OP,#VEC,__FILE__,__LINE__,__FUNCTION__)
+     
+#define VEC_ASSERT(EXPR,OP,TDEF) \
+  (void)((EXPR) ? 0 : (VEC_ASSERT_FAIL(OP,VEC(TDEF)), 0))
+#else
+#define VEC_ASSERT(EXPR,OP,TYPE) (void)(EXPR)
+#endif
+
+#define VEC(TDEF) VEC_##TDEF
+#define VEC_OP(TDEF,OP) VEC_OP_(VEC(TDEF),OP)
+#define VEC_OP_(VEC,OP) VEC_OP__(VEC,OP)
+#define VEC_OP__(VEC,OP) VEC ## _ ## OP
+#else  /* IN_GENGTYPE */
+#define VEC(TDEF) VEC_ TDEF
+#define VEC_STRINGIFY(X) VEC_STRINGIFY_(X)
+#define VEC_STRINGIFY_(X) #X
+#undef GTY
+#endif /* IN_GENGTYPE */
+
+#define VEC_TDEF(TDEF)                                                   \
+typedef struct VEC (TDEF) GTY(())                                        \
+{                                                                        \
+  size_t num;                                                            \
+  size_t alloc;                                                                  \
+  TDEF GTY ((length ("%h.num"))) vec[1];                                 \
+} VEC (TDEF)
+
+/* Vector of pointer to object.  */
+#if IN_GENGTYPE
+{"DEF_VEC_P", VEC_STRINGIFY (VEC_TDEF (#)) ";", NULL},
+#else
+  
+#define DEF_VEC_P(TDEF)                                                          \
+VEC_TDEF (TDEF);                                                         \
+                                                                         \
+static inline size_t VEC_OP (TDEF,length)                                \
+     (const VEC (TDEF) *vec_)                                            \
+{                                                                        \
+  return vec_ ? vec_->num : 0;                                           \
+}                                                                        \
+                                                                         \
+static inline TDEF VEC_OP (TDEF,last)                                    \
+     (const VEC (TDEF) *vec_)                                            \
+{                                                                        \
+  VEC_ASSERT (vec_ && vec_->num, "last", TDEF);                                  \
+                                                                         \
+  return vec_->vec[vec->num - 1];                                        \
+}                                                                        \
+                                                                         \
+static inline TDEF VEC_OP (TDEF,index)                                   \
+     (const VEC (TDEF) *vec_, size_t ix_)                                \
+{                                                                        \
+  VEC_ASSERT (vec_ && ix_ < vec_->num, "index", TDEF);                   \
+                                                                         \
+  return vec_->vec[ix_];                                                 \
+}                                                                        \
+                                                                         \
+static inline TDEF VEC_OP (TDEF,iterate)                                 \
+     (const VEC (TDEF) *vec_, size_t ix_)                                \
+{                                                                        \
+  return vec_ && ix_ < vec_->num ? vec_->vec[ix_] : NULL;                \
+}                                                                        \
+                                                                         \
+static inline VEC (TDEF) *VEC_OP (TDEF,alloc)                            \
+     (size_t alloc_)                                                     \
+{                                                                        \
+  return vec_p_reserve (NULL, alloc_ - !alloc_);                         \
+}                                                                        \
+                                                                         \
+static inline void *VEC_OP (TDEF,embedded_alloc)                         \
+     (size_t offset_, size_t alloc_)                                     \
+{                                                                        \
+  return vec_embedded_alloc (offset_, offsetof (VEC(TDEF),vec),                  \
+                            sizeof (TDEF), alloc_);                      \
+}                                                                        \
+                                                                         \
+static inline void VEC_OP (TDEF,reserve)                                 \
+     (VEC (TDEF) **vec_, size_t alloc_)                                          \
+{                                                                        \
+  *vec_ = vec_p_reserve (*vec_, alloc_);                                 \
+}                                                                        \
+                                                                         \
+static inline TDEF *VEC_OP (TDEF,quick_push)                             \
+     (VEC (TDEF) *vec_, TDEF obj_)                                       \
+{                                                                        \
+  TDEF *slot_;                                                           \
+                                                                         \
+  VEC_ASSERT (vec_->num < vec_->alloc, "push", TDEF);                    \
+  slot_ = &vec_->vec[vec_->num++];                                       \
+  *slot_ = obj_;                                                         \
+                                                                         \
+  return slot_;                                                                  \
+}                                                                        \
+                                                                         \
+static inline TDEF *VEC_OP (TDEF,safe_push)                              \
+     (VEC (TDEF) **vec_, TDEF obj_)                                      \
+{                                                                        \
+  if (!*vec_ || (*vec_)->num == (*vec_)->alloc)                                  \
+    VEC_OP (TDEF,reserve) (vec_, ~0u);                                   \
+                                                                         \
+  return VEC_OP (TDEF,quick_push) (*vec_, obj_);                         \
+}                                                                        \
+                                                                         \
+static inline TDEF VEC_OP (TDEF,pop)                                     \
+     (VEC (TDEF) *vec_)                                                          \
+{                                                                        \
+  TDEF obj_;                                                             \
+                                                                         \
+  VEC_ASSERT (vec_->num, "pop", TDEF);                                   \
+  obj_ = vec_->vec[--vec_->num];                                         \
+                                                                         \
+  return obj_;                                                           \
+}                                                                        \
+                                                                         \
+static inline TDEF VEC_OP (TDEF,replace)                                 \
+     (VEC (TDEF) *vec_, size_t ix_, TDEF obj_)                           \
+{                                                                        \
+  TDEF old_obj_;                                                         \
+                                                                         \
+  VEC_ASSERT (ix_ < vec_->num, "replace", TDEF);                         \
+  old_obj_ = vec_->vec[ix_];                                             \
+  vec_->vec[ix_] = obj_;                                                 \
+                                                                         \
+  return old_obj_;                                                       \
+}                                                                        \
+                                                                         \
+static inline TDEF *VEC_OP (TDEF,quick_insert)                           \
+     (VEC (TDEF) *vec_, size_t ix_, TDEF obj_)                           \
+{                                                                        \
+  TDEF *slot_;                                                           \
+                                                                         \
+  VEC_ASSERT (vec_->num < vec_->alloc, "insert", TDEF);                          \
+  VEC_ASSERT (ix_ <= vec_->num, "insert", TDEF);                         \
+  slot_ = &vec_->vec[ix_];                                               \
+  memmove (slot_ + 1, slot_, vec_->num++ - ix_);                         \
+  *slot_ = obj_;                                                         \
+                                                                         \
+  return slot_;                                                                  \
+}                                                                        \
+                                                                         \
+static inline TDEF *VEC_OP (TDEF,safe_insert)                            \
+     (VEC (TDEF) **vec_, size_t ix_, TDEF obj_)                          \
+{                                                                        \
+  if (!*vec_ || (*vec_)->num == (*vec_)->alloc)                                  \
+    VEC_OP (TDEF,reserve) (vec_, ~0u);                                   \
+                                                                         \
+  return VEC_OP (TDEF,quick_insert) (*vec_, ix_, obj_);                          \
+}                                                                        \
+                                                                         \
+static inline TDEF VEC_OP (TDEF,ordered_remove)                                  \
+     (VEC (TDEF) *vec_, size_t ix_)                                      \
+{                                                                        \
+  TDEF *slot_;                                                           \
+  TDEF obj_;                                                             \
+                                                                         \
+  VEC_ASSERT (ix_ < vec_->num, "remove", TDEF);                                  \
+  slot_ = &vec_->vec[ix_];                                               \
+  obj_ = *slot_;                                                         \
+  memmove (slot_, slot_ + 1, --vec_->num - ix_);                                 \
+                                                                         \
+  return obj_;                                                           \
+}                                                                        \
+                                                                         \
+static inline TDEF VEC_OP (TDEF,unordered_remove)                        \
+     (VEC (TDEF) *vec_, size_t ix_)                                      \
+{                                                                        \
+  TDEF *slot_;                                                           \
+  TDEF obj_;                                                             \
+                                                                         \
+  VEC_ASSERT (ix_ < vec_->num, "remove", TDEF);                                  \
+  slot_ = &vec_->vec[ix_];                                               \
+  obj_ = *slot_;                                                         \
+  *slot_ = vec_->vec[--vec_->num];                                       \
+                                                                         \
+  return obj_;                                                           \
+}                                                                        \
+                                                                         \
+struct vec_swallow_trailing_semi
+#endif
+
+/* Vector of object.  */
+#if IN_GENGTYPE
+{"DEF_VEC_O", VEC_STRINGIFY (VEC_TDEF (#)) ";", NULL},
+#else
+  
+#define DEF_VEC_O(TDEF)                                                          \
+VEC_TDEF (TDEF);                                                         \
+                                                                         \
+static inline size_t VEC_OP (TDEF,length)                                \
+     (const VEC (TDEF) *vec_)                                            \
+{                                                                        \
+  return vec_ ? vec_->num : 0;                                           \
+}                                                                        \
+                                                                         \
+static inline TDEF *VEC_OP (TDEF,last)                                   \
+     (VEC (TDEF) *vec_)                                                          \
+{                                                                        \
+  VEC_ASSERT (vec_ && vec_->num, "last", TDEF);                                  \
+                                                                         \
+  return &vec_->vec[vec_->num - 1];                                      \
+}                                                                        \
+                                                                         \
+static inline TDEF *VEC_OP (TDEF,index)                                          \
+     (VEC (TDEF) *vec_, size_t ix_)                                      \
+{                                                                        \
+  VEC_ASSERT (vec_ && ix_ < vec_->num, "index", TDEF);                   \
+                                                                         \
+  return &vec_->vec[ix_];                                                \
+}                                                                        \
+                                                                         \
+static inline TDEF *VEC_OP (TDEF,iterate)                                \
+     (VEC (TDEF) *vec_, size_t ix_)                                      \
+{                                                                        \
+  return vec_ && ix_ < vec_->num ? &vec_->vec[ix_] : NULL;               \
+}                                                                        \
+                                                                         \
+static inline VEC (TDEF) *VEC_OP (TDEF,alloc)                            \
+     (size_t alloc_)                                                     \
+{                                                                        \
+  return vec_o_reserve (NULL, alloc_ - !alloc_,                                  \
+                       offsetof (VEC(TDEF),vec), sizeof (TDEF));         \
+}                                                                        \
+                                                                         \
+static inline void *VEC_OP (TDEF,embedded_alloc)                         \
+     (size_t offset_, size_t alloc_)                                     \
+{                                                                        \
+  return vec_embedded_alloc (offset_, offsetof (VEC(TDEF),vec),                  \
+                            sizeof (TDEF), alloc_);                      \
+}                                                                        \
+                                                                         \
+static inline void VEC_OP (TDEF,reserve)                                 \
+     (VEC (TDEF) **vec_, size_t alloc_)                                          \
+{                                                                        \
+  *vec_ = vec_o_reserve (*vec_, alloc_,                                          \
+                        offsetof (VEC(TDEF),vec), sizeof (TDEF));        \
+}                                                                        \
+                                                                         \
+static inline TDEF *VEC_OP (TDEF,quick_push)                             \
+     (VEC (TDEF) *vec_, const TDEF *obj_)                                \
+{                                                                        \
+  TDEF *slot_;                                                           \
+                                                                         \
+  VEC_ASSERT (vec_->num < vec_->alloc, "push", TDEF);                    \
+  slot_ = &vec_->vec[vec_->num++];                                       \
+  if (obj_)                                                              \
+    *slot_ = *obj_;                                                      \
+                                                                         \
+  return slot_;                                                                  \
+}                                                                        \
+                                                                         \
+static inline TDEF *VEC_OP (TDEF,safe_push)                              \
+     (VEC (TDEF) **vec_, const TDEF *obj_)                               \
+{                                                                        \
+  if (!*vec_ || (*vec_)->num == (*vec_)->alloc)                                  \
+    VEC_OP (TDEF,reserve) (vec_, ~0u);                                   \
+                                                                         \
+  return VEC_OP (TDEF,quick_push) (*vec_, obj_);                         \
+}                                                                        \
+                                                                         \
+static inline void VEC_OP (TDEF,pop)                                     \
+     (VEC (TDEF) *vec_)                                                          \
+{                                                                        \
+  VEC_ASSERT (vec_->num, "pop", TDEF);                                   \
+  vec_->vec[--vec_->num];                                                \
+}                                                                        \
+                                                                         \
+static inline TDEF *VEC_OP (TDEF,replace)                                \
+     (VEC (TDEF) *vec_, size_t ix_, const TDEF *obj_)                    \
+{                                                                        \
+  TDEF *slot_;                                                           \
+                                                                         \
+  VEC_ASSERT (ix_ < vec_->num, "replace", TDEF);                         \
+  slot_ = &vec_->vec[ix_];                                               \
+  if (obj_)                                                              \
+    *slot_ = *obj_;                                                      \
+                                                                         \
+  return slot_;                                                                  \
+}                                                                        \
+                                                                         \
+static inline TDEF *VEC_OP (TDEF,quick_insert)                           \
+     (VEC (TDEF) *vec_, size_t ix_, const TDEF *obj_)                    \
+{                                                                        \
+  TDEF *slot_;                                                           \
+                                                                         \
+  VEC_ASSERT (vec_->num < vec_->alloc, "insert", TDEF);                          \
+  VEC_ASSERT (ix_ <= vec_->num, "insert", TDEF);                         \
+  slot_ = &vec_->vec[ix_];                                               \
+  memmove (slot_ + 1, slot_, vec_->num++ - ix_);                         \
+  if (obj_)                                                              \
+    *slot_ = *obj_;                                                      \
+                                                                         \
+  return slot_;                                                                  \
+}                                                                        \
+                                                                         \
+static inline TDEF *VEC_OP (TDEF,safe_insert)                            \
+     (VEC (TDEF) **vec_, size_t ix_, const TDEF *obj_)                   \
+{                                                                        \
+  if (!*vec_ || (*vec_)->num == (*vec_)->alloc)                                  \
+    VEC_OP (TDEF,reserve) (vec_, ~0u);                                   \
+                                                                         \
+  return VEC_OP (TDEF,quick_insert) (*vec_, ix_, obj_);                          \
+}                                                                        \
+                                                                         \
+static inline void VEC_OP (TDEF,ordered_remove)                                  \
+     (VEC (TDEF) *vec_, size_t ix_)                                      \
+{                                                                        \
+  TDEF *slot_;                                                           \
+                                                                         \
+  VEC_ASSERT (ix_ < vec_->num, "remove", TDEF);                                  \
+  slot_ = &vec_->vec[ix_];                                               \
+  memmove (slot_, slot_ + 1, --vec_->num - ix_);                                 \
+}                                                                        \
+                                                                         \
+static inline void VEC_OP (TDEF,unordered_remove)                        \
+     (VEC (TDEF) *vec_, size_t ix_)                                      \
+{                                                                        \
+  VEC_ASSERT (ix_ < vec_->num, "remove", TDEF);                                  \
+  vec_->vec[ix_] = vec_->vec[--vec_->num];                               \
+}                                                                        \
+                                                                         \
+struct vec_swallow_trailing_semi
+#endif
+
+#endif /* GCC_VEC_H */