📄 genattrtab.c
字号:
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); exp = newexp; /* Fall through to COND case since this is now a COND. */ case COND: cond: { int allsame = 1; rtx defval; /* First, check for degenerate COND. */ if (XVECLEN (exp, 0) == 0) return make_canonical (attr, XEXP (exp, 1)); defval = XEXP (exp, 1) = make_canonical (attr, XEXP (exp, 1)); for (i = 0; i < XVECLEN (exp, 0); i += 2) { XVECEXP (exp, 0, i) = copy_boolean (XVECEXP (exp, 0, i)); XVECEXP (exp, 0, i + 1) = make_canonical (attr, XVECEXP (exp, 0, i + 1)); if (! rtx_equal_p (XVECEXP (exp, 0, i + 1), defval)) allsame = 0; } if (allsame) return defval; break; } } return exp;}static rtxcopy_boolean (exp) rtx exp;{ if (GET_CODE (exp) == AND || GET_CODE (exp) == IOR) return attr_rtx (GET_CODE (exp), copy_boolean (XEXP (exp, 0)), copy_boolean (XEXP (exp, 1))); return exp;}/* Given a value and an attribute description, return a `struct attr_value *' that represents that value. This is either an existing structure, if the value has been previously encountered, or a newly-created structure. `insn_code' is the code of an insn whose attribute has the specified value (-2 if not processing an insn). We ensure that all insns for a given value have the same number of alternatives if the value checks alternatives. */static struct attr_value *get_attr_value (value, attr, insn_code) rtx value; struct attr_desc *attr; int insn_code;{ struct attr_value *av; int num_alt = 0; value = make_canonical (attr, value); if (compares_alternatives_p (value)) { if (insn_code < 0 || insn_alternatives == NULL) fatal ("(eq_attr \"alternatives\" ...) used in non-insn context"); else num_alt = insn_alternatives[insn_code]; } for (av = attr->first_value; av; av = av->next) if (rtx_equal_p (value, av->value) && (num_alt == 0 || av->first_insn == NULL || insn_alternatives[av->first_insn->insn_code])) return av; av = (struct attr_value *) oballoc (sizeof (struct attr_value)); av->value = value; av->next = attr->first_value; attr->first_value = av; av->first_insn = NULL; av->num_insns = 0; av->has_asm_insn = 0; return av;}/* After all DEFINE_DELAYs have been read in, create internal attributes to generate the required routines. First, we compute the number of delay slots for each insn (as a COND of each of the test expressions in DEFINE_DELAYs). Then, if more than one delay type is specified, we compute a similar function giving the DEFINE_DELAY ordinal for each insn. Finally, for each [DEFINE_DELAY, slot #] pair, we compute an attribute that tells whether a given insn can be in that delay slot. Normal attribute filling and optimization expands these to contain the information needed to handle delay slots. */static voidexpand_delays (){ struct delay_desc *delay; rtx condexp; rtx newexp; int i; char *p; /* First, generate data for `num_delay_slots' function. */ condexp = rtx_alloc (COND); XVEC (condexp, 0) = rtvec_alloc (num_delays * 2); XEXP (condexp, 1) = make_numeric_value (0); for (i = 0, delay = delays; delay; i += 2, delay = delay->next) { XVECEXP (condexp, 0, i) = XEXP (delay->def, 0); XVECEXP (condexp, 0, i + 1) = make_numeric_value (XVECLEN (delay->def, 1) / 3); } make_internal_attr ("*num_delay_slots", condexp, 0); /* If more than one delay type, do the same for computing the delay type. */ if (num_delays > 1) { condexp = rtx_alloc (COND); XVEC (condexp, 0) = rtvec_alloc (num_delays * 2); XEXP (condexp, 1) = make_numeric_value (0); for (i = 0, delay = delays; delay; i += 2, delay = delay->next) { XVECEXP (condexp, 0, i) = XEXP (delay->def, 0); XVECEXP (condexp, 0, i + 1) = make_numeric_value (delay->num); } make_internal_attr ("*delay_type", condexp, 1); } /* For each delay possibility and delay slot, compute an eligibility attribute for non-annulled insns and for each type of annulled (annul if true and annul if false). */ for (delay = delays; delay; delay = delay->next) { for (i = 0; i < XVECLEN (delay->def, 1); i += 3) { condexp = XVECEXP (delay->def, 1, i); if (condexp == 0) condexp = false_rtx; newexp = attr_rtx (IF_THEN_ELSE, condexp, make_numeric_value (1), make_numeric_value (0)); p = attr_printf (sizeof ("*delay__") + MAX_DIGITS*2, "*delay_%d_%d", delay->num, i / 3); make_internal_attr (p, newexp, 1); if (have_annul_true) { condexp = XVECEXP (delay->def, 1, i + 1); if (condexp == 0) condexp = false_rtx; newexp = attr_rtx (IF_THEN_ELSE, condexp, make_numeric_value (1), make_numeric_value (0)); p = attr_printf (sizeof ("*annul_true__") + MAX_DIGITS*2, "*annul_true_%d_%d", delay->num, i / 3); make_internal_attr (p, newexp, 1); } if (have_annul_false) { condexp = XVECEXP (delay->def, 1, i + 2); if (condexp == 0) condexp = false_rtx; newexp = attr_rtx (IF_THEN_ELSE, condexp, make_numeric_value (1), make_numeric_value (0)); p = attr_printf (sizeof ("*annul_false__") + MAX_DIGITS*2, "*annul_false_%d_%d", delay->num, i / 3); make_internal_attr (p, newexp, 1); } } }}/* This function is given a left and right side expression and an operator. Each side is a conditional expression, each alternative of which has a numerical value. The function returns another conditional expression which, for every possible set of condition values, returns a value that is the operator applied to the values of the two sides. Since this is called early, it must also support IF_THEN_ELSE. */static rtxoperate_exp (op, left, right) enum operator op; rtx left, right;{ int left_value, right_value; rtx newexp; int i; /* If left is a string, apply operator to it and the right side. */ if (GET_CODE (left) == CONST_STRING) { /* If right is also a string, just perform the operation. */ if (GET_CODE (right) == CONST_STRING) { left_value = atoi (XSTR (left, 0)); right_value = atoi (XSTR (right, 0)); switch (op) { case PLUS_OP: i = left_value + right_value; break; case MINUS_OP: i = left_value - right_value; break; case POS_MINUS_OP: /* The positive part of LEFT - RIGHT. */ if (left_value > right_value) i = left_value - right_value; else i = 0; break; case OR_OP: i = left_value | right_value; break; case EQ_OP: i = left_value == right_value; break; case RANGE_OP: i = (left_value << (HOST_BITS_PER_INT / 2)) | right_value; break; case MAX_OP: if (left_value > right_value) i = left_value; else i = right_value; break; case MIN_OP: if (left_value < right_value) i = left_value; else i = right_value; break; default: abort (); } return make_numeric_value (i); } else if (GET_CODE (right) == IF_THEN_ELSE) { /* Apply recursively to all values within. */ rtx newleft = operate_exp (op, left, XEXP (right, 1)); rtx newright = operate_exp (op, left, XEXP (right, 2)); if (rtx_equal_p (newleft, newright)) return newleft; return attr_rtx (IF_THEN_ELSE, XEXP (right, 0), newleft, newright); } else if (GET_CODE (right) == COND) { int allsame = 1; rtx defval; newexp = rtx_alloc (COND); XVEC (newexp, 0) = rtvec_alloc (XVECLEN (right, 0)); defval = XEXP (newexp, 1) = operate_exp (op, left, XEXP (right, 1)); for (i = 0; i < XVECLEN (right, 0); i += 2) { XVECEXP (newexp, 0, i) = XVECEXP (right, 0, i); XVECEXP (newexp, 0, i + 1) = operate_exp (op, left, XVECEXP (right, 0, i + 1)); if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1), defval)) allsame = 0; } /* If the resulting cond is trivial (all alternatives give the same value), optimize it away. */ if (allsame) { obstack_free (rtl_obstack, newexp); return operate_exp (op, left, XEXP (right, 1)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -