OSDN Git Service

Clean up att_align calculations so that XXXALIGN macros
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 25 Mar 1999 03:49:34 +0000 (03:49 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 25 Mar 1999 03:49:34 +0000 (03:49 +0000)
need not be bogus.

src/backend/bootstrap/bootstrap.c
src/include/access/tupmacs.h
src/include/catalog/pg_type.h
src/include/postgres.h
src/include/utils/memutils.h

index eacb012..c4cb0df 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.56 1999/03/17 22:52:45 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.57 1999/03/25 03:49:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -605,8 +605,28 @@ DefineAttr(char *name, char *type, int attnum)
                        printf("<%s %s> ", attrtypes[attnum]->attname.data, type);
                attrtypes[attnum]->attnum = 1 + attnum; /* fillatt */
                attlen = attrtypes[attnum]->attlen = Procid[typeoid].len;
-               attrtypes[attnum]->attbyval = (attlen == 1) || (attlen == 2) || (attlen == 4);
-               attrtypes[attnum]->attalign = 'i';
+               /* Cheat like mad to fill in these items from the length only.
+                * This only has to work for types used in the system catalogs...
+                */
+               switch (attlen)
+               {
+                       case 1:
+                               attrtypes[attnum]->attbyval = true;
+                               attrtypes[attnum]->attalign = 'c';
+                               break;
+                       case 2:
+                               attrtypes[attnum]->attbyval = true;
+                               attrtypes[attnum]->attalign = 's';
+                               break;
+                       case 4:
+                               attrtypes[attnum]->attbyval = true;
+                               attrtypes[attnum]->attalign = 'i';
+                               break;
+                       default:
+                               attrtypes[attnum]->attbyval = false;
+                               attrtypes[attnum]->attalign = 'i';
+                               break;
+               }
        }
        attrtypes[attnum]->attcacheoff = -1;
        attrtypes[attnum]->atttypmod = -1;
index c9cb759..6dd499c 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: tupmacs.h,v 1.8 1999/02/13 23:20:59 momjian Exp $
+ * $Id: tupmacs.h,v 1.9 1999/03/25 03:49:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
        (char *) (T) \
 )
 
+/* att_align aligns the given offset as needed for a datum of length attlen
+ * and alignment requirement attalign.  In practice we don't need the length.
+ * The attalign cases are tested in what is hopefully something like their
+ * frequency of occurrence.
+ */
 #define att_align(cur_offset, attlen, attalign) \
 ( \
-       ((attlen) < sizeof(int32)) ? \
-       ( \
-               ((attlen) == -1) ? \
-               ( \
-                       ((attalign) == 'd') ?   DOUBLEALIGN(cur_offset) : \
-                                                                       INTALIGN(cur_offset) \
-               ) \
-               : \
-               ( \
-                       ((attlen) == sizeof(char)) ? \
-                       ( \
-                               (long)(cur_offset) \
-                       ) \
-                       : \
-                       ( \
-                               AssertMacro((attlen) == sizeof(short)), \
-                               SHORTALIGN(cur_offset) \
-                       ) \
-               ) \
-       ) \
-       : \
-       ( \
-               ((attlen) == sizeof(int32)) ? \
-               ( \
-                       INTALIGN(cur_offset) \
-               ) \
-               : \
+       ((attalign) == 'i') ? INTALIGN(cur_offset) : \
+        (((attalign) == 'c') ? ((long)(cur_offset)) : \
+         (((attalign) == 'd') ? DOUBLEALIGN(cur_offset) : \
                ( \
-                       AssertMacro((attlen) > sizeof(int32)), \
-                       ((attalign) == 'd') ?   DOUBLEALIGN(cur_offset) : \
-                                                                       LONGALIGN(cur_offset) \
-               ) \
-       ) \
+                       AssertMacro((attalign) == 's'), \
+                       SHORTALIGN(cur_offset) \
+               ))) \
 )
-       
+
 #define att_addlength(cur_offset, attlen, attval) \
 ( \
        ((attlen) != -1) ? \
index a185a19..2abfa64 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_type.h,v 1.55 1999/03/10 05:02:34 tgl Exp $
+ * $Id: pg_type.h,v 1.56 1999/03/25 03:49:25 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -21,7 +21,7 @@
 #include <utils/rel.h>
 
 /* ----------------
- *             postgres.h contains the system type definintions and the
+ *             postgres.h contains the system type definitions and the
  *             CATALOG(), BOOTSTRAP and DATA() sugar words so this file
  *             can be read by both genbki.sh and the C compiler.
  * ----------------
@@ -53,36 +53,30 @@ CATALOG(pg_type) BOOTSTRAP
 
        /*
         * typbyval determines whether internal Postgres routines pass a value
-        * of this type by value or by reference.  Postgres uses a 4 byte area
-        * for passing a field value info, so if the value is not 1, 2, or 4
-        * bytes long, Postgres does not have the option of passing by value
-        * and ignores typbyval.
-        *
-        * (I don't understand why this column exists.  The above description may
-        * be an oversimplification.  Also, there appear to be bugs in which
-        * Postgres doesn't ignore typbyval when it should, but I'm afraid to
-        * change them until I see proof of damage. -BRYANH 96.08).
-        *
-        * (Postgres crashes if typbyval is true, the declared length is 8, and
-        * the I/O routines are written to expect pass by reference. Note that
-        * float4 is written for pass by reference and has a declared length
-        * of 4 bytes, so it looks like pass by reference must be consistant
-        * with the declared length, and typbyval is used somewhere. - tgl
-        * 1997-03-20).
+        * of this type by value or by reference.  Only char, short, and int-
+        * equivalent items can be passed by value, so if the type is not
+        * 1, 2, or 4 bytes long, Postgres does not have the option of passing
+        * by value and so typbyval had better be FALSE.  Variable-length types
+        * are always passed by reference.
+        * Note that typbyval can be false even if the length would allow
+        * pass-by-value; this is currently true for type float4, for example.
         */
        char            typtype;
+
+       /*
+        * typtype is 'b' for a basic type and 'c' for a catalog type (ie a class).
+        * If typtype is 'c', typrelid is the OID of the class' entry in pg_class.
+        * (Why do we need an entry in pg_type for classes, anyway?)
+        */
        bool            typisdefined;
        char            typdelim;
-       Oid                     typrelid;
+       Oid                     typrelid;               /* 0 if not a class type */
        Oid                     typelem;
 
        /*
-        * typelem is NULL if this is not an array type.  If this is an array
+        * typelem is 0 if this is not an array type.  If this is an array
         * type, typelem is the OID of the type of the elements of the array
         * (it identifies another row in Table pg_type).
-        *
-        * (Note that zero ("0") rather than _null_ is used in the declarations.
-        * - tgl 97/03/20)
         */
        regproc         typinput;
        regproc         typoutput;
@@ -90,7 +84,7 @@ CATALOG(pg_type) BOOTSTRAP
        regproc         typsend;
        char            typalign;
 
-       /*
+       /* ----------------
         * typalign is the alignment required when storing a value of this
         * type.  It applies to storage on disk as well as most
         * representations of the value inside Postgres.  When multiple values
@@ -99,11 +93,18 @@ CATALOG(pg_type) BOOTSTRAP
         * type so that it begins on the specified boundary.  The alignment
         * reference is the beginning of the first datum in the sequence.
         *
-        * 'c' = 1 byte alignment. 's' = 2 byte alignment. 'i' = 4 byte
-        * alignment. 'd' = 8 byte alignment.
+        * 'c' = CHAR alignment, ie no alignment needed.
+        * 's' = SHORT alignment (2 bytes on most machines).
+        * 'i' = INT alignment (4 bytes on most machines).
+        * 'd' = DOUBLE alignment (8 bytes on many machines, but by no means all).
+        *
+        * See include/utils/memutils.h for the macros that compute these
+        * alignment requirements.
         *
-        * (This might actually be flexible depending on machine architecture,
-        * but I doubt it - BRYANH 96.08).
+        * NOTE: for types used in system tables, it is critical that the
+        * size and alignment defined in pg_type agree with the way that the
+        * compiler will lay out the field in a struct representing a table row.
+        * ----------------
         */
        text            typdefault;             /* VARIABLE LENGTH FIELD */
 } FormData_pg_type;
@@ -218,21 +219,21 @@ DESCR("array of 8 oid, used in system tables");
 DATA(insert OID = 32 ( SET                PGUID -1  -1 f r t \054 0  -1 textin textout textin textout i _null_ ));
 DESCR("set of tuples");
 
-DATA(insert OID = 71 ( pg_type          PGUID -1 -1 t b t \054 1247 0 foo bar foo bar c _null_));
-DATA(insert OID = 75 ( pg_attribute PGUID -1 -1 t b t \054 1249 0 foo bar foo bar c _null_));
-DATA(insert OID = 81 ( pg_proc          PGUID -1 -1 t b t \054 1255 0 foo bar foo bar c _null_));
-DATA(insert OID = 83 ( pg_class         PGUID -1 -1 t b t \054 1259 0 foo bar foo bar c _null_));
-DATA(insert OID = 86 ( pg_shadow        PGUID -1 -1 t b t \054 1260 0 foo bar foo bar c _null_));
-DATA(insert OID = 87 ( pg_group         PGUID -1 -1 t b t \054 1261 0 foo bar foo bar c _null_));
-DATA(insert OID = 88 ( pg_database  PGUID -1 -1 t b t \054 1262 0 foo bar foo bar c _null_));
-DATA(insert OID = 90 ( pg_variable  PGUID -1 -1 t b t \054 1264 0 foo bar foo bar c _null_));
-DATA(insert OID = 99 ( pg_log           PGUID -1 -1 t b t \054 1269 0 foo bar foo bar c _null_));
+DATA(insert OID = 71 ( pg_type          PGUID 4 4 t c t \054 1247 0 foo bar foo bar i _null_));
+DATA(insert OID = 75 ( pg_attribute PGUID 4 4 t c t \054 1249 0 foo bar foo bar i _null_));
+DATA(insert OID = 81 ( pg_proc          PGUID 4 4 t c t \054 1255 0 foo bar foo bar i _null_));
+DATA(insert OID = 83 ( pg_class         PGUID 4 4 t c t \054 1259 0 foo bar foo bar i _null_));
+DATA(insert OID = 86 ( pg_shadow        PGUID 4 4 t c t \054 1260 0 foo bar foo bar i _null_));
+DATA(insert OID = 87 ( pg_group         PGUID 4 4 t c t \054 1261 0 foo bar foo bar i _null_));
+DATA(insert OID = 88 ( pg_database  PGUID 4 4 t c t \054 1262 0 foo bar foo bar i _null_));
+DATA(insert OID = 90 ( pg_variable  PGUID 4 4 t c t \054 1264 0 foo bar foo bar i _null_));
+DATA(insert OID = 99 ( pg_log           PGUID 4 4 t c t \054 1269 0 foo bar foo bar i _null_));
 
 /* OIDS 100 - 199 */
 
-DATA(insert OID = 109 (  pg_attrdef  PGUID -1 -1 t b t \054 1215 0 foo bar foo bar c _null_));
-DATA(insert OID = 110 (  pg_relcheck PGUID -1 -1 t b t \054 1216 0 foo bar foo bar c _null_));
-DATA(insert OID = 111 (  pg_trigger  PGUID -1 -1 t b t \054 1219 0 foo bar foo bar c _null_));
+DATA(insert OID = 109 (  pg_attrdef  PGUID 4 4 t c t \054 1215 0 foo bar foo bar i _null_));
+DATA(insert OID = 110 (  pg_relcheck PGUID 4 4 t c t \054 1216 0 foo bar foo bar i _null_));
+DATA(insert OID = 111 (  pg_trigger  PGUID 4 4 t c t \054 1219 0 foo bar foo bar i _null_));
 
 /* OIDS 200 - 299 */
 
index ed625cd..ab57059 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1995, Regents of the University of California
  *
- * $Id: postgres.h,v 1.20 1999/02/13 23:20:46 momjian Exp $
+ * $Id: postgres.h,v 1.21 1999/03/25 03:49:28 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -92,9 +92,14 @@ typedef struct varlena text;
 typedef int2 int28[8];
 typedef Oid oid8[8];
 
-typedef struct nameData
+/* We want NameData to have length NAMEDATALEN and int alignment,
+ * because that's how the data type 'name' is defined in pg_type.
+ * Use a union to make sure the compiler agrees.
+ */
+typedef union nameData
 {
        char            data[NAMEDATALEN];
+       int                     alignmentDummy;
 } NameData;
 typedef NameData *Name;
 
index 2d25f2e..58db496 100644 (file)
@@ -15,7 +15,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: memutils.h,v 1.21 1999/02/13 23:22:25 momjian Exp $
+ * $Id: memutils.h,v 1.22 1999/03/25 03:49:34 tgl Exp $
  *
  * NOTES
  *       some of the information in this file will be moved to
 #define MEMUTILS_H
 
 
-#ifdef NOT_USED
-/*****************************************************************************
- *             align.h                 - alignment macros                                                                       *
- ****************************************************************************
- [TRH] Let the compiler decide what alignment it uses instead of
-tending
-   we know better.
-   GCC (at least v2.5.8 and up) has an __alignof__ keyword.
-   However, we cannot use it here since on some architectures it reports
-   just a _recommended_ alignment instead of the actual alignment used in
-   padding structures (or at least, this is how I understand gcc).
-   So define a macro that gives us the _actual_ alignment inside a struct.
-   {{note: assumes that alignment size is always a power of 2.}}
+/* ----------------
+ * Alignment macros: align a length or address appropriately for a given type.
+ *
+ * It'd be best to use offsetof to check how the compiler aligns stuff,
+ * but not all compilers support that (still true)?  So we make the
+ * conservative assumption that a type must be aligned on a boundary equal
+ * to its own size, except on a few architectures where we know better.
+ *
+ * CAUTION: for the system tables, the struct declarations found in
+ * src/include/pg_*.h had better be interpreted by the compiler in a way
+ * that agrees with the workings of these macros.  In practice that means
+ * being careful to lay out the columns of a system table in a way that avoids
+ * wasted pad space.
+ *
+ * CAUTION: _ALIGN will not work if sizeof(TYPE) is not a power of 2.
+ * There are machines where sizeof(double) is not, for example.
+ * But such a size is almost certainly not an alignment boundary anyway.
+ * ----------------
  */
-#define _ALIGNSIZE(TYPE)               offsetof(struct { char __c; TYPE __t;}, __t)
-#define _ALIGN(TYPE, LEN) \
-               (((long)(LEN) + (_ALIGNSIZE(TYPE) - 1)) & ~(_ALIGNSIZE(TYPE) - 1))
-#define SHORTALIGN(LEN)                        _ALIGN(short, (LEN))
-#define INTALIGN(LEN)                  _ALIGN(int, (LEN))
-#define LONGALIGN(LEN)                 _ALIGN(long, (LEN))
-#define DOUBLEALIGN(LEN)               _ALIGN(double, (LEN))
-#define MAXALIGN(LEN)                  _ALIGN(double, (LEN))
 
-#endif  /* 0 */
+#define _ALIGN(TYPE,LEN) \
+               (((long)(LEN) + (sizeof(TYPE) - 1)) & ~(sizeof(TYPE) - 1))
 
-/*
- *             SHORTALIGN(LEN) - length (or address) aligned for shorts
- */
-#define SHORTALIGN(LEN)\
-               (((long)(LEN) + (sizeof (short) - 1)) & ~(sizeof (short) - 1))
+#define SHORTALIGN(LEN)                        _ALIGN(short, (LEN))
 
 #if defined(m68k)
-#define INTALIGN(LEN)   SHORTALIGN(LEN)
+#define INTALIGN(LEN)                  _ALIGN(short, (LEN))
 #else
-#define INTALIGN(LEN)\
-               (((long)(LEN) + (sizeof (int) - 1)) & ~(sizeof (int) -1))
+#define INTALIGN(LEN)                  _ALIGN(int, (LEN))
 #endif
 
-/*
- *             LONGALIGN(LEN)  - length (or address) aligned for longs
- */
 #if (defined(sun) && ! defined(sparc)) || defined(m68k)
-#define LONGALIGN(LEN) SHORTALIGN(LEN)
-#elif defined (__alpha)
-
- /*
-  * even though "long alignment" should really be on 8-byte boundaries for
-  * linuxalpha, we want the strictest alignment to be on 4-byte (int)
-  * boundaries, because otherwise things break when they try to use the
-  * FormData_pg_* structures.  --djm 12/12/96
-  */
-#define LONGALIGN(LEN)\
-               (((long)(LEN) + (sizeof (int) - 1)) & ~(sizeof (int) -1))
+#define LONGALIGN(LEN)                 _ALIGN(short, (LEN))
 #else
-#define LONGALIGN(LEN)\
-               (((long)(LEN) + (sizeof (long) - 1)) & ~(sizeof (long) -1))
+#define LONGALIGN(LEN)                 _ALIGN(long, (LEN))
 #endif
 
 #if defined(m68k)
-#define DOUBLEALIGN(LEN) SHORTALIGN(LEN)
-#define MAXALIGN(LEN)   SHORTALIGN(LEN)
-#elif ! defined(sco)
-#define DOUBLEALIGN(LEN)\
-               (((long)(LEN) + (sizeof (double) - 1)) & ~(sizeof (double) -1))
-
-#define MAXALIGN(LEN)\
-               (((long)(LEN) + (sizeof (double) - 1)) & ~(sizeof (double) -1))
+#define DOUBLEALIGN(LEN)               _ALIGN(short, (LEN))
+#define MAXALIGN(LEN)                  _ALIGN(short, (LEN))
+#elif defined(sco)
+#define DOUBLEALIGN(LEN)               _ALIGN(int, (LEN))
+#define MAXALIGN(LEN)                  _ALIGN(int, (LEN))
 #else
-#define DOUBLEALIGN(LEN) INTALIGN(LEN)
-#define MAXALIGN(LEN)   INTALIGN(LEN)
+#define DOUBLEALIGN(LEN)               _ALIGN(double, (LEN))
+#define MAXALIGN(LEN)                  _ALIGN(double, (LEN))
 #endif
 
 /*****************************************************************************