+2003-10-18 Richard Sandiford <rsandifo@redhat.com>
+
+ * rtl.h (rtl_size): Declare.
+ (rtunion): Remove rtwint.
+ (rtx_def): Replace 'fld' with a union of an rtunion or a HOST_WIDE_INT.
+ (RTX_HDR_SIZE, RTX_SIZE): New macros.
+ (RTL_CHECK1): Adjust for new rtx_def layout.
+ (RTL_CHECK2, RTL_CHECKC1, RTL_CHECKC2): Likewise.
+ (XWINT, XCWINT): Likewise. Access the rtx structure directly.
+ (X0WINT): Remove.
+ (X0ANY): New macro.
+ * rtl.def: Adjust comments for new rtx_def layout.
+ * ggc.h (ggc_alloc_rtx): Take the rtx code as argument, not the
+ number of slots.
+ * rtl.c (rtx_size): New array.
+ (rtx_alloc): Adjust call to ggc_alloc_rtx. Use RTX_HDR_SIZE.
+ (copy_rtx): Use RTX_HDR_SIZE. Adjust for new rtx_def layout.
+ (shallow_copy_rtx): Adjust call to ggc_alloc_rtx. Use RTX_SIZE.
+ * integrate.c (copy_rtx_and_substitute): Use X0ANY to copy '0' fields.
+ * emit-rtl.c (copy_most_rtx): Likewise.
+ (copy_rtx_if_shared): Use RTX_SIZE.
+ (copy_insn_1): Use RTX_HDR_SIZE. Adjust for new rtx_def layout.
+ * gengenrtl.c (gendef): Adjust ggc_alloc_rtx call. Use RTX_HDR_SIZE.
+ * gengtype.c (write_rtx_next): Use RTX_HDR_SIZE.
+ (adjust_field_rtx_def): Expect "rtx_def" to be a union rather than
+ an array. Adjust output for new rtx_def layout.
+ * ggc-page.c (RTL_SIZE): Use RTX_HDR_SIZE.
+ * reload1.c (eliminate_regs): Use RTX_SIZE.
+ * rtlanal.c (loc_mentioned_in_p): Adjust for new rtx_def layout.
+ * gdbinit.in (pi): Likewise.
+
2003-10-18 Jan Hubicka <jh@suse.cz>
* integrate.c (copy_decl_for_inlining): Fix copying of copies.
break;
case '0':
- /* Copy this through the wide int field; that's safest. */
- X0WINT (copy, i) = X0WINT (orig, i);
+ X0ANY (copy, i) = X0ANY (orig, i);
break;
default:
rtx copy;
copy = rtx_alloc (code);
- memcpy (copy, x,
- (sizeof (*copy) - sizeof (copy->fld)
- + sizeof (copy->fld[0]) * GET_RTX_LENGTH (code)));
+ memcpy (copy, x, RTX_SIZE (code));
x = copy;
copied = 1;
}
all fields need copying, and then clear the fields that should
not be copied. That is the sensible default behavior, and forces
us to explicitly document why we are *not* copying a flag. */
- memcpy (copy, orig, sizeof (struct rtx_def) - sizeof (rtunion));
+ memcpy (copy, orig, RTX_HDR_SIZE);
/* We do not copy the USED flag, which is used as a mark bit during
walks over the RTL. */
for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
{
- copy->fld[i] = orig->fld[i];
+ copy->u.fld[i] = orig->u.fld[i];
switch (*format_ptr++)
{
case 'e':
end
define pi
-print $.fld[0].rtx@7
+print $.u.fld[0].rtx@7
end
document pi
the memory and initializes it. */
puts ("{");
puts (" rtx rt;");
- printf (" rt = ggc_alloc_rtx (%d);\n", (int) strlen (format));
+ puts (" rt = ggc_alloc_rtx (code);\n");
- puts (" memset (rt, 0, sizeof (struct rtx_def) - sizeof (rtunion));\n");
+ puts (" memset (rt, 0, RTX_HDR_SIZE);\n");
puts (" PUT_CODE (rt, code);");
puts (" PUT_MODE (rt, mode);");
oprintf (f, " 0,\n");
else
oprintf (f,
- " offsetof (struct rtx_def, fld) + %d * sizeof (rtunion),\n",
+ " RTX_HDR_SIZE + %d * sizeof (rtunion),\n",
rtx_next_new[i]);
oprintf (f, "};\n");
}
#undef DEF_RTL_EXPR
};
- if (t->kind != TYPE_ARRAY)
+ if (t->kind != TYPE_UNION)
{
error_at_line (&lexer_line,
- "special `rtx_def' must be applied to an array");
+ "special `rtx_def' must be applied to a union");
return &string_type;
}
subfields = xmalloc (sizeof (*subfields));
subfields->next = old_subf;
subfields->type = t;
- subfields->name = xasprintf ("[%lu].%s", (unsigned long)aindex,
+ subfields->name = xasprintf (".fld[%lu].%s", (unsigned long)aindex,
subname);
subfields->line.file = __FILE__;
subfields->line.line = __LINE__;
#define NUM_EXTRA_ORDERS ARRAY_SIZE (extra_order_size_table)
#define RTL_SIZE(NSLOTS) \
- (sizeof (struct rtx_def) + ((NSLOTS) - 1) * sizeof (rtunion))
+ (RTX_HDR_SIZE + (NSLOTS) * sizeof (rtunion))
#define TREE_EXP_SIZE(OPS) \
(sizeof (struct tree_exp) + ((OPS) - 1) * sizeof (tree))
/* Like ggc_alloc_cleared, but performs a multiplication. */
extern void *ggc_calloc (size_t, size_t);
-#define ggc_alloc_rtx(NSLOTS) \
- ((rtx) ggc_alloc (sizeof (struct rtx_def) \
- + ((NSLOTS) - 1) * sizeof (rtunion)))
+#define ggc_alloc_rtx(CODE) ((rtx) ggc_alloc (RTX_SIZE (CODE)))
#define ggc_alloc_rtvec(NELT) \
((rtvec) ggc_alloc (sizeof (struct rtvec_def) \
switch (*format_ptr++)
{
case '0':
- /* Copy this through the wide int field; that's safest. */
- X0WINT (copy, i) = X0WINT (orig, i);
+ X0ANY (copy, i) = X0ANY (orig, i);
break;
case 'e':
if (new != XEXP (x, i) && ! copied)
{
rtx new_x = rtx_alloc (code);
- memcpy (new_x, x,
- (sizeof (*new_x) - sizeof (new_x->fld)
- + sizeof (new_x->fld[0]) * GET_RTX_LENGTH (code)));
+ memcpy (new_x, x, RTX_SIZE (code));
x = new_x;
copied = 1;
}
if (! copied)
{
rtx new_x = rtx_alloc (code);
- memcpy (new_x, x,
- (sizeof (*new_x) - sizeof (new_x->fld)
- + (sizeof (new_x->fld[0])
- * GET_RTX_LENGTH (code))));
+ memcpy (new_x, x, RTX_SIZE (code));
x = new_x;
copied = 1;
}
#undef DEF_RTL_EXPR
};
+/* Indexed by rtx code, gives the size of the rtx in bytes. */
+
+const unsigned char rtx_size[NUM_RTX_CODE] = {
+#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) \
+ ((ENUM) == CONST_INT || (ENUM) == CONST_DOUBLE \
+ ? RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (HOST_WIDE_INT) \
+ : RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (rtunion)),
+
+#include "rtl.def"
+#undef DEF_RTL_EXPR
+};
+
/* Names for kinds of NOTEs and REG_NOTEs. */
const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS] =
rtx_alloc (RTX_CODE code)
{
rtx rt;
- int n = GET_RTX_LENGTH (code);
- rt = ggc_alloc_rtx (n);
+ rt = ggc_alloc_rtx (code);
/* We want to clear everything up to the FLD array. Normally, this
is one int, but we don't want to assume that and it isn't very
portable anyway; this is. */
- memset (rt, 0, sizeof (struct rtx_def) - sizeof (rtunion));
+ memset (rt, 0, RTX_HDR_SIZE);
PUT_CODE (rt, code);
return rt;
}
all fields need copying, and then clear the fields that should
not be copied. That is the sensible default behavior, and forces
us to explicitly document why we are *not* copying a flag. */
- memcpy (copy, orig, sizeof (struct rtx_def) - sizeof (rtunion));
+ memcpy (copy, orig, RTX_HDR_SIZE);
/* We do not copy the USED flag, which is used as a mark bit during
walks over the RTL. */
for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
{
- copy->fld[i] = orig->fld[i];
+ copy->u.fld[i] = orig->u.fld[i];
switch (*format_ptr++)
{
case 'e':
rtx
shallow_copy_rtx (rtx orig)
{
- RTX_CODE code = GET_CODE (orig);
- size_t n = GET_RTX_LENGTH (code);
- rtx copy = ggc_alloc_rtx (n);
-
- memcpy (copy, orig,
- sizeof (struct rtx_def) + sizeof (rtunion) * (n - 1));
+ rtx copy;
+ copy = ggc_alloc_rtx (GET_CODE (orig));
+ memcpy (copy, orig, RTX_SIZE (GET_CODE (orig)));
return copy;
}
\f
These names are stored in rtx_name[].
By convention these are the internal (field 1) names in lower_case.
- 3. The print format, and type of each rtx->fld[] (field) in this rtx.
+ 3. The print format, and type of each rtx->u.fld[] (field) in this rtx.
These formats are stored in rtx_format[].
The meaning of the formats is documented in front of this array in rtl.c
All formats must start with "iuu" to handle the chain.
Each insn expression holds an rtl instruction and its semantics
during back-end processing.
- See macros's in "rtl.h" for the meaning of each rtx->fld[].
+ See macros's in "rtl.h" for the meaning of each rtx->u.fld[].
---------------------------------------------------------------------- */
DEF_RTL_EXPR(INSN, "insn", "iuuBieiee", 'i')
/* An instruction that can possibly jump.
- Fields ( rtx->fld[] ) have exact same meaning as INSN's. */
+ Fields ( rtx->u.fld[] ) have exact same meaning as INSN's. */
DEF_RTL_EXPR(JUMP_INSN, "jump_insn", "iuuBieiee0", 'i')
/* An instruction that can possibly call a subroutine
but which will not change which instruction comes next
in the current function.
- Field ( rtx->fld[9] ) is CALL_INSN_FUNCTION_USAGE.
- All other fields ( rtx->fld[] ) have exact same meaning as INSN's. */
+ Field ( rtx->u.fld[9] ) is CALL_INSN_FUNCTION_USAGE.
+ All other fields ( rtx->u.fld[] ) have exact same meaning as INSN's. */
DEF_RTL_EXPR(CALL_INSN, "call_insn", "iuuBieieee", 'i')
/* A marker that indicates that control will not flow through. */
extern const char rtx_class[NUM_RTX_CODE];
#define GET_RTX_CLASS(CODE) (rtx_class[(int) (CODE)])
+extern const unsigned char rtx_size[NUM_RTX_CODE];
extern const unsigned char rtx_next[NUM_RTX_CODE];
\f
/* The flags and bitfields of an ADDR_DIFF_VEC. BASE is the base label
union rtunion_def
{
- HOST_WIDE_INT rtwint;
int rtint;
unsigned int rtuint;
const char *rtstr;
/* The first element of the operands of this rtx.
The number of operands and their types are controlled
by the `code' field, according to rtl.def. */
- rtunion GTY ((special ("rtx_def"),
- desc ("GET_CODE (&%0)"))) fld[1];
+ union u {
+ rtunion fld[1];
+ HOST_WIDE_INT hwint[1];
+ } GTY ((special ("rtx_def"), desc ("GET_CODE (&%0)"))) u;
};
+/* The size in bytes of an rtx header (code, mode and flags). */
+#define RTX_HDR_SIZE offsetof (struct rtx_def, u)
+
+/* The size in bytes of an rtx with code CODE. */
+#define RTX_SIZE(CODE) rtx_size[CODE]
+
#define NULL_RTX (rtx) 0
/* The "next" and "previous" RTX, relative to this one. */
if (GET_RTX_FORMAT(_code)[_n] != C1) \
rtl_check_failed_type1 (_rtx, _n, C1, __FILE__, __LINE__, \
__FUNCTION__); \
- &_rtx->fld[_n]; }))
+ &_rtx->u.fld[_n]; }))
#define RTL_CHECK2(RTX, N, C1, C2) __extension__ \
(*({ rtx const _rtx = (RTX); const int _n = (N); \
&& GET_RTX_FORMAT(_code)[_n] != C2) \
rtl_check_failed_type2 (_rtx, _n, C1, C2, __FILE__, __LINE__, \
__FUNCTION__); \
- &_rtx->fld[_n]; }))
+ &_rtx->u.fld[_n]; }))
#define RTL_CHECKC1(RTX, N, C) __extension__ \
(*({ rtx const _rtx = (RTX); const int _n = (N); \
if (GET_CODE (_rtx) != (C)) \
rtl_check_failed_code1 (_rtx, (C), __FILE__, __LINE__, \
__FUNCTION__); \
- &_rtx->fld[_n]; }))
+ &_rtx->u.fld[_n]; }))
#define RTL_CHECKC2(RTX, N, C1, C2) __extension__ \
(*({ rtx const _rtx = (RTX); const int _n = (N); \
if (_code != (C1) && _code != (C2)) \
rtl_check_failed_code2 (_rtx, (C1), (C2), __FILE__, __LINE__, \
__FUNCTION__); \
- &_rtx->fld[_n]; }))
+ &_rtx->u.fld[_n]; }))
#define RTVEC_ELT(RTVEC, I) __extension__ \
(*({ rtvec const _rtvec = (RTVEC); const int _i = (I); \
__FUNCTION__); \
&_rtvec->elem[_i]; }))
+#define XWINT(RTX, N) __extension__ \
+(*({ rtx const _rtx = (RTX); const int _n = (N); \
+ const enum rtx_code _code = GET_CODE (_rtx); \
+ if (_n < 0 || _n >= GET_RTX_LENGTH (_code)) \
+ rtl_check_failed_bounds (_rtx, _n, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ if (GET_RTX_FORMAT(_code)[_n] != 'w') \
+ rtl_check_failed_type1 (_rtx, _n, 'w', __FILE__, __LINE__, \
+ __FUNCTION__); \
+ &_rtx->u.hwint[_n]; }))
+
+#define XCWINT(RTX, N, C) __extension__ \
+(*({ rtx const _rtx = (RTX); \
+ if (GET_CODE (_rtx) != (C)) \
+ rtl_check_failed_code1 (_rtx, (C), __FILE__, __LINE__, \
+ __FUNCTION__); \
+ &_rtx->u.hwint[N]; }))
+
extern void rtl_check_failed_bounds (rtx, int, const char *, int,
const char *)
ATTRIBUTE_NORETURN;
#else /* not ENABLE_RTL_CHECKING */
-#define RTL_CHECK1(RTX, N, C1) ((RTX)->fld[N])
-#define RTL_CHECK2(RTX, N, C1, C2) ((RTX)->fld[N])
-#define RTL_CHECKC1(RTX, N, C) ((RTX)->fld[N])
-#define RTL_CHECKC2(RTX, N, C1, C2) ((RTX)->fld[N])
+#define RTL_CHECK1(RTX, N, C1) ((RTX)->u.fld[N])
+#define RTL_CHECK2(RTX, N, C1, C2) ((RTX)->u.fld[N])
+#define RTL_CHECKC1(RTX, N, C) ((RTX)->u.fld[N])
+#define RTL_CHECKC2(RTX, N, C1, C2) ((RTX)->u.fld[N])
#define RTVEC_ELT(RTVEC, I) ((RTVEC)->elem[I])
+#define XWINT(RTX, N) ((RTX)->u.hwint[N])
+#define XCWINT(RTX, N, C) ((RTX)->u.hwint[N])
#endif
_rtx->volatil = 0; \
} while (0)
-#define XWINT(RTX, N) (RTL_CHECK1 (RTX, N, 'w').rtwint)
#define XINT(RTX, N) (RTL_CHECK2 (RTX, N, 'i', 'n').rtint)
#define XSTR(RTX, N) (RTL_CHECK2 (RTX, N, 's', 'S').rtstr)
#define XEXP(RTX, N) (RTL_CHECK2 (RTX, N, 'e', 'u').rtx)
#define XVECEXP(RTX, N, M) RTVEC_ELT (XVEC (RTX, N), M)
#define XVECLEN(RTX, N) GET_NUM_ELEM (XVEC (RTX, N))
-/* These are like XWINT, etc. except that they expect a '0' field instead
+/* These are like XINT, etc. except that they expect a '0' field instead
of the normal type code. */
-#define X0WINT(RTX, N) (RTL_CHECK1 (RTX, N, '0').rtwint)
#define X0INT(RTX, N) (RTL_CHECK1 (RTX, N, '0').rtint)
#define X0UINT(RTX, N) (RTL_CHECK1 (RTX, N, '0').rtuint)
#define X0STR(RTX, N) (RTL_CHECK1 (RTX, N, '0').rtstr)
#define X0MEMATTR(RTX, N) (RTL_CHECKC1 (RTX, N, MEM).rtmem)
#define X0REGATTR(RTX, N) (RTL_CHECKC1 (RTX, N, REG).rtreg)
-#define XCWINT(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rtwint)
+/* Access a '0' field with any type. */
+#define X0ANY(RTX, N) RTL_CHECK1 (RTX, N, '0')
+
#define XCINT(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rtint)
#define XCUINT(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rtuint)
#define XCSTR(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rtstr)
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
- if (loc == &in->fld[i].rtx)
+ if (loc == &in->u.fld[i].rtx)
return 1;
if (fmt[i] == 'e')
{