From 6febecc569f42817b7b86a167a38e682317a6c2c Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 25 Mar 1999 03:49:34 +0000 Subject: [PATCH] Clean up att_align calculations so that XXXALIGN macros need not be bogus. --- src/backend/bootstrap/bootstrap.c | 26 +++++++++-- src/include/access/tupmacs.h | 47 ++++++-------------- src/include/catalog/pg_type.h | 81 ++++++++++++++++++----------------- src/include/postgres.h | 9 +++- src/include/utils/memutils.h | 90 ++++++++++++++------------------------- 5 files changed, 117 insertions(+), 136 deletions(-) diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index eacb0129f6..c4cb0df1c5 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -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; diff --git a/src/include/access/tupmacs.h b/src/include/access/tupmacs.h index c9cb759221..6dd499c60b 100644 --- a/src/include/access/tupmacs.h +++ b/src/include/access/tupmacs.h @@ -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 $ * *------------------------------------------------------------------------- */ @@ -62,43 +62,22 @@ (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) ? \ diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index a185a1912d..2abfa64303 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -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 */ diff --git a/src/include/postgres.h b/src/include/postgres.h index ed625cd07d..ab57059295 100644 --- a/src/include/postgres.h +++ b/src/include/postgres.h @@ -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; diff --git a/src/include/utils/memutils.h b/src/include/utils/memutils.h index 2d25f2ebdc..58db49693e 100644 --- a/src/include/utils/memutils.h +++ b/src/include/utils/memutils.h @@ -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 @@ -27,76 +27,52 @@ #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 /***************************************************************************** -- 2.11.0