- gen_ccmp_first expands the first compare in CCMP.
- gen_ccmp_next expands the following compares.
- * If the final result is not used in a COND_EXPR (checked by function
- used_in_cond_stmt_p), it calls cstorecc4 pattern to store the CC to a
- general register.
+ * We use cstorecc4 pattern to convert the CCmode intermediate to
+ the integer mode result that expand_normal is expecting.
Since the operands of the later compares might clobber CC reg, we do not
emit the insns during expand. We keep the insn sequences in two seq
return false;
}
-/* Check whether EXP is used in a GIMPLE_COND statement or not. */
-static bool
-used_in_cond_stmt_p (tree exp)
-{
- bool expand_cond = false;
- imm_use_iterator ui;
- gimple use_stmt;
- FOR_EACH_IMM_USE_STMT (use_stmt, ui, exp)
- if (gimple_code (use_stmt) == GIMPLE_COND)
- {
- tree op1 = gimple_cond_rhs (use_stmt);
- if (integer_zerop (op1))
- expand_cond = true;
- BREAK_FROM_IMM_USE_STMT (ui);
- }
- else if (gimple_code (use_stmt) == GIMPLE_ASSIGN
- && gimple_expr_code (use_stmt) == COND_EXPR)
- {
- if (gimple_assign_rhs1 (use_stmt) == exp)
- expand_cond = true;
- }
-
- return expand_cond;
-}
-
/* PREV is the CC flag from precvious compares. The function expands the
next compare based on G which ops previous compare with CODE.
PREP_SEQ returns all insns to prepare opearands for compare.
enum machine_mode cc_mode = CCmode;
tree lhs = gimple_assign_lhs (g);
- /* TMP should be CC. If it is used in a GIMPLE_COND, just return it.
- Note: Target needs to define "cbranchcc4". */
- if (used_in_cond_stmt_p (lhs))
- {
- emit_insn (prep_seq);
- emit_insn (gen_seq);
- return tmp;
- }
-
#ifdef SELECT_CC_MODE
cc_mode = SELECT_CC_MODE (NE, tmp, const0_rtx);
#endif
- /* If TMP is not used in a GIMPLE_COND, store it with a csctorecc4_optab.
- Note: Target needs to define "cstorecc4". */
icode = optab_handler (cstore_optab, cc_mode);
if (icode != CODE_FOR_nothing)
{
--- /dev/null
+typedef unsigned int source_location;
+typedef source_location location_t;
+extern void error_at (location_t, const char *, ...)
+ __attribute__ ((__format__ (__gcc_tdiag__, 2, 3)))
+ __attribute__ ((__nonnull__ (2)));
+
+class Lex
+{
+ static int fetch_char (const char *str, unsigned int *value);
+ location_t location () const;
+ const char *advance_one_utf8_char (const char *, unsigned int *, bool *);
+ const char *advance_one_char (const char *, bool, unsigned int *, bool *);
+ int lineoff_;
+ int lineno_;
+};
+
+int
+Lex::fetch_char (const char *p, unsigned int *value)
+{
+ unsigned char c = *p;
+ if (c <= 0x7f)
+ {
+ return 1;
+ }
+ else if ((c & 0xe0) == 0xc0 && (p[1] & 0xc0) == 0x80)
+ {
+ *value = (((c & 0x1f) << 6) + (p[1] & 0x3f));
+ }
+ {
+ *value = (((c & 0xf) << 12) + (p[2] & 0x3f));
+ }
+}
+
+const char *
+Lex::advance_one_utf8_char (const char *p, unsigned int *value,
+ bool * issued_error)
+{
+ *issued_error = false;
+ if (*p == '\0')
+ {
+ *issued_error = true;
+ return p + 1;
+ }
+ int adv = Lex::fetch_char (p, value);
+ if (*value == 0xfeff && (this->lineno_ != 1 || this->lineoff_ != 0))
+ {
+ *issued_error = true;
+ }
+ return p + adv;
+}
+
+const char *
+Lex::advance_one_char (const char *p, bool is_single_quote,
+ unsigned int *value, bool * is_character)
+{
+ {
+ bool issued_error;
+ const char *ret = this->advance_one_utf8_char (p, value, &issued_error);
+ if (is_single_quote
+ && (*value == '\'' || *value == '\n') && !issued_error)
+ error_at (this->location (), "invalid character literal");
+ }
+}