From: Bill Schmidt <wschm...@linux.ibm.com> This is a slight reworking of the patches posted on June 17. I have made a couple of improvements, but the general arrangement of the patches is the same as before. Two major things to call out:
- I've introduced a uniform set of parsing error codes to make it easier to follow some of the logic when certain conditions occur during parsing. - I reorganized the treatment of built-in stanzas. Before, the stanza conditions were checked prior to initializing entries in the built-in table. Now, all built-ins are initialized, but we check the conditions at expand time to determine whether they should be enabled. This addresses a frequent problem we have with the existing methods, where "#pragma target" doesn't work as expected when changing the target CPU for a single function. As described before, the current built-in support in the rs6000 back end requires at least a master's degree in spelunking to comprehend. It's full of cruft, redundancy, and unused bits of code, and long overdue for a replacement. This is the first part of my project to do that. My intent is to make adding new built-in functions as simple as adding a few lines to a couple of files, and automatically generating as much of the initialization, overload resolution, and expansion logic as possible. This patch series establishes the format of the input files and creates a new program (rs600-gen-builtins) to: * Parse the input files into an internal representation; * Generate a file of #defines (rs6000-vecdefines.h) for eventual inclusion into altivec.h; and * Generate an initialization file to create and initialize tables of built-in functions and overloads. Patches 1, 3-7, and 9-19 contain the logic for rs6000-gen-builtins. Patch 8 provides balanced tree search support for parsing scalability. Patches 2 and 21-27 provide a first cut at the input files. Patch 20 incorporates the new code into the GCC build. Patch 28 adds comments to some existing files that will help during the transition from the previous built-in mechanism. Patch 29 turns on the initialization logic, while leaving GCC's behavior unchanged otherwise. The patch series is constructed so that any prefix set of the patches can be upstreamed without breaking anything. There's still plenty of work left, but I think it will be helpful to get this big chunk of patches upstream to make further progress easier (translation: avoid complex rebases like the one I just went through :-). Following is some additional information about the present and future design that may be of help. The set of patches submitted upstream so far does the relatively straightforward work of reading builtin descriptions from flat files and generating initialization code for builtin and overload tables. It also generates an include file meant to be included in altivec.h, which produces the #defines that map vec_* to __builtin_* functions for external consumption. Data structures are automatically initialized in rs6000_builtins.c: rs6000_autoinit_builtins. Initialized data structures are: - rs6000_gen_builtins: An enumeration of builtin identifiers, such as RS6000_BIF_CPU_SUPPORTS. These names are deliberately different from the existing builtin identifiers so they can co-exist for a while. - rs6000_gen_overloads: An enumeration of overload identifiers, such as RS6000_OVLD_MAX. Again, deliberately different from the old names. Right now I have the two enumerations using nonoverlapping numbers. This is because the two tables were part of one table in the old design, and I haven't yet proven for sure that I can separate them without problems. I think that I can, in which case I will have both enumerations start from zero. - A number of filescope variables representing TREE_TYPEs of functions. These are named <return-type>_ftype_<param1-type>_ ... _<paramN-type> and initialized as tree lists from the prototypes in the input files. The naming scheme for types is described in the code. - rs6000_builtin_info_x: An array indexed by rs6000_gen_builtins containing all the fun stuff for each builtin. The "_x" is because we already have rs6000_builtin_info as the old table, and they need to coexist for a while. - rs6000_overload_info: An array indexed by rs6000_gen_overloads containing all the fun stuff for each overload. - bif_hash: A hash table mapping builtin function names to pointers to their rs6000_builtin_info_x entries. - ovld_hash: A hash table mapping overload names to pointers to their rs6000_overload_info entries. The new initialization code is called from rs6000_init_builtins. Currently this function continues to do its existing initialization work, but also initializes the new tables (and then ignores them). The old initialization code contains a lot of ad hoc hackery to handle different kinds of functions that require extra behavior. The new design removes as much of that as possible, and instead uses syntax in the flat file to generate flags and other information that allows initialization to be done uniformly for all functions. It also means that all initialization is done as a single pass over the builtins, as opposed to the current methods that require multiple passes over all the builtins to find the particular special code required for a single one. Now, it's important to keep both the old and the new initialization code functional at once. There is a static variable new_builtins_are_live that's used to select which tables will be used during compilation. Its value can be set via a macro when building the compiler, or adjusted at runtime under debugger control. The important thing is to ensure that all differences in supported builtins between the old methods and the new ones are expected. We do want some differences, because we are removing a lot of long-deprecated functions. It will be important to test for differences on BE, LE, 64-bit, 32-bit, AIX, and Darwin, as I'm also trying to remove dependences on the "long" integer types wherever possible. We'll see how successful that is. A future patch will update the debug code to print out type signature information for each initialized builtin, to make it easier to compare the old and new functions for type equivalence. So that explains stage 1 of the code, mostly done in the patches I've posted, except as noted above. There are three remaining stages to be completed: - Gimple folding - Overload resolution - Builtin expansion The order above is the order that they take place during compilation. Gimple folding changes will be simple. The only change here is that the builtin names are different, so we'll need to check the different names depending on whether new_builtins_are_live is set or unset. Overload resolution changes should be mostly simple also. The new rs6000_overload_info table will be used instead of the handwritten table in rs6000-call.c. The new table does not have any limits on the number of operands, so all the hackery around unary, binary, ternary, quaternary, etc. will go away. The code for resolving an AltiVec builtin will be required to use the new table, and there is still some special case code in there that will need to be updated for the new naming scheme. But all in all I don't expect a lot of work here, except for adding all the new overload entries into the input file (not yet started). I have been working on the builtin expansion part next, which is the most complicated. rs6000_expand_builtin and its support functions are where all the worst offenses in the code exist. Most of the changes here involve removing as much of the special casing as possible, and replacing it with table-driven logic. In particular, this allows us to get rid of a lot of hand-written code checking for constant arguments that have a restricted set of allowable values. I can't get rid of all the special cases, but I can make them driven by flags in the builtin table instead of the ad hoc checking for specific builtins that occurs today. A lot of this has been written but not yet tested. My current plans are: - Get the first set of patches committed - Add debug code to make it easier to test which builtins (with type signatures) are created using the old and new methods - Test this on all the platforms that matter until I have everything matching - Complete writing the builtin expansion code - Write the Gimple folding and overload resolution pieces - Test and revise until the testsuite passes - Enable the new version of the code as the default - Let it burn in for a while and deal with bug reports - Remove the now-dead code supporting the old methods (around end of stage 3) That's it! Easy peasy. :-) Thanks in advance for reviewing this code, and I welcome comments on the overall design. I'd really like to get these patches upstream soon, as it's becoming clumsy to maintain them out of tree. Thanks! -- Bill Bill Schmidt (29): rs6000: Initial create of rs6000-gen-builtins.c rs6000: Add initial input files rs6000: Add file support and functions for diagnostic support rs6000: Add helper functions for parsing rs6000: Add functions for matching types, part 1 of 3 rs6000: Add functions for matching types, part 2 of 3 rs6000: Add functions for matching types, part 3 of 3 rs6000: Red-black tree implementation for balanced tree search rs6000: Main function with stubs for parsing and output rs6000: Parsing built-in input file, part 1 of 3 rs6000: Parsing built-in input file, part 2 of 3 rs6000: Parsing built-in input file, part 3 of 3 rs6000: Parsing of overload input file rs6000: Build and store function type identifiers rs6000: Write output to the vector definition include file rs6000: Write output to the builtins header file rs6000: Write output to the builtins init file, part 1 of 3 rs6000: Write output to the builtins init file, part 2 of 3 rs6000: Write output to the builtins init file, part 3 of 3 rs6000: Incorporate new builtins code into the build machinery rs6000: Add remaining AltiVec builtins rs6000: Add VSX builtins rs6000: Add available-everywhere and ancient builtins rs6000: Add Power7 builtins rs6000: Add Power8 vector builtins rs6000: Add Power9 builtins rs6000: Add remaining builtins rs6000: Add comments to help with transition rs6000: Call rs6000_autoinit_builtins from rs6000_builtins gcc/config.gcc | 3 +- gcc/config/rs6000/rbtree.c | 233 ++ gcc/config/rs6000/rbtree.h | 51 + gcc/config/rs6000/rs6000-builtin-new.def | 2967 ++++++++++++++++++++++ gcc/config/rs6000/rs6000-builtin.def | 15 + gcc/config/rs6000/rs6000-call.c | 170 ++ gcc/config/rs6000/rs6000-gen-builtins.c | 2660 +++++++++++++++++++ gcc/config/rs6000/rs6000-overload.def | 57 + gcc/config/rs6000/t-rs6000 | 25 +- 9 files changed, 6179 insertions(+), 2 deletions(-) create mode 100644 gcc/config/rs6000/rbtree.c create mode 100644 gcc/config/rs6000/rbtree.h create mode 100644 gcc/config/rs6000/rs6000-builtin-new.def create mode 100644 gcc/config/rs6000/rs6000-gen-builtins.c create mode 100644 gcc/config/rs6000/rs6000-overload.def -- 2.17.1