[CodeView] Read and dump LF_ALIAS - #218243
Conversation
|
@llvm/pr-subscribers-objectyaml @llvm/pr-subscribers-platform-windows Author: Nerixyz (Nerixyz) ChangesMost of this is taken from #153936. It only implements the read/dump/reconstruct part of #153936 - it doesn't change the generated debug info.
In typedef char16_t MyByte;
using U16 = char16_t;
struct Foo {
int bar = 1;
};
using Baz = Foo;
int main() {
using Inner = char;
using InnerPtr = char *;
const MyByte *something = u"a string";
const U16 *another = u"abc";
Inner a = '+';
const Inner *inner = "abc";
InnerPtr ip = &a;
Baz baz;
Baz *bp = &baz;
}
The following additions were made compared to #153936:
Co-authored-by: Walnut <ant_b356@me.com> Full diff: https://github.com/llvm/llvm-project/pull/218243.diff 13 Files Affected:
diff --git a/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def b/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def
index 86a74292dbb11..be0e81edbbb34 100644
--- a/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def
+++ b/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def
@@ -50,6 +50,7 @@ TYPE_RECORD_ALIAS(LF_STRUCTURE, 0x1505, Struct, Class)
TYPE_RECORD_ALIAS(LF_INTERFACE, 0x1519, Interface, Class)
TYPE_RECORD(LF_UNION, 0x1506, Union)
TYPE_RECORD(LF_ENUM, 0x1507, Enum)
+TYPE_RECORD(LF_ALIAS, 0x150a, Alias)
TYPE_RECORD(LF_TYPESERVER2, 0x1515, TypeServer2)
TYPE_RECORD(LF_VFTABLE, 0x151d, VFTable)
TYPE_RECORD(LF_VTSHAPE, 0x000a, VFTableShape)
@@ -187,7 +188,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..1b937a8621f7a 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` - A typedef where `Name` is typedef'd to `UnderlyingType`.
+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 2d1bfa6f8dcb9..bd02829c28cbe 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h
@@ -428,6 +428,8 @@ class LVLogicalVisitor final {
TypeIndex TI, LVElement *Element);
LLVM_ABI Error visitKnownRecord(CVType &Record, EndPrecompRecord &EndPrecomp,
TypeIndex TI, LVElement *Element);
+ LLVM_ABI Error visitKnownRecord(CVType &Record, AliasRecord &Alias,
+ TypeIndex TI, LVElement *Element);
LLVM_ABI Error visitUnknownMember(CVMemberRecord &Record, TypeIndex TI);
LLVM_ABI Error visitKnownMember(CVMemberRecord &Record, BaseClassRecord &Base,
diff --git a/llvm/lib/DebugInfo/CodeView/RecordName.cpp b/llvm/lib/DebugInfo/CodeView/RecordName.cpp
index 476f9bb935379..32b2267c06b3b 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 7dd2bad7da2e1..00f309ce45446 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
@@ -439,3 +439,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/TypeIndexDiscovery.cpp b/llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp
index c19e72187fc9c..38264aa12b3d6 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp
@@ -352,6 +352,9 @@ static void discoverTypeIndices(ArrayRef<uint8_t> Content, TypeLeafKind Kind,
case TypeLeafKind::LF_POINTER:
handlePointer(Content, Refs);
break;
+ case TypeLeafKind::LF_ALIAS:
+ Refs.push_back({TiRefKind::TypeRef, 0, 1}); // UnderlyingType
+ break;
default:
break;
}
diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
index e8c9744935bf7..ea436e846e0ee 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
@@ -721,3 +721,9 @@ 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 7320a188051bb..5f6b0f513d37d 100644
--- a/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.cpp
@@ -2671,6 +2671,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/DebugInfo/PDB/Native/TpiHashing.cpp b/llvm/lib/DebugInfo/PDB/Native/TpiHashing.cpp
index 941ce78027a21..28967d55324c0 100644
--- a/llvm/lib/DebugInfo/PDB/Native/TpiHashing.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/TpiHashing.cpp
@@ -85,6 +85,15 @@ static Expected<uint32_t> getSourceLineHash(const CVType &Rec) {
return hashStringV1(StringRef(Buf, 4));
}
+// LF_ALIAS is considered a UDT, so only the name is hashed.
+static Expected<uint32_t> getHashForAlias(const CVType &Rec) {
+ AliasRecord Deserialized;
+ if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
+ Deserialized))
+ return std::move(E);
+ return hashStringV1(Deserialized.Name);
+}
+
Expected<TagRecordHash> llvm::pdb::hashTagRecord(const codeview::CVType &Type) {
switch (Type.kind()) {
case LF_CLASS:
@@ -112,7 +121,8 @@ Expected<uint32_t> llvm::pdb::hashTypeRecord(const CVType &Rec) {
return getHashForUdt<UnionRecord>(Rec);
case LF_ENUM:
return getHashForUdt<EnumRecord>(Rec);
-
+ case LF_ALIAS:
+ return getHashForAlias(Rec);
case LF_UDT_SRC_LINE:
return getSourceLineHash<UdtSourceLineRecord>(Rec);
case LF_UDT_MOD_SRC_LINE:
diff --git a/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp b/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp
index 1542017d9d7e6..0470ec6f8056c 100644
--- a/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp
+++ b/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp
@@ -654,6 +654,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/test/tools/llvm-pdbutil/alias-record.test b/llvm/test/tools/llvm-pdbutil/alias-record.test
new file mode 100644
index 0000000000000..88a979ed5e659
--- /dev/null
+++ b/llvm/test/tools/llvm-pdbutil/alias-record.test
@@ -0,0 +1,45 @@
+# RUN: llvm-pdbutil yaml2pdb %s --pdb=%t.pdb
+# RUN: llvm-pdbutil dump --types --type-extras %t.pdb | FileCheck --check-prefix=CHECK-YAML2PDB %s
+
+# RUN: llvm-pdbutil pdb2yaml --tpi-stream %t.pdb > %t.yaml
+# RUN: FileCheck --input-file=%t.yaml --check-prefix=CHECK-PDB2YAML %s
+
+# CHECK-YAML2PDB: 0x1000 | LF_ALIAS [size = 16, hash = 0x1876E]
+# CHECK-YAML2PDB-NEXT: underlying type = 0x0070 (char), name = MyByte
+# CHECK-YAML2PDB-NEXT: 0x1001 | LF_ALIAS [size = 12, hash = 0x1D4A]
+# CHECK-YAML2PDB-NEXT: underlying type = 0x007A (char16_t), name = U16
+# CHECK-YAML2PDB-NEXT: 0x1002 | LF_ALIAS [size = 16, hash = 0x1876E]
+# CHECK-YAML2PDB-NEXT: underlying type = 0x007A (char16_t), name = MyByte
+
+# CHECK-PDB2YAML: Records:
+# CHECK-PDB2YAML-NEXT: - Kind: LF_ALIAS
+# CHECK-PDB2YAML-NEXT: Alias:
+# CHECK-PDB2YAML-NEXT: UnderlyingType: 112
+# CHECK-PDB2YAML-NEXT: Name: MyByte
+# CHECK-PDB2YAML-NEXT: - Kind: LF_ALIAS
+# CHECK-PDB2YAML-NEXT: Alias:
+# CHECK-PDB2YAML-NEXT: UnderlyingType: 122
+# CHECK-PDB2YAML-NEXT: Name: U16
+# CHECK-PDB2YAML-NEXT: - Kind: LF_ALIAS
+# CHECK-PDB2YAML-NEXT: Alias:
+# CHECK-PDB2YAML-NEXT: UnderlyingType: 122
+# CHECK-PDB2YAML-NEXT: Name: MyByte
+# CHECK-PDB2YAML-NEXT: ...
+
+---
+TpiStream:
+ Version: VC80
+ Records:
+ - Kind: LF_ALIAS
+ Alias:
+ UnderlyingType: 112
+ Name: MyByte
+ - Kind: LF_ALIAS
+ Alias:
+ UnderlyingType: 122
+ Name: U16
+ - Kind: LF_ALIAS
+ Alias:
+ UnderlyingType: 122
+ Name: MyByte
+...
diff --git a/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp b/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp
index fc29ec46180c4..13677bce09b75 100644
--- a/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp
+++ b/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp
@@ -535,6 +535,11 @@ Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
return Error::success();
}
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, AliasRecord &AR) {
+ P.formatLine("underlying type = {0}, name = {1}", AR.UnderlyingType, AR.Name);
+ return Error::success();
+}
+
Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
NestedTypeRecord &Nested) {
P.format(" [name = `{0}`, parent = {1}]", Nested.Name, Nested.Type);
diff --git a/llvm/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp b/llvm/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp
index 810aeada33da7..5f11de113c747 100644
--- a/llvm/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp
+++ b/llvm/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp
@@ -613,3 +613,9 @@ TEST_F(TypeIndexIteratorTest, RegRelativeIndir) {
writeSymbolRecords(RR);
checkTypeReferences(0, RR.Type);
}
+
+TEST_F(TypeIndexIteratorTest, AliasRecord) {
+ AliasRecord AR(TypeIndex::Int32(), "SomeName");
+ writeTypeRecords(AR);
+ checkTypeReferences(0, AR.UnderlyingType);
+}
|
|
@llvm/pr-subscribers-debuginfo Author: Nerixyz (Nerixyz) ChangesMost of this is taken from #153936. It only implements the read/dump/reconstruct part of #153936 - it doesn't change the generated debug info.
In typedef char16_t MyByte;
using U16 = char16_t;
struct Foo {
int bar = 1;
};
using Baz = Foo;
int main() {
using Inner = char;
using InnerPtr = char *;
const MyByte *something = u"a string";
const U16 *another = u"abc";
Inner a = '+';
const Inner *inner = "abc";
InnerPtr ip = &a;
Baz baz;
Baz *bp = &baz;
}
The following additions were made compared to #153936:
Co-authored-by: Walnut <ant_b356@me.com> Full diff: https://github.com/llvm/llvm-project/pull/218243.diff 13 Files Affected:
diff --git a/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def b/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def
index 86a74292dbb11..be0e81edbbb34 100644
--- a/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def
+++ b/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def
@@ -50,6 +50,7 @@ TYPE_RECORD_ALIAS(LF_STRUCTURE, 0x1505, Struct, Class)
TYPE_RECORD_ALIAS(LF_INTERFACE, 0x1519, Interface, Class)
TYPE_RECORD(LF_UNION, 0x1506, Union)
TYPE_RECORD(LF_ENUM, 0x1507, Enum)
+TYPE_RECORD(LF_ALIAS, 0x150a, Alias)
TYPE_RECORD(LF_TYPESERVER2, 0x1515, TypeServer2)
TYPE_RECORD(LF_VFTABLE, 0x151d, VFTable)
TYPE_RECORD(LF_VTSHAPE, 0x000a, VFTableShape)
@@ -187,7 +188,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..1b937a8621f7a 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` - A typedef where `Name` is typedef'd to `UnderlyingType`.
+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 2d1bfa6f8dcb9..bd02829c28cbe 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h
@@ -428,6 +428,8 @@ class LVLogicalVisitor final {
TypeIndex TI, LVElement *Element);
LLVM_ABI Error visitKnownRecord(CVType &Record, EndPrecompRecord &EndPrecomp,
TypeIndex TI, LVElement *Element);
+ LLVM_ABI Error visitKnownRecord(CVType &Record, AliasRecord &Alias,
+ TypeIndex TI, LVElement *Element);
LLVM_ABI Error visitUnknownMember(CVMemberRecord &Record, TypeIndex TI);
LLVM_ABI Error visitKnownMember(CVMemberRecord &Record, BaseClassRecord &Base,
diff --git a/llvm/lib/DebugInfo/CodeView/RecordName.cpp b/llvm/lib/DebugInfo/CodeView/RecordName.cpp
index 476f9bb935379..32b2267c06b3b 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 7dd2bad7da2e1..00f309ce45446 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
@@ -439,3 +439,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/TypeIndexDiscovery.cpp b/llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp
index c19e72187fc9c..38264aa12b3d6 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp
@@ -352,6 +352,9 @@ static void discoverTypeIndices(ArrayRef<uint8_t> Content, TypeLeafKind Kind,
case TypeLeafKind::LF_POINTER:
handlePointer(Content, Refs);
break;
+ case TypeLeafKind::LF_ALIAS:
+ Refs.push_back({TiRefKind::TypeRef, 0, 1}); // UnderlyingType
+ break;
default:
break;
}
diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
index e8c9744935bf7..ea436e846e0ee 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
@@ -721,3 +721,9 @@ 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 7320a188051bb..5f6b0f513d37d 100644
--- a/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.cpp
@@ -2671,6 +2671,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/DebugInfo/PDB/Native/TpiHashing.cpp b/llvm/lib/DebugInfo/PDB/Native/TpiHashing.cpp
index 941ce78027a21..28967d55324c0 100644
--- a/llvm/lib/DebugInfo/PDB/Native/TpiHashing.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/TpiHashing.cpp
@@ -85,6 +85,15 @@ static Expected<uint32_t> getSourceLineHash(const CVType &Rec) {
return hashStringV1(StringRef(Buf, 4));
}
+// LF_ALIAS is considered a UDT, so only the name is hashed.
+static Expected<uint32_t> getHashForAlias(const CVType &Rec) {
+ AliasRecord Deserialized;
+ if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
+ Deserialized))
+ return std::move(E);
+ return hashStringV1(Deserialized.Name);
+}
+
Expected<TagRecordHash> llvm::pdb::hashTagRecord(const codeview::CVType &Type) {
switch (Type.kind()) {
case LF_CLASS:
@@ -112,7 +121,8 @@ Expected<uint32_t> llvm::pdb::hashTypeRecord(const CVType &Rec) {
return getHashForUdt<UnionRecord>(Rec);
case LF_ENUM:
return getHashForUdt<EnumRecord>(Rec);
-
+ case LF_ALIAS:
+ return getHashForAlias(Rec);
case LF_UDT_SRC_LINE:
return getSourceLineHash<UdtSourceLineRecord>(Rec);
case LF_UDT_MOD_SRC_LINE:
diff --git a/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp b/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp
index 1542017d9d7e6..0470ec6f8056c 100644
--- a/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp
+++ b/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp
@@ -654,6 +654,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/test/tools/llvm-pdbutil/alias-record.test b/llvm/test/tools/llvm-pdbutil/alias-record.test
new file mode 100644
index 0000000000000..88a979ed5e659
--- /dev/null
+++ b/llvm/test/tools/llvm-pdbutil/alias-record.test
@@ -0,0 +1,45 @@
+# RUN: llvm-pdbutil yaml2pdb %s --pdb=%t.pdb
+# RUN: llvm-pdbutil dump --types --type-extras %t.pdb | FileCheck --check-prefix=CHECK-YAML2PDB %s
+
+# RUN: llvm-pdbutil pdb2yaml --tpi-stream %t.pdb > %t.yaml
+# RUN: FileCheck --input-file=%t.yaml --check-prefix=CHECK-PDB2YAML %s
+
+# CHECK-YAML2PDB: 0x1000 | LF_ALIAS [size = 16, hash = 0x1876E]
+# CHECK-YAML2PDB-NEXT: underlying type = 0x0070 (char), name = MyByte
+# CHECK-YAML2PDB-NEXT: 0x1001 | LF_ALIAS [size = 12, hash = 0x1D4A]
+# CHECK-YAML2PDB-NEXT: underlying type = 0x007A (char16_t), name = U16
+# CHECK-YAML2PDB-NEXT: 0x1002 | LF_ALIAS [size = 16, hash = 0x1876E]
+# CHECK-YAML2PDB-NEXT: underlying type = 0x007A (char16_t), name = MyByte
+
+# CHECK-PDB2YAML: Records:
+# CHECK-PDB2YAML-NEXT: - Kind: LF_ALIAS
+# CHECK-PDB2YAML-NEXT: Alias:
+# CHECK-PDB2YAML-NEXT: UnderlyingType: 112
+# CHECK-PDB2YAML-NEXT: Name: MyByte
+# CHECK-PDB2YAML-NEXT: - Kind: LF_ALIAS
+# CHECK-PDB2YAML-NEXT: Alias:
+# CHECK-PDB2YAML-NEXT: UnderlyingType: 122
+# CHECK-PDB2YAML-NEXT: Name: U16
+# CHECK-PDB2YAML-NEXT: - Kind: LF_ALIAS
+# CHECK-PDB2YAML-NEXT: Alias:
+# CHECK-PDB2YAML-NEXT: UnderlyingType: 122
+# CHECK-PDB2YAML-NEXT: Name: MyByte
+# CHECK-PDB2YAML-NEXT: ...
+
+---
+TpiStream:
+ Version: VC80
+ Records:
+ - Kind: LF_ALIAS
+ Alias:
+ UnderlyingType: 112
+ Name: MyByte
+ - Kind: LF_ALIAS
+ Alias:
+ UnderlyingType: 122
+ Name: U16
+ - Kind: LF_ALIAS
+ Alias:
+ UnderlyingType: 122
+ Name: MyByte
+...
diff --git a/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp b/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp
index fc29ec46180c4..13677bce09b75 100644
--- a/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp
+++ b/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp
@@ -535,6 +535,11 @@ Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
return Error::success();
}
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, AliasRecord &AR) {
+ P.formatLine("underlying type = {0}, name = {1}", AR.UnderlyingType, AR.Name);
+ return Error::success();
+}
+
Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
NestedTypeRecord &Nested) {
P.format(" [name = `{0}`, parent = {1}]", Nested.Name, Nested.Type);
diff --git a/llvm/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp b/llvm/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp
index 810aeada33da7..5f11de113c747 100644
--- a/llvm/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp
+++ b/llvm/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp
@@ -613,3 +613,9 @@ TEST_F(TypeIndexIteratorTest, RegRelativeIndir) {
writeSymbolRecords(RR);
checkTypeReferences(0, RR.Type);
}
+
+TEST_F(TypeIndexIteratorTest, AliasRecord) {
+ AliasRecord AR(TypeIndex::Int32(), "SomeName");
+ writeTypeRecords(AR);
+ checkTypeReferences(0, AR.UnderlyingType);
+}
|
dpaoliello
left a comment
There was a problem hiding this comment.
Please add handling in SymbolCache::findSymbolByTypeIndex - there may be downstream implications of that...
| }; | ||
|
|
||
| /// `LF_ALIAS` - A typedef where `Name` is typedef'd to `UnderlyingType`. | ||
| class AliasRecord : public TypeRecord { |
There was a problem hiding this comment.
I don't see any change to getSizeInBytesForTypeRecord - I don't think the default case is correct though, should we be forwarding the size of the underlying type?
There was a problem hiding this comment.
I don't think the default case is correct though, should we be forwarding the size of the underlying type?
Yeah - it returns (essentially) garbage for non-aggregates, the comment above says that
/// Given an arbitrary codeview type, return the type's size in the case
/// of aggregate (LF_STRUCTURE, LF_CLASS, LF_INTERFACE, LF_UNION).
I don't see LF_ALIAS as an aggregate. And given the function signature, it shouldn't read in the TPI stream. In my opinion, it should return an optional and only return the size in the documented cases.
There was a problem hiding this comment.
Hmm that also seems wrong - it should handle modifiers too.
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
28b3446 to
eb1f30c
Compare
🐧 Linux x64 Test Results
Failed Tests(click on a test name to see its output) MLIRMLIR.Dialect/Vector/vector-unroll-options.mlirIf these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the |
🪟 Windows x64 Test Results
Failed Tests(click on a test name to see its output) MLIRMLIR.Dialect/Vector/vector-unroll-options.mlirIf these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the |
|
|
||
| NativeTypeTypedefAlias::NativeTypeTypedefAlias( | ||
| NativeSession &Session, SymIndexId Id, | ||
| NativeTypeTypedefAlias &UnmodifiedType, codeview::ModifierRecord Modifier) |
There was a problem hiding this comment.
I'm a bit confused - where does this Modifier come from? Why aren't we dumping it elsewhere?
There was a problem hiding this comment.
This seems like dead functionality, perhaps exercised by the original PR. I would leave it out of scope if you don't need it for the core parsing / dumping code.
There was a problem hiding this comment.
This isn't dead - it's used in SymbolCache::createSymbolForModifiedType. It's similar to how modifiers for tag records are handled.
rnk
left a comment
There was a problem hiding this comment.
Interesting. It sounds like there's a "PDB schema change" coming, if that's the right word for it.
I seem to recall that Symbol UDTs were a major bottleneck for PDB writing, so it makes sense that Microsoft would seek to shift that information from the symbol record stream over to the type record stream, where it gets merged more efficiently.
It then just becomes a question of figuring out which typedefs are active in which translation unit, and I don't know how they'll do it. I guess that's a relevant question for LLDB.
|
|
||
| NativeTypeTypedefAlias::NativeTypeTypedefAlias( | ||
| NativeSession &Session, SymIndexId Id, | ||
| NativeTypeTypedefAlias &UnmodifiedType, codeview::ModifierRecord Modifier) |
There was a problem hiding this comment.
This seems like dead functionality, perhaps exercised by the original PR. I would leave it out of scope if you don't need it for the core parsing / dumping code.
Technically,
LLDB has only looked at the symbol UDTs when searching types. That seems to be what the DIA SDK does today too. I'm hoping to change that. Having this in the type stream also means that we know which values use a typedef - before we only knew that a typedef existed. |
Most of this is taken from #153936. It only implements the read/dump/reconstruct part of #153936 - doesn't change the generated debug info.
LF_ALIASrepresents a typedeftypedef UnderlyingType Name. MSVC 19.52.36615 (currently the preview version) can generate it by passing/d1typeAliasDebugRecords. I used that version to test my change. From what I can tell, MSVC only generatesLF_ALIASfor integer types (not even pointers to integers even if they're <0x1000). No clue why.In
FooandInnerPtrwon't get anLF_ALIAS. The type ofbazwill beFooandipwill bechar*.Furthermore, Visual Studio's debugger will fail to inspect
a. The others show fine. I think it can only handle aliases when they go through a pointer/reference.The following additions were made compared to #153936:
LF_ALIASto only include the name - it's considered a UDT, so only the name is hashed: https://github.com/microsoft/microsoft-pdb/blob/805655a28bd8198004be2ac27e6e0290121a5e89/PDB/dbi/tpi.cpp#L1888-L1890Co-authored-by: Walnut ant_b356@me.com