genoutput.c revision 132718
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, 3132718Skan 2003, 2004 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 1990075SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA 2090075Sobrien02111-1307, 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 5790075Sobrien b. `constraint' is the constraint for this operand. This exists 5890075Sobrien only if register constraints appear in match_operand rtx's. 5918334Speter 6090075Sobrien c. `address_p' indicates that the operand appears within ADDRESS 6190075Sobrien rtx's. This exists only if there are *no* register constraints 6290075Sobrien in the match_operand rtx's. 6318334Speter 6490075Sobrien d. `mode' is the machine mode that that operand is supposed to have. 6590075Sobrien 6690075Sobrien e. `strict_low', is nonzero for operands contained in a STRICT_LOW_PART. 6790075Sobrien 6890075Sobrien f. `eliminable', is nonzero for operands that are matched normally by 6990075Sobrien MATCH_OPERAND; it is zero for operands that should not be changed during 7090075Sobrien register elimination such as MATCH_OPERATORs. 7190075Sobrien 7290075Sobrien The code number of an insn is simply its position in the machine 7390075Sobrien description; code numbers are assigned sequentially to entries in 7490075Sobrien the description, starting with code number 0. 7590075Sobrien 7690075Sobrien Thus, the following entry in the machine description 7790075Sobrien 7818334Speter (define_insn "clrdf" 7918334Speter [(set (match_operand:DF 0 "general_operand" "") 8018334Speter (const_int 0))] 8118334Speter "" 8218334Speter "clrd %0") 8318334Speter 8490075Sobrien assuming it is the 25th entry present, would cause 8590075Sobrien insn_data[24].template to be "clrd %0", and 8690075Sobrien insn_data[24].n_operands to be 1. */ 8718334Speter 88132718Skan#include "bconfig.h" 8950397Sobrien#include "system.h" 90132718Skan#include "coretypes.h" 91132718Skan#include "tm.h" 9218334Speter#include "rtl.h" 9390075Sobrien#include "errors.h" 9490075Sobrien#include "gensupport.h" 9518334Speter 9690075Sobrien/* No instruction can have more operands than this. Sorry for this 9790075Sobrien arbitrary limit, but what machine will have an instruction with 9890075Sobrien this many operands? */ 9918334Speter 10018334Speter#define MAX_MAX_OPERANDS 40 10118334Speter 102132718Skanstatic int n_occurrences (int, const char *); 103132718Skanstatic const char *strip_whitespace (const char *); 10418334Speter 10518334Speter/* insns in the machine description are assigned sequential code numbers 10618334Speter that are used by insn-recog.c (produced by genrecog) to communicate 10718334Speter to insn-output.c (produced by this program). */ 10818334Speter 10918334Speterstatic int next_code_number; 11018334Speter 11118334Speter/* This counts all definitions in the md file, 11218334Speter for the sake of error messages. */ 11318334Speter 11418334Speterstatic int next_index_number; 11518334Speter 11690075Sobrien/* This counts all operands used in the md file. The first is null. */ 11790075Sobrien 11890075Sobrienstatic int next_operand_number = 1; 11990075Sobrien 12090075Sobrien/* Record in this chain all information about the operands we will output. */ 12190075Sobrien 12290075Sobrienstruct operand_data 12390075Sobrien{ 12490075Sobrien struct operand_data *next; 12590075Sobrien int index; 12690075Sobrien const char *predicate; 12790075Sobrien const char *constraint; 12890075Sobrien enum machine_mode mode; 12990075Sobrien unsigned char n_alternatives; 13090075Sobrien char address_p; 13190075Sobrien char strict_low; 13290075Sobrien char eliminable; 13390075Sobrien char seen; 13490075Sobrien}; 13590075Sobrien 13690075Sobrien/* Begin with a null operand at index 0. */ 13790075Sobrien 13890075Sobrienstatic struct operand_data null_operand = 13990075Sobrien{ 14090075Sobrien 0, 0, "", "", VOIDmode, 0, 0, 0, 0, 0 14190075Sobrien}; 14290075Sobrien 14390075Sobrienstatic struct operand_data *odata = &null_operand; 14490075Sobrienstatic struct operand_data **odata_end = &null_operand.next; 14590075Sobrien 14690075Sobrien/* Must match the constants in recog.h. */ 14790075Sobrien 14890075Sobrien#define INSN_OUTPUT_FORMAT_NONE 0 /* abort */ 14990075Sobrien#define INSN_OUTPUT_FORMAT_SINGLE 1 /* const char * */ 15090075Sobrien#define INSN_OUTPUT_FORMAT_MULTI 2 /* const char * const * */ 15190075Sobrien#define INSN_OUTPUT_FORMAT_FUNCTION 3 /* const char * (*)(...) */ 15290075Sobrien 15318334Speter/* Record in this chain all information that we will output, 15418334Speter associated with the code number of the insn. */ 15518334Speter 15618334Speterstruct data 15718334Speter{ 15890075Sobrien struct data *next; 15990075Sobrien const char *name; 16090075Sobrien const char *template; 16118334Speter int code_number; 16218334Speter int index_number; 16390075Sobrien int lineno; 16418334Speter int n_operands; /* Number of operands this insn recognizes */ 16518334Speter int n_dups; /* Number times match_dup appears in pattern */ 16618334Speter int n_alternatives; /* Number of alternatives in each constraint */ 16790075Sobrien int operand_number; /* Operand index in the big array. */ 16890075Sobrien int output_format; /* INSN_OUTPUT_FORMAT_*. */ 16990075Sobrien struct operand_data operand[MAX_MAX_OPERANDS]; 17018334Speter}; 17118334Speter 17290075Sobrien/* This variable points to the first link in the insn chain. */ 17318334Speter 17490075Sobrienstatic struct data *idata, **idata_end = &idata; 17518334Speter 176132718Skanstatic void output_prologue (void); 177132718Skanstatic void output_operand_data (void); 178132718Skanstatic void output_insn_data (void); 179132718Skanstatic void output_get_insn_name (void); 180132718Skanstatic void scan_operands (struct data *, rtx, int, int); 181132718Skanstatic int compare_operands (struct operand_data *, 182132718Skan struct operand_data *); 183132718Skanstatic void place_operands (struct data *); 184132718Skanstatic void process_template (struct data *, const char *); 185132718Skanstatic void validate_insn_alternatives (struct data *); 186132718Skanstatic void validate_insn_operands (struct data *); 187132718Skanstatic void gen_insn (rtx, int); 188132718Skanstatic void gen_peephole (rtx, int); 189132718Skanstatic void gen_expand (rtx, int); 190132718Skanstatic void gen_split (rtx, int); 191132718Skanstatic void check_constraint_len (void); 192132718Skanstatic int constraint_len (const char *, int); 19350397Sobrien 19490075Sobrienconst char * 195132718Skanget_insn_name (int index) 19652284Sobrien{ 19752284Sobrien static char buf[100]; 19852284Sobrien 19952284Sobrien struct data *i, *last_named = NULL; 20090075Sobrien for (i = idata; i ; i = i->next) 20152284Sobrien { 20252284Sobrien if (i->index_number == index) 20352284Sobrien return i->name; 20452284Sobrien if (i->name) 20552284Sobrien last_named = i; 20652284Sobrien } 20752284Sobrien 20852284Sobrien if (last_named) 20952284Sobrien sprintf(buf, "%s+%d", last_named->name, index - last_named->index_number); 21052284Sobrien else 21152284Sobrien sprintf(buf, "insn %d", index); 21252284Sobrien 21352284Sobrien return buf; 21452284Sobrien} 21552284Sobrien 21618334Speterstatic void 217132718Skanoutput_prologue (void) 21818334Speter{ 21918334Speter printf ("/* Generated automatically by the program `genoutput'\n\ 22090075Sobrien from the machine description file `md'. */\n\n"); 22118334Speter 22218334Speter printf ("#include \"config.h\"\n"); 22350397Sobrien printf ("#include \"system.h\"\n"); 224132718Skan printf ("#include \"coretypes.h\"\n"); 225132718Skan printf ("#include \"tm.h\"\n"); 22650397Sobrien printf ("#include \"flags.h\"\n"); 22790075Sobrien printf ("#include \"ggc.h\"\n"); 22818334Speter printf ("#include \"rtl.h\"\n"); 22990075Sobrien printf ("#include \"expr.h\"\n"); 23090075Sobrien printf ("#include \"insn-codes.h\"\n"); 23190075Sobrien printf ("#include \"tm_p.h\"\n"); 23290075Sobrien printf ("#include \"function.h\"\n"); 23318334Speter printf ("#include \"regs.h\"\n"); 23418334Speter printf ("#include \"hard-reg-set.h\"\n"); 23518334Speter printf ("#include \"real.h\"\n"); 23618334Speter printf ("#include \"insn-config.h\"\n\n"); 23718334Speter printf ("#include \"conditions.h\"\n"); 23818334Speter printf ("#include \"insn-attr.h\"\n\n"); 23918334Speter printf ("#include \"recog.h\"\n\n"); 24090075Sobrien printf ("#include \"toplev.h\"\n"); 24118334Speter printf ("#include \"output.h\"\n"); 242132718Skan printf ("#include \"target.h\"\n"); 24318334Speter} 24418334Speter 24518334Speterstatic void 246132718Skanoutput_operand_data (void) 24718334Speter{ 24890075Sobrien struct operand_data *d; 24918334Speter 25090075Sobrien printf ("\nstatic const struct insn_operand_data operand_data[] = \n{\n"); 25190075Sobrien 25290075Sobrien for (d = odata; d; d = d->next) 25318334Speter { 25490075Sobrien printf (" {\n"); 25518334Speter 25690075Sobrien printf (" %s,\n", 25790075Sobrien d->predicate && d->predicate[0] ? d->predicate : "0"); 25890075Sobrien 25990075Sobrien printf (" \"%s\",\n", d->constraint ? d->constraint : ""); 26090075Sobrien 26190075Sobrien printf (" %smode,\n", GET_MODE_NAME (d->mode)); 26290075Sobrien 26390075Sobrien printf (" %d,\n", d->strict_low); 26490075Sobrien 26590075Sobrien printf (" %d\n", d->eliminable); 26690075Sobrien 26790075Sobrien printf(" },\n"); 26818334Speter } 26990075Sobrien printf("};\n\n\n"); 27090075Sobrien} 27118334Speter 27290075Sobrienstatic void 273132718Skanoutput_insn_data (void) 27490075Sobrien{ 27590075Sobrien struct data *d; 27690075Sobrien int name_offset = 0; 27790075Sobrien int next_name_offset; 27890075Sobrien const char * last_name = 0; 27990075Sobrien const char * next_name = 0; 28090075Sobrien struct data *n; 28118334Speter 28290075Sobrien for (n = idata, next_name_offset = 1; n; n = n->next, next_name_offset++) 28390075Sobrien if (n->name) 28418334Speter { 28590075Sobrien next_name = n->name; 28690075Sobrien break; 28718334Speter } 28818334Speter 289132718Skan printf ("#if GCC_VERSION >= 2007\n__extension__\n#endif\n"); 29090075Sobrien printf ("\nconst struct insn_data insn_data[] = \n{\n"); 29118334Speter 29290075Sobrien for (d = idata; d; d = d->next) 29390075Sobrien { 29490075Sobrien printf (" {\n"); 29518334Speter 29690075Sobrien if (d->name) 29718334Speter { 29890075Sobrien printf (" \"%s\",\n", d->name); 29990075Sobrien name_offset = 0; 30090075Sobrien last_name = d->name; 30190075Sobrien next_name = 0; 30290075Sobrien for (n = d->next, next_name_offset = 1; n; 30390075Sobrien n = n->next, next_name_offset++) 30418334Speter { 30590075Sobrien if (n->name) 30690075Sobrien { 30790075Sobrien next_name = n->name; 30890075Sobrien break; 30990075Sobrien } 31018334Speter } 31118334Speter } 31290075Sobrien else 31318334Speter { 31490075Sobrien name_offset++; 31590075Sobrien if (next_name && (last_name == 0 31690075Sobrien || name_offset > next_name_offset / 2)) 31790075Sobrien printf (" \"%s-%d\",\n", next_name, 31890075Sobrien next_name_offset - name_offset); 31990075Sobrien else 32090075Sobrien printf (" \"%s+%d\",\n", last_name, name_offset); 32118334Speter } 32218334Speter 32390075Sobrien switch (d->output_format) 32490075Sobrien { 32590075Sobrien case INSN_OUTPUT_FORMAT_NONE: 326132718Skan printf ("#if HAVE_DESIGNATED_INITIALIZERS\n"); 327132718Skan printf (" { 0 },\n"); 328132718Skan printf ("#else\n"); 329132718Skan printf (" { 0, 0, 0 },\n"); 330132718Skan printf ("#endif\n"); 33190075Sobrien break; 33290075Sobrien case INSN_OUTPUT_FORMAT_SINGLE: 33318334Speter { 33490075Sobrien const char *p = d->template; 33590075Sobrien char prev = 0; 336132718Skan 337132718Skan printf ("#if HAVE_DESIGNATED_INITIALIZERS\n"); 338132718Skan printf (" { .single =\n"); 339132718Skan printf ("#else\n"); 340132718Skan printf (" {\n"); 341132718Skan printf ("#endif\n"); 34290075Sobrien printf (" \""); 34390075Sobrien while (*p) 34418334Speter { 34596263Sobrien if (IS_VSPACE (*p) && prev != '\\') 34696263Sobrien { 34796263Sobrien /* Preserve two consecutive \n's or \r's, but treat \r\n 34896263Sobrien as a single newline. */ 34996263Sobrien if (*p == '\n' && prev != '\r') 35096263Sobrien printf ("\\n\\\n"); 35196263Sobrien } 35290075Sobrien else 35390075Sobrien putchar (*p); 35490075Sobrien prev = *p; 35590075Sobrien ++p; 35618334Speter } 35790075Sobrien printf ("\",\n"); 358132718Skan printf ("#if HAVE_DESIGNATED_INITIALIZERS\n"); 359132718Skan printf (" },\n"); 360132718Skan printf ("#else\n"); 361132718Skan printf (" 0, 0 },\n"); 362132718Skan printf ("#endif\n"); 36318334Speter } 36490075Sobrien break; 36590075Sobrien case INSN_OUTPUT_FORMAT_MULTI: 366132718Skan printf ("#if HAVE_DESIGNATED_INITIALIZERS\n"); 367132718Skan printf (" { .multi = output_%d },\n", d->code_number); 368132718Skan printf ("#else\n"); 369132718Skan printf (" { 0, output_%d, 0 },\n", d->code_number); 370132718Skan printf ("#endif\n"); 371132718Skan break; 37290075Sobrien case INSN_OUTPUT_FORMAT_FUNCTION: 373132718Skan printf ("#if HAVE_DESIGNATED_INITIALIZERS\n"); 374132718Skan printf (" { .function = output_%d },\n", d->code_number); 375132718Skan printf ("#else\n"); 376132718Skan printf (" { 0, 0, output_%d },\n", d->code_number); 377132718Skan printf ("#endif\n"); 37890075Sobrien break; 37990075Sobrien default: 38090075Sobrien abort (); 38190075Sobrien } 38218334Speter 38390075Sobrien if (d->name && d->name[0] != '*') 38490075Sobrien printf (" (insn_gen_fn) gen_%s,\n", d->name); 38590075Sobrien else 38690075Sobrien printf (" 0,\n"); 38790075Sobrien 38890075Sobrien printf (" &operand_data[%d],\n", d->operand_number); 38990075Sobrien printf (" %d,\n", d->n_operands); 39090075Sobrien printf (" %d,\n", d->n_dups); 39190075Sobrien printf (" %d,\n", d->n_alternatives); 39290075Sobrien printf (" %d\n", d->output_format); 39390075Sobrien 39490075Sobrien printf(" },\n"); 39590075Sobrien } 39690075Sobrien printf ("};\n\n\n"); 39718334Speter} 39890075Sobrien 39990075Sobrienstatic void 400132718Skanoutput_get_insn_name (void) 40190075Sobrien{ 40290075Sobrien printf ("const char *\n"); 403132718Skan printf ("get_insn_name (int code)\n"); 40490075Sobrien printf ("{\n"); 405132718Skan printf (" if (code == NOOP_MOVE_INSN_CODE)\n"); 406132718Skan printf (" return \"NOOP_MOVE\";\n"); 407132718Skan printf (" else\n"); 408132718Skan printf (" return insn_data[code].name;\n"); 40990075Sobrien printf ("}\n"); 41090075Sobrien} 41190075Sobrien 41218334Speter 41390075Sobrien/* Stores in max_opno the largest operand number present in `part', if 41490075Sobrien that is larger than the previous value of max_opno, and the rest of 41590075Sobrien the operand data into `d->operand[i]'. 41618334Speter 41718334Speter THIS_ADDRESS_P is nonzero if the containing rtx was an ADDRESS. 41818334Speter THIS_STRICT_LOW is nonzero if the containing rtx was a STRICT_LOW_PART. */ 41918334Speter 42018334Speterstatic int max_opno; 42118334Speterstatic int num_dups; 42218334Speter 42318334Speterstatic void 424132718Skanscan_operands (struct data *d, rtx part, int this_address_p, 425132718Skan int this_strict_low) 42618334Speter{ 42790075Sobrien int i, j; 42890075Sobrien const char *format_ptr; 42918334Speter int opno; 43018334Speter 43118334Speter if (part == 0) 43218334Speter return; 43318334Speter 43418334Speter switch (GET_CODE (part)) 43518334Speter { 43618334Speter case MATCH_OPERAND: 43718334Speter opno = XINT (part, 0); 43818334Speter if (opno > max_opno) 43918334Speter max_opno = opno; 44018334Speter if (max_opno >= MAX_MAX_OPERANDS) 44118334Speter { 44290075Sobrien message_with_line (d->lineno, 44390075Sobrien "maximum number of operands exceeded"); 44490075Sobrien have_error = 1; 44518334Speter return; 44618334Speter } 44790075Sobrien if (d->operand[opno].seen) 44818334Speter { 44990075Sobrien message_with_line (d->lineno, 45090075Sobrien "repeated operand number %d\n", opno); 45190075Sobrien have_error = 1; 45218334Speter } 45390075Sobrien 45490075Sobrien d->operand[opno].seen = 1; 45590075Sobrien d->operand[opno].mode = GET_MODE (part); 45690075Sobrien d->operand[opno].strict_low = this_strict_low; 45790075Sobrien d->operand[opno].predicate = XSTR (part, 1); 45890075Sobrien d->operand[opno].constraint = strip_whitespace (XSTR (part, 2)); 45990075Sobrien d->operand[opno].n_alternatives 46090075Sobrien = n_occurrences (',', d->operand[opno].constraint) + 1; 46190075Sobrien d->operand[opno].address_p = this_address_p; 46290075Sobrien d->operand[opno].eliminable = 1; 46318334Speter return; 46418334Speter 46518334Speter case MATCH_SCRATCH: 46618334Speter opno = XINT (part, 0); 46718334Speter if (opno > max_opno) 46818334Speter max_opno = opno; 46918334Speter if (max_opno >= MAX_MAX_OPERANDS) 47018334Speter { 47190075Sobrien message_with_line (d->lineno, 47290075Sobrien "maximum number of operands exceeded"); 47390075Sobrien have_error = 1; 47418334Speter return; 47518334Speter } 47690075Sobrien if (d->operand[opno].seen) 47718334Speter { 47890075Sobrien message_with_line (d->lineno, 47990075Sobrien "repeated operand number %d\n", opno); 48090075Sobrien have_error = 1; 48118334Speter } 48290075Sobrien 48390075Sobrien d->operand[opno].seen = 1; 48490075Sobrien d->operand[opno].mode = GET_MODE (part); 48590075Sobrien d->operand[opno].strict_low = 0; 48690075Sobrien d->operand[opno].predicate = "scratch_operand"; 48790075Sobrien d->operand[opno].constraint = strip_whitespace (XSTR (part, 1)); 48890075Sobrien d->operand[opno].n_alternatives 48990075Sobrien = n_occurrences (',', d->operand[opno].constraint) + 1; 49090075Sobrien d->operand[opno].address_p = 0; 49190075Sobrien d->operand[opno].eliminable = 0; 49218334Speter return; 49318334Speter 49418334Speter case MATCH_OPERATOR: 49518334Speter case MATCH_PARALLEL: 49618334Speter opno = XINT (part, 0); 49718334Speter if (opno > max_opno) 49818334Speter max_opno = opno; 49918334Speter if (max_opno >= MAX_MAX_OPERANDS) 50018334Speter { 50190075Sobrien message_with_line (d->lineno, 50290075Sobrien "maximum number of operands exceeded"); 50390075Sobrien have_error = 1; 50418334Speter return; 50518334Speter } 50690075Sobrien if (d->operand[opno].seen) 50790075Sobrien { 50890075Sobrien message_with_line (d->lineno, 50990075Sobrien "repeated operand number %d\n", opno); 51090075Sobrien have_error = 1; 51190075Sobrien } 51290075Sobrien 51390075Sobrien d->operand[opno].seen = 1; 51490075Sobrien d->operand[opno].mode = GET_MODE (part); 51590075Sobrien d->operand[opno].strict_low = 0; 51690075Sobrien d->operand[opno].predicate = XSTR (part, 1); 51790075Sobrien d->operand[opno].constraint = 0; 51890075Sobrien d->operand[opno].address_p = 0; 51990075Sobrien d->operand[opno].eliminable = 0; 52018334Speter for (i = 0; i < XVECLEN (part, 2); i++) 52190075Sobrien scan_operands (d, XVECEXP (part, 2, i), 0, 0); 52218334Speter return; 52318334Speter 52418334Speter case MATCH_DUP: 52518334Speter case MATCH_OP_DUP: 52618334Speter case MATCH_PAR_DUP: 52718334Speter ++num_dups; 52896263Sobrien break; 52918334Speter 53018334Speter case ADDRESS: 53190075Sobrien scan_operands (d, XEXP (part, 0), 1, 0); 53218334Speter return; 53318334Speter 53418334Speter case STRICT_LOW_PART: 53590075Sobrien scan_operands (d, XEXP (part, 0), 0, 1); 53618334Speter return; 537132718Skan 53850397Sobrien default: 53950397Sobrien break; 54018334Speter } 54118334Speter 54218334Speter format_ptr = GET_RTX_FORMAT (GET_CODE (part)); 54318334Speter 54418334Speter for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++) 54518334Speter switch (*format_ptr++) 54618334Speter { 54718334Speter case 'e': 54850397Sobrien case 'u': 54990075Sobrien scan_operands (d, XEXP (part, i), 0, 0); 55018334Speter break; 55118334Speter case 'E': 55218334Speter if (XVEC (part, i) != NULL) 55318334Speter for (j = 0; j < XVECLEN (part, i); j++) 55490075Sobrien scan_operands (d, XVECEXP (part, i, j), 0, 0); 55518334Speter break; 55618334Speter } 55718334Speter} 55890075Sobrien 55990075Sobrien/* Compare two operands for content equality. */ 56090075Sobrien 56190075Sobrienstatic int 562132718Skancompare_operands (struct operand_data *d0, struct operand_data *d1) 56390075Sobrien{ 56490075Sobrien const char *p0, *p1; 56590075Sobrien 56690075Sobrien p0 = d0->predicate; 56790075Sobrien if (!p0) 56890075Sobrien p0 = ""; 56990075Sobrien p1 = d1->predicate; 57090075Sobrien if (!p1) 57190075Sobrien p1 = ""; 57290075Sobrien if (strcmp (p0, p1) != 0) 57390075Sobrien return 0; 57490075Sobrien 57590075Sobrien p0 = d0->constraint; 57690075Sobrien if (!p0) 57790075Sobrien p0 = ""; 57890075Sobrien p1 = d1->constraint; 57990075Sobrien if (!p1) 58090075Sobrien p1 = ""; 58190075Sobrien if (strcmp (p0, p1) != 0) 58290075Sobrien return 0; 58390075Sobrien 58490075Sobrien if (d0->mode != d1->mode) 58590075Sobrien return 0; 58690075Sobrien 58790075Sobrien if (d0->strict_low != d1->strict_low) 58890075Sobrien return 0; 58990075Sobrien 59090075Sobrien if (d0->eliminable != d1->eliminable) 59190075Sobrien return 0; 59290075Sobrien 59390075Sobrien return 1; 59490075Sobrien} 59590075Sobrien 59690075Sobrien/* Scan the list of operands we've already committed to output and either 59790075Sobrien find a subsequence that is the same, or allocate a new one at the end. */ 59890075Sobrien 59990075Sobrienstatic void 600132718Skanplace_operands (struct data *d) 60190075Sobrien{ 60290075Sobrien struct operand_data *od, *od2; 60390075Sobrien int i; 60490075Sobrien 60590075Sobrien if (d->n_operands == 0) 60690075Sobrien { 60790075Sobrien d->operand_number = 0; 60890075Sobrien return; 60990075Sobrien } 61090075Sobrien 61190075Sobrien /* Brute force substring search. */ 61290075Sobrien for (od = odata, i = 0; od; od = od->next, i = 0) 61390075Sobrien if (compare_operands (od, &d->operand[0])) 61490075Sobrien { 61590075Sobrien od2 = od->next; 61690075Sobrien i = 1; 61790075Sobrien while (1) 61890075Sobrien { 61990075Sobrien if (i == d->n_operands) 62090075Sobrien goto full_match; 62190075Sobrien if (od2 == NULL) 62290075Sobrien goto partial_match; 62390075Sobrien if (! compare_operands (od2, &d->operand[i])) 62490075Sobrien break; 62590075Sobrien ++i, od2 = od2->next; 62690075Sobrien } 62790075Sobrien } 62890075Sobrien 62990075Sobrien /* Either partial match at the end of the list, or no match. In either 63090075Sobrien case, we tack on what operands are remaining to the end of the list. */ 63190075Sobrien partial_match: 63290075Sobrien d->operand_number = next_operand_number - i; 63390075Sobrien for (; i < d->n_operands; ++i) 63490075Sobrien { 63590075Sobrien od2 = &d->operand[i]; 63690075Sobrien *odata_end = od2; 63790075Sobrien odata_end = &od2->next; 63890075Sobrien od2->index = next_operand_number++; 63990075Sobrien } 64090075Sobrien *odata_end = NULL; 64190075Sobrien return; 64290075Sobrien 64390075Sobrien full_match: 64490075Sobrien d->operand_number = od->index; 64590075Sobrien return; 64690075Sobrien} 64790075Sobrien 64818334Speter 64918334Speter/* Process an assembler template from a define_insn or a define_peephole. 65018334Speter It is either the assembler code template, a list of assembler code 65118334Speter templates, or C code to generate the assembler code template. */ 65218334Speter 65318334Speterstatic void 654132718Skanprocess_template (struct data *d, const char *template) 65518334Speter{ 65690075Sobrien const char *cp; 65790075Sobrien int i; 65818334Speter 65990075Sobrien /* Templates starting with * contain straight code to be run. */ 66090075Sobrien if (template[0] == '*') 66118334Speter { 66290075Sobrien d->template = 0; 66390075Sobrien d->output_format = INSN_OUTPUT_FORMAT_FUNCTION; 66418334Speter 665132718Skan puts ("\nstatic const char *"); 666132718Skan printf ("output_%d (rtx *operands ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED)\n", 66790075Sobrien d->code_number); 66890075Sobrien puts ("{"); 66918334Speter 67090075Sobrien puts (template + 1); 67190075Sobrien puts ("}"); 67290075Sobrien } 67318334Speter 67418334Speter /* If the assembler code template starts with a @ it is a newline-separated 67590075Sobrien list of assembler code templates, one for each alternative. */ 67690075Sobrien else if (template[0] == '@') 67718334Speter { 67890075Sobrien d->template = 0; 67990075Sobrien d->output_format = INSN_OUTPUT_FORMAT_MULTI; 68018334Speter 68190075Sobrien printf ("\nstatic const char * const output_%d[] = {\n", d->code_number); 68218334Speter 68318334Speter for (i = 0, cp = &template[1]; *cp; ) 68418334Speter { 68596263Sobrien while (ISSPACE (*cp)) 68618334Speter cp++; 68718334Speter 68890075Sobrien printf (" \""); 68996263Sobrien while (!IS_VSPACE (*cp) && *cp != '\0') 69050397Sobrien { 69150397Sobrien putchar (*cp); 69250397Sobrien cp++; 69350397Sobrien } 69418334Speter 69518334Speter printf ("\",\n"); 69618334Speter i++; 69718334Speter } 69890075Sobrien if (i == 1) 69990075Sobrien message_with_line (d->lineno, 70090075Sobrien "'@' is redundant for output template with single alternative"); 70118334Speter if (i != d->n_alternatives) 70290075Sobrien { 70390075Sobrien message_with_line (d->lineno, 70490075Sobrien "wrong number of alternatives in the output template"); 70590075Sobrien have_error = 1; 70690075Sobrien } 70718334Speter 70890075Sobrien printf ("};\n"); 70918334Speter } 71018334Speter else 71118334Speter { 71290075Sobrien d->template = template; 71390075Sobrien d->output_format = INSN_OUTPUT_FORMAT_SINGLE; 71418334Speter } 71518334Speter} 71618334Speter 71718334Speter/* Check insn D for consistency in number of constraint alternatives. */ 71818334Speter 71918334Speterstatic void 720132718Skanvalidate_insn_alternatives (struct data *d) 72118334Speter{ 72290075Sobrien int n = 0, start; 72390075Sobrien 72490075Sobrien /* Make sure all the operands have the same number of alternatives 72590075Sobrien in their constraints. Let N be that number. */ 72618334Speter for (start = 0; start < d->n_operands; start++) 72790075Sobrien if (d->operand[start].n_alternatives > 0) 72818334Speter { 729132718Skan int len, i; 730132718Skan const char *p; 731132718Skan char c; 732132718Skan int which_alternative = 0; 733132718Skan int alternative_count_unsure = 0; 734132718Skan 735132718Skan for (p = d->operand[start].constraint; (c = *p); p += len) 736132718Skan { 737132718Skan len = CONSTRAINT_LEN (c, p); 738132718Skan 739132718Skan if (len < 1 || (len > 1 && strchr (",#*+=&%!0123456789", c))) 740132718Skan { 741132718Skan message_with_line (d->lineno, 742132718Skan "invalid length %d for char '%c' in alternative %d of operand %d", 743132718Skan len, c, which_alternative, start); 744132718Skan len = 1; 745132718Skan have_error = 1; 746132718Skan } 747132718Skan 748132718Skan if (c == ',') 749132718Skan { 750132718Skan which_alternative++; 751132718Skan continue; 752132718Skan } 753132718Skan 754132718Skan for (i = 1; i < len; i++) 755132718Skan if (p[i] == '\0') 756132718Skan { 757132718Skan message_with_line (d->lineno, 758132718Skan "NUL in alternative %d of operand %d", 759132718Skan which_alternative, start); 760132718Skan alternative_count_unsure = 1; 761132718Skan break; 762132718Skan } 763132718Skan else if (strchr (",#*", p[i])) 764132718Skan { 765132718Skan message_with_line (d->lineno, 766132718Skan "'%c' in alternative %d of operand %d", 767132718Skan p[i], which_alternative, start); 768132718Skan alternative_count_unsure = 1; 769132718Skan } 770132718Skan } 771132718Skan if (alternative_count_unsure) 772132718Skan have_error = 1; 773132718Skan else if (n == 0) 77490075Sobrien n = d->operand[start].n_alternatives; 77590075Sobrien else if (n != d->operand[start].n_alternatives) 77690075Sobrien { 77790075Sobrien message_with_line (d->lineno, 77890075Sobrien "wrong number of alternatives in operand %d", 77990075Sobrien start); 78090075Sobrien have_error = 1; 78190075Sobrien } 78218334Speter } 78390075Sobrien 78418334Speter /* Record the insn's overall number of alternatives. */ 78518334Speter d->n_alternatives = n; 78618334Speter} 78790075Sobrien 78890075Sobrien/* Verify that there are no gaps in operand numbers for INSNs. */ 78990075Sobrien 79090075Sobrienstatic void 791132718Skanvalidate_insn_operands (struct data *d) 79290075Sobrien{ 79390075Sobrien int i; 79490075Sobrien 79590075Sobrien for (i = 0; i < d->n_operands; ++i) 79690075Sobrien if (d->operand[i].seen == 0) 79790075Sobrien { 79890075Sobrien message_with_line (d->lineno, "missing operand %d", i); 79990075Sobrien have_error = 1; 80090075Sobrien } 80190075Sobrien} 80218334Speter 80390075Sobrien/* Look at a define_insn just read. Assign its code number. Record 80490075Sobrien on idata the template and the number of arguments. If the insn has 80590075Sobrien a hairy output action, output a function for now. */ 80618334Speter 80718334Speterstatic void 808132718Skangen_insn (rtx insn, int lineno) 80918334Speter{ 810132718Skan struct data *d = xmalloc (sizeof (struct data)); 81190075Sobrien int i; 81218334Speter 81390075Sobrien d->code_number = next_code_number; 81418334Speter d->index_number = next_index_number; 81590075Sobrien d->lineno = lineno; 81618334Speter if (XSTR (insn, 0)[0]) 81718334Speter d->name = XSTR (insn, 0); 81818334Speter else 81918334Speter d->name = 0; 82018334Speter 82118334Speter /* Build up the list in the same order as the insns are seen 82218334Speter in the machine description. */ 82318334Speter d->next = 0; 82490075Sobrien *idata_end = d; 82590075Sobrien idata_end = &d->next; 82618334Speter 82718334Speter max_opno = -1; 82818334Speter num_dups = 0; 82990075Sobrien memset (d->operand, 0, sizeof (d->operand)); 83018334Speter 83118334Speter for (i = 0; i < XVECLEN (insn, 1); i++) 83290075Sobrien scan_operands (d, XVECEXP (insn, 1, i), 0, 0); 83318334Speter 83418334Speter d->n_operands = max_opno + 1; 83518334Speter d->n_dups = num_dups; 83618334Speter 837132718Skan check_constraint_len (); 83890075Sobrien validate_insn_operands (d); 83918334Speter validate_insn_alternatives (d); 84090075Sobrien place_operands (d); 84190075Sobrien process_template (d, XTMPL (insn, 3)); 84218334Speter} 84318334Speter 84418334Speter/* Look at a define_peephole just read. Assign its code number. 84590075Sobrien Record on idata the template and the number of arguments. 84618334Speter If the insn has a hairy output action, output it now. */ 84718334Speter 84818334Speterstatic void 849132718Skangen_peephole (rtx peep, int lineno) 85018334Speter{ 851132718Skan struct data *d = xmalloc (sizeof (struct data)); 85290075Sobrien int i; 85318334Speter 85490075Sobrien d->code_number = next_code_number; 85518334Speter d->index_number = next_index_number; 85690075Sobrien d->lineno = lineno; 85718334Speter d->name = 0; 85818334Speter 85918334Speter /* Build up the list in the same order as the insns are seen 86018334Speter in the machine description. */ 86118334Speter d->next = 0; 86290075Sobrien *idata_end = d; 86390075Sobrien idata_end = &d->next; 86418334Speter 86518334Speter max_opno = -1; 86690075Sobrien num_dups = 0; 86790075Sobrien memset (d->operand, 0, sizeof (d->operand)); 86818334Speter 86990075Sobrien /* Get the number of operands by scanning all the patterns of the 87090075Sobrien peephole optimizer. But ignore all the rest of the information 87190075Sobrien thus obtained. */ 87218334Speter for (i = 0; i < XVECLEN (peep, 0); i++) 87390075Sobrien scan_operands (d, XVECEXP (peep, 0, i), 0, 0); 87418334Speter 87518334Speter d->n_operands = max_opno + 1; 87618334Speter d->n_dups = 0; 87718334Speter 87818334Speter validate_insn_alternatives (d); 87990075Sobrien place_operands (d); 88090075Sobrien process_template (d, XTMPL (peep, 2)); 88118334Speter} 88218334Speter 88318334Speter/* Process a define_expand just read. Assign its code number, 88418334Speter only for the purposes of `insn_gen_function'. */ 88518334Speter 88618334Speterstatic void 887132718Skangen_expand (rtx insn, int lineno) 88818334Speter{ 889132718Skan struct data *d = xmalloc (sizeof (struct data)); 89090075Sobrien int i; 89118334Speter 89290075Sobrien d->code_number = next_code_number; 89318334Speter d->index_number = next_index_number; 89490075Sobrien d->lineno = lineno; 89518334Speter if (XSTR (insn, 0)[0]) 89618334Speter d->name = XSTR (insn, 0); 89718334Speter else 89818334Speter d->name = 0; 89918334Speter 90018334Speter /* Build up the list in the same order as the insns are seen 90118334Speter in the machine description. */ 90218334Speter d->next = 0; 90390075Sobrien *idata_end = d; 90490075Sobrien idata_end = &d->next; 90518334Speter 90618334Speter max_opno = -1; 90718334Speter num_dups = 0; 90890075Sobrien memset (d->operand, 0, sizeof (d->operand)); 90918334Speter 91018334Speter /* Scan the operands to get the specified predicates and modes, 91118334Speter since expand_binop needs to know them. */ 91218334Speter 91318334Speter if (XVEC (insn, 1)) 91418334Speter for (i = 0; i < XVECLEN (insn, 1); i++) 91590075Sobrien scan_operands (d, XVECEXP (insn, 1, i), 0, 0); 91618334Speter 91718334Speter d->n_operands = max_opno + 1; 91818334Speter d->n_dups = num_dups; 91990075Sobrien d->template = 0; 92090075Sobrien d->output_format = INSN_OUTPUT_FORMAT_NONE; 92118334Speter 92218334Speter validate_insn_alternatives (d); 92390075Sobrien place_operands (d); 92418334Speter} 92518334Speter 92618334Speter/* Process a define_split just read. Assign its code number, 92718334Speter only for reasons of consistency and to simplify genrecog. */ 92818334Speter 92918334Speterstatic void 930132718Skangen_split (rtx split, int lineno) 93118334Speter{ 932132718Skan struct data *d = xmalloc (sizeof (struct data)); 93390075Sobrien int i; 93418334Speter 93590075Sobrien d->code_number = next_code_number; 93618334Speter d->index_number = next_index_number; 93790075Sobrien d->lineno = lineno; 93818334Speter d->name = 0; 93918334Speter 94018334Speter /* Build up the list in the same order as the insns are seen 94118334Speter in the machine description. */ 94218334Speter d->next = 0; 94390075Sobrien *idata_end = d; 94490075Sobrien idata_end = &d->next; 94518334Speter 94618334Speter max_opno = -1; 94718334Speter num_dups = 0; 94890075Sobrien memset (d->operand, 0, sizeof (d->operand)); 94918334Speter 95090075Sobrien /* Get the number of operands by scanning all the patterns of the 95190075Sobrien split patterns. But ignore all the rest of the information thus 95290075Sobrien obtained. */ 95318334Speter for (i = 0; i < XVECLEN (split, 0); i++) 95490075Sobrien scan_operands (d, XVECEXP (split, 0, i), 0, 0); 95518334Speter 95618334Speter d->n_operands = max_opno + 1; 95718334Speter d->n_dups = 0; 95818334Speter d->n_alternatives = 0; 95918334Speter d->template = 0; 96090075Sobrien d->output_format = INSN_OUTPUT_FORMAT_NONE; 96118334Speter 96290075Sobrien place_operands (d); 96318334Speter} 96418334Speter 965132718Skanextern int main (int, char **); 96618334Speter 96718334Speterint 968132718Skanmain (int argc, char **argv) 96918334Speter{ 97018334Speter rtx desc; 97118334Speter 97290075Sobrien progname = "genoutput"; 97318334Speter 97418334Speter if (argc <= 1) 97590075Sobrien fatal ("no input file name"); 97618334Speter 97790075Sobrien if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) 97890075Sobrien return (FATAL_EXIT_CODE); 97918334Speter 98018334Speter output_prologue (); 98118334Speter next_code_number = 0; 98218334Speter next_index_number = 0; 98318334Speter 98418334Speter /* Read the machine description. */ 98518334Speter 98618334Speter while (1) 98718334Speter { 98890075Sobrien int line_no; 98990075Sobrien 99090075Sobrien desc = read_md_rtx (&line_no, &next_code_number); 99190075Sobrien if (desc == NULL) 99218334Speter break; 99318334Speter 99418334Speter if (GET_CODE (desc) == DEFINE_INSN) 99590075Sobrien gen_insn (desc, line_no); 99618334Speter if (GET_CODE (desc) == DEFINE_PEEPHOLE) 99790075Sobrien gen_peephole (desc, line_no); 99818334Speter if (GET_CODE (desc) == DEFINE_EXPAND) 99990075Sobrien gen_expand (desc, line_no); 100090075Sobrien if (GET_CODE (desc) == DEFINE_SPLIT 1001132718Skan || GET_CODE (desc) == DEFINE_PEEPHOLE2) 100290075Sobrien gen_split (desc, line_no); 100318334Speter next_index_number++; 100418334Speter } 100518334Speter 100690075Sobrien printf("\n\n"); 100790075Sobrien output_operand_data (); 100890075Sobrien output_insn_data (); 100990075Sobrien output_get_insn_name (); 101018334Speter 101118334Speter fflush (stdout); 101290075Sobrien return (ferror (stdout) != 0 || have_error 101318334Speter ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 101418334Speter} 101518334Speter 101690075Sobrien/* Return the number of occurrences of character C in string S or 101790075Sobrien -1 if S is the null string. */ 101890075Sobrien 101918334Speterstatic int 1020132718Skann_occurrences (int c, const char *s) 102118334Speter{ 102218334Speter int n = 0; 102390075Sobrien 102490075Sobrien if (s == 0 || *s == '\0') 102590075Sobrien return -1; 102690075Sobrien 102718334Speter while (*s) 102818334Speter n += (*s++ == c); 102990075Sobrien 103018334Speter return n; 103118334Speter} 103290075Sobrien 103390075Sobrien/* Remove whitespace in `s' by moving up characters until the end. 103490075Sobrien Return a new string. */ 103590075Sobrien 103690075Sobrienstatic const char * 1037132718Skanstrip_whitespace (const char *s) 103890075Sobrien{ 103990075Sobrien char *p, *q; 104090075Sobrien char ch; 104190075Sobrien 104290075Sobrien if (s == 0) 104390075Sobrien return 0; 104490075Sobrien 104590075Sobrien p = q = xmalloc (strlen (s) + 1); 104690075Sobrien while ((ch = *s++) != '\0') 104790075Sobrien if (! ISSPACE (ch)) 104890075Sobrien *p++ = ch; 104990075Sobrien 105090075Sobrien *p = '\0'; 105190075Sobrien return q; 105290075Sobrien} 1053132718Skan 1054132718Skan/* Verify that DEFAULT_CONSTRAINT_LEN is used properly and not 1055132718Skan tampered with. This isn't bullet-proof, but it should catch 1056132718Skan most genuine mistakes. */ 1057132718Skanstatic void 1058132718Skancheck_constraint_len (void) 1059132718Skan{ 1060132718Skan const char *p; 1061132718Skan int d; 1062132718Skan 1063132718Skan for (p = ",#*+=&%!1234567890"; *p; p++) 1064132718Skan for (d = -9; d < 9; d++) 1065132718Skan if (constraint_len (p, d) != d) 1066132718Skan abort (); 1067132718Skan} 1068132718Skan 1069132718Skanstatic int 1070132718Skanconstraint_len (const char *p, int genoutput_default_constraint_len) 1071132718Skan{ 1072132718Skan /* Check that we still match defaults.h . First we do a generation-time 1073132718Skan check that fails if the value is not the expected one... */ 1074132718Skan if (DEFAULT_CONSTRAINT_LEN (*p, p) != 1) 1075132718Skan abort (); 1076132718Skan /* And now a compile-time check that should give a diagnostic if the 1077132718Skan definition doesn't exactly match. */ 1078132718Skan#define DEFAULT_CONSTRAINT_LEN(C,STR) 1 1079132718Skan /* Now re-define DEFAULT_CONSTRAINT_LEN so that we can verify it is 1080132718Skan being used. */ 1081132718Skan#undef DEFAULT_CONSTRAINT_LEN 1082132718Skan#define DEFAULT_CONSTRAINT_LEN(C,STR) \ 1083132718Skan ((C) != *p || STR != p ? -1 : genoutput_default_constraint_len) 1084132718Skan return CONSTRAINT_LEN (*p, p); 1085132718Skan /* And set it back. */ 1086132718Skan#undef DEFAULT_CONSTRAINT_LEN 1087132718Skan#define DEFAULT_CONSTRAINT_LEN(C,STR) 1 1088132718Skan} 1089