Commit 4fe12442 by Donald Lindsay Committed by Don Lindsay

change MIPS varargs ABI in config/mips/mips.c

From-SVN: r33621
parent f4e79153
Tue May 2 18:20:31 2000 Donald Lindsay <dlindsay@hound.cygnus.com>
* config/mips/mips.c (mips_build_va_list,mips_va_start,mips_va_arg): new
ABI for varargs, across all MIPS. This is incompatible because the
va_list (__builtin_va_list) structure is different, so a compilation
unit passing a va_list and a compilation unit being passed one, should
both be compiled with the same ABI. (The old structure had two
pointers, now it has three.)
Tue May 2 19:18:43 2000 Jason Eckhardt <jle@cygnus.com> Tue May 2 19:18:43 2000 Jason Eckhardt <jle@cygnus.com>
* bb-reorder.c (struct reorder_block_def): Remove members end, * bb-reorder.c (struct reorder_block_def): Remove members end,
......
...@@ -4138,41 +4138,71 @@ function_arg_partial_nregs (cum, mode, type, named) ...@@ -4138,41 +4138,71 @@ function_arg_partial_nregs (cum, mode, type, named)
return 0; return 0;
} }
/* Create the va_list data type. */ /* Create the va_list data type.
We keep 3 pointers, and two offsets.
Two pointers are to the overflow area, which starts at the CFA.
One of these is constant, for addressing into the GPR save area below it.
The other is advanced up the stack through the overflow region.
The third pointer is to the GPR save area. Since the FPR save area
is just below it, we can address FPR slots off this pointer.
We also keep two one-byte offsets, which are to be subtracted from the
constant pointers to yield addresses in the GPR and FPR save areas.
These are downcounted as float or non-float arguments are used,
and when they get to zero, the argument must be obtained from the
overflow region.
If TARGET_SOFT_FLOAT or TARGET_SINGLE_FLOAT, then no FPR save area exists,
and a single pointer is enough. It's started at the GPR save area,
and is advanced, period.
Note that the GPR save area is not constant size, due to optimization
in the prologue. Hence, we can't use a design with two pointers
and two offsets, although we could have designed this with two pointers
and three offsets. */
tree tree
mips_build_va_list () mips_build_va_list ()
{ {
if (mips_abi == ABI_EABI && !TARGET_SOFT_FLOAT && !TARGET_SINGLE_FLOAT) if (mips_abi == ABI_EABI && !TARGET_SOFT_FLOAT && !TARGET_SINGLE_FLOAT)
{ {
tree f_fpr, f_rem, f_gpr, record; tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff, record;
record = make_node (RECORD_TYPE); record = make_node (RECORD_TYPE);
f_fpr = build_decl (FIELD_DECL, get_identifier ("__fp_regs"), f_ovfl = build_decl (FIELD_DECL, get_identifier ("__overflow_argptr"),
ptr_type_node);
f_gtop = build_decl (FIELD_DECL, get_identifier ("__gpr_top"),
ptr_type_node); ptr_type_node);
f_rem = build_decl (FIELD_DECL, get_identifier ("__fp_left"), f_ftop = build_decl (FIELD_DECL, get_identifier ("__fpr_top"),
integer_type_node);
f_gpr = build_decl (FIELD_DECL, get_identifier ("__gp_regs"),
ptr_type_node); ptr_type_node);
f_goff = build_decl (FIELD_DECL, get_identifier ("__gpr_offset"),
unsigned_char_type_node);
f_foff = build_decl (FIELD_DECL, get_identifier ("__fpr_offset"),
unsigned_char_type_node);
DECL_FIELD_CONTEXT (f_fpr) = record;
DECL_FIELD_CONTEXT (f_rem) = record;
DECL_FIELD_CONTEXT (f_gpr) = record;
TYPE_FIELDS (record) = f_fpr; DECL_FIELD_CONTEXT (f_ovfl) = record;
TREE_CHAIN (f_fpr) = f_rem; DECL_FIELD_CONTEXT (f_gtop) = record;
TREE_CHAIN (f_rem) = f_gpr; DECL_FIELD_CONTEXT (f_ftop) = record;
DECL_FIELD_CONTEXT (f_goff) = record;
DECL_FIELD_CONTEXT (f_foff) = record;
layout_type (record); TYPE_FIELDS (record) = f_ovfl;
TREE_CHAIN (f_ovfl) = f_gtop;
TREE_CHAIN (f_gtop) = f_ftop;
TREE_CHAIN (f_ftop) = f_goff;
TREE_CHAIN (f_goff) = f_foff;
layout_type (record);
return record; return record;
} }
else else
return ptr_type_node; return ptr_type_node;
} }
/* Implement va_start. */ /* Implement va_start. stdarg_p is 0 if implementing
__builtin_varargs_va_start, 1 if implementing __builtin_stdarg_va_start.
Note that this routine isn't called when compiling e.g. "_vfprintf_r".
(It doesn't have "...", so it inherits the pointers of its caller.) */
void void
mips_va_start (stdarg_p, valist, nextarg) mips_va_start (stdarg_p, valist, nextarg)
...@@ -4180,82 +4210,139 @@ mips_va_start (stdarg_p, valist, nextarg) ...@@ -4180,82 +4210,139 @@ mips_va_start (stdarg_p, valist, nextarg)
tree valist; tree valist;
rtx nextarg; rtx nextarg;
{ {
int arg_words; int int_arg_words;
tree t; tree t;
arg_words = current_function_args_info.arg_words; /* Find out how many non-float named formals */
int_arg_words = current_function_args_info.arg_words;
if (mips_abi == ABI_EABI) if (mips_abi == ABI_EABI)
{ {
int gpr_save_area_size;
/* Note UNITS_PER_WORD is 4 bytes or 8, depending on TARGET_64BIT. */
if (int_arg_words < 8 )
/* Adjust for the prologue's economy measure */
gpr_save_area_size = (8 - int_arg_words) * UNITS_PER_WORD;
else
gpr_save_area_size = 0;
if (!TARGET_SOFT_FLOAT && !TARGET_SINGLE_FLOAT) if (!TARGET_SOFT_FLOAT && !TARGET_SINGLE_FLOAT)
{ {
tree f_fpr, f_rem, f_gpr, fpr, rem, gpr; tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff;
tree gprv, fprv; tree ovfl, gtop, ftop, goff, foff;
int gpro, fpro; tree gprv;
int float_formals, fpr_offset, size_excess, floats_passed_in_regs;
fpro = (8 - current_function_args_info.fp_arg_words); int fpr_save_offset;
float_formals = current_function_args_info.fp_arg_words;
/* If mips2, the number of formals is half the reported # of words */
if (!TARGET_64BIT) if (!TARGET_64BIT)
fpro /= 2; float_formals /= 2;
floats_passed_in_regs = (TARGET_64BIT ? 8 : 4);
f_fpr = TYPE_FIELDS (va_list_type_node);
f_rem = TREE_CHAIN (f_fpr); f_ovfl = TYPE_FIELDS (va_list_type_node);
f_gpr = TREE_CHAIN (f_rem); f_gtop = TREE_CHAIN (f_ovfl);
f_ftop = TREE_CHAIN (f_gtop);
fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr); f_goff = TREE_CHAIN (f_ftop);
rem = build (COMPONENT_REF, TREE_TYPE (f_rem), valist, f_rem); f_foff = TREE_CHAIN (f_goff);
gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl);
gtop = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop);
ftop = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop);
goff = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff);
foff = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff);
/* Emit code setting a pointer into the overflow (shared-stack) area.
If there were more than 8 non-float formals, or more than 8
float formals, then this pointer isn't to the base of the area.
In that case, it must point to where the first vararg is. */
size_excess = 0;
if (float_formals > floats_passed_in_regs)
size_excess += (float_formals-floats_passed_in_regs) * 8;
if (int_arg_words > 8)
size_excess += (int_arg_words-8) * UNITS_PER_WORD;
/* FIXME: for mips2, the above size_excess can be wrong. Because the
overflow stack holds mixed size items, there can be alignments,
so that an 8 byte double following a 4 byte int will be on an
8 byte boundary. This means that the above calculation should
take into account the exact sequence of floats and non-floats
which make up the excess. That calculation should be rolled
into the code which sets the current_function_args_info struct.
The above then reduces to a fetch from that struct. */
t = make_tree (TREE_TYPE (ovfl), virtual_incoming_args_rtx);
if (size_excess)
t = build (PLUS_EXPR, TREE_TYPE (ovfl), t,
build_int_2 (size_excess, 0));
t = build (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
if (arg_words < 8) /* Emit code setting a ptr to the base of the overflow area. */
gpro = (8 - arg_words) * UNITS_PER_WORD; t = make_tree (TREE_TYPE (gtop), virtual_incoming_args_rtx);
else t = build (MODIFY_EXPR, TREE_TYPE (gtop), gtop, t);
gpro = (stdarg_p ? 0 : UNITS_PER_WORD); expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
gprv = make_tree (ptr_type_node, nextarg); /* Emit code setting a pointer to the GPR save area.
if (gpro != 0) More precisely, a pointer to off-the-end of the FPR save area.
If mips4, this is gpr_save_area_size below the overflow area.
If mips2, also round down to an 8-byte boundary, since the FPR
save area is 8-byte aligned, and GPR is 4-byte-aligned.
Therefore there can be a 4-byte gap between the save areas. */
gprv = make_tree (TREE_TYPE (ftop), virtual_incoming_args_rtx);
fpr_save_offset = gpr_save_area_size;
if (!TARGET_64BIT)
{ {
gprv = build (PLUS_EXPR, ptr_type_node, gprv, if (fpr_save_offset & 7)
build_int_2 (-gpro, -1)); fpr_save_offset += 4;
} }
if (fpr_save_offset)
t = build (MODIFY_EXPR, ptr_type_node, gpr, gprv); gprv = build (PLUS_EXPR, TREE_TYPE (ftop), gprv,
TREE_SIDE_EFFECTS (t) = 1; build_int_2 (-fpr_save_offset,-1));
t = build (MODIFY_EXPR, TREE_TYPE (ftop), ftop, gprv);
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
t = build (MODIFY_EXPR, integer_type_node, rem, /* Emit code initting an offset to the size of the GPR save area */
build_int_2 (fpro, 0)); t = build (MODIFY_EXPR, TREE_TYPE (goff), goff,
TREE_SIDE_EFFECTS (t) = 1; build_int_2 (gpr_save_area_size,0));
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
if (fpro == 0) /* Emit code initting an offset from ftop to the first float
fprv = gprv; vararg. This varies in size, since any float
else varargs are put in the FPR save area after the formals.
fprv = fold (build (PLUS_EXPR, ptr_type_node, gprv, Note it's 8 bytes/formal regardless of TARGET_64BIT.
build_int_2 (-(fpro*8), -1))); However, mips2 stores 4 GPRs, mips4 stores 8 GPRs.
If there are 8 or more float formals, init to zero.
if (! TARGET_64BIT) (In fact, the formals aren't stored in the bottom of the
fprv = fold (build (BIT_AND_EXPR, ptr_type_node, fprv, FPR save area: they are elsewhere, and the size of the FPR
build_int_2 (-8, -1))); save area is economized by the prologue. But this code doesn't
care. This design is unaffected by that fact.) */
t = build (MODIFY_EXPR, ptr_type_node, fpr, fprv); if (float_formals >= floats_passed_in_regs)
TREE_SIDE_EFFECTS (t) = 1; fpr_offset = 0;
else
fpr_offset = (floats_passed_in_regs - float_formals) * 8;
t = build (MODIFY_EXPR, TREE_TYPE (foff), foff,
build_int_2 (fpr_offset,0));
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
} }
else else
{ {
int ofs; /* TARGET_SOFT_FLOAT or TARGET_SINGLE_FLOAT */
if (arg_words >= 8) /* Everything is in the GPR save area, or in the overflow
ofs = (stdarg_p ? 0 : UNITS_PER_WORD); area which is contiguous with it. */
else
ofs = (8 - arg_words) * UNITS_PER_WORD;
nextarg = plus_constant (nextarg, -ofs); int offset = -gpr_save_area_size;
if (gpr_save_area_size == 0)
offset = (stdarg_p ? 0 : -UNITS_PER_WORD);
nextarg = plus_constant (nextarg, offset);
std_expand_builtin_va_start (1, valist, nextarg); std_expand_builtin_va_start (1, valist, nextarg);
} }
} }
else else
{ {
/* not EABI */
int ofs; int ofs;
if (stdarg_p) if (stdarg_p)
...@@ -4266,7 +4353,7 @@ mips_va_start (stdarg_p, valist, nextarg) ...@@ -4266,7 +4353,7 @@ mips_va_start (stdarg_p, valist, nextarg)
_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32
and both iris5.h and iris6.h define _MIPS_SIM. */ and both iris5.h and iris6.h define _MIPS_SIM. */
if (mips_abi == ABI_N32 || mips_abi == ABI_64) if (mips_abi == ABI_N32 || mips_abi == ABI_64)
ofs = (arg_words >= 8 ? -UNITS_PER_WORD : 0); ofs = (int_arg_words >= 8 ? -UNITS_PER_WORD : 0);
else else
ofs = -UNITS_PER_WORD; ofs = -UNITS_PER_WORD;
} }
...@@ -4291,9 +4378,10 @@ mips_va_arg (valist, type) ...@@ -4291,9 +4378,10 @@ mips_va_arg (valist, type)
if (mips_abi == ABI_EABI) if (mips_abi == ABI_EABI)
{ {
tree gpr;
int indirect; int indirect;
rtx lab_over = NULL_RTX, lab_false, r; rtx r, lab_over = NULL_RTX, lab_false;
tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff;
tree ovfl, gtop, ftop, goff, foff;
indirect indirect
= function_arg_pass_by_reference (NULL, TYPE_MODE (type), type, 0); = function_arg_pass_by_reference (NULL, TYPE_MODE (type), type, 0);
...@@ -4302,75 +4390,172 @@ mips_va_arg (valist, type) ...@@ -4302,75 +4390,172 @@ mips_va_arg (valist, type)
addr_rtx = gen_reg_rtx (Pmode); addr_rtx = gen_reg_rtx (Pmode);
if (!TARGET_SOFT_FLOAT && !TARGET_SINGLE_FLOAT) if (TARGET_SOFT_FLOAT || TARGET_SINGLE_FLOAT)
{
/* Case of all args in a merged stack. No need to check bounds,
just advance valist along the stack. */
tree gpr = valist;
if (! indirect
&& ! TARGET_64BIT
&& TYPE_ALIGN (type) > (unsigned) BITS_PER_WORD)
{ {
tree f_fpr, f_rem, f_gpr, fpr, rem; t = build (PLUS_EXPR, TREE_TYPE (gpr), gpr,
build_int_2 (2*UNITS_PER_WORD - 1, 0));
t = build (BIT_AND_EXPR, TREE_TYPE (t), t,
build_int_2 (-2*UNITS_PER_WORD, -1));
t = build (MODIFY_EXPR, TREE_TYPE (gpr), gpr, t);
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
f_fpr = TYPE_FIELDS (va_list_type_node); t = build (POSTINCREMENT_EXPR, TREE_TYPE (gpr), gpr,
f_rem = TREE_CHAIN (f_fpr); size_int (rsize));
f_gpr = TREE_CHAIN (f_rem); r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
if (r != addr_rtx)
emit_move_insn (addr_rtx, r);
fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr); /* flush the POSTINCREMENT */
rem = build (COMPONENT_REF, TREE_TYPE (f_rem), valist, f_rem); emit_queue();
gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr);
if (TREE_CODE (type) == REAL_TYPE) if (indirect)
{
r = gen_rtx_MEM (Pmode, addr_rtx);
MEM_ALIAS_SET (r) = get_varargs_alias_set ();
emit_move_insn (addr_rtx, r);
}
else
{ {
if (BYTES_BIG_ENDIAN && rsize != size)
addr_rtx = plus_constant (addr_rtx, rsize - size);
}
return addr_rtx;
}
/* Not a simple merged stack. Need ptrs and indexes left by va_start. */
f_ovfl = TYPE_FIELDS (va_list_type_node);
f_gtop = TREE_CHAIN (f_ovfl);
f_ftop = TREE_CHAIN (f_gtop);
f_goff = TREE_CHAIN (f_ftop);
f_foff = TREE_CHAIN (f_goff);
ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl);
gtop = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop);
ftop = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop);
goff = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff);
foff = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff);
lab_false = gen_label_rtx (); lab_false = gen_label_rtx ();
lab_over = gen_label_rtx (); lab_over = gen_label_rtx ();
r = expand_expr (rem, NULL_RTX, TYPE_MODE (TREE_TYPE (rem)), if (TREE_CODE (type) == REAL_TYPE)
EXPAND_NORMAL); {
emit_cmp_and_jump_insns (r, const0_rtx, LE, const1_rtx,
GET_MODE (r), 1, 1, lab_false);
t = build (PLUS_EXPR, TREE_TYPE (rem), rem, /* Emit code to branch if foff == 0. */
build_int_2 (-1, -1)); r = expand_expr (foff, NULL_RTX, TYPE_MODE (TREE_TYPE (foff)),
t = build (MODIFY_EXPR, TREE_TYPE (rem), rem, t); EXPAND_NORMAL);
TREE_SIDE_EFFECTS (t) = 1; emit_cmp_and_jump_insns (r, const0_rtx, EQ,
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); const1_rtx, GET_MODE (r), 1, 1, lab_false);
t = build (POSTINCREMENT_EXPR, TREE_TYPE (fpr), fpr, /* Emit code for addr_rtx = ftop - foff */
build_int_2 (8, 0)); t = build (MINUS_EXPR, TREE_TYPE (ftop), ftop, foff );
TREE_SIDE_EFFECTS (t) = 1;
r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL); r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
if (r != addr_rtx) if (r != addr_rtx)
emit_move_insn (addr_rtx, r); emit_move_insn (addr_rtx, r);
/* Ensure that the POSTINCREMENT is emitted before lab_over */ /* Emit code for foff-=8.
emit_queue(); Advances the offset up FPR save area by one double */
t = build (MINUS_EXPR, TREE_TYPE (foff), foff, build_int_2 (8, 0));
t = build (MODIFY_EXPR, TREE_TYPE (foff), foff, t);
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
emit_queue();
emit_jump (lab_over); emit_jump (lab_over);
emit_barrier (); emit_barrier ();
emit_label (lab_false); emit_label (lab_false);
if (!TARGET_64BIT)
{
/* For mips2, the overflow area contains mixed size items.
If a 4-byte int is followed by an 8-byte float, then
natural alignment causes a 4 byte gap.
So, dynamically adjust ovfl up to a multiple of 8. */
t = build (BIT_AND_EXPR, TREE_TYPE (ovfl), ovfl,
build_int_2 (7, 0));
t = build (PLUS_EXPR, TREE_TYPE (ovfl), ovfl, t);
t = build (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
} }
/* Emit code for addr_rtx = the ovfl pointer into overflow area.
Regardless of mips2, postincrement the ovfl pointer by 8. */
t = build (POSTINCREMENT_EXPR, TREE_TYPE(ovfl), ovfl,
size_int (8));
r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
if (r != addr_rtx)
emit_move_insn (addr_rtx, r);
emit_queue();
emit_label (lab_over);
return addr_rtx;
} }
else else
gpr = valist; {
/* not REAL_TYPE */
int step_size;
if (! indirect if (! TARGET_64BIT
&& ! TARGET_64BIT && TREE_CODE (type) == INTEGER_TYPE
&& TYPE_ALIGN (type) > (unsigned) BITS_PER_WORD) && TYPE_PRECISION (type) == 64)
{ {
t = build (PLUS_EXPR, TREE_TYPE (gpr), gpr, /* In mips2, int takes 32 bits of the GPR save area, but
build_int_2 (2*UNITS_PER_WORD - 1, 0)); longlong takes an aligned 64 bits. So, emit code
t = build (BIT_AND_EXPR, TREE_TYPE (t), t, to zero the low order bits of goff, thus aligning
build_int_2 (-2*UNITS_PER_WORD, -1)); the later calculation of (gtop-goff) upwards. */
t = build (MODIFY_EXPR, TREE_TYPE (gpr), gpr, t); t = build (BIT_AND_EXPR, TREE_TYPE (goff), goff,
TREE_SIDE_EFFECTS (t) = 1; build_int_2 (-8, -1));
t = build (MODIFY_EXPR, TREE_TYPE (goff), goff, t);
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
} }
t = build (POSTINCREMENT_EXPR, TREE_TYPE (gpr), gpr, size_int (rsize)); /* Emit code to branch if goff == 0. */
TREE_SIDE_EFFECTS (t) = 1; r = expand_expr (goff, NULL_RTX, TYPE_MODE (TREE_TYPE (goff)),
EXPAND_NORMAL);
emit_cmp_and_jump_insns (r, const0_rtx, EQ,
const1_rtx, GET_MODE (r), 1, 1, lab_false);
/* Emit code for addr_rtx = gtop - goff. */
t = build (MINUS_EXPR, TREE_TYPE (gtop), gtop, goff);
r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL); r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
if (r != addr_rtx) if (r != addr_rtx)
emit_move_insn (addr_rtx, r); emit_move_insn (addr_rtx, r);
/* Ensure that the above POSTINCREMENT is emitted before lab_over */ /* Note that mips2 int is 32 bit, but mips2 longlong is 64. */
if (! TARGET_64BIT && TYPE_PRECISION (type) == 64)
step_size = 8;
else
step_size = UNITS_PER_WORD;
/* Emit code for goff = goff - step_size.
Advances the offset up GPR save area over the item. */
t = build (MINUS_EXPR, TREE_TYPE (goff), goff,
build_int_2 (step_size, 0));
t = build (MODIFY_EXPR, TREE_TYPE (goff), goff, t);
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
emit_queue(); emit_queue();
emit_jump (lab_over);
emit_barrier ();
emit_label (lab_false);
/* Emit code for addr_rtx -> overflow area, postinc by step_size */
t = build (POSTINCREMENT_EXPR, TREE_TYPE(ovfl), ovfl,
size_int (step_size));
r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
if (r != addr_rtx)
emit_move_insn (addr_rtx, r);
if (lab_over) emit_queue();
emit_label (lab_over); emit_label (lab_over);
if (indirect) if (indirect)
...@@ -4384,11 +4569,12 @@ mips_va_arg (valist, type) ...@@ -4384,11 +4569,12 @@ mips_va_arg (valist, type)
if (BYTES_BIG_ENDIAN && rsize != size) if (BYTES_BIG_ENDIAN && rsize != size)
addr_rtx = plus_constant (addr_rtx, rsize - size); addr_rtx = plus_constant (addr_rtx, rsize - size);
} }
return addr_rtx; return addr_rtx;
} }
}
else else
{ {
/* Not EABI. */
int align; int align;
/* ??? The original va-mips.h did always align, despite the fact /* ??? The original va-mips.h did always align, despite the fact
...@@ -4406,7 +4592,6 @@ mips_va_arg (valist, type) ...@@ -4406,7 +4592,6 @@ mips_va_arg (valist, type)
build_int_2 (align - 1, 0)); build_int_2 (align - 1, 0));
t = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1)); t = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t); t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
/* Everything past the alignment is standard. */ /* Everything past the alignment is standard. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment