📄 genattrtab.c
字号:
static void gen_unit PROTO((rtx));static void write_test_expr PROTO((rtx, int));static int max_attr_value PROTO((rtx));static void walk_attr_value PROTO((rtx));static void write_attr_get PROTO((struct attr_desc *));static rtx eliminate_known_true PROTO((rtx, rtx, int, int));static void write_attr_set PROTO((struct attr_desc *, int, rtx, char *, char *, rtx, int, int));static void write_attr_case PROTO((struct attr_desc *, struct attr_value *, int, char *, char *, int, rtx));static void write_attr_valueq PROTO((struct attr_desc *, char *));static void write_attr_value PROTO((struct attr_desc *, rtx));static void write_upcase PROTO((char *));static void write_indent PROTO((int));static void write_eligible_delay PROTO((char *));static void write_function_unit_info PROTO((void));static void write_complex_function PROTO((struct function_unit *, char *, char *));static int n_comma_elts PROTO((char *));static char *next_comma_elt PROTO((char **));static struct attr_desc *find_attr PROTO((char *, int));static void make_internal_attr PROTO((char *, rtx, int));static struct attr_value *find_most_used PROTO((struct attr_desc *));static rtx find_single_value PROTO((struct attr_desc *));static rtx make_numeric_value PROTO((int));static void extend_range PROTO((struct range *, int, int));char *xrealloc PROTO((char *, unsigned));char *xmalloc PROTO((unsigned));#define oballoc(size) obstack_alloc (hash_obstack, size)/* Hash table for sharing RTL and strings. *//* Each hash table slot is a bucket containing a chain of these structures. Strings are given negative hash codes; RTL expressions are given positive hash codes. */struct attr_hash{ struct attr_hash *next; /* Next structure in the bucket. */ int hashcode; /* Hash code of this rtx or string. */ union { char *str; /* The string (negative hash codes) */ rtx rtl; /* or the RTL recorded here. */ } u;};/* Now here is the hash table. When recording an RTL, it is added to the slot whose index is the hash code mod the table size. Note that the hash table is used for several kinds of RTL (see attr_rtx) and for strings. While all these live in the same table, they are completely independent, and the hash code is computed differently for each. */#define RTL_HASH_SIZE 4093struct attr_hash *attr_hash_table[RTL_HASH_SIZE];/* Here is how primitive or already-shared RTL's hash codes are made. */#define RTL_HASH(RTL) ((HOST_WIDE_INT) (RTL) & 0777777)/* Add an entry to the hash table for RTL with hash code HASHCODE. */static voidattr_hash_add_rtx (hashcode, rtl) int hashcode; rtx rtl;{ register struct attr_hash *h; h = (struct attr_hash *) obstack_alloc (hash_obstack, sizeof (struct attr_hash)); h->hashcode = hashcode; h->u.rtl = rtl; h->next = attr_hash_table[hashcode % RTL_HASH_SIZE]; attr_hash_table[hashcode % RTL_HASH_SIZE] = h;}/* 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 VPROTO((enum rtx_code code, ...)){#ifndef __STDC__ enum rtx_code code;#endif va_list p; 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);#ifndef __STDC__ code = va_arg (p, enum rtx_code);#endif /* 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 VPROTO((register int len, char *fmt, ...)){#ifndef __STDC__ register int len; char *fmt;#endif va_list p; register char *str; VA_START (p, fmt);#ifndef __STDC__ len = va_arg (p, int); fmt = va_arg (p, char*);#endif /* Print the string into a temporary location. */ str = (char *) alloca (len); 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -