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