llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-platform-windows @llvm/pr-subscribers-debuginfo Author: Walnut (Walnut356) <details> <summary>Changes</summary> This patch causes LLVM to emit `lf_alias` nodes for typedefs, allowing typedefs to be represented in the type data stream. Typedef `S_UDT` nodes are still created for the symbol stream. This strictly generates additional information and points to that additional information when possible. This is important because local variable symbols store *type* indexes. Without this change, it is impossible for a local variable to convey its typedefed type to the debugger. <details> <summary>Sample program</summary> ```cpp #include <iostream> #include <inttypes.h> struct Point { float x = 0.0; float y = 0.0; }; typedef Point Coord; int main() { unsigned char uc = 0; uint8_t u8 = 1; Point p = Point{5, 10}; Coord c = Coord{15, 20}; std::cout << "Hello World!\n"; } ``` </details> Before (LLVM 20.1.8): <img width="261" height="191" alt="image" src="https://github.com/user-attachments/assets/cb9e9e7e-3ad0-4e3a-81c7-5edb4248d2db" /> After: <img width="221" height="179" alt="image" src="https://github.com/user-attachments/assets/d6035b33-ce5c-4b22-a6c0-aa38b2495fb3" /> Please use extra scrutiny when looking over the LLDB-related changes. I have a bit of experience working with `SymbolFileNativePDB` and `PdbAstBuilder`, but I'm not super familiar with clang's `QualType` and such. In particular, I'm using a default `CompilerDeclContext` for the typedef type because I wasn't sure what else to use. --- Full diff: https://github.com/llvm/llvm-project/pull/152484.diff 13 Files Affected: - (modified) lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp (+14) - (modified) lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp (+15) - (modified) lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h (+3) - (modified) llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def (+1-1) - (modified) llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h (+13) - (modified) llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h (+2) - (modified) llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (+4-9) - (modified) llvm/lib/DebugInfo/CodeView/RecordName.cpp (+5) - (modified) llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp (+6) - (modified) llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp (+7) - (modified) llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.cpp (+12) - (modified) llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp (+5) - (modified) llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp (+7) ``````````diff diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index f01fba3c48ce9..db29c96b6194a 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -805,6 +805,20 @@ clang::QualType PdbAstBuilder::CreateType(PdbTypeSymId type) { return CreateFunctionType(mfr.ArgumentList, mfr.ReturnType, mfr.CallConv); } + if (cvt.kind() == LF_ALIAS) { + AliasRecord ar; + llvm::cantFail(TypeDeserializer::deserializeAs<AliasRecord>(cvt, ar)); + + auto underlying_type = ToCompilerType(GetOrCreateType(ar.UnderlyingType)); + + std::string name = std::string(DropNameScope(ar.Name)); + + CompilerType ct = underlying_type.CreateTypedef( + name.c_str(), CompilerDeclContext(), 0); + + return m_clang.GetQualType(ct.GetOpaqueQualType()); + } + return {}; } diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index dcea33dd9f854..57a4c29a037e6 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -709,6 +709,15 @@ TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id, ct, lldb_private::Type::ResolveState::Full); } +TypeSP SymbolFileNativePDB::CreateAliasType(PdbTypeSymId type_id, + const AliasRecord &ar, + CompilerType ct) { + + return MakeType(toOpaqueUid(type_id), ct.GetTypeName(), llvm::expectedToOptional(ct.GetByteSize(nullptr)), nullptr, LLDB_INVALID_UID, + lldb_private::Type::eEncodingIsUID, Declaration(), ct, + lldb_private::Type::ResolveState::Full); +} + TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) { if (type_id.index.isSimple()) return CreateSimpleType(type_id.index, ct); @@ -765,6 +774,12 @@ TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) { return CreateFunctionType(type_id, mfr, ct); } + if (cvt.kind() == LF_ALIAS) { + AliasRecord ar; + llvm::cantFail(TypeDeserializer::deserializeAs<AliasRecord>(cvt, ar)); + return CreateAliasType(type_id, ar, ct); + } + return nullptr; } diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index eda375d4cebe7..1ed2f22293b43 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -216,6 +216,9 @@ class SymbolFileNativePDB : public SymbolFileCommon { lldb::TypeSP CreateProcedureType(PdbTypeSymId type_id, const llvm::codeview::ProcedureRecord &pr, CompilerType ct); + lldb::TypeSP CreateAliasType(PdbTypeSymId type_id, + const llvm::codeview::AliasRecord &ar, + CompilerType ct); lldb::TypeSP CreateClassStructUnion(PdbTypeSymId type_id, const llvm::codeview::TagRecord &record, size_t size, CompilerType ct); diff --git a/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def b/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def index a31111eb80a4e..aa3beea75c75b 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def +++ b/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def @@ -53,6 +53,7 @@ TYPE_RECORD(LF_ENUM, 0x1507, Enum) TYPE_RECORD(LF_TYPESERVER2, 0x1515, TypeServer2) TYPE_RECORD(LF_VFTABLE, 0x151d, VFTable) TYPE_RECORD(LF_VTSHAPE, 0x000a, VFTableShape) +TYPE_RECORD(LF_ALIAS, 0x150a, Alias) TYPE_RECORD(LF_BITFIELD, 0x1205, BitField) @@ -181,7 +182,6 @@ CV_TYPE(LF_MANAGED_ST, 0x140f) CV_TYPE(LF_ST_MAX, 0x1500) CV_TYPE(LF_TYPESERVER, 0x1501) CV_TYPE(LF_DIMARRAY, 0x1508) -CV_TYPE(LF_ALIAS, 0x150a) CV_TYPE(LF_DEFARG, 0x150b) CV_TYPE(LF_FRIENDFCN, 0x150c) CV_TYPE(LF_NESTTYPEEX, 0x1512) diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h b/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h index 5a84fac5f5903..0e739650bd089 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h +++ b/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -952,6 +952,19 @@ class EndPrecompRecord : public TypeRecord { uint32_t Signature = 0; }; +// LF_ALIAS +class AliasRecord : public TypeRecord { +public: + AliasRecord() = default; + explicit AliasRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + AliasRecord(TypeIndex UnderlyingType, StringRef Name) + : TypeRecord(TypeRecordKind::Alias), UnderlyingType(UnderlyingType), Name(Name) {} + + TypeIndex UnderlyingType; + StringRef Name; + +}; + } // end namespace codeview } // end namespace llvm diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h index eb6371e911be4..164ea990336e0 100644 --- a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h +++ b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h @@ -418,6 +418,8 @@ class LVLogicalVisitor final { LVElement *Element); Error visitKnownRecord(CVType &Record, EndPrecompRecord &EndPrecomp, TypeIndex TI, LVElement *Element); + Error visitKnownRecord(CVType &Record, AliasRecord &Alias, + TypeIndex TI, LVElement *Element); Error visitUnknownMember(CVMemberRecord &Record, TypeIndex TI); Error visitKnownMember(CVMemberRecord &Record, BaseClassRecord &Base, diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index c5d6e40eb7c1e..29978c9e5270f 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -1728,6 +1728,9 @@ TypeIndex CodeViewDebug::lowerTypeAlias(const DIDerivedType *Ty) { addToUDTs(Ty); + AliasRecord AR(UnderlyingTypeIndex, TypeName); + auto alias_index = TypeTable.writeLeafType(AR); + if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::Int32Long) && TypeName == "HRESULT") return TypeIndex(SimpleTypeKind::HResult); @@ -1735,7 +1738,7 @@ TypeIndex CodeViewDebug::lowerTypeAlias(const DIDerivedType *Ty) { TypeName == "wchar_t") return TypeIndex(SimpleTypeKind::WideCharacter); - return UnderlyingTypeIndex; + return alias_index; } TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) { @@ -2750,14 +2753,6 @@ TypeIndex CodeViewDebug::getCompleteTypeIndex(const DIType *Ty) { if (!Ty) return TypeIndex::Void(); - // Look through typedefs when getting the complete type index. Call - // getTypeIndex on the typdef to ensure that any UDTs are accumulated and are - // emitted only once. - if (Ty->getTag() == dwarf::DW_TAG_typedef) - (void)getTypeIndex(Ty); - while (Ty->getTag() == dwarf::DW_TAG_typedef) - Ty = cast<DIDerivedType>(Ty)->getBaseType(); - // If this is a non-record type, the complete type index is the same as the // normal type index. Just call getTypeIndex. switch (Ty->getTag()) { diff --git a/llvm/lib/DebugInfo/CodeView/RecordName.cpp b/llvm/lib/DebugInfo/CodeView/RecordName.cpp index e06b036ede63a..80c9cfa2253fb 100644 --- a/llvm/lib/DebugInfo/CodeView/RecordName.cpp +++ b/llvm/lib/DebugInfo/CodeView/RecordName.cpp @@ -251,6 +251,11 @@ Error TypeNameComputer::visitKnownRecord(CVType &CVR, return Error::success(); } +Error TypeNameComputer::visitKnownRecord(CVType &CVR, AliasRecord &Alias) { + Name = Alias.Name; + return Error::success(); +} + std::string llvm::codeview::computeTypeName(TypeCollection &Types, TypeIndex Index) { TypeNameComputer Computer(Types); diff --git a/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp b/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp index 776676410e782..629b7e5746ff4 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp @@ -568,3 +568,9 @@ Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, W->printHex("Signature", EndPrecomp.getSignature()); return Error::success(); } + +Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, AliasRecord &Alias) { + printTypeIndex("UnderlyingType", Alias.UnderlyingType); + W->printString("Name", Alias.Name); + return Error::success(); +} diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp index 0bc65f8d0359a..530a119de85fe 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp @@ -752,3 +752,10 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, error(IO.mapInteger(EndPrecomp.Signature, "Signature")); return Error::success(); } + +Error TypeRecordMapping::visitKnownRecord(CVType &CVR, AliasRecord &Alias) { + error(IO.mapInteger(Alias.UnderlyingType, "UnderlyingType")); + error(IO.mapStringZ(Alias.Name, "Name")); + + return Error::success(); +} diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.cpp index 24eaa1234727d..6cd53d42a43cd 100644 --- a/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.cpp @@ -2623,6 +2623,18 @@ Error LVLogicalVisitor::visitKnownRecord(CVType &Record, return Error::success(); } +// LF_ALIAS (TPI) +Error LVLogicalVisitor::visitKnownRecord(CVType &Record, AliasRecord &Alias, + TypeIndex TI, LVElement *Element) { + LLVM_DEBUG({ + printTypeBegin(Record, TI, Element, StreamTPI); + printTypeIndex("UnderlyingType", Alias.UnderlyingType, StreamTPI); + W.printString("Name", Alias.Name); + printTypeEnd(Record); + }); + return Error::success(); +} + Error LVLogicalVisitor::visitUnknownMember(CVMemberRecord &Record, TypeIndex TI) { LLVM_DEBUG({ W.printHex("UnknownMember", unsigned(Record.Kind)); }); diff --git a/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp b/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp index f4ca1b22eafa0..84f33a3fea6a8 100644 --- a/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp +++ b/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp @@ -614,6 +614,11 @@ template <> void LeafRecordImpl<EndPrecompRecord>::map(IO &IO) { IO.mapRequired("Signature", Record.Signature); } +template <> void LeafRecordImpl<AliasRecord>::map(IO &IO) { + IO.mapRequired("UnderlyingType", Record.UnderlyingType); + IO.mapRequired("Name", Record.Name); +} + template <> void MemberRecordImpl<OneMethodRecord>::map(IO &IO) { MappingTraits<OneMethodRecord>::mapping(IO, Record); } diff --git a/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp b/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp index db3a752d58165..7931d606a7bf8 100644 --- a/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp +++ b/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp @@ -523,6 +523,13 @@ Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, return Error::success(); } +Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVT, + AliasRecord &Alias) { + P.format("alias = {0}, underlying type = {1}", Alias.Name, + Alias.UnderlyingType); + return Error::success(); +} + Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, NestedTypeRecord &Nested) { P.format(" [name = `{0}`, parent = {1}]", Nested.Name, Nested.Type); `````````` </details> https://github.com/llvm/llvm-project/pull/152484 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits