[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:28 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-debuginfo

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