Emit a S_UDT record for typedefs. We still need to do something for
class types.
Details
Diff Detail
Event Timeline
lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | ||
---|---|---|
809 | Why do we need this condition? Don't we want to emit typdefs at global scope? I'd expect we can reference function local typedefs from outside the function, with something like return type deduction: auto f() { typedef int myty; struct A { myty a; }; return A(); } decltype(f()) gv; Maybe that's contrived, but the reliance on type emission order here feels fragile. I was envisioning that we'd have a vector of plain DIType*'s, and we'd iterate them at end of TU and call getCompleteTypeIndex on them, which would trigger emission of all non-forward decl record types. |
lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | ||
---|---|---|
809 | MSVC emits typedefs nested within functions in the same symbol section as the one for the function, I was trying to make sure that this would happen. That being said, I think we can just never use the COMDAT section for the S_UDT records and always just stick them in the default section. |
lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | ||
---|---|---|
809 | What if we staple UDTs into the relevant FunctionInfo? Currently FnDebugInfo is indexed by Function*, but it could easily be changed to DISubprogram since the Function points to that. |
lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | ||
---|---|---|
809 | Hmm, I'm not sure how this helps. Today, we add functions to FnDebugInfo at beginFunction and we process them at endModule. When would we be doing the stapling? We will only see the types when we are processing entities like locals. What if the local we are processing references a type that was defined in a prior FnDebugInfo entry? |
lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | ||
---|---|---|
809 | Not sure how this is possible. |
lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | ||
---|---|---|
809 | Here is how it is possible: extern inline auto f() { struct X { struct Y {}; }; return X{}; } void g() { decltype(f())::Y y; } I never claimed that my code solved the case and I'm quite aware that we are potentially dropping S_UDTs where we shouldn't. The question is: how do we fix it. |
lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | ||
---|---|---|
801 | Move this code to separate function (we will need it soon in other places). | |
809 | We should lower types at beginModule/beginFunction/beginInstruction, and S_UDT should be part of FnDebugInfo as Reid suggested. In addition, we will need one set of S_UDT for the module scope. |
We spent some time talking about this today, and I think there's two ways to do this:
- The hard way: compute type indices for all types used in the function's symbol substream before endFunction. Assert if someone calls getTypeIndex during .debug$S emission.
- The easy way: Don't handle the corner cases where people reference function-internal typedefs from outside that function, and just handle typedefs at file/namespace scope and function scope. This is David's current approach.
I think we should go with approach 2, but we should also remember file/namespace scope typedefs before committing this. I think it just requires an 'else if' in the existing code and a vector on CodeViewDebug. Together that will handle 99% of all typedef usage.
lgtm
lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | ||
---|---|---|
810 | Can you add a FIXME or TODO about how we would handle the 'else' case? We would have to perform all type translation before beginning emission of .debug$S, and then make LocalUDTs a member of FunctionInfo. | |
test/DebugInfo/COFF/udts.ll | ||
4 | Paste the C++ source and say something about how this is testing for local UDTs? I'm guessing it's: void f() { typedef int FOO; FOO f; } |
Move this code to separate function (we will need it soon in other places).
For example:
std::string getScopedName(StringRef Name, DIScope *Scope)