📄 genattrtab.c
字号:
register RTX_CODE code; register char *format_ptr; /* No need to copy a permanent object. */ if (RTX_INTEGRATED_P (orig)) return orig; code = GET_CODE (orig); switch (code) { case REG: case QUEUED: case CONST_INT: case CONST_DOUBLE: case SYMBOL_REF: case CODE_LABEL: case PC: case CC0: return orig; } copy = rtx_alloc (code); PUT_MODE (copy, GET_MODE (orig)); copy->in_struct = orig->in_struct; copy->volatil = orig->volatil; copy->unchanging = orig->unchanging; copy->integrated = orig->integrated; format_ptr = GET_RTX_FORMAT (GET_CODE (copy)); for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++) { switch (*format_ptr++) { case 'e': XEXP (copy, i) = XEXP (orig, i); if (XEXP (orig, i) != NULL) XEXP (copy, i) = attr_copy_rtx (XEXP (orig, i)); break; case 'E': case 'V': XVEC (copy, i) = XVEC (orig, i); if (XVEC (orig, i) != NULL) { XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i)); for (j = 0; j < XVECLEN (copy, i); j++) XVECEXP (copy, i, j) = attr_copy_rtx (XVECEXP (orig, i, j)); } break; case 'n': case 'i': XINT (copy, i) = XINT (orig, i); break; case 'w': XWINT (copy, i) = XWINT (orig, i); break; case 's': case 'S': XSTR (copy, i) = XSTR (orig, i); break; default: abort (); } } return copy;}/* Given a test expression for an attribute, ensure it is validly formed. IS_CONST indicates whether the expression is constant for each compiler run (a constant expression may not test any particular insn). Convert (eq_attr "att" "a1,a2") to (ior (eq_attr ... ) (eq_attrq ..)) and (eq_attr "att" "!a1") to (not (eq_attr "att" "a1")). Do the latter test first so that (eq_attr "att" "!a1,a2,a3") works as expected. Update the string address in EQ_ATTR expression to be the same used in the attribute (or `alternative_name') to speed up subsequent `find_attr' calls and eliminate most `strcmp' calls. Return the new expression, if any. */static rtxcheck_attr_test (exp, is_const) rtx exp; int is_const;{ struct attr_desc *attr; struct attr_value *av; char *name_ptr, *p; rtx orexp, newexp; switch (GET_CODE (exp)) { case EQ_ATTR: /* Handle negation test. */ if (XSTR (exp, 1)[0] == '!') return check_attr_test (attr_rtx (NOT, attr_eq (XSTR (exp, 0), &XSTR (exp, 1)[1])), is_const); else if (n_comma_elts (XSTR (exp, 1)) == 1) { 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, -2); } return check_attr_test (orexp, is_const); } break; case ATTR_FLAG: 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 ("Invalid 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -