This is an archive of the discontinued LLVM Phabricator instance.

[RFC] Handle qualified unnamed types in CodeView printer
ClosedPublic

Authored by smeenai on Feb 26 2018, 7:54 PM.

Details

Summary

When attempting to compile the following Objective-C++ code with
CodeView debug info:

void (^b)(void) = []() {};

The generated debug metadata contains a structure like the following:

!43 = !DICompositeType(tag: DW_TAG_structure_type, name: "__block_literal_1", scope: !6, file: !6, line: 1, size: 168, elements: !44)
!44 = !{!45, !46, !47, !48, !49, !52}
...
!52 = !DIDerivedType(tag: DW_TAG_member, scope: !6, file: !6, line: 1, baseType: !53, size: 8, offset: 160, flags: DIFlagPublic)
!53 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !54)
!54 = !DICompositeType(tag: DW_TAG_class_type, file: !6, line: 1, flags: DIFlagFwdDecl)

Note that the member node (!52) is unnamed, but rather than pointing to
a DICompositeType directly, it points to a DIDerivedType with tag
DW_TAG_const_type, which then points to the DICompositeType. However,
the CodeView assembly printer currently assumes that the base type for
an unnamed member will always be a DICompositeType, and attempts to
perform that cast, which triggers an assertion failure, since in this
case the base type is actually a DIDerivedType, not a DICompositeType
(and we would have to get the base type of the DIDerivedType to reach
the DICompositeType). I think the debug metadata being generated by the
frontend is correct (or at least plausible), and the CodeView printer
needs to handle this case.

This patch teaches the CodeView printer to unwrap any qualifier types.
The qualifiers are just dropped for now. Ideally, they would be applied
to the added indirect members instead, but this occurs infrequently
enough that adding the logic to handle the qualifiers correctly isn't
worth it for now. A FIXME is added to note this.

Additionally, Reid pointed out that the underlying assumption that an
unnamed member must be a composite type is itself incorrect and may not
hold for all frontends. Therefore, after all qualifiers have been
stripped, check if the resulting type is in fact a DICompositeType and
just return if it isn't, rather than assuming the type and crashing if
that assumption is violated.

Diff Detail

Repository
rL LLVM

Event Timeline

smeenai created this revision.Feb 26 2018, 7:54 PM
rnk added inline comments.Feb 27 2018, 10:30 AM
lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
1817–1818 ↗(On Diff #136031)

This seems like a flawed assumption. Other frontends might want to emit unnamed fields that aren't nested structs. I'd rather rewrite this logic so that it's a pattern match of an unnamed DICompositeType that is possibly wrapped in qualifier types. Basically, I'd just make the DICompositeType cast below a dyn_cast, and if it fails, drop the unnamed member. I have a feeling that VS and windbg will not cope with unnamed members.

smeenai added inline comments.Feb 27 2018, 10:48 AM
lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
1817–1818 ↗(On Diff #136031)

Thanks. Is there a better way to do that pattern match than what I have here? (In particular, should I be concerned about preserving the qualifiers in the nested types, as opposed to just dropping them, which I'm doing right now?)

rnk added inline comments.Feb 27 2018, 10:58 AM
lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
1817–1818 ↗(On Diff #136031)

I suppose the correct thing to do is to mark all the indirect members inside the anonymous struct here with the qualifiers on the outer struct. It would look kind of like this:

struct Outer {
  const struct {
    int inner1;
    int inner2;
  };
};
--> codeview
struct Outer {
  const int inner1;
  const int inner2;
};

That could be implemented by adding qualifiers to ClassInfo::MemberInfo, and then copying some of the logic from lowerTypeModifier to generate the right LF_MODIFIER records for it. Alternatively, we could synthesize new DIDerivedType metadata and then call getTypeIndex on it. It seems a little heroic, though, just to deal with a format limitation.

lowerTypeModifier is also about to get more complicated in D43060.

In conclusion, I'd drop them for now. Add a FIXME, maybe?

smeenai updated this revision to Diff 136132.Feb 27 2018, 12:12 PM
smeenai edited the summary of this revision. (Show Details)

Reid's comments

rnk accepted this revision.Feb 27 2018, 12:59 PM

lgtm

This revision is now accepted and ready to land.Feb 27 2018, 12:59 PM
This revision was automatically updated to reflect the committed changes.