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 
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 
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 
35 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 
70 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 
79 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 
101 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 
108 bool NativeTypePointer::isReference() const {
109   if (!Record)
110     return false;
111   return Record->getMode() == PointerMode::LValueReference;
112 }
113 
114 bool NativeTypePointer::isRValueReference() const {
115   if (!Record)
116     return false;
117   return Record->getMode() == PointerMode::RValueReference;
118 }
119 
120 bool NativeTypePointer::isPointerToDataMember() const {
121   if (!Record)
122     return false;
123   return Record->getMode() == PointerMode::PointerToDataMember;
124 }
125 
126 bool NativeTypePointer::isPointerToMemberFunction() const {
127   if (!Record)
128     return false;
129   return Record->getMode() == PointerMode::PointerToMemberFunction;
130 }
131 
132 bool NativeTypePointer::isConstType() const {
133   if (!Record)
134     return false;
135   return (Record->getOptions() & PointerOptions::Const) != PointerOptions::None;
136 }
137 
138 bool NativeTypePointer::isRestrictedType() const {
139   if (!Record)
140     return false;
141   return (Record->getOptions() & PointerOptions::Restrict) !=
142          PointerOptions::None;
143 }
144 
145 bool NativeTypePointer::isVolatileType() const {
146   if (!Record)
147     return false;
148   return (Record->getOptions() & PointerOptions::Volatile) !=
149          PointerOptions::None;
150 }
151 
152 bool NativeTypePointer::isUnalignedType() const {
153   if (!Record)
154     return false;
155   return (Record->getOptions() & PointerOptions::Unaligned) !=
156          PointerOptions::None;
157 }
158 
159 static inline bool isInheritanceKind(const MemberPointerInfo &MPI,
160                                      PointerToMemberRepresentation P1,
161                                      PointerToMemberRepresentation P2) {
162   return (MPI.getRepresentation() == P1 || MPI.getRepresentation() == P2);
163 }
164 
165 bool NativeTypePointer::isSingleInheritance() const {
166   if (!isMemberPointer())
167     return false;
168   return isInheritanceKind(
169       Record->getMemberInfo(),
170       PointerToMemberRepresentation::SingleInheritanceData,
171       PointerToMemberRepresentation::SingleInheritanceFunction);
172 }
173 
174 bool NativeTypePointer::isMultipleInheritance() const {
175   if (!isMemberPointer())
176     return false;
177   return isInheritanceKind(
178       Record->getMemberInfo(),
179       PointerToMemberRepresentation::MultipleInheritanceData,
180       PointerToMemberRepresentation::MultipleInheritanceFunction);
181 }
182 
183 bool NativeTypePointer::isVirtualInheritance() const {
184   if (!isMemberPointer())
185     return false;
186   return isInheritanceKind(
187       Record->getMemberInfo(),
188       PointerToMemberRepresentation::VirtualInheritanceData,
189       PointerToMemberRepresentation::VirtualInheritanceFunction);
190 }
191 
192 bool NativeTypePointer::isMemberPointer() const {
193   return isPointerToDataMember() || isPointerToMemberFunction();
194 }
195