From: Bernd Schmidt Date: Thu, 8 Oct 1998 04:07:40 +0000 (-0600) Subject: stmt.c (n_occurrences): New static function. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2a230e9dc40fd0a9ffe86e0548a935350dd39459;p=gcc.git stmt.c (n_occurrences): New static function. * stmt.c (n_occurrences): New static function. (expand_asm_operands): Verify that all constrains match in the number of alternatives. Verify that '+' or '=' are at the beginning of an output constraint. Don't allow '&' for input operands. Verify that '%' isn't written for the last operand. * reload.c (find_reloads): Abort if an asm is found with invalid constraints; all possible problems ought to be checked for earlier. From-SVN: r22911 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3ecdb777ea8..45090a7a06d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +Thu Oct 8 05:05:34 1998 Bernd Schmidt + + * stmt.c (n_occurrences): New static function. + (expand_asm_operands): Verify that all constrains match in the + number of alternatives. + Verify that '+' or '=' are at the beginning of an output constraint. + Don't allow '&' for input operands. + Verify that '%' isn't written for the last operand. + * reload.c (find_reloads): Abort if an asm is found with invalid + constraints; all possible problems ought to be checked for earlier. + Thu Oct 8 04:26:20 1998 Michael Hayes * flags.h (flag_branch_on_count_reg): Always declare diff --git a/gcc/reload.c b/gcc/reload.c index 428ce879894..32ee0f57e49 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -2442,15 +2442,6 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) bcopy ((char *) constraints, (char *) constraints1, noperands * sizeof (char *)); n_alternatives = n_occurrences (',', constraints[0]) + 1; - for (i = 1; i < noperands; i++) - if (n_alternatives != n_occurrences (',', constraints[i]) + 1) - { - error_for_asm (insn, "operand constraints differ in number of alternatives"); - /* Avoid further trouble with this insn. */ - PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx); - n_reloads = 0; - return; - } } break; } @@ -2510,15 +2501,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) { /* The last operand should not be marked commutative. */ if (i == noperands - 1) - { - if (this_insn_is_asm) - warning_for_asm (this_insn, - "`%%' constraint used with last operand"); - else - abort (); - } - else - commutative = i; + abort (); + + commutative = i; } else if (c >= '0' && c <= '9') { @@ -2528,13 +2513,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) /* An operand may not match itself. */ if (c == i) - { - if (this_insn_is_asm) - warning_for_asm (this_insn, - "operand %d has constraint %d", i, c); - else - abort (); - } + abort (); /* If C can be commuted with C+1, and C might need to match I, then C+1 might also need to match I. */ @@ -3372,14 +3351,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) early_data = decompose (recog_operand[i]); if (modified[i] == RELOAD_READ) - { - if (this_insn_is_asm) - warning_for_asm (this_insn, - "`&' constraint used with input operand"); - else - abort (); - continue; - } + abort (); if (this_alternative[i] == NO_REGS) { diff --git a/gcc/stmt.c b/gcc/stmt.c index b524362d524..658c872fad4 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -425,6 +425,7 @@ struct label_chain static int using_eh_for_cleanups_p = 0; +static int n_occurrences PROTO((int, char *)); static void expand_goto_internal PROTO((tree, rtx, rtx)); static int expand_fixup PROTO((tree, rtx, rtx)); static void fixup_gotos PROTO((struct nesting *, rtx, tree, @@ -1096,8 +1097,18 @@ fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in) f->stack_level = stack_level; } } - - + +/* Return the number of times character C occurs in string S. */ +static int +n_occurrences (c, s) + int c; + char *s; +{ + int n = 0; + while (*s) + n += (*s++ == c); + return n; +} /* Generate RTL for an asm statement (explicit assembler code). BODY is a STRING_CST node containing the assembler code text, @@ -1184,13 +1195,38 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) last_expr_type = 0; + /* Check that the number of alternatives is constant across all + operands. */ + if (outputs || inputs) + { + tree tmp = TREE_PURPOSE (outputs ? outputs : inputs); + int nalternatives = n_occurrences (',', TREE_STRING_POINTER (tmp)); + tree next = inputs; + + tmp = outputs; + while (tmp) + { + char *constraint = TREE_STRING_POINTER (TREE_PURPOSE (tmp)); + if (n_occurrences (',', constraint) != nalternatives) + { + error ("operand constraints for `asm' differ in number of alternatives"); + return; + } + if (TREE_CHAIN (tmp)) + tmp = TREE_CHAIN (tmp); + else + tmp = next, next = 0; + } + } + for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++) { tree val = TREE_VALUE (tail); tree type = TREE_TYPE (val); + char *constraint; + int c_len; int j; - int found_equal = 0; - int found_plus = 0; + int is_inout = 0; int allows_reg = 0; /* If there's an erroneous arg, emit no insn. */ @@ -1202,27 +1238,43 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) the worst that happens if we get it wrong is we issue an error message. */ - for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1; j++) - switch (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j]) + c_len = TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1; + constraint = TREE_STRING_POINTER (TREE_PURPOSE (tail)); + + if (c_len == 0 + || (constraint[0] != '=' && constraint[0] != '+')) + { + error ("output operand constraint lacks `='"); + return; + } + + is_inout = constraint[0] == '+'; + /* Replace '+' with '='. */ + constraint[0] = '='; + /* Make sure we can specify the matching operand. */ + if (is_inout && i > 9) + { + error ("output operand constraint %d contains `+'", i); + return; + } + + for (j = 1; j < c_len; j++) + switch (constraint[j]) { case '+': - /* Make sure we can specify the matching operand. */ - if (i > 9) + case '=': + error ("operand constraint contains '+' or '=' at illegal position."); + return; + + case '%': + if (i + 1 == ninputs + noutputs) { - error ("output operand constraint %d contains `+'", i); + error ("`%%' constraint used with last operand"); return; } - - /* Replace '+' with '='. */ - TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] = '='; - found_plus = 1; break; - case '=': - found_equal = 1; - break; - - case '?': case '!': case '*': case '%': case '&': + case '?': case '!': case '*': case '&': case 'V': case 'm': case 'o': case '<': case '>': case 'E': case 'F': case 'G': case 'H': case 'X': case 's': case 'i': case 'n': @@ -1244,12 +1296,6 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) break; } - if (! found_equal && ! found_plus) - { - error ("output operand constraint lacks `='"); - return; - } - /* If an output operand is not a decl or indirect ref and our constraint allows a register, make a temporary to act as an intermediate. Make the asm insn write into that, then our caller will copy it to @@ -1260,7 +1306,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) && ! (GET_CODE (DECL_RTL (val)) == REG && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type))) || ! allows_reg - || found_plus) + || is_inout) { if (! allows_reg) mark_addressable (TREE_VALUE (tail)); @@ -1278,7 +1324,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) TREE_VALUE (tail) = make_tree (type, output_rtx[i]); } - if (found_plus) + if (is_inout) { inout_mode[ninout] = TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))); inout_opnum[ninout++] = i; @@ -1311,12 +1357,16 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) { int j; int allows_reg = 0; + char *constraint; + int c_len; /* If there's an erroneous arg, emit no insn, because the ASM_INPUT would get VOIDmode and that could cause a crash in reload. */ if (TREE_TYPE (TREE_VALUE (tail)) == error_mark_node) return; + + /* ??? Can this happen, and does the error message make any sense? */ if (TREE_PURPOSE (tail) == NULL_TREE) { error ("hard register `%s' listed as input operand to `asm'", @@ -1324,17 +1374,27 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) return; } - /* Make sure constraint has neither `=' nor `+'. */ + c_len = TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1; + constraint = TREE_STRING_POINTER (TREE_PURPOSE (tail)); - for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1; j++) - switch (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j]) + /* Make sure constraint has neither `=', `+', nor '&'. */ + + for (j = 0; j < c_len; j++) + switch (constraint[j]) { - case '+': case '=': - error ("input operand constraint contains `%c'", - TREE_STRING_POINTER (TREE_PURPOSE (tail))[j]); + case '+': case '=': case '&': + error ("input operand constraint contains `%c'", constraint[j]); return; - case '?': case '!': case '*': case '%': case '&': + case '%': + if (i + 1 == ninputs - ninout) + { + error ("`%%' constraint used with last operand"); + return; + } + break; + + case '?': case '!': case '*': case 'V': case 'm': case 'o': case '<': case '>': case 'E': case 'F': case 'G': case 'H': case 'X': case 's': case 'i': case 'n': @@ -1352,8 +1412,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) operands to memory. */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - if (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] - >= '0' + noutputs) + if (constraint[j] >= '0' + noutputs) { error ("matching constraint references invalid operand number"); @@ -1398,10 +1457,10 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) emit_move_insn (memloc, XVECEXP (body, 3, i)); XVECEXP (body, 3, i) = memloc; } - + XVECEXP (body, 4, i) /* constraints */ = gen_rtx_ASM_INPUT (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))), - TREE_STRING_POINTER (TREE_PURPOSE (tail))); + constraint); i++; }