Commit Graph
4 Commits
Author SHA1 Message Date
Richard Smith 3a9bc01ec4 Flatten two terminator kind macros into one. (#2948)
As requested in #2942.
2023-06-26 15:44:46 -07:00
Richard Smith 4b69264cb1 Add implied return; at end of non-value-returning functions. (#2942)
Add validation that every code block in a function is terminated by a sequence of terminating instructions, and that terminators don't appear anywhere else in code blocks.

This required tracking whether we're in a reachable code block. That's done on the fly when we create a new code block; the new `SemanticsNodeBlockId::Unreachable` is used to represent the case where we're not actually creating a code block because we're in unreachable code.
2023-06-26 15:17:47 -07:00
Chandler CarruthandJon Ross-Perkins a1ad39fa29 Introduce helpers to build enum-wrapping classes. (#2504)
The goal here is to (significantly) reduce the boilerplate needed when defining classes that wrap enums, especially those managed with the `.def`-file style X-macros that are common in the toolchain.

This should also provide both better and more consistent functionality to those classes once ported over to it.

Initially, only `ParserState`, `SemanticsNodeKind`, and `SemanticsBuiltinKind` are ported as these were also the three that JonMeow ported in his original pull/2453 "option 5". This is heavily based on that version of the code.

Goals I was considering that influenced the design:

- Keep the individual enum-wrapping classes as simple and easy to read as possible. Especially important is keeping the `.def` files that are often filled with really important documentation clean and easy to maintain over time.

- Don't rely on computed `#include`s as that is an especially dark corner of the preprocessor and breaks some build systems.

- Have a really good API of the enum-wrapping class, including nice constant names for the values, easy printing, and even easy debugger-callable methods to get the name (as opposed to the integer value).

- Keep the API that users interact with in the base class as clean and easy to read as possible.

- Reduce the boiler plate for each instance of these as much as possible.

- Avoid excessive inline generated code or constants that would result in steady growth in object file sizes and linker effort doing deduplication.

These goals aren't always compatible, so we end up needing to pick a compromise between them when in tension. I think this version is a pretty good compromise.

The original version I started with already pull most of the API into a CRTP-style base class. This version pulls *all* of the common API. This is the main tool for getting consistency and avoiding duplication. However, connecting this base class to the individual enum wrappers is still difficult. Some specific changes here that try to do as much as possible there:

- Use a slightly fancier macro pattern to reduce the boilerplate of defining the raw `enum class` prior to the wrapper class.

- Use a macro to simplify naming the base class.

- Move the name table to a `.cpp` file to avoid every inclusion generating a complete copy of the strings (that the linker has to deduplicate). This is done with some care to sharply reduce the boilerplate needed in that `.cpp` file.

- Sink the name _API_ fully into the CRTP base class. This requires some significant complexity in the implementation, but all of that is hidden behind a single implementation detail macro, and the API itself is simple and readable. This also makes it much more reasonable to test the entire system a single time next to the base class.

This version also moves from constant factory functions to normal constants. This requires two batches -- first a declaration, and then a definition -- but the API result is significantly better and similar to the original option, the macro structure reduces the cost of these. Unfortunately that makes the adoption a bit noisy, but I think its worth the churn.

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2023-01-04 12:33:06 -08:00
Jon Ross-Perkins 1f8508204b Rewrite semantics towards a more pure instruction model (#2320)
This rewrites semantics towards a more pure instruction model, in pursuit of the simple instruction-style output.

I think I can get this approach to type-check as it goes along, but obviously this change doesn't prove that yet. I'm separating it out because it's a large rewrite of the semantics structure, tossing out a lot of what was there before. But I think it does help towards several requests, like setting up a clear path for consolidating duplicate identifiers and making the node style more standardized.

I expect to need to pass multiple args to function calls, that'd probably be storing vectors of args similar to how I'm showing identifiers and integer literals stored.

This removes the semantics namespace because (a) it was getting annoying writing the `::` everywhere, and (b) I think the leaning with Carbon is to avoid namespaces (@chandlerc asked not to put SemanticsIR/SemanticsFactory in a namespace, which is the crux of the issue). But, it's still necessary to avoid name conflicts so I just prefix everything with "Semantics" (still a lot of typing, but no `::`).
2022-10-20 12:50:10 -07:00