1 //===- NativeTypePointer.cpp - info about pointer type ----------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
10 
11 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
12 
13 #include <cassert>
14 
15 using namespace llvm;
16 using namespace llvm::codeview;
17 using namespace llvm::pdb;
18 
19 NativeTypePointer::NativeTypePointer(NativeSession &Session, SymIndexId Id,
20                                      codeview::TypeIndex TI)
21     : NativeRawSymbol(Session, PDB_SymType::PointerType, Id), TI(TI) {
22   assert(TI.isSimple());
23   assert(TI.getSimpleMode() != SimpleTypeMode::Direct);
24 }
25 
26 NativeTypePointer::NativeTypePointer(NativeSession &Session, SymIndexId Id,
27                                      codeview::TypeIndex TI,
28                                      codeview::PointerRecord Record)
29     : NativeRawSymbol(Session, PDB_SymType::PointerType, Id), TI(TI),
30       Record(std::move(Record)) {}
31 
32 NativeTypePointer::~NativeTypePointer() {}
33 
34 void NativeTypePointer::dump(raw_ostream &OS, int Indent,
35                              PdbSymbolIdField ShowIdFields,
36                              PdbSymbolIdField RecurseIdFields) const {
37   NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
38 
39   if (isMemberPointer()) {
40     dumpSymbolIdField(OS, "classParentId", getClassParentId(), Indent, Session,
41                       PdbSymbolIdField::ClassParent, ShowIdFields,
42                       RecurseIdFields);
43   }
44   dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
45                     PdbSymbolIdField::LexicalParent, ShowIdFields,
46                     RecurseIdFields);
47   dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
48                     PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
49   dumpSymbolField(OS, "length", getLength(), Indent);
50   dumpSymbolField(OS, "constType", isConstType(), Indent);
51   dumpSymbolField(OS, "isPointerToDataMember", isPointerToDataMember(), Indent);
52   dumpSymbolField(OS, "isPointerToMemberFunction", isPointerToMemberFunction(),
53                   Indent);
54   dumpSymbolField(OS, "RValueReference", isRValueReference(), Indent);
55   dumpSymbolField(OS, "reference", isReference(), Indent);
56   dumpSymbolField(OS, "restrictedType", isRestrictedType(), Indent);
57   if (isMemberPointer()) {
58     if (isSingleInheritance())
59       dumpSymbolField(OS, "isSingleInheritance", 1, Indent);
60     else if (isMultipleInheritance())
61       dumpSymbolField(OS, "isMultipleInheritance", 1, Indent);
62     else if (isVirtualInheritance())
63       dumpSymbolField(OS, "isVirtualInheritance", 1, Indent);
64   }
65   dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
66   dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
67 }
68 
69 SymIndexId NativeTypePointer::getClassParentId() const {
70   if (!isMemberPointer())
71     return 0;
72 
73   assert(Record);
74   const MemberPointerInfo &MPI = Record->getMemberInfo();
75   return Session.getSymbolCache().findSymbolByTypeIndex(MPI.ContainingType);
76 }
77 
78 uint64_t NativeTypePointer::getLength() const {
79   if (Record)
80     return Record->getSize();
81 
82   switch (TI.getSimpleMode()) {
83   case SimpleTypeMode::NearPointer:
84   case SimpleTypeMode::FarPointer:
85   case SimpleTypeMode::HugePointer:
86     return 2;
87   case SimpleTypeMode::NearPointer32:
88   case SimpleTypeMode::FarPointer32:
89     return 4;
90   case SimpleTypeMode::NearPointer64:
91     return 8;
92   case SimpleTypeMode::NearPointer128:
93     return 16;
94   default:
95     assert(false && "invalid simple type mode!");
96   }
97   return 0;
98 }
99 
100 SymIndexId NativeTypePointer::getTypeId() const {
101   // This is the pointee SymIndexId.
102   TypeIndex Referent = Record ? Record->ReferentType : TI.makeDirect();
103 
104   return Session.getSymbolCache().findSymbolByTypeIndex(Referent);
105 }
106 
107 bool NativeTypePointer::isReference() const {
108   if (!Record)
109     return false;
110   return Record->getMode() == PointerMode::LValueReference;
111 }
112 
113 bool NativeTypePointer::isRValueReference() const {
114   if (!Record)
115     return false;
116   return Record->getMode() == PointerMode::RValueReference;
117 }
118 
119 bool NativeTypePointer::isPointerToDataMember() const {
120   if (!Record)
121     return false;
122   return Record->getMode() == PointerMode::PointerToDataMember;
123 }
124 
125 bool NativeTypePointer::isPointerToMemberFunction() const {
126   if (!Record)
127     return false;
128   return Record->getMode() == PointerMode::PointerToMemberFunction;
129 }
130 
131 bool NativeTypePointer::isConstType() const {
132   if (!Record)
133     return false;
134   return (Record->getOptions() & PointerOptions::Const) != PointerOptions::None;
135 }
136 
137 bool NativeTypePointer::isRestrictedType() const {
138   if (!Record)
139     return false;
140   return (Record->getOptions() & PointerOptions::Restrict) !=
141          PointerOptions::None;
142 }
143 
144 bool NativeTypePointer::isVolatileType() const {
145   if (!Record)
146     return false;
147   return (Record->getOptions() & PointerOptions::Volatile) !=
148          PointerOptions::None;
149 }
150 
151 bool NativeTypePointer::isUnalignedType() const {
152   if (!Record)
153     return false;
154   return (Record->getOptions() & PointerOptions::Unaligned) !=
155          PointerOptions::None;
156 }
157 
158 static inline bool isInheritanceKind(const MemberPointerInfo &MPI,
159                                      PointerToMemberRepresentation P1,
160                                      PointerToMemberRepresentation P2) {
161   return (MPI.getRepresentation() == P1 || MPI.getRepresentation() == P2);
162 }
163 
164 bool NativeTypePointer::isSingleInheritance() const {
165   if (!isMemberPointer())
166     return false;
167   return isInheritanceKind(
168       Record->getMemberInfo(),
169       PointerToMemberRepresentation::SingleInheritanceData,
170       PointerToMemberRepresentation::SingleInheritanceFunction);
171 }
172 
173 bool NativeTypePointer::isMultipleInheritance() const {
174   if (!isMemberPointer())
175     return false;
176   return isInheritanceKind(
177       Record->getMemberInfo(),
178       PointerToMemberRepresentation::MultipleInheritanceData,
179       PointerToMemberRepresentation::MultipleInheritanceFunction);
180 }
181 
182 bool NativeTypePointer::isVirtualInheritance() const {
183   if (!isMemberPointer())
184     return false;
185   return isInheritanceKind(
186       Record->getMemberInfo(),
187       PointerToMemberRepresentation::VirtualInheritanceData,
188       PointerToMemberRepresentation::VirtualInheritanceFunction);
189 }
190 
191 bool NativeTypePointer::isMemberPointer() const {
192   return isPointerToDataMember() || isPointerToMemberFunction();
193 }
194