[patch] Prototype/proof-of-concept for DWARF type units

This isn’t a realistic/viable implementation, just a hacked up “can I make it produce the right output” kind of thing, but while I hammer out a few more details (like fixing MC to allow multiple sections with the same name but different comdat groups) I figured I’d throw it out there to have a bit of a chat about it.

I’ve tested simple cases of a single type and they seem to work OK. Multiple types from the same translation unit won’t work at the moment due to the MC issue.

The practical details are fairly simple. When CompileUnit goes to create a type, first it hands it off to DwarfDebug to decide whether it’s going to be in a type unit. If it is, DwarfDebug spins up a new CompileUnit that’s really a type unit, emits the type into that unit (creating all dependent types and other paraphernalia), attaches the signature (using the ODR hash as a stand-in for now) and offset to the CompileUnit and the signature to the DIE the original CompileUnit provided (along with any other DIEs that needed that signature and were discovered along the way).

Then emit it as normal - with a few special cases to add the necessary extra headers, offsets, etc.

A realistic implementation probably involves moving unit header handling down into CompileUnit, extracting most of the common functionality into a Unit type and having CompileUnit and TypeUnit types to handle the header differences. Sound about right?

I haven’t got to looking at how this is meant to (or currently does) interact with fission, but I suspect it might be pretty close ‘for free’.

type_units.diff (24 KB)

Hi Dave,

This isn't a realistic/viable implementation, just a hacked up "can I make
it produce the right output" kind of thing, but while I hammer out a few
more details (like fixing MC to allow multiple sections with the same name
but different comdat groups) I figured I'd throw it out there to have a bit
of a chat about it.

This is definitely a good start.

I've tested simple cases of a single type and they seem to work OK. Multiple
types from the same translation unit won't work at the moment due to the MC
issue.

OK.

The practical details are fairly simple. When CompileUnit goes to create a
type, first it hands it off to DwarfDebug to decide whether it's going to be
in a type unit. If it is, DwarfDebug spins up a new CompileUnit that's
really a type unit, emits the type into that unit (creating all dependent
types and other paraphernalia), attaches the signature (using the ODR hash
as a stand-in for now) and offset to the CompileUnit and the signature to
the DIE the original CompileUnit provided (along with any other DIEs that
needed that signature and were discovered along the way).

Then emit it as normal - with a few special cases to add the necessary extra
headers, offsets, etc.

This is definitely how I was thinking this would work, yes.

A realistic implementation probably involves moving unit header handling
down into CompileUnit, extracting most of the common functionality into a
Unit type and having CompileUnit and TypeUnit types to handle the header
differences. Sound about right?

Sounds good to me here.

I haven't got to looking at how this is meant to (or currently does)
interact with fission, but I suspect it might be pretty close 'for free'.

It should be orthogonal yes.

Few comments on random aspects of the patch:

@@ -789,7 +797,7 @@ DIE *CompileUnit::getOrCreateTypeDIE(const MDNode *TyNode) {
     return TyDIE;

   // Create new type.
- TyDIE = new DIE(dwarf::DW_TAG_base_type);
+ TyDIE = new DIE(Ty.getTag());
   insertDIE(Ty, TyDIE);
   if (Ty.isBasicType())
     constructTypeDIE(*TyDIE, DIBasicType(Ty));
@@ -911,13 +919,10 @@ void CompileUnit::constructTypeDIE(DIE &Buffer,
DIBasicType BTy) {
   if (!Name.empty())
     addString(&Buffer, dwarf::DW_AT_name, Name);

- if (BTy.getTag() == dwarf::DW_TAG_unspecified_type) {
- Buffer.setTag(dwarf::DW_TAG_unspecified_type);
- // An unspecified type only has a name attribute.
+ // An unspecified type only has a name attribute.
+ if (BTy.getTag() == dwarf::DW_TAG_unspecified_type)
     return;
- }

- Buffer.setTag(dwarf::DW_TAG_base_type);
   addUInt(&Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
           BTy.getEncoding());

Probably a fine separate cleanup.

@@ -930,12 +935,11 @@ void CompileUnit::constructTypeDIE(DIE &Buffer,
DIDerivedType DTy) {
   // Get core information.
   StringRef Name = DTy.getName();
   uint64_t Size = DTy.getSizeInBits() >> 3;
- uint16_t Tag = DTy.getTag();

   // FIXME - Workaround for templates.
- if (Tag == dwarf::DW_TAG_inheritance) Tag = dwarf::DW_TAG_reference_type;