New TableGen backends: llvm-tblgen or a new swift-tblgen?

There are a two things that are particularly hard to express in the macro-based system: lists and optional attributes.

Lists are difficult to make work because {"one", "two"} is multiple preprocessor tokens, ({"one", "two"}) isn't a valid array literal, etc. As a result, I had to create EducationalNotes.def and a separate set of macros to associate a list of filenames with a diagnostic id for the experimental educational notes feature.

Optional attributes are also annoying to work with because they require either defining a whole bunch of macro variants or explicitly specifying their absence. This isn't a problem today because the only optional tags are PointsToFirstBadToken and Fatal, but it does add a useless none specifier to 95% of diagnostics, and a diagnostic can't be both PointsToFirstBadToken and Fatal.

The TableGen format I have in mind looks roughly like this:

def non_nominal_extension:
  Error<"non-nominal type %0 cannot be extended", [Type]>,
  PointsToFirstBadToken,
  EducationalNotes<["nominal-types.md"]>;

Where only the Error supertype is required.

This can potentially extend in the future to support a lot of the improvements discussed here like:

  • user-facing public diagnostic names (PublicName<"...">)
  • an extended diagnostic message format to, for example, surface more detailed type inference info (ExtendedMessage<[Args...], [{ // C++ to generate an extended message }]>)

Moving to TableGen makes it much easier to explore these future directions, even if not all of them end up being implemented.