118334Speter/* Generate code from to output assembler insns as recognized from rtl. 2132718Skan Copyright (C) 1987, 1988, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2002, 3169689Skan 2003, 2004, 2005 Free Software Foundation, Inc. 418334Speter 590075SobrienThis file is part of GCC. 618334Speter 790075SobrienGCC is free software; you can redistribute it and/or modify it under 890075Sobrienthe terms of the GNU General Public License as published by the Free 990075SobrienSoftware Foundation; either version 2, or (at your option) any later 1090075Sobrienversion. 1118334Speter 1290075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1390075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1490075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1590075Sobrienfor more details. 1618334Speter 1718334SpeterYou should have received a copy of the GNU General Public License 1890075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 20169689Skan02110-1301, USA. */ 2118334Speter 2218334Speter 2318334Speter/* This program reads the machine description for the compiler target machine 2418334Speter and produces a file containing these things: 2518334Speter 2690075Sobrien 1. An array of `struct insn_data', which is indexed by insn code number, 2790075Sobrien which contains: 2818334Speter 2990075Sobrien a. `name' is the name for that pattern. Nameless patterns are 3090075Sobrien given a name. 3118334Speter 3290075Sobrien b. `output' hold either the output template, an array of output 3390075Sobrien templates, or an output function. 3418334Speter 3590075Sobrien c. `genfun' is the function to generate a body for that pattern, 3690075Sobrien given operands as arguments. 3718334Speter 3890075Sobrien d. `n_operands' is the number of distinct operands in the pattern 3990075Sobrien for that insn, 4018334Speter 4190075Sobrien e. `n_dups' is the number of match_dup's that appear in the insn's 4290075Sobrien pattern. This says how many elements of `recog_data.dup_loc' are 4390075Sobrien significant after an insn has been recognized. 4418334Speter 4590075Sobrien f. `n_alternatives' is the number of alternatives in the constraints 4690075Sobrien of each pattern. 4718334Speter 4890075Sobrien g. `output_format' tells what type of thing `output' is. 4918334Speter 5090075Sobrien h. `operand' is the base of an array of operand data for the insn. 5118334Speter 5290075Sobrien 2. An array of `struct insn_operand data', used by `operand' above. 5318334Speter 5490075Sobrien a. `predicate', an int-valued function, is the match_operand predicate 5590075Sobrien for this operand. 5618334Speter 57169689Skan b. `constraint' is the constraint for this operand. 5818334Speter 5990075Sobrien c. `address_p' indicates that the operand appears within ADDRESS 60169689Skan rtx's. 6118334Speter 6290075Sobrien d. `mode' is the machine mode that that operand is supposed to have. 6390075Sobrien 6490075Sobrien e. `strict_low', is nonzero for operands contained in a STRICT_LOW_PART. 6590075Sobrien 6690075Sobrien f. `eliminable', is nonzero for operands that are matched normally by 6790075Sobrien MATCH_OPERAND; it is zero for operands that should not be changed during 6890075Sobrien register elimination such as MATCH_OPERATORs. 6990075Sobrien 7090075Sobrien The code number of an insn is simply its position in the machine 7190075Sobrien description; code numbers are assigned sequentially to entries in 7290075Sobrien the description, starting with code number 0. 7390075Sobrien 7490075Sobrien Thus, the following entry in the machine description 7590075Sobrien 7618334Speter (define_insn "clrdf" 7718334Speter [(set (match_operand:DF 0 "general_operand" "") 7818334Speter (const_int 0))] 7918334Speter "" 8018334Speter "clrd %0") 8118334Speter 8290075Sobrien assuming it is the 25th entry present, would cause 8390075Sobrien insn_data[24].template to be "clrd %0", and 8490075Sobrien insn_data[24].n_operands to be 1. */ 8518334Speter 86132718Skan#include "bconfig.h" 8750397Sobrien#include "system.h" 88132718Skan#include "coretypes.h" 89132718Skan#include "tm.h" 9018334Speter#include "rtl.h" 9190075Sobrien#include "errors.h" 9290075Sobrien#include "gensupport.h" 9318334Speter 9490075Sobrien/* No instruction can have more operands than this. Sorry for this 9590075Sobrien arbitrary limit, but what machine will have an instruction with 9690075Sobrien this many operands? */ 9718334Speter 9818334Speter#define MAX_MAX_OPERANDS 40 9918334Speter 100132718Skanstatic int n_occurrences (int, const char *); 101132718Skanstatic const char *strip_whitespace (const char *); 10218334Speter 10318334Speter/* insns in the machine description are assigned sequential code numbers 10418334Speter that are used by insn-recog.c (produced by genrecog) to communicate 10518334Speter to insn-output.c (produced by this program). */ 10618334Speter 10718334Speterstatic int next_code_number; 10818334Speter 10918334Speter/* This counts all definitions in the md file, 11018334Speter for the sake of error messages. */ 11118334Speter 11218334Speterstatic int next_index_number; 11318334Speter 11490075Sobrien/* This counts all operands used in the md file. The first is null. */ 11590075Sobrien 11690075Sobrienstatic int next_operand_number = 1; 11790075Sobrien 11890075Sobrien/* Record in this chain all information about the operands we will output. */ 11990075Sobrien 12090075Sobrienstruct operand_data 12190075Sobrien{ 12290075Sobrien struct operand_data *next; 12390075Sobrien int index; 12490075Sobrien const char *predicate; 12590075Sobrien const char *constraint; 12690075Sobrien enum machine_mode mode; 12790075Sobrien unsigned char n_alternatives; 12890075Sobrien char address_p; 12990075Sobrien char strict_low; 13090075Sobrien char eliminable; 13190075Sobrien char seen; 13290075Sobrien}; 13390075Sobrien 13490075Sobrien/* Begin with a null operand at index 0. */ 13590075Sobrien 13690075Sobrienstatic struct operand_data null_operand = 13790075Sobrien{ 13890075Sobrien 0, 0, "", "", VOIDmode, 0, 0, 0, 0, 0 13990075Sobrien}; 14090075Sobrien 14190075Sobrienstatic struct operand_data *odata = &null_operand; 14290075Sobrienstatic struct operand_data **odata_end = &null_operand.next; 14390075Sobrien 14490075Sobrien/* Must match the constants in recog.h. */ 14590075Sobrien 14690075Sobrien#define INSN_OUTPUT_FORMAT_NONE 0 /* abort */ 14790075Sobrien#define INSN_OUTPUT_FORMAT_SINGLE 1 /* const char * */ 14890075Sobrien#define INSN_OUTPUT_FORMAT_MULTI 2 /* const char * const * */ 14990075Sobrien#define INSN_OUTPUT_FORMAT_FUNCTION 3 /* const char * (*)(...) */ 15090075Sobrien 15118334Speter/* Record in this chain all information that we will output, 15218334Speter associated with the code number of the insn. */ 15318334Speter 15418334Speterstruct data 15518334Speter{ 15690075Sobrien struct data *next; 15790075Sobrien const char *name; 15890075Sobrien const char *template; 15918334Speter int code_number; 16018334Speter int index_number; 161169689Skan const char *filename; 16290075Sobrien int lineno; 16318334Speter int n_operands; /* Number of operands this insn recognizes */ 16418334Speter int n_dups; /* Number times match_dup appears in pattern */ 16518334Speter int n_alternatives; /* Number of alternatives in each constraint */ 16690075Sobrien int operand_number; /* Operand index in the big array. */ 16790075Sobrien int output_format; /* INSN_OUTPUT_FORMAT_*. */ 16890075Sobrien struct operand_data operand[MAX_MAX_OPERANDS]; 16918334Speter}; 17018334Speter 17190075Sobrien/* This variable points to the first link in the insn chain. */ 17218334Speter 17390075Sobrienstatic struct data *idata, **idata_end = &idata; 17418334Speter 175132718Skanstatic void output_prologue (void); 176132718Skanstatic void output_operand_data (void); 177132718Skanstatic void output_insn_data (void); 178132718Skanstatic void output_get_insn_name (void); 179132718Skanstatic void scan_operands (struct data *, rtx, int, int); 180132718Skanstatic int compare_operands (struct operand_data *, 181132718Skan struct operand_data *); 182132718Skanstatic void place_operands (struct data *); 183132718Skanstatic void process_template (struct data *, const char *); 184132718Skanstatic void validate_insn_alternatives (struct data *); 185132718Skanstatic void validate_insn_operands (struct data *); 186132718Skanstatic void gen_insn (rtx, int); 187132718Skanstatic void gen_peephole (rtx, int); 188132718Skanstatic void gen_expand (rtx, int); 189132718Skanstatic void gen_split (rtx, int); 190169689Skan 191169689Skan#ifdef USE_MD_CONSTRAINTS 192169689Skan 193169689Skanstruct constraint_data 19452284Sobrien{ 195169689Skan struct constraint_data *next_this_letter; 196169689Skan int lineno; 197169689Skan unsigned int namelen; 198169689Skan const char name[1]; 199169689Skan}; 20052284Sobrien 201169689Skan/* This is a complete list (unlike the one in genpreds.c) of constraint 202169689Skan letters and modifiers with machine-independent meaning. The only 203169689Skan omission is digits, as these are handled specially. */ 204169689Skanstatic const char indep_constraints[] = ",=+%*?!#&<>EFVXgimnoprs"; 20552284Sobrien 206169689Skanstatic struct constraint_data * 207169689Skanconstraints_by_letter_table[1 << CHAR_BIT]; 20852284Sobrien 209169689Skanstatic int mdep_constraint_len (const char *, int, int); 210169689Skanstatic void note_constraint (rtx, int); 21152284Sobrien 212169689Skan#else /* !USE_MD_CONSTRAINTS */ 213169689Skan 214169689Skanstatic void check_constraint_len (void); 215169689Skanstatic int constraint_len (const char *, int); 216169689Skan 217169689Skan#endif /* !USE_MD_CONSTRAINTS */ 218169689Skan 219169689Skan 22018334Speterstatic void 221132718Skanoutput_prologue (void) 22218334Speter{ 22318334Speter printf ("/* Generated automatically by the program `genoutput'\n\ 22490075Sobrien from the machine description file `md'. */\n\n"); 22518334Speter 22618334Speter printf ("#include \"config.h\"\n"); 22750397Sobrien printf ("#include \"system.h\"\n"); 228132718Skan printf ("#include \"coretypes.h\"\n"); 229132718Skan printf ("#include \"tm.h\"\n"); 23050397Sobrien printf ("#include \"flags.h\"\n"); 23190075Sobrien printf ("#include \"ggc.h\"\n"); 23218334Speter printf ("#include \"rtl.h\"\n"); 23390075Sobrien printf ("#include \"expr.h\"\n"); 23490075Sobrien printf ("#include \"insn-codes.h\"\n"); 23590075Sobrien printf ("#include \"tm_p.h\"\n"); 23690075Sobrien printf ("#include \"function.h\"\n"); 23718334Speter printf ("#include \"regs.h\"\n"); 23818334Speter printf ("#include \"hard-reg-set.h\"\n"); 23918334Speter printf ("#include \"real.h\"\n"); 24018334Speter printf ("#include \"insn-config.h\"\n\n"); 24118334Speter printf ("#include \"conditions.h\"\n"); 24218334Speter printf ("#include \"insn-attr.h\"\n\n"); 24318334Speter printf ("#include \"recog.h\"\n\n"); 24490075Sobrien printf ("#include \"toplev.h\"\n"); 24518334Speter printf ("#include \"output.h\"\n"); 246132718Skan printf ("#include \"target.h\"\n"); 247169689Skan printf ("#include \"tm-constrs.h\"\n"); 24818334Speter} 24918334Speter 25018334Speterstatic void 251132718Skanoutput_operand_data (void) 25218334Speter{ 25390075Sobrien struct operand_data *d; 25418334Speter 25590075Sobrien printf ("\nstatic const struct insn_operand_data operand_data[] = \n{\n"); 25690075Sobrien 25790075Sobrien for (d = odata; d; d = d->next) 25818334Speter { 25990075Sobrien printf (" {\n"); 26018334Speter 26190075Sobrien printf (" %s,\n", 26290075Sobrien d->predicate && d->predicate[0] ? d->predicate : "0"); 26390075Sobrien 26490075Sobrien printf (" \"%s\",\n", d->constraint ? d->constraint : ""); 26590075Sobrien 26690075Sobrien printf (" %smode,\n", GET_MODE_NAME (d->mode)); 26790075Sobrien 26890075Sobrien printf (" %d,\n", d->strict_low); 26990075Sobrien 27090075Sobrien printf (" %d\n", d->eliminable); 27190075Sobrien 27290075Sobrien printf(" },\n"); 27318334Speter } 27490075Sobrien printf("};\n\n\n"); 27590075Sobrien} 27618334Speter 27790075Sobrienstatic void 278132718Skanoutput_insn_data (void) 27990075Sobrien{ 28090075Sobrien struct data *d; 28190075Sobrien int name_offset = 0; 28290075Sobrien int next_name_offset; 28390075Sobrien const char * last_name = 0; 28490075Sobrien const char * next_name = 0; 28590075Sobrien struct data *n; 28618334Speter 28790075Sobrien for (n = idata, next_name_offset = 1; n; n = n->next, next_name_offset++) 28890075Sobrien if (n->name) 28918334Speter { 29090075Sobrien next_name = n->name; 29190075Sobrien break; 29218334Speter } 29318334Speter 294132718Skan printf ("#if GCC_VERSION >= 2007\n__extension__\n#endif\n"); 29590075Sobrien printf ("\nconst struct insn_data insn_data[] = \n{\n"); 29618334Speter 29790075Sobrien for (d = idata; d; d = d->next) 29890075Sobrien { 299169689Skan printf (" /* %s:%d */\n", d->filename, d->lineno); 30090075Sobrien printf (" {\n"); 30118334Speter 30290075Sobrien if (d->name) 30318334Speter { 30490075Sobrien printf (" \"%s\",\n", d->name); 30590075Sobrien name_offset = 0; 30690075Sobrien last_name = d->name; 30790075Sobrien next_name = 0; 30890075Sobrien for (n = d->next, next_name_offset = 1; n; 30990075Sobrien n = n->next, next_name_offset++) 31018334Speter { 31190075Sobrien if (n->name) 31290075Sobrien { 31390075Sobrien next_name = n->name; 31490075Sobrien break; 31590075Sobrien } 31618334Speter } 31718334Speter } 31890075Sobrien else 31918334Speter { 32090075Sobrien name_offset++; 32190075Sobrien if (next_name && (last_name == 0 32290075Sobrien || name_offset > next_name_offset / 2)) 32390075Sobrien printf (" \"%s-%d\",\n", next_name, 32490075Sobrien next_name_offset - name_offset); 32590075Sobrien else 32690075Sobrien printf (" \"%s+%d\",\n", last_name, name_offset); 32718334Speter } 32818334Speter 32990075Sobrien switch (d->output_format) 33090075Sobrien { 33190075Sobrien case INSN_OUTPUT_FORMAT_NONE: 332132718Skan printf ("#if HAVE_DESIGNATED_INITIALIZERS\n"); 333132718Skan printf (" { 0 },\n"); 334132718Skan printf ("#else\n"); 335132718Skan printf (" { 0, 0, 0 },\n"); 336132718Skan printf ("#endif\n"); 33790075Sobrien break; 33890075Sobrien case INSN_OUTPUT_FORMAT_SINGLE: 33918334Speter { 34090075Sobrien const char *p = d->template; 34190075Sobrien char prev = 0; 342132718Skan 343132718Skan printf ("#if HAVE_DESIGNATED_INITIALIZERS\n"); 344132718Skan printf (" { .single =\n"); 345132718Skan printf ("#else\n"); 346132718Skan printf (" {\n"); 347132718Skan printf ("#endif\n"); 34890075Sobrien printf (" \""); 34990075Sobrien while (*p) 35018334Speter { 35196263Sobrien if (IS_VSPACE (*p) && prev != '\\') 35296263Sobrien { 35396263Sobrien /* Preserve two consecutive \n's or \r's, but treat \r\n 35496263Sobrien as a single newline. */ 35596263Sobrien if (*p == '\n' && prev != '\r') 35696263Sobrien printf ("\\n\\\n"); 35796263Sobrien } 35890075Sobrien else 35990075Sobrien putchar (*p); 36090075Sobrien prev = *p; 36190075Sobrien ++p; 36218334Speter } 36390075Sobrien printf ("\",\n"); 364132718Skan printf ("#if HAVE_DESIGNATED_INITIALIZERS\n"); 365132718Skan printf (" },\n"); 366132718Skan printf ("#else\n"); 367132718Skan printf (" 0, 0 },\n"); 368132718Skan printf ("#endif\n"); 36918334Speter } 37090075Sobrien break; 37190075Sobrien case INSN_OUTPUT_FORMAT_MULTI: 372132718Skan printf ("#if HAVE_DESIGNATED_INITIALIZERS\n"); 373132718Skan printf (" { .multi = output_%d },\n", d->code_number); 374132718Skan printf ("#else\n"); 375132718Skan printf (" { 0, output_%d, 0 },\n", d->code_number); 376132718Skan printf ("#endif\n"); 377132718Skan break; 37890075Sobrien case INSN_OUTPUT_FORMAT_FUNCTION: 379132718Skan printf ("#if HAVE_DESIGNATED_INITIALIZERS\n"); 380132718Skan printf (" { .function = output_%d },\n", d->code_number); 381132718Skan printf ("#else\n"); 382132718Skan printf (" { 0, 0, output_%d },\n", d->code_number); 383132718Skan printf ("#endif\n"); 38490075Sobrien break; 38590075Sobrien default: 386169689Skan gcc_unreachable (); 38790075Sobrien } 38818334Speter 38990075Sobrien if (d->name && d->name[0] != '*') 39090075Sobrien printf (" (insn_gen_fn) gen_%s,\n", d->name); 39190075Sobrien else 39290075Sobrien printf (" 0,\n"); 39390075Sobrien 39490075Sobrien printf (" &operand_data[%d],\n", d->operand_number); 39590075Sobrien printf (" %d,\n", d->n_operands); 39690075Sobrien printf (" %d,\n", d->n_dups); 39790075Sobrien printf (" %d,\n", d->n_alternatives); 39890075Sobrien printf (" %d\n", d->output_format); 39990075Sobrien 40090075Sobrien printf(" },\n"); 40190075Sobrien } 40290075Sobrien printf ("};\n\n\n"); 40318334Speter} 40490075Sobrien 40590075Sobrienstatic void 406132718Skanoutput_get_insn_name (void) 40790075Sobrien{ 40890075Sobrien printf ("const char *\n"); 409132718Skan printf ("get_insn_name (int code)\n"); 41090075Sobrien printf ("{\n"); 411132718Skan printf (" if (code == NOOP_MOVE_INSN_CODE)\n"); 412132718Skan printf (" return \"NOOP_MOVE\";\n"); 413132718Skan printf (" else\n"); 414132718Skan printf (" return insn_data[code].name;\n"); 41590075Sobrien printf ("}\n"); 41690075Sobrien} 41790075Sobrien 41818334Speter 41990075Sobrien/* Stores in max_opno the largest operand number present in `part', if 42090075Sobrien that is larger than the previous value of max_opno, and the rest of 42190075Sobrien the operand data into `d->operand[i]'. 42218334Speter 42318334Speter THIS_ADDRESS_P is nonzero if the containing rtx was an ADDRESS. 42418334Speter THIS_STRICT_LOW is nonzero if the containing rtx was a STRICT_LOW_PART. */ 42518334Speter 42618334Speterstatic int max_opno; 42718334Speterstatic int num_dups; 42818334Speter 42918334Speterstatic void 430132718Skanscan_operands (struct data *d, rtx part, int this_address_p, 431132718Skan int this_strict_low) 43218334Speter{ 43390075Sobrien int i, j; 43490075Sobrien const char *format_ptr; 43518334Speter int opno; 43618334Speter 43718334Speter if (part == 0) 43818334Speter return; 43918334Speter 44018334Speter switch (GET_CODE (part)) 44118334Speter { 44218334Speter case MATCH_OPERAND: 44318334Speter opno = XINT (part, 0); 44418334Speter if (opno > max_opno) 44518334Speter max_opno = opno; 44618334Speter if (max_opno >= MAX_MAX_OPERANDS) 44718334Speter { 44890075Sobrien message_with_line (d->lineno, 44990075Sobrien "maximum number of operands exceeded"); 45090075Sobrien have_error = 1; 45118334Speter return; 45218334Speter } 45390075Sobrien if (d->operand[opno].seen) 45418334Speter { 45590075Sobrien message_with_line (d->lineno, 45690075Sobrien "repeated operand number %d\n", opno); 45790075Sobrien have_error = 1; 45818334Speter } 45990075Sobrien 46090075Sobrien d->operand[opno].seen = 1; 46190075Sobrien d->operand[opno].mode = GET_MODE (part); 46290075Sobrien d->operand[opno].strict_low = this_strict_low; 46390075Sobrien d->operand[opno].predicate = XSTR (part, 1); 46490075Sobrien d->operand[opno].constraint = strip_whitespace (XSTR (part, 2)); 46590075Sobrien d->operand[opno].n_alternatives 46690075Sobrien = n_occurrences (',', d->operand[opno].constraint) + 1; 46790075Sobrien d->operand[opno].address_p = this_address_p; 46890075Sobrien d->operand[opno].eliminable = 1; 46918334Speter return; 47018334Speter 47118334Speter case MATCH_SCRATCH: 47218334Speter opno = XINT (part, 0); 47318334Speter if (opno > max_opno) 47418334Speter max_opno = opno; 47518334Speter if (max_opno >= MAX_MAX_OPERANDS) 47618334Speter { 47790075Sobrien message_with_line (d->lineno, 47890075Sobrien "maximum number of operands exceeded"); 47990075Sobrien have_error = 1; 48018334Speter return; 48118334Speter } 48290075Sobrien if (d->operand[opno].seen) 48318334Speter { 48490075Sobrien message_with_line (d->lineno, 48590075Sobrien "repeated operand number %d\n", opno); 48690075Sobrien have_error = 1; 48718334Speter } 48890075Sobrien 48990075Sobrien d->operand[opno].seen = 1; 49090075Sobrien d->operand[opno].mode = GET_MODE (part); 49190075Sobrien d->operand[opno].strict_low = 0; 49290075Sobrien d->operand[opno].predicate = "scratch_operand"; 49390075Sobrien d->operand[opno].constraint = strip_whitespace (XSTR (part, 1)); 49490075Sobrien d->operand[opno].n_alternatives 49590075Sobrien = n_occurrences (',', d->operand[opno].constraint) + 1; 49690075Sobrien d->operand[opno].address_p = 0; 49790075Sobrien d->operand[opno].eliminable = 0; 49818334Speter return; 49918334Speter 50018334Speter case MATCH_OPERATOR: 50118334Speter case MATCH_PARALLEL: 50218334Speter opno = XINT (part, 0); 50318334Speter if (opno > max_opno) 50418334Speter max_opno = opno; 50518334Speter if (max_opno >= MAX_MAX_OPERANDS) 50618334Speter { 50790075Sobrien message_with_line (d->lineno, 50890075Sobrien "maximum number of operands exceeded"); 50990075Sobrien have_error = 1; 51018334Speter return; 51118334Speter } 51290075Sobrien if (d->operand[opno].seen) 51390075Sobrien { 51490075Sobrien message_with_line (d->lineno, 51590075Sobrien "repeated operand number %d\n", opno); 51690075Sobrien have_error = 1; 51790075Sobrien } 51890075Sobrien 51990075Sobrien d->operand[opno].seen = 1; 52090075Sobrien d->operand[opno].mode = GET_MODE (part); 52190075Sobrien d->operand[opno].strict_low = 0; 52290075Sobrien d->operand[opno].predicate = XSTR (part, 1); 52390075Sobrien d->operand[opno].constraint = 0; 52490075Sobrien d->operand[opno].address_p = 0; 52590075Sobrien d->operand[opno].eliminable = 0; 52618334Speter for (i = 0; i < XVECLEN (part, 2); i++) 52790075Sobrien scan_operands (d, XVECEXP (part, 2, i), 0, 0); 52818334Speter return; 52918334Speter 53018334Speter case MATCH_DUP: 53118334Speter case MATCH_OP_DUP: 53218334Speter case MATCH_PAR_DUP: 53318334Speter ++num_dups; 53496263Sobrien break; 53518334Speter 53618334Speter case ADDRESS: 53790075Sobrien scan_operands (d, XEXP (part, 0), 1, 0); 53818334Speter return; 53918334Speter 54018334Speter case STRICT_LOW_PART: 54190075Sobrien scan_operands (d, XEXP (part, 0), 0, 1); 54218334Speter return; 543132718Skan 54450397Sobrien default: 54550397Sobrien break; 54618334Speter } 54718334Speter 54818334Speter format_ptr = GET_RTX_FORMAT (GET_CODE (part)); 54918334Speter 55018334Speter for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++) 55118334Speter switch (*format_ptr++) 55218334Speter { 55318334Speter case 'e': 55450397Sobrien case 'u': 55590075Sobrien scan_operands (d, XEXP (part, i), 0, 0); 55618334Speter break; 55718334Speter case 'E': 55818334Speter if (XVEC (part, i) != NULL) 55918334Speter for (j = 0; j < XVECLEN (part, i); j++) 56090075Sobrien scan_operands (d, XVECEXP (part, i, j), 0, 0); 56118334Speter break; 56218334Speter } 56318334Speter} 56490075Sobrien 56590075Sobrien/* Compare two operands for content equality. */ 56690075Sobrien 56790075Sobrienstatic int 568132718Skancompare_operands (struct operand_data *d0, struct operand_data *d1) 56990075Sobrien{ 57090075Sobrien const char *p0, *p1; 57190075Sobrien 57290075Sobrien p0 = d0->predicate; 57390075Sobrien if (!p0) 57490075Sobrien p0 = ""; 57590075Sobrien p1 = d1->predicate; 57690075Sobrien if (!p1) 57790075Sobrien p1 = ""; 57890075Sobrien if (strcmp (p0, p1) != 0) 57990075Sobrien return 0; 58090075Sobrien 58190075Sobrien p0 = d0->constraint; 58290075Sobrien if (!p0) 58390075Sobrien p0 = ""; 58490075Sobrien p1 = d1->constraint; 58590075Sobrien if (!p1) 58690075Sobrien p1 = ""; 58790075Sobrien if (strcmp (p0, p1) != 0) 58890075Sobrien return 0; 58990075Sobrien 59090075Sobrien if (d0->mode != d1->mode) 59190075Sobrien return 0; 59290075Sobrien 59390075Sobrien if (d0->strict_low != d1->strict_low) 59490075Sobrien return 0; 59590075Sobrien 59690075Sobrien if (d0->eliminable != d1->eliminable) 59790075Sobrien return 0; 59890075Sobrien 59990075Sobrien return 1; 60090075Sobrien} 60190075Sobrien 60290075Sobrien/* Scan the list of operands we've already committed to output and either 60390075Sobrien find a subsequence that is the same, or allocate a new one at the end. */ 60490075Sobrien 60590075Sobrienstatic void 606132718Skanplace_operands (struct data *d) 60790075Sobrien{ 60890075Sobrien struct operand_data *od, *od2; 60990075Sobrien int i; 61090075Sobrien 61190075Sobrien if (d->n_operands == 0) 61290075Sobrien { 61390075Sobrien d->operand_number = 0; 61490075Sobrien return; 61590075Sobrien } 61690075Sobrien 61790075Sobrien /* Brute force substring search. */ 61890075Sobrien for (od = odata, i = 0; od; od = od->next, i = 0) 61990075Sobrien if (compare_operands (od, &d->operand[0])) 62090075Sobrien { 62190075Sobrien od2 = od->next; 62290075Sobrien i = 1; 62390075Sobrien while (1) 62490075Sobrien { 62590075Sobrien if (i == d->n_operands) 62690075Sobrien goto full_match; 62790075Sobrien if (od2 == NULL) 62890075Sobrien goto partial_match; 62990075Sobrien if (! compare_operands (od2, &d->operand[i])) 63090075Sobrien break; 63190075Sobrien ++i, od2 = od2->next; 63290075Sobrien } 63390075Sobrien } 63490075Sobrien 63590075Sobrien /* Either partial match at the end of the list, or no match. In either 63690075Sobrien case, we tack on what operands are remaining to the end of the list. */ 63790075Sobrien partial_match: 63890075Sobrien d->operand_number = next_operand_number - i; 63990075Sobrien for (; i < d->n_operands; ++i) 64090075Sobrien { 64190075Sobrien od2 = &d->operand[i]; 64290075Sobrien *odata_end = od2; 64390075Sobrien odata_end = &od2->next; 64490075Sobrien od2->index = next_operand_number++; 64590075Sobrien } 64690075Sobrien *odata_end = NULL; 64790075Sobrien return; 64890075Sobrien 64990075Sobrien full_match: 65090075Sobrien d->operand_number = od->index; 65190075Sobrien return; 65290075Sobrien} 65390075Sobrien 65418334Speter 65518334Speter/* Process an assembler template from a define_insn or a define_peephole. 65618334Speter It is either the assembler code template, a list of assembler code 65718334Speter templates, or C code to generate the assembler code template. */ 65818334Speter 65918334Speterstatic void 660132718Skanprocess_template (struct data *d, const char *template) 66118334Speter{ 66290075Sobrien const char *cp; 66390075Sobrien int i; 66418334Speter 66590075Sobrien /* Templates starting with * contain straight code to be run. */ 66690075Sobrien if (template[0] == '*') 66718334Speter { 66890075Sobrien d->template = 0; 66990075Sobrien d->output_format = INSN_OUTPUT_FORMAT_FUNCTION; 67018334Speter 671132718Skan puts ("\nstatic const char *"); 672132718Skan printf ("output_%d (rtx *operands ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED)\n", 67390075Sobrien d->code_number); 67490075Sobrien puts ("{"); 675169689Skan print_rtx_ptr_loc (template); 67690075Sobrien puts (template + 1); 67790075Sobrien puts ("}"); 67890075Sobrien } 67918334Speter 68018334Speter /* If the assembler code template starts with a @ it is a newline-separated 68190075Sobrien list of assembler code templates, one for each alternative. */ 68290075Sobrien else if (template[0] == '@') 68318334Speter { 68490075Sobrien d->template = 0; 68590075Sobrien d->output_format = INSN_OUTPUT_FORMAT_MULTI; 68618334Speter 68790075Sobrien printf ("\nstatic const char * const output_%d[] = {\n", d->code_number); 68818334Speter 68918334Speter for (i = 0, cp = &template[1]; *cp; ) 69018334Speter { 691169689Skan const char *ep, *sp; 692169689Skan 69396263Sobrien while (ISSPACE (*cp)) 69418334Speter cp++; 69518334Speter 69690075Sobrien printf (" \""); 697169689Skan 698169689Skan for (ep = sp = cp; !IS_VSPACE (*ep) && *ep != '\0'; ++ep) 699169689Skan if (!ISSPACE (*ep)) 700169689Skan sp = ep + 1; 701169689Skan 702169689Skan if (sp != ep) 703169689Skan message_with_line (d->lineno, 704169689Skan "trailing whitespace in output template"); 705169689Skan 706169689Skan while (cp < sp) 70750397Sobrien { 70850397Sobrien putchar (*cp); 70950397Sobrien cp++; 71050397Sobrien } 71118334Speter 71218334Speter printf ("\",\n"); 71318334Speter i++; 71418334Speter } 71590075Sobrien if (i == 1) 71690075Sobrien message_with_line (d->lineno, 71790075Sobrien "'@' is redundant for output template with single alternative"); 71818334Speter if (i != d->n_alternatives) 71990075Sobrien { 72090075Sobrien message_with_line (d->lineno, 72190075Sobrien "wrong number of alternatives in the output template"); 72290075Sobrien have_error = 1; 72390075Sobrien } 72418334Speter 72590075Sobrien printf ("};\n"); 72618334Speter } 72718334Speter else 72818334Speter { 72990075Sobrien d->template = template; 73090075Sobrien d->output_format = INSN_OUTPUT_FORMAT_SINGLE; 73118334Speter } 73218334Speter} 73318334Speter 73418334Speter/* Check insn D for consistency in number of constraint alternatives. */ 73518334Speter 73618334Speterstatic void 737132718Skanvalidate_insn_alternatives (struct data *d) 73818334Speter{ 73990075Sobrien int n = 0, start; 74090075Sobrien 74190075Sobrien /* Make sure all the operands have the same number of alternatives 74290075Sobrien in their constraints. Let N be that number. */ 74318334Speter for (start = 0; start < d->n_operands; start++) 74490075Sobrien if (d->operand[start].n_alternatives > 0) 74518334Speter { 746132718Skan int len, i; 747132718Skan const char *p; 748132718Skan char c; 749132718Skan int which_alternative = 0; 750132718Skan int alternative_count_unsure = 0; 751132718Skan 752132718Skan for (p = d->operand[start].constraint; (c = *p); p += len) 753132718Skan { 754169689Skan#ifdef USE_MD_CONSTRAINTS 755169689Skan if (ISSPACE (c) || strchr (indep_constraints, c)) 756169689Skan len = 1; 757169689Skan else if (ISDIGIT (c)) 758169689Skan { 759169689Skan const char *q = p; 760169689Skan do 761169689Skan q++; 762169689Skan while (ISDIGIT (*q)); 763169689Skan len = q - p; 764169689Skan } 765169689Skan else 766169689Skan len = mdep_constraint_len (p, d->lineno, start); 767169689Skan#else 768132718Skan len = CONSTRAINT_LEN (c, p); 769132718Skan 770132718Skan if (len < 1 || (len > 1 && strchr (",#*+=&%!0123456789", c))) 771132718Skan { 772132718Skan message_with_line (d->lineno, 773132718Skan "invalid length %d for char '%c' in alternative %d of operand %d", 774132718Skan len, c, which_alternative, start); 775132718Skan len = 1; 776132718Skan have_error = 1; 777132718Skan } 778169689Skan#endif 779132718Skan 780132718Skan if (c == ',') 781132718Skan { 782132718Skan which_alternative++; 783132718Skan continue; 784132718Skan } 785132718Skan 786132718Skan for (i = 1; i < len; i++) 787132718Skan if (p[i] == '\0') 788132718Skan { 789132718Skan message_with_line (d->lineno, 790132718Skan "NUL in alternative %d of operand %d", 791132718Skan which_alternative, start); 792132718Skan alternative_count_unsure = 1; 793132718Skan break; 794132718Skan } 795132718Skan else if (strchr (",#*", p[i])) 796132718Skan { 797132718Skan message_with_line (d->lineno, 798132718Skan "'%c' in alternative %d of operand %d", 799132718Skan p[i], which_alternative, start); 800132718Skan alternative_count_unsure = 1; 801132718Skan } 802132718Skan } 803132718Skan if (alternative_count_unsure) 804132718Skan have_error = 1; 805132718Skan else if (n == 0) 80690075Sobrien n = d->operand[start].n_alternatives; 80790075Sobrien else if (n != d->operand[start].n_alternatives) 80890075Sobrien { 80990075Sobrien message_with_line (d->lineno, 81090075Sobrien "wrong number of alternatives in operand %d", 81190075Sobrien start); 81290075Sobrien have_error = 1; 81390075Sobrien } 81418334Speter } 81590075Sobrien 81618334Speter /* Record the insn's overall number of alternatives. */ 81718334Speter d->n_alternatives = n; 81818334Speter} 81990075Sobrien 82090075Sobrien/* Verify that there are no gaps in operand numbers for INSNs. */ 82190075Sobrien 82290075Sobrienstatic void 823132718Skanvalidate_insn_operands (struct data *d) 82490075Sobrien{ 82590075Sobrien int i; 82690075Sobrien 82790075Sobrien for (i = 0; i < d->n_operands; ++i) 82890075Sobrien if (d->operand[i].seen == 0) 82990075Sobrien { 83090075Sobrien message_with_line (d->lineno, "missing operand %d", i); 83190075Sobrien have_error = 1; 83290075Sobrien } 83390075Sobrien} 83418334Speter 83590075Sobrien/* Look at a define_insn just read. Assign its code number. Record 83690075Sobrien on idata the template and the number of arguments. If the insn has 83790075Sobrien a hairy output action, output a function for now. */ 83818334Speter 83918334Speterstatic void 840132718Skangen_insn (rtx insn, int lineno) 84118334Speter{ 842169689Skan struct data *d = XNEW (struct data); 84390075Sobrien int i; 84418334Speter 84590075Sobrien d->code_number = next_code_number; 84618334Speter d->index_number = next_index_number; 847169689Skan d->filename = read_rtx_filename; 84890075Sobrien d->lineno = lineno; 84918334Speter if (XSTR (insn, 0)[0]) 85018334Speter d->name = XSTR (insn, 0); 85118334Speter else 85218334Speter d->name = 0; 85318334Speter 85418334Speter /* Build up the list in the same order as the insns are seen 85518334Speter in the machine description. */ 85618334Speter d->next = 0; 85790075Sobrien *idata_end = d; 85890075Sobrien idata_end = &d->next; 85918334Speter 86018334Speter max_opno = -1; 86118334Speter num_dups = 0; 86290075Sobrien memset (d->operand, 0, sizeof (d->operand)); 86318334Speter 86418334Speter for (i = 0; i < XVECLEN (insn, 1); i++) 86590075Sobrien scan_operands (d, XVECEXP (insn, 1, i), 0, 0); 86618334Speter 86718334Speter d->n_operands = max_opno + 1; 86818334Speter d->n_dups = num_dups; 86918334Speter 870169689Skan#ifndef USE_MD_CONSTRAINTS 871132718Skan check_constraint_len (); 872169689Skan#endif 87390075Sobrien validate_insn_operands (d); 87418334Speter validate_insn_alternatives (d); 87590075Sobrien place_operands (d); 87690075Sobrien process_template (d, XTMPL (insn, 3)); 87718334Speter} 87818334Speter 87918334Speter/* Look at a define_peephole just read. Assign its code number. 88090075Sobrien Record on idata the template and the number of arguments. 88118334Speter If the insn has a hairy output action, output it now. */ 88218334Speter 88318334Speterstatic void 884132718Skangen_peephole (rtx peep, int lineno) 88518334Speter{ 886169689Skan struct data *d = XNEW (struct data); 88790075Sobrien int i; 88818334Speter 88990075Sobrien d->code_number = next_code_number; 89018334Speter d->index_number = next_index_number; 891169689Skan d->filename = read_rtx_filename; 89290075Sobrien d->lineno = lineno; 89318334Speter d->name = 0; 89418334Speter 89518334Speter /* Build up the list in the same order as the insns are seen 89618334Speter in the machine description. */ 89718334Speter d->next = 0; 89890075Sobrien *idata_end = d; 89990075Sobrien idata_end = &d->next; 90018334Speter 90118334Speter max_opno = -1; 90290075Sobrien num_dups = 0; 90390075Sobrien memset (d->operand, 0, sizeof (d->operand)); 90418334Speter 90590075Sobrien /* Get the number of operands by scanning all the patterns of the 90690075Sobrien peephole optimizer. But ignore all the rest of the information 90790075Sobrien thus obtained. */ 90818334Speter for (i = 0; i < XVECLEN (peep, 0); i++) 90990075Sobrien scan_operands (d, XVECEXP (peep, 0, i), 0, 0); 91018334Speter 91118334Speter d->n_operands = max_opno + 1; 91218334Speter d->n_dups = 0; 91318334Speter 91418334Speter validate_insn_alternatives (d); 91590075Sobrien place_operands (d); 91690075Sobrien process_template (d, XTMPL (peep, 2)); 91718334Speter} 91818334Speter 91918334Speter/* Process a define_expand just read. Assign its code number, 92018334Speter only for the purposes of `insn_gen_function'. */ 92118334Speter 92218334Speterstatic void 923132718Skangen_expand (rtx insn, int lineno) 92418334Speter{ 925169689Skan struct data *d = XNEW (struct data); 92690075Sobrien int i; 92718334Speter 92890075Sobrien d->code_number = next_code_number; 92918334Speter d->index_number = next_index_number; 930169689Skan d->filename = read_rtx_filename; 93190075Sobrien d->lineno = lineno; 93218334Speter if (XSTR (insn, 0)[0]) 93318334Speter d->name = XSTR (insn, 0); 93418334Speter else 93518334Speter d->name = 0; 93618334Speter 93718334Speter /* Build up the list in the same order as the insns are seen 93818334Speter in the machine description. */ 93918334Speter d->next = 0; 94090075Sobrien *idata_end = d; 94190075Sobrien idata_end = &d->next; 94218334Speter 94318334Speter max_opno = -1; 94418334Speter num_dups = 0; 94590075Sobrien memset (d->operand, 0, sizeof (d->operand)); 94618334Speter 94718334Speter /* Scan the operands to get the specified predicates and modes, 94818334Speter since expand_binop needs to know them. */ 94918334Speter 95018334Speter if (XVEC (insn, 1)) 95118334Speter for (i = 0; i < XVECLEN (insn, 1); i++) 95290075Sobrien scan_operands (d, XVECEXP (insn, 1, i), 0, 0); 95318334Speter 95418334Speter d->n_operands = max_opno + 1; 95518334Speter d->n_dups = num_dups; 95690075Sobrien d->template = 0; 95790075Sobrien d->output_format = INSN_OUTPUT_FORMAT_NONE; 95818334Speter 95918334Speter validate_insn_alternatives (d); 96090075Sobrien place_operands (d); 96118334Speter} 96218334Speter 96318334Speter/* Process a define_split just read. Assign its code number, 96418334Speter only for reasons of consistency and to simplify genrecog. */ 96518334Speter 96618334Speterstatic void 967132718Skangen_split (rtx split, int lineno) 96818334Speter{ 969169689Skan struct data *d = XNEW (struct data); 97090075Sobrien int i; 97118334Speter 97290075Sobrien d->code_number = next_code_number; 97318334Speter d->index_number = next_index_number; 974169689Skan d->filename = read_rtx_filename; 97590075Sobrien d->lineno = lineno; 97618334Speter d->name = 0; 97718334Speter 97818334Speter /* Build up the list in the same order as the insns are seen 97918334Speter in the machine description. */ 98018334Speter d->next = 0; 98190075Sobrien *idata_end = d; 98290075Sobrien idata_end = &d->next; 98318334Speter 98418334Speter max_opno = -1; 98518334Speter num_dups = 0; 98690075Sobrien memset (d->operand, 0, sizeof (d->operand)); 98718334Speter 98890075Sobrien /* Get the number of operands by scanning all the patterns of the 98990075Sobrien split patterns. But ignore all the rest of the information thus 99090075Sobrien obtained. */ 99118334Speter for (i = 0; i < XVECLEN (split, 0); i++) 99290075Sobrien scan_operands (d, XVECEXP (split, 0, i), 0, 0); 99318334Speter 99418334Speter d->n_operands = max_opno + 1; 99518334Speter d->n_dups = 0; 99618334Speter d->n_alternatives = 0; 99718334Speter d->template = 0; 99890075Sobrien d->output_format = INSN_OUTPUT_FORMAT_NONE; 99918334Speter 100090075Sobrien place_operands (d); 100118334Speter} 100218334Speter 1003132718Skanextern int main (int, char **); 100418334Speter 100518334Speterint 1006132718Skanmain (int argc, char **argv) 100718334Speter{ 100818334Speter rtx desc; 100918334Speter 101090075Sobrien progname = "genoutput"; 101118334Speter 101290075Sobrien if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 101390075Sobrien return (FATAL_EXIT_CODE); 101418334Speter 101518334Speter output_prologue (); 101618334Speter next_code_number = 0; 101718334Speter next_index_number = 0; 101818334Speter 101918334Speter /* Read the machine description. */ 102018334Speter 102118334Speter while (1) 102218334Speter { 102390075Sobrien int line_no; 102490075Sobrien 102590075Sobrien desc = read_md_rtx (&line_no, &next_code_number); 102690075Sobrien if (desc == NULL) 102718334Speter break; 102818334Speter 1029169689Skan switch (GET_CODE (desc)) 1030169689Skan { 1031169689Skan case DEFINE_INSN: 1032169689Skan gen_insn (desc, line_no); 1033169689Skan break; 1034169689Skan 1035169689Skan case DEFINE_PEEPHOLE: 1036169689Skan gen_peephole (desc, line_no); 1037169689Skan break; 1038169689Skan 1039169689Skan case DEFINE_EXPAND: 1040169689Skan gen_expand (desc, line_no); 1041169689Skan break; 1042169689Skan 1043169689Skan case DEFINE_SPLIT: 1044169689Skan case DEFINE_PEEPHOLE2: 1045169689Skan gen_split (desc, line_no); 1046169689Skan break; 1047169689Skan 1048169689Skan#ifdef USE_MD_CONSTRAINTS 1049169689Skan case DEFINE_CONSTRAINT: 1050169689Skan case DEFINE_REGISTER_CONSTRAINT: 1051169689Skan case DEFINE_ADDRESS_CONSTRAINT: 1052169689Skan case DEFINE_MEMORY_CONSTRAINT: 1053169689Skan note_constraint (desc, line_no); 1054169689Skan break; 1055169689Skan#endif 1056169689Skan 1057169689Skan default: 1058169689Skan break; 1059169689Skan } 106018334Speter next_index_number++; 106118334Speter } 106218334Speter 106390075Sobrien printf("\n\n"); 106490075Sobrien output_operand_data (); 106590075Sobrien output_insn_data (); 106690075Sobrien output_get_insn_name (); 106718334Speter 106818334Speter fflush (stdout); 106990075Sobrien return (ferror (stdout) != 0 || have_error 107018334Speter ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 107118334Speter} 107218334Speter 107390075Sobrien/* Return the number of occurrences of character C in string S or 107490075Sobrien -1 if S is the null string. */ 107590075Sobrien 107618334Speterstatic int 1077132718Skann_occurrences (int c, const char *s) 107818334Speter{ 107918334Speter int n = 0; 108090075Sobrien 108190075Sobrien if (s == 0 || *s == '\0') 108290075Sobrien return -1; 108390075Sobrien 108418334Speter while (*s) 108518334Speter n += (*s++ == c); 108690075Sobrien 108718334Speter return n; 108818334Speter} 108990075Sobrien 109090075Sobrien/* Remove whitespace in `s' by moving up characters until the end. 109190075Sobrien Return a new string. */ 109290075Sobrien 109390075Sobrienstatic const char * 1094132718Skanstrip_whitespace (const char *s) 109590075Sobrien{ 109690075Sobrien char *p, *q; 109790075Sobrien char ch; 109890075Sobrien 109990075Sobrien if (s == 0) 110090075Sobrien return 0; 110190075Sobrien 1102169689Skan p = q = XNEWVEC (char, strlen (s) + 1); 110390075Sobrien while ((ch = *s++) != '\0') 110490075Sobrien if (! ISSPACE (ch)) 110590075Sobrien *p++ = ch; 110690075Sobrien 110790075Sobrien *p = '\0'; 110890075Sobrien return q; 110990075Sobrien} 1110132718Skan 1111169689Skan#ifdef USE_MD_CONSTRAINTS 1112169689Skan 1113169689Skan/* Record just enough information about a constraint to allow checking 1114169689Skan of operand constraint strings above, in validate_insn_alternatives. 1115169689Skan Does not validate most properties of the constraint itself; does 1116169689Skan enforce no duplicate names, no overlap with MI constraints, and no 1117169689Skan prefixes. EXP is the define_*constraint form, LINENO the line number 1118169689Skan reported by the reader. */ 1119169689Skanstatic void 1120169689Skannote_constraint (rtx exp, int lineno) 1121169689Skan{ 1122169689Skan const char *name = XSTR (exp, 0); 1123169689Skan unsigned int namelen = strlen (name); 1124169689Skan struct constraint_data **iter, **slot, *new; 1125169689Skan 1126169689Skan if (strchr (indep_constraints, name[0])) 1127169689Skan { 1128169689Skan if (name[1] == '\0') 1129169689Skan message_with_line (lineno, "constraint letter '%s' cannot be " 1130169689Skan "redefined by the machine description", name); 1131169689Skan else 1132169689Skan message_with_line (lineno, "constraint name '%s' cannot be defined by " 1133169689Skan "the machine description, as it begins with '%c'", 1134169689Skan name, name[0]); 1135169689Skan have_error = 1; 1136169689Skan return; 1137169689Skan } 1138169689Skan 1139169689Skan slot = &constraints_by_letter_table[(unsigned int)name[0]]; 1140169689Skan for (iter = slot; *iter; iter = &(*iter)->next_this_letter) 1141169689Skan { 1142169689Skan /* This causes slot to end up pointing to the 1143169689Skan next_this_letter field of the last constraint with a name 1144169689Skan of equal or greater length than the new constraint; hence 1145169689Skan the new constraint will be inserted after all previous 1146169689Skan constraints with names of the same length. */ 1147169689Skan if ((*iter)->namelen >= namelen) 1148169689Skan slot = iter; 1149169689Skan 1150169689Skan if (!strcmp ((*iter)->name, name)) 1151169689Skan { 1152169689Skan message_with_line (lineno, "redefinition of constraint '%s'", name); 1153169689Skan message_with_line ((*iter)->lineno, "previous definition is here"); 1154169689Skan have_error = 1; 1155169689Skan return; 1156169689Skan } 1157169689Skan else if (!strncmp ((*iter)->name, name, (*iter)->namelen)) 1158169689Skan { 1159169689Skan message_with_line (lineno, "defining constraint '%s' here", name); 1160169689Skan message_with_line ((*iter)->lineno, "renders constraint '%s' " 1161169689Skan "(defined here) a prefix", (*iter)->name); 1162169689Skan have_error = 1; 1163169689Skan return; 1164169689Skan } 1165169689Skan else if (!strncmp ((*iter)->name, name, namelen)) 1166169689Skan { 1167169689Skan message_with_line (lineno, "constraint '%s' is a prefix", name); 1168169689Skan message_with_line ((*iter)->lineno, "of constraint '%s' " 1169169689Skan "(defined here)", (*iter)->name); 1170169689Skan have_error = 1; 1171169689Skan return; 1172169689Skan } 1173169689Skan } 1174169689Skan new = xmalloc (sizeof (struct constraint_data) + namelen); 1175169689Skan strcpy ((char *)new + offsetof(struct constraint_data, name), name); 1176169689Skan new->namelen = namelen; 1177169689Skan new->lineno = lineno; 1178169689Skan new->next_this_letter = *slot; 1179169689Skan *slot = new; 1180169689Skan} 1181169689Skan 1182169689Skan/* Return the length of the constraint name beginning at position S 1183169689Skan of an operand constraint string, or issue an error message if there 1184169689Skan is no such constraint. Does not expect to be called for generic 1185169689Skan constraints. */ 1186169689Skanstatic int 1187169689Skanmdep_constraint_len (const char *s, int lineno, int opno) 1188169689Skan{ 1189169689Skan struct constraint_data *p; 1190169689Skan 1191169689Skan p = constraints_by_letter_table[(unsigned int)s[0]]; 1192169689Skan 1193169689Skan if (p) 1194169689Skan for (; p; p = p->next_this_letter) 1195169689Skan if (!strncmp (s, p->name, p->namelen)) 1196169689Skan return p->namelen; 1197169689Skan 1198169689Skan message_with_line (lineno, 1199169689Skan "error: undefined machine-specific constraint " 1200169689Skan "at this point: \"%s\"", s); 1201169689Skan message_with_line (lineno, "note: in operand %d", opno); 1202169689Skan have_error = 1; 1203169689Skan return 1; /* safe */ 1204169689Skan} 1205169689Skan 1206169689Skan#else 1207132718Skan/* Verify that DEFAULT_CONSTRAINT_LEN is used properly and not 1208132718Skan tampered with. This isn't bullet-proof, but it should catch 1209132718Skan most genuine mistakes. */ 1210132718Skanstatic void 1211132718Skancheck_constraint_len (void) 1212132718Skan{ 1213132718Skan const char *p; 1214132718Skan int d; 1215132718Skan 1216132718Skan for (p = ",#*+=&%!1234567890"; *p; p++) 1217132718Skan for (d = -9; d < 9; d++) 1218169689Skan gcc_assert (constraint_len (p, d) == d); 1219132718Skan} 1220132718Skan 1221132718Skanstatic int 1222132718Skanconstraint_len (const char *p, int genoutput_default_constraint_len) 1223132718Skan{ 1224132718Skan /* Check that we still match defaults.h . First we do a generation-time 1225132718Skan check that fails if the value is not the expected one... */ 1226169689Skan gcc_assert (DEFAULT_CONSTRAINT_LEN (*p, p) == 1); 1227132718Skan /* And now a compile-time check that should give a diagnostic if the 1228132718Skan definition doesn't exactly match. */ 1229132718Skan#define DEFAULT_CONSTRAINT_LEN(C,STR) 1 1230132718Skan /* Now re-define DEFAULT_CONSTRAINT_LEN so that we can verify it is 1231132718Skan being used. */ 1232132718Skan#undef DEFAULT_CONSTRAINT_LEN 1233132718Skan#define DEFAULT_CONSTRAINT_LEN(C,STR) \ 1234132718Skan ((C) != *p || STR != p ? -1 : genoutput_default_constraint_len) 1235132718Skan return CONSTRAINT_LEN (*p, p); 1236132718Skan /* And set it back. */ 1237132718Skan#undef DEFAULT_CONSTRAINT_LEN 1238132718Skan#define DEFAULT_CONSTRAINT_LEN(C,STR) 1 1239132718Skan} 1240169689Skan#endif 1241