This is an archive of the discontinued LLVM Phabricator instance.

[CodeView] Emit static data members as S_CONSTANTs.
ClosedPublic

Authored by akhuang on Oct 8 2020, 1:58 PM.

Details

Summary

We used to only emit static const data members in CodeView as
S_CONSTANTS when they were used; this patch makes it so they are always emitted.

I changed CodeViewDebug.cpp to find the static const members from the
class debug info instead of creating DIGlobalVariables in the IR
whenever a static const data member is used.

Bug: https://bugs.llvm.org/show_bug.cgi?id=47580

Diff Detail

Event Timeline

akhuang created this revision.Oct 8 2020, 1:58 PM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptOct 8 2020, 1:58 PM
akhuang requested review of this revision.Oct 8 2020, 1:58 PM

I'll probably leave the llvm/CodeView parts of this for @rnk - but for the clang parts, they should have corresponding clang test coverage & I'd be curious to see the test for that to understand what the IR was before/after this change. (& to understand if/how either of those differ from the DWARF IR)

I'll probably leave the llvm/CodeView parts of this for @rnk - but for the clang parts, they should have corresponding clang test coverage & I'd be curious to see the test for that to understand what the IR was before/after this change. (& to understand if/how either of those differ from the DWARF IR)

Oh, I forgot to update the clang tests. The clang change reverts https://reviews.llvm.org/D62167, which made the IR for CodeView different (adding DIGlobalVariables for static members).

akhuang edited the summary of this revision. (Show Details)Oct 8 2020, 3:46 PM
akhuang updated this revision to Diff 297068.Oct 8 2020, 3:59 PM

Update clang test for static data members, and make it test the general cases
on the windows target as well.

dblaikie added inline comments.Oct 9 2020, 6:55 PM
clang/test/CodeGenCXX/debug-info-static-member.cpp
144–147

Bug or feature? If it's a bug, probably should at least make this comment a "FIXME"

rnk added inline comments.Oct 13 2020, 1:52 PM
clang/test/CodeGenCXX/debug-info-static-member.cpp
144–147

Feature. The easiest way to understand it is to hallucinate the C++17 inline keyword on MSVC static const integer data members with inline initializers. This metadata is probably emitted in MS mode, but it probably comes later on.

llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
3149

Let's move this past the continue so we don't construct the name unless the value is non-null.

3171

This makes me suspect that we still have bugs in the original S_CONSTANT code. Looks like this is a pre-existing bug:

$ cat t.cpp
static const signed int gv_signed = 0xFFFFFFFF;
const signed int useit2() { return gv_signed; }

$ clang-cl -c -Z7 t.cpp  && llvm-pdbutil dump -symbols t.obj | grep -A1 S_CONST
       0 | S_CONSTANT [size = 28] `gv_signed`
           type = 0x1000 (const int), value = 18446744073709551615

$ cl -c -Z7 t.cpp  && llvm-pdbutil dump -symbols t.obj | grep -A1 S_CONST
Microsoft (R) C/C++ Optimizing Compiler Version 19.27.29111 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

t.cpp
       0 | S_CONSTANT [size = 21] `gv_signed`
           type = 0x1000 (const int), value = -1

Can you re-structure this so that we aren't duplicating the calls to mapEncodedInteger in two places? mapEncodedInteger takes an APInt, which carries a sign already. We just have to use the type information to correct the sign on Value.

akhuang updated this revision to Diff 298258.Oct 14 2020, 4:04 PM
akhuang marked an inline comment as done.

address comments

akhuang marked an inline comment as done.Oct 14 2020, 4:04 PM
akhuang added inline comments.
clang/test/CodeGenCXX/debug-info-static-member.cpp
144–147

Oh, ok. I don't think the metadata for const_va is emitted anywhere in MS mode though. I guess it should be.

saudi added a subscriber: saudi.Oct 19 2020, 7:19 AM
dblaikie added inline comments.Oct 19 2020, 9:42 PM
clang/test/CodeGenCXX/debug-info-static-member.cpp
144–147

Not quite sure I follow - even though it's "inline" and thus the actual storage for the variable isn't emitted here (because it's just emitted anywhere it's needed, so the definition can be ignored)...

Oh, because the definition is the only root holding the type alive in this file - yeah, if the definition is ignored, the type won't be emitted, etc. Fair enough. Test might be fixed to be more portable by making the type referenced otherwise (eg: declaring a variable that is a pointer to this type, maybe)

Oh, but right... yeah, the virtual dtor is there specifically to test the case where there is no type definition.

As to "const_va is not emitted anywhere in MS mode" - I'd have expected it to be emitted if the type definition is emitted:

!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "x", file: !3, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !7, identifier: "_ZTS1x")
!7 = !{!8}
!8 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !6, file: !3, line: 1, baseType: !9, flags: DIFlagStaticMember, extraData: i32 42)

Something like that. But, yeah, if you use a type to hold some constants but never emit the type definition anywhere - then you'd never get the static member, I suppose.

rnk accepted this revision.Oct 22 2020, 4:30 PM

Looks good with a test for explicit zero initialization.

llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
3159

What about zero constants like:

struct Foo {
  static const int sdm = 0;
};

I think isNullValue just compares against zero, so that's not quite right. Maybe structure it as if ConstantInt / else if ConstantFP / else continue?

This revision is now accepted and ready to land.Oct 22 2020, 4:30 PM
rnk added a comment.Oct 23 2020, 12:21 PM

It seems like there are related test failures according to the Phabricator/Jenkins automation. Is that a true positive? Please confirm either way before landing.

akhuang marked an inline comment as done.Oct 23 2020, 4:27 PM

Whoops, forgot to check the tests. Apparently mapEncodedInteger asserts if a signed APInt is not less than 0. I just removed the assert because it doesn't seem necessary?

akhuang updated this revision to Diff 300438.Oct 23 2020, 5:08 PM

Fix test failures; remove assert for signed APSInts.

rnk accepted this revision.Oct 26 2020, 11:41 AM

lgtm

Please fix this case in a follow-up, though:

static const signed int gv_signed = 0xFFFFFFFF;
const signed int useit2() { return gv_signed; }

I think your APSInt code only works on static data member constants.

This revision was landed with ongoing or failed builds.Oct 26 2020, 3:30 PM
This revision was automatically updated to reflect the committed changes.

Patch to emit signed ints for other S_CONSTANTs: https://reviews.llvm.org/D90199

akhuang reopened this revision.Oct 27 2020, 12:08 PM

Reverted because my copied isUnsignedDIType function had problems (guess I copied it at first but then was messing with the code); I moved it to DebugHandlerBase.h so it doesn't need to be copied.

This revision is now accepted and ready to land.Oct 27 2020, 12:08 PM
akhuang updated this revision to Diff 301080.Oct 27 2020, 12:09 PM

Moved isUnsignedDIType to DebugHandlerBase to avoid copying it.

This revision was landed with ongoing or failed builds.Oct 28 2020, 4:36 PM
This revision was automatically updated to reflect the committed changes.