This is an archive of the discontinued LLVM Phabricator instance.

Emit global variables as S_CONSTANT records for codeview debug info.
ClosedPublic

Authored by akhuang on May 14 2019, 5:44 PM.

Details

Summary

This emits S_CONSTANT records for global variables.
Currently this emits records for the global variables already being tracked in the
LLVM IR metadata, which are just constant global variables; we'll also want S_CONSTANTs
for static data members and enums.

Related to https://bugs.llvm.org/show_bug.cgi?id=41615

Diff Detail

Repository
rL LLVM

Event Timeline

akhuang created this revision.May 14 2019, 5:44 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 14 2019, 5:44 PM
rnk added inline comments.May 15 2019, 11:44 AM
llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
202 ↗(On Diff #199540)

I think we might want to try to generalize this CVGlobalVariable type to handle constants by leaving the GV member null. Then we won't need a second vector. I think there may be some cases where we should emit the S_CONSTANT inside a function, something like:

int f(int x) {
  static const int CppIsAwesome = 42; // Is this an S_CONSTANT or an S_LOCAL?
  enum { CppIsAwesome = 42 }; // If its written this way, is this an S_CONSTANT? Where does it come out?
  return x + CppIsAwesome;
}

I guess eventually CVGlobalVariable may become a bad fit for enumerator values, but I could see generalizing it.

To carry the DIExpression which contains the constant value in CVGlobalVariable, you can use a PointerIntUnion to store either a DIExpression* for constants or GlobalVariable* for true globals. Then the global emission code can check which is active and emit S_CONSTANT or S_[GL]DATA32

akhuang updated this revision to Diff 199694.May 15 2019, 4:01 PM
  • Save constant global variables in the same vector as other global variables
rnk added a comment.May 15 2019, 4:18 PM

I was going to ask for a test case that makes local constants, but I see clang generates pretty weird metadata for this test case:

int f(int x) {
  static const int MyConst = 42;
  return x + MyConst;
}

That's supposed to generate a local S_CONSTANT, but we don't populate the DIExpression properly. Hm.

llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
3000 ↗(On Diff #199694)

I think it's impossible for S_CONSTANTs to be comdat because we find the comdat on the global variable, so I would suggest using .get instead of dyn_cast, so that we crash earlier if that invariant is violated.

3033–3034 ↗(On Diff #199694)

I think it would be simpler to have this take a const CVGlobalVariable & rather than taking the two members individually.

3055–3056 ↗(On Diff #199694)

Maybe do this, so that this code complains loudly if another PointerUnion case is added instead of silently emitting nothing:

} else {
  const DIExpression *DIE = GVInfo.get<const DIExpression *>();
3059 ↗(On Diff #199694)

I think it would be better to check isConstant() earlier, before we set up the pointer union, so that no non-constant expressions make it here.

akhuang updated this revision to Diff 199703.May 15 2019, 4:58 PM
akhuang marked 4 inline comments as done.
  • Small code changes

Yeah, I noticed that the DIExpression is empty for local constants. I guess that's another thing to look at later?

rnk accepted this revision.May 16 2019, 12:54 PM

lgtm with some nits

llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
3063 ↗(On Diff #199703)

I think 10 bytes is all that's needed to write an encoded integer, so this might as well be 10 bytes long with a comment about it.

3059 ↗(On Diff #199694)

nit: I guess we should assert isConstant() here. I wish there was some helper for pulling out the constant value. :(

This revision is now accepted and ready to land.May 16 2019, 12:54 PM
akhuang updated this revision to Diff 199892.May 16 2019, 1:46 PM
akhuang marked 2 inline comments as done.

nits

akhuang updated this revision to Diff 199895.May 16 2019, 1:49 PM

whitespace

This revision was automatically updated to reflect the committed changes.