+#define PROCESS_ARG(N) \
+ do { \
+ TREE_OPERAND (t, N) = arg##N; \
+ if (arg##N &&!TYPE_P (arg##N) && fro > N) \
+ { \
+ if (TREE_SIDE_EFFECTS (arg##N)) \
+ side_effects = 1; \
+ if (!TREE_READONLY (arg##N)) \
+ read_only = 0; \
+ if (!TREE_CONSTANT (arg##N)) \
+ constant = 0; \
+ if (!TREE_INVARIANT (arg##N)) \
+ invariant = 0; \
+ } \
+ } while (0)
+
+tree
+build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
+{
+ bool constant, read_only, side_effects, invariant;
+ tree t;
+ int fro;
+
+#ifdef ENABLE_CHECKING
+ if (TREE_CODE_LENGTH (code) != 2)
+ abort ();
+#endif
+
+ t = make_node_stat (code PASS_MEM_STAT);
+ TREE_TYPE (t) = tt;
+
+ /* Below, we automatically set TREE_SIDE_EFFECTS and TREE_READONLY for the
+ result based on those same flags for the arguments. But if the
+ arguments aren't really even `tree' expressions, we shouldn't be trying
+ to do this. */
+ fro = first_rtl_op (code);
+
+ /* Expressions without side effects may be constant if their
+ arguments are as well. */
+ constant = (TREE_CODE_CLASS (code) == '<'
+ || TREE_CODE_CLASS (code) == '2');
+ read_only = 1;
+ side_effects = TREE_SIDE_EFFECTS (t);
+ invariant = constant;
+
+ PROCESS_ARG(0);
+ PROCESS_ARG(1);
+
+ TREE_READONLY (t) = read_only;
+ TREE_CONSTANT (t) = constant;
+ TREE_INVARIANT (t) = invariant;
+ TREE_SIDE_EFFECTS (t) = side_effects;
+ TREE_THIS_VOLATILE (t)
+ = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0);
+
+ return t;
+}
+
+tree
+build3_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
+ tree arg2 MEM_STAT_DECL)
+{
+ bool constant, read_only, side_effects, invariant;
+ tree t;
+ int fro;
+
+#ifdef ENABLE_CHECKING
+ if (TREE_CODE_LENGTH (code) != 3)
+ abort ();
+#endif
+
+ t = make_node_stat (code PASS_MEM_STAT);
+ TREE_TYPE (t) = tt;
+
+ fro = first_rtl_op (code);
+
+ side_effects = TREE_SIDE_EFFECTS (t);
+
+ PROCESS_ARG(0);
+ PROCESS_ARG(1);
+ PROCESS_ARG(2);
+
+ if (code == CALL_EXPR && !side_effects)
+ {
+ tree node;
+ int i;
+
+ /* Calls have side-effects, except those to const or
+ pure functions. */
+ i = call_expr_flags (t);
+ if (!(i & (ECF_CONST | ECF_PURE)))
+ side_effects = 1;
+
+ /* And even those have side-effects if their arguments do. */
+ else for (node = arg1; node; node = TREE_CHAIN (node))
+ if (TREE_SIDE_EFFECTS (TREE_VALUE (node)))
+ {
+ side_effects = 1;
+ break;
+ }
+ }
+
+ TREE_SIDE_EFFECTS (t) = side_effects;
+ TREE_THIS_VOLATILE (t)
+ = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0);
+
+ return t;
+}
+
+tree
+build4_stat (enum tree_code code, tree tt, tree arg0, tree arg1,
+ tree arg2, tree arg3 MEM_STAT_DECL)
+{
+ bool constant, read_only, side_effects, invariant;
+ tree t;
+ int fro;
+
+#ifdef ENABLE_CHECKING
+ if (TREE_CODE_LENGTH (code) != 4)
+ abort ();
+#endif
+
+ t = make_node_stat (code PASS_MEM_STAT);
+ TREE_TYPE (t) = tt;
+
+ fro = first_rtl_op (code);
+
+ side_effects = TREE_SIDE_EFFECTS (t);
+
+ PROCESS_ARG(0);
+ PROCESS_ARG(1);
+ PROCESS_ARG(2);
+ PROCESS_ARG(3);
+
+ TREE_SIDE_EFFECTS (t) = side_effects;
+ TREE_THIS_VOLATILE (t)
+ = TREE_CODE_CLASS (code) == 'r' && arg0 && TREE_THIS_VOLATILE (arg0);
+
+ return t;
+}
+
+/* Backup definition for non-gcc build compilers. */
+
+tree
+(build) (enum tree_code code, tree tt, ...)
+{
+ tree t, arg0, arg1, arg2, arg3;
+ int length = TREE_CODE_LENGTH (code);
+ va_list p;
+
+ va_start (p, tt);
+ switch (length)
+ {
+ case 0:
+ t = build0 (code, tt);
+ break;
+ case 1:
+ arg0 = va_arg (p, tree);
+ t = build1 (code, tt, arg0);
+ break;
+ case 2:
+ arg0 = va_arg (p, tree);
+ arg1 = va_arg (p, tree);
+ t = build2 (code, tt, arg0, arg1);
+ break;
+ case 3:
+ arg0 = va_arg (p, tree);
+ arg1 = va_arg (p, tree);
+ arg2 = va_arg (p, tree);
+ t = build3 (code, tt, arg0, arg1, arg2);
+ break;
+ case 4:
+ arg0 = va_arg (p, tree);
+ arg1 = va_arg (p, tree);
+ arg2 = va_arg (p, tree);
+ arg3 = va_arg (p, tree);
+ t = build4 (code, tt, arg0, arg1, arg2, arg3);
+ break;
+ default:
+ abort ();
+ }
+ va_end (p);
+
+ return t;
+}
+