1 1.1 mrg /* Generate code to allocate RTL structures. 2 1.1 mrg Copyright (C) 1997-2022 Free Software Foundation, Inc. 3 1.1 mrg 4 1.1 mrg This file is part of GCC. 5 1.1 mrg 6 1.1 mrg GCC is free software; you can redistribute it and/or modify it under 7 1.1 mrg the terms of the GNU General Public License as published by the Free 8 1.1 mrg Software Foundation; either version 3, or (at your option) any later 9 1.1 mrg version. 10 1.1 mrg 11 1.1 mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 1.1 mrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 1.1 mrg for more details. 15 1.1 mrg 16 1.1 mrg You should have received a copy of the GNU General Public License 17 1.1 mrg along with GCC; see the file COPYING3. If not see 18 1.1 mrg <http://www.gnu.org/licenses/>. */ 19 1.1 mrg 20 1.1 mrg 21 1.1 mrg #include "bconfig.h" 22 1.1 mrg #include "system.h" 23 1.1 mrg 24 1.1 mrg struct rtx_definition 25 1.1 mrg { 26 1.1 mrg const char *const enumname, *const name, *const format; 27 1.1 mrg }; 28 1.1 mrg 29 1.1 mrg /* rtl.def needs CONST_DOUBLE_FORMAT, but we don't care what 30 1.1 mrg CONST_DOUBLE_FORMAT is because we're not going to be generating 31 1.1 mrg anything for CONST_DOUBLE anyway. */ 32 1.1 mrg #define CONST_DOUBLE_FORMAT "" 33 1.1 mrg 34 1.1 mrg #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) { #ENUM, NAME, FORMAT }, 35 1.1 mrg 36 1.1 mrg static const struct rtx_definition defs[] = 37 1.1 mrg { 38 1.1 mrg #include "rtl.def" /* rtl expressions are documented here */ 39 1.1 mrg }; 40 1.1 mrg #define NUM_RTX_CODE ARRAY_SIZE (defs) 41 1.1 mrg 42 1.1 mrg static const char *formats[NUM_RTX_CODE]; 43 1.1 mrg 44 1.1 mrg /* Decode a format letter into a C type string. */ 46 1.1 mrg 47 1.1 mrg static const char * 48 1.1 mrg type_from_format (int c) 49 1.1 mrg { 50 1.1 mrg switch (c) 51 1.1 mrg { 52 1.1 mrg case 'i': 53 1.1 mrg return "int "; 54 1.1 mrg 55 1.1 mrg case 'w': 56 1.1 mrg return "HOST_WIDE_INT "; 57 1.1 mrg 58 1.1 mrg case 'p': 59 1.1 mrg return "poly_uint16 "; 60 1.1 mrg 61 1.1 mrg case 's': 62 1.1 mrg return "const char *"; 63 1.1 mrg 64 1.1 mrg case 'e': case 'u': 65 1.1 mrg return "rtx "; 66 1.1 mrg 67 1.1 mrg case 'E': 68 1.1 mrg return "rtvec "; 69 1.1 mrg case 't': 70 1.1 mrg return "tree "; 71 1.1 mrg case 'B': 72 1.1 mrg return "basic_block "; 73 1.1 mrg default: 74 1.1 mrg gcc_unreachable (); 75 1.1 mrg } 76 1.1 mrg } 77 1.1 mrg 78 1.1 mrg /* Decode a format letter into the proper accessor function. */ 79 1.1 mrg 80 1.1 mrg static const char * 81 1.1 mrg accessor_from_format (int c) 82 1.1 mrg { 83 1.1 mrg switch (c) 84 1.1 mrg { 85 1.1 mrg case 'i': 86 1.1 mrg return "XINT"; 87 1.1 mrg 88 1.1 mrg case 'w': 89 1.1 mrg return "XWINT"; 90 1.1 mrg 91 1.1 mrg case 's': 92 1.1 mrg return "XSTR"; 93 1.1 mrg 94 1.1 mrg case 'e': case 'u': 95 1.1 mrg return "XEXP"; 96 1.1 mrg 97 1.1 mrg case 'E': 98 1.1 mrg return "XVEC"; 99 1.1 mrg 100 1.1 mrg case 't': 101 1.1 mrg return "XTREE"; 102 1.1 mrg 103 1.1 mrg case 'B': 104 1.1 mrg return "XBBDEF"; 105 1.1 mrg 106 1.1 mrg default: 107 1.1 mrg gcc_unreachable (); 108 1.1 mrg } 109 1.1 mrg } 110 1.1 mrg 111 1.1 mrg /* Return nonzero if we should ignore FMT, an RTL format, when making 112 1.1 mrg the list of formats we write routines to create. */ 113 1.1 mrg 114 1.1 mrg static int 115 1.1 mrg special_format (const char *fmt) 116 1.1 mrg { 117 1.1 mrg return (strchr (fmt, '*') != 0 118 1.1 mrg || strchr (fmt, 'V') != 0 119 1.1 mrg || strchr (fmt, 'S') != 0 120 1.1 mrg || strchr (fmt, 'n') != 0 121 1.1 mrg || strchr (fmt, 'r') != 0); 122 1.1 mrg } 123 1.1 mrg 124 1.1 mrg /* Return true if CODE always has VOIDmode. */ 125 1.1 mrg 126 1.1 mrg static inline bool 127 1.1 mrg always_void_p (int idx) 128 1.1 mrg { 129 1.1 mrg return strcmp (defs[idx].enumname, "SET") == 0; 130 1.1 mrg } 131 1.1 mrg 132 1.1 mrg /* Return nonzero if the RTL code given by index IDX is one that we should 133 1.1 mrg generate a gen_rtx_raw_FOO macro for, not gen_rtx_FOO (because gen_rtx_FOO 134 1.1 mrg is a wrapper in emit-rtl.cc). */ 135 1.1 mrg 136 1.1 mrg static int 137 1.1 mrg special_rtx (int idx) 138 1.1 mrg { 139 1.1 mrg return (strcmp (defs[idx].enumname, "EXPR_LIST") == 0 140 1.1 mrg || strcmp (defs[idx].enumname, "INSN_LIST") == 0 141 1.1 mrg || strcmp (defs[idx].enumname, "INSN") == 0 142 1.1 mrg || strcmp (defs[idx].enumname, "CONST_INT") == 0 143 1.1 mrg || strcmp (defs[idx].enumname, "REG") == 0 144 1.1 mrg || strcmp (defs[idx].enumname, "SUBREG") == 0 145 1.1 mrg || strcmp (defs[idx].enumname, "MEM") == 0 146 1.1 mrg || strcmp (defs[idx].enumname, "PC") == 0 147 1.1 mrg || strcmp (defs[idx].enumname, "RETURN") == 0 148 1.1 mrg || strcmp (defs[idx].enumname, "SIMPLE_RETURN") == 0 149 1.1 mrg || strcmp (defs[idx].enumname, "CONST_VECTOR") == 0); 150 1.1 mrg } 151 1.1 mrg 152 1.1 mrg /* Return nonzero if the RTL code given by index IDX is one that we should 153 1.1 mrg generate no macro for at all (because gen_rtx_FOO is never used or 154 1.1 mrg cannot have the obvious interface). */ 155 1.1 mrg 156 1.1 mrg static int 157 1.1 mrg excluded_rtx (int idx) 158 1.1 mrg { 159 1.1 mrg return (strcmp (defs[idx].enumname, "VAR_LOCATION") == 0 160 1.1 mrg || strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0 161 1.1 mrg || strcmp (defs[idx].enumname, "CONST_WIDE_INT") == 0 162 1.1 mrg || strcmp (defs[idx].enumname, "CONST_POLY_INT") == 0 163 1.1 mrg || strcmp (defs[idx].enumname, "CONST_FIXED") == 0); 164 1.1 mrg } 165 1.1 mrg 166 1.1 mrg /* Place a list of all format specifiers we use into the array FORMAT. */ 167 1.1 mrg 168 1.1 mrg static void 169 1.1 mrg find_formats (void) 170 1.1 mrg { 171 1.1 mrg unsigned int i; 172 1.1 mrg 173 1.1 mrg for (i = 0; i < NUM_RTX_CODE; i++) 174 1.1 mrg { 175 1.1 mrg const char **f; 176 1.1 mrg 177 1.1 mrg if (special_format (defs[i].format)) 178 1.1 mrg continue; 179 1.1 mrg 180 1.1 mrg for (f = formats; *f; f++) 181 1.1 mrg if (! strcmp (*f, defs[i].format)) 182 1.1 mrg break; 183 1.1 mrg 184 1.1 mrg if (*f == 0) 185 1.1 mrg *f = defs[i].format; 186 1.1 mrg } 187 1.1 mrg } 188 1.1 mrg 189 1.1 mrg 190 1.1 mrg /* Generate macros to generate RTL of code IDX using the functions we 191 1.1 mrg write. */ 192 1.1 mrg 193 1.1 mrg static void 194 1.1 mrg genmacro (int idx) 195 1.1 mrg { 196 1.1 mrg const char *p; 197 1.1 mrg const char *sep = ""; 198 1.1 mrg int i; 199 1.1 mrg 200 1.1 mrg /* We write a macro that defines gen_rtx_RTLCODE to be an equivalent to 201 1.1 mrg gen_rtx_fmt_FORMAT where FORMAT is the RTX_FORMAT of RTLCODE. */ 202 1.1 mrg 203 1.1 mrg if (excluded_rtx (idx)) 204 1.1 mrg /* Don't define a macro for this code. */ 205 1.1 mrg return; 206 1.1 mrg 207 1.1 mrg bool has_mode_p = !always_void_p (idx); 208 1.1 mrg printf ("#define gen_rtx_%s%s(", 209 1.1 mrg special_rtx (idx) ? "raw_" : "", defs[idx].enumname); 210 1.1 mrg if (has_mode_p) 211 1.1 mrg { 212 1.1 mrg printf ("MODE"); 213 1.1 mrg sep = ", "; 214 1.1 mrg } 215 1.1 mrg 216 1.1 mrg for (p = defs[idx].format, i = 0; *p != 0; p++) 217 1.1 mrg if (*p != '0') 218 1.1 mrg { 219 1.1 mrg printf ("%sARG%d", sep, i++); 220 1.1 mrg sep = ", "; 221 1.1 mrg } 222 1.1 mrg 223 1.1 mrg printf (") \\\n gen_rtx_fmt_%s (%s, %s", 224 1.1 mrg defs[idx].format, defs[idx].enumname, 225 1.1 mrg has_mode_p ? "(MODE)" : "VOIDmode"); 226 1.1 mrg 227 1.1 mrg for (p = defs[idx].format, i = 0; *p != 0; p++) 228 1.1 mrg if (*p != '0') 229 1.1 mrg printf (", (ARG%d)", i++); 230 1.1 mrg 231 1.1 mrg puts (")"); 232 1.1 mrg } 233 1.1 mrg 234 1.1 mrg /* Generate the code for functions to generate RTL whose format is FORMAT. */ 235 1.1 mrg 236 1.1 mrg static void 237 1.1 mrg gendef (const char *format) 238 1.1 mrg { 239 1.1 mrg const char *p; 240 1.1 mrg int i, j; 241 1.1 mrg 242 1.1 mrg /* Write the definition of the init function name and the types 243 1.1 mrg of the arguments. */ 244 1.1 mrg 245 1.1 mrg puts ("static inline rtx"); 246 1.1 mrg printf ("init_rtx_fmt_%s (rtx rt, machine_mode mode", format); 247 1.1 mrg for (p = format, i = 0; *p != 0; p++) 248 1.1 mrg if (*p != '0') 249 1.1 mrg printf (",\n\t%sarg%d", type_from_format (*p), i++); 250 1.1 mrg puts (")"); 251 1.1 mrg 252 1.1 mrg /* Now write out the body of the init function itself. */ 253 1.1 mrg puts ("{"); 254 1.1 mrg puts (" PUT_MODE_RAW (rt, mode);"); 255 1.1 mrg 256 1.1 mrg for (p = format, i = j = 0; *p ; ++p, ++i) 257 1.1 mrg if (*p == '0') 258 1.1 mrg printf (" X0EXP (rt, %d) = NULL_RTX;\n", i); 259 1.1 mrg else if (*p == 'p') 260 1.1 mrg printf (" SUBREG_BYTE (rt) = arg%d;\n", j++); 261 1.1 mrg else 262 1.1 mrg printf (" %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++); 263 1.1 mrg 264 1.1 mrg puts (" return rt;\n}\n"); 265 1.1 mrg 266 1.1 mrg /* Write the definition of the gen function name and the types 267 1.1 mrg of the arguments. */ 268 1.1 mrg 269 1.1 mrg puts ("static inline rtx"); 270 1.1 mrg printf ("gen_rtx_fmt_%s_stat (RTX_CODE code, machine_mode mode", format); 271 1.1 mrg for (p = format, i = 0; *p != 0; p++) 272 1.1 mrg if (*p != '0') 273 1.1 mrg printf (",\n\t%sarg%d", type_from_format (*p), i++); 274 1.1 mrg puts (" MEM_STAT_DECL)"); 275 1.1 mrg 276 1.1 mrg /* Now write out the body of the function itself, which allocates 277 1.1 mrg the memory and initializes it. */ 278 1.1 mrg puts ("{"); 279 1.1 mrg puts (" rtx rt;\n"); 280 1.1 mrg 281 1.1 mrg puts (" rt = rtx_alloc (code PASS_MEM_STAT);"); 282 1.1 mrg printf (" return init_rtx_fmt_%s (rt, mode", format); 283 1.1 mrg for (p = format, i = 0; *p != 0; p++) 284 1.1 mrg if (*p != '0') 285 1.1 mrg printf (", arg%d", i++); 286 1.1 mrg puts (");\n}\n"); 287 1.1 mrg 288 1.1 mrg /* Write the definition of gen macro. */ 289 1.1 mrg 290 1.1 mrg printf ("#define gen_rtx_fmt_%s(c, m", format); 291 1.1 mrg for (p = format, i = 0; *p != 0; p++) 292 1.1 mrg if (*p != '0') 293 1.1 mrg printf (", arg%d", i++); 294 1.1 mrg printf (") \\\n gen_rtx_fmt_%s_stat ((c), (m)", format); 295 1.1 mrg for (p = format, i = 0; *p != 0; p++) 296 1.1 mrg if (*p != '0') 297 1.1 mrg printf (", (arg%d)", i++); 298 1.1 mrg printf (" MEM_STAT_INFO)\n\n"); 299 1.1 mrg 300 1.1 mrg /* Write the definition of alloca macro. */ 301 1.1 mrg 302 1.1 mrg printf ("#define alloca_rtx_fmt_%s(c, m", format); 303 1.1 mrg for (p = format, i = 0; *p != 0; p++) 304 1.1 mrg if (*p != '0') 305 1.1 mrg printf (", arg%d", i++); 306 1.1 mrg printf (") \\\n init_rtx_fmt_%s (rtx_alloca ((c)), (m)", format); 307 1.1 mrg for (p = format, i = 0; *p != 0; p++) 308 1.1 mrg if (*p != '0') 309 1.1 mrg printf (", (arg%d)", i++); 310 1.1 mrg printf (")\n\n"); 311 1.1 mrg } 312 1.1 mrg 313 1.1 mrg /* Generate the documentation header for files we write. */ 314 1.1 mrg 315 1.1 mrg static void 316 1.1 mrg genlegend (void) 317 1.1 mrg { 318 1.1 mrg puts ("/* Generated automatically by gengenrtl from rtl.def. */\n"); 319 1.1 mrg } 320 1.1 mrg 321 1.1 mrg /* Generate the text of the header file we make, genrtl.h. */ 322 1.1 mrg 323 1.1 mrg static void 324 1.1 mrg genheader (void) 325 1.1 mrg { 326 1.1 mrg unsigned int i; 327 1.1 mrg const char **fmt; 328 1.1 mrg 329 1.1 mrg puts ("#ifndef GCC_GENRTL_H"); 330 1.1 mrg puts ("#define GCC_GENRTL_H\n"); 331 1.1 mrg puts ("#include \"statistics.h\"\n"); 332 1.1 mrg 333 1.1 mrg for (fmt = formats; *fmt; ++fmt) 334 1.1 mrg gendef (*fmt); 335 1.1 mrg 336 1.1 mrg putchar ('\n'); 337 1.1 mrg 338 1.1 mrg for (i = 0; i < NUM_RTX_CODE; i++) 339 1.1 mrg if (! special_format (defs[i].format)) 340 1.1 mrg genmacro (i); 341 1.1 mrg 342 1.1 mrg puts ("\n#endif /* GCC_GENRTL_H */"); 343 1.1 mrg } 344 1.1 mrg 345 1.1 mrg /* This is the main program. */ 346 1.1 mrg 347 1.1 mrg int 348 1.1 mrg main (void) 349 1.1 mrg { 350 1.1 mrg find_formats (); 351 1.1 mrg genlegend (); 352 1.1 mrg 353 1.1 mrg genheader (); 354 1.1 mrg 355 1.1 mrg if (ferror (stdout) || fflush (stdout) || fclose (stdout)) 356 1.1 mrg return FATAL_EXIT_CODE; 357 1.1 mrg 358 1.1 mrg return SUCCESS_EXIT_CODE; 359 } 360