📄 genemit.c
字号:
/* Generate code from machine description to emit insns as rtl. Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#include <stdio.h>#include "hconfig.h"#include "rtl.h"#include "obstack.h"static struct obstack obstack;struct obstack *rtl_obstack = &obstack;#define obstack_chunk_alloc xmalloc#define obstack_chunk_free freeextern void free ();extern rtx read_rtx ();char *xmalloc ();static void fatal ();void fancy_abort ();static int max_opno;static int max_dup_opno;static int register_constraints;static int insn_code_number;static int insn_index_number;/* Data structure for recording the patterns of insns that have CLOBBERs. We use this to output a function that adds these CLOBBERs to a previously-allocated PARALLEL expression. */struct clobber_pat{ struct clobber_ent *insns; rtx pattern; int first_clobber; struct clobber_pat *next;} *clobber_list;/* Records one insn that uses the clobber list. */struct clobber_ent{ int code_number; /* Counts only insns. */ struct clobber_ent *next;};static voidmax_operand_1 (x) rtx x;{ register RTX_CODE code; register int i; register int len; register char *fmt; if (x == 0) return; code = GET_CODE (x); if (code == MATCH_OPERAND && XSTR (x, 2) != 0 && *XSTR (x, 2) != '\0') register_constraints = 1; if (code == MATCH_SCRATCH && XSTR (x, 1) != 0 && *XSTR (x, 1) != '\0') register_constraints = 1; if (code == MATCH_OPERAND || code == MATCH_OPERATOR || code == MATCH_PARALLEL) max_opno = MAX (max_opno, XINT (x, 0)); if (code == MATCH_DUP || code == MATCH_OP_DUP || code == MATCH_PAR_DUP) max_dup_opno = MAX (max_dup_opno, XINT (x, 0)); fmt = GET_RTX_FORMAT (code); len = GET_RTX_LENGTH (code); for (i = 0; i < len; i++) { if (fmt[i] == 'e' || fmt[i] == 'u') max_operand_1 (XEXP (x, i)); else if (fmt[i] == 'E') { int j; for (j = 0; j < XVECLEN (x, i); j++) max_operand_1 (XVECEXP (x, i, j)); } }}static intmax_operand_vec (insn, arg) rtx insn; int arg;{ register int len = XVECLEN (insn, arg); register int i; max_opno = -1; max_dup_opno = -1; for (i = 0; i < len; i++) max_operand_1 (XVECEXP (insn, arg, i)); return max_opno + 1;}static voidprint_code (code) RTX_CODE code;{ register char *p1; for (p1 = GET_RTX_NAME (code); *p1; p1++) { if (*p1 >= 'a' && *p1 <= 'z') putchar (*p1 + 'A' - 'a'); else putchar (*p1); }}/* Print a C expression to construct an RTX just like X, substituting any operand references appearing within. */static voidgen_exp (x) rtx x;{ register RTX_CODE code; register int i; register int len; register char *fmt; if (x == 0) { printf ("NULL_RTX"); return; } code = GET_CODE (x); switch (code) { case MATCH_OPERAND: case MATCH_DUP: printf ("operand%d", XINT (x, 0)); return; case MATCH_OP_DUP: printf ("gen_rtx (GET_CODE (operand%d), GET_MODE (operand%d)", XINT (x, 0), XINT (x, 0)); for (i = 0; i < XVECLEN (x, 1); i++) { printf (",\n\t\t"); gen_exp (XVECEXP (x, 1, i)); } printf (")"); return; case MATCH_OPERATOR: printf ("gen_rtx (GET_CODE (operand%d)", XINT (x, 0)); printf (", %smode", GET_MODE_NAME (GET_MODE (x))); for (i = 0; i < XVECLEN (x, 2); i++) { printf (",\n\t\t"); gen_exp (XVECEXP (x, 2, i)); } printf (")"); return; case MATCH_PARALLEL: case MATCH_PAR_DUP: printf ("operand%d", XINT (x, 0)); return; case MATCH_SCRATCH: printf ("gen_rtx (SCRATCH, %smode, 0)", GET_MODE_NAME (GET_MODE (x))); return; case ADDRESS: fatal ("ADDRESS expression code used in named instruction pattern"); case PC: printf ("pc_rtx"); return; case CC0: printf ("cc0_rtx"); return; case CONST_INT: if (INTVAL (x) == 0) printf ("const0_rtx"); else if (INTVAL (x) == 1) printf ("const1_rtx"); else if (INTVAL (x) == -1) printf ("constm1_rtx"); else if (INTVAL (x) == STORE_FLAG_VALUE) printf ("const_true_rtx"); else printf (#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT "GEN_INT (%d)",#else "GEN_INT (%ld)",#endif INTVAL (x)); return; case CONST_DOUBLE: /* These shouldn't be written in MD files. Instead, the appropriate routines in varasm.c should be called. */ abort (); } printf ("gen_rtx ("); print_code (code); printf (", %smode", GET_MODE_NAME (GET_MODE (x))); fmt = GET_RTX_FORMAT (code); len = GET_RTX_LENGTH (code); for (i = 0; i < len; i++) { if (fmt[i] == '0') break; printf (", "); if (fmt[i] == 'e' || fmt[i] == 'u') gen_exp (XEXP (x, i)); else if (fmt[i] == 'i') printf ("%u", XINT (x, i)); else if (fmt[i] == 's') printf ("\"%s\"", XSTR (x, i)); else if (fmt[i] == 'E') { int j; printf ("gen_rtvec (%d", XVECLEN (x, i)); for (j = 0; j < XVECLEN (x, i); j++) { printf (",\n\t\t"); gen_exp (XVECEXP (x, i, j)); } printf (")"); } else abort (); } printf (")");} /* Generate the `gen_...' function for a DEFINE_INSN. */static voidgen_insn (insn) rtx insn;{ int operands; register int i; /* See if the pattern for this insn ends with a group of CLOBBERs of (hard) registers or MATCH_SCRATCHes. If so, store away the information for later. */ if (XVEC (insn, 1)) { for (i = XVECLEN (insn, 1) - 1; i > 0; i--) if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER || (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != REG && GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH)) break; if (i != XVECLEN (insn, 1) - 1) { register struct clobber_pat *p; register struct clobber_ent *link = (struct clobber_ent *) xmalloc (sizeof (struct clobber_ent)); register int j; link->code_number = insn_code_number; /* See if any previous CLOBBER_LIST entry is the same as this one. */ for (p = clobber_list; p; p = p->next) { if (p->first_clobber != i + 1 || XVECLEN (p->pattern, 1) != XVECLEN (insn, 1)) continue; for (j = i + 1; j < XVECLEN (insn, 1); j++) { rtx old = XEXP (XVECEXP (p->pattern, 1, j), 0); rtx new = XEXP (XVECEXP (insn, 1, j), 0); /* OLD and NEW are the same if both are to be a SCRATCH of the same mode, or if both are registers of the same mode and number. */ if (! (GET_MODE (old) == GET_MODE (new) && ((GET_CODE (old) == MATCH_SCRATCH && GET_CODE (new) == MATCH_SCRATCH) || (GET_CODE (old) == REG && GET_CODE (new) == REG && REGNO (old) == REGNO (new))))) break; } if (j == XVECLEN (insn, 1)) break; } if (p == 0) { p = (struct clobber_pat *) xmalloc (sizeof (struct clobber_pat)); p->insns = 0; p->pattern = insn; p->first_clobber = i + 1; p->next = clobber_list; clobber_list = p; } link->next = p->insns; p->insns = link; } } /* Don't mention instructions whose names are the null string. They are in the machine description just to be recognized. */ if (strlen (XSTR (insn, 0)) == 0) return; /* Find out how many operands this function has, and also whether any of them have register constraints. */ register_constraints = 0; operands = max_operand_vec (insn, 1); if (max_dup_opno >= operands) fatal ("match_dup operand number has no match_operand"); /* Output the function name and argument declarations. */ printf ("rtx\ngen_%s (", XSTR (insn, 0)); for (i = 0; i < operands; i++) printf (i ? ", operand%d" : "operand%d", i); printf (")\n"); for (i = 0; i < operands; i++) printf (" rtx operand%d;\n", i); printf ("{\n"); /* Output code to construct and return the rtl for the instruction body */ if (XVECLEN (insn, 1) == 1) { printf (" return "); gen_exp (XVECEXP (insn, 1, 0)); printf (";\n}\n\n"); } else { printf (" return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (%d", XVECLEN (insn, 1)); for (i = 0; i < XVECLEN (insn, 1); i++) { printf (",\n\t\t"); gen_exp (XVECEXP (insn, 1, i)); } printf ("));\n}\n\n"); }}/* Generate the `gen_...' function for a DEFINE_EXPAND. */static voidgen_expand (expand) rtx expand;{ int operands; register int i; if (strlen (XSTR (expand, 0)) == 0) fatal ("define_expand lacks a name"); if (XVEC (expand, 1) == 0) fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0)); /* Find out how many operands this function has, and also whether any of them have register constraints. */ register_constraints = 0; operands = max_operand_vec (expand, 1); /* Output the function name and argument declarations. */ printf ("rtx\ngen_%s (", XSTR (expand, 0));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -