static rtx alter_predicate_for_insn (rtx pattern, int alt, int max_op, int lineno) { const char *fmt; enum rtx_code code; int i, j, len; code = GET_CODE (pattern); switch (code) { case MATCH_OPERAND: { const char *c = XSTR (pattern, 2); if (n_alternatives (c) != 1) { message_with_line (lineno, "too many alternatives for operand %d", XINT (pattern, 0)); errors = 1; return NULL; } /* Replicate C as needed to fill out ALT alternatives. */ if (c && *c && alt > 1) { size_t c_len = strlen (c); size_t len = alt * (c_len + 1); char *new_c = XNEWVEC(char, len); memcpy (new_c, c, c_len); for (i = 1; i < alt; ++i) { new_c[i * (c_len + 1) - 1] = ','; memcpy (&new_c[i * (c_len + 1)], c, c_len); } new_c[len - 1] = '\0'; XSTR (pattern, 2) = new_c; } } /* Fall through. */ case MATCH_OPERATOR: case MATCH_SCRATCH: case MATCH_PARALLEL: XINT (pattern, 0) += max_op; break; default: break; }
static void identify_predicable_attribute (void) { struct queue_elem *elem; char *p_true, *p_false; const char *value; /* Look for the DEFINE_ATTR for `predicable', which must exist. */ for (elem = define_attr_queue; elem ; elem = elem->next) if (strcmp (XSTR (elem->data, 0), "predicable") == 0) goto found; message_with_line (define_cond_exec_queue->lineno, "attribute `predicable' not defined"); errors = 1; return; found: value = XSTR (elem->data, 1); p_false = xstrdup (value); p_true = strchr (p_false, ','); if (p_true == NULL || strchr (++p_true, ',') != NULL) { message_with_line (elem->lineno, "attribute `predicable' is not a boolean"); errors = 1; if (p_false) free (p_false); return; } p_true[-1] = '\0'; predicable_true = p_true; predicable_false = p_false; switch (GET_CODE (XEXP (elem->data, 2))) { case CONST_STRING: value = XSTR (XEXP (elem->data, 2), 0); break; case CONST: message_with_line (elem->lineno, "attribute `predicable' cannot be const"); errors = 1; if (p_false) free (p_false); return; default: message_with_line (elem->lineno, "attribute `predicable' must have a constant default"); errors = 1; if (p_false) free (p_false); return; } if (strcmp (value, p_true) == 0) predicable_default = 1; else if (strcmp (value, p_false) == 0) predicable_default = 0; else { message_with_line (elem->lineno, "unknown value `%s' for `predicable' attribute", value); errors = 1; if (p_false) free (p_false); } }
static void process_include (rtx desc, int lineno) { const char *filename = XSTR (desc, 0); const char *old_filename; int old_lineno; char *pathname; FILE *input_file; /* If specified file name is absolute, skip the include stack. */ if (! IS_ABSOLUTE_PATH (filename)) { struct file_name_list *stackp; /* Search directory path, trying to open the file. */ for (stackp = first_dir_md_include; stackp; stackp = stackp->next) { static const char sep[2] = { DIR_SEPARATOR, '\0' }; pathname = concat (stackp->fname, sep, filename, NULL); input_file = fopen (pathname, "r"); if (input_file != NULL) goto success; free (pathname); } } if (base_dir) pathname = concat (base_dir, filename, NULL); else pathname = xstrdup (filename); input_file = fopen (pathname, "r"); if (input_file == NULL) { free (pathname); message_with_line (lineno, "include file `%s' not found", filename); errors = 1; return; } success: /* Save old cursor; setup new for the new file. Note that "lineno" the argument to this function is the beginning of the include statement, while read_rtx_lineno has already been advanced. */ old_filename = read_rtx_filename; old_lineno = read_rtx_lineno; read_rtx_filename = pathname; read_rtx_lineno = 1; if (include_callback) include_callback (pathname); /* Read the entire file. */ while (read_rtx (input_file, &desc, &lineno)) process_rtx (desc, lineno); /* Do not free pathname. It is attached to the various rtx queue elements. */ read_rtx_filename = old_filename; read_rtx_lineno = old_lineno; fclose (input_file); }
static int is_predicable (struct queue_elem *elem) { rtvec vec = XVEC (elem->data, 4); const char *value; int i; if (! vec) return predicable_default; for (i = GET_NUM_ELEM (vec) - 1; i >= 0; --i) { rtx sub = RTVEC_ELT (vec, i); switch (GET_CODE (sub)) { case SET_ATTR: if (strcmp (XSTR (sub, 0), "predicable") == 0) { value = XSTR (sub, 1); goto found; } break; case SET_ATTR_ALTERNATIVE: if (strcmp (XSTR (sub, 0), "predicable") == 0) { message_with_line (elem->lineno, "multiple alternatives for `predicable'"); errors = 1; return 0; } break; case SET: if (GET_CODE (SET_DEST (sub)) != ATTR || strcmp (XSTR (SET_DEST (sub), 0), "predicable") != 0) break; sub = SET_SRC (sub); if (GET_CODE (sub) == CONST_STRING) { value = XSTR (sub, 0); goto found; } /* ??? It would be possible to handle this if we really tried. It's not easy though, and I'm not going to bother until it really proves necessary. */ message_with_line (elem->lineno, "non-constant value for `predicable'"); errors = 1; return 0; default: gcc_unreachable (); } } return predicable_default; found: /* Verify that predicability does not vary on the alternative. */ /* ??? It should be possible to handle this by simply eliminating the non-predicable alternatives from the insn. FRV would like to do this. Delay this until we've got the basics solid. */ if (strchr (value, ',') != NULL) { message_with_line (elem->lineno, "multiple alternatives for `predicable'"); errors = 1; return 0; } /* Find out which value we're looking at. */ if (strcmp (value, predicable_true) == 0) return 1; if (strcmp (value, predicable_false) == 0) return 0; message_with_line (elem->lineno, "unknown value `%s' for `predicable' attribute", value); errors = 1; return 0; }
static rtx alter_predicate_for_insn (rtx pattern, int alt, int max_op, int lineno) { const char *fmt; enum rtx_code code; int i, j, len; code = GET_CODE (pattern); switch (code) { case MATCH_OPERAND: { const char *c = XSTR (pattern, 2); if (n_alternatives (c) != 1) { message_with_line (lineno, "too many alternatives for operand %d", XINT (pattern, 0)); errors = 1; return NULL; } /* Replicate C as needed to fill out ALT alternatives. */ if (c && *c && alt > 1) { size_t c_len = strlen (c); size_t len = alt * (c_len + 1); char *new_c = xmalloc (len); memcpy (new_c, c, c_len); for (i = 1; i < alt; ++i) { new_c[i * (c_len + 1) - 1] = ','; memcpy (&new_c[i * (c_len + 1)], c, c_len); } new_c[len - 1] = '\0'; XSTR (pattern, 2) = new_c; } } /* Fall through. */ case MATCH_OPERATOR: case MATCH_SCRATCH: case MATCH_PARALLEL: case MATCH_INSN: XINT (pattern, 0) += max_op; break; default: break; } fmt = GET_RTX_FORMAT (code); len = GET_RTX_LENGTH (code); for (i = 0; i < len; i++) { rtx r; switch (fmt[i]) { case 'e': case 'u': r = alter_predicate_for_insn (XEXP (pattern, i), alt, max_op, lineno); if (r == NULL) return r; break; case 'E': for (j = XVECLEN (pattern, i) - 1; j >= 0; --j) { r = alter_predicate_for_insn (XVECEXP (pattern, i, j), alt, max_op, lineno); if (r == NULL) return r; } break; case 'i': case 'w': case '0': case 's': break; default: abort (); } } return pattern; }