recog.h 16.2 KB
Newer Older
Charles Hannum committed
1
/* Declarations for interface to insn recognizer and insn-output.c.
2
   Copyright (C) 1987-2017 Free Software Foundation, Inc.
Charles Hannum committed
3

4
This file is part of GCC.
Charles Hannum committed
5

6 7
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
8
Software Foundation; either version 3, or (at your option) any later
9
version.
Charles Hannum committed
10

11 12 13 14
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.
Charles Hannum committed
15 16

You should have received a copy of the GNU General Public License
17 18
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
Charles Hannum committed
19

20 21 22
#ifndef GCC_RECOG_H
#define GCC_RECOG_H

23 24 25
/* Random number that should be large enough for all purposes.  Also define
   a type that has at least MAX_RECOG_ALTERNATIVES + 1 bits, with the extra
   bit giving an invalid value that can be used to mean "uninitialized".  */
26 27
#define MAX_RECOG_ALTERNATIVES 35
typedef uint64_t alternative_mask;
28 29 30 31 32 33

/* A mask of all alternatives.  */
#define ALL_ALTERNATIVES ((alternative_mask) -1)

/* A mask containing just alternative X.  */
#define ALTERNATIVE_BIT(X) ((alternative_mask) 1 << (X))
34

35 36 37 38 39 40 41
/* Types of operands.  */
enum op_type {
  OP_IN,
  OP_OUT,
  OP_INOUT
};

42 43 44 45
struct operand_alternative
{
  /* Pointer to the beginning of the constraint string for this alternative,
     for easier access by alternative number.  */
46
  const char *constraint;
47 48

  /* The register class valid for this alternative (possibly NO_REGS).  */
49
  ENUM_BITFIELD (reg_class) cl : 16;
50 51 52

  /* "Badness" of this alternative, computed from number of '?' and '!'
     characters in the constraint string.  */
53
  unsigned int reject : 16;
54 55

  /* -1 if no matching constraint was found, or an operand number.  */
56
  int matches : 8;
57 58 59
  /* The same information, but reversed: -1 if this operand is not
     matched by any other, or the operand number of the operand that
     matches this one.  */
60
  int matched : 8;
61 62

  /* Nonzero if '&' was found in the constraint string.  */
63
  unsigned int earlyclobber : 1;
64 65
  /* Nonzero if TARGET_MEM_CONSTRAINT was found in the constraint
     string.  */
66
  unsigned int memory_ok : 1;
67
  /* Nonzero if 'p' was found in the constraint string.  */
68
  unsigned int is_address : 1;
69 70
  /* Nonzero if 'X' was found in the constraint string, or if the constraint
     string for this alternative was empty.  */
71
  unsigned int anything_ok : 1;
72

73
  unsigned int unused : 12;
74 75
};

76 77 78 79 80 81 82 83
/* Return the class for operand I of alternative ALT, taking matching
   constraints into account.  */

static inline enum reg_class
alternative_class (const operand_alternative *alt, int i)
{
  return alt[i].matches >= 0 ? alt[alt[i].matches].cl : alt[i].cl;
}
84

85 86 87
extern void init_recog (void);
extern void init_recog_no_volatile (void);
extern int check_asm_operands (rtx);
88
extern int asm_operand_ok (rtx, const char *, const char **);
89 90
extern bool validate_change (rtx, rtx *, rtx, bool);
extern bool validate_unshare_change (rtx, rtx *, rtx, bool);
91
extern bool canonicalize_change_group (rtx_insn *insn, rtx x);
92
extern int insn_invalid_p (rtx_insn *, bool);
93
extern int verify_changes (int);
94
extern void confirm_change_group (void);
95 96 97
extern int apply_change_group (void);
extern int num_validated_changes (void);
extern void cancel_changes (int);
98 99
extern int constrain_operands (int, alternative_mask);
extern int constrain_operands_cached (rtx_insn *, int);
100
extern int memory_address_addr_space_p (machine_mode, rtx, addr_space_t);
101 102
#define memory_address_p(mode,addr) \
	memory_address_addr_space_p ((mode), (addr), ADDR_SPACE_GENERIC)
103
extern int strict_memory_address_addr_space_p (machine_mode, rtx,
104 105 106
					       addr_space_t);
#define strict_memory_address_p(mode,addr) \
	strict_memory_address_addr_space_p ((mode), (addr), ADDR_SPACE_GENERIC)
107 108 109 110 111
extern int validate_replace_rtx_subexp (rtx, rtx, rtx_insn *, rtx *);
extern int validate_replace_rtx (rtx, rtx, rtx_insn *);
extern int validate_replace_rtx_part (rtx, rtx, rtx *, rtx_insn *);
extern int validate_replace_rtx_part_nosimplify (rtx, rtx, rtx *, rtx_insn *);
extern void validate_replace_rtx_group (rtx, rtx, rtx_insn *);
112
extern void validate_replace_src_group (rtx, rtx, rtx_insn *);
113
extern bool validate_simplify_insn (rtx_insn *insn);
114
extern int num_changes_pending (void);
115
extern int next_insn_tests_no_inequality (rtx_insn *);
116
extern bool reg_fits_class_p (const_rtx, reg_class_t, int, machine_mode);
117 118 119

extern int offsettable_memref_p (rtx);
extern int offsettable_nonstrict_memref_p (rtx);
120
extern int offsettable_address_addr_space_p (int, machine_mode, rtx,
121 122 123 124
					     addr_space_t);
#define offsettable_address_p(strict,mode,addr) \
	offsettable_address_addr_space_p ((strict), (mode), (addr), \
					  ADDR_SPACE_GENERIC)
125
extern bool mode_dependent_address_p (rtx, addr_space_t);
126

127
extern int recog (rtx, rtx_insn *, int *);
128
#ifndef GENERATOR_FILE
129
static inline int recog_memoized (rtx_insn *insn);
130
#endif
131 132
extern void add_clobbers (rtx, int);
extern int added_clobbers_hard_reg_p (int);
133
extern void insn_extract (rtx_insn *);
134
extern void extract_insn (rtx_insn *);
135
extern void extract_constrain_insn (rtx_insn *insn);
136 137
extern void extract_constrain_insn_cached (rtx_insn *);
extern void extract_insn_cached (rtx_insn *);
138 139
extern void preprocess_constraints (int, int, const char **,
				    operand_alternative *);
140
extern const operand_alternative *preprocess_insn_constraints (unsigned int);
141
extern void preprocess_constraints (rtx_insn *);
142
extern rtx_insn *peep2_next_insn (int);
143 144
extern int peep2_regno_dead_p (int, int);
extern int peep2_reg_dead_p (int, rtx);
145
#ifdef CLEAR_HARD_REG_SET
146
extern rtx peep2_find_free_register (int, int, const char *,
147
				     machine_mode, HARD_REG_SET *);
148
#endif
149
extern rtx_insn *peephole2_insns (rtx, rtx_insn *, int *);
Charles Hannum committed
150

David Malcolm committed
151 152
extern int store_data_bypass_p (rtx_insn *, rtx_insn *);
extern int if_test_bypass_p (rtx_insn *, rtx_insn *);
153

154
#ifndef GENERATOR_FILE
Matt Austern committed
155 156 157 158 159 160 161
/* Try recognizing the instruction INSN,
   and return the code number that results.
   Remember the code so that repeated calls do not
   need to spend the time for actual rerecognition.

   This function is the normal interface to instruction recognition.
   The automatically-generated function `recog' is normally called
162
   through this one.  */
Matt Austern committed
163 164

static inline int
165
recog_memoized (rtx_insn *insn)
Matt Austern committed
166 167 168 169 170
{
  if (INSN_CODE (insn) < 0)
    INSN_CODE (insn) = recog (PATTERN (insn), insn, 0);
  return INSN_CODE (insn);
}
171
#endif
Matt Austern committed
172

173 174 175 176 177 178 179 180 181 182 183 184 185
/* Skip chars until the next ',' or the end of the string.  This is
   useful to skip alternatives in a constraint string.  */
static inline const char *
skip_alternative (const char *p)
{
  const char *r = p;
  while (*r != '\0' && *r != ',')
    r++;
  if (*r == ',')
    r++;
  return r;
}

Charles Hannum committed
186 187 188
/* Nonzero means volatile operands are recognized.  */
extern int volatile_ok;

189 190 191 192
/* Set by constrain_operands to the number of the alternative that
   matched.  */
extern int which_alternative;

Charles Hannum committed
193 194
/* The following vectors hold the results from insn_extract.  */

195
struct recog_data_d
196 197 198 199 200 201
{
  /* It is very tempting to make the 5 operand related arrays into a
     structure and index on that.  However, to be source compatible
     with all of the existing md file insn constraints and output
     templates, we need `operand' as a flat array.  Without that
     member, making an array for the rest seems pointless.  */
Charles Hannum committed
202

203 204
  /* Gives value of operand N.  */
  rtx operand[MAX_RECOG_OPERANDS];
Charles Hannum committed
205

206 207
  /* Gives location where operand N was found.  */
  rtx *operand_loc[MAX_RECOG_OPERANDS];
Charles Hannum committed
208

209 210
  /* Gives the constraint string for operand N.  */
  const char *constraints[MAX_RECOG_OPERANDS];
Charles Hannum committed
211

212 213 214
  /* Nonzero if operand N is a match_operator or a match_parallel.  */
  char is_operator[MAX_RECOG_OPERANDS];

215
  /* Gives the mode of operand N.  */
216
  machine_mode operand_mode[MAX_RECOG_OPERANDS];
217

218 219
  /* Gives the type (in, out, inout) for operand N.  */
  enum op_type operand_type[MAX_RECOG_OPERANDS];
220

221 222 223
  /* Gives location where the Nth duplicate-appearance of an operand
     was found.  This is something that matched MATCH_DUP.  */
  rtx *dup_loc[MAX_DUP_OPERANDS];
224

225 226
  /* Gives the operand number that was duplicated in the Nth
     duplicate-appearance of an operand.  */
227
  char dup_num[MAX_DUP_OPERANDS];
228

229
  /* ??? Note that these are `char' instead of `unsigned char' to (try to)
230
     avoid certain lossage from K&R C, wherein `unsigned char' default
231 232 233 234 235 236 237 238
     promotes to `unsigned int' instead of `int' as in ISO C.  As of 1999,
     the most common places to bootstrap from K&R C are SunOS and HPUX,
     both of which have signed characters by default.  The only other
     supported natives that have both K&R C and unsigned characters are
     ROMP and Irix 3, and neither have been seen for a while, but do
     continue to consider unsignedness when performing arithmetic inside
     a comparison.  */

239
  /* The number of operands of the insn.  */
240
  char n_operands;
241

242
  /* The number of MATCH_DUPs in the insn.  */
243
  char n_dups;
244

245
  /* The number of alternatives in the constraints for the insn.  */
246
  char n_alternatives;
247

248 249 250
  /* True if insn is ASM_OPERANDS.  */
  bool is_asm;

251
  /* In case we are caching, hold insn data was generated for.  */
252
  rtx_insn *insn;
253 254
};

255
extern struct recog_data_d recog_data;
256

257
extern const operand_alternative *recog_op_alt;
258 259 260 261 262

/* Return a pointer to an array in which index OP describes the constraints
   on operand OP of the current instruction alternative (which_alternative).
   Only valid after calling preprocess_constraints and constrain_operands.  */

263
inline static const operand_alternative *
264 265 266 267 268 269
which_op_alt ()
{
  gcc_checking_assert (IN_RANGE (which_alternative, 0,
				 recog_data.n_alternatives - 1));
  return &recog_op_alt[which_alternative * recog_data.n_operands];
}
270

271
/* A table defined in insn-output.c that give information about
Charles Hannum committed
272 273
   each insn-code value.  */

274
typedef int (*insn_operand_predicate_fn) (rtx, machine_mode);
275
typedef const char * (*insn_output_fn) (rtx *, rtx_insn *);
276 277 278

struct insn_gen_fn
{
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
  typedef rtx_insn * (*f0) (void);
  typedef rtx_insn * (*f1) (rtx);
  typedef rtx_insn * (*f2) (rtx, rtx);
  typedef rtx_insn * (*f3) (rtx, rtx, rtx);
  typedef rtx_insn * (*f4) (rtx, rtx, rtx, rtx);
  typedef rtx_insn * (*f5) (rtx, rtx, rtx, rtx, rtx);
  typedef rtx_insn * (*f6) (rtx, rtx, rtx, rtx, rtx, rtx);
  typedef rtx_insn * (*f7) (rtx, rtx, rtx, rtx, rtx, rtx, rtx);
  typedef rtx_insn * (*f8) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
  typedef rtx_insn * (*f9) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
  typedef rtx_insn * (*f10) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
  typedef rtx_insn * (*f11) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
  typedef rtx_insn * (*f12) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
  typedef rtx_insn * (*f13) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
  typedef rtx_insn * (*f14) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
  typedef rtx_insn * (*f15) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
  typedef rtx_insn * (*f16) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
296 297 298

  typedef f0 stored_funcptr;

299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
  rtx_insn * operator () (void) const { return ((f0)func) (); }
  rtx_insn * operator () (rtx a0) const { return ((f1)func) (a0); }
  rtx_insn * operator () (rtx a0, rtx a1) const { return ((f2)func) (a0, a1); }
  rtx_insn * operator () (rtx a0, rtx a1, rtx a2) const { return ((f3)func) (a0, a1, a2); }
  rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3) const { return ((f4)func) (a0, a1, a2, a3); }
  rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4) const { return ((f5)func) (a0, a1, a2, a3, a4); }
  rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5) const { return ((f6)func) (a0, a1, a2, a3, a4, a5); }
  rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6) const { return ((f7)func) (a0, a1, a2, a3, a4, a5, a6); }
  rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7) const { return ((f8)func) (a0, a1, a2, a3, a4, a5, a6, a7); }
  rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8) const { return ((f9)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8); }
  rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9) const { return ((f10)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
  rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10) const { return ((f11)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
  rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11) const { return ((f12)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
  rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12) const { return ((f13)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
  rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13) const { return ((f14)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
  rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13, rtx a14) const { return ((f15)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
  rtx_insn * operator () (rtx a0, rtx a1, rtx a2, rtx a3, rtx a4, rtx a5, rtx a6, rtx a7, rtx a8, rtx a9, rtx a10, rtx a11, rtx a12, rtx a13, rtx a14, rtx a15) const { return ((f16)func) (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
316 317 318 319 320 321 322 323 324 325 326

  // This is for compatibility of code that invokes functions like
  //   (*funcptr) (arg)
  insn_gen_fn operator * (void) const { return *this; }

  // The wrapped function pointer must be public and there must not be any
  // constructors.  Otherwise the insn_data_d struct initializers generated
  // by genoutput.c will result in static initializer functions, which defeats
  // the purpose of the generated insn_data_d array.
  stored_funcptr func;
};
Charles Hannum committed
327

328 329
struct insn_operand_data
{
330
  const insn_operand_predicate_fn predicate;
Charles Hannum committed
331

332
  const char *const constraint;
Charles Hannum committed
333

334
  ENUM_BITFIELD(machine_mode) const mode : 16;
335

336
  const char strict_low;
337

338 339
  const char is_operator;

340
  const char eliminable;
341 342

  const char allows_mem;
343
};
Charles Hannum committed
344

345 346 347 348 349 350 351
/* Legal values for insn_data.output_format.  Indicate what type of data
   is stored in insn_data.output.  */
#define INSN_OUTPUT_FORMAT_NONE		0	/* abort */
#define INSN_OUTPUT_FORMAT_SINGLE	1	/* const char * */
#define INSN_OUTPUT_FORMAT_MULTI	2	/* const char * const * */
#define INSN_OUTPUT_FORMAT_FUNCTION	3	/* const char * (*)(...) */

352
struct insn_data_d
353
{
354
  const char *const name;
355
#if HAVE_DESIGNATED_UNION_INITIALIZERS
356 357 358 359 360 361 362 363 364 365 366 367
  union {
    const char *single;
    const char *const *multi;
    insn_output_fn function;
  } output;
#else
  struct {
    const char *single;
    const char *const *multi;
    insn_output_fn function;
  } output;
#endif
368 369
  const insn_gen_fn genfun;
  const struct insn_operand_data *const operand;
Charles Hannum committed
370

371
  const char n_generator_args;
372 373 374 375
  const char n_operands;
  const char n_dups;
  const char n_alternatives;
  const char output_format;
376
};
Charles Hannum committed
377

378
extern const struct insn_data_d insn_data[];
379
extern int peep2_current_count;
380

381 382 383
#ifndef GENERATOR_FILE
#include "insn-codes.h"

384 385 386 387 388 389 390 391 392
/* An enum of boolean attributes that may only depend on the current
   subtarget, not on things like operands or compiler phase.  */
enum bool_attr {
  BA_ENABLED,
  BA_PREFERRED_FOR_SPEED,
  BA_PREFERRED_FOR_SIZE,
  BA_LAST = BA_PREFERRED_FOR_SIZE
};

393 394 395
/* Target-dependent globals.  */
struct target_recog {
  bool x_initialized;
396 397
  alternative_mask x_bool_attr_masks[NUM_INSN_CODES][BA_LAST + 1];
  operand_alternative *x_op_alt[NUM_INSN_CODES];
398 399 400 401 402 403 404 405 406
};

extern struct target_recog default_target_recog;
#if SWITCHABLE_TARGET
extern struct target_recog *this_target_recog;
#else
#define this_target_recog (&default_target_recog)
#endif

407
alternative_mask get_enabled_alternatives (rtx_insn *);
408
alternative_mask get_preferred_alternatives (rtx_insn *);
409
alternative_mask get_preferred_alternatives (rtx_insn *, basic_block);
410
bool check_bool_attrs (rtx_insn *);
411 412 413 414

void recog_init ();
#endif

415
#endif /* GCC_RECOG_H */