DWARF Type Units and single definition types

@adrian.prantl @pogo59 (not sure if this tagging thing works - there’s no dropdown list, etc in Discourse)

So… we use the identifier attribute of DICompositeType for a couple of things:

  1. To deduplicate types (including type declarations and definitions) during IR linking
  2. To determine if a type should be placed in a DWARF type unit (& then use the identifier as the key for that type unit)

Type units have some overhead in DWARF encoding, so it’s beneficial to avoid using a type unit if a type is only going to be emitted once.

This comes up in some cases and I implemented it a few years ago - so, for instance, if a type is using vtable-based homing, and the vtable has strong linkage (because the key function has strong linkage). But the way I implemented it is sub-optimal - I did it by dropping the identifier from these types, so they wouldn’t get a type unit.

This had the unintended side effect of meaning decls and defs of such a type aren’t deduplicated/merged (so in LTO you end up with a decl in one CU and a def in another, instead of just the def and cross-cu references to refer to it).

This came up because I wanted/needed to push this direction further (for simplified template names - for… Reasons) - for any type definition that refers to an internal type (eg: namespace { struct t1 { }; } struct t2 { t1 v1; }; (you could imagine this coming up with a pimpl idiom - where t2 is the pimpl implementation, but isn’t itself file-local). Such a type can also only be defined in one translation unit, so we shouldn’t put it in a type unit - to save space.

But I don’t want to exacerbate the exist LTO problem.

So - do we add a flag to DICompositeType’s flags (these are part of the generic metadata flags, we’re running a bit short on them - should we split out a separate DICompositeType flags, the same way we did for DISubprogram flags?) to indicate if the type should be placed in a TU? (with this flag we could then remove command line flag support for type units - properly respecting per-file -fdebug-types-section in LTO (so it works more like non-LTO, where the compile-time flag is respected, even then codegen is done at link time instead), which is a bonus)

Aside: I’ve never liked the name-based deduplication, it’s missing an opportunity to detect ODR violations.

Naively it looks like some DIFlags could be moved to DICompositeType and win back a few bits. Actually it looks like more could be moved to DISubprogram, I see 3-4 that look specific to subprograms. Would have to look at how they’re actually used of course. I’m okay with it, but Apple is likely way more affected so I’d leave it up to Adrian.