📄 genattrtab.c
字号:
/* Add an entry to the hash table for STRING with hash code HASHCODE. */static voidattr_hash_add_string (hashcode, str) int hashcode; char *str;{ register struct attr_hash *h; h = (struct attr_hash *) obstack_alloc (hash_obstack, sizeof (struct attr_hash)); h->hashcode = -hashcode; h->u.str = str; h->next = attr_hash_table[hashcode % RTL_HASH_SIZE]; attr_hash_table[hashcode % RTL_HASH_SIZE] = h;}/* Generate an RTL expression, but avoid duplicates. Set the RTX_INTEGRATED_P flag for these permanent objects. In some cases we cannot uniquify; then we return an ordinary impermanent rtx with RTX_INTEGRATED_P clear. Args are like gen_rtx, but without the mode: rtx attr_rtx (code, [element1, ..., elementn]) *//*VARARGS1*/static rtxattr_rtx (va_alist) va_dcl{ va_list p; enum rtx_code code; register int i; /* Array indices... */ register char *fmt; /* Current rtx's format... */ register rtx rt_val; /* RTX to return to caller... */ int hashcode; register struct attr_hash *h; struct obstack *old_obstack = rtl_obstack; va_start (p); code = va_arg (p, enum rtx_code); /* For each of several cases, search the hash table for an existing entry. Use that entry if one is found; otherwise create a new RTL and add it to the table. */ if (GET_RTX_CLASS (code) == '1') { rtx arg0 = va_arg (p, rtx); /* A permanent object cannot point to impermanent ones. */ if (! RTX_INTEGRATED_P (arg0)) { rt_val = rtx_alloc (code); XEXP (rt_val, 0) = arg0; va_end (p); return rt_val; } hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0)); for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next) if (h->hashcode == hashcode && GET_CODE (h->u.rtl) == code && XEXP (h->u.rtl, 0) == arg0) goto found; if (h == 0) { rtl_obstack = hash_obstack; rt_val = rtx_alloc (code); XEXP (rt_val, 0) = arg0; } } else if (GET_RTX_CLASS (code) == 'c' || GET_RTX_CLASS (code) == '2' || GET_RTX_CLASS (code) == '<') { rtx arg0 = va_arg (p, rtx); rtx arg1 = va_arg (p, rtx); /* A permanent object cannot point to impermanent ones. */ if (! RTX_INTEGRATED_P (arg0) || ! RTX_INTEGRATED_P (arg1)) { rt_val = rtx_alloc (code); XEXP (rt_val, 0) = arg0; XEXP (rt_val, 1) = arg1; va_end (p); return rt_val; } hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0) + RTL_HASH (arg1)); for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next) if (h->hashcode == hashcode && GET_CODE (h->u.rtl) == code && XEXP (h->u.rtl, 0) == arg0 && XEXP (h->u.rtl, 1) == arg1) goto found; if (h == 0) { rtl_obstack = hash_obstack; rt_val = rtx_alloc (code); XEXP (rt_val, 0) = arg0; XEXP (rt_val, 1) = arg1; } } else if (GET_RTX_LENGTH (code) == 1 && GET_RTX_FORMAT (code)[0] == 's') { char * arg0 = va_arg (p, char *); if (code == SYMBOL_REF) arg0 = attr_string (arg0, strlen (arg0)); hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0)); for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next) if (h->hashcode == hashcode && GET_CODE (h->u.rtl) == code && XSTR (h->u.rtl, 0) == arg0) goto found; if (h == 0) { rtl_obstack = hash_obstack; rt_val = rtx_alloc (code); XSTR (rt_val, 0) = arg0; } } else if (GET_RTX_LENGTH (code) == 2 && GET_RTX_FORMAT (code)[0] == 's' && GET_RTX_FORMAT (code)[1] == 's') { char *arg0 = va_arg (p, char *); char *arg1 = va_arg (p, char *); hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0) + RTL_HASH (arg1)); for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next) if (h->hashcode == hashcode && GET_CODE (h->u.rtl) == code && XSTR (h->u.rtl, 0) == arg0 && XSTR (h->u.rtl, 1) == arg1) goto found; if (h == 0) { rtl_obstack = hash_obstack; rt_val = rtx_alloc (code); XSTR (rt_val, 0) = arg0; XSTR (rt_val, 1) = arg1; } } else if (code == CONST_INT) { HOST_WIDE_INT arg0 = va_arg (p, HOST_WIDE_INT); if (arg0 == 0) return false_rtx; if (arg0 == 1) return true_rtx; goto nohash; } else { nohash: rt_val = rtx_alloc (code); /* Allocate the storage space. */ fmt = GET_RTX_FORMAT (code); /* Find the right format... */ for (i = 0; i < GET_RTX_LENGTH (code); i++) { switch (*fmt++) { case '0': /* Unused field. */ break; case 'i': /* An integer? */ XINT (rt_val, i) = va_arg (p, int); break; case 'w': /* A wide integer? */ XWINT (rt_val, i) = va_arg (p, HOST_WIDE_INT); break; case 's': /* A string? */ XSTR (rt_val, i) = va_arg (p, char *); break; case 'e': /* An expression? */ case 'u': /* An insn? Same except when printing. */ XEXP (rt_val, i) = va_arg (p, rtx); break; case 'E': /* An RTX vector? */ XVEC (rt_val, i) = va_arg (p, rtvec); break; default: abort(); } } va_end (p); return rt_val; } rtl_obstack = old_obstack; va_end (p); attr_hash_add_rtx (hashcode, rt_val); RTX_INTEGRATED_P (rt_val) = 1; return rt_val; found: va_end (p); return h->u.rtl;}/* Create a new string printed with the printf line arguments into a space of at most LEN bytes: rtx attr_printf (len, format, [arg1, ..., argn]) */#ifdef HAVE_VPRINTF/*VARARGS2*/static char *attr_printf (va_alist) va_dcl{ va_list p; register int len; register char *fmt; register char *str; /* Print the string into a temporary location. */ va_start (p); len = va_arg (p, int); str = (char *) alloca (len); fmt = va_arg (p, char *); vsprintf (str, fmt, p); va_end (p); return attr_string (str, strlen (str));}#else /* not HAVE_VPRINTF */static char *attr_printf (len, fmt, arg1, arg2, arg3) int len; char *fmt; char *arg1, *arg2, *arg3; /* also int */{ register char *str; /* Print the string into a temporary location. */ str = (char *) alloca (len); sprintf (str, fmt, arg1, arg2, arg3); return attr_string (str, strlen (str));}#endif /* not HAVE_VPRINTF */rtxattr_eq (name, value) char *name, *value;{ return attr_rtx (EQ_ATTR, attr_string (name, strlen (name)), attr_string (value, strlen (value)));}char *attr_numeral (n) int n;{ return XSTR (make_numeric_value (n), 0);}/* Return a permanent (possibly shared) copy of a string STR (not assumed to be null terminated) with LEN bytes. */static char *attr_string (str, len) char *str; int len;{ register struct attr_hash *h; int hashcode; int i; register char *new_str; /* Compute the hash code. */ hashcode = (len + 1) * 613 + (unsigned)str[0]; for (i = 1; i <= len; i += 2) hashcode = ((hashcode * 613) + (unsigned)str[i]); if (hashcode < 0) hashcode = -hashcode; /* Search the table for the string. */ for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next) if (h->hashcode == -hashcode && h->u.str[0] == str[0] && !strncmp (h->u.str, str, len)) return h->u.str; /* <-- return if found. */ /* Not found; create a permanent copy and add it to the hash table. */ new_str = (char *) obstack_alloc (hash_obstack, len + 1); bcopy (str, new_str, len); new_str[len] = '\0'; attr_hash_add_string (hashcode, new_str); return new_str; /* Return the new string. */}/* Check two rtx's for equality of contents, taking advantage of the fact that if both are hashed then they can't be equal unless they are the same object. */intattr_equal_p (x, y) rtx x, y;{ return (x == y || (! (RTX_INTEGRATED_P (x) && RTX_INTEGRATED_P (y)) && rtx_equal_p (x, y)));}/* Copy an attribute value expression, descending to all depths, but not copying any permanent hashed subexpressions. */rtxattr_copy_rtx (orig) register rtx orig;{ register rtx copy; register int i, j; 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -