Clean up att_align calculations so that XXXALIGN macros
authorTom Lane
Thu, 25 Mar 1999 03:49:34 +0000 (03:49 +0000)
committerTom Lane
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 eacb0129f6b6fd17f7dc654d8c280814eee884a3..c4cb0df1c569979b5bb47e500dd5cdf2d5318b6a 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 c9cb759221bf353bf0f0c23742861e0324cfd25d..6dd499c60b98167f0d9bc8db26d7a76739e5f4f1 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 a185a1912d47b1372f525016837d636cd4fb6dda..2abfa643032bab26b3e9b9e28e1206e52ce84d72 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 
 
 /* ----------------
- *     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 ed625cd07d0863fa63de634dc3a0e3a329d461cb..ab57059295f081fab5da4edcfc4a218e2b091fd5 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 2d25f2ebdc9ba865071a3964602640e2b8d04529..58db49693ee721206436f52649b997da44d5a04e 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
 
 /*****************************************************************************