[llvm] [LLVM] Create `lf_alias` nodes for `typedef` and `using` (PR #153936)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 16 00:53:29 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-platform-windows
Author: Walnut (Walnut356)
<details>
<summary>Changes</summary>
Part 1 of 2 in splitting https://github.com/llvm/llvm-project/pull/152484
In short: Local and global variables can only store their type via a **type** node. Typedefs currently only use `S_UDT`, which is a **symbol** node. This patch makes the compiler output `lf_alias` nodes (equivalent to DWARF's `DW_TAG_typedef`), which exist in the type stream. This allows debuggers to tell the difference between `uint8_t var;` and `unsigned char var;`.
2 important notes:
* This behavior **does not** match msvc's output. I think it's likely that that is a defect on their end. I've submitted an issue about it on their forums.
* This change causes LLDB's DIA parser to differ in output from the native parser since DIA understands `lf_alias` and native does not. The followup patch will add `lf_alias` support to the native parser.
---
Full diff: https://github.com/llvm/llvm-project/pull/153936.diff
13 Files Affected:
- (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)
- (added) llvm/test/DebugInfo/PDB/Inputs/typedef.cpp (+14)
- (added) llvm/test/DebugInfo/PDB/Inputs/typedef.pdb ()
- (added) llvm/test/DebugInfo/PDB/typedef.test (+8)
- (modified) llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp (+7)
``````````diff
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/test/DebugInfo/PDB/Inputs/typedef.cpp b/llvm/test/DebugInfo/PDB/Inputs/typedef.cpp
new file mode 100644
index 0000000000000..40220da3d9e05
--- /dev/null
+++ b/llvm/test/DebugInfo/PDB/Inputs/typedef.cpp
@@ -0,0 +1,14 @@
+// Build with clang -fno-rtti -g -O0 typedef.cpp
+// Built with clang (22+) because MSVC does not output lf_alias for typedefs
+
+void *__purecall = 0;
+
+typedef unsigned char u8;
+using i64 = long long;
+
+int main() {
+ u8 val = 15;
+ i64 val2 = -1;
+
+ return 0;
+}
diff --git a/llvm/test/DebugInfo/PDB/Inputs/typedef.pdb b/llvm/test/DebugInfo/PDB/Inputs/typedef.pdb
new file mode 100644
index 0000000000000..3b9cf69aecff8
Binary files /dev/null and b/llvm/test/DebugInfo/PDB/Inputs/typedef.pdb differ
diff --git a/llvm/test/DebugInfo/PDB/typedef.test b/llvm/test/DebugInfo/PDB/typedef.test
new file mode 100644
index 0000000000000..43f4db1a186c4
--- /dev/null
+++ b/llvm/test/DebugInfo/PDB/typedef.test
@@ -0,0 +1,8 @@
+RUN: llvm-pdbutil dump -type-index=0x348A,0x348C %p/Inputs/typedef.pdb \
+RUN: | FileCheck --check-prefix=TYPES %s
+
+TYPES: Types (TPI Stream)
+TYPES-NEXT:============================================================
+TYPES-NEXT: Showing 2 records.
+TYPES-NEXT: 0x348A | LF_ALIAS [size = 12] alias = u8, underlying type = 0x0020 (unsigned char)
+TYPES-NEXT: 0x348C | LF_ALIAS [size = 12] alias = i64, underlying type = 0x0013 (__int64)
diff --git a/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp b/llvm/tools/llvm-pdbutil/MinimalTypeDumper.cpp
index db3a752d58165..b7caf167c3d61 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/153936
More information about the llvm-commits
mailing list