[llvm-exegesis][NFC] Fix typo
[llvm-complete.git] / lib / DebugInfo / CodeView / RecordName.cpp
blobd868ae237a44ff3ee2c5ce91d765075432f13072
1 //===- RecordName.cpp ----------------------------------------- *- C++ --*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
10 #include "llvm/DebugInfo/CodeView/RecordName.h"
12 #include "llvm/ADT/SmallString.h"
13 #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
14 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
15 #include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"
16 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
17 #include "llvm/Support/FormatVariadic.h"
19 using namespace llvm;
20 using namespace llvm::codeview;
22 namespace {
23 class TypeNameComputer : public TypeVisitorCallbacks {
24 /// The type collection. Used to calculate names of nested types.
25 TypeCollection &Types;
26 TypeIndex CurrentTypeIndex = TypeIndex::None();
28 /// Name of the current type. Only valid before visitTypeEnd.
29 SmallString<256> Name;
31 public:
32 explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {}
34 StringRef name() const { return Name; }
36 /// Paired begin/end actions for all types. Receives all record data,
37 /// including the fixed-length record prefix.
38 Error visitTypeBegin(CVType &Record) override;
39 Error visitTypeBegin(CVType &Record, TypeIndex Index) override;
40 Error visitTypeEnd(CVType &Record) override;
42 #define TYPE_RECORD(EnumName, EnumVal, Name) \
43 Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
44 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
45 #define MEMBER_RECORD(EnumName, EnumVal, Name)
46 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
48 } // namespace
50 Error TypeNameComputer::visitTypeBegin(CVType &Record) {
51 llvm_unreachable("Must call visitTypeBegin with a TypeIndex!");
52 return Error::success();
55 Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) {
56 // Reset Name to the empty string. If the visitor sets it, we know it.
57 Name = "";
58 CurrentTypeIndex = Index;
59 return Error::success();
62 Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); }
64 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
65 FieldListRecord &FieldList) {
66 Name = "<field list>";
67 return Error::success();
70 Error TypeNameComputer::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
71 StringIdRecord &String) {
72 Name = String.getString();
73 return Error::success();
76 Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
77 auto Indices = Args.getIndices();
78 uint32_t Size = Indices.size();
79 Name = "(";
80 for (uint32_t I = 0; I < Size; ++I) {
81 assert(Indices[I] < CurrentTypeIndex);
83 Name.append(Types.getTypeName(Indices[I]));
84 if (I + 1 != Size)
85 Name.append(", ");
87 Name.push_back(')');
88 return Error::success();
91 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
92 StringListRecord &Strings) {
93 auto Indices = Strings.getIndices();
94 uint32_t Size = Indices.size();
95 Name = "\"";
96 for (uint32_t I = 0; I < Size; ++I) {
97 Name.append(Types.getTypeName(Indices[I]));
98 if (I + 1 != Size)
99 Name.append("\" \"");
101 Name.push_back('\"');
102 return Error::success();
105 Error TypeNameComputer::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
106 Name = Class.getName();
107 return Error::success();
110 Error TypeNameComputer::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
111 Name = Union.getName();
112 return Error::success();
115 Error TypeNameComputer::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
116 Name = Enum.getName();
117 return Error::success();
120 Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
121 Name = AT.getName();
122 return Error::success();
125 Error TypeNameComputer::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
126 Name = VFT.getName();
127 return Error::success();
130 Error TypeNameComputer::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
131 Name = Id.getName();
132 return Error::success();
135 Error TypeNameComputer::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
136 StringRef Ret = Types.getTypeName(Proc.getReturnType());
137 StringRef Params = Types.getTypeName(Proc.getArgumentList());
138 Name = formatv("{0} {1}", Ret, Params).sstr<256>();
139 return Error::success();
142 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
143 MemberFunctionRecord &MF) {
144 StringRef Ret = Types.getTypeName(MF.getReturnType());
145 StringRef Class = Types.getTypeName(MF.getClassType());
146 StringRef Params = Types.getTypeName(MF.getArgumentList());
147 Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>();
148 return Error::success();
151 Error TypeNameComputer::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
152 Name = Func.getName();
153 return Error::success();
156 Error TypeNameComputer::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
157 Name = TS.getName();
158 return Error::success();
161 Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
163 if (Ptr.isPointerToMember()) {
164 const MemberPointerInfo &MI = Ptr.getMemberInfo();
166 StringRef Pointee = Types.getTypeName(Ptr.getReferentType());
167 StringRef Class = Types.getTypeName(MI.getContainingType());
168 Name = formatv("{0} {1}::*", Pointee, Class);
169 } else {
170 Name.append(Types.getTypeName(Ptr.getReferentType()));
172 if (Ptr.getMode() == PointerMode::LValueReference)
173 Name.append("&");
174 else if (Ptr.getMode() == PointerMode::RValueReference)
175 Name.append("&&");
176 else if (Ptr.getMode() == PointerMode::Pointer)
177 Name.append("*");
179 // Qualifiers in pointer records apply to the pointer, not the pointee, so
180 // they go on the right.
181 if (Ptr.isConst())
182 Name.append(" const");
183 if (Ptr.isVolatile())
184 Name.append(" volatile");
185 if (Ptr.isUnaligned())
186 Name.append(" __unaligned");
187 if (Ptr.isRestrict())
188 Name.append(" __restrict");
190 return Error::success();
193 Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
194 uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
196 if (Mods & uint16_t(ModifierOptions::Const))
197 Name.append("const ");
198 if (Mods & uint16_t(ModifierOptions::Volatile))
199 Name.append("volatile ");
200 if (Mods & uint16_t(ModifierOptions::Unaligned))
201 Name.append("__unaligned ");
202 Name.append(Types.getTypeName(Mod.getModifiedType()));
203 return Error::success();
206 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
207 VFTableShapeRecord &Shape) {
208 Name = formatv("<vftable {0} methods>", Shape.getEntryCount());
209 return Error::success();
212 Error TypeNameComputer::visitKnownRecord(
213 CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
214 return Error::success();
217 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
218 UdtSourceLineRecord &SourceLine) {
219 return Error::success();
222 Error TypeNameComputer::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {
223 return Error::success();
226 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
227 MethodOverloadListRecord &Overloads) {
228 return Error::success();
231 Error TypeNameComputer::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {
232 return Error::success();
235 Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) {
236 return Error::success();
239 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
240 PrecompRecord &Precomp) {
241 return Error::success();
244 Error TypeNameComputer::visitKnownRecord(CVType &CVR,
245 EndPrecompRecord &EndPrecomp) {
246 return Error::success();
249 std::string llvm::codeview::computeTypeName(TypeCollection &Types,
250 TypeIndex Index) {
251 TypeNameComputer Computer(Types);
252 CVType Record = Types.getType(Index);
253 if (auto EC = visitTypeRecord(Record, Index, Computer)) {
254 consumeError(std::move(EC));
255 return "<unknown UDT>";
257 return Computer.name();
260 static int getSymbolNameOffset(CVSymbol Sym) {
261 switch (Sym.kind()) {
262 // See ProcSym
263 case SymbolKind::S_GPROC32:
264 case SymbolKind::S_LPROC32:
265 case SymbolKind::S_GPROC32_ID:
266 case SymbolKind::S_LPROC32_ID:
267 case SymbolKind::S_LPROC32_DPC:
268 case SymbolKind::S_LPROC32_DPC_ID:
269 return 35;
270 // See Thunk32Sym
271 case SymbolKind::S_THUNK32:
272 return 21;
273 // See SectionSym
274 case SymbolKind::S_SECTION:
275 return 16;
276 // See CoffGroupSym
277 case SymbolKind::S_COFFGROUP:
278 return 14;
279 // See PublicSym32, FileStaticSym, RegRelativeSym, DataSym, ThreadLocalDataSym
280 case SymbolKind::S_PUB32:
281 case SymbolKind::S_FILESTATIC:
282 case SymbolKind::S_REGREL32:
283 case SymbolKind::S_GDATA32:
284 case SymbolKind::S_LDATA32:
285 case SymbolKind::S_LMANDATA:
286 case SymbolKind::S_GMANDATA:
287 case SymbolKind::S_LTHREAD32:
288 case SymbolKind::S_GTHREAD32:
289 case SymbolKind::S_PROCREF:
290 case SymbolKind::S_LPROCREF:
291 return 10;
292 // See RegisterSym and LocalSym
293 case SymbolKind::S_REGISTER:
294 case SymbolKind::S_LOCAL:
295 return 6;
296 // See BlockSym
297 case SymbolKind::S_BLOCK32:
298 return 18;
299 // See LabelSym
300 case SymbolKind::S_LABEL32:
301 return 7;
302 // See ObjNameSym, ExportSym, and UDTSym
303 case SymbolKind::S_OBJNAME:
304 case SymbolKind::S_EXPORT:
305 case SymbolKind::S_UDT:
306 return 4;
307 // See BPRelativeSym
308 case SymbolKind::S_BPREL32:
309 return 8;
310 // See UsingNamespaceSym
311 case SymbolKind::S_UNAMESPACE:
312 return 0;
313 default:
314 return -1;
318 StringRef llvm::codeview::getSymbolName(CVSymbol Sym) {
319 if (Sym.kind() == SymbolKind::S_CONSTANT) {
320 // S_CONSTANT is preceded by an APSInt, which has a variable length. So we
321 // have to do a full deserialization.
322 BinaryStreamReader Reader(Sym.content(), llvm::support::little);
323 // The container doesn't matter for single records.
324 SymbolRecordMapping Mapping(Reader, CodeViewContainer::ObjectFile);
325 ConstantSym Const(SymbolKind::S_CONSTANT);
326 cantFail(Mapping.visitSymbolBegin(Sym));
327 cantFail(Mapping.visitKnownRecord(Sym, Const));
328 cantFail(Mapping.visitSymbolEnd(Sym));
329 return Const.Name;
332 int Offset = getSymbolNameOffset(Sym);
333 if (Offset == -1)
334 return StringRef();
336 StringRef StringData = toStringRef(Sym.content()).drop_front(Offset);
337 return StringData.split('\0').first;