genconfig.c revision 18334
118334Speter/* Generate from machine description: 218334Speter 318334Speter - some #define configuration flags. 418334Speter Copyright (C) 1987, 1991 Free Software Foundation, Inc. 518334Speter 618334SpeterThis file is part of GNU CC. 718334Speter 818334SpeterGNU CC is free software; you can redistribute it and/or modify 918334Speterit under the terms of the GNU General Public License as published by 1018334Speterthe Free Software Foundation; either version 2, or (at your option) 1118334Speterany later version. 1218334Speter 1318334SpeterGNU CC is distributed in the hope that it will be useful, 1418334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of 1518334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1618334SpeterGNU General Public License for more details. 1718334Speter 1818334SpeterYou should have received a copy of the GNU General Public License 1918334Speteralong with GNU CC; see the file COPYING. If not, write to 2018334Speterthe Free Software Foundation, 59 Temple Place - Suite 330, 2118334SpeterBoston, MA 02111-1307, USA. */ 2218334Speter 2318334Speter 2418334Speter#include <stdio.h> 2518334Speter#include "hconfig.h" 2618334Speter#include "rtl.h" 2718334Speter#include "obstack.h" 2818334Speter 2918334Speterstatic struct obstack obstack; 3018334Speterstruct obstack *rtl_obstack = &obstack; 3118334Speter 3218334Speter#define obstack_chunk_alloc xmalloc 3318334Speter#define obstack_chunk_free free 3418334Speter 3518334Speterextern void free (); 3618334Speterextern rtx read_rtx (); 3718334Speter 3818334Speter/* flags to determine output of machine description dependent #define's. */ 3918334Speterstatic int max_recog_operands; /* Largest operand number seen. */ 4018334Speterstatic int max_dup_operands; /* Largest number of match_dup in any insn. */ 4118334Speterstatic int max_clobbers_per_insn; 4218334Speterstatic int register_constraint_flag; 4318334Speterstatic int have_cc0_flag; 4418334Speterstatic int have_cmove_flag; 4518334Speterstatic int have_lo_sum_flag; 4618334Speter 4718334Speter/* Maximum number of insns seen in a split. */ 4818334Speterstatic int max_insns_per_split = 1; 4918334Speter 5018334Speterstatic int clobbers_seen_this_insn; 5118334Speterstatic int dup_operands_seen_this_insn; 5218334Speter 5318334Speterchar *xmalloc (); 5418334Speterstatic void fatal (); 5518334Spetervoid fancy_abort (); 5618334Speter 5718334Speter/* RECOG_P will be non-zero if this pattern was seen in a context where it will 5818334Speter be used to recognize, rather than just generate an insn. 5918334Speter 6018334Speter NON_PC_SET_SRC will be non-zero if this pattern was seen in a SET_SRC 6118334Speter of a SET whose destination is not (pc). */ 6218334Speter 6318334Speterstatic void 6418334Speterwalk_insn_part (part, recog_p, non_pc_set_src) 6518334Speter rtx part; 6618334Speter int recog_p; 6718334Speter int non_pc_set_src; 6818334Speter{ 6918334Speter register int i, j; 7018334Speter register RTX_CODE code; 7118334Speter register char *format_ptr; 7218334Speter 7318334Speter if (part == 0) 7418334Speter return; 7518334Speter 7618334Speter code = GET_CODE (part); 7718334Speter switch (code) 7818334Speter { 7918334Speter case CLOBBER: 8018334Speter clobbers_seen_this_insn++; 8118334Speter break; 8218334Speter 8318334Speter case MATCH_OPERAND: 8418334Speter if (XINT (part, 0) > max_recog_operands) 8518334Speter max_recog_operands = XINT (part, 0); 8618334Speter if (XSTR (part, 2) && *XSTR (part, 2)) 8718334Speter register_constraint_flag = 1; 8818334Speter return; 8918334Speter 9018334Speter case MATCH_OP_DUP: 9118334Speter case MATCH_PAR_DUP: 9218334Speter ++dup_operands_seen_this_insn; 9318334Speter case MATCH_SCRATCH: 9418334Speter case MATCH_PARALLEL: 9518334Speter case MATCH_OPERATOR: 9618334Speter if (XINT (part, 0) > max_recog_operands) 9718334Speter max_recog_operands = XINT (part, 0); 9818334Speter /* Now scan the rtl's in the vector inside the MATCH_OPERATOR or 9918334Speter MATCH_PARALLEL. */ 10018334Speter break; 10118334Speter 10218334Speter case LABEL_REF: 10318334Speter if (GET_CODE (XEXP (part, 0)) == MATCH_OPERAND) 10418334Speter break; 10518334Speter return; 10618334Speter 10718334Speter case MATCH_DUP: 10818334Speter ++dup_operands_seen_this_insn; 10918334Speter if (XINT (part, 0) > max_recog_operands) 11018334Speter max_recog_operands = XINT (part, 0); 11118334Speter return; 11218334Speter 11318334Speter case CC0: 11418334Speter if (recog_p) 11518334Speter have_cc0_flag = 1; 11618334Speter return; 11718334Speter 11818334Speter case LO_SUM: 11918334Speter if (recog_p) 12018334Speter have_lo_sum_flag = 1; 12118334Speter return; 12218334Speter 12318334Speter case SET: 12418334Speter walk_insn_part (SET_DEST (part), 0, recog_p); 12518334Speter walk_insn_part (SET_SRC (part), recog_p, 12618334Speter GET_CODE (SET_DEST (part)) != PC); 12718334Speter return; 12818334Speter 12918334Speter case IF_THEN_ELSE: 13018334Speter /* Only consider this machine as having a conditional move if the 13118334Speter two arms of the IF_THEN_ELSE are both MATCH_OPERAND. Otherwise, 13218334Speter we have some specific IF_THEN_ELSE construct (like the doz 13318334Speter instruction on the RS/6000) that can't be used in the general 13418334Speter context we want it for. */ 13518334Speter 13618334Speter if (recog_p && non_pc_set_src 13718334Speter && GET_CODE (XEXP (part, 1)) == MATCH_OPERAND 13818334Speter && GET_CODE (XEXP (part, 2)) == MATCH_OPERAND) 13918334Speter have_cmove_flag = 1; 14018334Speter break; 14118334Speter 14218334Speter case REG: case CONST_INT: case SYMBOL_REF: 14318334Speter case PC: 14418334Speter return; 14518334Speter } 14618334Speter 14718334Speter format_ptr = GET_RTX_FORMAT (GET_CODE (part)); 14818334Speter 14918334Speter for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++) 15018334Speter switch (*format_ptr++) 15118334Speter { 15218334Speter case 'e': 15318334Speter case 'u': 15418334Speter walk_insn_part (XEXP (part, i), recog_p, non_pc_set_src); 15518334Speter break; 15618334Speter case 'E': 15718334Speter if (XVEC (part, i) != NULL) 15818334Speter for (j = 0; j < XVECLEN (part, i); j++) 15918334Speter walk_insn_part (XVECEXP (part, i, j), recog_p, non_pc_set_src); 16018334Speter break; 16118334Speter } 16218334Speter} 16318334Speter 16418334Speterstatic void 16518334Spetergen_insn (insn) 16618334Speter rtx insn; 16718334Speter{ 16818334Speter int i; 16918334Speter 17018334Speter /* Walk the insn pattern to gather the #define's status. */ 17118334Speter clobbers_seen_this_insn = 0; 17218334Speter dup_operands_seen_this_insn = 0; 17318334Speter if (XVEC (insn, 1) != 0) 17418334Speter for (i = 0; i < XVECLEN (insn, 1); i++) 17518334Speter walk_insn_part (XVECEXP (insn, 1, i), 1, 0); 17618334Speter 17718334Speter if (clobbers_seen_this_insn > max_clobbers_per_insn) 17818334Speter max_clobbers_per_insn = clobbers_seen_this_insn; 17918334Speter if (dup_operands_seen_this_insn > max_dup_operands) 18018334Speter max_dup_operands = dup_operands_seen_this_insn; 18118334Speter} 18218334Speter 18318334Speter/* Similar but scan a define_expand. */ 18418334Speter 18518334Speterstatic void 18618334Spetergen_expand (insn) 18718334Speter rtx insn; 18818334Speter{ 18918334Speter int i; 19018334Speter 19118334Speter /* Walk the insn pattern to gather the #define's status. */ 19218334Speter 19318334Speter /* Note that we don't bother recording the number of MATCH_DUPs 19418334Speter that occur in a gen_expand, because only reload cares about that. */ 19518334Speter if (XVEC (insn, 1) != 0) 19618334Speter for (i = 0; i < XVECLEN (insn, 1); i++) 19718334Speter { 19818334Speter /* Compute the maximum SETs and CLOBBERS 19918334Speter in any one of the sub-insns; 20018334Speter don't sum across all of them. */ 20118334Speter clobbers_seen_this_insn = 0; 20218334Speter 20318334Speter walk_insn_part (XVECEXP (insn, 1, i), 0, 0); 20418334Speter 20518334Speter if (clobbers_seen_this_insn > max_clobbers_per_insn) 20618334Speter max_clobbers_per_insn = clobbers_seen_this_insn; 20718334Speter } 20818334Speter} 20918334Speter 21018334Speter/* Similar but scan a define_split. */ 21118334Speter 21218334Speterstatic void 21318334Spetergen_split (split) 21418334Speter rtx split; 21518334Speter{ 21618334Speter int i; 21718334Speter 21818334Speter /* Look through the patterns that are matched 21918334Speter to compute the maximum operand number. */ 22018334Speter for (i = 0; i < XVECLEN (split, 0); i++) 22118334Speter walk_insn_part (XVECEXP (split, 0, i), 1, 0); 22218334Speter /* Look at the number of insns this insn could split into. */ 22318334Speter if (XVECLEN (split, 2) > max_insns_per_split) 22418334Speter max_insns_per_split = XVECLEN (split, 2); 22518334Speter} 22618334Speter 22718334Speterstatic void 22818334Spetergen_peephole (peep) 22918334Speter rtx peep; 23018334Speter{ 23118334Speter int i; 23218334Speter 23318334Speter /* Look through the patterns that are matched 23418334Speter to compute the maximum operand number. */ 23518334Speter for (i = 0; i < XVECLEN (peep, 0); i++) 23618334Speter walk_insn_part (XVECEXP (peep, 0, i), 1, 0); 23718334Speter} 23818334Speter 23918334Speterchar * 24018334Speterxmalloc (size) 24118334Speter unsigned size; 24218334Speter{ 24318334Speter register char *val = (char *) malloc (size); 24418334Speter 24518334Speter if (val == 0) 24618334Speter fatal ("virtual memory exhausted"); 24718334Speter 24818334Speter return val; 24918334Speter} 25018334Speter 25118334Speterchar * 25218334Speterxrealloc (ptr, size) 25318334Speter char *ptr; 25418334Speter unsigned size; 25518334Speter{ 25618334Speter char *result = (char *) realloc (ptr, size); 25718334Speter if (!result) 25818334Speter fatal ("virtual memory exhausted"); 25918334Speter return result; 26018334Speter} 26118334Speter 26218334Speterstatic void 26318334Speterfatal (s, a1, a2) 26418334Speter char *s; 26518334Speter{ 26618334Speter fprintf (stderr, "genconfig: "); 26718334Speter fprintf (stderr, s, a1, a2); 26818334Speter fprintf (stderr, "\n"); 26918334Speter exit (FATAL_EXIT_CODE); 27018334Speter} 27118334Speter 27218334Speter/* More 'friendly' abort that prints the line and file. 27318334Speter config.h can #define abort fancy_abort if you like that sort of thing. */ 27418334Speter 27518334Spetervoid 27618334Speterfancy_abort () 27718334Speter{ 27818334Speter fatal ("Internal gcc abort."); 27918334Speter} 28018334Speter 28118334Speterint 28218334Spetermain (argc, argv) 28318334Speter int argc; 28418334Speter char **argv; 28518334Speter{ 28618334Speter rtx desc; 28718334Speter FILE *infile; 28818334Speter register int c; 28918334Speter 29018334Speter obstack_init (rtl_obstack); 29118334Speter 29218334Speter if (argc <= 1) 29318334Speter fatal ("No input file name."); 29418334Speter 29518334Speter infile = fopen (argv[1], "r"); 29618334Speter if (infile == 0) 29718334Speter { 29818334Speter perror (argv[1]); 29918334Speter exit (FATAL_EXIT_CODE); 30018334Speter } 30118334Speter 30218334Speter init_rtl (); 30318334Speter 30418334Speter printf ("/* Generated automatically by the program `genconfig'\n\ 30518334Speterfrom the machine description file `md'. */\n\n"); 30618334Speter 30718334Speter /* Allow at least 10 operands for the sake of asm constructs. */ 30818334Speter max_recog_operands = 9; /* We will add 1 later. */ 30918334Speter max_dup_operands = 1; 31018334Speter 31118334Speter /* Read the machine description. */ 31218334Speter 31318334Speter while (1) 31418334Speter { 31518334Speter c = read_skip_spaces (infile); 31618334Speter if (c == EOF) 31718334Speter break; 31818334Speter ungetc (c, infile); 31918334Speter 32018334Speter desc = read_rtx (infile); 32118334Speter if (GET_CODE (desc) == DEFINE_INSN) 32218334Speter gen_insn (desc); 32318334Speter if (GET_CODE (desc) == DEFINE_EXPAND) 32418334Speter gen_expand (desc); 32518334Speter if (GET_CODE (desc) == DEFINE_SPLIT) 32618334Speter gen_split (desc); 32718334Speter if (GET_CODE (desc) == DEFINE_PEEPHOLE) 32818334Speter gen_peephole (desc); 32918334Speter } 33018334Speter 33118334Speter printf ("\n#define MAX_RECOG_OPERANDS %d\n", max_recog_operands + 1); 33218334Speter 33318334Speter printf ("\n#define MAX_DUP_OPERANDS %d\n", max_dup_operands); 33418334Speter 33518334Speter /* This is conditionally defined, in case the user writes code which emits 33618334Speter more splits than we can readily see (and knows s/he does it). */ 33718334Speter printf ("#ifndef MAX_INSNS_PER_SPLIT\n#define MAX_INSNS_PER_SPLIT %d\n#endif\n", 33818334Speter max_insns_per_split); 33918334Speter 34018334Speter if (register_constraint_flag) 34118334Speter printf ("#define REGISTER_CONSTRAINTS\n"); 34218334Speter 34318334Speter if (have_cc0_flag) 34418334Speter printf ("#define HAVE_cc0\n"); 34518334Speter 34618334Speter if (have_cmove_flag) 34718334Speter printf ("#define HAVE_conditional_move\n"); 34818334Speter 34918334Speter if (have_lo_sum_flag) 35018334Speter printf ("#define HAVE_lo_sum\n"); 35118334Speter 35218334Speter fflush (stdout); 35318334Speter exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); 35418334Speter /* NOTREACHED */ 35518334Speter return 0; 35618334Speter} 357