diff options
-rw-r--r-- | gcc/ChangeLog | 36 | ||||
-rw-r--r-- | gcc/builtins.c | 13 | ||||
-rw-r--r-- | gcc/calls.c | 82 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.md | 2 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.c | 2 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.md | 2 | ||||
-rw-r--r-- | gcc/config/arm/arm.md | 3 | ||||
-rw-r--r-- | gcc/config/cr16/cr16.c | 2 | ||||
-rw-r--r-- | gcc/config/iq2000/iq2000.md | 2 | ||||
-rw-r--r-- | gcc/config/m68k/m68k.md | 2 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 2 | ||||
-rw-r--r-- | gcc/config/pa/pa.md | 2 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 2 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.md | 2 | ||||
-rw-r--r-- | gcc/config/tilegx/tilegx.md | 2 | ||||
-rw-r--r-- | gcc/config/tilepro/tilepro.md | 2 | ||||
-rw-r--r-- | gcc/config/visium/visium.md | 2 | ||||
-rw-r--r-- | gcc/genflags.c | 46 | ||||
-rw-r--r-- | gcc/gensupport.c | 18 | ||||
-rw-r--r-- | gcc/gensupport.h | 1 | ||||
-rw-r--r-- | gcc/gentarget-def.c | 106 | ||||
-rw-r--r-- | gcc/target-insns.def | 15 |
22 files changed, 192 insertions, 154 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7ef1166..8c83523 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,41 @@ 2015-08-24 Richard Sandiford <richard.sandiford@arm.com> + * genflags.c (gen_macro): Delete. + (gen_proto): Don't create GEN.*CALL.* macros. + * gensupport.h (get_file_location): Declare. + * gensupport.c (rtx_locs): New variable. + (read_md_rtx): Record rtx locations. + (get_file_location): New function. + * target-insns.def (call, call_pop, call_value, call_value_pop) + (sibcall, sibcall_value): New patterns. + * gentarget-def.c (parse_argument): New function. + (def_target_insn): Use it. Handle optional operands. Raise an + error if an .md pattern has the wrong number of operands for the + pattern name. Remove the names of unused operands from the prototype. + * builtins.c (expand_builtin_apply): Use targetm functions + instead of HAVE_call_value and GEN_CALL_VALUE. + * calls.c (emit_call_1): Likewise. Remove support for sibcall_pop + and sibcall_value_pop. + * config/aarch64/aarch64.md (untyped_call): Use gen_call instead + of GEN_CALL. + * config/alpha/alpha.md (untyped_call): Likewise. + * config/iq2000/iq2000.md (untyped_call): Likewise. + * config/m68k/m68k.md (untyped_call): Likewise. + * config/mips/mips.md (untyped_call): Likewise. + * config/pa/pa.md (untyped_call): Likewise. + * config/rs6000/rs6000.md (untyped_call): Likewise. + * config/sparc/sparc.md (untyped_call): Likewise. + * config/tilegx/tilegx.md (untyped_call): Likewise. + * config/tilepro/tilepro.md (untyped_call): Likewise. + * config/visium/visium.md (untyped_call): Likewise. + * config/alpha/alpha.c (alpha_emit_xfloating_libcall): Use + gen_call_value instead of GEN_CALL_VALUE. + * config/arm/arm.md (untyped_call): Likewise. + * config/cr16/cr16.c (cr16_function_arg): Remove reference to + GEN_CALL. + +2015-08-24 Richard Sandiford <richard.sandiford@arm.com> + * ifcvt.c (HAVE_incscc, HAVE_decscc, HAVE_cbranchcc4): Delete. (have_cbranchcc4): New variable. (cc_in_cond, noce_emit_cmove, noce_get_alt_condition) diff --git a/gcc/builtins.c b/gcc/builtins.c index 5021dcf..d79372c 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -1686,9 +1686,7 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize) emit_call_insn (targetm.gen_untyped_call (mem, result, result_vector (1, result))); } - else -#ifdef HAVE_call_value - if (HAVE_call_value) + else if (targetm.have_call_value ()) { rtx valreg = 0; @@ -1699,19 +1697,18 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize) for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) if ((mode = apply_result_mode[regno]) != VOIDmode) { - gcc_assert (!valreg); /* HAVE_untyped_call required. */ + gcc_assert (!valreg); /* have_untyped_call required. */ valreg = gen_rtx_REG (mode, regno); } - emit_call_insn (GEN_CALL_VALUE (valreg, - gen_rtx_MEM (FUNCTION_MODE, function), - const0_rtx, NULL_RTX, const0_rtx)); + emit_insn (targetm.gen_call_value (valreg, + gen_rtx_MEM (FUNCTION_MODE, function), + const0_rtx, NULL_RTX, const0_rtx)); emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg); } else -#endif gcc_unreachable (); /* Find the CALL insn we just emitted, and attach the register usage diff --git a/gcc/calls.c b/gcc/calls.c index 5636725..026cb53 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -291,7 +291,7 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU cumulative_args_t args_so_far ATTRIBUTE_UNUSED) { rtx rounded_stack_size_rtx = GEN_INT (rounded_stack_size); - rtx call, funmem; + rtx call, funmem, pat; int already_popped = 0; HOST_WIDE_INT n_popped = targetm.calls.return_pops_args (fndecl, funtype, stack_size); @@ -330,90 +330,50 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU else if (fntree) set_mem_expr (funmem, build_simple_mem_ref (CALL_EXPR_FN (fntree))); -#if defined (HAVE_sibcall_pop) && defined (HAVE_sibcall_value_pop) - if ((ecf_flags & ECF_SIBCALL) - && HAVE_sibcall_pop && HAVE_sibcall_value_pop - && (n_popped > 0 || stack_size == 0)) + if (ecf_flags & ECF_SIBCALL) { - rtx n_pop = GEN_INT (n_popped); - rtx pat; - - /* If this subroutine pops its own args, record that in the call insn - if possible, for the sake of frame pointer elimination. */ - if (valreg) - pat = GEN_SIBCALL_VALUE_POP (valreg, funmem, rounded_stack_size_rtx, - next_arg_reg, n_pop); + pat = targetm.gen_sibcall_value (valreg, funmem, + rounded_stack_size_rtx, + next_arg_reg, NULL_RTX); else - pat = GEN_SIBCALL_POP (funmem, rounded_stack_size_rtx, next_arg_reg, - n_pop); - - emit_call_insn (pat); - already_popped = 1; + pat = targetm.gen_sibcall (funmem, rounded_stack_size_rtx, + next_arg_reg, GEN_INT (struct_value_size)); } - else -#endif - -#if defined (HAVE_call_pop) && defined (HAVE_call_value_pop) /* If the target has "call" or "call_value" insns, then prefer them if no arguments are actually popped. If the target does not have "call" or "call_value" insns, then we must use the popping versions even if the call has no arguments to pop. */ -#if defined (HAVE_call) && defined (HAVE_call_value) - if (HAVE_call && HAVE_call_value && HAVE_call_pop && HAVE_call_value_pop - && n_popped > 0) -#else - if (HAVE_call_pop && HAVE_call_value_pop) -#endif + else if (n_popped > 0 + || !(valreg + ? targetm.have_call_value () + : targetm.have_call ())) { rtx n_pop = GEN_INT (n_popped); - rtx pat; /* If this subroutine pops its own args, record that in the call insn if possible, for the sake of frame pointer elimination. */ if (valreg) - pat = GEN_CALL_VALUE_POP (valreg, funmem, rounded_stack_size_rtx, - next_arg_reg, n_pop); + pat = targetm.gen_call_value_pop (valreg, funmem, + rounded_stack_size_rtx, + next_arg_reg, n_pop); else - pat = GEN_CALL_POP (funmem, rounded_stack_size_rtx, next_arg_reg, - n_pop); + pat = targetm.gen_call_pop (funmem, rounded_stack_size_rtx, + next_arg_reg, n_pop); - emit_call_insn (pat); already_popped = 1; } else -#endif - -#if defined (HAVE_sibcall) && defined (HAVE_sibcall_value) - if ((ecf_flags & ECF_SIBCALL) - && HAVE_sibcall && HAVE_sibcall_value) - { - if (valreg) - emit_call_insn (GEN_SIBCALL_VALUE (valreg, funmem, - rounded_stack_size_rtx, - next_arg_reg, NULL_RTX)); - else - emit_call_insn (GEN_SIBCALL (funmem, rounded_stack_size_rtx, - next_arg_reg, - GEN_INT (struct_value_size))); - } - else -#endif - -#if defined (HAVE_call) && defined (HAVE_call_value) - if (HAVE_call && HAVE_call_value) { if (valreg) - emit_call_insn (GEN_CALL_VALUE (valreg, funmem, rounded_stack_size_rtx, - next_arg_reg, NULL_RTX)); + pat = targetm.gen_call_value (valreg, funmem, rounded_stack_size_rtx, + next_arg_reg, NULL_RTX); else - emit_call_insn (GEN_CALL (funmem, rounded_stack_size_rtx, next_arg_reg, - GEN_INT (struct_value_size))); + pat = targetm.gen_call (funmem, rounded_stack_size_rtx, next_arg_reg, + GEN_INT (struct_value_size)); } - else -#endif - gcc_unreachable (); + emit_insn (pat); /* Find the call we just emitted. */ rtx_call_insn *call_insn = last_call_insn (); diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 35255e9..f8c4468 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -768,7 +768,7 @@ { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx, NULL)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index ca07cc7..32bb36e 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -3110,7 +3110,7 @@ alpha_emit_xfloating_libcall (rtx func, rtx target, rtx operands[], } tmp = gen_rtx_MEM (QImode, func); - tmp = emit_call_insn (GEN_CALL_VALUE (reg, tmp, const0_rtx, + tmp = emit_call_insn (gen_call_value (reg, tmp, const0_rtx, const0_rtx, const0_rtx)); CALL_INSN_FUNCTION_USAGE (tmp) = usage; RTL_CONST_CALL_P (tmp) = 1; diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index 7626d3f..5068f60 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -3646,7 +3646,7 @@ { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index eefb7fa..b6c2047 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -8162,8 +8162,7 @@ size += GET_MODE_SIZE (GET_MODE (src)); } - emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL, - const0_rtx)); + emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL)); size = 0; diff --git a/gcc/config/cr16/cr16.c b/gcc/config/cr16/cr16.c index 8185b59..7b3b6ef 100644 --- a/gcc/config/cr16/cr16.c +++ b/gcc/config/cr16/cr16.c @@ -583,7 +583,7 @@ cr16_function_arg (cumulative_args_t cum_v, machine_mode mode, /* function_arg () is called with this type just after all the args have had their registers assigned. The rtx that function_arg returns from this type is supposed to pass to 'gen_call' but currently it is not - implemented (see macro GEN_CALL). */ + implemented. */ if (type == void_type_node) return NULL_RTX; diff --git a/gcc/config/iq2000/iq2000.md b/gcc/config/iq2000/iq2000.md index e87cb68..bba6760 100644 --- a/gcc/config/iq2000/iq2000.md +++ b/gcc/config/iq2000/iq2000.md @@ -1708,7 +1708,7 @@ { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index 7f4195a..463c827 100644 --- a/gcc/config/m68k/m68k.md +++ b/gcc/config/m68k/m68k.md @@ -6908,7 +6908,7 @@ { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index a0079d5..f4ffd68 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -7055,7 +7055,7 @@ { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index ad92892..46fc0f5 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -8248,7 +8248,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 527ad98..e7d97df 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -9516,7 +9516,7 @@ { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, const0_rtx, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 9665ee6..5b9f051 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -6403,7 +6403,7 @@ /* Pass constm1 to indicate that it may expect a structure value, but we don't know what size it is. */ - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, constm1_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx, NULL, constm1_rtx)); /* Save the function value registers. */ emit_move_insn (adjust_address (result, DImode, 0), valreg1); diff --git a/gcc/config/tilegx/tilegx.md b/gcc/config/tilegx/tilegx.md index 75322e1..944953c 100644 --- a/gcc/config/tilegx/tilegx.md +++ b/gcc/config/tilegx/tilegx.md @@ -2670,7 +2670,7 @@ { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { diff --git a/gcc/config/tilepro/tilepro.md b/gcc/config/tilepro/tilepro.md index a97ebf9..b1e6b81 100644 --- a/gcc/config/tilepro/tilepro.md +++ b/gcc/config/tilepro/tilepro.md @@ -1516,7 +1516,7 @@ { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { diff --git a/gcc/config/visium/visium.md b/gcc/config/visium/visium.md index 969cb88..370b6a4 100644 --- a/gcc/config/visium/visium.md +++ b/gcc/config/visium/visium.md @@ -2375,7 +2375,7 @@ { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx, NULL)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { diff --git a/gcc/genflags.c b/gcc/genflags.c index e67a48b..0dedc8d 100644 --- a/gcc/genflags.c +++ b/gcc/genflags.c @@ -42,7 +42,6 @@ static int max_opno; static void max_operand_1 (rtx); static int num_operands (rtx); static void gen_proto (rtx); -static void gen_macro (const char *, int, int); /* Count the number of match_operand's found. */ @@ -92,32 +91,6 @@ num_operands (rtx insn) return max_opno + 1; } -/* Print out a wrapper macro for a function which corrects the number - of arguments it takes. Any missing arguments are assumed to be at - the end. */ -static void -gen_macro (const char *name, int real, int expect) -{ - int i; - - gcc_assert (real <= expect); - gcc_assert (real); - - /* #define GEN_CALL(A, B, C, D) gen_call((A), (B)) */ - fputs ("#define GEN_", stdout); - for (i = 0; name[i]; i++) - putchar (TOUPPER (name[i])); - - putchar ('('); - for (i = 0; i < expect - 1; i++) - printf ("%c, ", i + 'A'); - printf ("%c) gen_%s (", i + 'A', name); - - for (i = 0; i < real - 1; i++) - printf ("(%c), ", i + 'A'); - printf ("(%c))\n", i + 'A'); -} - /* Print out prototype information for a generator function. If the insn pattern has been elided, print out a dummy generator that does nothing. */ @@ -130,25 +103,6 @@ gen_proto (rtx insn) const char *name = XSTR (insn, 0); int truth = maybe_eval_c_test (XSTR (insn, 2)); - /* Many md files don't refer to the last two operands passed to the - call patterns. This means their generator functions will be two - arguments too short. Instead of changing every md file to touch - those operands, we wrap the prototypes in macros that take the - correct number of arguments. */ - if (name[0] == 'c' || name[0] == 's') - { - if (!strcmp (name, "call") - || !strcmp (name, "call_pop") - || !strcmp (name, "sibcall") - || !strcmp (name, "sibcall_pop")) - gen_macro (name, num, 4); - else if (!strcmp (name, "call_value") - || !strcmp (name, "call_value_pop") - || !strcmp (name, "sibcall_value") - || !strcmp (name, "sibcall_value_pop")) - gen_macro (name, num, 5); - } - if (truth != 0) printf ("extern rtx gen_%-*s (", max_id_len, name); else diff --git a/gcc/gensupport.c b/gcc/gensupport.c index 9e00f13..0480e17 100644 --- a/gcc/gensupport.c +++ b/gcc/gensupport.c @@ -93,6 +93,9 @@ static struct queue_elem **other_tail = &other_queue; static struct queue_elem *define_subst_attr_queue; static struct queue_elem **define_subst_attr_tail = &define_subst_attr_queue; +/* Mapping from DEFINE_* rtxes to their location in the source file. */ +static hash_map <rtx, file_location> *rtx_locs; + static void remove_constraints (rtx); static int is_predicable (struct queue_elem *); @@ -2619,9 +2622,24 @@ read_md_rtx (md_rtx_info *info) else info->index = -1; + if (!rtx_locs) + rtx_locs = new hash_map <rtx, file_location>; + rtx_locs->put (info->def, info->loc); + return true; } +/* Return the file location of DEFINE_* rtx X, which was previously + returned by read_md_rtx. */ +file_location +get_file_location (rtx x) +{ + gcc_assert (rtx_locs); + file_location *entry = rtx_locs->get (x); + gcc_assert (entry); + return *entry; +} + /* Return the number of possible INSN_CODEs. Only meaningful once the whole file has been processed. */ unsigned int diff --git a/gcc/gensupport.h b/gcc/gensupport.h index a15c36a..0199e39 100644 --- a/gcc/gensupport.h +++ b/gcc/gensupport.h @@ -132,6 +132,7 @@ struct pattern_stats extern void get_pattern_stats (struct pattern_stats *ranges, rtvec vec); extern void compute_test_codes (rtx, file_location, char *); +extern file_location get_file_location (rtx); extern const char *get_emit_function (rtx); extern bool needs_barrier_p (rtx); diff --git a/gcc/gentarget-def.c b/gcc/gentarget-def.c index e5e291e..9c8a250 100644 --- a/gcc/gentarget-def.c +++ b/gcc/gentarget-def.c @@ -60,6 +60,43 @@ static hash_table <nofree_string_hash> *stubs; from the C condition to the function name. */ static hash_map <nofree_string_hash, const char *> *have_funcs; +/* Return true if the part of the prototype at P is for an argument + name. If so, point *END_OUT to the first character after the name. + If OPNO_OUT is nonnull, set *OPNO_OUT to the number of the associated + operand. If REQUIRED_OUT is nonnull, set *REQUIRED_OUT to whether the + .md pattern is required to match the operand. */ + +static bool +parse_argument (const char *p, const char **end_out, + unsigned int *opno_out = 0, + bool *required_out = 0) +{ + while (ISSPACE (*p)) + p++; + if (p[0] == 'x' && ISDIGIT (p[1])) + { + p += 1; + if (required_out) + *required_out = true; + } + else if (p[0] == 'o' && p[1] == 'p' && p[2] == 't' && ISDIGIT (p[3])) + { + p += 3; + if (required_out) + *required_out = false; + } + else + return false; + + char *endptr; + unsigned int opno = strtol (p, &endptr, 10); + if (opno_out) + *opno_out = opno; + *end_out = endptr; + return true; +} + + /* Output hook definitions for pattern NAME, which has target-insns.def prototype PROTOTYPE. */ @@ -78,21 +115,27 @@ def_target_insn (const char *name, const char *prototype) char *suffix = XALLOCAVEC (char, strlen (prototype) + 1); i = 0; unsigned int opno = 0; + unsigned int required_ops = 0; + unsigned int this_opno; + bool required_p; for (const char *p = prototype; *p; ++p) - if (*p == 'x' && ISDIGIT (p[1])) + if (parse_argument (p, &p, &this_opno, &required_p)) { - /* This should be a parameter name of the form "x<OPNO>". - That doesn't contribute to the suffix, so skip ahead and - process the following character. */ - char *endptr; - if ((unsigned int) strtol (p + 1, &endptr, 10) != opno - || (*endptr != ',' && *endptr != ')')) + if (this_opno != opno || (*p != ',' && *p != ')')) { error ("invalid prototype for '%s'", name); exit (FATAL_EXIT_CODE); } + if (required_p && required_ops < opno) + { + error ("prototype for '%s' has required operands after" + " optional operands", name); + exit (FATAL_EXIT_CODE); + } opno += 1; - p = endptr; + if (required_p) + required_ops = opno; + /* Skip over ')'s. */ if (*p == ',') suffix[i++] = '_'; } @@ -117,6 +160,22 @@ def_target_insn (const char *name, const char *prototype) const char *have_name = name; if (rtx insn = insns->find_with_hash (name, hash)) { + pattern_stats stats; + get_pattern_stats (&stats, XVEC (insn, 1)); + unsigned int actual_ops = stats.num_generator_args; + if (opno == required_ops && opno != actual_ops) + error_at (get_file_location (insn), + "'%s' must have %d operands (excluding match_dups)", + name, required_ops); + else if (actual_ops < required_ops) + error_at (get_file_location (insn), + "'%s' must have at least %d operands (excluding match_dups)", + name, required_ops); + else if (actual_ops > opno) + error_at (get_file_location (insn), + "'%s' must have no more than %d operands" + " (excluding match_dups)", name, opno); + const char *test = XSTR (insn, 2); truth = maybe_eval_c_test (test); gcc_assert (truth != 0); @@ -139,13 +198,23 @@ def_target_insn (const char *name, const char *prototype) have_name = entry; } printf ("\nstatic rtx_insn *\n"); - printf ("target_gen_%s %s\n", name, prototype); - printf ("{\n"); + printf ("target_gen_%s ", name); + /* Print the prototype with the argument names after ACTUAL_OPS + removed. */ + const char *p = prototype, *end; + while (*p) + if (parse_argument (p, &end, &this_opno) && this_opno >= actual_ops) + p = end; + else + fputc (*p++, stdout); + + printf ("\n{\n"); if (truth < 0) printf (" gcc_checking_assert (targetm.have_%s ());\n", name); printf (" return insnify (gen_%s (", name); - for (i = 0; i < opno; ++i) - printf ("%sx%d", i == 0 ? "" : ", ", i); + for (i = 0; i < actual_ops; ++i) + printf ("%s%s%d", i == 0 ? "" : ", ", + i < required_ops ? "x" : "opt", i); printf ("));\n"); printf ("}\n"); } @@ -157,18 +226,11 @@ def_target_insn (const char *name, const char *prototype) *slot = xstrdup (suffix); printf ("\nstatic rtx_insn *\n"); printf ("invalid_%s ", suffix); + /* Print the prototype with the argument names removed. */ const char *p = prototype; while (*p) - { - if (p[0] == 'x' && ISDIGIT (p[1])) - { - char *endptr; - strtol (p + 1, &endptr, 10); - p = endptr; - } - else - fputc (*p++, stdout); - } + if (!parse_argument (p, &p)) + fputc (*p++, stdout); printf ("\n{\n"); printf (" gcc_unreachable ();\n"); printf ("}\n"); diff --git a/gcc/target-insns.def b/gcc/target-insns.def index d204105..00e0027 100644 --- a/gcc/target-insns.def +++ b/gcc/target-insns.def @@ -27,15 +27,23 @@ where NAME is the name of the pattern and PROTOTYPE is its C prototype. The prototype should use parameter names of the form "x0", "x1", etc. - Patterns that take no operands should have a prototype "(void)". + for the operands that the .md pattern is required to have, followed by + parameter names of the form "optN" for operands that the .md pattern + may choose to ignore. Patterns that never take operands should have + a prototype "(void)". - Instructions should be documented in md.texi rather than here. */ + Pattern names should be documented in md.texi rather than here. */ DEF_TARGET_INSN (allocate_stack, (rtx x0, rtx x1)) DEF_TARGET_INSN (atomic_test_and_set, (rtx x0, rtx x1, rtx x2)) DEF_TARGET_INSN (builtin_longjmp, (rtx x0)) DEF_TARGET_INSN (builtin_setjmp_receiver, (rtx x0)) DEF_TARGET_INSN (builtin_setjmp_setup, (rtx x0)) DEF_TARGET_INSN (canonicalize_funcptr_for_compare, (rtx x0, rtx x1)) +DEF_TARGET_INSN (call, (rtx x0, rtx opt1, rtx opt2, rtx opt3)) +DEF_TARGET_INSN (call_pop, (rtx x0, rtx opt1, rtx opt2, rtx opt3)) +DEF_TARGET_INSN (call_value, (rtx x0, rtx x1, rtx opt2, rtx opt3, rtx opt4)) +DEF_TARGET_INSN (call_value_pop, (rtx x0, rtx x1, rtx opt2, rtx opt3, + rtx opt4)) DEF_TARGET_INSN (casesi, (rtx x0, rtx x1, rtx x2, rtx x3, rtx x4)) DEF_TARGET_INSN (check_stack, (rtx x0)) DEF_TARGET_INSN (clear_cache, (rtx x0, rtx x1)) @@ -69,7 +77,10 @@ DEF_TARGET_INSN (return, (void)) DEF_TARGET_INSN (save_stack_block, (rtx x0, rtx x1)) DEF_TARGET_INSN (save_stack_function, (rtx x0, rtx x1)) DEF_TARGET_INSN (save_stack_nonlocal, (rtx x0, rtx x1)) +DEF_TARGET_INSN (sibcall, (rtx x0, rtx opt1, rtx opt2, rtx opt3)) DEF_TARGET_INSN (sibcall_epilogue, (void)) +DEF_TARGET_INSN (sibcall_value, (rtx x0, rtx x1, rtx opt2, rtx opt3, + rtx opt4)) DEF_TARGET_INSN (simple_return, (void)) DEF_TARGET_INSN (split_stack_prologue, (void)) DEF_TARGET_INSN (split_stack_space_check, (rtx x0, rtx x1)) |