Commit 0310e537 by Richard Henderson Committed by Richard Sandiford

mips-protos.h (mips_va_arg): Delete.

	* config/mips/mips-protos.h (mips_va_arg): Delete.
	* config/mips/mips.h (EXPAND_BUILTIN_VA_ARG): Delete.
	* config/mips/mips.c: Include tree-gimple.h.
	(TARGET_GIMPLIFY_VA_ARG_EXPR): Define.
	(mips_arg_info): Remove special handling of must_pass_in_stck args.
	(mips_gimplify_va_arg_expr): Rewritten from mips_va_arg.
	(function_arg_pass_by_reference): Return true if must_pass_in_stack.

Co-Authored-By: Richard Sandiford <rsandifo@redhat.com>

From-SVN: r84671
parent 1cb6d0da
2004-07-14 Richard Henderson <rth@redhat.com>
Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips-protos.h (mips_va_arg): Delete.
* config/mips/mips.h (EXPAND_BUILTIN_VA_ARG): Delete.
* config/mips/mips.c: Include tree-gimple.h.
(TARGET_GIMPLIFY_VA_ARG_EXPR): Define.
(mips_arg_info): Remove special handling of must_pass_in_stck args.
(mips_gimplify_va_arg_expr): Rewritten from mips_va_arg.
(function_arg_pass_by_reference): Return true if must_pass_in_stack.
2004-07-13 Bob Wilson <bob.wilson@acm.org> 2004-07-13 Bob Wilson <bob.wilson@acm.org>
* config/xtensa/xtensa.c (xtensa_gimplify_va_arg_expr): Swap * config/xtensa/xtensa.c (xtensa_gimplify_va_arg_expr): Swap
......
...@@ -143,7 +143,6 @@ extern int function_arg_partial_nregs (const CUMULATIVE_ARGS *, ...@@ -143,7 +143,6 @@ extern int function_arg_partial_nregs (const CUMULATIVE_ARGS *,
extern bool mips_pad_arg_upward (enum machine_mode, tree); extern bool mips_pad_arg_upward (enum machine_mode, tree);
extern bool mips_pad_reg_upward (enum machine_mode, tree); extern bool mips_pad_reg_upward (enum machine_mode, tree);
extern void mips_va_start (tree, rtx); extern void mips_va_start (tree, rtx);
extern struct rtx_def *mips_va_arg (tree, tree);
extern bool mips_expand_unaligned_load (rtx, rtx, unsigned int, int); extern bool mips_expand_unaligned_load (rtx, rtx, unsigned int, int);
extern bool mips_expand_unaligned_store (rtx, rtx, unsigned int, int); extern bool mips_expand_unaligned_store (rtx, rtx, unsigned int, int);
......
...@@ -55,6 +55,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -55,6 +55,7 @@ Boston, MA 02111-1307, USA. */
#include "langhooks.h" #include "langhooks.h"
#include "cfglayout.h" #include "cfglayout.h"
#include "sched-int.h" #include "sched-int.h"
#include "tree-gimple.h"
/* Enumeration for all of the relational tests, so that we can build /* Enumeration for all of the relational tests, so that we can build
arrays indexed by the test type, and not worry about the order arrays indexed by the test type, and not worry about the order
...@@ -288,6 +289,7 @@ static void mips_init_libfuncs (void); ...@@ -288,6 +289,7 @@ static void mips_init_libfuncs (void);
static void mips_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, static void mips_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
tree, int *, int); tree, int *, int);
static tree mips_build_builtin_va_list (void); static tree mips_build_builtin_va_list (void);
static tree mips_gimplify_va_arg_expr (tree, tree, tree *, tree *);
#if TARGET_IRIX #if TARGET_IRIX
static void irix_asm_named_section_1 (const char *, unsigned int, static void irix_asm_named_section_1 (const char *, unsigned int,
...@@ -716,6 +718,8 @@ const struct mips_cpu_info mips_cpu_info_table[] = { ...@@ -716,6 +718,8 @@ const struct mips_cpu_info mips_cpu_info_table[] = {
#undef TARGET_BUILD_BUILTIN_VA_LIST #undef TARGET_BUILD_BUILTIN_VA_LIST
#define TARGET_BUILD_BUILTIN_VA_LIST mips_build_builtin_va_list #define TARGET_BUILD_BUILTIN_VA_LIST mips_build_builtin_va_list
#undef TARGET_GIMPLIFY_VA_ARG_EXPR
#define TARGET_GIMPLIFY_VA_ARG_EXPR mips_gimplify_va_arg_expr
#undef TARGET_PROMOTE_FUNCTION_ARGS #undef TARGET_PROMOTE_FUNCTION_ARGS
#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
...@@ -3554,22 +3558,15 @@ mips_arg_info (const CUMULATIVE_ARGS *cum, enum machine_mode mode, ...@@ -3554,22 +3558,15 @@ mips_arg_info (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
even_reg_p = true; even_reg_p = true;
} }
if (mips_abi != ABI_EABI && targetm.calls.must_pass_in_stack (mode, type)) /* Set REG_OFFSET to the register count we're interested in.
/* This argument must be passed on the stack. Eat up all the The EABI allocates the floating-point registers separately,
remaining registers. */ but the other ABIs allocate them like integer registers. */
info->reg_offset = MAX_ARGS_IN_REGISTERS; info->reg_offset = (mips_abi == ABI_EABI && info->fpr_p
else ? cum->num_fprs
{ : cum->num_gprs);
/* Set REG_OFFSET to the register count we're interested in.
The EABI allocates the floating-point registers separately,
but the other ABIs allocate them like integer registers. */
info->reg_offset = (mips_abi == ABI_EABI && info->fpr_p
? cum->num_fprs
: cum->num_gprs);
if (even_reg_p) if (even_reg_p)
info->reg_offset += info->reg_offset & 1; info->reg_offset += info->reg_offset & 1;
}
/* The alignment applied to registers is also applied to stack arguments. */ /* The alignment applied to registers is also applied to stack arguments. */
info->stack_offset = cum->stack_words; info->stack_offset = cum->stack_words;
...@@ -4041,272 +4038,179 @@ mips_va_start (tree valist, rtx nextarg) ...@@ -4041,272 +4038,179 @@ mips_va_start (tree valist, rtx nextarg)
/* Implement va_arg. */ /* Implement va_arg. */
rtx static tree
mips_va_arg (tree valist, tree type) mips_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
{ {
HOST_WIDE_INT size, rsize; HOST_WIDE_INT size, rsize;
rtx addr_rtx; tree addr;
tree t; bool indirect;
indirect
= function_arg_pass_by_reference (NULL, TYPE_MODE (type), type, 0);
if (indirect)
type = build_pointer_type (type);
size = int_size_in_bytes (type); size = int_size_in_bytes (type);
rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD; rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
if (mips_abi == ABI_EABI) if (mips_abi != ABI_EABI || !EABI_FLOAT_VARARGS_P)
addr = std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
else
{ {
bool indirect; /* Not a simple merged stack. */
rtx r;
tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff;
indirect tree ovfl, top, off, align;
= function_arg_pass_by_reference (NULL, TYPE_MODE (type), type, 0); HOST_WIDE_INT osize;
tree t, u;
if (indirect)
{ f_ovfl = TYPE_FIELDS (va_list_type_node);
size = POINTER_SIZE / BITS_PER_UNIT; f_gtop = TREE_CHAIN (f_ovfl);
rsize = UNITS_PER_WORD; f_ftop = TREE_CHAIN (f_gtop);
} f_goff = TREE_CHAIN (f_ftop);
f_foff = TREE_CHAIN (f_goff);
if (!EABI_FLOAT_VARARGS_P)
/* We maintain separate pointers and offsets for floating-point
and integer arguments, but we need similar code in both cases.
Let:
TOP be the top of the register save area;
OFF be the offset from TOP of the next register;
ADDR_RTX be the address of the argument;
RSIZE be the number of bytes used to store the argument
when it's in the register save area;
OSIZE be the number of bytes used to store it when it's
in the stack overflow area; and
PADDING be (BYTES_BIG_ENDIAN ? OSIZE - RSIZE : 0)
The code we want is:
1: off &= -rsize; // round down
2: if (off != 0)
3: {
4: addr_rtx = top - off;
5: off -= rsize;
6: }
7: else
8: {
9: ovfl += ((intptr_t) ovfl + osize - 1) & -osize;
10: addr_rtx = ovfl + PADDING;
11: ovfl += osize;
14: }
[1] and [9] can sometimes be optimized away. */
ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl,
NULL_TREE);
if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT
&& GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FPVALUE)
{ {
/* Case of all args in a merged stack. No need to check bounds, top = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop,
just advance valist along the stack. */ NULL_TREE);
off = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff,
tree gpr = valist; NULL_TREE);
if (!indirect
&& !TARGET_64BIT /* When floating-point registers are saved to the stack,
&& TYPE_ALIGN (type) > (unsigned) BITS_PER_WORD) each one will take up UNITS_PER_HWFPVALUE bytes, regardless
{ of the float's precision. */
/* Align the pointer using: ap = (ap + align - 1) & -align, rsize = UNITS_PER_HWFPVALUE;
where align is 2 * UNITS_PER_WORD. */
t = build (PLUS_EXPR, TREE_TYPE (gpr), gpr, /* Overflow arguments are padded to UNITS_PER_WORD bytes
build_int_2 (2 * UNITS_PER_WORD - 1, 0)); (= PARM_BOUNDARY bits). This can be different from RSIZE
t = build (BIT_AND_EXPR, TREE_TYPE (t), t, in two cases:
build_int_2 (-2 * UNITS_PER_WORD, -1));
t = build (MODIFY_EXPR, TREE_TYPE (gpr), gpr, t); (1) On 32-bit targets when TYPE is a structure such as:
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
} struct s { float f; };
/* Emit code to set addr_rtx to the valist, and postincrement Such structures are passed in paired FPRs, so RSIZE
the valist by the size of the argument, rounded up to the will be 8 bytes. However, the structure only takes
next word. Account for padding on big-endian targets. */ up 4 bytes of memory, so OSIZE will only be 4.
t = build (POSTINCREMENT_EXPR, TREE_TYPE (gpr), gpr,
size_int (rsize)); (2) In combinations such as -mgp64 -msingle-float
addr_rtx = expand_expr (t, 0, Pmode, EXPAND_NORMAL); -fshort-double. Doubles passed in registers
if (BYTES_BIG_ENDIAN) will then take up 4 (UNITS_PER_HWFPVALUE) bytes,
addr_rtx = plus_constant (addr_rtx, rsize - size); but those passed on the stack take up
UNITS_PER_WORD bytes. */
/* Flush the POSTINCREMENT. */ osize = MAX (GET_MODE_SIZE (TYPE_MODE (type)), UNITS_PER_WORD);
emit_queue();
} }
else else
{ {
/* Not a simple merged stack. */ top = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop,
NULL_TREE);
tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff; off = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff,
tree ovfl, top, off; NULL_TREE);
rtx lab_over = NULL_RTX, lab_false; if (rsize > UNITS_PER_WORD)
HOST_WIDE_INT osize;
addr_rtx = gen_reg_rtx (Pmode);
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);
/* We maintain separate pointers and offsets for floating-point
and integer arguments, but we need similar code in both cases.
Let:
TOP be the top of the register save area;
OFF be the offset from TOP of the next register;
ADDR_RTX be the address of the argument;
RSIZE be the number of bytes used to store the argument
when it's in the register save area;
OSIZE be the number of bytes used to store it when it's
in the stack overflow area; and
PADDING be (BYTES_BIG_ENDIAN ? OSIZE - RSIZE : 0)
The code we want is:
1: off &= -rsize; // round down
2: if (off != 0)
3: {
4: addr_rtx = top - off;
5: off -= rsize;
6: }
7: else
8: {
9: ovfl += ((intptr_t) ovfl + osize - 1) & -osize;
10: addr_rtx = ovfl + PADDING;
11: ovfl += osize;
14: }
[1] and [9] can sometimes be optimized away. */
lab_false = gen_label_rtx ();
lab_over = gen_label_rtx ();
ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl,
NULL_TREE);
if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT
&& GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FPVALUE)
{ {
top = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop, /* [1] Emit code for: off &= -rsize. */
NULL_TREE); t = build (BIT_AND_EXPR, TREE_TYPE (off), off,
off = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff, build_int_2 (-rsize, -1));
NULL_TREE); t = build (MODIFY_EXPR, TREE_TYPE (off), off, t);
gimplify_and_add (t, pre_p);
/* When floating-point registers are saved to the stack,
each one will take up UNITS_PER_HWFPVALUE bytes, regardless
of the float's precision. */
rsize = UNITS_PER_HWFPVALUE;
/* Overflow arguments are padded to UNITS_PER_WORD bytes
(= PARM_BOUNDARY bits). This can be different from RSIZE
in two cases:
(1) On 32-bit targets when TYPE is a structure such as:
struct s { float f; };
Such structures are passed in paired FPRs, so RSIZE
will be 8 bytes. However, the structure only takes
up 4 bytes of memory, so OSIZE will only be 4.
(2) In combinations such as -mgp64 -msingle-float
-fshort-double. Doubles passed in registers
will then take up 4 (UNITS_PER_HWFPVALUE) bytes,
but those passed on the stack take up
UNITS_PER_WORD bytes. */
osize = MAX (GET_MODE_SIZE (TYPE_MODE (type)), UNITS_PER_WORD);
} }
else osize = rsize;
{ }
top = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop,
NULL_TREE);
off = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff,
NULL_TREE);
if (rsize > UNITS_PER_WORD)
{
/* [1] Emit code for: off &= -rsize. */
t = build (BIT_AND_EXPR, TREE_TYPE (off), off,
build_int_2 (-rsize, -1));
t = build (MODIFY_EXPR, TREE_TYPE (off), off, t);
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
osize = rsize;
}
/* [2] Emit code to branch if off == 0. */
r = expand_expr (off, NULL_RTX, TYPE_MODE (TREE_TYPE (off)),
EXPAND_NORMAL);
emit_cmp_and_jump_insns (r, const0_rtx, EQ, const1_rtx, GET_MODE (r),
1, lab_false);
/* [4] Emit code for: addr_rtx = top - off. On big endian machines,
the argument has RSIZE - SIZE bytes of leading padding. */
t = build (MINUS_EXPR, TREE_TYPE (top), top, off);
if (BYTES_BIG_ENDIAN && rsize > size)
t = build (PLUS_EXPR, TREE_TYPE (t), t,
build_int_2 (rsize - size, 0));
r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
if (r != addr_rtx)
emit_move_insn (addr_rtx, r);
/* [5] Emit code for: off -= rsize. */
t = build (MINUS_EXPR, TREE_TYPE (off), off, build_int_2 (rsize, 0));
t = build (MODIFY_EXPR, TREE_TYPE (off), off, t);
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
/* [7] Emit code to jump over the else clause, then the label
that starts it. */
emit_queue();
emit_jump (lab_over);
emit_barrier ();
emit_label (lab_false);
if (osize > UNITS_PER_WORD) /* [2] Emit code to branch if off == 0. */
{ t = lang_hooks.truthvalue_conversion (off);
/* [9] Emit: ovfl += ((intptr_t) ovfl + osize - 1) & -osize. */ addr = build (COND_EXPR, ptr_type_node, t, NULL, NULL);
t = build (PLUS_EXPR, TREE_TYPE (ovfl), ovfl,
build_int_2 (osize - 1, 0)); /* [5] Emit code for: off -= rsize. We do this as a form of
t = build (BIT_AND_EXPR, TREE_TYPE (ovfl), t, post-increment not available to C. Also widen for the
build_int_2 (-osize, -1)); coming pointer arithmetic. */
t = build (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t); t = fold_convert (TREE_TYPE (off), build_int_2 (rsize, 0));
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); t = build (POSTDECREMENT_EXPR, TREE_TYPE (off), off, t);
} t = fold_convert (sizetype, t);
t = fold_convert (TREE_TYPE (top), t);
/* [4] Emit code for: addr_rtx = top - off. On big endian machines,
the argument has RSIZE - SIZE bytes of leading padding. */
t = build (MINUS_EXPR, TREE_TYPE (top), top, t);
if (BYTES_BIG_ENDIAN && rsize > size)
{
u = fold_convert (TREE_TYPE (t), build_int_2 (rsize - size, 0));
t = build (PLUS_EXPR, TREE_TYPE (t), t, u);
}
COND_EXPR_THEN (addr) = t;
/* [10, 11]. Emit code to store ovfl in addr_rtx, then if (osize > UNITS_PER_WORD)
post-increment ovfl by osize. On big-endian machines, {
the argument has OSIZE - SIZE bytes of leading padding. */ /* [9] Emit: ovfl += ((intptr_t) ovfl + osize - 1) & -osize. */
t = build (POSTINCREMENT_EXPR, TREE_TYPE (ovfl), ovfl, u = fold_convert (TREE_TYPE (ovfl), build_int_2 (osize - 1, 0));
size_int (osize)); t = build (PLUS_EXPR, TREE_TYPE (ovfl), ovfl, u);
if (BYTES_BIG_ENDIAN && osize > size) u = fold_convert (TREE_TYPE (ovfl), build_int_2 (-osize, -1));
t = build (PLUS_EXPR, TREE_TYPE (t), t, t = build (BIT_AND_EXPR, TREE_TYPE (ovfl), t, u);
build_int_2 (osize - size, 0)); align = build (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
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);
} }
if (indirect) else
align = NULL;
/* [10, 11]. Emit code to store ovfl in addr_rtx, then
post-increment ovfl by osize. On big-endian machines,
the argument has OSIZE - SIZE bytes of leading padding. */
u = fold_convert (TREE_TYPE (ovfl), build_int_2 (osize, 0));
t = build (POSTINCREMENT_EXPR, TREE_TYPE (ovfl), ovfl, u);
if (BYTES_BIG_ENDIAN && osize > size)
{ {
addr_rtx = force_reg (Pmode, addr_rtx); u = fold_convert (TREE_TYPE (t), build_int_2 (osize - size, 0));
r = gen_rtx_MEM (Pmode, addr_rtx); t = build (PLUS_EXPR, TREE_TYPE (t), t, u);
set_mem_alias_set (r, get_varargs_alias_set ());
emit_move_insn (addr_rtx, r);
} }
return addr_rtx;
}
else
{
/* Not EABI. */
int align;
HOST_WIDE_INT min_offset;
/* ??? The original va-mips.h did always align, despite the fact /* String [9] and [10,11] together. */
that alignments <= UNITS_PER_WORD are preserved by the va_arg if (align)
increment mechanism. */ t = build (COMPOUND_EXPR, TREE_TYPE (t), align, t);
COND_EXPR_ELSE (addr) = t;
if (TARGET_NEWABI && TYPE_ALIGN (type) > 64) addr = fold_convert (build_pointer_type (type), addr);
align = 16; addr = build_fold_indirect_ref (addr);
else if (TARGET_64BIT) }
align = 8;
else if (TYPE_ALIGN (type) > 32)
align = 8;
else
align = 4;
t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
build_int_2 (align - 1, 0));
t = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
/* If arguments of type TYPE must be passed on the stack,
set MIN_OFFSET to the offset of the first stack parameter. */
if (!targetm.calls.must_pass_in_stack (TYPE_MODE (type), type))
min_offset = 0;
else if (TARGET_NEWABI)
min_offset = current_function_pretend_args_size;
else
min_offset = REG_PARM_STACK_SPACE (current_function_decl);
/* Make sure the new address is at least MIN_OFFSET bytes from
the incoming argument pointer. */
if (min_offset > 0)
t = build (MAX_EXPR, TREE_TYPE (valist), t,
make_tree (TREE_TYPE (valist),
plus_constant (virtual_incoming_args_rtx,
min_offset)));
t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t); if (indirect)
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); addr = build_fold_indirect_ref (addr);
/* Everything past the alignment is standard. */ return addr;
return std_expand_builtin_va_arg (valist, type);
}
} }
/* Return true if it is possible to use left/right accesses for a /* Return true if it is possible to use left/right accesses for a
...@@ -7425,18 +7329,22 @@ function_arg_pass_by_reference (const CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, ...@@ -7425,18 +7329,22 @@ function_arg_pass_by_reference (const CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
enum machine_mode mode, tree type, enum machine_mode mode, tree type,
int named ATTRIBUTE_UNUSED) int named ATTRIBUTE_UNUSED)
{ {
int size; if (mips_abi == ABI_EABI)
{
/* The EABI is the only one to pass args by reference. */ int size;
if (mips_abi != ABI_EABI)
return 0;
/* ??? How should SCmode be handled? */ /* ??? How should SCmode be handled? */
if (type == NULL_TREE || mode == DImode || mode == DFmode) if (type == NULL_TREE || mode == DImode || mode == DFmode)
return 0; return 0;
size = int_size_in_bytes (type); size = int_size_in_bytes (type);
return size == -1 || size > UNITS_PER_WORD; return size == -1 || size > UNITS_PER_WORD;
}
else
{
/* If we have a variable-sized parameter, we have no choice. */
return targetm.calls.must_pass_in_stack (mode, type);
}
} }
/* Return the class of registers for which a mode change from FROM to TO /* Return the class of registers for which a mode change from FROM to TO
......
...@@ -2387,10 +2387,6 @@ typedef struct mips_args { ...@@ -2387,10 +2387,6 @@ typedef struct mips_args {
/* Implement `va_start' for varargs and stdarg. */ /* Implement `va_start' for varargs and stdarg. */
#define EXPAND_BUILTIN_VA_START(valist, nextarg) \ #define EXPAND_BUILTIN_VA_START(valist, nextarg) \
mips_va_start (valist, nextarg) mips_va_start (valist, nextarg)
/* Implement `va_arg'. */
#define EXPAND_BUILTIN_VA_ARG(valist, type) \
mips_va_arg (valist, type)
/* Output assembler code to FILE to increment profiler label # LABELNO /* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */ for profiling a function entry. */
......
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