📄 genattrtab.c
字号:
{ attr = find_attr (XSTR (exp, 0), 0); if (attr == NULL) { if (! strcmp (XSTR (exp, 0), "alternative")) { XSTR (exp, 0) = alternative_name; /* This can't be simplified any further. */ RTX_UNCHANGING_P (exp) = 1; return exp; } else fatal ("Unknown attribute `%s' in EQ_ATTR", XEXP (exp, 0)); } if (is_const && ! attr->is_const) fatal ("Constant expression uses insn attribute `%s' in EQ_ATTR", XEXP (exp, 0)); /* Copy this just to make it permanent, so expressions using it can be permanent too. */ exp = attr_eq (XSTR (exp, 0), XSTR (exp, 1)); /* It shouldn't be possible to simplify the value given to a constant attribute, so don't expand this until it's time to write the test expression. */ if (attr->is_const) RTX_UNCHANGING_P (exp) = 1; if (attr->is_numeric) { for (p = XSTR (exp, 1); *p; p++) if (*p < '0' || *p > '9') fatal ("Attribute `%s' takes only numeric values", XEXP (exp, 0)); } else { for (av = attr->first_value; av; av = av->next) if (GET_CODE (av->value) == CONST_STRING && ! strcmp (XSTR (exp, 1), XSTR (av->value, 0))) break; if (av == NULL) fatal ("Unknown value `%s' for `%s' attribute", XEXP (exp, 1), XEXP (exp, 0)); } } else { /* Make an IOR tree of the possible values. */ orexp = false_rtx; name_ptr = XSTR (exp, 1); while ((p = next_comma_elt (&name_ptr)) != NULL) { newexp = attr_eq (XSTR (exp, 0), p); orexp = insert_right_side (IOR, orexp, newexp, -2); } return check_attr_test (orexp, is_const); } break; case CONST_INT: /* Either TRUE or FALSE. */ if (XWINT (exp, 0)) return true_rtx; else return false_rtx; case IOR: case AND: XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), is_const); XEXP (exp, 1) = check_attr_test (XEXP (exp, 1), is_const); break; case NOT: XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), is_const); break; case MATCH_OPERAND: if (is_const) fatal ("RTL operator \"%s\" not valid in constant attribute test", GET_RTX_NAME (MATCH_OPERAND)); /* These cases can't be simplified. */ RTX_UNCHANGING_P (exp) = 1; break; case LE: case LT: case GT: case GE: case LEU: case LTU: case GTU: case GEU: case NE: case EQ: if (GET_CODE (XEXP (exp, 0)) == SYMBOL_REF && GET_CODE (XEXP (exp, 1)) == SYMBOL_REF) exp = attr_rtx (GET_CODE (exp), attr_rtx (SYMBOL_REF, XSTR (XEXP (exp, 0), 0)), attr_rtx (SYMBOL_REF, XSTR (XEXP (exp, 1), 0))); /* These cases can't be simplified. */ RTX_UNCHANGING_P (exp) = 1; break; case SYMBOL_REF: if (is_const) { /* These cases are valid for constant attributes, but can't be simplified. */ exp = attr_rtx (SYMBOL_REF, XSTR (exp, 0)); RTX_UNCHANGING_P (exp) = 1; break; } default: fatal ("RTL operator \"%s\" not valid in attribute test", GET_RTX_NAME (GET_CODE (exp))); } return exp;}/* Given an expression, ensure that it is validly formed and that all named attribute values are valid for the given attribute. Issue a fatal error if not. If no attribute is specified, assume a numeric attribute. Return a perhaps modified replacement expression for the value. */static rtxcheck_attr_value (exp, attr) rtx exp; struct attr_desc *attr;{ struct attr_value *av; char *p; int i; switch (GET_CODE (exp)) { case CONST_INT: if (attr && ! attr->is_numeric) fatal ("CONST_INT not valid for non-numeric `%s' attribute", attr->name); if (INTVAL (exp) < 0) fatal ("Negative numeric value specified for `%s' attribute", attr->name); break; case CONST_STRING: if (! strcmp (XSTR (exp, 0), "*")) break; if (attr == 0 || attr->is_numeric) { p = XSTR (exp, 0); if (attr && attr->negative_ok && *p == '-') p++; for (; *p; p++) if (*p > '9' || *p < '0') fatal ("Non-numeric value for numeric `%s' attribute", attr ? attr->name : "internal"); break; } for (av = attr->first_value; av; av = av->next) if (GET_CODE (av->value) == CONST_STRING && ! strcmp (XSTR (av->value, 0), XSTR (exp, 0))) break; if (av == NULL) fatal ("Unknown value `%s' for `%s' attribute", XSTR (exp, 0), attr ? attr->name : "internal"); break; case IF_THEN_ELSE: XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), attr ? attr->is_const : 0); XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr); XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr); break; case COND: if (XVECLEN (exp, 0) % 2 != 0) fatal ("First operand of COND must have even length"); for (i = 0; i < XVECLEN (exp, 0); i += 2) { XVECEXP (exp, 0, i) = check_attr_test (XVECEXP (exp, 0, i), attr ? attr->is_const : 0); XVECEXP (exp, 0, i + 1) = check_attr_value (XVECEXP (exp, 0, i + 1), attr); } XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr); break; case SYMBOL_REF: if (attr && attr->is_const) /* A constant SYMBOL_REF is valid as a constant attribute test and is expanded later by make_canonical into a COND. */ return attr_rtx (SYMBOL_REF, XSTR (exp, 0)); /* Otherwise, fall through... */ default: fatal ("Illegal operation `%s' for attribute value", GET_RTX_NAME (GET_CODE (exp))); } return exp;}/* Given an SET_ATTR_ALTERNATIVE expression, convert to the canonical SET. It becomes a COND with each test being (eq_attr "alternative "n") */static rtxconvert_set_attr_alternative (exp, num_alt, insn_code, insn_index) rtx exp; int num_alt; int insn_code, insn_index;{ rtx condexp; int i; if (XVECLEN (exp, 1) != num_alt) fatal ("Bad number of entries in SET_ATTR_ALTERNATIVE for insn %d", insn_index); /* Make a COND with all tests but the last. Select the last value via the default. */ condexp = rtx_alloc (COND); XVEC (condexp, 0) = rtvec_alloc ((num_alt - 1) * 2); for (i = 0; i < num_alt - 1; i++) { char *p; p = attr_numeral (i); XVECEXP (condexp, 0, 2 * i) = attr_eq (alternative_name, p);#if 0 /* Sharing this EQ_ATTR rtl causes trouble. */ XVECEXP (condexp, 0, 2 * i) = rtx_alloc (EQ_ATTR); XSTR (XVECEXP (condexp, 0, 2 * i), 0) = alternative_name; XSTR (XVECEXP (condexp, 0, 2 * i), 1) = p;#endif XVECEXP (condexp, 0, 2 * i + 1) = XVECEXP (exp, 1, i); } XEXP (condexp, 1) = XVECEXP (exp, 1, i); return attr_rtx (SET, attr_rtx (ATTR, XSTR (exp, 0)), condexp);}/* Given a SET_ATTR, convert to the appropriate SET. If a comma-separated list of values is given, convert to SET_ATTR_ALTERNATIVE first. */static rtxconvert_set_attr (exp, num_alt, insn_code, insn_index) rtx exp; int num_alt; int insn_code, insn_index;{ rtx newexp; char *name_ptr; char *p; int n; /* See how many alternative specified. */ n = n_comma_elts (XSTR (exp, 1)); if (n == 1) return attr_rtx (SET, attr_rtx (ATTR, XSTR (exp, 0)), attr_rtx (CONST_STRING, XSTR (exp, 1))); newexp = rtx_alloc (SET_ATTR_ALTERNATIVE); XSTR (newexp, 0) = XSTR (exp, 0); XVEC (newexp, 1) = rtvec_alloc (n); /* Process each comma-separated name. */ name_ptr = XSTR (exp, 1); n = 0; while ((p = next_comma_elt (&name_ptr)) != NULL) XVECEXP (newexp, 1, n++) = attr_rtx (CONST_STRING, p); return convert_set_attr_alternative (newexp, num_alt, insn_code, insn_index);}/* Scan all definitions, checking for validity. Also, convert any SET_ATTR and SET_ATTR_ALTERNATIVE expressions to the corresponding SET expressions. */static voidcheck_defs (){ struct insn_def *id; struct attr_desc *attr; int i; rtx value; for (id = defs; id; id = id->next) { if (XVEC (id->def, id->vec_idx) == NULL) continue; for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++) { value = XVECEXP (id->def, id->vec_idx, i); switch (GET_CODE (value)) { case SET: if (GET_CODE (XEXP (value, 0)) != ATTR) fatal ("Bad attribute set in pattern %d", id->insn_index); break; case SET_ATTR_ALTERNATIVE: value = convert_set_attr_alternative (value, id->num_alternatives, id->insn_code, id->insn_index); break; case SET_ATTR: value = convert_set_attr (value, id->num_alternatives, id->insn_code, id->insn_index); break; default: fatal ("Invalid attribute code `%s' for pattern %d", GET_RTX_NAME (GET_CODE (value)), id->insn_index); } if ((attr = find_attr (XSTR (XEXP (value, 0), 0), 0)) == NULL) fatal ("Unknown attribute `%s' for pattern number %d", XSTR (XEXP (value, 0), 0), id->insn_index); XVECEXP (id->def, id->vec_idx, i) = value; XEXP (value, 1) = check_attr_value (XEXP (value, 1), attr); } }}/* Given a constant SYMBOL_REF expression, convert to a COND that explicitly tests each enumerated value. */static rtxconvert_const_symbol_ref (exp, attr) rtx exp; struct attr_desc *attr;{ rtx condexp; struct attr_value *av; int i; int num_alt = 0; for (av = attr->first_value; av; av = av->next) num_alt++; /* Make a COND with all tests but the last, and in the original order. Select the last value via the default. Note that the attr values are constructed in reverse order. */ condexp = rtx_alloc (COND); XVEC (condexp, 0) = rtvec_alloc ((num_alt - 1) * 2); av = attr->first_value; XEXP (condexp, 1) = av->value; for (i = num_alt - 2; av = av->next, i >= 0; i--) { char *p, *string; rtx value; string = p = (char *) oballoc (2 + strlen (attr->name) + strlen (XSTR (av->value, 0))); strcpy (p, attr->name); strcat (p, "_"); strcat (p, XSTR (av->value, 0)); for (; *p != '\0'; p++) if (*p >= 'a' && *p <= 'z') *p -= 'a' - 'A'; value = attr_rtx (SYMBOL_REF, string); RTX_UNCHANGING_P (value) = 1; XVECEXP (condexp, 0, 2 * i) = attr_rtx (EQ, exp, value); XVECEXP (condexp, 0, 2 * i + 1) = av->value; } return condexp;}/* Given a valid expression for an attribute value, remove any IF_THEN_ELSE expressions by converting them into a COND. This removes cases from this program. Also, replace an attribute value of "*" with the default attribute value. */static rtxmake_canonical (attr, exp) struct attr_desc *attr; rtx exp;{ int i; rtx newexp; switch (GET_CODE (exp)) { case CONST_INT: exp = make_numeric_value (INTVAL (exp)); break; case CONST_STRING: if (! strcmp (XSTR (exp, 0), "*")) { if (attr == 0 || attr->default_val == 0) fatal ("(attr_value \"*\") used in invalid context."); exp = attr->default_val->value; } break; case SYMBOL_REF: if (!attr->is_const || RTX_UNCHANGING_P (exp)) break; /* The SYMBOL_REF is constant for a given run, so mark it as unchanging. This makes the COND something that won't be considered an arbitrary expression by walk_attr_value. */ RTX_UNCHANGING_P (exp) = 1; exp = convert_const_symbol_ref (exp, attr); RTX_UNCHANGING_P (exp) = 1; exp = check_attr_value (exp, attr); /* Goto COND case since this is now a COND. Note that while the new expression is rescanned, all symbol_ref notes are mared as unchanging. */ goto cond; case IF_THEN_ELSE: newexp = rtx_alloc (COND); XVEC (newexp, 0) = rtvec_alloc (2); XVECEXP (newexp, 0, 0) = XEXP (exp, 0); XVECEXP (newexp, 0, 1) = XEXP (exp, 1); XEXP (newexp, 1) = XEXP (exp, 2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -